taskswitcher/backstepping/src/tsbackstepping.cpp
changeset 117 c63ee96dbe5f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/taskswitcher/backstepping/src/tsbackstepping.cpp	Thu Sep 16 12:11:40 2010 +0100
@@ -0,0 +1,196 @@
+/*
+* Copyright (c) 2009 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:
+*
+*/
+
+#include "tsbackstepping.h"
+
+#include <w32std.h>// key event
+#include <apgwgnam.h>// for CApaWindowGroupName
+#include <apgtask.h>
+#include <coedef.h>
+#include <e32property.h>
+
+#include <homescreendomainpskeys.h>
+#include <afactivitylauncher.h>
+
+#include "tsbacksteppingfilter.h"
+
+_LIT(KHsActivactionUri, "appto://20022F35?activityname=HsIdleView&activityinbackground=true");
+
+/** 
+ *  CTsBackstepping::NewL
+ *  two phase constructor
+ */
+CTsBackstepping* CTsBackstepping::NewL(MTsWindowGroupsMonitor &monitor)
+  {
+  CTsBackstepping* self = CTsBackstepping::NewLC(monitor);
+  CleanupStack::Pop(self);
+  return self;
+  }
+
+/** 
+ *  CTsBackstepping::NewLC
+ *  two phase constructor
+ */
+CTsBackstepping* CTsBackstepping::NewLC(MTsWindowGroupsMonitor &monitor)
+{ 
+  CTsBackstepping* self = new (ELeave) CTsBackstepping(monitor);
+  CleanupStack::PushL(self);
+  self->ConstructL();
+  return self;
+}
+
+/** 
+ * CTsBackstepping::CTsBackstepping
+ * constructor
+ */
+CTsBackstepping::CTsBackstepping(MTsWindowGroupsMonitor &monitor)
+:
+CTsWindowGroupsObserver(monitor)
+{
+}
+
+/** 
+ *  CTsBackstepping::~CTsBackstepping
+ *  deconstructor
+ */
+CTsBackstepping::~CTsBackstepping()
+{
+    delete mFilter;
+}
+
+/** 
+ *  CTsBackstepping::ConstructL
+ *  two phase constructor
+ */
+void CTsBackstepping::ConstructL ()
+{
+    BaseConstructL();
+    mFilter = CTsBacksteppingFilter::NewL();
+}
+
+/** 
+ * CTsBackstepping::AnalyseWindowStackL
+ * Analyzes window stack and move homescreen to proper position
+ */
+void CTsBackstepping::HandleWindowGroupChanged(MTsResourceManager &resource, const TArray<RWsSession::TWindowGroupChainInfo> &windowGroups)
+{
+    TRAP_IGNORE(HandleWindowGroupChangedL(resource, windowGroups));
+}
+
+/** 
+ * CTsBackstepping::AnalyseWindowStackL
+ * Analyzes window stack and move homescreen to proper position
+ */
+void CTsBackstepping::HandleWindowGroupChangedL(MTsResourceManager &resource,
+                                                const TArray<RWsSession::TWindowGroupChainInfo> &windowGroups)
+{  
+    // calculate the desired position of Homescreen
+    const TInt currentHsOffset(homescreenOffsetL(resource, windowGroups));
+    TInt optimalOffset(1);
+    TInt targetHsOffset(currentHsOffset);
+    for (TInt offset(0); offset < currentHsOffset; ++offset) {
+        TUid uid = getUidFromWindowGroupL(resource, windowGroups[offset].iId);
+        if (TUid::Null() != uid) {
+            if (isEmbededApp(windowGroups[offset])) {
+                targetHsOffset = parentOffsetL(offset, windowGroups) + 1;
+            } else if (!mFilter->isBlocked(uid)) {
+                if(offset + 1 < currentHsOffset && 
+                        getUidFromWindowGroupL(resource, windowGroups[offset+1].iId) == TUid::Null()) {
+                ++optimalOffset;
+                }
+                targetHsOffset = optimalOffset;
+            }
+            break;
+        } else {
+            ++optimalOffset;
+        }
+    }
+
+    // change windows order if necessary
+    if (targetHsOffset != currentHsOffset) {
+        const TInt hsWindowGroup(windowGroups[currentHsOffset].iId);
+        resource.WsSession().SetWindowGroupOrdinalPosition(hsWindowGroup, targetHsOffset);
+    }
+    
+    // switch Homescreen to Idle state if Homescreen is not in foreground and is in different state
+    if (targetHsOffset != 0) {
+        TInt hsState(EHomeScreenIdleState);
+        User::LeaveIfError(RProperty::Get(KHsCategoryUid, KHsCategoryStateKey, hsState));
+        if (hsState != EHomeScreenIdleState) {
+            CAfActivityLauncher *activityEnabler = 
+                CAfActivityLauncher::NewLC(resource.ApaSession(), 
+                                           resource.WsSession());
+            activityEnabler->launchActivityL(KHsActivactionUri);
+            CleanupStack::PopAndDestroy(activityEnabler);
+        }
+    }
+}
+
+/** 
+ * CTsBackstepping::homescreenOffsetL
+ */
+TInt CTsBackstepping::homescreenOffsetL(MTsResourceManager &resource,
+                                        const TArray<RWsSession::TWindowGroupChainInfo> &windowGroups) const 
+{
+    TInt offset(KErrNotFound);
+    for (TInt iter(0);KErrNotFound == offset && iter < windowGroups.Count(); ++iter) {
+        if (KHsCategoryUid == getUidFromWindowGroupL(resource, windowGroups[iter].iId)) {
+            offset = iter;
+        }
+    }
+    User::LeaveIfError(offset);
+    return offset;
+}
+
+/** 
+ * CTsBackstepping::homescreenOffsetL
+ */
+TInt CTsBackstepping::parentOffsetL(TInt offset,
+                                    const TArray<RWsSession::TWindowGroupChainInfo> &windowGroups) const 
+{
+    for(TInt iter(offset + 1); iter < windowGroups.Count(); ++iter) {
+        if(windowGroups[iter].iId == windowGroups[offset].iParentId) {
+            return isEmbededApp(windowGroups[iter]) ? 
+                   parentOffsetL(iter, windowGroups) : iter; 
+        }
+    }
+    User::Leave(KErrNotFound);
+    return KErrNotFound;
+}
+
+/** 
+ * CTsBackstepping::isEmbededApp
+ */
+TBool CTsBackstepping::isEmbededApp(const RWsSession::TWindowGroupChainInfo &windowGroupInfo) const 
+{
+    return 0 < windowGroupInfo.iParentId;
+}
+
+/** 
+ * CTsBackstepping::getUidFromWindowGroupL
+ */
+TUid CTsBackstepping::getUidFromWindowGroupL(MTsResourceManager &resource, TInt windowGroupId) const
+{
+    TUid retVal(TUid::Null());
+    CApaWindowGroupName *windowGroupName = CApaWindowGroupName::NewLC(resource.WsSession());
+    windowGroupName->ConstructFromWgIdL(windowGroupId);
+    retVal = windowGroupName->AppUid();
+    CleanupStack::PopAndDestroy(windowGroupName);
+    return retVal;
+}
+
+// end of file