diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/ServerCore/Src/alfbridge.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/ServerCore/Src/alfbridge.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,5513 @@ +/* +* 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: AppUi class +* +*/ + + +#include +#include +#include "alf/alfappui.h" +#include "alf/alfappserver.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef ALF_USE_CANVAS +#include +#endif + +#include "alflogger.h" +#include "alf/alfappsrvsessionbase.h" +#include "alfsrvresourcemanager.h" +#include "alfsrvsettingshandler.h" +#include +#include "alfsrvtexturemanager.h" + +#include "alfstreamerserver.h" +#include "alfshareddisplaycoecontrol.h" +#include "alfbridge.h" +#include "alfstreamerconsts.h" +#include "alfscreen.h" +#include + +#include "alfwindowmanager.h" +#include "alfwindowstructs.h" +#include +#include "HuiFxEffect.h" +#include +#include +#include "alfwindowdata.h" +#include "huieffectable.h" +#include +#include "HuiRenderPlugin.h" +#include "huicanvasgc.h" +#include "huicanvasrenderbuffer.h" + +#ifdef HUI_DEBUG_TRACK_DRAWING +#include +#endif + +#ifdef _ALF_FXLOGGING +#include +#endif + +#ifdef SYMBIAN_BUILD_GCE +#include +#endif + +const TInt KVisualTransformationStepRotate = 0; + +const TReal32 KAlfVisualDefaultOpacity = 1.0f; +//const TReal32 KAlfVisualDefaultOpacity = 0.5f; + +_LIT8(KAlfWindowGroupContainerControlTag, "WGROUP"); +const TInt KAlfNumberOfFixedControlGroups = 2; + +// This debug option prints window group order with __ALFLOGSTRING +//#define ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + +// This debug option shows window groups in a grid +//#define ALF_DEBUG_VISUALIZE_WINDOWGROUP_ORDER + + +const TInt KFadeAction = 6000; + +const TInt KRosterFreezeEndTimeoutInMs = 400; + +// Timer to send finish full screen effect +// --------------------------------------------------------- +// CAlfFinishTimer +// --------------------------------------------------------- +// +NONSHARABLE_CLASS( CAlfRosterFreezeEndTimer ):public CTimer + { + public: // Constructors and destructor + static CAlfRosterFreezeEndTimer* NewL( CAlfBridge& aBridge ); + virtual ~CAlfRosterFreezeEndTimer(); + + public: // New functions + void Start( TTimeIntervalMicroSeconds32 aPeriod ); + + protected: // Functions from base classes + void DoCancel(); + + private: + CAlfRosterFreezeEndTimer( CAlfBridge& aBridge ); + void ConstructL(); + void RunL(); + + private: // Data + CAlfBridge& iBridge; + + }; + + +// --------------------------------------------------------- +// CAlfRosterFreezeEndTimer +// --------------------------------------------------------- +// +CAlfRosterFreezeEndTimer::CAlfRosterFreezeEndTimer( CAlfBridge& aBridge ) + :CTimer ( EPriorityStandard ), + iBridge( aBridge ) + { + } + +void CAlfRosterFreezeEndTimer::ConstructL() + { + CTimer::ConstructL(); + CActiveScheduler::Add( this ); + } + +CAlfRosterFreezeEndTimer* CAlfRosterFreezeEndTimer::NewL( CAlfBridge& aBridge ) + { + CAlfRosterFreezeEndTimer* self = new ( ELeave ) CAlfRosterFreezeEndTimer( aBridge ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +CAlfRosterFreezeEndTimer::~CAlfRosterFreezeEndTimer() + { + Cancel(); + } + +void CAlfRosterFreezeEndTimer::Start( TTimeIntervalMicroSeconds32 aPeriod ) + { + if (!IsActive()) + { + After( aPeriod ); + } + } + +void CAlfRosterFreezeEndTimer::RunL() + { + iBridge.iHuiEnv->Display(0).SetDirty(); + TRAP_IGNORE(iBridge.iHuiEnv->Display(0).Roster().FreezeVisibleContentL(EFalse)); + iBridge.SetVisualTreeVisibilityChanged(ETrue); + } + +void CAlfRosterFreezeEndTimer::DoCancel() + { + CTimer::DoCancel(); + } + +// --------------------------------------------------------- +// CAlfLayoutSwitchEffectcoordinator +// --------------------------------------------------------- +// +NONSHARABLE_CLASS( CAlfLayoutSwitchEffectCoordinator ) : public CBase, public MAlfGfxEffectObserver + { + public: // Constructors and destructor + CAlfLayoutSwitchEffectCoordinator( CAlfBridge& aBridge ); + virtual ~CAlfLayoutSwitchEffectCoordinator(); + + public: // MAlfGfxEffectObserver + void AlfGfxEffectEndCallBack( TInt aHandle ); + + public: + void BeginLayoutSwitch(); + void Cancel(); + + private: + AknTransEffect::TContext NextLayoutSwitchContext(); + void SetLayoutSwitchEffect(AknTransEffect::TContext aContext); + TBool LayoutSwitchEffectsExist(); + + private: // Data + + CAlfBridge& iBridge; + AknTransEffect::TContext iLayoutSwitchEffectContext; + TThreadPriority iOriginalPriority; + CAlfRosterFreezeEndTimer* iRosterFreezeEndTimer; + }; + +CAlfLayoutSwitchEffectCoordinator::CAlfLayoutSwitchEffectCoordinator( CAlfBridge& aBridge ) : + iBridge( aBridge ), + iLayoutSwitchEffectContext(AknTransEffect::ENone) + { + RThread me = RThread(); + iOriginalPriority = me.Priority(); + me.Close(); + } + +CAlfLayoutSwitchEffectCoordinator::~CAlfLayoutSwitchEffectCoordinator() + { + } + +// --------------------------------------------------------- +// CAlfLayoutSwitchEffectCoordinator::AlfGfxEffectEndCallBack +// +// This method is callback which gets called when layout +// switch effect has ended. +// --------------------------------------------------------- +// +void CAlfLayoutSwitchEffectCoordinator::AlfGfxEffectEndCallBack( TInt aHandle ) + { + //RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::AlfGfxEffectEndCallBack")); + if (iLayoutSwitchEffectContext == aHandle) + { + AknTransEffect::TContext nextContext = NextLayoutSwitchContext(); + + // Unfreeze visible content. This reveals real roster content (in new orientation). + if (nextContext == AknTransEffect::ELayoutSwitchExit) + { + #ifdef HUI_DEBUG_TRACK_DRAWING + RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::AlfGfxEffectEndCallBack unfreezing roster content")); + #endif + iBridge.iHuiEnv->Display(0).SetDirty(); + TRAP_IGNORE(iBridge.iHuiEnv->Display(0).Roster().FreezeVisibleContentL(EFalse)); + iBridge.SetVisualTreeVisibilityChanged(ETrue); + } + + // Set next effect + SetLayoutSwitchEffect(nextContext); + + if (nextContext == AknTransEffect::ENone) + { + // Restore normal priority + RThread me = RThread(); + me.SetPriority(iOriginalPriority); + me.Close(); + + // Just in case refresh everything + iBridge.iHuiEnv->Display(0).SetDirty(); + } + } + else + { + //RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::AlfGfxEffectEndCallBack - got different handle (normal, dont worry...) - %i"), aHandle); + } + } + +// --------------------------------------------------------- +// CAlfLayoutSwitchEffectCoordinator::Cancel +// --------------------------------------------------------- +// +void CAlfLayoutSwitchEffectCoordinator::Cancel() + { + // Disable effect + SetLayoutSwitchEffect( AknTransEffect::ENone ); + + // Unfreeze visible content + if ( iRosterFreezeEndTimer ) + { + iRosterFreezeEndTimer->Cancel(); + } + + iBridge.iHuiEnv->Display(0).SetDirty(); + TRAP_IGNORE(iBridge.iHuiEnv->Display(0).Roster().FreezeVisibleContentL(EFalse)); + iBridge.SetVisualTreeVisibilityChanged(ETrue); + + // Restore normal priority + RThread me = RThread(); + me.SetPriority(iOriginalPriority); + me.Close(); + } + +// --------------------------------------------------------- +// CAlfLayoutSwitchEffectCoordinator::BeginLayoutSwitch +// +// This method starts the layout switch effect procedure. +// --------------------------------------------------------- +// +void CAlfLayoutSwitchEffectCoordinator::BeginLayoutSwitch() + { + // Hm. what to do if earlier is already in progress ? + //RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::BeginLayoutSwitch")); + if ( iBridge.iHuiEnv->MemoryLevel() <= EHuiMemoryLevelLowest ) + { + // No effects in low memory mode + return; + } + + if (!iLayoutSwitchEffectContext) + { + TBool tfxOn = CAknTransitionUtils::TransitionsEnabled(AknTransEffect::ELayoutswitchTransitionsOff ); + TBool tfxExists = LayoutSwitchEffectsExist(); + if (tfxOn && tfxExists) + { + // Boost priority so that we are able to draw more frames for the effect + RThread me = RThread(); + me.SetPriority(EPriorityAbsoluteHigh); + me.Close(); + + // Freeze visual content + //RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::BeginLayoutSwitch freezing roster content")); + iBridge.iHuiEnv->Display(0).SetDirty(); + TRAP_IGNORE(iBridge.iHuiEnv->Display(0).Roster().FreezeVisibleContentL(ETrue)); + + // Remove all other effects + iBridge.HandleGfxStopEvent( EFalse ); + iBridge.RemoveAllTemporaryPresenterVisuals(); + + // Set first layout switch effect + SetLayoutSwitchEffect(AknTransEffect::ELayoutSwitchStart); + } + else + { + if (!iRosterFreezeEndTimer) + { + TRAP_IGNORE(iRosterFreezeEndTimer = CAlfRosterFreezeEndTimer::NewL(iBridge)); + } + + if (iRosterFreezeEndTimer) + { + iBridge.iHuiEnv->Display(0).SetDirty(); + TRAP_IGNORE(iBridge.iHuiEnv->Display(0).Roster().FreezeVisibleContentL(ETrue)); + + // Remove all other effects + iBridge.HandleGfxStopEvent( EFalse ); + iBridge.RemoveAllTemporaryPresenterVisuals(); + + // Set remove freeze timer + iRosterFreezeEndTimer->Start(KRosterFreezeEndTimeoutInMs*1000); + } + //RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::BeginLayoutSwitch - tfx are set OFF -> I am not starting effect.")); + } + } + else + { + //RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::BeginLayoutSwitch - old effect exists - %i"), iLayoutSwitchEffectContext); + } + } + +// --------------------------------------------------------- +// CAlfLayoutSwitchEffectCoordinator::NextLayoutSwitchContext +// +// This method automatically selects the next context in the +// layout switch procedure. +// +// Contextes change in the following order during layout switch: +// +// 1. AknTransEffect::ENone +// 2. AknTransEffect::ELayoutSwitchStart +// 3. AknTransEffect::ELayoutSwitchExit +// 4. AknTransEffect::ENone +// +// After new context is selected, appropriate effect is set +// (and/or removed) from the roster. +// +// --------------------------------------------------------- +// +AknTransEffect::TContext CAlfLayoutSwitchEffectCoordinator::NextLayoutSwitchContext() + { + // Resolve next context based on current context + AknTransEffect::TContext newContext = AknTransEffect::ENone; + switch (iLayoutSwitchEffectContext) + { + case AknTransEffect::ENone: + { + newContext = AknTransEffect::ELayoutSwitchStart; + break; + } + case AknTransEffect::ELayoutSwitchStart: + { + newContext = AknTransEffect::ELayoutSwitchExit; + break; + } + case AknTransEffect::ELayoutSwitchExit: // fallthrough + default: + { + newContext = AknTransEffect::ENone; + break; + } + } + + //RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::NextLayoutSwitchEffectL old ctx = %i, new ctx = %i"), iLayoutSwitchEffectContext, newContext); + return newContext; + } + +// --------------------------------------------------------- +// CAlfLayoutSwitchEffectCoordinator::SetLayoutSwitchEffectL +// +// This method sets correct effect based on the given +// layout switch context. +// +// --------------------------------------------------------- +// +void CAlfLayoutSwitchEffectCoordinator::SetLayoutSwitchEffect(AknTransEffect::TContext aContext) + { + MHuiEffectable* effectable = iBridge.iHuiEnv->Display(0).Roster().Effectable(); + CHuiFxEffect* effect = NULL; + CHuiFxEngine* engine = iBridge.iHuiEnv->EffectsEngine(); + + if (!effectable || !engine) + { + return; + } + + // Update current context + iLayoutSwitchEffectContext = aContext; + + if (aContext == AknTransEffect::ENone) + { + // Just remove effect + //RDebug::Print(_L("CAlfLayoutSwitchEffectCoordinator::NextLayoutSwitchEffectL - removing effect")); + effectable->EffectSetEffect(NULL); // This calls AlfGfxEffectEndCallBack + } + else + { + // Load correct effect + for ( TInt i = 0; iLoadEffectL(*iBridge.iAlfRegisteredEffects[i].iEffectFile, effect, effectable, NULL, this, iLayoutSwitchEffectContext, 0 ) ); + break; + } + } + } + } + +TBool CAlfLayoutSwitchEffectCoordinator::LayoutSwitchEffectsExist() + { + TBool appearExists = EFalse; + TBool disAppearExists = EFalse; + + for ( TInt i = 0; iConstructL(); + CleanupStack::Pop( self ); + return self; + } + +CAlfEffectEndTimer::~CAlfEffectEndTimer() + { + Cancel(); + } + +void CAlfEffectEndTimer::Start( TTimeIntervalMicroSeconds32 aPeriod, TInt aHandle ) + { + iHandle = aHandle; + After( aPeriod ); + } + +void CAlfEffectEndTimer::RunL() + { + // + // timer completes and control is returned to caller + // + iBridge.TransitionFinishedHandlerL( iHandle ); + // We don't become active unless we are explicitly restarted + } + +void CAlfEffectEndTimer::DoCancel() + { + CTimer::DoCancel(); + } + + +// ======== MEMBER FUNCTIONS ======== + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +CAlfBridge* CAlfBridge::NewL( CAlfStreamerBridge** aHost, CHuiEnv* aEnv ) + { + CAlfBridge* self = new (ELeave) CAlfBridge( aHost ); + CleanupStack::PushL( self ); + self->ConstructL( aEnv ); + CleanupStack::Pop( self ); + return self; + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::ProvideBitmapL(TInt /*aId*/, CFbsBitmap*& aBitmap, CFbsBitmap*& aMaskBitmap) + { + aBitmap = iHack; + aMaskBitmap = iDummyMask; + }; + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +CAlfBridge::CAlfBridge(CAlfStreamerBridge** aHost) + : iHost(aHost), iCurrentMemoryLevel(EHuiMemoryLevelNormal) + { + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +CAlfBridge::~CAlfBridge() + { + delete iFadeEffectFile; + iWindowHashArray.Close(); + for( TInt i = 0; i< iAlfRegisteredEffects.Count(); i++ ) + { + delete iAlfRegisteredEffects[i].iEffectFile; + } + iAlfRegisteredEffects.Close(); + iFinishedEffects.Close(); + delete iEffectEndTimer; + iDeadControlGroups.Close(); + iEffectWindowGroups.Close(); + delete iFullScreenEffectData; + + if (iActivated) + { + iBridgerClient.Close(); + } + +#ifdef HUI_DEBUG_TRACK_DRAWING + delete iCommandDebug; +#endif + delete iCursorTimer; + delete iLayoutSwitchEffectCoordinator; + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::ConstructL(CHuiEnv* aEnv) + { + iHuiEnv = aEnv; + +#ifdef SYMBIAN_BUILD_GCE + iPrintFPS = EFalse; +#ifndef __WINSCW__ + _LIT(KRDSupport, "c:\\resource\\errrd" ); + RFs& fs = CHuiStatic::FsSession(); + if (fs.Handle() && BaflUtils::FileExists( fs, KRDSupport )) + { + iPrintFPS = ETrue; + } +#endif +#endif //SYMBIAN_BUILD_GCE + // create the key for indication transition ends + // No access restrictions for starters + TInt err = RProperty::Define( KPSAlfDomain, KAlfTransitionStatus, + RProperty::EInt ); + if (!err) + { + // Initialize to no transition + RProperty::Set( KPSAlfDomain, KAlfTransitionStatus, 0 ); + } + + iEffectEndTimer = CAlfEffectEndTimer::NewL( *this ); + iWindowHashArray.ReserveL( 500 ); + iAlfRegisteredEffects.ReserveL(10); + +#ifdef HUI_DEBUG_TRACK_DRAWING + iCommandDebug = CAlfCommandDebug::NewL(); +#endif + + iLayoutSwitchEffectCoordinator = new (ELeave) CAlfLayoutSwitchEffectCoordinator(*this); + iAlfSecureId = RThread().SecureId(); + RegisterFadeEffectL(); + } + +// --------------------------------------------------------------------------- +// RegisterFadeEffectL +// +// Note, If theme DOES NOT register its own fade effect, another hardcoded fade +// effect will be used instead. For example, if theme effects are turned off, +// a fade that does not belong to the theme may be in use. +// --------------------------------------------------------------------------- +void CAlfBridge::RegisterFadeEffectL() + { + // TODO: RND, REMOVE MMC DRIVE-F, WHEN NOT REQUIRED FOR TESTING + _LIT(KDrivePrefence,"FZC"); + // Force register fade effect. Try first MMC, then ROM. + CHuiFxEngine* engine = iHuiEnv->EffectsEngine(); + RFs& fs = CHuiStatic::FsSession(); + if (fs.Handle() && engine) + { + _LIT(KFadeEffectPath, ":\\resource\\effects\\fade_effect.fxml"); + TBufC<4> drives(KDrivePrefence); + HBufC* effectFullName = HBufC::NewLC(KFadeEffectPath().Length() + 1); + + for(TInt i=0; i< drives.Length(); i++) + { + effectFullName->Des().Copy(drives.Mid(i,1)); + effectFullName->Des().Append(KFadeEffectPath); + + if (BaflUtils::FileExists( fs, *effectFullName )) + { + DoRegisterEffectL(*effectFullName, KFadeAction); + break; + } + } + CleanupStack::PopAndDestroy(effectFullName); + DoSetCachedFadeEffectL(); + } + } + +// --------------------------------------------------------------------------- +// DoSetCachedFadeEffectL +// --------------------------------------------------------------------------- +// +void CAlfBridge::DoSetCachedFadeEffectL() + { + for (TInt i = 0; i < iAlfRegisteredEffects.Count(); i++) + { + //KFadeAction = 6000, indicating the action corroposnds to fading + if (iAlfRegisteredEffects[i].iAction == KFadeAction) + { + delete iFadeEffectFile; + iFadeEffectFile = NULL; + iFadeEffectFile = iAlfRegisteredEffects[i].iEffectFile->AllocL(); + __ALFLOGSTRING1( ">> Setting fade effect file %S", iFadeEffectFile ); + break; + } + } + } + +// --------------------------------------------------------------------------- +// AddNewScreenL +// --------------------------------------------------------------------------- +// +void CAlfBridge::AddNewScreenL(CAlfSharedDisplayCoeControl* aSharedCoeControl) + { + TInt screenNumber = iAlfScreens.Count(); // \todo this might not be the same as real WServ screen number + + // We do not yet support drawing winGC draw commands to other than primary screen. + // As fully functional and tested implementation is not there, better to panic here. + if (screenNumber!=0) + { + __ALFLOGSTRING("CAlfBridge::AddNewScreenL. Fatal error! Only screen 0 is supported in Alf server!"); + User::Invariant(); + } + + CAlfScreen* screen = new(ELeave) CAlfScreen(); + CleanupStack::PushL(screen); + screen->ConstructL(screenNumber, *this, *iHuiEnv, aSharedCoeControl); + iAlfScreens.AppendL( screen ); + CleanupStack::Pop(screen); + + ShowControlGroupL(screen->iDisplay->Roster(), *(screen->iFloatingSpriteControlGroup), KHuiRosterShowAtTop, screenNumber); + ShowControlGroupL(screen->iDisplay->Roster(), *(screen->iFullscreenEffectControlGroup), KHuiRosterShowAtTop, screenNumber); + + + screen->iFloatingSpriteControlGroup->SetAcceptInput(EFalse); + screen->iFullscreenEffectControlGroup->SetAcceptInput(EFalse); + } + +//------------------------------------------------------------------------------ +// Dumdidumdidum.. +//------------------------------------------------------------------------------ +void CAlfBridge::AddNewScreenFromWindowL(RWindow* aWindow) + { + TInt screenNumber = iAlfScreens.Count(); // \todo this might not be the same as real WServ screen number + + CAlfScreen* screen = new(ELeave) CAlfScreen(); + CleanupStack::PushL(screen); + screen->ConstructL(screenNumber, *this, *iHuiEnv, aWindow); + iAlfScreens.AppendL( screen ); + CleanupStack::Pop(screen); + + ShowControlGroupL(screen->iDisplay->Roster(), *(screen->iFloatingSpriteControlGroup), KHuiRosterShowAtTop, screenNumber); + ShowControlGroupL(screen->iDisplay->Roster(), *(screen->iFullscreenEffectControlGroup), KHuiRosterShowAtTop, screenNumber); + + screen->iFloatingSpriteControlGroup->SetAcceptInput(EFalse); + screen->iFullscreenEffectControlGroup->SetAcceptInput(EFalse); + } + + + +// --------------------------------------------------------------------------- +// AddVisual +// --------------------------------------------------------------------------- +// +void CAlfBridge::AddVisual( + TInt aWindowNodeId, + TInt aClientSideId, + TInt aClientSideGroupId, + CHuiCanvasVisual* aVisual ) + { + __ALFFXLOGSTRING1("CAlfBridge::AddVisual 0x%x", aWindowNodeId); + THashVisualStruct visualStruct( aVisual, aClientSideId, aClientSideGroupId); + iWindowHashArray.Insert( aWindowNodeId, visualStruct ); + iPreviouslySearchedVisualId = aWindowNodeId; + iPreviouslySearchedVisual = aVisual; + } + +// --------------------------------------------------------------------------- +// RemoveVisual +// --------------------------------------------------------------------------- +// +void CAlfBridge::RemoveVisual( TInt aWindowNodeId ) + { + __ALFFXLOGSTRING1("CAlfBridge::RemoveVisual 0x%x", aWindowNodeId); + iWindowHashArray.Remove( aWindowNodeId ); + iPreviouslySearchedVisualId = 0; + } + +// --------------------------------------------------------------------------- +// FindVisual +// --------------------------------------------------------------------------- +// +CHuiCanvasVisual* CAlfBridge::FindVisual(TInt aWindowNodeId ) + { + if ( iPreviouslySearchedVisualId == aWindowNodeId ) + { + return iPreviouslySearchedVisual; + } + + THashVisualStruct* visualStruct = iWindowHashArray.Find( aWindowNodeId ); + if ( visualStruct ) + { + iPreviouslySearchedVisualId = aWindowNodeId; + iPreviouslySearchedVisual = visualStruct->iVisual; + return iPreviouslySearchedVisual; + } + __ALFFXLOGSTRING1("CAlfBridge::FindVisual - Visual 0x%x not found", aWindowNodeId); + return NULL; + } + +// --------------------------------------------------------------------------- +// FindVisualByClientSideId +// --------------------------------------------------------------------------- +// +CHuiCanvasVisual* CAlfBridge::FindVisualByClientSideIds( + TUint32 aClientSideId, + TUint32 aClientSideGroupId ) + { + THashMapIter iter(iWindowHashArray); + THashVisualStruct const * node = 0; + do + { + node = iter.NextValue(); + if (node + && (*node).iClientSideId==aClientSideId + && (*node).iClientSideGroupId==aClientSideGroupId ) + { + return (*node).iVisual; + } + } + while(node); + return NULL; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +CHuiControlGroup* CAlfBridge::FindControlGroup(TInt aWindowGroupNodeId, TInt aScreenNumber ) + { + for (TInt i=0; iiControlGroups.Count();i++) + { + if (iAlfScreens[aScreenNumber]->iControlGroups[i].iWindowGroupNodeId == aWindowGroupNodeId) + { + return iAlfScreens[aScreenNumber]->iControlGroups[i].iControlGroup; + } + } + return NULL; + } + +// --------------------------------------------------------------------------- +// FindClientWindowGroupId +// --------------------------------------------------------------------------- +// +TInt CAlfBridge::FindClientWindowGroupId( TInt aScreenNumber, CHuiControlGroup& aControlGroup ) + { + for (TInt i=0; iiControlGroups.Count();i++) + { + if( iAlfScreens[aScreenNumber]->iControlGroups[i].iControlGroup == &aControlGroup ) + { + return iAlfScreens[aScreenNumber]->iControlGroups[i].iClientWindowGroupId; + } + } + return KErrNotFound; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +CHuiControlGroup* CAlfBridge::FindControlGroupByWindowGroupId( TInt aWindowGroupId, TInt& aScreenNumber, TAlfControlGroupEntry** aAlfGroup ) + { + TInt firstWin = aScreenNumber; + TInt lastWin = aScreenNumber; + if ( aScreenNumber == KErrNotFound ) + { + firstWin = 0; + lastWin = iAlfScreens.Count()-1; + } + + for ( TInt j = firstWin; j <= lastWin; j++ ) + { + for ( TInt i = 0; i < iAlfScreens[j]->iControlGroups.Count(); i++ ) + { + if ( iAlfScreens[j]->iControlGroups[i].iClientWindowGroupId == aWindowGroupId ) + { + aScreenNumber = j; + if ( aAlfGroup != NULL ) + { + *aAlfGroup = &iAlfScreens[j]->iControlGroups[i]; + } + return iAlfScreens[j]->iControlGroups[i].iControlGroup; + } + } + } + return NULL; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +CHuiControlGroup* CAlfBridge::FindControlGroupByAppId( TInt aAppId ) + { + for ( TInt i = 0; i < iAlfScreens[0]->iControlGroups.Count(); i++ ) + { + if ( iAlfScreens[0]->iControlGroups[i].iSecureId == aAppId ) + { + return iAlfScreens[0]->iControlGroups[i].iControlGroup; + } + } + return NULL; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// + +void CAlfBridge::ListFamilyTreeL( RPointerArray& aArray, const CHuiLayout* aLayout ) + { + if (aLayout->Count()) + { + aArray.Append(aLayout); + + for(TInt i = 0; i< aLayout->Count(); i++) + { + ListFamilyTreeL(aArray, (CHuiLayout*)&aLayout->Visual(i)); + } + } + else + { + aArray.Append(aLayout); + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::DeleteControlGroupL(TInt aWindowGroupNodeId, TInt aScreenNumber ) + { + for (TInt i=0; iiControlGroups.Count();i++) + { + if (iAlfScreens[aScreenNumber]->iControlGroups[i].iWindowGroupNodeId == aWindowGroupNodeId) + { + if (iAlfScreens[aScreenNumber]->iDisplay) + { + CHuiControl& control = iAlfScreens[aScreenNumber]->iControlGroups[i].iControlGroup->Control(0); + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + // wserv has notifed that this control group and its layout should be destroyed. However, we might be + // have effect on the layout itself or layout is being drawn as external content. This indicates that + // we should not delete the control group at this point, but add it to iDeadControlGroup list, which + // is cleared when effect has finished. + RPointerArray familyTree; + ListFamilyTreeL(familyTree, layout); // recursively dig the family tree + + if (HasActiveEffect(layout)) + { + __ALFFXLOGSTRING1("Layout 0x%x has external content", layout); + // EHuiVisualFlagShouldDestroy destroy flag should have come for the windows in this layout already + layout->SetFlags(EHuiVisualFlagShouldDestroy); + // move this layout to effect control group, where it can still be shown. this control group may be deleted. + CHuiControl& control = iAlfScreens[aScreenNumber]->iControlGroups[i].iControlGroup->Control(0); + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + + for(TInt familyIndex = 0; familyIndex < familyTree.Count();familyIndex++) + { + control.Remove(familyTree[familyIndex]); // remove ownership from original group + } + + control.Remove(layout); // remove ownership from original group + // move visuals to safe place. the original group must be destroyed. + __ALFFXLOGSTRING1("MOVING 0x%x to effect group", layout); + CHuiControl& effectControlGroup = iAlfScreens[0]->iFullscreenEffectControlGroup->Control(0); + CHuiLayout* effectControlGroupLayout = (CHuiLayout*) &effectControlGroup.Visual(0); + // Transfers ownership of visuals. + effectControlGroup.AppendL(layout, effectControlGroupLayout); // this will remove it from the previous layout + layout->SetOwner(effectControlGroup); + + for(TInt familyIndex = 0; familyIndex < familyTree.Count();familyIndex++) + { + familyTree[familyIndex]->SetOwner(effectControlGroup); + } + } + else + { + // check once more, that the windows in this group are not having effects. + // the layout is not have effect, but some child window might. + // in this case, the child window effects WILL BE REMOVED. + for(TInt familyIndex = 0; familyIndex < familyTree.Count();familyIndex++) + { + RemoveTemporaryPresenterVisual(familyTree[familyIndex]); + } + } + familyTree.Close(); + iAlfScreens[aScreenNumber]->iDisplay->Roster().Hide(*iAlfScreens[aScreenNumber]->iControlGroups[i].iControlGroup); + __ALFFXLOGSTRING("CAlfBridge::DeleteControlGroupL - Deleting group"); + iAlfScreens[aScreenNumber]->iControlGroups.Remove(i); + iHuiEnv->DeleteControlGroup(aWindowGroupNodeId); + __ALFFXLOGSTRING("CAlfBridge::DeleteControlGroupL - Deleting group done"); + } + break; + } + } + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +CHuiControlGroup& CAlfBridge::CreateControlGroupL( + TInt aWindowGroupNodeId, + TInt aClientWindowGroupId, + TInt aSecureId, + TInt aScreenNumber ) + { + CHuiControlGroup* group = FindControlGroup(aWindowGroupNodeId,aScreenNumber); + if (!group) + { + group = &iHuiEnv->NewControlGroupL(aWindowGroupNodeId); + CleanupStack::PushL(group); + CHuiControl* cntrl = new (ELeave) CHuiControl(*iHuiEnv); + CleanupStack::PushL(cntrl); + CHuiLayout* layout = NULL; + + cntrl->ConstructL(); + group->AppendL(cntrl); + CleanupStack::Pop(cntrl); + cntrl->SetRole(EAlfWindowGroupContainer); + + layout = CHuiCanvasVisual::AddNewL(*cntrl); + layout->SetTagL(KAlfWindowGroupContainerControlTag); + layout->ClearFlag(EHuiVisualFlagClipping); // No need to clip, should be faster without clipping + // IsVisualOpaque should return true if there is no effect. + // So that's why opaque flag is set to this layout. + layout->SetFlag(EHuiVisualFlagOpaqueHint); + + TAlfControlGroupEntry entry; + entry.iControlGroup = group; + entry.iWindowGroupNodeId = aWindowGroupNodeId; + entry.iClientWindowGroupId = aClientWindowGroupId; + entry.iSecureId = aSecureId; + // we have received start effect for this group, but the group did not exist in alf universe at the time. hide the group. + if (iFullScreenEffectData + && iFullScreenEffectData->iWaitingWindowGroup + && iFullScreenEffectData->iToAppId == aSecureId) + { + CHuiControlGroup* fromGroup = NULL; + CHuiLayout* fromLayout = NULL; + fromGroup = FindControlGroupByAppId(iFullScreenEffectData->iFromAppId); + if (fromGroup) + { + CHuiControl& control2 = fromGroup->Control(0); + fromLayout = (CHuiLayout*)&control2.Visual(0); + } + + + // First HandleGfxEvent, then clear iWaitingWindowGroup. + TBool failed = HandleGfxEventL( *iFullScreenEffectData, layout, fromLayout ); + if ( iFullScreenEffectData ) + { + iFullScreenEffectData->iWaitingWindowGroup = EFalse; + } + if ( failed ) + { + // Effect failed, reset state + HandleGfxStopEvent( EFalse ); // destroys iFullScreenEffectData + } + } + entry.iScreenNumber = aScreenNumber; +// entry.iRole = EAlfWindowGroupContainer; + + iAlfScreens[aScreenNumber]->iControlGroups.Append(entry); + CleanupStack::Pop(group); + + if (iAlfScreens[aScreenNumber]->iDisplay) + ShowControlGroupL(iAlfScreens[aScreenNumber]->iDisplay->Roster(), *group, KHuiRosterShowAtTop, aScreenNumber); + } + + + return *group; + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::ShowControlGroupL(CHuiRoster& aRoster, CHuiControlGroup& aGroup, TInt aWhere, TInt aScreenNumber ) + { + CAlfScreen* screen = iAlfScreens[aScreenNumber]; + +#ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + DebugPrintControlGroupOrder(*screen, aRoster, aGroup); +#endif + +#ifdef ALF_DEBUG_VISUALIZE_WINDOWGROUP_ORDER + if (!aGroup.IsTransformed()) + { + aGroup.EnableTransformationL(); + aGroup.Transformation().Translate(0,0); + aGroup.Transformation().Scale(0.3,0.3); + } +#endif + + TInt last = aRoster.Count() - 1; + + +// when an application exits, it must be shown on top util the effect has run its course. +// But this tends to mess up the order of other groups, and application menu softkeys will +// disappear. + if ( aGroup.Control(0).Visual(0).Effect() ) + { + if ( aGroup.Control(0).Role() != EAlfWindowGroupContainer ) + { + // The case where the application control group is deleted by window server + // has been solved by deleting the tag when window server wants to delete + // the group. Window server no longer has it, but we keep it alive for a while + // to show the effect. The group will be deleted when the effect ends. + aWhere = aRoster.Count() - KAlfNumberOfFixedControlGroups; + } + } + + if (aGroup.Control(0).Role() == EAlfWindowGroupContainer) + { + // Window group control groups + ShowWindowGroupControlGroupL(aRoster, aGroup, aWhere, aScreenNumber); + aGroup.SetAcceptInput(EFalse); + } + else if (aGroup.Control(0).Role() == EAlfSessionContainer) + { + // ALF application control groups + ShowSessionContainerControlGroupL(aRoster, aGroup, aWhere, aScreenNumber); + } + else + { + aRoster.ShowL(aGroup, aWhere); + aGroup.SetAcceptInput(EFalse); + } + +#ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + DebugPrintControlGroupOrder(*screen, aRoster, aGroup); +#endif + +#ifdef ALF_DEBUG_VISUALIZE_WINDOWGROUP_ORDER + VisualizeControlGroupOrderL(aRoster, aGroup); +#endif + + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::ShowSessionContainerControlGroupL(CHuiRoster& aRoster, CHuiControlGroup& aGroup, TInt aWhere, TInt aScreenNumber ) + { + TInt last = aRoster.Count() - 1; + + CAlfScreen* screen = iAlfScreens[aScreenNumber]; + + if (aWhere == KHuiRosterShowAtBottom) + { + // Most bottom one of alf control groups + aRoster.ShowL(aGroup, FirstAlfControlGroupIndex(aScreenNumber)); + } + else if (aWhere == KHuiRosterShowAtTop) + { + // Most top one of alf control groups + TInt newIndex = LastAlfControlGroupIndex(aScreenNumber); + + // check if the aGroup is already in a roster + for (TInt j=0; j= 0; i--) + { + if (aRoster.ControlGroup(i).Control(0).Role() == EAlfWindowGroupContainer) + { + aRoster.ShowL(aGroup, i); + break; + } + } + } + } + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::SetAlfWindowGroupId(TInt aAlfWindowGroupId) + { + iAlfWindowGroupId = aAlfWindowGroupId; + // check if hithcock window group was already there + TInt secureId = RThread().SecureId(); + if (iAlfScreens.Count()) + { + for ( TInt i = 0; i < iAlfScreens[0]->iControlGroups.Count(); i++ ) + { + if ( iAlfScreens[0]->iControlGroups[i].iSecureId == secureId && + iAlfScreens[0]->iControlGroups[i].iClientWindowGroupId != CHuiStatic::RootWin(0)->Identifier()) + { + iAlfWindowGroupNodeId = iAlfScreens[0]->iControlGroups[i].iWindowGroupNodeId; + return; + } + } + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +CHuiDisplay* CAlfBridge::Display(TInt aScreenNum) + { + for ( TInt i = 0 ; i < iAlfScreens.Count() ; i++ ) + { + if ( iAlfScreens[i]->iScreenNum == aScreenNum ) + { + return iAlfScreens[i]->iDisplay; + } + } + return NULL; + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::ReorderAlfControlGroupsL( TInt aScreenNumber ) + { + if (iAlfScreens[aScreenNumber]->iDisplay) + { + RPointerArray controlGroupOrder; + CHuiRoster& roster = iAlfScreens[aScreenNumber]->iDisplay->Roster(); + for (TInt j=0; jiDisplay) + { + CHuiRoster& roster = iAlfScreens[aScreenNumber]->iDisplay->Roster(); + for (TInt j=0; jiDisplay) + { + CHuiRoster& roster = iAlfScreens[aScreenNumber]->iDisplay->Roster(); + for (TInt j=0; jiDisplay == &aDisplay ) + { + return iAlfScreens[i]->iScreenNum; + } + } + return KErrNotFound; + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::NotifyDisplayRefreshStarted(CHuiDisplay& aDisplay) + { + // Look for the correct display + TInt screenNumber = ResolveScreenNumber(aDisplay); + RemoveTemporaryPresenterVisuals(); + if ( screenNumber != KErrNotFound ) + { + // FPS Counter with hitchcock drawing +#ifdef SYMBIAN_BUILD_GCE + if(iPrintFPS) + { + TReal fps = CHuiStatic::FrameRate(); + if(fps > 0) + { + TBuf<8> numBuf; + numBuf.AppendNum(fps, TRealFormat(5,1)); + TRAP_IGNORE( + { + iAlfScreens[screenNumber]->iFPSText->SetTextL( numBuf ); + }) + } + } +#endif + + if (iAlfScreens[screenNumber]->IsVisualTreeVisibilityChanged()) + { + HandleVisualVisibility( screenNumber ); + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(EFalse); + } + + if (!iActivated) + { + iBridgerClient.Connect(); + iActivated = ETrue; + } + } + } + +// --------------------------------------------------------------------------- +// Check if there is effect and it's not fade effect. +// --------------------------------------------------------------------------- +// +static TBool IsNonFadeEffect(CHuiFxEffect* aEffect) + { + return aEffect && !(aEffect->EffectFlags() & KHuiFadeEffectFlag); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +TBool CAlfBridge::IsVisualOpaque(CHuiVisual& aVisual) + { + TBool transparent = EFalse; + + // TODO: We should check transformation too and perhaps parent transformations as well ? + //transparent |= aVisual.IsTransformed(); + + // if the control has an attached effect which is transformed, it must be considered transparent + // as it may not cover the full screen + if ( IsNonFadeEffect( aVisual.Effect() ) ) + { + return EFalse; + } + if ( aVisual.Layout() && IsNonFadeEffect( aVisual.Layout()->Effect() ) ) + { + return EFalse; + } + + if (aVisual.Flags() & EHuiVisualFlagDrawOnlyAsExternalContent) + { + return EFalse; // not transparent + } + + transparent |= (!((aVisual.Flags() & EHuiVisualFlagOpaqueHint) == EHuiVisualFlagOpaqueHint)); + transparent |= (aVisual.iOpacity.Now() < KAlfVisualDefaultOpacity); + transparent |= (aVisual.iOpacity.Target() < KAlfVisualDefaultOpacity); + + return !transparent; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::ClipVisualRect(TRect& aRect, const TRect& aClippingRect) + { + if (aRect.Intersects(aClippingRect)) + { + // Clip to visible area, there are windows larger than screen for some reason. + aRect.Intersection(aClippingRect); + } + else + { + // no intersection with the clipping rect -> outside of the screen -> not visible + aRect = TRect(0,0,0,0); + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +TBool CAlfBridge::IsRectCoveredByRegion(TRect aRect, TRegion& aCoveringRegion) + { + TBool isCovered = EFalse; + + // Zero sized rects are considered as covered (although it is a bit philosphical question) + if (aRect.Size() == TSize(0,0)) + { + isCovered = ETrue; + } + + // First check if it is covered by one of the rects in the covering region... + if (!isCovered) + { + TPoint topLeft = aRect.iTl; + TPoint bottomRight = aRect.iBr; + bottomRight.iX--; + bottomRight.iY--; + + for (TInt i=0; i < aCoveringRegion.Count(); i++) + { + if (aCoveringRegion[i].Contains(topLeft) && + aCoveringRegion[i].Contains(bottomRight)) + { + isCovered = ETrue; + } + } + } + + // ...it may still cover it with a combination of several rects + if (!isCovered) + { + iTempVisualRegion.Clear(); + iTempIntersectingRegion.Clear(); + + iTempVisualRegion.AddRect(aRect); + + iTempIntersectingRegion.Intersection(aCoveringRegion, iTempVisualRegion); + iTempIntersectingRegion.Tidy(); + + if (iTempIntersectingRegion.Count() == 1) + { + if (iTempIntersectingRegion[0] == aRect) + { + isCovered = ETrue; + } + } + } + + return isCovered; + } + + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleVisualVisibility( TInt aScreenNumber ) + { + if (!iAlfScreens.Count()) + return; + + iTempRegion.Clear(); + + CAlfScreen* screen = iAlfScreens[aScreenNumber]; + TRect fullscreen = TRect(TPoint(0,0), screen->Size()); + TBool fadeEffectInScreen = EFalse; + + + // Prepare SW render target (if needed) + if (iSwRenderingEnabled) + { + TBool modified = PrepareSwRenderingTarget( screen ); + + if ( modified ) + { + // To avoid debug panic, we need to reset foreground bitmap. + TRAP_IGNORE( screen->iDisplay->SetForegroundBitmapL( + screen->iSwRenderingTarget ) ); + } + } + + TBool fullscreenCovered = EFalse; + //iActiveVisualCount = 0; + iBgSurfaceFound = EFalse; + //iPaintedArea = 0; + // skip the topmost (effect) layer, start from floating sprite group + for (TInt j=screen->iDisplay->Roster().Count() - 2; j>=0; j--) + { +#ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + TInt activevisualcount = 0; + TInt passivevisualcount = 0; +#endif + + CHuiControlGroup& controlgroup = iAlfScreens[aScreenNumber]->iDisplay->Roster().ControlGroup(j); + CHuiControl& control = controlgroup.Control(0); + CHuiCanvasVisual* layout = (CHuiCanvasVisual*)&control.Visual(0); +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( layout->Tracking() ) + { + RDebug::Print(_L("CAlfBridge::HandleVisualVisibility: tracked visual 0x%x"), canvasVisual); + } +#endif + + // Dont mess with alf control group visuals, alf session handling does it for us + // just add the rect to covered region because alf draws solid background. + if (control.Role() == EAlfSessionContainer) + { + iTempRegion.AddRect(fullscreen); + iTempRegion.Tidy(); + continue; + } + + // For optimization reasons, check if all visuals below in Z-order are covered + if (!fullscreenCovered) + { + fullscreenCovered = IsRectCoveredByRegion(fullscreen, iTempRegion); +#ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + if (fullscreenCovered) + __ALFLOGSTRING("Full screen covered!"); +#endif + } + + if (!fullscreenCovered) + { + fullscreenCovered = screen->iDisplay->Roster().IsVisibleContentFrozen(); +#ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + if (fullscreenCovered) + __ALFLOGSTRING("Full screen covered because of frozen roster content"); +#endif + } + + TBool subTreeCovered = EFalse; + TBool hasActiveVisualsInVisualTree = HandleLayoutVisualVisibility( layout, controlgroup, control, fullscreenCovered, fullscreen, screen, subTreeCovered, IsVisualOpaque(*layout) ); + TBool hasFadeEffectsInVisualTree = (layout->CanvasFlags() & EHuiCanvasFlagExternalFadeExistsInsideVisualTree); + + // If we layout is active setup the fade effects. Also if it is inactive, but has been + // flagged as containing fade effect, then run the setup as well so that effects which + // are no more needed get removed. + if (hasActiveVisualsInVisualTree || (!hasActiveVisualsInVisualTree && hasFadeEffectsInVisualTree)) + { + fadeEffectInScreen = ETrue; + + // Prepare fade effects to whole visual tree below layout + PrepareFadeEffects( *layout ); + + // Load needed fade effects (or remove them) + TBool visualTreeHasFadeEffects = LoadFadeEffectsL( *layout ); + + // Set flag so that next time we can optimize + if (visualTreeHasFadeEffects) + { + layout->SetCanvasFlags(EHuiCanvasFlagExternalFadeExistsInsideVisualTree); + } + else + { + layout->ClearCanvasFlags(EHuiCanvasFlagExternalFadeExistsInsideVisualTree); + } + } + + if (!hasActiveVisualsInVisualTree) + { + // Setting also the root visual (layout) as inactive, if it had none + // active children. This is because otherwise the Inactive checks won't + // work correctly within RosterImpl ScanDirty & ClearChanged phases. + layout->SetFlag(EHuiVisualFlagInactive); + } + else + { + layout->ClearFlag(EHuiVisualFlagInactive); + } + +#ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + __ALFLOGSTRING1(">>>> HandleVisualVisibility: Control group index: %d", j ); + __ALFLOGSTRING1(">>>> HandleVisualVisibility: Active visuals : %d", activevisualcount ); + __ALFLOGSTRING1(">>>> HandleVisualVisibility: Passive visuals: %d", passivevisualcount ); +#endif + + } + if (iBgSurfaceFound) + { + if (!iInLowMemMode) + { + SetLowMemory(ETrue); + iBridgerClient.SendBlind(KAlfCompositionTargetHidden, TIpcArgs()); + iInLowMemMode = ETrue; + } + } + else if (iInLowMemMode) + { + SetLowMemory(EFalse); + iBridgerClient.SendBlind(KAlfCompositionTargetVisible, TIpcArgs()); + iInLowMemMode = EFalse; + } + + + // Finally, if there are fadeeffects applied to windowgroups, make sure first one does not + // blend itself, but other windowgroups do blend. Otherwise windowgrouops above others + // would clear the screen areas where they do not really draw. + if (fadeEffectInScreen) + { + TBool firstFadedWindowGroupFound = EFalse; + for (TInt j=0; jiDisplay->Roster().Count() - 2; j++) // skip the topmost (effect) layer + { + CHuiControlGroup& controlgroup = iAlfScreens[aScreenNumber]->iDisplay->Roster().ControlGroup(j); + CHuiControl& control = controlgroup.Control(0); + CHuiCanvasVisual* layout = (CHuiCanvasVisual*)&control.Visual(0); + if (layout->Effect() && (layout->Effect()->EffectFlags() & KHuiFadeEffectFlag)) + { + if (firstFadedWindowGroupFound) + { + TInt flags = layout->Effect()->EffectFlags(); + flags |= KHuiFxAlwaysBlend; + layout->Effect()->SetEffectFlags(flags); + } + firstFadedWindowGroupFound = ETrue; + } + } + } + } + +TBool CAlfBridge::HandleLayoutVisualVisibility( + CHuiLayout* aLayout, + CHuiControlGroup& aControlGroup, + CHuiControl& aControl, + TBool& aFullscreenCovered, + TRect& aFullscreen, + CAlfScreen* aScreen, + TBool& aSubtreeVisible, + TBool aChildCanBeOpaque ) + { + TBool visualTreeActive = EFalse; + TRect visualDisplayRect; + TBool visualRectIsCovered = EFalse; + TBool visualIsOpaque = EFalse; + TBool visualIsActive = EFalse; + CHuiCanvasVisual* canvasVisual = NULL; + + for (TInt i=aLayout->Count()-1; i >= 0; i--) + { + visualDisplayRect = TRect(0,0,0,0); + visualRectIsCovered = EFalse; + visualIsOpaque = EFalse; + visualIsActive = EFalse; + TBool visualSubtreeVisible = EFalse; + + // Check first if visual itself is hidden or does hide other visuals below + // in z-order. If it does not hide, then we do not add its displayrect to covering + // region. + canvasVisual = (CHuiCanvasVisual*)(&aLayout->Visual(i)); + + // Child can be considered to be opaque only if all parents are opaque and + // visual itself is opaque. + // For example, parent can have opacity < 1 and that affects children as well. + // As another example, parent can have scaling transformation. + visualIsOpaque = aChildCanBeOpaque && IsVisualOpaque(*canvasVisual); + if (canvasVisual->Count()) + { + visualTreeActive |= HandleLayoutVisualVisibility( canvasVisual, aControlGroup, aControl, aFullscreenCovered, aFullscreen, aScreen, visualSubtreeVisible, visualIsOpaque ); + } + #ifdef HUI_DEBUG_TRACK_DRAWING + if ( canvasVisual->Tracking() ) + { + RDebug::Print(_L("CAlfBridge::HandleVisualVisibility: tracked visual 0x%x"), canvasVisual); + } + #endif + + if (visualSubtreeVisible) + { + aSubtreeVisible = ETrue; + } + + // Optimization, it is faster to check fullscreen than read visuals displayrect + if (aFullscreenCovered) + { + visualRectIsCovered = ETrue; + } + else + { + // Check where visual is + visualDisplayRect = canvasVisual->DisplayRect(); + + // Make sure we clip visual rect to visible screen area + ClipVisualRect(visualDisplayRect, aFullscreen); + + // Check if this visual is covered by other opaque visuals which rects are in "covered" region + visualRectIsCovered = IsRectCoveredByRegion(visualDisplayRect, iTempRegion); + } + + /* if ( layout->Effect() || canvasVisual->Effect() ) + { + visualRectIsCovered = EFalse; + } + */ + TBool wasInactive = canvasVisual->Flags() & + ( EHuiVisualFlagInactive | EHuiVisualFlagUnderOpaqueHint ); + + if (visualRectIsCovered) + { + // We clear texture cache here to avoid running out of texture memory + if (!(canvasVisual->Flags() & EHuiVisualFlagAlwaysDraw)) // The window has been hidden. However it has exit effect and it must stay active until effect has stopped + { + if (visualSubtreeVisible) + { + canvasVisual->SetFlag(EHuiVisualFlagUnderOpaqueHint); + canvasVisual->ClearFlags(EHuiVisualFlagInactive); + } + else + { + canvasVisual->SetFlag(EHuiVisualFlagInactive); + canvasVisual->ClearFlags(EHuiVisualFlagUnderOpaqueHint); + } + + canvasVisual->ClearCache(); + // For SW rendering, disable capturing buffer + canvasVisual->SetCapturingBufferL(NULL); + } + else + { // this should be drawn, but inactivate when effect is done + canvasVisual->ClearFlags( + EHuiVisualFlagInactive | EHuiVisualFlagUnderOpaqueHint | + EHuiVisualFlagShouldBeInactive | EHuiVisualFlagShouldBeUnderOpaqueHint ); + if (visualSubtreeVisible) + { + canvasVisual->SetFlag(EHuiVisualFlagShouldBeUnderOpaqueHint); + } + else + { + canvasVisual->SetFlag(EHuiVisualFlagShouldBeInactive); + } + canvasVisual->PrepareCache(); + // For SW rendering, set capturing buffer if it exists) + canvasVisual->SetCapturingBufferL(aScreen->iSwRenderingTarget); + + if (wasInactive) + { + canvasVisual->SetChanged(); + } + } + + if (!wasInactive) + { + aScreen->iDisplay->SetDirty(); + } + + #ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + passivevisualcount++; + #endif + } + else + { + aSubtreeVisible = ETrue; + canvasVisual->ClearFlags( + EHuiVisualFlagInactive | EHuiVisualFlagShouldBeInactive | + EHuiVisualFlagUnderOpaqueHint | EHuiVisualFlagShouldBeUnderOpaqueHint ); + canvasVisual->PrepareCache(); + canvasVisual->SetCapturingBufferL(aScreen->iSwRenderingTarget); + + // we've found non-inactive window which has background surface + // attached.. + if (canvasVisual->IsBackgroundDrawingEnabled() && + canvasVisual->LayerExtent() != TRect() && + !canvasVisual->LayerUsesAlphaFlag() ) + { + // if paintedareacount is exactly one, it means that the window + // has background surface but no drawing commands + if (canvasVisual->PaintedAreaCount() == 1) + { + THuiCanvasPaintedArea pa = canvasVisual->PaintedArea(0); + TRect r = pa.iPaintedRect.Round(); + // if we found a fullscreen surface with no other drawing commands + // we can safely assume that it's about the only thing to be visible + // and we can release memory occupied by other parts of the system + // + // NOTE: this mechanism keeps the system in low mem state + // if the surface is visible, meaning that for example + // opening an options menu does not instantly trigger normal + // memory state. We want to do it like this as otherwise + // we would be triggering for example background animation + // on / off quite rapidly........ + if ( r == Display(0)->VisibleArea()) + { + // Final test. Surface must not be ALF surface, but some other surface. + CHuiControlGroup* alfControlGroup = FindControlGroupByAppId( iAlfSecureId ); + if (alfControlGroup != &aControlGroup) + { + iBgSurfaceFound = ETrue; + } + } + } + } + + if (wasInactive) + { + canvasVisual->SetChanged(); + } + #ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + activevisualcount++; + #endif + } + + // Finally check the area that this visual covers and add it to covered region + visualIsActive = !(canvasVisual->Flags() & EHuiVisualFlagInactive); + + // Sprites and effects as we consider them always as transparent and also + // if controlgroup is transformed somehow + + if (aControl.Role() == EAlfFullScreenEffectContainer + || aControl.Role() == EAlfWindowFloatingSpriteContainer || + aControlGroup.IsTransformed()) + { + visualIsOpaque = EFalse; + } + + if (visualIsActive && visualIsOpaque && !visualRectIsCovered) + { + #ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + if (canvasVisual->PaintedAreaCount()) + __ALFLOGSTRING2("Visual has painted areas: displayrect: iTl: %i, %i", visualDisplayRect.iTl.iX, visualDisplayRect.iTl.iY); + __ALFLOGSTRING2("Visual has painted areas: displayrect: iBr: %i, %i", visualDisplayRect.iBr.iX,visualDisplayRect.iBr.iY); + #endif + for (TInt k=0; k < canvasVisual->PaintedAreaCount(); k++) + { + THuiCanvasPaintedArea paintArea = canvasVisual->PaintedArea(k); + TRect coveredRect = paintArea.iPaintedRect; + + // Clip to visible area, there are windows larger than screen for some reason. + ClipVisualRect(coveredRect, aFullscreen); + + // Only add to covering region if the painted area is defined as opaque + if (paintArea.iPaintType == EHuiCanvasPaintTypeOpaque) + { + #ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + __ALFLOGSTRING2("Covered rect: iTl: %i, %i", coveredRect.iTl.iX, coveredRect.iTl.iY); + __ALFLOGSTRING2("Covered rect: iBr: %i, %i", coveredRect.iBr.iX,coveredRect.iBr.iY); + #endif + iTempRegion.AddRect(coveredRect); + iTempRegion.Tidy(); + } + } + } + } + + visualTreeActive |= visualIsActive; + return visualTreeActive; + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::ClearCanvasVisualCommandSets(TBool aInactiveOnly) + { + if (!iAlfScreens.Count()) + return; + + CAlfScreen* screen = iAlfScreens[0]; // TODO + for (TInt j=screen->iDisplay->Roster().Count() - 2; j>=0; j--) // skip the topmost (effect) layer + { + CHuiControlGroup& controlgroup = iAlfScreens[0]->iDisplay->Roster().ControlGroup(j); + CHuiControl& control = controlgroup.Control(0); + + if ( control.Role() == EAlfSessionContainer ) + { + continue; + } + + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + for (TInt i=layout->Count()-1; i >= 0; i--) + { + CHuiCanvasVisual* canvasVisual = (CHuiCanvasVisual*)(&layout->Visual(i)); + if (!aInactiveOnly) + { + canvasVisual->ClearCommandSet(); + } + else if (aInactiveOnly && (canvasVisual->Flags() & EHuiVisualFlagInactive)) + { + canvasVisual->ClearCommandSet(); + } + else + { + // dont clear + } + } + } + } + + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::EnableVisualDefaultTransformationsL(CHuiVisual& aVisual) + { + aVisual.EnableTransformationL(); + if (!aVisual.Transformation().Count()) + { + aVisual.Transformation().Rotate(0); + aVisual.Transformation().Scale(1,1); + aVisual.Transformation().Translate(0,0); + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleCallback(TInt aStatus) + { + TInt err = KErrNone; + if (aStatus >= 0) + { + TRAP(err, DoDispatchL(aStatus)) + } + + if (aStatus < 0 || err) + { + __ALFLOGSTRING2("CAlfBridge::HandleCallback status: %d error: %d",aStatus,err); + + CEikonEnv* eikenv = CEikonEnv::Static(); + if ( eikenv ) + { + eikenv->HandleError(err?err:aStatus); + } + } + } + + +// --------------------------------------------------------------------------- +// DoDispatchL +// --------------------------------------------------------------------------- +// +void CAlfBridge::DoDispatchL(TInt aStatus) + { + if (*iHost) + { + TAlfBridgerData data = (*iHost)->GetData(aStatus); + // dispatch + __ALFLOGSTRING1( "CAlfBridge::DoDispatchL: %d",data.iOp ); + + switch (data.iOp) + { + case EAlfDSCreateNewDisplay: + { + AddNewScreenL(NULL); + break; + } + case EAlfDSDestroyDisplay: + { + HandleDestroyDisplay( data.iInt1 ); + break; + } + case EAlfDSNewWindow: + { + HandleNewWindowL( data ); + break; + } + case EAlfDSDestroyWindow: + { + HandleDestroyWindowL( data ); + break; + } + case EAlfDSSetWindowPos: + { + HandleSetWindowPosL( data ); + break; + } + case EAlfDSSetWindowSize: + { + HandleSetWindowSizeL( data ); + break; + } + case EAlfDSSetWindowRotation: + { + HandleSetWindowRotationL( data ); + break; + } + case EAlfDSSetWindowOpacity: + { + HandleSetWindowOpacityL( data ); + break; + } + case EAlfDSRefreshCallback: + { + iHuiEnv->ContinueRefresh(); + break; + } + case EAlfDSReorder: + { + HandleReorderWindowL( data ); + break; + } + case EAlfDSPostCanvasBuffer: + { + HandlePostCanvasBufferL( data ); + break; + } + case EAlfDSSetWindowActive: + { + HandleSetWindowActiveL( data ); + break; + } + case EAlfDSSetWindowFlag: + case EAlfDSClearWindowFlag: + { + HandleSetWindowFlagL(data, data.iOp); + break; + } + case EAlfDSSetSurfaceExtent: + { + HandleSetSurfaceExtentL( data ); + break; + } + case EAlfDsLayerUsesAlphaFlagChanged: + { + HandleLayerUsesAlphaFlagChanged( data ); + break; + } + case EAlfDSGetAlfNativeWindowData: + { +// HandleGetNativeWindowDataL( data ); + break; + } + case EAlfDSGroupChained: + { + __ALFLOGSTRING("CAlfBridge::DoDispatchL, EAlfDSGroupChained"); + // TODO, link groups + break; + } + case EAlfDSGroupChainBroken: + { + __ALFLOGSTRING("CAlfBridge::DoDispatchL, EAlfDSGroupChainBroken"); + // TODO, break link + break; + } + case EAlfDSMoveWindowToNewGroup: + { + /* + RDebug::Print(_L("CAlfBridge::DoDispatchL, EAlfDSMoveWindowToNewGroup, THIS METHOD IS UNTESTED. EXPECT TROUBLE!")); + // TODO: TEST! + TInt windowGroupNodeId = data.iInt1; + TInt windowNodeId = data.iInt2; + TInt newGroupId = (TInt)data.iPtr; + CHuiLayout* layout = NULL; + CHuiCanvasVisual* viz = (CHuiCanvasVisual*)FindVisual(windowNodeId, windowGroupNodeId,screenNumber); + if (viz) + { + // #1 remove visual from old group + layout = viz->Layout(); + layout->Remove(viz); + viz->Owner().Remove(viz); + // #2 insert visual to the beginning of the new group + CHuiControlGroup* controlGroup = FindControlGroup(newGroupId,screenNumber); + if (controlGroup) + { + CHuiControl& control = controlGroup->Control(0); + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + layout->AppendL( viz ); + } + }*/ + break; + } + case EAlfEffectFx: + { + HandleGfxEffectsL( data ); + break; + } + case EAlfStopEffectFx: + { + HandleGfxStopEffectsL( data ); + break; + } + case EAlfControlEffectFx: + { + HandleGfxControlEffectsL( data ); + break; + } + // TODO: implement these + case EAlfRegisterEffectFx: + { + HandleRegisterEffectL( data ); + break; + } + case EAlfUnregisterEffectFx: + { + for (TInt i = 0; i < iAlfRegisteredEffects.Count(); i++) + { + if (iAlfRegisteredEffects[i].iAction == data.iInt1) + { + TRegisteredEffectsStruct removed = + iAlfRegisteredEffects[i]; + iAlfRegisteredEffects.Remove(i); + CHuiFxEngine* engine = NULL; + engine = iHuiEnv->EffectsEngine(); + if (engine) + { + engine->UnRegisterEffectL(*removed.iEffectFile); + } + delete removed.iEffectFile; + // if this happened to be the fade effect, the cached fade effect filename should + // be cleared + if ( data.iInt1 == KFadeAction) + { + RegisterFadeEffectL(); + } + break; + } + } + break; + } + case EAlfUnregisterAllFx: + { + while (iAlfRegisteredEffects.Count()) + { + TRegisteredEffectsStruct removed = + iAlfRegisteredEffects[0]; + iAlfRegisteredEffects.Remove(0); + CHuiFxEngine* engine = NULL; + engine = iHuiEnv->EffectsEngine(); + if (engine) + { + engine->UnRegisterEffectL(*removed.iEffectFile); + } + + delete removed.iEffectFile; + } + // fade file might have changed. This will be resolved when next fade effect request arrives. + RegisterFadeEffectL(); + break; + } + case EAlfDSSetCursorData: + { + HandleSetCursorDataL( data ); + break; + } + case EAlfDSSetFadeEffect: + { + HandleSetFadeEffectL( data ); + break; + } + case EAlfDSSetNodeTracking: + { + HandleSetNodeTracking( data ); + break; + } + case EAlfBridgeSetScreenRotation: + { + //short cut.. + __ALFLOGSTRING1("CAlfBridge::DoDispatchL: EAlfBridgeSetScreenRotation: %d",data.iInt1); + CHuiGc::TOrientation huiOrientation(CHuiGc::EOrientationNormal); + switch(data.iInt1) + { + case 1: // 90 + huiOrientation = CHuiGc::EOrientationCCW90; + break; + case 2: // 180 + huiOrientation = CHuiGc::EOrientation180; + break; + case 3: // 270 + huiOrientation = CHuiGc::EOrientationCW90; + break; + default: + break; + } + if (iAlfScreens[0]->iDisplay->Orientation() != huiOrientation) + { + HandleSetLayoutSwitchEffectL(); + iAlfScreens[0]->iDisplay->SetOrientation(huiOrientation); + if (iAppUi) + { + iAppUi->AdjustWindowGroupPositionL(0,CAlfAppServer::EAlfWindowSize); // hackish, but one way to enforce alf window resizing + } + __ALFLOGSTRING1("AlfScreens[0]->iDisplay->SetOrientation: %d",huiOrientation); + } + + break; + } + case EAlfEffectFxBeginSyncronizedGroup: + { + CHuiFxEngine* engine = iHuiEnv->EffectsEngine(); + if (engine) + { + engine->BeginGroupEffect(data.iInt1); + } + break; + } + case EAlfEffectFxEndSyncronizedGroup: + { + TInt groupId = data.iInt1; + //TBool forced = data.iInt2; + __ALFLOGSTRING1("CAlfBridge::DoDispatchL - Ending for group %d requested.", + groupId ); + CHuiFxEngine* engine = iHuiEnv->EffectsEngine(); + if (engine) + { + engine->StartGroupEffect(groupId); + } + iHuiEnv->ContinueRefresh(); + break; + } + case KUnInitialized: + { + __ALFLOGSTRING1("CAlfBridge::DoDispatchL: Received KUnInitialized: %d - CRITICAL ERROR!",data.iOp); + USER_INVARIANT(); + } + default: + { + // Should not happen + __ALFLOGSTRING1("CAlfBridge::DoDispatchL: Received Unknown op: %d",data.iOp); + } + } + } + } + +// --------------------------------------------------------------------------- +// HandleDestroyDisplay +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleDestroyDisplay( TInt aScreenNumber ) + { + iAlfScreens[aScreenNumber]->iDisplay->iRefreshObservers.Remove( *this ); + // TODO: Following delete iAlfScreens[aScreenNumber] crashes when display is trying to delete roster. + // RosterEntry is trying to refer to display, which is appareantly alrady destroyed. The roster should have no iRootVisual when display is removed. + + iAlfScreens[aScreenNumber]->iDisplay->Roster().Hide(*(iAlfScreens[aScreenNumber]->iFloatingSpriteControlGroup)); + iAlfScreens[aScreenNumber]->iDisplay->Roster().Hide(*(iAlfScreens[aScreenNumber]->iFullscreenEffectControlGroup)); + delete iAlfScreens[aScreenNumber]; + iAlfScreens.Remove( aScreenNumber ); + } + +// --------------------------------------------------------------------------- +// HandleNewWindowL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleNewWindowL( TAlfBridgerData& aData ) + { + TInt windowGroupNodeId = aData.iInt1; + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*) (*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + __ALFLOGSTRING1("CAlfBridge::HandleNewWindowL: new window %d!",windowNodeId); + + switch (windowAttributes->iWindowNodeType) + { + case EAlfWinTreeNodeGroup: + { + CHuiControlGroup& controlGroup = CreateControlGroupL( + windowGroupNodeId, + windowAttributes->iClientHandle, + windowAttributes->iSecureId, + screenNumber); + + // We just received notification for our own window group creation, store its node id for doing + // faster lookups later... + if (windowAttributes->iClientHandle == iAlfWindowGroupId) + { + iAlfWindowGroupNodeId = windowGroupNodeId; + } + break; + } + case EAlfWinTreeNodeClient: + case EAlfWinTreeNodeRoot: // TODO: Root window receives drawing commands too + case EAlfWinTreeNodeAnim: + case EAlfWinTreeNodeSprite: + case EAlfWinTreeNodeTextCursor: + { + CHuiControlGroup* controlGroup = FindControlGroup(windowGroupNodeId,screenNumber); + // Floating sprites only require own group. Normal sprites should behave as normal visuals. + if (!controlGroup && windowAttributes->iWindowNodeType == EAlfWinTreeNodeSprite ) + { + controlGroup = iAlfScreens[screenNumber]->iFloatingSpriteControlGroup; + } + + if (controlGroup) + { + CHuiControl& control = controlGroup->Control(0); + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + CHuiCanvasVisual* viz = NULL; + CHuiCanvasVisual* parentViz = NULL; + parentViz = (CHuiCanvasVisual*)FindVisual(windowAttributes->iParentNodeId); + if (parentViz) + { + viz = CHuiCanvasVisual::AddNewL(control, parentViz); + } + else + { + viz = CHuiCanvasVisual::AddNewL(control, layout); + } + __ALFFXLOGSTRING2("CAlfBridge::HandleNewWindowL visual: 0x%x, id 0x%x", viz, windowNodeId); + AddVisual( + windowNodeId, + windowAttributes->iClientHandle, + windowAttributes->iClientGroupHandle, + viz ); + + // check , if a window is having already defined effect. + if (iControlEffectData + && iControlEffectData->iClientHandle == windowAttributes->iClientHandle + && iControlEffectData->iClientGroupHandle == windowAttributes->iClientGroupHandle) + { + HandleGfxControlEventL(*iControlEffectData, viz); + delete iControlEffectData; + iControlEffectData = NULL; + } + viz->SetCommandType( CHuiCanvasVisual::ECommandBufferSgc ); + viz->SetFlags(EHuiVisualFlagManualLayout | EHuiVisualFlagInactive); +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( windowAttributes->iTrackWindow ) + { + viz->SetTracking( windowAttributes->iTrackWindow ); + } +#endif + // draw sprites and anims the last inside their windowgroup + /*if (windowAttributes->iWindowNodeType == EAlfWinTreeNodeSprite || windowAttributes->iWindowNodeType == EAlfWinTreeNodeAnim ) + { + viz->SetFlag(EHuiVisualFlagDrawAfterOthers); + } +*/ + // Store identifier / tag to get handle of this visual later + TBuf8<16> buf; + buf.AppendNum(windowNodeId); + viz->SetTagL(buf); + viz->SetPos(windowAttributes->iPosition, windowAttributes->iTransitionTime); + viz->SetSize(windowAttributes->iSize, windowAttributes->iTransitionTime); + + // Keep window invisible until activated, for now we use opacity for that. + viz->iOpacity.Set(0, 0); + + // Set up parent link for clipping calculations + if (parentViz) + { + viz->SetCanvasFlags(EHuiCanvasFlagEnableCanvasClipping); + viz->SetParentCanvas(parentViz); + } + else + { + __ALFLOGSTRING1("CAlfBridge::HandleNewWindowL: Parent not found for visual %d!",windowNodeId); + } + } + else + { + __ALFLOGSTRING1("CAlfBridge::HandleNewWindowL: Control group not found for visual %d!",windowNodeId); + } + + break; + } + default: + { + __ALFLOGSTRING("CAlfBridge::HandleNewWindowL: Unknown window node type received !"); + } + } + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); + } + +// --------------------------------------------------------------------------- +// HandleDestroyWindow +// --------------------------------------------------------------------------- +// +void CAlfBridge::DestroyWindow(CHuiVisual* aVisual, TBool aUseForce) + { + if ( !aUseForce && HasActiveEffect(aVisual) ) + { + // this visual will be destroyed on the effect call back. + __ALFFXLOGSTRING1("CAlfBridge::DestroyWindow - not destroying 0x%x", aVisual); + aVisual->SetFlag(EHuiVisualFlagShouldDestroy); + // TODO: Revise + // move to effect controlgroup + //CHuiControl& effectControlGroup = iAlfScreens[0]->iFullscreenEffectControlGroup->Control(0); + //CHuiLayout* effectControlGroupLayout = (CHuiLayout*) &effectControlGroup.Visual(0); + // Transfers ownership of visuals. + //effectControlGroup.AppendL(aVisual, effectControlGroupLayout); // this will remove it from the previous layout + //aVisual->SetOwner(effectControlGroup); + return; + } + __ALFFXLOGSTRING1("CAlfBridge::DestroyWindow 0x%x", aVisual); + RemoveImageBrushL(*aVisual); + CHuiLayout* layout = aVisual->Layout(); + if (layout) + layout->Remove(aVisual); + aVisual->Owner().Remove(aVisual); + __ALFLOGSTRING1("CAlfBridge::HandleDestroyWindow - destroying visual 0x%x", aVisual); + // check if visual is having an effect at the moment. This could occur, if options menu is exited (with effect) and then + // application is exited. EHuiVisualFlagDrawOnlyAsExternalContent is indication that + // there might be effect on this visual. It is not guaranteen. + + delete aVisual; + } +// --------------------------------------------------------------------------- +// HandleDestroyWindowL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleDestroyWindowL( TAlfBridgerData& aData ) + { + TInt windowGroupNodeId = aData.iInt1; + TInt windowNodeId = aData.iInt2; + + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*) (*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + + switch (windowAttributes->iWindowNodeType) + { + case EAlfWinTreeNodeGroup: + { + DeleteControlGroupL(windowGroupNodeId, screenNumber); + break; + } + case EAlfWinTreeNodeClient: + case EAlfWinTreeNodeRoot: + case EAlfWinTreeNodeAnim: + case EAlfWinTreeNodeSprite: + case EAlfWinTreeNodeFloatingSprite: + case EAlfWinTreeNodeTextCursor: + { + // close cursor timer + if (windowAttributes->iWindowNodeType == EAlfWinTreeNodeTextCursor) + { + iCursorTimer->Cancel(); + } + + //just remove the visual + CHuiCanvasVisual* viz; + + viz = (CHuiCanvasVisual*)FindVisual(windowNodeId); + CHuiControlGroup* controlGroup = FindControlGroup( windowGroupNodeId, screenNumber ); + // Sprite is in its own group, and can be deleted normally. + if ( !controlGroup && windowAttributes->iWindowNodeType != EAlfWinTreeNodeSprite ) + { + __ALFLOGSTRING("CAlfBridge::HandleDestroyWindowL: group containing this visual has been destroyed.!"); + // the group containing this visual has been destroyed. Thus the visual itself has been destroyed by + // the group. Ignore this. + } + else + { + // = (CHuiCanvasVisual*)de(windowNodeId, windowGroupNodeId,screenNumber); + if (viz) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( viz->Tracking() ) + { + RDebug::Print(_L("CAlfBridge::HandleDestroyWindowL - Tracked visual")); + } +#endif + DestroyWindow(viz); + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleDestroyWindowL: visual not found!"); + } + } + RemoveVisual( windowNodeId ); + break; + } + default: + { + __ALFLOGSTRING("CAlfBridge::HandleDestroyWindowL: Unknown window node type received !"); + break; + } + } + // TODO: Toolkit does not support recycling (of visuals), + // this is not in line with Nokia environmental policy... + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); + } + +// --------------------------------------------------------------------------- +// HandleSetWindowPosL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetWindowPosL( TAlfBridgerData& aData ) + { + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*) (*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + // fetch visual + CHuiVisual* viz = FindVisual(windowNodeId); + if (viz) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( viz->Tracking() ) + { + RDebug::Print(_L("CAlfBridge::HandleSetWindowPosL - Tracked visual")); + } +#endif + + viz->SetPos(windowAttributes->iPosition, windowAttributes->iTransitionTime); + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); // TODO: Check if really changed + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowPosL, EAlfDSSetWindowPos: Visual not found!"); + } + } + +// --------------------------------------------------------------------------- +// HandleSetWindowSizeL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetWindowSizeL( TAlfBridgerData& aData ) + { + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*) (*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + // fetch visual + CHuiVisual* viz = FindVisual(windowNodeId); + if (viz) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( viz->Tracking() ) + { + RDebug::Print(_L("CAlfBridge::HandleSetWindowSizeL - Tracked visual")); + } +#endif + viz->SetSize(windowAttributes->iSize, windowAttributes->iTransitionTime); + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowSizeL, EAlfDSSetWindowSize: Visual not found!"); + } + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); + } + +// --------------------------------------------------------------------------- +// HandleSetWindowRotationL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetWindowRotationL( TAlfBridgerData& aData ) + { + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*) (*iHost)->GetVarDataL( (TInt)aData.iPtr ); + // fetch visual + CHuiVisual* viz = FindVisual(windowNodeId); + if (viz) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( viz->Tracking() ) + { + RDebug::Print(_L("CAlfBridge::HandleSetWindowRotationL - Tracked visual")); + } +#endif + EnableVisualDefaultTransformationsL(*viz); + viz->Transformation()[KVisualTransformationStepRotate].iParams[0].Set(windowAttributes->iRotation, + windowAttributes->iTransitionTime); + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowRotationL, EAlfDSSetWindowRotation: Visual not found!"); + } + } + +// --------------------------------------------------------------------------- +// HandleSetWindowOpacityL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetWindowOpacityL( TAlfBridgerData& aData ) + { + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*) (*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + // fetch visual + CHuiVisual* viz = FindVisual(windowNodeId); + if (viz) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( viz->Tracking() ) + { + RDebug::Print(_L("CAlfBridge::HandleSetWindowOpacityL - Tracked visual")); + } +#endif + viz->iOpacity.Set(windowAttributes->iOpacity, windowAttributes->iTransitionTime); + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); // TODO: Check if really changed + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowOpacityL, EAlfDSSetWindowOpacity: Visual not found!"); + } + } + +// --------------------------------------------------------------------------- +// HandleReorderWindowL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleReorderWindowL( TAlfBridgerData& aData ) + { + TInt windowGroupNodeId = aData.iInt1; + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*) (*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + TInt ordinalPosition = windowAttributes->iOrdinalPosition; + + switch (windowAttributes->iWindowNodeType) + { + case EAlfWinTreeNodeGroup: + { + + // HACK !!!! + #ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + if (windowGroupNodeId == iAlfWindowGroupNodeId) + { + __ALFLOGSTRING1("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: Alf window group going to: %d ",windowAttributes->iOrdinalPosition); + } + else + { + __ALFLOGSTRING1("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: WS window group going to: %d ",windowAttributes->iOrdinalPosition); + } + #endif + + CHuiControlGroup* controlGroup = FindControlGroup(windowGroupNodeId,screenNumber); + + if (!controlGroup) + { + User::Leave(KErrNotFound); + } + + // Window server nodes are in inverted Z-order, we switch it here. + iAlfScreens[screenNumber]->iDisplay->Roster().Hide(*controlGroup); + TInt wsWindowGroupCount = 0; + for (TInt i=0; iiDisplay->Roster().Count();i++) + { + if (iAlfScreens[screenNumber]->iDisplay->Roster().ControlGroup(i).Control(0).Role()==EAlfWindowGroupContainer) + { + wsWindowGroupCount++; + } + } + ordinalPosition = wsWindowGroupCount - windowAttributes->iOrdinalPosition; + + #ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER + __ALFLOGSTRING1("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: wsWindowGroupCount: %d ", wsWindowGroupCount); + __ALFLOGSTRING1("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: Wimpautettu: %d ", ordinalPosition); + //RDebug::Print(_L("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: Last total pos: %d "), iDisplay->Roster().Count() - 1); + #endif + + if (ordinalPosition < -1) + { + ordinalPosition = -1; // show at top ? + } + + if (iAlfScreens[screenNumber]->iDisplay && controlGroup) + { + ShowControlGroupL(iAlfScreens[screenNumber]->iDisplay->Roster(), *controlGroup, ordinalPosition, screenNumber); + } + else + { + __ALFLOGSTRING2("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: Control group not found! Screen: %d, Id: %d ", screenNumber, windowNodeId ); + } + + ReorderAlfControlGroupsL(screenNumber); + break; + } + case EAlfWinTreeNodeClient: + case EAlfWinTreeNodeRoot: + case EAlfWinTreeNodeAnim: + case EAlfWinTreeNodeSprite: + case EAlfWinTreeNodeFloatingSprite: + case EAlfWinTreeNodeTextCursor: + { + + // fetch visual + CHuiLayout* layout = NULL; + CHuiVisual* viz = FindVisual(windowNodeId); + if (viz) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( viz->Tracking() ) + { + __ALFLOGSTRING("CAlfBridge::HandleReorderWindowL - Tracked visual"); + } +#endif + layout = viz->Layout(); + __ALFLOGSTRING3("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: Id: %d, position %d, layout count %d", windowNodeId, windowAttributes->iOrdinalPosition, layout->Count() ); + TInt pos = windowAttributes->iOrdinalPosition; + TInt layoutCount = layout->Count(); + + if (windowAttributes->iOrdinalPosition > layoutCount - 1 ) + { + __ALFLOGSTRING("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: Illegal visual index !"); + pos = layoutCount - 1; // FixMe !!! + } + + pos = layoutCount - pos - 1; + layout->Reorder(*viz, pos); + } + else + { + __ALFLOGSTRING2("CAlfBridge::HandleReorderWindowL, EAlfDSReorder: Visual not found! Screen: %d, Id: %d ", screenNumber, windowNodeId ); + } + break; + } + default: + { + __ALFLOGSTRING("CAlfBridge::HandleReorderWindowL: Unknown window node type received !"); + break; + } + } + + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); // TODO: Check if really changed + } + +// --------------------------------------------------------------------------- +// HandlePostCanvasBufferL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandlePostCanvasBufferL( TAlfBridgerData& aData ) + { + TInt windowGroupNodeId = aData.iInt1; + TInt windowNodeId = aData.iInt2; + TAlfWindowCommandBufferAttributes* bufferAttributes = (TAlfWindowCommandBufferAttributes*)(*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = bufferAttributes->iScreenNumber; + + CHuiCanvasVisual* viz = (CHuiCanvasVisual*)FindVisual(windowNodeId); + + // For now we omit drawing commands to ALF window group because in some configurations it causes issues + // TODO: Possible viz->Flags() & EHuiVisualFlagDrawAf.. is not needed anymore. To be checked. Currently this enables floating sprites on the "root visual" + if (viz && iAlfWindowGroupNodeId != windowGroupNodeId + || ( viz && viz->Flags() & EHuiVisualFlagDrawAfterOthers )/* THIS LINE IS HACK FOR DRAWING FLOATING SPRITES */ ) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + TBool tracking( EFalse ); + CHuiControlGroup* controlGroup = FindControlGroup( windowGroupNodeId, screenNumber ); + CAlfScreen* screen = iAlfScreens[screenNumber]; + + //TInt clientWindowGroupId = FindClientWindowGroupId( screenNumber, *controlGroup ); + // NOTE, THE FOLLOWING WServClientFileName MAY CAUSE DEADLOCK. + // THIS DOES NOT HAPPEN IF HUI_DEBUG_TRACK_DRAWING IS NOT ENABLED (DEFAULT) + TFileName processName;/* = iCommandDebug->WServClientFileName( clientWindowGroupId, CHuiStatic::WsSession() ); + + if ( viz->Tracking() || + ( processName.Length() > 0 && iCommandDebug->TrackProcess( (HBufC16*)processName.Ptr() ) ) ) + { + tracking = ETrue; + }*/ +#endif + // Now when we receive actual drawing commands, we can set the window as opaque (unless the flags say it isn't opaque). + if (bufferAttributes->iWindowNodeFlags & EAlfWinNodeFlagOpaque) + { + viz->SetFlag(EHuiVisualFlagOpaqueHint); + } + + if (!viz->HasCommandBuffers(EFalse)) + { + // For performance resons, only set visual tree changed if this + // was the first buffer for the window. + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); + } + + TPtrC8 commands((TUint8*)bufferAttributes->iBuffer, bufferAttributes->iBufferLength); + if ( bufferAttributes->iEmptyThisBuffer ) + { + viz->ClearCommandSet(); + } + // If tracking has been enabled for this CHuiCanvasVisual object, the buffers will be marked for tracking aswell in CHuiCanvasVisual + switch( bufferAttributes->iPartStatus ) + { + case TAlfWindowCommandBufferAttributes::EPartComplete: + { + viz->AddCommandSetL( commands ); +#ifdef HUI_DEBUG_TRACK_DRAWING + viz->SetTrackCommandSet( processName, tracking ); +#endif + break; + } + case TAlfWindowCommandBufferAttributes::ENotComplete: // ENotComplete part should be eventually followed by ELastPart + { + viz->AddPartialCommandSetL( commands, EFalse ); + break; + } + case TAlfWindowCommandBufferAttributes::ELastPart: + { + viz->AddPartialCommandSetL( commands, ETrue ); +#ifdef HUI_DEBUG_TRACK_DRAWING + viz->SetTrackCommandSet( processName, tracking ); +#endif + break; + } + default: + __ALFLOGSTRING("CAlfBridge::HandlePostCanvasBufferL, EAlfDSPostCanvasBuffer: Unknown iPartStatus !!!!"); + USER_INVARIANT(); + break; + } + } + else + { + __ALFLOGSTRING3("CAlfBridge::HandlePostCanvasBufferL, EAlfDSPostCanvasBuffer: Visual not found! Screen: %d, Id: %d, GroupId: %d ", screenNumber, windowNodeId, windowGroupNodeId ); + } + } + +// --------------------------------------------------------------------------- +// SetWindowActiveL +// --------------------------------------------------------------------------- +// +void CAlfBridge::SetWindowActiveL(CHuiVisual* aVisual, TBool aActive) + { + if (!HasActiveEffect(aVisual)) + { + // Does not have effect + if (aActive) + { + aVisual->ClearFlags(EHuiVisualFlagShouldBeHidden | EHuiVisualFlagShouldBeShown); + aVisual->iOpacity.Set(KAlfVisualDefaultOpacity); + } + else + { + aVisual->ClearFlags(EHuiVisualFlagShouldBeShown | EHuiVisualFlagShouldBeHidden); + aVisual->iOpacity.Set(0.0f); + } + } + else + { + // Has effect + // these flags are put to action in RemoveTemporaryPresenterItem + if (aActive) + { + // this prevents windows appearing before their "effected" time + aVisual->SetFlag(EHuiVisualFlagShouldBeShown); + aVisual->ClearFlag(EHuiVisualFlagShouldBeHidden); + } + else + { + // this prevents windows disappearing before their effect has finished + aVisual->SetFlag(EHuiVisualFlagShouldBeHidden); + aVisual->ClearFlag(EHuiVisualFlagShouldBeShown); + } + } + } + +// --------------------------------------------------------------------------- +// HandleSetWindowActiveL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetWindowActiveL( TAlfBridgerData& aData ) + { + TInt windowGroupNodeId = aData.iInt1; + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*)(*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + + if (windowAttributes->iWindowNodeType == EAlfWinTreeNodeTextCursor && iCursorTimer) + { + if (!windowAttributes->iActive) + { + iCursorTimer->Cancel(); + } + else + { + SetCursorTimerL(); // continue with set interwal + } + } + + + switch (windowAttributes->iWindowNodeType) + { + case EAlfWinTreeNodeGroup: + { + CHuiControlGroup* controlGroup = FindControlGroup(windowGroupNodeId,screenNumber); + if (controlGroup) + { + CHuiControl& control = controlGroup->Control(0); + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + // Uses opacity for now + SetWindowActiveL(layout, windowAttributes->iActive); + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowActiveL, EAlfDSSetWindowActive: EAlfWinTreeNodeGroup not found!"); + } + break; + } + case EAlfWinTreeNodeClient: + case EAlfWinTreeNodeRoot: + case EAlfWinTreeNodeAnim: + case EAlfWinTreeNodeSprite: + case EAlfWinTreeNodeFloatingSprite: + case EAlfWinTreeNodeTextCursor: + { + CHuiVisual* viz = FindVisual(windowNodeId); + if (viz) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + if ( viz->Tracking() ) + { + RDebug::Print(_L("CAlfBridge::HandleSetWindowActiveL - Tracked visual")); + } +#endif + // Uses opacity for now + SetWindowActiveL(viz, windowAttributes->iActive); + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowActiveL, EAlfDSSetWindowActive: Visual not found!"); + } + break; + } + default: + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowActiveL, EAlfDSSetWindowActive: Unknown iWindowNodeType!"); + USER_INVARIANT(); + break; + } + } + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); // TODO: Check if really changed + } + + +// --------------------------------------------------------------------------- +// HandleSetWindowFlagL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetWindowFlagL( TAlfBridgerData& aData, TInt aOp ) + { + TInt windowGroupNodeId = aData.iInt1; + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*)(*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + TInt windowFlag = windowAttributes->iActive; + THuiVisualFlags visualFlag = (THuiVisualFlags)0; + switch(windowFlag) + { + case TAlfWindowData::EShouldInactivate: + { + visualFlag = EHuiVisualFlagShouldBeHidden; + break; + } + case TAlfWindowData::EShouldDestroy: + { + visualFlag = EHuiVisualFlagShouldDestroy; + break; + } + default:; + } + + switch (windowAttributes->iWindowNodeType) + { + case EAlfWinTreeNodeGroup: + { + CHuiControlGroup* controlGroup = FindControlGroup(windowGroupNodeId,screenNumber); + if (controlGroup) + { + CHuiControl& control = controlGroup->Control(0); + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + // Uses opacity for now + if (aOp == EAlfDSSetWindowFlag) + { + layout->SetFlag(visualFlag); + } + else + { + layout->ClearFlag(visualFlag); + } + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowActiveL, EAlfDSSetWindowActive: EAlfWinTreeNodeGroup not found!"); + } + break; + } + case EAlfWinTreeNodeClient: + case EAlfWinTreeNodeRoot: + case EAlfWinTreeNodeAnim: + case EAlfWinTreeNodeSprite: + case EAlfWinTreeNodeFloatingSprite: + case EAlfWinTreeNodeTextCursor: + { + CHuiVisual* viz = FindVisual(windowNodeId); + if (viz) + { + if (aOp == EAlfDSSetWindowFlag) + { + viz->SetFlag(visualFlag); + if (visualFlag == EHuiVisualFlagShouldDestroy ) + { + if (windowAttributes->iWindowNodeType == EAlfWinTreeNodeTextCursor && iCursorTimer) + { + iCursorTimer->Cancel(); + } + RemoveVisual(windowNodeId); // Only the effect will have pointer to this visual from here on + } + } + else + { + viz->ClearFlag(visualFlag); + } + } + else + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowFlagL, HandleSetWindowFlagL: Visual not found!"); + } + break; + } + default: + { + __ALFLOGSTRING("CAlfBridge::HandleSetWindowFlagL, HandleSetWindowFlagL: Unknown iWindowNodeType!"); + USER_INVARIANT(); + break; + } + } + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); // TODO: Check if really changed + } + +// --------------------------------------------------------------------------- +// InsertImageBrushL +// --------------------------------------------------------------------------- +// +void CAlfBridge::InsertImageBrushL(CHuiVisual& aVisual, TInt aBitmapHandle) + { + // NOTE: We wssume that image brush is always the only brush + CHuiTexture* texture = CHuiTexture::NewL(); + CleanupStack::PushL(texture); + THuiImage image(*texture); + CHuiImageBrush* imageBrush = CHuiImageBrush::NewL(image); + imageBrush->SetLayer(EHuiBrushLayerForeground); + CleanupStack::Pop(texture); + + aVisual.EnableBrushesL(ETrue); + aVisual.Brushes()->InsertL(0, imageBrush, EHuiHasOwnership); + + UpdateImageBrushL(aVisual, aBitmapHandle); + } + +// --------------------------------------------------------------------------- +// UpdateImageBrushL +// --------------------------------------------------------------------------- +// +void CAlfBridge::UpdateImageBrushL(CHuiVisual& aVisual, TInt aBitmapHandle) + { + // NOTE: We wssume that image brush is always the only brush with EImageBrush type + const TInt KAlfCanvasVisualImageBrushIndex = 0; + + if (aVisual.Brushes() && aVisual.Brushes()->BrushWithTypeCount(CHuiBrush::EImageBrush)) + { + CFbsBitmap* bitmap = new (ELeave) CFbsBitmap; + CleanupStack::PushL(bitmap); + bitmap->Duplicate(aBitmapHandle); + + CHuiImageBrush* imageBrush = (CHuiImageBrush*) aVisual.Brushes()->BrushWithTypeAt(CHuiBrush::EImageBrush, KAlfCanvasVisualImageBrushIndex); + CHuiTexture* texture = (CHuiTexture*) &imageBrush->Image().Texture(); + + // Use of direct upload here would give much better performance, but is + // it too risky ? + texture->UploadL(*bitmap, NULL); + imageBrush->SetChanged(); + + CleanupStack::PopAndDestroy(bitmap); + } + } + +// --------------------------------------------------------------------------- +// RemoveImageBrushL +// --------------------------------------------------------------------------- +// +void CAlfBridge::RemoveImageBrushL(CHuiVisual& aVisual) + { + // NOTE: We wssume that image brush is always the only brush with EImageBrush type + const TInt KAlfCanvasVisualImageBrushIndex = 0; + + if (aVisual.Brushes() && aVisual.Brushes()->BrushWithTypeCount(CHuiBrush::EImageBrush)) + { + CHuiImageBrush* imageBrush = (CHuiImageBrush*) aVisual.Brushes()->BrushWithTypeAt(CHuiBrush::EImageBrush, KAlfCanvasVisualImageBrushIndex); + CHuiTexture* texture = (CHuiTexture*) &imageBrush->Image().Texture(); + THuiImage image; + imageBrush->SetImage(image); + delete texture; + } + + if (aVisual.Brushes()) + { + aVisual.EnableBrushesL(EFalse); + } + } + + +// --------------------------------------------------------------------------- +// HandleSetSurfaceExtentL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetSurfaceExtentL( TAlfBridgerData& aData ) + { + TInt windowGroupNodeId = aData.iInt1; + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*)(*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + // fetch visual + CHuiCanvasVisual* viz = FindVisual(windowNodeId); + + // We should not do this for alf window, but renderstage does not know if it is + // handling alf window or other window, so we ignore the request here if needed. + // TODO: When alf apps work in multiple display, check here for every displays alf groups... + if (viz && iAlfWindowGroupNodeId != windowGroupNodeId) + { + viz->SetLayerExtent(windowAttributes->iSurfaceExtent); + // Set surface extend area to be cleared with fully transparent color + // Note: does not support extend that is bigger that the visual + // if surface extent is (0,0,0,0) then the background item array is reseted + // and surface extent will not be cleared. + if (windowAttributes->iSurfaceExtent != TRect()) + { + // Set surface extend area to be cleared with fully transparent color + // Note: does not support extend that is bigger that the visual + TRgb fullyTransparentColor(255,0,0,0); // Red but fully transparent. Red color component has been set only for debug purposes, it is not visible. + viz->SetClearBackground(CHuiDisplay::EClearWithColor); + viz->SetBackgroundColor(fullyTransparentColor); + } + else + { + viz->SetClearBackground(CHuiDisplay::EClearNone); + } + } + else + { + if (iAlfWindowGroupNodeId != windowGroupNodeId) + __ALFLOGSTRING("CAlfBridge::HandleSetSurfaceExtentL, EAlfDSSetSurfaceExtent: Visual not found!"); + } + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); // TODO: Check if really changed + } + +// --------------------------------------------------------------------------- +// HandleLayerUsesAlphaFlagChanged +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleLayerUsesAlphaFlagChanged( TAlfBridgerData& aData ) + { + TInt windowGroupNodeId = aData.iInt1; + TInt windowNodeId = aData.iInt2; + TAlfWindowAttributes* windowAttributes = (TAlfWindowAttributes*)(*iHost)->GetVarDataL( (TInt)aData.iPtr ); + TInt screenNumber = windowAttributes->iScreenNumber; + + // fetch visual + CHuiCanvasVisual* viz = (CHuiCanvasVisual*)FindVisual(windowNodeId); + + // We should not do this for alf window, but renderstage does not know if it is + // handling alf window or other window, so we ignore the request here if needed. + // TODO: When alf apps work in multiple display, check here for every displays alf groups... + if (viz && iAlfWindowGroupNodeId != windowGroupNodeId) + { + viz->SetLayerUsesAlphaFlag(windowAttributes->iLayerUsesAlphaFlagEnabled); + } + else + { + if (iAlfWindowGroupNodeId != windowGroupNodeId) + __ALFLOGSTRING("CAlfBridge::HandleLayerUsesAlphaFlagChanged: Visual not found!"); + } + iAlfScreens[screenNumber]->SetVisualTreeVisibilityChanged(ETrue); // TODO: Check if really changed + } + + +// --------------------------------------------------------------------------- +// HandleGetNativeWindowDataL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleGetNativeWindowDataL( TAlfBridgerData& aData ) + { + // Get the data from original Render Stage message + RMessage2* rsMessage = (RMessage2*)aData.iInt1; + TAlfNativeWindowData winData; + TPckg winDataPckg(winData); + rsMessage->Read(0, winDataPckg); + + if(winData.iScreenNumber == 0) + { + // primary screen + CHuiDisplay& disp = iHuiEnv->PrimaryDisplay(); + if (disp.NativeWindow()) + { + winData.iAlfWindowHandle = disp.NativeWindow()->ClientHandle(); + winData.iAlfWindowGrpId = disp.NativeWindow()->WindowGroupId(); + } + } + else + { + // other than primary screen + for (TInt i = 1; i < iAlfScreens.Count(); i++) + { + if (iAlfScreens[i]->iScreenNum == winData.iScreenNumber) + { + RDrawableWindow* win = iAlfScreens[i]->iCoeControl->DrawableWindow(); + winData.iAlfWindowHandle = win->ClientHandle(); + winData.iAlfWindowGrpId = win->WindowGroupId(); + } + } + } + + // write result + rsMessage->Write(0, winDataPckg); + + if (winData.iAlfWindowHandle == 0) + { + __ALFLOGSTRING("CAlfBridge::HandleGetNativeWindowDataL, EAlfDSGetAlfNativeWindowData. Error: window data not found!"); + } + } + + +void CAlfBridge::PrepareFadeEffects( CHuiCanvasVisual& aVisual ) + { + TBool faded = aVisual.CanvasFlags() & EHuiCanvasFlagExternalFade; + if (faded) + { + if (IsFadedByParent( aVisual )) + { + // Faded by parent + aVisual.SetCanvasFlags(EHuiCanvasFlagExternalFadeByParent); + + // Faded by parent, include to parent effect + aVisual.ClearCanvasFlags(EHuiCanvasFlagExcludeFromParentEffect); + + // Does not fade own children because parent already does that. + aVisual.ClearCanvasFlags(EHuiCanvasFlagExternalFadeToChildren); + } + else + { + // Not faded by parent + aVisual.ClearCanvasFlags(EHuiCanvasFlagExternalFadeByParent); + + // Not faded by parent, exclude from parent effect + aVisual.SetCanvasFlags(EHuiCanvasFlagExcludeFromParentEffect); + + // Does (or does not) fade own children if it can. + if (CanFadeChildren(aVisual)) + { + aVisual.SetCanvasFlags(EHuiCanvasFlagExternalFadeToChildren); + } + else + { + aVisual.ClearCanvasFlags(EHuiCanvasFlagExternalFadeToChildren); + } + } + } + else + { + // Not faded + aVisual.ClearCanvasFlags(EHuiCanvasFlagExternalFadeByParent); + + if (IsNearestParentEffectFade( aVisual )) + { + // Exclude from parent effect to avoid getting faded by parent. + aVisual.SetCanvasFlags(EHuiCanvasFlagExcludeFromParentEffect); + } + else + { + // By default included into parent effects. + aVisual.ClearCanvasFlags(EHuiCanvasFlagExcludeFromParentEffect); + } + + // Does not fade own children because it is not faded itself. + aVisual.ClearCanvasFlags(EHuiCanvasFlagExternalFadeToChildren); + } + + // Handle children + TInt count = aVisual.Count(); + for (TInt i=0; i NO) + // + // V4(f) V3(f) + // \ / + // \ / + // V5(f) V2 + // \ / + // \ / + // V1(f) + // + // Scenario 5) CanFadeChildren(V1) (NO) (Can't fade because non-faded child is drawn first) + // CanFadeChildren(V2) (NO) (Can't fade children because it does not have children) + // CanFadeChildren(V3) (YES) (All children are faded) + // + // V4(f) V4(f) + // \ / + // \ / + // V3(f) V2 + // \ / + // \ / + // V1(f) + // + // + // TODO: Real implementation for algorithm which takes into account the order of non-fading and + // fading children. Current implentation has side-effect where drawing order of non-fading + // children may get altered. But on the other hand without visual treefader (i.e each visual + // faded with separate effects) there still exists a potential problem with faded transparent + // windows above faded windows (double fade)! + // + + // For now this function just checks if there are children to be faded... + return HasActiveFadedChildren( aParent ); + } + + +TInt CAlfBridge::RecursiveChildCount( CHuiCanvasVisual& aParent, TInt aCanvasFlags ) + { + TInt childCount = 0; + TInt count = aParent.Count(); + for (TInt i=0; iCanvasFlags() & aCanvasFlags) + { + childCount++; + } + } + else + { + childCount++; + } + childCount += RecursiveChildCount( *child, aCanvasFlags ); + } + return childCount; + } + +TBool CAlfBridge::IsNearestParentEffectFade( CHuiCanvasVisual& aVisual ) + { + TBool nearestParentEffectFade = EFalse; + CHuiCanvasVisual* parent = (CHuiCanvasVisual*) (aVisual.Layout()); + while (parent) + { + if (parent->Effect()) + { + nearestParentEffectFade |= (parent->Effect() && (parent->Effect()->EffectFlags() & KHuiFadeEffectFlag)); + return nearestParentEffectFade; + } + parent = (CHuiCanvasVisual*) (parent->Layout()); + } + return EFalse; + } + + +TBool CAlfBridge::IsFadedByParent( CHuiCanvasVisual& aVisual ) + { + CHuiCanvasVisual* parent = (CHuiCanvasVisual*) (aVisual.Layout()); + while (parent) + { + TInt flags = parent->CanvasFlags(); + if ((flags & EHuiCanvasFlagExternalFade) && (flags & EHuiCanvasFlagExternalFadeToChildren)) + { + return ETrue; + } + parent = (CHuiCanvasVisual*) (parent->Layout()); + } + return EFalse; + } + +TBool CAlfBridge::HasActivePaintedAreas( CHuiCanvasVisual& aVisual, TBool aIncludeChildren ) + { + TBool visualHasPaintedAreas = aVisual.PaintedAreaCount() > 0; + if (!visualHasPaintedAreas && aIncludeChildren) + { + TInt count = aVisual.Count(); + for (TInt i=0; iFlags() & EHuiVisualFlagInactive); + if (childIsActive && child->PaintedAreaCount()) + { + visualHasPaintedAreas = ETrue; + break; + } + } + } + return visualHasPaintedAreas; + } + +TBool CAlfBridge::HasActiveFadedChildren( CHuiCanvasVisual& aVisual ) + { + TBool has = EFalse; + TInt count = aVisual.Count(); + for (TInt i=0; iFlags() & EHuiVisualFlagInactive); + TBool faded = child->CanvasFlags() & EHuiCanvasFlagExternalFade; + + if (active && faded && child->PaintedAreaCount()) + { + has = ETrue; + break; + } + } + return has; + } + + +// --------------------------------------------------------------------------- +// SetupFadeEffectL +// +// NOTE: This method gets called very often, so we should not do anything time +// consuming here (unless we really need to). +// +// --------------------------------------------------------------------------- +// +TBool CAlfBridge::SetupFadeEffectL( CHuiCanvasVisual& aVisual ) + { + TBool didFadeEffectLoad = EFalse; + + TBool faded = (aVisual.CanvasFlags() & EHuiCanvasFlagExternalFade); + + // Just in case, check if we are alrady faded to avoid unnecassary effect loadings. + TBool alreadyFaded = aVisual.Effect() && (aVisual.Effect()->EffectFlags() & KHuiFadeEffectFlag); + + TBool fadesChildren = EFalse; + + if (faded) + { + fadesChildren = (aVisual.CanvasFlags() & EHuiCanvasFlagExternalFadeToChildren); + + // Inactive visuals are not faded. + TBool visualIsActive = !(aVisual.Flags() & EHuiVisualFlagInactive); + + // Avoid interrupting other effects. + TBool otherEffectActive = aVisual.Effect() && !(aVisual.Effect()->EffectFlags() & KHuiFadeEffectFlag); + + // Check if we really need to fade. Note the order of if-conditions, fastest checks first to optimize performance. + if (visualIsActive && !alreadyFaded && !otherEffectActive && !IsFadedByParent(aVisual) && HasActivePaintedAreas(aVisual, fadesChildren)) + { + CHuiFxEffect* effect = NULL; + CHuiFxEngine* engine = iHuiEnv->EffectsEngine(); + + if (engine && iFadeEffectFile ) + { + __ALFLOGSTRING1( ">> Using cached fade effect file name: %S", iFadeEffectFile ); + TInt err = 0; + // CHuiFxParser sets the effect to visual if loading succeeds. + TInt effectFlags = 0; + effectFlags |= KHuiFadeEffectFlag; + effectFlags |= KHuiFxEffectDisableMarginsFlag; // Margins cannot safely be used in fade usecase, artefacts may appear depending on window location in window tree + + // For top level canvas visuals (window group visuals) disable background for + // performance reasons (in case canvas visual is not opaque). + if (!aVisual.Layout()) + { + effectFlags |= KHuiFxDisableBackground; + } + + if (fadesChildren) + { + /* + TInt children = RecursiveChildCount( aVisual, 0 ); + TInt faded = RecursiveChildCount( aVisual, EHuiCanvasFlagExternalFade ); + TInt fadedbyparent = RecursiveChildCount( aVisual, EHuiCanvasFlagExternalFadeByParent ); + TInt excludedfromparenteffect = RecursiveChildCount( aVisual, EHuiCanvasFlagExcludeFromParentEffect ); + RDebug::Print(_L("CAlfBridge::SetupFadeEffectL - faded parent has %i children"), children); + RDebug::Print(_L("CAlfBridge::SetupFadeEffectL - faded parent has %i faded children"), faded); + RDebug::Print(_L("CAlfBridge::SetupFadeEffectL - faded parent fades %i children"), fadedbyparent); + RDebug::Print(_L("CAlfBridge::SetupFadeEffectL - faded parent has %i children which are excluded from parent fx"), excludedfromparenteffect); + */ + } + else + { + // All children in the tree are not faded, do not apply effect on children. + effectFlags |= KHuiFxEffectExcludeChildrenFlag; + //RDebug::Print(_L("CAlfBridge::SetupFadeEffectL - no children faded by parent")); + } + TRAP( err, engine->LoadEffectL(*iFadeEffectFile, effect, aVisual.Effectable(), NULL, NULL, 0, effectFlags ) ); + didFadeEffectLoad = ETrue; + } + } + } + else + { + // remove only an old fade effect, leave any others intact + if (alreadyFaded) + { + aVisual.SetEffect( NULL ); + alreadyFaded = EFalse; + } + } + + // If we did load and fade children we must re-prepare the flags again + // Maybe there is more elegant way to avoid this. + if (didFadeEffectLoad && fadesChildren) + { + PrepareFadeEffects( aVisual ); + } + + return (didFadeEffectLoad || alreadyFaded); + } + + +// --------------------------------------------------------------------------- +// HandleSetFadeEffect +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetFadeEffectL( TAlfBridgerData& aData ) + { + TInt windowNodeId = aData.iInt1; + TBool faded = aData.iInt2; + + CHuiVisual* viz = (CHuiVisual*)FindVisual(windowNodeId); + if (!viz) + { + // Visual not found, it could be window group. It must be searched with other method. + CHuiControlGroup* cg = FindControlGroup(windowNodeId, 0); // TODO: Screen + if (cg) + { + CHuiControl& control = cg->Control(0); + viz = &control.Visual(0); + } + } + + if ( viz ) + { + CHuiCanvasVisual* canvasviz = (CHuiCanvasVisual*)viz; + if (faded) + { + canvasviz->SetCanvasFlags(EHuiCanvasFlagExternalFade); + } + else + { + canvasviz->ClearCanvasFlags(EHuiCanvasFlagExternalFade); + } + iAlfScreens[0]->SetVisualTreeVisibilityChanged(ETrue); // TODO: Screen + } + } + +void CAlfBridge::HandleSetLayoutSwitchEffectL() + { + ClearCanvasVisualCommandSets(EFalse); + iLayoutSwitchEffectCoordinator->BeginLayoutSwitch(); + } + +TInt Blink(TAny* aVisual) + { + CHuiVisual* visual = (CHuiVisual*)aVisual; + if (visual->iOpacity.Now() > 0.01 ) // kind of an epsilon + { + visual->iOpacity.Set(0); + } + else + { + visual->iOpacity.Set(1); + } + + return ETrue; // call me again + } + +void CAlfBridge::SetCursorTimerL(TUint aTime, CHuiVisual* aCursor) + { + if (aTime) + { + iCursorInterval = aTime; + } + + if (aCursor) + { + iCursorVisual = aCursor; + } + + if (iCursorInterval && iCursorVisual) + { + if (iCursorTimer) + { + iCursorTimer->Cancel(); + } + + if (!iCursorTimer) + { + iCursorTimer = CPeriodic::NewL(CActive::EPriorityHigh); + } + + iCursorTimer->Start(iCursorInterval, iCursorInterval, TCallBack(Blink, aCursor)); + } + } + +// --------------------------------------------------------------------------- +// HandleSetCursorDataL +// --------------------------------------------------------------------------- +// +void CAlfBridge::HandleSetCursorDataL( TAlfBridgerData& aData ) + { + TInt windowNodeId = aData.iInt2; + + TAlfCursorDataBufferAttributes* windowAttributes = (TAlfCursorDataBufferAttributes*) (*iHost)->GetVarDataL( (TInt)aData.iPtr ); + CHuiVisual* viz = (CHuiVisual*)FindVisual(windowNodeId); + if (viz) + { + viz->SetFlags(windowAttributes->iFlags); + SetCursorTimerL(windowAttributes->iFlashInterval, viz); + } + else + { + __ALFLOGSTRING1("CAlfBridge::HandleSetCursorDataL - WARNING! Cursor node 0x%x not found!", windowNodeId); + } + } + +// --------------------------------------------------------------------------- +// HandleSetNodeTracking +// --------------------------------------------------------------------------- +// +#ifdef HUI_DEBUG_TRACK_DRAWING +void CAlfBridge::HandleSetNodeTracking( TAlfBridgerData& aData ) + { + TInt windowNodeId = aData.iInt1; + CHuiCanvasVisual* viz = (CHuiCanvasVisual*)FindVisual(windowNodeId); + if ( aData.iInt2 ) + { + viz->SetTracking( aData.iInt2 ); + } +#else +void CAlfBridge::HandleSetNodeTracking( TAlfBridgerData& ) + { +#endif + } + +void RecursiveStoreRenderBufferL(CHuiVisual *aVisual) + { + CHuiCanvasVisual *canvasvisual = dynamic_cast(aVisual); + if (canvasvisual && canvasvisual->Layout()) + { + canvasvisual->StoreRenderBufferL(); + } + + TInt c = aVisual->Count(); + for(int i=0;iVisual(i); + RecursiveStoreRenderBufferL(&vis); + } + } + +void StoreRenderBufferStartL(CHuiLayout *aLayout) + { + // assumes that the layout takes full screen area. + CHuiRenderPlugin& renderplugin = CHuiStatic::Renderer(); + CHuiCanvasGc *canvasGc = renderplugin.CreateCanvasGcL(); + CleanupStack::PushL(canvasGc); + + CHuiCanvasRenderBuffer *renderBuffer; + renderBuffer = canvasGc->CreateRenderBufferL(TSize(0,0)); + CleanupStack::PushL(renderBuffer); + renderBuffer->InitializeL(CHuiStatic::Env().Display(0).VisibleArea().Size()); + renderBuffer->Copy(TPoint(0,0)); + CleanupStack::Pop(renderBuffer); + aLayout->SetStoredRenderBuffer(renderBuffer); // moves ownership + + CleanupStack::PopAndDestroy(); + } +TBool NeedsStoredBuffers(CHuiFxEngine *aEngine, const TDesC &aFileName) + { + return aEngine->FxmlUsesInput1(aFileName); + } + +TBool CAlfBridge::HandleGfxEventL(CFullScreenEffectState& aEvent, CHuiLayout* aToLayout, CHuiLayout *aFromLayout) + { + TInt err = KErrNone; + TBool failed = EFalse; + + // Check if there is an effects engine in HuiEnv + CHuiFxEffect* effect = NULL; + // We need to pass the filenamerta from the transeffect plugin that handles the controls + // that define which effect is used for the selected skin or the selected application + // For full screen effects the skin should determine the effect, or there should be + // some default effects. + + CHuiFxEngine* engine = NULL; + // engine is not owned by us, it is a member of HuiEnv + engine = iHuiEnv->EffectsEngine(); + + if ( engine ) + { + switch(aEvent.iOperation) + { + case MAlfGfxEffectPlugin::EBeginFullscreen: + { + aToLayout->SetStoredRenderBufferModificationsEnabled(ETrue); + TBool needStoredBuffers = NeedsStoredBuffers(engine, *aEvent.iEffectName); + if (needStoredBuffers) + { + TRAP(err,StoreRenderBufferStartL(aToLayout)); + if (err == KErrNone) + { + aToLayout->SetFreezeState(ETrue); + } + else + { + return ETrue; // failed, effect will be canceled + } + } + + switch(aEvent.iAction) + { + case AknTransEffect::EApplicationStart: + case AknTransEffect::EApplicationStartRect: + { + aToLayout->iOpacity.Set(0.0f); // these are meant for applications that yet dont have anything to show + FreezeLayoutUntilEffectDestroyedL(aFromLayout, aEvent.iHandle); + break; + } + case AknTransEffect::EApplicationStartSwitch: + case AknTransEffect::EApplicationStartSwitchRect: + { + aToLayout->iOpacity.Set(0.0f); // this is meant for applications that are in the background. + FreezeLayoutUntilEffectDestroyedL(aFromLayout, aEvent.iHandle); + break; + } + + case AknTransEffect::EApplicationExit: + { + // The effect should start when the new view is ready, + // but we have no signal telling us that, so we just have to do our best + + // Effect end observer is given to engine in LoadEffectL + // It will be set to effect there and called when the effect ends or is deleted + + // The layout should be visible at this time. if not, then this is assumed + // as effect to an background application and ignored. + if (aToLayout->Effect()) + { + // effect on a layout must be an application start effect. + // External content visual is not used for that. + __ALFFXLOGSTRING2("CAlfBridge::HandleGfxEventL - Found effect on layout 0x%x. Removing effect 0x%x", aToLayout, aToLayout->Effect()); + aToLayout->SetEffect(NULL); + } + if (!(aToLayout->Flags() & EHuiVisualFlagInactive)) + { + // this will tag the visual, that they cannot be hidden by HandleVisualVisibility + // Initialize layout for the exit effect + iLayoutInitializedForExitEffect = SetupEffectLayoutContainerL(aEvent.iHandle, aToLayout, ETrue); + aEvent.iSetupDone = iLayoutInitializedForExitEffect; + } + else + { + iLayoutInitializedForExitEffect = EFalse; + } + return failed; + } + default: + break; + } + break; + } + case MAlfGfxEffectPlugin::EEndFullscreen: + { + TBool layoutEffectable(EFalse); + if (aEvent.iAction != 5000) + { + if ( aEvent.iAction != AknTransEffect::EApplicationExit && aToLayout->Flags() & EHuiVisualFlagInactive) + { + aToLayout->iOpacity.Set(1.0f); + failed = ETrue; + return failed; + } + + if (aToLayout) + { + aToLayout->iOpacity.Set(1.0f); + __ALFFXLOGSTRING1("HandleGfxEventL - loading effect, handle %d", aEvent.iHandle ); + if (aEvent.iAction == AknTransEffect::EApplicationExit) + { + // Exit effect was initialized earlier with EBeginFullscreen event + layoutEffectable = iLayoutInitializedForExitEffect; + } + else + { + // add visuals to visual cleanupstack + aToLayout->SetStoredRenderBufferModificationsEnabled(EFalse); + layoutEffectable = SetupEffectLayoutContainerL(aEvent.iHandle,aToLayout, EFalse); + aEvent.iSetupDone = layoutEffectable; + aToLayout->SetStoredRenderBufferModificationsEnabled(ETrue); + } + + if (layoutEffectable) + { + if (aEvent.iRect != TRect()) + { + TRAP( err, engine->LoadGroupEffectL( *aEvent.iEffectName, effect, aToLayout->Effectable(), engine->ActiveGroupEffect(), &aEvent.iRect, this, aEvent.iHandle ) ); + } + else + { + TRAP( err, engine->LoadGroupEffectL( *aEvent.iEffectName, effect, aToLayout->Effectable(), engine->ActiveGroupEffect(), NULL, this, aEvent.iHandle ) ); + } + effect = NULL; + // only use the effect if the effect file was correctly parsed + if (err != KErrNone) + { + // visuals added to "active effect visual" stack, but they wont be used, because effect loading has failed. cleanup. + RemoveTemporaryPresenterVisual(NULL, aEvent.iHandle); + aToLayout->SetEffect(NULL); + failed = ETrue; + } + } + else + { + failed = ETrue; + __ALFFXLOGSTRING2("CAlfBridge::HandleGfxEventL - Effect layout initialization failed. Skipping effect handle: %d, Visual: 0x%x", aEvent.iHandle, aToLayout); + } + } + } + break; + } + default: + { + // just in case... + break; + } + } + } + iLastAction = aEvent.iAction; // TODO: useless? + return failed; + } + +void CAlfBridge::FreezeLayoutUntilEffectDestroyedL(CHuiLayout* aLayout, TInt aHandle) + { + if (aLayout) + { + TRAPD(err, StoreRenderBufferStartL(aLayout)); + if (err == KErrNone) + { + // Freeze only, if buffer was reserved succesfully + aLayout->SetFreezeState(ETrue); + TBool itemsDestroyed; + AddEffectItemL(aHandle, aLayout, NULL, NULL, EFalse, itemsDestroyed, EFalse); + iFullScreenEffectData->iAppStartScreenshotItemHandle = aHandle; + } + } + } + +void CAlfBridge::HandleGfxStopEvent( TBool aClientRequest ) + { + __ALFFXLOGSTRING("CAlfBridge::HandleGfxStopEvent BEGIN"); + if (!iFullScreenEffectData) + { + __ALFFXLOGSTRING("CAlfBridge::HandleGfxStopEvent - END: none"); + return; + } + + CFullScreenEffectState* fxData = iFullScreenEffectData; + iFullScreenEffectData = NULL; + CleanupStack::PushL( fxData ); + + __ALFFXLOGSTRING2(" - handle: %d, toAppUid: 0x%x", fxData->iHandle, fxData->iToAppId); + + // clean effects with this handle + RemoveTemporaryPresenterVisual(NULL, fxData->iHandle); + // this was abort, so we might have received earlier event hiding this window. Here we'll bring it + // back + if (fxData->iToAppId && fxData->iToAppId != KErrNotFound) + { + RemoveEffectFromApp(fxData->iToAppId); + RemoveEffectFromApp(fxData->iFromAppId); + } + else + { + // abort ALL effects + RemoveAllTemporaryPresenterVisuals(); + } + + iHuiEnv->ContinueRefresh(); + + if ( !aClientRequest ) + { + // Aborted errornously, signal client side + RProperty::Set( KPSAlfDomain, KAlfTransitionStatus, fxData->iCompletionHandle ); + } + + CleanupStack::PopAndDestroy( fxData ); + __ALFFXLOGSTRING("CAlfBridge::HandleGfxStopEvent - END"); + } + +void CAlfBridge::RemoveEffectFromApp(TInt aAppUid) + { + if(aAppUid <= 0) + { + return; + } + CHuiControlGroup* group = FindControlGroupByAppId(aAppUid); + if (group) + { + CHuiControl& control = group->Control(0); + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + + TInt handle = FindEffectHandle(layout); + if (handle != KErrNotFound) + { + __ALFFXLOGSTRING2("CAlfBridge::HandleGfxStopEvent - layout visual: 0x%x ; handle: %d ", layout, handle); + RemoveTemporaryPresenterVisual(NULL, handle); + } + layout->iOpacity.Set(1.0f); + } + } + +CAlfBridge::CEffectState::CEffectState() + { + // CBase clears all variables + } + +CAlfBridge::CEffectState::~CEffectState() + { + delete iEffectName; + } + +void CAlfBridge::CEffectState::ResolveFileNameL(RMemReadStream& aStream) + { + HBufC* effectDirectory = HBufC::NewLC(aStream, 256); + HBufC* effectFile = HBufC::NewLC(aStream, 256); + + // Add one extra because we want to be able to append a number to the filename + HBufC* effectFullName = HBufC::NewL(effectDirectory->Des().Length() + + effectFile->Des().Length() + 1); + CleanupStack::PushL(effectFullName); + + effectFullName->Des().Copy(*(effectDirectory)); + effectFullName->Des().Append(*(effectFile)); + delete iEffectName; + iEffectName = effectFullName; // ownership transferred + CleanupStack::Pop(effectFullName); + CleanupStack::PopAndDestroy(2, effectDirectory); + } + +void CAlfBridge::CFullScreenEffectState::ConstructL( + TInt aAction, + RMemReadStream& aStream) + { + iAction = aAction; + + iHandle = aStream.ReadInt32L(); + + iType = aStream.ReadInt32L(); + iWg1 = aStream.ReadInt32L(); + iWg2 = aStream.ReadInt32L(); + iToAppId = aStream.ReadInt32L(); + iFromAppId = aStream.ReadInt32L(); + + if (iType == AknTransEffect::EParameterType) + { + /*screen1 =*/aStream.ReadInt32L(); + /*screen2 =*/aStream.ReadInt32L(); + } + /*TInt flags =*/ + aStream.ReadInt32L(); + iRect.iTl.iX = aStream.ReadInt32L(); + iRect.iTl.iY = aStream.ReadInt32L(); + iRect.iBr.iX = aStream.ReadInt32L(); + iRect.iBr.iY = aStream.ReadInt32L(); + + ResolveFileNameL(aStream); + + iCompletionHandle = iHandle; + } + +void CAlfBridge::CControlEffectState::ConstructL(TInt aAction, + RMemReadStream& aStream) + { + iAction = aAction; + TInt operation = aStream.ReadInt32L(); + iHandle = aStream.ReadInt32L(); + iClientHandle = aStream.ReadInt32L(); + iClientGroupHandle = aStream.ReadInt32L(); + TInt screenNumber = aStream.ReadInt32L(); // this has always value 0 + // Are Symbian full filename+directory combinations still max 256 characters long? + ResolveFileNameL(aStream); + } + +// --------------------------------------------------------------------------- +// HandleGfxEffectsL +// --------------------------------------------------------------------------- +// + +void CAlfBridge::HandleGfxEffectsL( TAlfBridgerData data ) + { + // This method is called when "Begin fullscreen" and "End fullscreen" are + // invoked. Data in "Begin fullscreen" is used, "End fullscreen" and + // "Abort fullscreen" (HandleStopGfxEffectsL) are just signals. + // As a general limitation, there can be exactly one fullscreen effect + // ongoing at once. + + TInt action = data.iInt1; + TInt length = data.iInt2; + __ALFFXLOGSTRING1("CAlfBridge::HandleGfxEffectsL - BEGIN (bridge data %d)", (TInt)data.iPtr); + void* bridgeBuffer = (void*) (*iHost)->GetEffectsDataL( (TInt)data.iPtr ); + RMemReadStream stream( bridgeBuffer, length ); + + // operation tells if this is begin full screen or end full screen + TInt operation = stream.ReadInt32L(); + + if ( operation == MAlfGfxEffectPlugin::EBeginFullscreen ) + { + if ( !iFullScreenEffectData || !iFullScreenEffectData->iSetupDone ) + { + // No fullsceen effect ongoing or fullscreen effect hasn't yet been set up, + // so we can initialize iFullScreenEffectData from stream. + + __ALFFXLOGSTRING("HandleGfxEffectsL - fresh start"); + + CFullScreenEffectState* fxData = new (ELeave) CFullScreenEffectState; + CleanupStack::PushL( fxData ); + fxData->ConstructL( action, stream ); + CleanupStack::Pop( fxData ); + + // the effect handle of freezed layout (iAppStartScreenshotItemHandle) must match the actual + // effect handle that is run. Only then frozen application can be freed at the end of the effect + if (iFullScreenEffectData) + { + for (TInt i = 0; i < iEffectCleanupStack.Count(); i++) + { + TEffectCleanupStruct& effectItem = iEffectCleanupStack[i]; + if (iFullScreenEffectData->iAppStartScreenshotItemHandle == effectItem.iHandle) + { + effectItem.iHandle = fxData->iHandle; + } + } + } + + if (iFullScreenEffectData && iFullScreenEffectData->iToAppId != fxData->iToAppId) + { + __ALFFXLOGSTRING("CAlfBridge::HandleGfxEffectsL - WARNING - Another fullscreen effect to different app. Deleting the previous ongoing effect"); + RemoveEffectFromApp(iFullScreenEffectData->iToAppId);// Fullscreen effect for another app has arrived, and the previous has not finished and abort effect was not called. + RemoveEffectFromApp(iFullScreenEffectData->iFromAppId); + // Fullscreen effect for another + } + + delete iFullScreenEffectData; + iFullScreenEffectData = fxData; + iFullScreenEffectData->iAppStartScreenshotItemHandle = fxData->iHandle; + + stream.Release(); + } + else + { + // Fullscreen effect is ongoing. We could either use new data + // and abort the ongoing effect, or just continue ongoing. + // For now, we continue ongoing. + + __ALFFXLOGSTRING("HandleGfxEffectsL - END: ongoing"); + + // Client expects completion to be signalled with this handle. + iFullScreenEffectData->iCompletionHandle = stream.ReadInt32L(); + + stream.Release(); + return ; + } + } + else // MAlfGfxEffectPlugin::EEndFullscreen + { + stream.Release(); + + // End fullscreen signal received. We proceed only if there is really + // effect ongoing and "end fullscreen" hasn't already been processed. + + if ( !iFullScreenEffectData || iFullScreenEffectData->iEndFullScreen ) + { + __ALFFXLOGSTRING("CAlfBridge::HandleGfxEffectsL - END: fx ready"); + return; + } + + __ALFFXLOGSTRING("HandleGfxEffectsL - process end"); + iFullScreenEffectData->iEndFullScreen = ETrue; + } + + CFullScreenEffectState* fxData = iFullScreenEffectData; + fxData->iOperation = operation; + fxData->iWaitingWindowGroup = EFalse; + + __ALFFXLOGSTRING3("Operation: %d, handle: %d, type: %d", operation, fxData->iHandle, fxData->iType); + __ALFFXLOGSTRING2("wg1: %d, wg2: %d", fxData->iWg1, fxData->iWg2); + + // find root nodes and attach effects to them + // First we need a windowgroup node id. So far we have a list of window ids + + // wg2 is the window group that is supposed to disappear from view + // when a new application starts. We don't have any use for it now... + + // This is the group that is disappearing + // Currently we don't add an effect to it. + + // TODO: when ids available from wserv... + // if ( appUid2 ) + //{ + // group2 = FindControlGrouAppUId( appUid2, screen2, &alfGroup ); + // } + //if ( toAppId2 ) + // { + // group2 = FindControlGroupByAppId(toAppId2); + // } + //if ( wg2 && wg2 != KErrNotFound ) + // { + // group2 = FindControlGroupByWindowGroupId( wg2, screen2 ); + // } + // if ( group2 ) + // { + // CHuiControl& control = group2->Control(0); + // layout2 = (CHuiLayout*)&control.Visual(0); + // } + + // This effect is triggered either by BeginFullScreen or by EndFullScreen + // depending on if we have an application that is already running or not + + // TAlfControlGroupEntry* alfGroup = NULL; + // TODO: + //wg1 = (*iHost)->FindWgForAppUid(TUid::Uid(toAppId1)); + //if (!wg1 && action != AknTransEffect::EApplicationExit ) + // { + // // window group is not available yet, but it will be created in short while. + // iEffectWaitingWindowgroup.Append(toAppId1); + // } + // TODO: when ids available from wserv... + // if ( appUid1 ) + //{ + // group1 = FindControlGrouAppUId( appUid1, screen1, &alfGroup ); + // } + + TBool failed = EFalse; + if (fxData->iToAppId && fxData->iToAppId != KErrNotFound) + { + CHuiControlGroup* toGroup = NULL; + CHuiLayout* toLayout = NULL; + toGroup = FindControlGroupByAppId(fxData->iToAppId); + + CHuiControlGroup* fromGroup = NULL; + CHuiLayout* fromLayout = NULL; + fromGroup = FindControlGroupByAppId(fxData->iFromAppId); + + if (!toGroup) // group has been destroyed and moved to effectControlGroup for waiting the application exit effect EndFullScreen trigger + { + toLayout = FindLayoutByEffectHandle(fxData->iHandle); + } + else + { + CHuiControl& control = toGroup->Control(0); + toLayout = (CHuiLayout*)&control.Visual(0); + } + if (fromGroup) + { + CHuiControl& control2 = fromGroup->Control(0); + fromLayout = (CHuiLayout*)&control2.Visual(0); + } + + if (toLayout) + { + failed = HandleGfxEventL(*fxData, toLayout, fromLayout); + } + else + { + __ALFFXLOGSTRING("HandleGfxEffectsL - waiting window group"); + fxData->iWaitingWindowGroup = ETrue; + } + } + + if ( failed ) + { + // Effect failed, reset state + HandleGfxStopEvent( EFalse ); // destroys iFullScreenEffectData + } + + for (TInt i = 0; i < iAlfScreens.Count(); i++) + { + iAlfScreens[i]->iDisplay->SetDirty(); + } + iAlfScreens[0]->iVisualTreeVisibilityChanged = ETrue; + iHuiEnv->ContinueRefresh(); + + __ALFFXLOGSTRING("CAlfBridge::HandleGfxEffectsL - END"); + } + +// TODO: add effect type to effect struct. remove all fullscreen effects. currently some might hang around +void CAlfBridge::HandleGfxStopEffectsL(TAlfBridgerData data) + { + // Fullscreen effect is aborted. Clear the state. + + //TInt action = data.iInt1; + TInt length = data.iInt2; + __ALFFXLOGSTRING1("CAlfBridge::HandleGfxStopEffectsL - Reading bridge data %d", (TInt)data.iPtr); + void* bridgeBuffer = (void*) (*iHost)->GetEffectsDataL( (TInt)data.iPtr ); + RMemReadStream stream( bridgeBuffer, length ); + + TInt operation = stream.ReadInt32L(); + TInt handle = stream.ReadInt32L(); + TInt type = stream.ReadInt32L(); + TInt wg1 = stream.ReadInt32L(); + TInt wg2 = stream.ReadInt32L(); + TInt toAppUi = stream.ReadInt32L(); + stream.Release(); + + // operation tells if this is abort full screen or something else + // When this function is used to abort control transitions, all data is 0s + if ( iFullScreenEffectData ) + { + __ALFFXLOGSTRING("CAlfBridge::HandleGfxStopEffectsL - kill fullscreen"); + HandleGfxStopEvent( ETrue ); + } + + if ( !toAppUi ) + { + __ALFFXLOGSTRING("CAlfBridge::HandleGfxStopEffectsL - kill all"); + RemoveAllTemporaryPresenterVisuals(); + iHuiEnv->ContinueRefresh(); + } + __ALFFXLOGSTRING("CAlfBridge::HandleGfxStopEffectsL - end"); + } + +void CAlfBridge::HandleRegisterEffectL( TAlfBridgerData data ) + { + TInt action = data.iInt1; + TInt length = data.iInt2; + + void* bridgeBuffer = (void*) (*iHost)->GetEffectsDataL( (TInt)data.iPtr ); + RMemReadStream stream( bridgeBuffer, length ); + + + HBufC* effectDirectory = HBufC::NewL( stream, 256 ); + CleanupStack::PushL( effectDirectory ); + HBufC* effectFile = HBufC::NewL( stream, 256 ); + CleanupStack::PushL( effectFile ); + HBufC* effectFullName = HBufC::NewL( effectDirectory->Des().Length() + effectFile->Des().Length() ); + CleanupStack::PushL( effectFullName ); + effectFullName->Des().Copy( *effectDirectory ); + effectFullName->Des().Append( *effectFile ); + + stream.Release(); + __ALFFXLOGSTRING2("CAlfBridge::HandleRegisterEffectL - dir: %S, file: %S", effectDirectory, effectFile); + DoRegisterEffectL(*effectFullName, action); + + if (action == KFadeAction) + { + DoSetCachedFadeEffectL(); + } + + CleanupStack::PopAndDestroy(effectFullName); + CleanupStack::PopAndDestroy(effectFile); + CleanupStack::PopAndDestroy(effectDirectory); + } + +void CAlfBridge::DoRegisterEffectL(const TDesC& aFilename, TInt aAction) + { + TRegisteredEffectsStruct newEntry; + newEntry.iAction = aAction; + newEntry.iEffectFile = HBufC::NewL(aFilename.Length()); + newEntry.iEffectFile->Des().Append(aFilename); + iAlfRegisteredEffects.AppendL(newEntry); + + CHuiFxEngine* engine = NULL; + engine = iHuiEnv->EffectsEngine(); + if (engine) + { + engine->RegisterEffectL(aFilename); + } + } + +CHuiCanvasVisual* CAlfBridge::AddEffectItemL( + TInt aEffectHandle, + CHuiVisual* aSourceVisual, + CHuiLayout* aTargetLayout, + CHuiControl* aEffectControl, + TBool aInsertTemporaryVisual, + TInt& aItemDestroyed, + TBool aIsExitEffect) + { + CHuiCanvasVisual* temporaryPresenterVisual = NULL; + TInt enableEffect = ETrue; + + aSourceVisual->ClearFlags(EHuiVisualFlagShouldBeInactive | EHuiVisualFlagShouldBeUnderOpaqueHint); + if (aIsExitEffect) + { + aSourceVisual->SetFlag(EHuiVisualFlagAlwaysDraw); // forces drawing during exit effect. handlevisualvisibility will set the EShouldbeInactive flag, if visual is determined inactive while this flag is set + } + + if (HasActiveEffect(aSourceVisual)) + { + // this visual is having effect and we are closing down the layout this visual inhabits. + // Propably this is the case, when application is closed while the options menu is + // still having effect animation. + + // removes the effect, and the visual (if EShouldDestroy flag enabled). Removes from effect + // cleanup stack iEffectCleanupStack + enableEffect = aSourceVisual->Flags() & EHuiVisualFlagShouldDestroy ? 0 : 1; + __ALFFXLOGSTRING2("CAlfBridge::SetupEffectLayoutContainerL - visual 0x%x is having effect. EShouldBeDestroyed flag state %d", &aSourceVisual, enableEffect ); + RemoveTemporaryPresenterVisual(aSourceVisual); + if (!enableEffect) + { + aItemDestroyed++; + } + } + if ( enableEffect ) + { + // RDebug::Print(_L("CAlfBridge::SetupEffectLayoutContainerL - binding visual 0x%x (source)--> 0x%x (presenter) layout 0x%x (presenter layout)"), &sourceVisual, temporaryPresenterVisual, temporaryPresenterLayout); + if (aInsertTemporaryVisual) + { + temporaryPresenterVisual = CHuiCanvasVisual::AddNewL(*aEffectControl, aTargetLayout); + + temporaryPresenterVisual->SetExternalContentL(aSourceVisual); + temporaryPresenterVisual->SetSize(THuiRealSize(640, 640)); + temporaryPresenterVisual->SetPos(aSourceVisual->Pos().Target()); + aSourceVisual->SetFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + temporaryPresenterVisual->SetChanged(); + TEffectCleanupStruct item = TEffectCleanupStruct( + aEffectHandle, + aSourceVisual, + temporaryPresenterVisual, + ETrue, + EFalse); + iEffectCleanupStack.AppendL(item); + } + else + { + // this will be a child of another visual, and draw by its parent external content visual + // aSourceVisual->SetFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + TEffectCleanupStruct item = TEffectCleanupStruct(aEffectHandle, + aSourceVisual, NULL, EFalse, + EFalse); + iEffectCleanupStack.AppendL(item); + } + } + return temporaryPresenterVisual; + } + +void CAlfBridge::AddToEffectLayoutContainerL( + TInt aEffectHandle, + CHuiLayout* aSourceLayout, + CHuiLayout* aTargetLayout, + CHuiControl* aEffectControl, + TInt& aItemsDestroyed, + TBool aAddLayout, + TBool aIsExitEffect) + { + __ALFFXLOGSTRING2("CAlfBridge::AddToEffectLayoutContainerL 0x%x is having %d children", aSourceLayout, aSourceLayout->Count()); + if (aAddLayout) + { + AddEffectItemL(aEffectHandle, aSourceLayout, aTargetLayout, aEffectControl, EFalse, aItemsDestroyed, aIsExitEffect); + } + + for (TInt i = 0; i < aSourceLayout->Count(); i++) + { + CHuiCanvasVisual& sourceVisual = static_cast (aSourceLayout->Visual(i)); + + if (sourceVisual.Count()) + { + CHuiLayout& layout = static_cast (aSourceLayout->Visual(i)); + AddToEffectLayoutContainerL(aEffectHandle, &layout, NULL, aEffectControl, aItemsDestroyed, EFalse,aIsExitEffect ); + } + AddEffectItemL(aEffectHandle, &sourceVisual, aTargetLayout, aEffectControl, EFalse, aItemsDestroyed, aIsExitEffect); + } + __ALFFXLOGSTRING2("CAlfBridge::AddToEffectLayoutContainerL 0x%x end of children", aSourceLayout, aSourceLayout->Count()); + } + +TBool CAlfBridge::SetupEffectLayoutContainerL(TInt aHandle,CHuiLayout* aSourceLayout, TBool aIsExitEffect) + { + if (aSourceLayout->Flags() & EHuiVisualFlagDrawOnlyAsExternalContent) + { + // the requested visual is already having an effect. + __ALFFXLOGSTRING("CAlfBridge::SetupEffectLayoutContainerL - WE ARE ALREADY HAVING EFFECT! WHAT TO DO??"); + // layout is having already effect. this is tricky. This might be place to panic. Resolve later. + } + // duplicate the layout to effect window group + CHuiControl& effectControlGroup = iAlfScreens[0]->iFullscreenEffectControlGroup->Control(0); + CHuiLayout& effectControlGroupLayout = (CHuiLayout&) effectControlGroup.Visual(0); + + // CHuiCanvasVisual* temporaryPresenterLayout = CHuiCanvasVisual::AddNewL( effectControlGroup, &effectControlGroupLayout); + // create presenter visual and set bindings + TInt itemsDestroyed(0); + AddToEffectLayoutContainerL(aHandle, aSourceLayout, NULL, &effectControlGroup, itemsDestroyed, EFalse, aIsExitEffect); + + if (aIsExitEffect) + { + CHuiCanvasVisual* temporaryPresenterVisual = AddEffectItemL(aHandle, aSourceLayout, &effectControlGroupLayout, &effectControlGroup, ETrue, itemsDestroyed, aIsExitEffect); + aSourceLayout->SetFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + __ALFFXLOGSTRING3("CAlfBridge::SetupEffectLayoutContainerL - adding handle: %d, 0x%x (source layout)-> 0x%x (presenter layout) to iEffectCleanupStack", aHandle, aSourceLayout, temporaryPresenterVisual); + } + else + { + AddEffectItemL(aHandle, aSourceLayout, NULL, &effectControlGroup, ETrue, itemsDestroyed, EFalse); + __ALFFXLOGSTRING2("CAlfBridge::SetupEffectLayoutContainerL - adding handle: %d, 0x%x (source layout), NO presenter layout) to iEffectCleanupStack", aHandle, aSourceLayout); + } + iAlfScreens[0]->iVisualTreeVisibilityChanged = ETrue; + iAlfScreens[0]->iDisplay->SetDirty(); + if (itemsDestroyed) + { + __ALFFXLOGSTRING3("CAlfBridge::SetupEffectLayoutContainerL - trying to put effect on destroyed visuals. Skipping effect visual: 0x%x, handle %d, %d items destroyed", aSourceLayout, aHandle, itemsDestroyed); + } + __ALFFXLOGSTRING("CAlfBridge::SetupEffectLayoutContainerL"); + return ETrue; // TBool(!itemsDestroyed); + } + +void CAlfBridge::SetupEffectContainerL(TInt aHandle, + CHuiCanvasVisual* aSourceVisual, TBool aIsExitEffect) + { + // if the original visual is having an effect, then remove it. + if (HasActiveEffect(aSourceVisual)) + { + RemoveTemporaryPresenterVisual(aSourceVisual); + } + + // Create new temporary presenter visual for the effect + CHuiControl& effectControlGroup = + iAlfScreens[0]->iFullscreenEffectControlGroup->Control(0); + CHuiLayout* layout = (CHuiLayout*) &effectControlGroup.Visual(0); + CHuiCanvasVisual* temporaryPresenterVisual = NULL; + temporaryPresenterVisual = CHuiCanvasVisual::AddNewL(effectControlGroup, layout); + // attach the source to the presenter visual + temporaryPresenterVisual->SetExternalContentL(aSourceVisual); + aSourceVisual->SetFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + temporaryPresenterVisual->ClearFlag(EHuiVisualFlagInactive); + aSourceVisual->SetChanged(); + // append to cleanup stack. this is cleaned in RemoveTemporaryVisuals after effect has finished + iEffectCleanupStack.AppendL(TEffectCleanupStruct(aHandle, aSourceVisual, temporaryPresenterVisual, EFalse /*iIsLayout*/, aIsExitEffect)); + __ALFFXLOGSTRING3("CAlfBridge::SetupEffectContainerL - adding handle: %d, 0x%x (source visual)-> 0x%x (presenter visual)", aHandle, aSourceVisual, temporaryPresenterVisual); + } + +void CAlfBridge::HandleGfxControlEffectsL( TAlfBridgerData data ) + { + TInt err = KErrNone; + TInt action = data.iInt1; + TInt length = data.iInt2; + __ALFFXLOGSTRING1("HandleGfxControlEffectsL - Reading bridge data %d", (TInt)data.iPtr); + void* bridgeBuffer = (void*) (*iHost)->GetEffectsDataL((TInt) data.iPtr); + RMemReadStream stream(bridgeBuffer, length); + if (iControlEffectData) + { + delete iControlEffectData; + iControlEffectData = NULL; + } + CControlEffectState* fxData = new (ELeave) CControlEffectState; + CleanupStack::PushL(fxData); + fxData->ConstructL(action, stream); + iControlEffectData = fxData; + CleanupStack::Pop(fxData); + + // We now have all the data sent to us. + stream.Release(); + + // We need to pass the filename from the transeffect plugin that handles the controls + // that define which effect is used for the selected skin or the selected application + // For full screen effects the skin should determine the effect, or there should be + // some default effects. + + CHuiCanvasVisual* visual = FindVisualByClientSideIds(fxData->iClientHandle, fxData->iClientGroupHandle); + + if (visual) + { + HandleGfxControlEventL(*iControlEffectData, visual); + } + else + { + __ALFFXLOGSTRING2("CAlfBridge::HandleGfxControlEffectsL - Control not found. iClientHandle 0x%x, iClientGroupHandle 0x%x", + iControlEffectData->iClientHandle, + iControlEffectData->iClientGroupHandle); + return; + } + iAlfScreens[0]->iDisplay->SetDirty(); + + iHuiEnv->ContinueRefresh(); + + if (visual && err != KErrNone) + { + // if the effect loading failed too soon, we must call our callback ourselves + // RDebug::Print(_L("HandleGfxControlEffectsL - effect not set - going directly to callback")); + AlfGfxEffectEndCallBack(fxData->iHandle); + } + + delete iControlEffectData; + iControlEffectData = NULL; + + __ALFFXLOGSTRING("HandleGfxControlEffectsL - end"); + } + +void CAlfBridge::HandleGfxControlEventL(CControlEffectState& aEvent, + CHuiCanvasVisual* aCanvasVisual) + { + TInt err = KErrNone; + // Check if there is an effects engine in HuiEnv + CHuiFxEffect* effect = NULL; + CHuiFxEngine* engine = NULL; + // engine is not owned by us, it is a member of HuiEnv + engine = iHuiEnv->EffectsEngine(); + if (NeedsStoredBuffers(engine, *aEvent.iEffectName)) + { + RecursiveStoreRenderBufferL(aCanvasVisual); + } + + if (engine) + { + // clear out old effect if this visual has one + __ALFFXLOGSTRING1("HandleGfxControlEffectsL - loading effect %S", &aEvent.iEffectName ); + __ALFFXLOGSTRING1("HandleGfxControlEffectsL - loading control effect, handle %d", aEvent.iHandle ); + if (HasActiveEffect(aCanvasVisual)) + { + __ALFFXLOGSTRING1("HandleGfxControlEffectsL - 0x%x has active effect. Requesting removal.", aCanvasVisual); + // another effect coming to already effected visual. E.g. close options menu, while opening effect still ongoing + RemoveTemporaryPresenterVisual(aCanvasVisual); + } + TBool layoutEffectable(EFalse); + aCanvasVisual->iOpacity.Set(KAlfVisualDefaultOpacity); + if (aEvent.iAction == KGfxControlDisappearAction) + { // TODO: revise + // The control stays visible because the inactive flag is not set + // if the window is reserved. + /*if (aCanvasVisual->iOpacity.Target() == 0.0f) + { + // this visual was hidden, before the effect arrived. sounds like trouble. + // Lets make it visible again, and ask it to be hidden in the end of the effect + // this enables at least the notes disappear effects + aCanvasVisual->iOpacity.Set(KAlfVisualDefaultOpacity); + // visual->SetFlag(EHuiVisualFlagShouldBeHidden); + }*/ + layoutEffectable = SetupEffectLayoutContainerL(aEvent.iHandle, aCanvasVisual, ETrue); + } + else + { + layoutEffectable = SetupEffectLayoutContainerL(aEvent.iHandle, aCanvasVisual, EFalse); + } + if (layoutEffectable) + { + TRAP( err, engine->LoadGroupEffectL(*aEvent.iEffectName, effect, aCanvasVisual->Effectable(), engine->ActiveGroupEffect(), NULL, this, aEvent.iHandle ) ); + } + else + { + err = KErrNotFound; + } + // RDebug::Print(_L("HandleGfxControlEffectsL - loading effect returned %d"), err ); + // only use the effect if the effect file was correctly parsed + if (err == KErrNone) + { + iLastEffectHandle = aEvent.iHandle; + +#ifdef HUI_DEBUG_TRACK_DRAWING + visual->SetTracking(ETrue); +#endif + // HuiVisual takes ownership of the effect, but we save the value for reference + // add new visual to iFullscreenEffectControlGroup. This enables multiple effects in the group, and their + // destruction in any order + } + else + { + // visuals added to "active effect visual" stack, but they wont be used, because effect loading has failed. cleanup. + RemoveTemporaryPresenterVisual(NULL, aEvent.iHandle); + } + effect = NULL; // HuiVisual has taken ownership + } + } + +TBool CAlfBridge::RemoveTemporaryPresenterItem(TEffectCleanupStruct& aEffectItem) + { + CHuiVisual* sourceViz = aEffectItem.iEffectedVisual; + CHuiCanvasVisual* sourceViz2 = dynamic_cast (aEffectItem.iEffectedVisual); + // wserv has already hidden this window. Effect has finished, so lets do what + // was asked. Also hide, if this is supposed to be destroyed by now. + sourceViz->SetFreezeState(EFalse); + sourceViz->SetStoredRenderBuffer(NULL); // free render buffer from visual + if (sourceViz2 && sourceViz2->Layout()) + { + sourceViz2->FreeRenderBuffer(); + } + sourceViz->ClearFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + TBool hideVisual = sourceViz->Flags() & EHuiVisualFlagShouldBeHidden; + TBool showVisual = sourceViz->Flags() & EHuiVisualFlagShouldBeShown; + TBool destroyVisual = sourceViz->Flags() & EHuiVisualFlagShouldDestroy; + TBool shouldInactivate = sourceViz->Flags() & EHuiVisualFlagShouldBeInactive; + TBool shouldBeUnderOpaqueHint = sourceViz->Flags() & EHuiVisualFlagShouldBeUnderOpaqueHint; + __ALFFXLOGSTRING3("CAlfBridge::RemoveTemporaryPresenterItem - cleaning handle: %d, 0x%x -> 0x%x", aEffectItem.iHandle, aEffectItem.iEffectedVisual, aEffectItem.iTemporaryPresenterVisual); + __ALFFXLOGSTRING3("CAlfBridge::RemoveTemporaryPresenterItem - hide %d, destroy %d, should inactivate: %d", TBool(hideVisual), TBool(destroyVisual), TBool(shouldInactivate)); + + sourceViz->ClearFlag(EHuiVisualFlagAlwaysDraw); + if (hideVisual) + { + // this was exit effect, and window was not really destroyed. + sourceViz->iOpacity.Set(0.0f); + sourceViz->ClearFlag(EHuiVisualFlagShouldBeHidden); // it is now hidden + } + else + { + // visual may be transparent after manipulation of the effect + sourceViz->iOpacity.Set(KAlfVisualDefaultOpacity); + } + if (showVisual) + { + sourceViz->iOpacity.Set(KAlfVisualDefaultOpacity); + sourceViz->ClearFlag(EHuiVisualFlagShouldBeShown); // it is now hidden + } + + if (destroyVisual) + { + sourceViz->iOpacity.Set(0.0f); + } + if (shouldInactivate) + { + sourceViz->SetFlag(EHuiVisualFlagInactive); + + if (sourceViz2) + { + sourceViz2->ClearCache(); + } + sourceViz->ClearFlags(EHuiVisualFlagShouldBeInactive); + } + if (shouldBeUnderOpaqueHint) + { + sourceViz->SetFlag(EHuiVisualFlagUnderOpaqueHint); + if (sourceViz2) + { + sourceViz2->ClearCache(); + } + sourceViz->ClearFlags(EHuiVisualFlagShouldBeUnderOpaqueHint); + } + if (sourceViz->Effect()) + { + sourceViz->SetEffect(NULL); + } + + // first delete the temporary presenter visual, because this will unbind the external content + if (aEffectItem.iTemporaryPresenterVisual) + { + CHuiVisual* viz = aEffectItem.iTemporaryPresenterVisual; + + if (viz) + { + if (viz->Effect()) + { + // temporary presenter visual should not have effect, because the effect is + // applied to the original visual. However, if somebody misuses this API, it + // is good to cleap up the effect here. + viz->SetEffect(NULL); + } + if (viz->Layout()) + { + viz->Layout()->Remove(viz); + } + viz->Owner().Remove(viz); + delete viz; + aEffectItem.iTemporaryPresenterVisual = NULL; + } + } + // although layout does not support EHuiVisualFlagDrawOnlyAsExternalContent flag, it is being used to indicate a layout that has effect. flag must be cleared, that the layout can be drawn normally after the effect. + if (aEffectItem.iIsLayout) + { + aEffectItem.iEffectedVisual->ClearFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + // sourceViz->iOpacity.Set(1.0f); + } + + if (destroyVisual) + { + // window has been destroyed during effect. Kill it once and for all + // DeleteControlGroupL and DestroyWindow can do their duty, when this flag is cleared + sourceViz->ClearFlags(EHuiVisualFlagShouldDestroy | EHuiVisualFlagDrawOnlyAsExternalContent); + if (aEffectItem.iIsLayout) + { + if (sourceViz->Layout()) + { + sourceViz->Layout()->Remove(sourceViz); + } + sourceViz->Owner().Remove(sourceViz); + + delete sourceViz; + __ALFFXLOGSTRING1("CAlfBridge::RemoveTemporaryPresenterItem - Destroying sourceViz: 0x%x", sourceViz); + aEffectItem.iEffectedVisual = NULL; + } + else + { + TLex8 lex(sourceViz->Tag()); + TInt nodeId; + lex.Val(nodeId); + DestroyWindow(sourceViz, ETrue); + } + } + return TBool(destroyVisual); + } + +// RemoveTemporaryPresenterVisual removes the temporary presenter visual, and unbinds it from the source. +TBool CAlfBridge::RemoveTemporaryPresenterVisual(CHuiVisual* aVisual, + TInt aHandle) + { + __ALFFXLOGSTRING2("CAlfBridge::RemoveTemporaryPresenterVisual - cleaning handle: %d, 0x%x", aHandle, aVisual); + TInt visualsRemoved = 0; + for (TInt i = 0; i < iEffectCleanupStack.Count(); i++) + { + TEffectCleanupStruct& effectItem = iEffectCleanupStack[i]; + if (aVisual == effectItem.iEffectedVisual || + aHandle == effectItem.iHandle) + { + if (RemoveTemporaryPresenterItem(effectItem)) + { + visualsRemoved++; + } + // must remove from finished effects to keep it in sync + for(TInt k = 0; k < iFinishedCleanupStackEffects.Count(); k++) + { + if (iFinishedCleanupStackEffects[k] == effectItem.iHandle) + { + iFinishedCleanupStackEffects.Remove(k); + k--; + } + } + iEffectCleanupStack.Remove(i); + i--; + } + } + return TBool(visualsRemoved); + } + +CHuiLayout* CAlfBridge::FindTemporaryPresenterLayout(CHuiVisual* aVisual) + { + for (TInt i = 0; i < iEffectCleanupStack.Count(); i++) + { + if (aVisual == iEffectCleanupStack[i].iEffectedVisual) + { + ASSERT(iEffectCleanupStack[i].iIsLayout); + return (CHuiLayout*)iEffectCleanupStack[i].iTemporaryPresenterVisual; + } + } + return NULL; + } + +TBool CAlfBridge::HasActiveEffect(CHuiVisual* aVisual) + { + for (TInt i = 0; i < iEffectCleanupStack.Count(); i++) + { + if (aVisual == iEffectCleanupStack[i].iEffectedVisual) + { + return ETrue; + } + } + return EFalse; + } + +TInt CAlfBridge::FindEffectHandle(CHuiVisual* aVisual) + { + for (TInt i = 0; i < iEffectCleanupStack.Count(); i++) + { + if (aVisual == iEffectCleanupStack[i].iEffectedVisual) + { + return iEffectCleanupStack[i].iHandle; + } + } + __ALFFXLOGSTRING1(" CAlfBridge::SetupEffectLayoutContainerL - Could not find handle for 0x%x", aVisual); + return KErrNotFound; + } + +CHuiLayout* CAlfBridge::FindLayoutByEffectHandle(TInt aHandle) + { + for (TInt i = 0; i < iEffectCleanupStack.Count(); i++) + { + if (aHandle == iEffectCleanupStack[i].iHandle && iEffectCleanupStack[i].iIsLayout) + { + return (CHuiLayout*)iEffectCleanupStack[i].iEffectedVisual; + } + } + return NULL; + } + + +TBool CAlfBridge::RemoveTemporaryPresenterVisuals() + { + if (!iFinishedCleanupStackEffects.Count()) + { + return 0; + } + TInt itemsRemoved(0); + CHuiControl& effectControlGroup = iAlfScreens[0]->iFullscreenEffectControlGroup->Control(0); + CHuiLayout* effectControlGroupLayout = (CHuiLayout*) &effectControlGroup.Visual(0); + __ALFFXLOGSTRING1("CAlfBridge::RemoveTemporaryPresenterVisuals - BEGIN - effects in layout %d", effectControlGroupLayout->Count()); + + while (iFinishedCleanupStackEffects.Count()) + { + for (TInt i = 0; i < iEffectCleanupStack.Count() && iFinishedCleanupStackEffects.Count(); i++) + { + __ALFFXLOGSTRING2("CAlfBridge::RemoveTemporaryPresenterVisuals - looping, finished count: %d, index in active effecs: %d", iFinishedCleanupStackEffects.Count(), i ); + + TEffectCleanupStruct& effectItem = iEffectCleanupStack[i]; + if (iFinishedCleanupStackEffects[0] == effectItem.iHandle) + { + if (RemoveTemporaryPresenterItem(effectItem)) + { + itemsRemoved++; + } + iEffectCleanupStack.Remove(i); + iFinishedCleanupStackEffects.Remove(0); + i--; + } + } + } + iAlfScreens[0]->iVisualTreeVisibilityChanged = ETrue; // TODO: Check if really changed + iAlfScreens[0]->iDisplay->SetDirty(); + __ALFFXLOGSTRING1("CAlfBridge::RemoveTemporaryPresenterVisuals - END - effects in layout %d", effectControlGroupLayout->Count()); + return itemsRemoved; + } + +void CAlfBridge::RemoveAllTemporaryPresenterVisuals() + { + CHuiControl& effectControlGroup = iAlfScreens[0]->iFullscreenEffectControlGroup->Control(0); + CHuiLayout* effectControlGroupLayout = (CHuiLayout*) &effectControlGroup.Visual(0); + __ALFFXLOGSTRING1("CAlfBridge::RemoveAllTemporaryPresenterVisuals - BEGIN - effects in layout %d", effectControlGroupLayout->Count()); + + while(iEffectCleanupStack.Count()) + { + TEffectCleanupStruct& effectItem = iEffectCleanupStack[0]; + RemoveTemporaryPresenterItem(effectItem); + iEffectCleanupStack.Remove(0); + } + + while(iFinishedCleanupStackEffects.Count()) + { + iFinishedCleanupStackEffects.Remove(0); + } + } + +void CAlfBridge::AlfGfxEffectEndCallBack(TInt aHandle) + { + // We need a delay to prevent the refresh from being messed up + // We try a short delay before clearing everything up. + __ALFFXLOGSTRING1("AlfGfxEffectEndCallBack, append handle %d", aHandle ); + // RDebug::Print(_L("AlfGfxEffectEndCallBack, append handle %d"), aHandle ); + // If the handle cannot be appended, the function returns an error. + // However, if the memory is low, there is nothing we can do about it. + // We try to handle the transition finish anyway. + // If there are already other handles in the queue, the handler will not + // be called for this handle, but all handles that have been left hanging + // around will be cleared when HandleGfxStopEffectsL is called + + + iFinishedEffects.Append(aHandle); + + // iFinishedCleanupStackEffects.Append(aHandle); + if (!iEffectEndTimer->IsActive()) + { + iEffectEndTimer->Start( 10000, aHandle ); + } + + // We should do visual visibility scan after effect is ended + iAlfScreens[0]->SetVisualTreeVisibilityChanged(ETrue); + } + +void CAlfBridge::TransitionFinishedHandlerL(TInt aHandle) + { + for (TInt i=0;iiHandle; + if ( fsEffectDone ) + { + aHandle = iFullScreenEffectData->iCompletionHandle; + } + RProperty::Set( KPSAlfDomain, KAlfTransitionStatus, aHandle ); + + // Effect finished + if ( fsEffectDone ) + { + delete iFullScreenEffectData; + iFullScreenEffectData = NULL; + } + } + + +void CAlfBridge::PrintAllocMem() + { +#ifdef _ALF_LOGGING + TInt allocCells = 0; + TInt allocSpace = 0; + TInt freeSpace = 0; + TInt largestFreeBlock = 0; + allocCells = User::AllocSize( allocSpace ); + freeSpace = User::Available( largestFreeBlock ); + __ALFLOGSTRING2("CAlfBridge::PrintAllocMem - alloc cells %d, alloc space %d", allocCells, allocSpace ); + __ALFLOGSTRING2("CAlfBridge::PrintAllocMem - free space %d, largest free block %d", freeSpace, largestFreeBlock ); +#endif + } + +// --------------------------------------------------------------------------- +// DebugPrintControlGroupOrder +// +// Note, that HUI_DEBUG_TRACK_DRAWING must be enabled if you want to see the +// real process names +// --------------------------------------------------------------------------- +// + +#ifdef ALF_DEBUG_PRINT_WINDOWGROUP_ORDER +void CAlfBridge::DebugPrintControlGroupOrder(CAlfScreen& aScreen, CHuiRoster& aRoster, CHuiControlGroup& aGroup) + { + __ALFLOGSTRING(">> ---AFTER-----"); + for (TInt i=0; iWServClientFileName( clientWindowGroupId, CHuiStatic::WsSession() ); +#endif + if (indexedGroup.Control(0).Role() == EAlfWindowGroupContainer) + { + if (aRoster.ControlGroup(i).ResourceId() == iAlfWindowGroupNodeId) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + __ALFLOGSTRING2(">> %d WINDOW GROUP (ALF), %d", i, clientWindowGroupId); +#endif + } + else + { +#ifdef HUI_DEBUG_TRACK_DRAWING + __ALFLOGSTRING3(">> %d WINDOW GROUP %S, %d", i, &processName, clientWindowGroupId); +#else + __ALFLOGSTRING1(">> %d WINDOW GROUP", i); +#endif + } + } + else if (indexedGroup.Control(0).Role() == EAlfSessionContainer) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + __ALFLOGSTRING2(">> %d ALF GROUP, %d", i, clientWindowGroupId); +#endif + } + else if (indexedGroup.Control(0).Role() == EAlfWindowFloatingSpriteContainer) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + __ALFLOGSTRING3(">> %d FLOATING SPRITE GROUP %S, %d", i, &processName, clientWindowGroupId); +#else + __ALFLOGSTRING1(">> %d FLOATING SPRITE GROUP", i); +#endif + } + else if (indexedGroup.Control(0).Role() == EAlfFullScreenEffectContainer) + { +#ifdef HUI_DEBUG_TRACK_DRAWING + __ALFLOGSTRING3(">> %d EFFECT GROUP %S, %d", i, &processName, clientWindowGroupId ); +#else + __ALFLOGSTRING1(">> %d EFFECT GROUP", i); +#endif + } + else + { +#ifdef HUI_DEBUG_TRACK_DRAWING + __ALFLOGSTRING3(">> %d UNKNOWN GROUP ?!!? %S, %d", i, &processName, clientWindowGroupId ); +#endif + } + + if (&indexedGroup == &aGroup) + { + __ALFLOGSTRING("<<"); + } + } + + // Print the group that has keyboard focus + TInt focusWindowGroupId = CHuiStatic::WsSession().GetFocusWindowGroup(); + TFileName processName; + TThreadId threadId; + TInt error = CHuiStatic::WsSession().GetWindowGroupClientThreadId( focusWindowGroupId, threadId ); + RThread thread; + TInt err = thread.Open( threadId ); + if( !err ) + { + RProcess process; + err = thread.Process( process ); + if( !err ) + { + processName = process.FileName(); + __ALFLOGSTRING2( ">> Keyboard focus group: %S, %d", &processName, focusWindowGroupId ); + } + process.Close(); + thread.Close(); + } + __ALFLOGSTRING(">> ---------------"); + } +#else +void CAlfBridge::DebugPrintControlGroupOrder(CAlfScreen& /*aScreen*/, CHuiRoster& /*aRoster*/, CHuiControlGroup& /*aGroup*/) + { + } +#endif + +#ifdef ALF_DEBUG_VISUALIZE_WINDOWGROUP_ORDER +void CAlfBridge::VisualizeControlGroupOrderL(CHuiRoster& aRoster, CHuiControlGroup& /*aGroup*/) + { + TInt nbrofcolums = 3; + TInt nbrofrows = 3; + TInt gridIndex = 0; + TBool skipEmpty = EFalse; + if (aRoster.Count() > 3) + { + for (TInt i=aRoster.Count() - 3; i>0; i--) + { + CHuiControl& control = aRoster.ControlGroup(i).Control(0); + if (skipEmpty) + { + TBool empty = ETrue; + CHuiLayout* layout = (CHuiLayout*)&control.Visual(0); + for (TInt j=layout->Count()-1; j >= 0; j--) + { + CHuiCanvasVisual* canvasVisual = (CHuiCanvasVisual*) &layout->Visual(j); + if (canvasVisual && canvasVisual->DisplayRect().Size().Round() != TSize(0,0) && canvasVisual->PaintedAreaCount()) + { + empty = EFalse; + break; + } + } + + if (empty && skipEmpty) + { + continue; + } + } + + TSize screensize = HuiUtil::ScreenSize(); + CHuiTransformation::TTransform& step = aRoster.ControlGroup(i).Transformation().Step(0); + step.iParams[EHuiTransformParamTranslateX].Set((gridIndex % nbrofcolums) * (screensize.iWidth/nbrofcolums), 500); + step.iParams[EHuiTransformParamTranslateY].Set((gridIndex / nbrofrows) * (screensize.iHeight/nbrofrows), 500); + gridIndex++; + } + } + iAlfScreens[0]->iDisplay->SetClearBackgroundL(CHuiDisplay::EClearWithSkinBackground); + } +#else +void CAlfBridge::VisualizeControlGroupOrderL(CHuiRoster& /*aRoster*/, CHuiControlGroup& /*aGroup*/) + { + } +#endif + +// --------------------------------------------------------------------------- +// PostQTCommandBufferL +// --------------------------------------------------------------------------- +// +void CAlfBridge::PostQTCommandBufferL( TAlfQtCommandBufferParams params ) + { + CHuiCanvasVisual* huiVisual = NULL; + if ((*iHost)) + { + if( (*iHost)->StreamerServer() ) + { + if ((*iHost)->StreamerServer()->WindowMgr()) + { + RArray winInfoList; + + (*iHost)->StreamerServer()->WindowMgr()->GetWinInfoListL( params.iWsWgId, + params.iWsClientId, winInfoList ); + + for ( TInt i= 0; iSetCommandType( 1 ); // set to ECommandBufferWs should it be some QT specific? + if ( bufferStatus == EComplete ) + { + huiVisual->ClearCommandSet(); + huiVisual->AddCommandSetL(commands); + } + else if ( bufferStatus == EPartial ) + { + huiVisual->AddPartialCommandSetL( commands, EFalse ); + } + else if ( bufferStatus == ELastPart ) + { + huiVisual->AddPartialCommandSetL( commands, ETrue ); + } + } + } + + +// --------------------------------------------------------------------------- +// SetClientWindowForDrawingL +// +// Note: One external content visual can exist in one canvas visual at the +// time. When external content visual is deleted, in destructor, it removes +// pointers to it from all canvas visuals. So canvasVisual->ExternalContent() +// always returns a valid pointer, or NULL. The parameter aRootVisual can +// be NULL, which means that the external content is removed from the canvas +// visual +// --------------------------------------------------------------------------- +// +void CAlfBridge::SetClientWindowForDrawingL(TInt aWindowGroupId, TInt aClientWindowHandle, + CHuiVisual* aExternalContentVisual) + { + RArray winInfoList; + CleanupClosePushL(winInfoList); + + // Find canvas visual for the RWindow + + (*iHost)->StreamerServer()->WindowMgr()->GetWinInfoListL(aWindowGroupId, aClientWindowHandle, winInfoList ); + if(winInfoList.Count() != 1) + { + User::Leave(KErrArgument); + } + + CHuiCanvasVisual* canvasVisual = (CHuiCanvasVisual*)FindVisual(winInfoList[0].iRefId.iWindowIdentifer); + if (!canvasVisual) + { + User::Leave(KErrNotFound); + } + + // Current external content + CHuiVisual* currentContent = canvasVisual->ExternalContent(); + + if (!aExternalContentVisual) + { + // Do not draw external content any more. + + // Disable external content for the canvas visual + canvasVisual->SetExternalContentL(NULL); + // For the current content, enable drawing it in the original visual tree. + if (currentContent) + { + currentContent->ClearFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + } + } + else if (!(aExternalContentVisual->Flags() & EHuiVisualFlagDrawOnlyAsExternalContent)) + { + // The visual is not yet used by other canvas visual + + // Enable external content for the canvas visual + canvasVisual->SetExternalContentL(aExternalContentVisual); + // For the current content, enable drawing it in the original visual tree. + if (currentContent) + { + currentContent->ClearFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + } + // Disable normal drawing and start using as external content + aExternalContentVisual->SetFlag(EHuiVisualFlagDrawOnlyAsExternalContent); + } + else + { + // aExternalContentVisual is already used as an external content for some visual + User::Leave(KErrAlreadyExists); + } + + CleanupStack::PopAndDestroy(); // winInfoList + } + +void CAlfBridge::SetVisualTreeVisibilityChanged(TBool aChanged) + { + for (TInt i=0; iiVisualTreeVisibilityChanged = aChanged; + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::EnableSwRenderingL(TBool aEnable) + { + if (aEnable == iSwRenderingEnabled) + { + return; + } + + iSwRenderingEnabled = aEnable; + for (TInt i=0; iiDisplay->SetForegroundBitmapL( iAlfScreens[i]->iSwRenderingTarget ); + CleanupStack::Pop(texture); + iAlfScreens[i]->iDisplay->SetForegroundTexture(texture); + iAlfScreens[i]->iDisplay->iRosterObservers.AppendL(*this); + } + else + { + iAlfScreens[i]->iDisplay->SetForegroundBitmapL(NULL); + iAlfScreens[i]->iDisplay->SetForegroundTexture(NULL); + iAlfScreens[i]->iDisplay->iRosterObservers.Remove(*this); + } + + // SetCapturingBufferL is called from HandleVisualVisibility. + iAlfScreens[i]->SetVisualTreeVisibilityChanged(ETrue); + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::UploadSwRenderingTargetL(CAlfScreen* aScreen) + { + if (iSwRenderingEnabled) + { + CHuiTexture* texture = aScreen->iDisplay->ForegroundTexture(); + if (texture && aScreen->iSwRenderingTarget) + { + texture->UploadL(*aScreen->iSwRenderingTarget, NULL); + } + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +TBool CAlfBridge::PrepareSwRenderingTarget( CAlfScreen* aScreen ) + { + TBool modified = EFalse; + + // Check ultra low memory mode here + if (iHuiEnv->MemoryLevel() <= EHuiMemoryLevelLowest) + { + if (!aScreen->iSwRenderingTarget) + { + // screen owns this bitmap + aScreen->iSwRenderingTarget = new CFbsBitmap; + if (aScreen->iSwRenderingTarget) + { + aScreen->iSwRenderingTarget->Create(aScreen->Size(), EColor16MA); + modified = ETrue; + } + } + + if (aScreen->iSwRenderingTarget) + { + if (aScreen->iSwRenderingTarget->SizeInPixels() != aScreen->Size()) + { + aScreen->iSwRenderingTarget->Resize(aScreen->Size()); + modified = ETrue; + } + // For tests + //TUint32* data = aScreen->iSwRenderingTarget->DataAddress(); + } + } + else + { + delete aScreen->iSwRenderingTarget; + aScreen->iSwRenderingTarget = NULL; + modified = ETrue; + } + + return modified; + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::SetMemoryLevel(THuiMemoryLevel aMemoryLevel) + { + iCurrentMemoryLevel = aMemoryLevel; + DoUpdateMemoryLevel(); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::SetLowMemory(TBool aEnabled) + { + iLowMemoryMode = aEnabled; + DoUpdateMemoryLevel(); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +TInt CAlfBridge::ForceSwRendering(TBool aEnabled) + { + iForcedSwRendering = aEnabled; + DoUpdateMemoryLevel(); + return KErrNone; + } + +// --------------------------------------------------------------------------- +// This decides memory level for core toolkit. This should the only place +// where core toolkit memory level is modified. +// --------------------------------------------------------------------------- +// +void CAlfBridge::DoUpdateMemoryLevel() + { + THuiMemoryLevel memoryLevel = iCurrentMemoryLevel; + if ( iLowMemoryMode && ( memoryLevel > EHuiMemoryLevelLow ) ) + { + memoryLevel = EHuiMemoryLevelLow; + } + if ( iForcedSwRendering && ( memoryLevel > EHuiMemoryLevelLowest ) ) + { + // For now, we use memory level to force SW rendering + // to be used. + memoryLevel = EHuiMemoryLevelLowest; + } + + if ( memoryLevel != iHuiEnv->MemoryLevel() ) + { + __ALFLOGSTRING1("CAlfBridge::DoUpdateMemoryLevel -> %d", memoryLevel); + if ( memoryLevel <= EHuiMemoryLevelLowest) + { + LowMemoryCancelAllEffects(); + } + + iHuiEnv->NotifyMemoryLevel(memoryLevel); + if (memoryLevel <= EHuiMemoryLevelLowest) + { + TRAP_IGNORE(EnableSwRenderingL(ETrue)); + } + else + { + TRAP_IGNORE(EnableSwRenderingL(EFalse)); + } + } + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::LowMemoryCancelAllEffects() + { + __ALFLOGSTRING("CAlfBridge::LowMemoryCancelAllEffects"); + iLayoutSwitchEffectCoordinator->Cancel(); + HandleGfxStopEvent( EFalse ); + __ALFLOGSTRING("CAlfBridge::LowMemoryCancelAllEffects done"); + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::NotifyRosterDrawStart(CHuiDisplay& /*aDisplay*/) + { + // Do nothing + } + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- +// +void CAlfBridge::NotifyRosterDrawEnd(CHuiDisplay& aDisplay) + { + TInt screenNumber = ResolveScreenNumber(aDisplay); + TRAP_IGNORE(UploadSwRenderingTargetL(iAlfScreens[screenNumber])); + } + +// end of file