diff -r 000000000000 -r 2f259fa3e83a uifw/AknGlobalUI/AknCapServer/src/AknEikSgcs.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AknGlobalUI/AknCapServer/src/AknEikSgcs.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,1510 @@ +/* +* Copyright (c) 2002-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: Server side implementation of AVKON System +* Graphics Coordinator. +* +*/ + + +#include "AknEikSgcs.h" +#include +#include "eiksrvsp.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "AknCapServerEntry.h" +#include +#include "winchangemonitor.h" +#include "akncapserverdebug.h" +#include "akncompaif.h" + +#include +#include +#include +#include +#include +#include "avkoninternalpskeys.h" +#include +#include +#ifdef RD_UI_TRANSITION_EFFECTS_LAYOUT_SWITCH +#include +#include +#endif + +#include +#include +const TInt KCdlEComInterfaceId = 0x101f8243; + +const TInt KLayoutChangeTimeout = 2000000; // 2s +const TInt KWgStatesGranularity = 4; +const TInt KRelinquishedThreadListGranularity = 4; +const TInt KRemoveBlankDelay = 200000; // 0.2s +// Drawing is slower when transparency is enabled. The time needs to be +// big enough to account for slowest drawing application. +const TInt KRemoveBlankDelayTransparency = 1500000; // 1.5s + +// 4s should be enough for foreground app's operations to complete. +const TInt KRestoreThreadPriorityDelay = 4000000; + +// Screensaver application UID +const TUid KScreensaverAppUid = { 0x100056CF }; + +// Read pass policy +_LIT_SECURITY_POLICY_PASS(KPassReadPolicy); + +// Policy requiring write device data capability. +_LIT_SECURITY_POLICY_C1(KWriteDDPolicy, ECapabilityWriteDeviceData); + +enum TWgStateFlags + { + EWgStateFullScreen, + EWgStatePartialForeground, + EWgStateUnderstandsPartialForeground, + EWgStateLegacyLayout, + EWgStateOrientationSpecified, + EWgStateOrientationLandscape + }; + +enum TSetLayoutBlankStep + { + ESetLayoutBlankBeforeLayoutLoad, + ESetLayoutBlankBetweenLayoutLoadAndScreenRotate, + ESetLayoutBlankAfterScreenRotate, + ESetLayoutBlankNever + }; + +NONSHARABLE_CLASS(CAknSgcServerImpl) : public CAknSgcImpl + { +public: + CAknSgcServerImpl(CEikSgcServer* aServer); + void MoveApp(TInt aAppWindowGroupId, TSgcMoveAppToWhere aWhere); + +private: + CEikSgcServer* iServer; + }; + + +class CLayoutChangeCallBack : public CActive + { +public: + CLayoutChangeCallBack(CEikSgcServer* aSgc); + void ConstructL(); + ~CLayoutChangeCallBack(); + + void RestartTimerL(); + +private: + void DoCancel(); + void RunL(); + + static TInt ThreadFunc(TAny* aStat); + + static TInt TimeoutCallback(TAny* aThis); + void DoTimeout(); + +private: + CEikSgcServer* iSgc; + RThread iThread; + TThreadId iMain; + CPeriodic* iTimeout; + }; + +CLayoutChangeCallBack::CLayoutChangeCallBack(CEikSgcServer* aSgc) +: CActive(CActive::EPriorityLow), iSgc(aSgc), iMain(RThread().Id()) + { + CActiveScheduler::Add(this); + } + +void CLayoutChangeCallBack::ConstructL() + { + // Create the thread. + User::LeaveIfError(iThread.Create(KNullDesC, ThreadFunc, 0x400, NULL, this)); + iThread.SetPriority(EPriorityAbsoluteBackground); + + // Set the active status & start the thread. + iStatus = KRequestPending; + SetActive(); + iThread.Resume(); + + RestartTimerL(); + } + +void CLayoutChangeCallBack::RestartTimerL() + { + delete iTimeout; + iTimeout = NULL; + iTimeout = CPeriodic::NewL(CActive::EPriorityStandard); + iTimeout->Start(KLayoutChangeTimeout, KLayoutChangeTimeout, TCallBack(TimeoutCallback, this)); + } + +CLayoutChangeCallBack::~CLayoutChangeCallBack() + { + Cancel(); + iThread.Close(); + delete iTimeout; + } + +void CLayoutChangeCallBack::DoCancel() + { + iThread.Terminate(0); + + // Only complete the request if not yet completed by the background thread. + if ( iStatus == KRequestPending ) + { + TRequestStatus* pStatus = &iStatus; + User::RequestComplete(pStatus, KErrCancel); + } + } + +void CLayoutChangeCallBack::RunL() + { + iSgc->HandleLayoutChangeCallBackL(); + } + + +// --------------------------------------------------------------------------- +// CLayoutChangeCallBack::ThreadFunc +// Thread entry point function. +// --------------------------------------------------------------------------- +// +TInt CLayoutChangeCallBack::ThreadFunc( TAny* aLayoutChangeCallBack ) + { + CLayoutChangeCallBack* self = + static_cast(aLayoutChangeCallBack); + RThread main; + if (KErrNone == main.Open(self->iMain)) + { + TRequestStatus* pStatus = &self->iStatus; + main.RequestComplete(pStatus, KErrNone); + main.Close(); + } + return KErrNone; + } + +TInt CLayoutChangeCallBack::TimeoutCallback( TAny* aThis ) + { + static_cast( aThis )->DoTimeout(); + return EFalse; + } + +void CLayoutChangeCallBack::DoTimeout() + { + TRAP_IGNORE( iSgc->HandleLayoutChangeCallBackL() ); + } + + +CEikSgcServer::TWgState::TWgState() +: iWgId(0), iSpLayout(0), iSpFlags(0), iAppScreenMode(KAknScreenModeUnset) + { + // Default state for window groups is full screen - handles non + // avkon apps. + iFlags.Set(EWgStateFullScreen); + } + +CEikSgcServer::TWgState::TWgState(TInt aWgId) +: iWgId(aWgId), iSpLayout(0), iSpFlags(0), iAppScreenMode(KAknScreenModeUnset) + { + // Default state for window groups is full screen - handles non + // avkon apps. + iFlags.Set(EWgStateFullScreen); + } + +inline TInt CEikSgcServer::TWgState::WgId() const + { + return iWgId; + } + +inline void CEikSgcServer::TWgState::SetWgId(TInt aWgId) + { + iWgId = aWgId; + } + +inline TInt CEikSgcServer::TWgState::SpLayout() const + { + return iSpLayout; + } + +inline void CEikSgcServer::TWgState::SetSpLayout(TInt aSpLayout) + { + iSpLayout = aSpLayout; + } + +inline TInt CEikSgcServer::TWgState::SpFlags() const + { + return iSpFlags; + } + +inline void CEikSgcServer::TWgState::SetSpFlags(TInt aSpFlags) + { + iSpFlags = aSpFlags; + } + +inline TBool CEikSgcServer::TWgState::IsFullScreen() const + { + return iFlags[EWgStateFullScreen]; + } + +inline void CEikSgcServer::TWgState::SetFullScreen(TBool aFullScreen) + { + iFlags.Assign(EWgStateFullScreen, aFullScreen); + } + +inline TBool CEikSgcServer::TWgState::IsPartialForeground() const + { + return iFlags[EWgStatePartialForeground]; + } + +inline void CEikSgcServer::TWgState::SetPartialForeground(TBool aPartialForeground) + { + iFlags.Assign(EWgStatePartialForeground, aPartialForeground); + } + +inline TBool CEikSgcServer::TWgState::UnderstandsPartialForeground() const + { + return iFlags[EWgStateUnderstandsPartialForeground]; + } + +inline void CEikSgcServer::TWgState::SetUnderstandsPartialForeground(TBool aPartialForeground) + { + iFlags.Assign(EWgStateUnderstandsPartialForeground, aPartialForeground); + } + +inline TBool CEikSgcServer::TWgState::IsLegacyLayout() const + { + return iFlags[EWgStateLegacyLayout]; + } + +inline void CEikSgcServer::TWgState::SetLegacyLayout(TBool aLegacyLayout) + { + iFlags.Assign(EWgStateLegacyLayout, aLegacyLayout); + } + +inline TBool CEikSgcServer::TWgState::IsOrientationSpecified() const + { + return iFlags[EWgStateOrientationSpecified]; + } + +inline void CEikSgcServer::TWgState::SetOrientationSpecified(TBool aOrientationSpecified) + { + iFlags.Assign(EWgStateOrientationSpecified, aOrientationSpecified); + } + +inline TBool CEikSgcServer::TWgState::IsOrientationLandscape() const + { + return iFlags[EWgStateOrientationLandscape]; + } + +inline void CEikSgcServer::TWgState::SetOrientationLandscape(TBool aOrientationLandscape) + { + iFlags.Assign(EWgStateOrientationLandscape, aOrientationLandscape); + } + +inline TInt CEikSgcServer::TWgState::AppScreenMode() const + { + return iAppScreenMode; + } + +inline void CEikSgcServer::TWgState::SetAppScreenMode(TInt aAppScreenMode) + { + iAppScreenMode = aAppScreenMode; + } + +CEikSgcServer* CEikSgcServer::NewL() + { + CEikSgcServer* self = new(ELeave) CEikSgcServer(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CEikSgcServer::CEikSgcServer() +: iWs(CEikonEnv::Static()->WsSession()), + iLastScreenModeSet(-1), + iRelinquishedThreads(KRelinquishedThreadListGranularity), + iSetLayoutBlankStep(ESetLayoutBlankBeforeLayoutLoad) + { + } + +void CEikSgcServer::ConstructL() + { + iWgStates = new(ELeave) CWgStates(KWgStatesGranularity); + + TInt err = RProperty::Define(KPSUidUikon, KUikPreferredOrientation, RProperty::EInt); + User::LeaveIfError(err); + + err = RProperty::Define( + KPSUidAvkonDomain, + KAknNotificationsInIdleAllowed, + RProperty::EInt, + KPassReadPolicy, + KWriteDDPolicy); + User::LeaveIfError(err); +#if FADE_BITMAP + + err = RProperty::Define(KPSUidAvkonInternal, KAknFadeBitmapHandle, + RProperty::EInt, + KPassReadPolicy, + KWriteDDPolicy); + User::LeaveIfError(err); + err = RProperty::Define(KPSUidAvkonInternal, KAknFadeMaskHandle, + RProperty::EInt, + KPassReadPolicy, + KWriteDDPolicy); + User::LeaveIfError(err); +#endif + + err = RProperty::Define(KPSUidAvkonInternal, KAknFadeColorHandle, + RProperty::EInt, + KPassReadPolicy, + KWriteDDPolicy); + User::LeaveIfError(err); + + err = RProperty::Define(KPSUidAvkonInternal, KAknFadeBlackMapHandle, + RProperty::EInt, + KPassReadPolicy, + KWriteDDPolicy); + User::LeaveIfError(err); + err = RProperty::Define(KPSUidAvkonInternal, KAknFadeWhiteMapHandle, + RProperty::EInt, + KPassReadPolicy, + KWriteDDPolicy); + User::LeaveIfError(err); + + + + +#ifndef TFX_USE_WCHANGE_EVENT + iWinChange = CWindowChangeMonitor::NewL(iWs); +#endif + + CAknSgcServerImpl* sgcImpl = new(ELeave) CAknSgcServerImpl(this); + // CAknSgcClient takes ownership of sgcImpl and replaces + // existing client impl with it. + CAknSgcClient::SetImpl(sgcImpl); + + // Touch compatibility mode + iAvkonAppUiBase->MopGetObjectNoChaining(iTouchCompaModeIf); + iTouchCompaScreenMode = KErrNotFound; + if (iTouchCompaModeIf) + { + iTouchCompaScreenMode = iTouchCompaModeIf->FindCompaScreenMode(); + } + + // ECom notifier for ILD installations + TCallBack callback(CEikSgcServer::LayoutInstallationCallBack, this); + iLayoutNotifier = CEComPluginNotifier::NewL(KNullUid, callback); + iLayoutNotifier->Start(); + EComPluginUtils::GetInfoArrayL(TUid::Uid(KCdlEComInterfaceId), iPrevPluginInfo); + } + +TInt CEikSgcServer::LayoutInstallationCallBack(TAny* aPtr) + { + return ((CEikSgcServer*)aPtr)->RefreshLayoutIfRequiredL(); + } + +TInt CEikSgcServer::RefreshLayoutIfRequiredL() + { + REComPluginInfoArray newPlugins; + EComPluginUtils::GetInfoArrayL(TUid::Uid(KCdlEComInterfaceId), newPlugins); + REComPluginInfoArray newPluginsCopy = newPlugins; + + // Remove any plugins that haven't changed from the arrays + TInt prevCount = iPrevPluginInfo.Count(); + while(prevCount > 0) + { + prevCount--; + TUid prevUid = (iPrevPluginInfo[prevCount]).iUid; + TInt prevVer = (iPrevPluginInfo[prevCount]).iVersion; + TInt newCount = newPlugins.Count(); + while(newCount > 0) + { + newCount--; + TUid newUid = (newPlugins[newCount]).iUid; + TInt newVer = (newPlugins[newCount]).iVersion; + if(prevUid == newUid && prevVer == newVer) + { + newPlugins.Remove(newCount); + iPrevPluginInfo.Remove(prevCount); + break; + } + } + } + + TBool refreshRequired = EFalse; + if(iPrevPluginInfo.Count() > 0) + { + // A plugin has been removed, but we can't check what it contained. + refreshRequired = ETrue; + } + else + { + // Check through the changed plugins to see whether any contain layout packs + _LIT(KLitDllPath, "%S%08x.dll"); + const TInt KPathLength = 14; // Drive letter + ":" + UID + ".dll" + for(TInt i=0; i buf; + TDriveName drive(imp.iDrive.Name()); + buf.Format(KLitDllPath, &drive, imp.iUid.iUid); + + CCdlRefCollection* refsInFile = CdlEngine::FileContentsLC(buf); + CCdlRefs* refs = CCdlRefs::NewLC(); + refs->AppendL(*refsInFile); + CCdlRefs* layoutsInFile = refs->SubsetByUidLC(LayoutPack::KCdlInterfaceUid); + TInt numLayouts = layoutsInFile->CountRefs(); + CleanupStack::PopAndDestroy(3, refsInFile); + + if(numLayouts > 0) + { + // Plugin added with layouts, refresh required + refreshRequired = ETrue; + break; + } + } + } + + // Send the event if it's needed + TInt result = KErrNone; + if(refreshRequired) + { + RWsSession session; + TInt err = session.Connect(); + if ( err == KErrNone ) + { + TWsEvent event; + event.SetType(KAknILDInstallationLayoutSwitch); + result = session.SendEventToAllWindowGroups(event); + session.Close(); + } + } + + // Store the copy of the new list of plugins for next time + iPrevPluginInfo.Reset(); + iPrevPluginInfo = newPluginsCopy; + + return result; + } + +CEikSgcServer::~CEikSgcServer() + { + delete iFadeBitmap; + delete iFadeMask; + + delete iWinChange; + delete iLayoutChangeCallBack; + delete iWgStates; + delete iRemoveBlankCallBack; + delete iLayoutNotifier; + } + +void CEikSgcServer::HandleWindowGroupListChangeL() + { + CWgIds* wgIds = CreateWgIdListLC(); + if (!TestWgListOrderOk(wgIds)) + { + ReOrderWgStatesL(wgIds); + PostChangeRecalcL(); + UpdateNotificationsInIdleAllowedKey(); + } + CleanupStack::PopAndDestroy( wgIds ); + } + +void CEikSgcServer::HandleWindowGroupParamChangeL(TInt aWgId, TBitFlags aAppFlags, TInt aSpLayout, + TInt aSpFlags, TInt aAppScreenMode) + { + LOGTEXT0("CEikSgcServer::HandleWindowGroupParamChangeL - ENTER"); + + TBool understandsPartialForegroundChanged = EFalse; + TBool fullScreenChanged = EFalse; + + TWgState& state = GetWgStateL(aWgId); + + const TBool wasFullScreen = state.IsFullScreen(); + state.SetFullScreen(aAppFlags[CAknSgcClient::EFullScreen]); + const TBool isFullScreen = state.IsFullScreen(); + + state.SetLegacyLayout(aAppFlags[CAknSgcClient::ELegacyLayout]); + state.SetSpLayout(aSpLayout); + state.SetSpFlags(aSpFlags); + + // Check whether understands partial foreground is changed. + if (!state.UnderstandsPartialForeground()) + { + understandsPartialForegroundChanged = ETrue; + } + state.SetUnderstandsPartialForeground(ETrue); + + state.SetOrientationSpecified(aAppFlags[CAknSgcClient::EOrientationSpecified]); + state.SetOrientationLandscape(aAppFlags[CAknSgcClient::EOrientationLandscape]); + state.SetAppScreenMode(aAppScreenMode); + PostChangeRecalcL(); + + // Check whether full screen mode has been changed. + fullScreenChanged = (wasFullScreen && !isFullScreen) || (!wasFullScreen && isFullScreen); + + if (understandsPartialForegroundChanged || fullScreenChanged) + { + LOGTEXT1(" understandsPartialForegroundChanged: %d", understandsPartialForegroundChanged); + LOGTEXT1(" fullScreenChanged: %d", fullScreenChanged); + + UpdateNotificationsInIdleAllowedKey(); + } + + LOGTEXT0("CEikSgcServer::HandleWindowGroupParamChangeL - EXIT"); + } + +CEikSgcServer::TWgState& CEikSgcServer::GetWgStateL(TInt aWgId) + { + TInt index = WgStateIndex(aWgId); + if (index == KErrNotFound) + { + iWgStates->AppendL(TWgState(aWgId)); + index = iWgStates->Count()-1; + } + return iWgStates->At(index); + } + +TInt CEikSgcServer::WgStateIndex(TInt aWgId) const + { + TInt count = iWgStates->Count(); + for (TInt ii=0; iiAt(ii).WgId() == aWgId) + { + return ii; + } + } + return KErrNotFound; + } + +CEikSgcServer::CWgIds* CEikSgcServer::CreateWgIdListLC() const + { + CWgIds* wgIds = new(ELeave) CWgIds(1); + CleanupStack::PushL(wgIds); + iWs.WindowGroupList(wgIds); + return wgIds; + } + +void CEikSgcServer::ReOrderWgStatesL(CWgIds* aWgIds) + { + CWgStates* newStates = new(ELeave) CWgStates(KWgStatesGranularity); + CleanupStack::PushL(newStates); + TInt count = aWgIds->Count(); + newStates->ResizeL(count); + for (TInt ii=0; iiAt(ii) = GetWgStateL(aWgIds->At(ii)); + } + CleanupStack::Pop(newStates); + delete iWgStates; + iWgStates = newStates; + } + +void CEikSgcServer::SetStatusPaneShapeAndFlagsL(TInt aSpIndex) + { + if (aSpIndex == KErrNotFound) + { + return; + } + TWgState& topState = iWgStates->At(aSpIndex); + + TInt layout = topState.SpLayout(); + if (iLayout != layout) + { + iSp->SwitchLayoutL(layout); + iLayout = layout; + } + + TInt flags = topState.SpFlags(); + if (iFlags != flags) + { + iSp->SetFlags(flags); + iFlags = flags; + } + } + +#ifndef TFX_USE_WCHANGE_EVENT +void CEikSgcServer::ActivateEffectL() + { + if(iWinChange == NULL) + { + return; // nobody there + } + +// CWindowChangeMonitor::TWinGroupEvent event = +// iWinChange->WinGroupEvent(); + + const TInt index = FocusWgIndex(); + //WgStateIndex(iWinChange-> GetFocusWg()); + + const TInt focusWgIndex = index < 0 ? 0 : index; + + const TInt count = iWgStates->Count(); + + for (TInt i = focusWgIndex; i < count; i++) + { + const TWgState& state = iWgStates->At(focusWgIndex); + const TInt wgId = state.WgId(); + + if(state.UnderstandsPartialForeground()) + { + if(wgId != iFirstFullScreenWg) + { + iWinChange->WgChangeL(wgId); + } + + // Note that exits also for non fullscreen (unlike SetPartialForegroundStatusesL). + return; + } + } + } +#endif + +void CEikSgcServer::SetPartialForegroundStatusesL() + { + TInt count = iWgStates->Count(); + TInt ii; + TBool partialFg = EFalse; + for (ii = FocusWgIndex(); ii < count; ii++) + { + TWgState& state = iWgStates->At(ii); + if (state.UnderstandsPartialForeground()) + { + if (partialFg) + { + SetWgPartialFg(state); + } + if (!state.IsFullScreen()) + { + partialFg = ETrue; + } + else + { + // Notify first full-screen app that it is topmost application though does not + // have kb focus. + if (iFirstFullScreenWg != iWgStates->At(ii).WgId() ) + { + // same event instance will be recycled for both of events... + TWsEvent event; + event.SetTimeNow(); + + if (iFirstFullScreenWg) // notify old that it has lost its focus + { + event.SetType(KAknFullOrPartialForegroundLost); + iWs.SendEventToWindowGroup(iFirstFullScreenWg, event); + } + + iFirstFullScreenWg = iWgStates->At(ii).WgId(); + event.SetType(KAknFullOrPartialForegroundGained); + iWs.SendEventToWindowGroup(iFirstFullScreenWg, event); + } + break; + } + } + } + for (++ii; iiAt(ii); + if (state.UnderstandsPartialForeground()) + { + ClearWgPartialFg(state); + } + } + +#ifndef TFX_USE_WCHANGE_EVENT + if(iWinChange != NULL) + { + iWinChange->SetWgL(iFirstFullScreenWg); + } +#endif + } + +void CEikSgcServer::PostChangeRecalcL() + { +#ifndef TFX_USE_WCHANGE_EVENT + ActivateEffectL(); +#endif + + TInt topSp = TopSpIndex(); + SetLayoutL(topSp); + SetStatusPaneShapeAndFlagsL(topSp); + SetPartialForegroundStatusesL(); + } + +TBool CEikSgcServer::TestWgListOrderOk(CWgIds* aWgIds) const + { + TInt count = aWgIds->Count(); + if (count != iWgStates->Count()) + { + return EFalse; + } + for (TInt ii = 0; ii < count; ii++) + { + if (aWgIds->At(ii) != iWgStates->At(ii).WgId()) + { + return EFalse; + } + } + return ETrue; + } + +TInt CEikSgcServer::FocusWgIndex() const + { + TInt index = WgStateIndex(iWs.GetFocusWindowGroup()); + if (index == KErrNotFound) + { + index = 0; + } + return index; + } + +void CEikSgcServer::SetWgPartialFg(TWgState& aWgState) + { + if (!aWgState.IsPartialForeground()) + { + aWgState.SetPartialForeground(ETrue); + } + } + +void CEikSgcServer::ClearWgPartialFg(TWgState& aWgState) + { + if (aWgState.IsPartialForeground()) + { + aWgState.SetPartialForeground(EFalse); + } + } + +void CEikSgcServer::SetStatusPane(CEikServStatusPane* aSp) + { + ASSERT(aSp); + iSp = aSp; + iSpWg = aSp->WindowGroup(); + } + +TInt CEikSgcServer::TopSpIndex(TInt aAfter) const + { + TInt count = iWgStates->Count(); + for (TInt topSp=aAfter+1; topSpAt(topSp).SpLayout()) + { + return topSp; + } + } + return KErrNotFound; + } + +void CEikSgcServer::PrepareForAppExitL(TInt aWgId) + { + TInt topSp = TopSpIndex(); + if (topSp != KErrNotFound) + { + TWgState& topState = iWgStates->At(topSp); + if (topState.WgId() == aWgId) + { + TInt focusWg = FocusWgIndex(); + if (focusWg != KErrNotFound && iWgStates->At(focusWg).IsPartialForeground()) + { // we trust that wg order is valid at this point. + if ( focusWg < iWgStates->Count()-1 ) + { + TWsEvent event; + event.SetType(EEventUser); + *(TApaSystemEvent*)(event.EventData())=EApaSystemEventBroughtToForeground; + event.SetTimeNow(); + iWs.SendEventToWindowGroup(iWgStates->At(focusWg+1).WgId(), event); + } + } + + // remove the status pane from the exiting wg + topState.SetSpLayout(0); + + // Set the status pane to the shape for the app below + topSp = TopSpIndex(topSp); + SetLayoutL(topSp); + SetStatusPaneShapeAndFlagsL(topSp); + if (iSp) + { + iSp->PrepareForAppExit(); + } + } + } + } + +#define FADE_COLOR_17 1 +//#define FADE_COLOR_TEXT 1 + +inline TUint8 GetColorIntensity(TUint32 aColor) + { + // Separate R, G, B + register TUint32 r = (aColor >> 16) & 0xFF; + register TUint32 g = (aColor >> 8) & 0xFF; + register TUint32 b = (aColor) & 0xFF; + + // Calculate and return intensity + return TUint8( (r*306 + g*601 + b*117) >> 10 ); + } + +void CEikSgcServer::FadeColorGenerationL() + { + MAknsSkinInstance *skin = AknsUtils::SkinInstance(); + bool b = false; +#if FADE_COLOR_17 + TAknsItemID skinid = KAknsIIDQsnOtherColors; + TRgb colorrgb; + TInt err = AknsUtils::GetCachedColor(skin, colorrgb, skinid, 19-1); + if (err != KErrNone) + { + colorrgb = TRgb(255,255,255,0); + + CFbsBitmap *bitmap=NULL, *mask=NULL; + TAknsItemID skinid = KAknsIIDQsnFrPopupCenter ; + TRAP(err, AknsUtils::CreateIconL(skin, skinid, bitmap, mask, _L(""), -1, -1)); + if (err == KErrNone) + { + TSize size(30,30); + AknIconUtils::DisableCompression(bitmap); + AknIconUtils::SetSize(bitmap, size, EAspectRatioNotPreserved); + TPoint point(15,15); + + //TBuf8<4> buf; + //bitmap->GetScanLine(buf, point, 1, bitmap->DisplayMode()); + //colorrgb = TRgb(buf[3], buf[2], buf[1], buf[0]); + + //colorrgb.SetAlpha(buf[0]); + //colorrgb.SetBlue(buf[1]); + //colorrgb.SetGreen(buf[2]); + //colorrgb.SetRed(buf[3]); + bitmap->GetPixel(colorrgb, point); + + delete bitmap; + delete mask; + b=true; + } + } + TRgb blackmap, whitemap; + TInt err1 = AknsUtils::GetCachedColor(skin, blackmap, skinid, 17-1); + TInt err2 = AknsUtils::GetCachedColor(skin, whitemap, skinid, 18-1); + + if (err1 != KErrNone) blackmap = TRgb(0,0,0,0); + if (err2 != KErrNone) whitemap = TRgb(255,255,255,0); + + TInt blackcolor = (blackmap.Red()<<16) + (blackmap.Green()<<8) + blackmap.Blue(); + TInt whitecolor = (whitemap.Red()<<16) + (whitemap.Green()<<8) + whitemap.Blue(); + + TInt blackmapint = GetColorIntensity(blackcolor); + TInt whitemapint = GetColorIntensity(whitecolor); + +#endif + +#if FADE_COLOR_TEXT + TAknsItemID skinid = KAknsIIDQsnOtherColors; + TRgb colorrgb; + TInt err = AknsUtils::GetCachedColor(skin, colorrgb, skinid, 17); + if (err != KErrNone) + { + + TAknsItemID skinid = KAknsIIDQsnTextColors ; + TInt err = AknsUtils::GetCachedColor(skin, colorrgb, skinid, EAknsCIQsnTextColorsCG19 ); + } + TInt blackmapint = 0; + TInt whitemapint = 255; +#endif + + TInt color = (colorrgb.Red()<<16) + (colorrgb.Green()<<8) + colorrgb.Blue(); + + if (b) + { + TInt intensity = GetColorIntensity(color); + if (intensity < 127) + { // background color dark + blackmapint = 0; + whitemapint = 64; + color = 0xffffff; + } + else + { + blackmapint = 192; + whitemapint = 255; + color = 0xffffff; + } + } + RProperty::Set(KPSUidAvkonInternal, KAknFadeBlackMapHandle, blackmapint); + RProperty::Set(KPSUidAvkonInternal, KAknFadeWhiteMapHandle, whitemapint); + RProperty::Set(KPSUidAvkonInternal, KAknFadeColorHandle, color); + + } + +void CEikSgcServer::FadeBitmapGenerationL() + { +#if FADE_BITMAP + // + // Generates bitmap and mask for fade wserv plugin and + // publishes them in publish&subscribe. + // + delete iFadeBitmap; + delete iFadeMask; + iFadeBitmap = NULL; + iFadeMask = NULL; + + MAknsSkinInstance *skin = AknsUtils::SkinInstance(); + + TInt err= KErrNone; + if (!Layout_Meta_Data::IsLandscapeOrientation()) + { + TAknsItemID skinid = KAknsIIDQgnGrafBgDimmingPrt; // TODO + TRAP(err, AknsUtils::CreateIconL(skin, skinid, iFadeBitmap, iFadeMask, _L(""), -1, -1)); + } + else + { + TAknsItemID skinid = KAknsIIDQgnGrafBgDimmingLsc; // TODO + TRAP(err, AknsUtils::CreateIconL(skin, skinid, iFadeBitmap, iFadeMask, _L(""), -1, -1)); + } + if (err != KErrNone) + { + TAknsItemID skinid = KAknsIIDQgnGrafBgDimming ; // TODO + TRAP(err, AknsUtils::CreateIconL(skin, skinid, iFadeBitmap, iFadeMask, _L(""), -1, -1)); + } + + if (err == KErrNone) + { // found from skins + + TRect rect = TRect(0,0,0,0); + TAknLayoutRect r; + r.LayoutRect(rect, AknLayoutScalable_Avkon::Screen().LayoutLine()); + TSize size = r.Rect().Size(); + + AknIconUtils::SetSize(iFadeBitmap, size, EAspectRatioNotPreserved); + + + TInt bitmaphandle = iFadeBitmap->Handle(); + TInt maskhandle = iFadeMask->Handle(); + RProperty::Set(KPSUidAvkonInternal, KAknFadeBitmapHandle, bitmaphandle); + RProperty::Set(KPSUidAvkonInternal, KAknFadeMaskHandle, maskhandle); + } +#endif + } +void CEikSgcServer::SetLayoutL(TInt aSpIndex) + { + if (aSpIndex == KErrNotFound) + { + return; + } + + TWgState& topState = iWgStates->At(aSpIndex); + + CEikonEnv* eikEnv = CEikonEnv::Static(); + + CAknLayoutConfig::TScreenMode mode = CAknSgcClient::CalculateScreenMode( + ETrue, + topState.IsOrientationSpecified(), + topState.IsOrientationLandscape(), + topState.AppScreenMode()); + + TInt modeIndex = mode.ModeNumber(); + TBool blank = iLastScreenModeSet != -1; + if (modeIndex != iLastScreenModeSet) + { + + // Touch compatibility mode. Disable transition effects if compa-mode + // application becomes foreground. Restore back in opposite case. + if (iTouchCompaModeIf) + { + // Disable or restore transition + iTouchCompaModeIf->DisableTransEffects( + iTouchCompaScreenMode == modeIndex); + } + + TBool tfxOn = EFalse; +#ifdef RD_UI_TRANSITION_EFFECTS_LAYOUT_SWITCH + tfxOn = CAknTransitionUtils::TransitionsEnabled( + AknTransEffect::ELayoutswitchTransitionsOff ); + if ( tfxOn ) + { + iSetLayoutBlankStep = ESetLayoutBlankAfterScreenRotate; + } + else + { + iSetLayoutBlankStep = ESetLayoutBlankBeforeLayoutLoad; + } +#endif + + if (!tfxOn) + eikEnv->WsSession().ClearAllRedrawStores(); + + // If AknNfySrv or EikSrv is displaying a global note, + // the screen blanker is allowed to stay on until it times + // out (like when AknCapSrv is displaying a note). + TInt blankCnt = 1; + if (IsGlobalNoteForeground()) + { + // For some reason, AknNfySrv and EikSrv unblank twice on target hardware. + // therefore blank is done 3 times to allow it to remain on until timeout. + blankCnt += 2; + } + + SetLayoutBlankScreenL(blank, ESetLayoutBlankBeforeLayoutLoad, + blankCnt); + + const TAknLayoutConfigScreenMode& modeRef = (const TAknLayoutConfigScreenMode&) mode; + TBool newLayoutLoaded = CAknEnv::Static()->LoadAknLayoutL(modeRef); + + FadeBitmapGenerationL(); + FadeColorGenerationL(); + SetLayoutBlankScreenL(blank, ESetLayoutBlankBetweenLayoutLoadAndScreenRotate); + + if (tfxOn) + eikEnv->WsSession().ClearAllRedrawStores(); + + // if layout change is preemptive for app change, move the app here + DoMoveApp(); + + // Set wserv screen mode + iLastScreenModeSet = modeIndex; + eikEnv->ScreenDevice()->SetScreenMode(modeIndex); + + SetLayoutBlankScreenL(blank, ESetLayoutBlankAfterScreenRotate, + blankCnt); + + // Set legacy mode in eiksrv app UI + iAvkonAppUiBase->SetLayoutAwareApp(!topState.IsLegacyLayout()); + + // Start callback for handling new layout + if (newLayoutLoaded) + { + // Swap the screen blanker to update the foreground app's layout + if (blank && iSetLayoutBlankStep < ESetLayoutBlankAfterScreenRotate) + { + iAknCapAppServerAppUi->SwapLayoutSwitchBlankScreenL(); + } + + CAknAppUi* appUi = static_cast(eikEnv->EikAppUi()); + if (appUi->IsForeground()) + { + for (; appUi; appUi = static_cast(appUi->ContainerAppUi())) + { + appUi->ReportResourceChangedToAppL(KEikDynamicLayoutVariantSwitch); + } + } + + if (iLayoutChangeCallBack) + { + // Restart the app delay callback timer if another layout change has happened + // before it triggers. + iLayoutChangeCallBack->RestartTimerL(); + } + else + { + iLayoutChangeCallBack = new(ELeave) CLayoutChangeCallBack(this); + iLayoutChangeCallBack->ConstructL(); + } + + // stop any existing timer to unblank the screen, iLayoutChangeCallBack will restart it + delete iRemoveBlankCallBack; + iRemoveBlankCallBack = NULL; + } + else + { + if (!iLayoutChangeCallBack && blank) + { + // The callback will not remove the screen blanker, + // so remove it now. + iBlankCount--; + iAknCapAppServerAppUi->BlankScreenL(EFalse); + } + } + } + } + +void CEikSgcServer::SetLayoutBlankScreenL(TBool aBlank, TInt aStep) + { + // Use a screen blanker to hide the screen change + if (aBlank && aStep == iSetLayoutBlankStep) + { + // blank the screen and keep track of how many times it's been blanked + iBlankCount++; + iAknCapAppServerAppUi->BlankScreenL(ETrue, ETrue); + } + } + +void CEikSgcServer::HandleLayoutChangeCallBackL() + { + // delete the active object + delete iLayoutChangeCallBack; + iLayoutChangeCallBack = NULL; + + CEikonEnv* eikEnv = CEikonEnv::Static(); + + // Report the layout change to the UI controls + for (CEikAppUi* appUi = eikEnv->EikAppUi(); appUi; appUi = appUi->ContainerAppUi()) + { + appUi->ReportResourceChangedToAppL(KEikDynamicLayoutVariantSwitch); + } + + // if visible tasklist must be updated during layout change event + iAknCapAppServerAppUi->UpdateTaskListL( ETrue ); + + // Remove any remaining screen blanker after a delay. + // Normally the foreground app will have removed all blanking + // before this function triggers. This is really just a backup + // in-case the app is behaving badly, or if some unfortuante + // timing has caused this function to trigger before the foreground app + // finished its redraw. The delay should give the foreground app + // sufficient time. + iRemoveBlankCount += iBlankCount; + iBlankCount = 0; + delete iRemoveBlankCallBack; + iRemoveBlankCallBack = NULL; + iRemoveBlankCallBack = CPeriodic::NewL(CActive::EPriorityLow); + + TInt removeBlankDelay = CAknEnv::Static()->TransparencyEnabled() ? + KRemoveBlankDelayTransparency : KRemoveBlankDelay; + + if(iAknCapAppServerAppUi->IsShortTimeGlobalNoteDisplaying()) + { + removeBlankDelay = KRemoveBlankDelay; + } + + iRemoveBlankCallBack->Start( + removeBlankDelay, + removeBlankDelay, + TCallBack(RemoveBlankCallBack, this)); + } + +void CEikSgcServer::RelinquishPriorityToForegroundAppL(const RMessage2& aMessage) + { + // get the client thread + SRelinquishedThread rel; + aMessage.ClientL(rel.iThread); + CleanupClosePushL(rel.iThread); + rel.iId = rel.iThread.Id(); + rel.iPriority = rel.iThread.ProcessPriority(); + + // reset the callback timer, ensure that failure does not stop existing timer + CPeriodic* newCallBack = CPeriodic::NewL(CActive::EPriorityStandard); + delete iRelinquishedThreadCallBack; + iRelinquishedThreadCallBack = newCallBack; + + iRelinquishedThreadCallBack->Start( + KRestoreThreadPriorityDelay, + KRestoreThreadPriorityDelay, + TCallBack(RestoreThreadPriorities, this)); + + // look for an existing thread + TInt count = iRelinquishedThreads.Count(); + TInt pos; + for ( pos = 0; pos < count; pos++ ) + { + if (iRelinquishedThreads[pos].iId == rel.iId) + { + break; + } + } + + if (pos( aThis )->DoRestoreThreadPriorities(); + return EFalse; + } + +void CEikSgcServer::DoRestoreThreadPriorities() + { + delete iRelinquishedThreadCallBack; + iRelinquishedThreadCallBack = NULL; + TInt count = iRelinquishedThreads.Count(); + for (TInt ii=0; iiScreenDevice(); + TInt screenMode = device->CurrentScreenMode(); + + CEikonEnv* eikEnv = CEikonEnv::Static(); + + // Update the setting cache and get SGCS to process the screen mode + // change, this may broadcast a screen device change to the apps, + // to inform them of the update + CAknEnv::Static()->SettingCache().Update( KAknHardwareLayoutSwitch ); + HandleWindowGroupParamChangeL( + eikEnv->RootWin().Identifier(), + 0, + 0, + 0, + KAknScreenModeUnset ); + + if (screenMode == device->CurrentScreenMode()) + { + // Apps will not have received a screen device changed event + // so send a KAknHardwareLayoutSwitch to the apps to ensure + // they get to know about the key + TWsEvent event; + event.SetType(KAknHardwareLayoutSwitch); + event.SetHandle(0); + eikEnv->WsSession().SendEventToAllWindowGroups( 0, event ); + } + } + +void CEikSgcServer::UpdateNotificationsInIdleAllowedKey() + { + // First, get screensaver window group identifier. + TApaTaskList taskList(CEikonEnv::Static()->WsSession()); + const TApaTask screensaverTask = taskList.FindApp(KScreensaverAppUid); + const TInt screensaverWgId = screensaverTask.WgId(); + + // Get also idle window group identifier. + TVwsViewId idleView; + if (AknDef::GetPhoneIdleViewId(idleView) != KErrNone) + { + return; + } + + const TApaTask idleTask = taskList.FindApp(idleView.iAppUid); + const TInt idleWgId = idleTask.WgId(); + + // Then go through window groups skipping partial apps and screensaver - + // check if idleWgId follows. + TBool result = EFalse; + TBool found = EFalse; + const TInt wgCount = iWgStates->Count(); + TInt ii = FocusWgIndex(); + + LOGTEXT0("======================================"); + LOGTEXT1("Window groups: %d", wgCount); + LOGTEXT1("Idle wg id: %d", idleWgId); + LOGTEXT1("Screensaver wg id: %d", screensaverWgId); + LOGTEXT1("Focus window group: %d", ii); + LOGTEXT0("======================================"); + + // Loops window groups from top to bottom, starting from focus window group. + // (Index 0 contains the foreground window group.) + while (ii < wgCount && !found) + { + const TWgState& state = iWgStates->At(ii); + const TInt currentWgId = state.WgId(); + + LOGTEXT0("\n"); + LOGTEXT1(" Window group id: %d", currentWgId); + LOGTEXT1(" UnderstandsPartialForeground: %d", state.UnderstandsPartialForeground()); + LOGTEXT1(" IsFullScreen: %d", state.IsFullScreen()); + + // Ignores non-application window groups (e.g. incall bubble), partial screen + // applications and screensaver. + if (state.UnderstandsPartialForeground() && + state.IsFullScreen() && + currentWgId != screensaverWgId) + { + // Check if current app is idle. + result = (idleWgId == currentWgId); + found = ETrue; + + LOGTEXT0("\n"); + LOGTEXT1("Window group found. Result: %d", result); + } + + ii++; + } + + // Update the P&S key only if the value has been changed. + if ((iNotificationsInIdleAllowed && !result) || (!iNotificationsInIdleAllowed && result)) + { + iNotificationsInIdleAllowed = result; + RProperty::Set(KPSUidAvkonDomain, KAknNotificationsInIdleAllowed, result); + } + } + + +TInt CEikSgcServer::RemoveBlankCallBack( TAny* aThis ) + { + static_cast( aThis )->DoRemoveBlank(); + return EFalse; + } + +void CEikSgcServer::DoRemoveBlank() + { + // remove any remaining screen blanker + for (; iRemoveBlankCount>0; iRemoveBlankCount--) + { + TRAP_IGNORE( iAknCapAppServerAppUi->BlankScreenL( EFalse ) ); + } + + iRemoveBlankCount = 0; + + // readjust the status pane wg since we pushed it forward with the screen blanker + iLastTopSpWg = -1; + + delete iRemoveBlankCallBack; + iRemoveBlankCallBack = NULL; + } + +void CEikSgcServer::SetLayoutBlankScreenL(TBool aBlank, TInt aStep, + TInt aCnt) + { + while(aCnt--) + { + SetLayoutBlankScreenL(aBlank, aStep); + } + } + +// Check if AknNfySrv or EikSrv is displaying a global note +TBool CEikSgcServer::IsGlobalNoteForeground() + { + TBool isForeground = EFalse; + TThreadId threadId; + if (iWs.GetWindowGroupClientThreadId(iWs.GetFocusWindowGroup(), + threadId) == KErrNone) + { + RThread thread; + if (thread.Open(threadId) == KErrNone) + { + TSecureId secId = thread.SecureId(); + thread.Close(); + const TUid KEikSrvUid = {0x10003a4a}; + isForeground = + secId.iId == KCommonNotifierAppSrvUid.iUid || + secId.iId == KEikSrvUid.iUid; + } + } + return isForeground; + } + +void CEikSgcServer::MoveAppL(TInt aAppWindowGroupId, TSgcMoveAppToWhere aWhere) + { + CAknTaskList* taskList = CAknTaskList::NewLC(iWs); + + // step 1: Find root (going to foreground) or tip (going to background) of + // aAppWindowGroupId's window group chain + TInt wgId = aAppWindowGroupId; + for (TInt next=wgId; next;) + { + wgId = next; + next = (aWhere == ESgcMoveAppToForeground) ? + taskList->FindParentWgId(wgId) : + taskList->FindChildWgId(wgId); + } + + // step 2: Move whole window group chain + while (wgId) + { + // move the window group + TInt index = WgStateIndex(wgId); + if (index >= 0) + { + TWgState state = iWgStates->At(index); + iWgStates->Delete(index); + if (aWhere == ESgcMoveAppToForeground) + iWgStates->InsertL(0, state); + else + iWgStates->AppendL(state); + } + + // get the next window group in the chain + wgId = (aWhere == ESgcMoveAppToForeground) ? + taskList->FindChildWgId(wgId) : + taskList->FindParentWgId(wgId); + } + + CleanupStack::PopAndDestroy(taskList); + + // Step 3: do screen rotation and move app + iMoveAppWdId = aAppWindowGroupId; + iMoveAppWhere = aWhere; + + PostChangeRecalcL(); + + // if no layout switch occured, move app here + DoMoveApp(); + } + +void CEikSgcServer::DoMoveApp() + { + if (iMoveAppWdId) + { + TApaTask task(iWs); + task.SetWgId(iMoveAppWdId); + if (iMoveAppWhere == ESgcMoveAppToForeground) + task.BringToForeground(); + else + task.SendToBackground(); + iMoveAppWdId = 0; + } + } + + +// +// CAknSgcServerImpl +// +CAknSgcServerImpl::CAknSgcServerImpl(CEikSgcServer* aServer) +: iServer(aServer) + { + } + +void CAknSgcServerImpl::MoveApp(TInt aAppWindowGroupId, TSgcMoveAppToWhere aWhere) + { + TRAP_IGNORE(iServer->MoveAppL(aAppWindowGroupId, aWhere)); + } + +// End of file