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