diff -r 3ab5c078b490 -r c63ee96dbe5f taskswitcher/server/src/tsdatalist.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/taskswitcher/server/src/tsdatalist.cpp Thu Sep 16 12:11:40 2010 +0100 @@ -0,0 +1,565 @@ +/* + * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). + * All rights reserved. + * This component and the accompanying materials are made available + * under the terms of "Eclipse Public License v1.0" + * which accompanies this distribution, and is available + * at the URL "http://www.eclipse.org/legal/epl-v10.html". + * + * Initial Contributors: + * Nokia Corporation - initial contribution. + * + * Contributors: + * + * Description: File containing application list classes + * + */ + +//INCLUDES: +#include // for CleanupResetAndDestroyPushL +#include +#include +#include // avkon +#include // fbsbitmap +#include +#include +#include +#include +#include + +#include "tsdatalist.h" +#include "tsentrykeygenerator.h" +#include "tsscreenshotmsg.h" +#include "tsunregscreenshotmsg.h" +#include "tsvisibilitymsg.h" + +// size for the created app icons +const TInt KAppIconWidth = 128; +const TInt KAppIconHeight = 128; + +//uids to be hidden +const TUid KHsApplicationUid = { 0x20022F35 }; + +// ================= MEMBER FUNCTIONS ======================= + +// -------------------------------------------------------------------------- +/** + * Two-phased constructor. + */ +CTsDataList* CTsDataList::NewL(MTsResourceManager& resources, + MTsWindowGroupsMonitor &monitor, + MTsDataObserver& observer) +{ + CTsDataList* self = new (ELeave) CTsDataList(resources, monitor, observer); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; +} + +// -------------------------------------------------------------------------- +/** + * Constructor. + */ +CTsDataList::CTsDataList(MTsResourceManager& resources, + MTsWindowGroupsMonitor &monitor, + MTsDataObserver& observer) +: + CTsWindowGroupsObserver(monitor), + mResources(resources), + mObserver(observer) +{ +} + +// -------------------------------------------------------------------------- +/* + * Destructor + */ +CTsDataList::~CTsDataList() +{ + mData.ResetAndDestroy(); + mVisibleData.Close(); + mHiddenUids.Close(); + RFbsSession::Disconnect(); + RAknIconSrvClient::Disconnect(); + delete mDefaultIcon; +} + +// -------------------------------------------------------------------------- +/** + * Performs 2nd phase construction. + */ +void CTsDataList::ConstructL() +{ + BaseConstructL(); + mHiddenUids.AppendL(KHsApplicationUid); + User::LeaveIfError(RFbsSession::Connect()); + RAknIconSrvClient::Connect(); + mDefaultIcon = HbIcon2CFbsBitmapL(HbIcon("qtg_large_application")); +} + +// -------------------------------------------------------------------------- +/** + * Returns a reference to the current content. + * Also performs sanity checks, e.g. associates application icons + * when no screenshot has been received. + * @return ref to content array + */ +const RTsFswArray& CTsDataList::Data() const +{ + return mVisibleData; +} + +// -------------------------------------------------------------------------- +/** + * Interface implementation + * @see MTsWindowGroupsObserver HandleWindowGroupChanged + */ +void CTsDataList::HandleWindowGroupChanged(MTsResourceManager &, + const TArray &wgList) +{ + TRAP_IGNORE(RTsFswArray newAppsList; + CleanupResetAndDestroyPushL(newAppsList); + CollectAppsL(newAppsList, wgList); + FitDataToList(newAppsList); + CleanupStack::PopAndDestroy(&newAppsList); + ); +} + +// -------------------------------------------------------------------------- +/** + * Adds running apps to the list. + * @param appsList array to add to + */ +void CTsDataList::CollectAppsL(RTsFswArray& appsList, + const TArray &wgList) +{ + for (TInt i = 0; i < wgList.Count(); ++i) { + TTsEntryKey key; + TInt err = TsEntryKeyGeneraror::Generate(key, wgList[i].iId, wgList); + + //skip this entry if it is already on list or generate key failed + if (err!=KErrNone || FindEntry(appsList, key) >= 0) { + continue; + } + + // get window group name + CApaWindowGroupName* windowName = CApaWindowGroupName::NewLC(mResources.WsSession(), key.WindowGroupId()); + TUid appUid = windowName->AppUid(); + + // get screen number (-1=console, 0=main screen, 1=cover ui) + TInt appScreen = 0; + TInt scrNumErr = mResources.ApaSession().GetDefaultScreenNumber( appScreen, appUid ); + + if (appUid.iUid && !windowName->Hidden() && (appScreen == 0 || appScreen == -1) && scrNumErr == KErrNone ) { + AddEntryL(key, appUid, windowName, appsList); + } + + CleanupStack::PopAndDestroy(windowName); + } +} + +// -------------------------------------------------------------------------- +/** + * Called from CollectTasksL for each entry in the task list. + * @param key entry key + * @param appUid application uid + * @param wgName window group name or NULL + * @param newList list to add to + */ +void CTsDataList::AddEntryL(const TTsEntryKey& key, const TUid& appUid, + CApaWindowGroupName* wgName, RTsFswArray& newList) +{ + CTsEntry* entry = CTsEntry::NewLC(key, mObserver); + + // check if present in old list and if yes then take some of the old data + TBool found = ConsiderOldDataL(key); + + // if not present previously then find out app name + // and check if screenshot is already available + if (!found) { + entry->SetAppUid(appUid); + + HBufC* name = FindAppNameLC(wgName, appUid, key.WindowGroupId()); + if (name) { + entry->SetAppNameL(*name); + } + CleanupStack::PopAndDestroy(name); + + CFbsBitmap* iconBitmap = GetAppIconL(appUid); + //transfer ownership to entry + entry->SetAppIcon(iconBitmap); + } + + if (wgName) { + entry->SetCloseableApp(!wgName->IsSystem()); + } + + // add to new list, ownership is transferred + newList.AppendL(entry); + CleanupStack::Pop(entry); +} + +// -------------------------------------------------------------------------- +/** + * Checks if there is an entry for same app in the content list. + * If yes then it takes some of the data for the entry that + * will correspond to the same app in the refreshed content list. + * @param key new key in content list + * @return ETrue if app was found + */ +TBool CTsDataList::ConsiderOldDataL(const TTsEntryKey& key) +{ + for (TInt entryIdx = 0, oldCount = mData.Count(); entryIdx < oldCount; ++entryIdx) { + if (mData[entryIdx]->Key() == key) { + return ETrue; + } + } + return EFalse; +} + +// -------------------------------------------------------------------------- +/** + * Finds out the application name. + * @param windowName window group name or NULL + * @param appUId application uid + * @param wgId window group id + * @return application name, ownership transferred to caller + */ +HBufC* CTsDataList::FindAppNameLC(CApaWindowGroupName* windowName, const TUid& appUid, TInt wgId) +{ + //Retrieve the app name + TApaAppInfo info; + mResources.ApaSession().GetAppInfo(info, appUid); + TPtrC caption = info.iShortCaption; + + HBufC* tempName = 0; + if (!caption.Length() && windowName) // if not set - use thread name instead + { + if (windowName->Caption().Length()) { + tempName = windowName->Caption().AllocL(); + //put on cleanupstack after the if + } + else { + TThreadId threadId; + TInt err = mResources.WsSession().GetWindowGroupClientThreadId(wgId, threadId); + if (err == KErrNone) { + RThread thread; + CleanupClosePushL(thread); + err = thread.Open(threadId); + if (err == KErrNone) { + tempName = thread.Name().AllocL(); // codescanner::forgottoputptroncleanupstack + // tempName put on cleanupstack after the if + } + CleanupStack::PopAndDestroy(&thread); + } + } + } + else { + tempName = caption.AllocL(); + //put on cleanupstack after the if + } + CleanupStack::PushL(tempName); + return tempName; +} + +// -------------------------------------------------------------------------- +/** + * Fit existing class contained data list into give one. + * Data is being changed with application type consideration that is based + * on aConsiderWidgets param. + * Function removes or add entries into data depend on given list. + * @param listToFit list with actual data + */ +void CTsDataList::FitDataToList(RTsFswArray& listToFit) +{ + TBool changed = EFalse; + TInt listCount = listToFit.Count(); + TInt dataCount = mData.Count(); + + //remove items that dont't exists in newly collected list + for (TInt i = dataCount - 1; i >= 0; --i) { + if (!CheckIfExists(*mData[i], listToFit)) { + delete mData[i]; + mData.Remove(i); + changed = ETrue; + } + } + RArray allKeys; + + //add new items at start + for (TInt i = listToFit.Count() - 1; i >= 0; --i) { + allKeys.Insert(listToFit[i]->Key(), 0); + if (!CheckIfExists(*listToFit[i], mData)) { + HideEntryIfNotAllowed(listToFit[i]); + mData.Insert(listToFit[i], 0); + + TTime currentTimestamp; + currentTimestamp.UniversalTime(); + mData[0]->SetTimestamp(currentTimestamp); + + listToFit[i] = 0; + changed = ETrue; + } + } + //establish order + TBool orderChanged = EstablishOrder(allKeys); + + //update entries data + TBool dataChanged = UpdateEntryData(listToFit); + RebuildVisibleDataListL(); + if (changed || orderChanged || dataChanged) { + mObserver.DataChanged(); + } + allKeys.Close(); +} + +// -------------------------------------------------------------------------- +/** + * Checks if there is an entry for same app in the given list. + * @param entry entry + * @param newList ref to list + * @return ETrue if app was found + */ + +TBool CTsDataList::CheckIfExists(const CTsEntry& entry, const RTsFswArray& list) const +{ + TBool exists(EFalse); + TInt pos = FindEntry(list, entry.Key()); + if (pos >= 0) { + exists = ETrue; + } + return exists; +} + +// -------------------------------------------------------------------------- +/** + * Retrieves the bitmap for the icon of the given app. + * @param appUid application uid + * @return app CFbsBitmap + */ +CFbsBitmap* CTsDataList::GetAppIconL(const TUid& aAppUid) +{ + HbIcon icon = CaMenuIconUtility::getApplicationIcon(aAppUid.iUid, QSizeF(KAppIconWidth, KAppIconHeight)); + CFbsBitmap* iconBitmap = HbIcon2CFbsBitmapL(icon); + if (!iconBitmap) { + iconBitmap = new(ELeave) CFbsBitmap; + TInt err = KErrNotFound; + if(mDefaultIcon) { + err = iconBitmap->Duplicate(mDefaultIcon->Handle()); + } + if (KErrNone!=err) { + delete iconBitmap; + iconBitmap = NULL; + } + } + return iconBitmap; + } + +// -------------------------------------------------------------------------- +/** + * Converts HbIcon to CFbsBitmap + * @param icon icon to be coverted + * @return CFbsBitmap + */ +CFbsBitmap* CTsDataList::HbIcon2CFbsBitmapL(const HbIcon& icon) +{ + QIcon qicon = icon.qicon(); + QPixmap pixmap = qicon.pixmap(QSize(KAppIconWidth, KAppIconHeight)); + CFbsBitmap* retValue = NULL; + if (!pixmap.isNull()) { + retValue = pixmap.toSymbianCFbsBitmap(); + } + return retValue; +} +// -------------------------------------------------------------------------- +TBool CTsDataList::isSupported(TInt function) const +{ + return (RegisterScreenshotMessage == function || + UnregisterScreenshotMessage == function || + VisibilityChange == function); +} + +// -------------------------------------------------------------------------- +void CTsDataList::handleDataL(TInt function,RReadStream& dataStream) +{ + switch(function){ + case RegisterScreenshotMessage: + registerScreenshotL(dataStream); + break; + case UnregisterScreenshotMessage: + unregisterScreenshotL(dataStream); + break; + case VisibilityChange: + changeVisibilityL(dataStream); + break; + } +} + +// -------------------------------------------------------------------------- +void CTsDataList::registerScreenshotL(RReadStream& dataStream) +{ + CTsScreenshotMsg* msg = CTsScreenshotMsg::NewLC(dataStream); + const TInt pos = FindEntry(mData, GenerateKeyL(msg->windowGroupId())); + User::LeaveIfError(pos); + mData[pos]->SetScreenshotL(msg->screenshot(), msg->priority()); + CleanupStack::PopAndDestroy(msg); +} +// -------------------------------------------------------------------------- +void CTsDataList::unregisterScreenshotL(RReadStream& dataStream) +{ + + CTsUnregisterScreenshotMsg* msg = CTsUnregisterScreenshotMsg::NewLC(dataStream); + const TInt pos = FindEntry(mData, GenerateKeyL(msg->windowGroupId())); + User::LeaveIfError(pos); + mData[pos]->RemoveScreenshotL(); + CleanupStack::PopAndDestroy(msg); +} +// -------------------------------------------------------------------------- +void CTsDataList::changeVisibilityL(RReadStream& dataStream) +{ + CTsVisibilitMsg* msg = CTsVisibilitMsg::NewLC(dataStream); + const TInt pos = FindEntry(mData, GenerateKeyL(msg->windowGroupId())); + User::LeaveIfError(pos); + msg->visibility() == mData[pos]->GetVisibility() ? User::Leave(KErrInUse) : + mData[pos]->SetVisibility(msg->visibility()); + CleanupStack::PopAndDestroy(msg); + RebuildVisibleDataListL(); + mObserver.DataChanged(); +} + +// -------------------------------------------------------------------------- +/** + * Checks if given uid is on hidden list + * @param aUid uid to be checked + * @return ETrue if uid is on hidden list + */ +TBool CTsDataList::IsHiddenUid(TUid uid) +{ + return mHiddenUids.Find(uid) >= 0 ? ETrue : EFalse; +} + +// -------------------------------------------------------------------------- +/** + * Finds entry in array + * @param list list to find + * @param key finding key + * @return position or KErrNotFound + */ +TInt CTsDataList::FindEntry(const RTsFswArray& list, const TTsEntryKey& key) const +{ + TInt pos(KErrNotFound); + for (TInt entryIdx = 0; entryIdx < list.Count(); ++entryIdx) { + if (list[entryIdx]->Key() == key) { + pos = entryIdx; + break; + } + } + return pos; +} + +// -------------------------------------------------------------------------- +/** + * Establish entry order accridung to aKeyList, all keys MUST be in iData + * @param keyList reference key list + * @return ETrue if changes occured + */ +TBool CTsDataList::EstablishOrder(const RArray& keyList) +{ + TBool changed(EFalse); + TInt lastChangedItem(KErrNotFound); + __ASSERT_ALWAYS(mData.Count() == keyList.Count(), User::Panic(_L("EstablishOrder 1"), KErrBadHandle) ); + for (TInt i = 0; i < keyList.Count(); i++) { + const TTsEntryKey& currentdataKey = mData[i]->Key(); + const TTsEntryKey& referenceKey = keyList[i]; + if (!(currentdataKey == referenceKey)) { + TInt foundPos = FindEntry(mData, referenceKey); + __ASSERT_ALWAYS(foundPos>=0, User::Panic(_L("EstablishOrder 2"), KErrBadHandle) ); + CTsEntry* entry = mData[foundPos]; + mData.Remove(foundPos); + mData.Insert(entry, i); + changed = ETrue; + lastChangedItem = i; + } + } + + TTime currentTimestamp; + currentTimestamp.UniversalTime(); + for (TInt i = lastChangedItem; i >= 0; --i) { + mData[i]->SetTimestamp(currentTimestamp); + } + + return changed; +} + +// -------------------------------------------------------------------------- +/** + * Updates entry data on mData according to list + * @param list reference entires list + * @return ETrue if changes occured + */ +TBool CTsDataList::UpdateEntryData(const RTsFswArray& list) +{ + __ASSERT_ALWAYS(mData.Count() == list.Count(), User::Panic(_L("UpdateEntryData 1"), KErrBadHandle) ); + TBool changed(EFalse); + for (TInt i=0; iKey() == list[i]->Key(), User::Panic(_L("UpdateEntryData 12"), KErrBadHandle) ); + if(mData[i]->CloseableApp() != list[i]->CloseableApp()) { + mData[i]->SetCloseableApp(list[i]->CloseableApp()); + changed = ETrue; + } + } + } + return changed; +} + +// -------------------------------------------------------------------------- +/** + * Function generate task key using window group id + * @param wgId - window group id of running application + * @param entry key + */ +TTsEntryKey CTsDataList::GenerateKeyL(TInt wgId) +{ + RArray allWgIds; + CleanupClosePushL(allWgIds); + User::LeaveIfError(mResources.WsSession().WindowGroupList(0, &allWgIds)); + TTsEntryKey key; + User::LeaveIfError(TsEntryKeyGeneraror::Generate(key, wgId, allWgIds.Array())); + CleanupStack::PopAndDestroy(&allWgIds); + return key; +} + +// -------------------------------------------------------------------------- +/** + * Hides entrie if exist on mHiddenUids + * @param entry + */ +void CTsDataList::HideEntryIfNotAllowed(CTsEntry* entry) +{ + TUid uid = entry->AppUid(); + if(mHiddenUids.Find(uid) >= 0) { + entry->SetVisibility(Invisible); + } + +} + +void CTsDataList::RebuildVisibleDataListL() +{ + mVisibleData.Reset(); + + RArray visibleItems(mData.Count() ? mData.Count() : 1); + CleanupClosePushL(visibleItems); + for (TInt iter = 0; iter < mData.Count(); ++iter) { + if (Visible == mData[iter]->GetVisibility()) { + visibleItems.AppendL(iter); + } + } + + for (TInt iter = 0; iter < visibleItems.Count(); ++iter) { + mVisibleData.AppendL(mData[visibleItems[iter]]); + } + CleanupStack::PopAndDestroy(&visibleItems); +} +// end of file