taskswitcher/backstepping/src/tsbackstepping.cpp
author Jaakko Haukipuro (Nokia-MS/Oulu) <Jaakko.Haukipuro@nokia.com>
Thu, 16 Sep 2010 12:11:40 +0100
changeset 117 c63ee96dbe5f
permissions -rw-r--r--
Missing activityfw and taskswitcher components - fix for Bug 3670

/*
* 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