diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/ServerCore/Src/alfappserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/ServerCore/Src/alfappserver.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,1450 @@ +/* +* Copyright (c) 2006 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: Application Sever +* +*/ + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "alf/alfappserver.h" +#include "alf/alfappui.h" +#include "alf/alfconstants.h" +#include "alfappsrvsession.h" +#include "alflogger.h" +#include "alfsrvsubsessionbase.h" +#include "alf/alfextensionfactory.h" +#include "alfstaticfactory.h" +#include "alfsrvtranseffect.h" +#include "alf/AlfTransEffectPlugin.h" +#include //@todo:: +#include "alfclientserver.h" +#include "alfsrvtexturemanager.h" +#include "alfsrvscreenbuffermanager.h" + +// ---------------------------- + +/** + * Common command batch buffer size. This must always be larger than command + * header size. In practice, this should be always larger than 128. + */ +const TInt KAlfCommonCommandBatchBufferSize = + KAlfClientServerDefaultCommandBatchBufferSize; + +// a kind of cleanup item for ecom info array +NONSHARABLE_CLASS(CCleanupEcomArray):public CBase + { + public: + ~CCleanupEcomArray() + { + iArray.ResetAndDestroy(); + iArray.Close(); + } + RImplInfoPtrArray iArray; + }; + + +// ECom notify helper. +NONSHARABLE_CLASS(CAlfEcomUtil): public CActive + { + public: + + CAlfEcomUtil(CAlfAppServer& aServer) + :CActive(EActivePriorityDefault), iOwner(aServer) + { + CActiveScheduler::Add(this); + } + + void ConstructL() + { + iEComSession = &REComSession::OpenL(); + } + + ~CAlfEcomUtil() + { + Cancel(); + if (iEComSession) + { + iEComSession->Close(); + } + iEComSession = NULL; + } + + static CAlfEcomUtil* NewL(CAlfAppServer& aServer) + { + CAlfEcomUtil* self = new (ELeave) CAlfEcomUtil(aServer); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + + void Start() + { + if (!IsActive()) + { + iEComSession->NotifyOnChange(iStatus); + SetActive(); + } + } + + void RunL() + { + // if there was an error, just breathe a moment, i.e. don't activate new request immediately + if (iStatus.Int() == KErrNone ) + { + //Check wether plugin was installed or removed + TRAP_IGNORE(iOwner.CheckForEcomPluginInstallUninstallL()) + Start(); + } + __ALFLOGSTRING1( "CAlfEcomUtil::RunL: status %d", iStatus.Int() ) + } + + void DoCancel() + { + iEComSession->CancelNotifyOnChange(iStatus); + } + + private: + CAlfAppServer& iOwner; + REComSession* iEComSession; + }; + + +// ======== MEMBER FUNCTIONS ======== + + +EXPORT_C CAlfAppServer* CAlfAppServer::NewAppServerL() + { + return new (ELeave) CAlfAppServer(); + } + + +// --------------------------------------------------------------------------- +// Constructor +// --------------------------------------------------------------------------- +// +CAlfAppServer::CAlfAppServer(): + iLastActiveClientWg(KErrNotFound) + { + CCoeEnv* coe = CCoeEnv::Static(); + if (coe) + { + iWs = &coe->WsSession(); + } + } + +// --------------------------------------------------------------------------- +// Second phase constructor +// --------------------------------------------------------------------------- +// +void CAlfAppServer::ConstructL( const TDesC& aFixedServerName ) + { + CAknAppServer::ConstructL( aFixedServerName ); + + iCommonCommandBatchBuffer = HBufC8::NewL( KAlfCommonCommandBatchBufferSize ); + iTextureManager = CAlfSrvTextureManager::NewL(); + iScreenBufferManager = CAlfSrvScreenBufferManager::NewL(*this); + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CAlfAppServer::~CAlfAppServer() + { + #ifdef TFXSERVER_API_V2 + if (iTfxServer) + { + iTfxServer->Disconnect(); + delete iTfxServer; + iTfxServer = NULL; + REComSession::DestroyedImplementation( iTfxServerEComDestructorUID ); + iTfxServerEComDestructorUID.iUid = 0; + } + #endif + + delete iBackgroundTimer; + delete iTransitionEffects; + + delete iEcomWatcher; + + iWindowChangeObservers.Close(); + + if (iAsynchOneShot) + { + iAsynchOneShot->Cancel(); + } + + delete iAsynchOneShot; + iRemovedArray.Close(); + + delete iObjectConIx; + + for (TInt ii = iCustomSessions.Count()-1; ii >= 0; ii--) + { + delete iCustomSessions[ii].iImpl; + REComSession::DestroyedImplementation( + iCustomSessions[ii].iDestructorUid); + } + + iCustomSessions.Close(); + + // Todo: check remaining implementations + for (TInt ii = iFactories.Count()-1; ii >= 0; ii--) + { + iFactories[ii].iImpl->Release(); + if (iFactories[ii].iDestructorUid.iUid) + { + REComSession::DestroyedImplementation( + iFactories[ii].iDestructorUid); + } + } + + iFactories.Close(); + + iMetricsInterface = NULL; + iAppUi= NULL; + + delete iCommonCommandBatchBuffer; + delete iScreenBufferManager; + delete iTextureManager; + } + +// --------------------------------------------------------------------------- +// Called when client application exist. +// All allocated resources for that application should be freed. +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfAppServer::HandleClientExit(TInt aClientId) + { + if (MetricsInterface()) + { + MetricsInterface()->SessionTerminated(aClientId); + } + + SyncEcomImplementations(aClientId); + + CAlfAppSrvSessionBase* session = reinterpret_cast(aClientId); + + ScreenBufferManager().RemoveScreenBufferObservers(session); + + if (session == iOldSession) + { + iOldSession = 0; + } + + if (iAppUi) + { + iAppUi->FreeResourcesForClient(aClientId); + } + else + { + return; + } + + for (TInt i = iWindowChangeObservers.Count()-1; i >= 0 ; i--) + { + if (iWindowChangeObservers[i].iId == aClientId) + { + iWindowChangeObservers.Remove(i); + } + } + + // todo, is it true that we have no other way to check the count than using iterator? + TInt count = 0; + iSessionIter.SetToFirst(); + for(;iSessionIter;iSessionIter++) + { + count++; + } + + // if this was the last client, it is ok to bail out here + if (count == 1) + { + AppUi()->UpdateActiveSession( 0 ); + AdjustWindowGroupPositionL(*CHuiStatic::RootWin(0),0,EAbsoluteBackground); + return; + } + + // Set wg position based in the topmost client app + TInt parentWg = KErrNotFound; + CAlfAppSrvSessionBase* dying = reinterpret_cast(aClientId); + + if ( dying->ClientWindowGroup() == KErrNotFound ) + { + // debugging trash + // just bail out w/o changing the order of window groups + return; + } + + if ( dying->ClientWindowGroup() == iLastActiveClientWg ) + { + iLastActiveClientWg = KErrNotFound; + parentWg = dying->ParentWindowGroupId(); + } + + CAlfAppSrvSessionBase* newFocusSession = 0; + + // if parent of embedded app found, check if it ALF app and set it to focus + if (parentWg != KErrNotFound) + { + iSessionIter.SetToFirst(); + while (iSessionIter) + { + CAlfAppSrvSessionBase* session = reinterpret_cast(iSessionIter++); + if ( session && session->ClientWindowGroup() == parentWg) + { + newFocusSession = session; + break; + } + } + } + + if (CCoeEnv::Static() && !newFocusSession) // else find topmost app and move us behind that + { + parentWg = KErrNotFound; // just in case app had parent but that was not ALF app + CArrayFixFlat* wgs = new CArrayFixFlat(4); + if ( wgs ) + { + iWs->WindowGroupList(wgs); + for ( TInt ordinal = 0 ; ordinal < wgs->Count(); ordinal++ ) + { + iSessionIter.SetToFirst(); + if( newFocusSession ) // session found from previous ordinal position. + { + break; + } + while (iSessionIter) + { + CAlfAppSrvSessionBase* session = reinterpret_cast(iSessionIter++); + if ( session && + session->ClientWindowGroup() == wgs->At( ordinal ) && + (TInt)session != aClientId ) + { + newFocusSession = session; + break; + } + } + } + } + delete wgs; + } + + TRAP_IGNORE(FocusedWindowGroupChangedL(newFocusSession, parentWg)) + } + + +// --------------------------------------------------------------------------- +// Static utility used in callback +// --------------------------------------------------------------------------- +// +TInt SynchEcomImplementations(TAny* aThis) + { + ((CAlfAppServer*)aThis)->DoSynchEcomImplementations(); + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Check if the exiting client is using ecom based session +// if so, set asynchronous callback for notifying Ecom FW about the change +// --------------------------------------------------------------------------- +// +void CAlfAppServer::SyncEcomImplementations(TInt aClientId) + { + TBool isEcom(EFalse); + for(TInt ii = iCustomSessions.Count()-1; ii >= 0 ; ii--) + { + if (iCustomSessions[ii] == aClientId) + { + isEcom = ETrue; + iCustomSessions[ii].iImpl = 0; // session is about to terminate, null the pointer + break; + } + } + if (isEcom) + { + iRemovedArray.Append(aClientId); + if (iAsynchOneShot && !iAsynchOneShot->IsActive()) + { + iAsynchOneShot->CallBack(); + } + + } + } + +// --------------------------------------------------------------------------- +// Check and notify Ecom FW about removed implementations caused by client exit +// Called asynchronously after a client usin ecom based session has exited. +// --------------------------------------------------------------------------- +// +void CAlfAppServer::DoSynchEcomImplementations() + { + // check if the session was ECOM based and notify FW if so + for (TInt i = iRemovedArray.Count()-1; i >= 0; i--) + { + for(TInt ii = iCustomSessions.Count()-1; ii >= 0 ; ii--) + { + if (iCustomSessions[ii] == iRemovedArray[i]) + { + REComSession::DestroyedImplementation( + iCustomSessions[ii].iDestructorUid); + iCustomSessions.Remove(ii); + } + } + + } + iRemovedArray.Reset(); + User::Heap().Compress(); + } + +// --------------------------------------------------------------------------- +// From class CAknAppServer. +// Called when all clients have existed. +// --------------------------------------------------------------------------- +// +void CAlfAppServer::HandleAllClientsClosed() + { + if (iAppUi) + iAppUi->AllClientsClosed(); + } + +// --------------------------------------------------------------------------- +// From class CAknAppServer. +// Allocates the session instance +// --------------------------------------------------------------------------- +// +CApaAppServiceBase* CAlfAppServer::CreateServiceL( TUid aServiceType ) const + { + CApaAppServiceBase* session = 0; + if (aServiceType == KAlfServiceUid) + { + session = CAlfAppSrvSession::NewL(this); + } + else + { // nasty const cast + session = ((CAlfAppServer*)this)->LoadServiceExtensionL(aServiceType); + } + + if(session) + { + if (MetricsInterface()) + { + const_cast(MetricsInterface())->SessionCreated(reinterpret_cast(session)); + } + + return session; + } + else + { + return CAknAppServer::CreateServiceL(aServiceType); + } + } + +// --------------------------------------------------------------------------- +// Adjusts server's wg according to client's wg. +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfAppServer::AdjustWindowGroupPositionL( + RWindowGroup& aWindowGroup, + TInt aParentIdentifier, + TAlfWGPostion aPosition) + { + if (!iAppUi ) + { + return; + } + + // Update the member variable based on the WG the server follows. + if (aPosition != EAbsoluteBackground) + { + iLastActiveClientWg = aParentIdentifier; + } + + if (!CCoeEnv::Static()) + { + iAppUi->AdjustWindowGroupPositionL( + aParentIdentifier, + aPosition); + return; + } + +#ifdef _ALF_LOGGING + LogWindowGroupsL(); + switch( aPosition ) + { + case EBehindOfParent: + __ALFLOGSTRING1( "CAlfAppServer::AdjWinGrpPosL EBehindOfParent parent id %d", aParentIdentifier ) + break; + case EOnTopOfParent: + __ALFLOGSTRING1( "CAlfAppServer::AdjWinGrpPosL EOnTopOfParent parent id %d", aParentIdentifier ) + break; + case EAbsoluteBackground: + __ALFLOGSTRING1( "CAlfAppServer::AdjWinGrpPosL EAbsoluteBackground parent id %d", aParentIdentifier ) + break; + default: + __ALFLOGSTRING2( "CAlfAppServer::AdjWinGrpPosL UNKNOWN parent id %d pos %d", aParentIdentifier, aPosition ) + break; + } +#endif + + if (aPosition == EAbsoluteBackground) // just for convenience + { + aWindowGroup.SetOrdinalPosition(0,ECoeWinPriorityNeverAtFront); + LogWindowGroupsL(); + return; + } + + TInt parentPriority = iWs->GetWindowGroupOrdinalPriority(aParentIdentifier); + + // perhaps we should maintain wg-list elsewhere + CArrayFixFlat* wgs = new (ELeave) CArrayFixFlat(1); + CleanupStack::PushL(wgs); + iWs->WindowGroupList(parentPriority,wgs); + + TInt pos = KErrNotFound; + TInt movingWgOldPos = KErrNotFound; + TInt wgCount = wgs->Count(); + for (TInt i = 0; i < wgCount; i++) + { + if (aParentIdentifier == wgs->At(i)) + { + if ( aPosition == EOnTopOfParent ) + { + pos = i; + } + else + { + pos = i+1; + } + } + if ( aWindowGroup.WindowGroupId() == wgs->At(i)) + { + movingWgOldPos = i; + } + + if ( pos != KErrNotFound && movingWgOldPos != KErrNotFound ) + { + // Both found already. + break; + } + } + + // If the moving window group has already been before the parent + // we need to adjust the new position + if ( movingWgOldPos < pos && movingWgOldPos != KErrNotFound ) + { + pos--; + } + + + User::LeaveIfError(pos); // parenty not found, leave + + // if iBackDropWgIdentifier has been set, status pane is partly drawn to + // back drop window group + if (aPosition == EBehindOfParent && + iBackDropWgIdentifier + && parentPriority == ECoeWinPriorityNormal ) // only apps with normal priority should use status pane + { + for (TInt ii = pos; ii < wgCount; ii++) + { + if (wgs->At(ii) == iBackDropWgIdentifier) + { + pos = ii+1; // right behind status pane + break; + } + } + + } + CleanupStack::PopAndDestroy(wgs); + + aWindowGroup.SetOrdinalPosition(pos, parentPriority); + + LogWindowGroupsL(); + } + +// --------------------------------------------------------------------------- +// Returns server's window server session. +// --------------------------------------------------------------------------- +// +EXPORT_C RWsSession& CAlfAppServer::WsSession() const + { + return *iWs; + } + +// --------------------------------------------------------------------------- +// Returns the metrics interface. +// --------------------------------------------------------------------------- +// +EXPORT_C MAlfMetricsInterface* CAlfAppServer::MetricsInterface() + { + return iMetricsInterface; + } + +// --------------------------------------------------------------------------- +// Returns the metrics interface. +// --------------------------------------------------------------------------- +// +EXPORT_C const MAlfMetricsInterface* CAlfAppServer::MetricsInterface() const + { + return iMetricsInterface; + } + +// --------------------------------------------------------------------------- +// Sets the metrics interface. +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfAppServer::SetMetricsInterface( + MAlfMetricsInterface* aMetricsInterface) + { + iMetricsInterface = aMetricsInterface; + } + +// --------------------------------------------------------------------------- +// Sets the AppUi. +// --------------------------------------------------------------------------- +// +void CAlfAppServer::SetAppUi(CAlfAppUi* aAppUi) + { + iAppUi = aAppUi; + iWs = &CHuiStatic::WsSession(); + } + +// --------------------------------------------------------------------------- +// Returns the AppUi pointer. +// --------------------------------------------------------------------------- +// +EXPORT_C CAlfAppUi* CAlfAppServer::AppUi() + { + __ASSERT_DEBUG(iAppUi, USER_INVARIANT()); + return iAppUi; + } + +// --------------------------------------------------------------------------- +// Called when the focused window group changes. +// --------------------------------------------------------------------------- +// +void CAlfAppServer::FocusedWindowGroupChangedL( CAlfAppSrvSessionBase* aSession, TInt aWgId) + { + iOldSession = NULL; + CancelBackgroundTimer(); + + // Find new and old focused clients + CAlfAppSrvSessionBase* newFocusedSession = aSession; + CAlfAppSrvSessionBase* oldFocusedSession = NULL; + + iSessionIter.SetToFirst(); + while (iSessionIter) + { + CAlfAppSrvSessionBase* session = + reinterpret_cast(iSessionIter++); + + if ( session && + !oldFocusedSession && + iLastActiveClientWg != KErrNotFound && + session->ClientWindowGroup() == iLastActiveClientWg ) + { + oldFocusedSession = session; + } + + // If found, stop the search. + if ( oldFocusedSession || iLastActiveClientWg == KErrNotFound ) + { + break; + } + // Otherwise, keep going... + } + + if ( !newFocusedSession ) + { + // Another application got the focus + // let the server follow the previous app wg + if ( oldFocusedSession ) + { + oldFocusedSession->ResetRootlayerTransformationsL(); + oldFocusedSession->FocusLostL( EFalse ); + AdjustWindowGroupPositionL( + *CHuiStatic::RootWin(), + oldFocusedSession->ClientWindowGroup(), + oldFocusedSession->PreferredWindowGroupPosition()); + } + else // this will be the case when there is only direct client connections left + { + AdjustWindowGroupPositionL(*CHuiStatic::RootWin(0),0,EAbsoluteBackground); + } + AppUi()->UpdateActiveSession( 0 ); + AppUi()->SetContainerNonFading( EFalse ); + } + else + { + // One of our clients got the focus + AdjustWindowGroupPositionL( + *CHuiStatic::RootWin(), + newFocusedSession->ClientWindowGroup(), + newFocusedSession->PreferredWindowGroupPosition() ); +#ifdef SYMBIAN_BUILD_GCE + newFocusedSession->ActivateContainerLayoutL(ETrue); +#endif // #ifdef SYMBIAN_BUILD_GCE + + TBool didFadeOutTransition = EFalse; // default, just make sure that visual trees are restored + if ( oldFocusedSession && newFocusedSession != oldFocusedSession) // switching between apps + { + if ((oldFocusedSession->ClientWindowGroup() == newFocusedSession->ParentWindowGroupId()) + || (newFocusedSession->ClientWindowGroup() == oldFocusedSession->ParentWindowGroupId() )) + { // swithching into embedded app + didFadeOutTransition = oldFocusedSession->FocusLostL( MAlfTransEffectPlugin::EContextEmbeddedExit ); + if (didFadeOutTransition) + { + didFadeOutTransition = MAlfTransEffectPlugin::EContextEmbeddedStart; + } + } + else // swithching between separate apps + { + didFadeOutTransition = oldFocusedSession->FocusLostL( MAlfTransEffectPlugin::EContextFocusLost ); + } + } + else if (!oldFocusedSession ) // New app is being launched + { // or previous app destroyed + if (aWgId == KErrNotFound) + { + didFadeOutTransition = MAlfTransEffectPlugin::EContextFocusGained; // enable default effect + } + else + { + didFadeOutTransition = MAlfTransEffectPlugin::EContextEmbeddedStart; // enable default effect + } + } + else + { + // Fot PC-lint + } + newFocusedSession->FocusGainedL( didFadeOutTransition ); + } +#ifdef SYMBIAN_BUILD_GCE +/* +#ifdef HUI_FX +*/ + // Should test if transition is running + // If transitions are disabled, no delay is needed + if ( oldFocusedSession && oldFocusedSession != newFocusedSession ) + { + if ( !newFocusedSession ) + { + iOldSession = oldFocusedSession; + StartBackgroundTimerL(iLastActiveClientWg); + } + else + { + oldFocusedSession->ActivateContainerLayoutL(EFalse); + } + } +/* +#else + if (oldFocusedSession && oldFocusedSession != newFocusedSession ) + oldFocusedSession->ActivateContainerLayoutL(EFalse); +#endif +*/ +#endif // #ifdef SYMBIAN_BUILD_GCE + } + + +// --------------------------------------------------------------------------- +// Notify window visibility observers about change +// --------------------------------------------------------------------------- +// +void CAlfAppServer::WindowVisiblityChangedL( + TUint aVisibilityFlags, + CCoeControl* aDestination ) + { + for (TInt i = 0; i < iWindowChangeObservers.Count(); i++) + { + if (iWindowChangeObservers[i].iPtr->CoeControl() == aDestination) + { + if ( aVisibilityFlags & + TWsVisibilityChangedEvent::EPartiallyVisible ) + { + iWindowChangeObservers[i].iPtr->WindowPartiallyVisible(); + } + else if ( aVisibilityFlags & + TWsVisibilityChangedEvent::EFullyVisible ) + { + iWindowChangeObservers[i].iPtr->WindowFullyVisible(); + } + else if ( aVisibilityFlags & + TWsVisibilityChangedEvent::ENotVisible ) + { + iWindowChangeObservers[i].iPtr->WindowNotVisible(); + } + else + { + // For PC-lint + } + + break; + } + } + } + +// --------------------------------------------------------------------------- +// Loads a session extension. +// --------------------------------------------------------------------------- +// +CAlfAppSrvSessionBase* CAlfAppServer::LoadServiceExtensionL(TUid aServiceType) + { + CAlfAppSrvSessionBase* newSession = 0; + // check if lib already loaded + if (ImplementationExists(aServiceType)) // no need to scan + { + newSession = NewImplementationL(aServiceType); + } + else + { + // perform plugin scan + CCleanupEcomArray* ecomInfoArray = new (ELeave) CCleanupEcomArray; + CleanupStack::PushL(ecomInfoArray); + REComSession::ListImplementationsL(TUid::Uid(K_ALF_SERVICE_INTERFACE), ecomInfoArray->iArray); + // check if plugin with implementation uid matches + TInt count = ecomInfoArray->iArray.Count(); + for (TInt ii = count-1; ii >= 0; ii-- ) + { + if ((ecomInfoArray->iArray[ii])->ImplementationUid() + == aServiceType) + { + newSession = NewImplementationL(aServiceType); + break; + } + } + CleanupStack::PopAndDestroy(); + } + + if (newSession && !iAsynchOneShot) + { // instantiate remove callback here if it does not exist yet + iAsynchOneShot = + new (ELeave) CAsyncCallBack( + TCallBack(SynchEcomImplementations, this), + EActivePriorityDefault); + } + + + return newSession; + } + +// --------------------------------------------------------------------------- +// Checks if implementation of this type has been loaded already, +// no need to perform scan if this is the case +// --------------------------------------------------------------------------- +// +TBool CAlfAppServer::ImplementationExists(TUid aServiceType) const + { + for(TInt ii = iCustomSessions.Count()-1; ii >= 0; ii--) + { + if (aServiceType==iCustomSessions[ii].iServiceUid) + { + return ETrue; + } + } + + return EFalse; + } + +// --------------------------------------------------------------------------- +// Loads and instantiates actual implementation using ECOM +// --------------------------------------------------------------------------- +// +CAlfAppSrvSessionBase* CAlfAppServer::NewImplementationL(TUid aServiceType) + { + TServiceExtension ext; + ext.iServiceUid = aServiceType; + ext.iImpl = + (CAlfAppSrvSessionBase*)REComSession::CreateImplementationL( + aServiceType, + ext.iDestructorUid, + this); + iCustomSessions.AppendL(ext); + + // set notify for changes in plugins (if it does not exist already) + if (!iEcomWatcher) + { + iEcomWatcher = CAlfEcomUtil::NewL(*this); + iEcomWatcher->Start(); + } + + return ext.iImpl; + } + +// --------------------------------------------------------------------------- +// Something has changed in ECom, check if we are affected +// --------------------------------------------------------------------------- +// +void CAlfAppServer::CheckForEcomPluginInstallUninstallL() + { + // cross-check services loaded + TInt csCount = iCustomSessions.Count(); + if (csCount) + { + CCleanupEcomArray* ecomInfoArray = new (ELeave) CCleanupEcomArray; + CleanupStack::PushL(ecomInfoArray); + REComSession::ListImplementationsL(TUid::Uid(K_ALF_SERVICE_INTERFACE), + ecomInfoArray->iArray); + // check if plugin with implementation uid matches + TInt count = ecomInfoArray->iArray.Count(); + while (csCount > 0) + { + csCount--; + TUid csUid = iCustomSessions[csCount].iServiceUid; + TBool found(EFalse); + for (TInt ii = count-1; ii >= 0; ii-- ) + { + if ((ecomInfoArray->iArray[ii])->ImplementationUid() + == csUid) + { + found = ETrue; + break; + } + } + if (!found) + { // notifies ECom about destroyed implementation + delete iCustomSessions[csCount].iImpl; + } + } + + CleanupStack::PopAndDestroy(); + } + + TInt factoryCount = iFactories.Count(); + if (factoryCount) + { + CCleanupEcomArray* ecomInfoArray = new (ELeave) CCleanupEcomArray; + CleanupStack::PushL(ecomInfoArray); + REComSession::ListImplementationsL(TUid::Uid( K_ALF_FACTORY_INTERFACE), + ecomInfoArray->iArray); + // check if plugin with implementation uid matches + TInt count = ecomInfoArray->iArray.Count(); + while (factoryCount > 0 ) + { + factoryCount--; + TUid fUid = iFactories[factoryCount].iUid; + if (fUid == KNullUid) // fixed factory + { + continue; + } + + TBool found(EFalse); + for (TInt ii = count-1; ii >= 0; ii-- ) + { + if ((ecomInfoArray->iArray[ii])->ImplementationUid() + == fUid) + { + found = ETrue; + break; + } + } + if (!found) + { // notifies ECom about destroyed implementation + NotifySessionsAboutDestroyedImplementation(iFactories[factoryCount].iUid.iUid); + iFactories[factoryCount].iImpl->Release(); + } + } + + CleanupStack::PopAndDestroy(); + } + + if (iCustomSessions.Count() == 0 && + (iFactories.Count() == 0 || (iFactories.Count() == 1 && iFactories[0].iUid == KNullUid) ) ) + { // no active extensions -> cancel notify + delete iEcomWatcher; + iEcomWatcher = 0; + } + + } + +// --------------------------------------------------------------------------- +// Appends new window visibility observer +// --------------------------------------------------------------------------- +// +EXPORT_C void CAlfAppServer::SetWindowChangeObserverL( + MWindowVisibilityObserver* aObserver, TInt aClientId) + { + iWindowChangeObservers.AppendL(TWindowChangeObserver(aObserver,aClientId)); + } + +TBool IsNewStatusPaneArchL() + { + _LIT(KS60ProductIDFile, "Series60v*.sis"); + _LIT(KROMInstallDir, "z:\\system\\install\\"); + + TFindFile ff( CHuiStatic::FsSession()); + CDir* result; + User::LeaveIfError( ff.FindWildByDir( KS60ProductIDFile, KROMInstallDir, result ) ); + CleanupStack::PushL( result ); + User::LeaveIfError( result->Sort( ESortByName|EDescending ) ); + + TInt major = (*result)[0].iName[9] - '0'; + TInt minor = (*result)[0].iName[11] - '0'; + + CleanupStack::PopAndDestroy(); // result + return ((major>3) || (major == 3 && minor >= 2)); + } + +void ResolveBdWgIdL(TInt& aId, RWsSession& aWs, CAlfAppUi& /*aAppUi*/) + { + if (!IsNewStatusPaneArchL()) + { + CArrayFixFlat* wgs = new (ELeave) CArrayFixFlat(1); + CleanupStack::PushL(wgs); + aWs.WindowGroupList(ECoeWinPriorityNormal,wgs); + TInt wgCount = wgs->Count(); + + CApaWindowGroupName* wgName = CApaWindowGroupName::NewLC(aWs); + HBufC* buf = HBufC::NewL(CApaWindowGroupName::EMaxLength); + wgName->SetWindowGroupName(buf); + + for ( TInt spPos = 0; spPos < wgCount; spPos++) + { + TPtr des = buf->Des(); + TInt err = aWs.GetWindowGroupNameFromIdentifier(wgs->At(spPos), des); + if (!err) + { + if ( wgName->Caption().Compare(EIKON_SERVER_BACKDROP_WINDOW_GROUP_NAME) == 0) + { + aId = wgs->At(spPos); + break; + } + } + } + CleanupStack::PopAndDestroy(2); // wgName, wgs + } + } + +// --------------------------------------------------------------------------- +// Creates container for session in which it holds the sub sessions. +// --------------------------------------------------------------------------- +// +CObjectCon* CAlfAppServer::NewContainerL() + { + if ( !iObjectConIx ) + { + iObjectConIx = CObjectConIx::NewL(); + // we don't have ConstructL, so this would be suitable place to do one-shot-only construction + if(CCoeEnv::Static()) + { + ResolveBdWgIdL(iBackDropWgIdentifier, *iWs, *iAppUi); + } + } + + return iObjectConIx->CreateL(); + } + +// ======== RnD FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// Logs window groups +// --------------------------------------------------------------------------- +// +void CAlfAppServer::LogWindowGroupsL() const + { +#ifdef _ALF_LOGGING + // uncomment block if you want to log the window group order. + /* + CArrayFixFlat* wgs = new (ELeave) CArrayFixFlat(4); + CleanupStack::PushL(wgs); + iWs->WindowGroupList(wgs); + const TInt focusedWg = iWs->GetFocusWindowGroup(); + + for ( TInt i = 0; i < wgs->Count() ; i++ ) + { + TThreadId threadId; + iWs->GetWindowGroupClientThreadId(wgs->At(i), threadId); + RThread thread; + if ( thread.Open(threadId) == KErrNone ) + { + TName name = thread.Name(); + TPtrC ptr(name); + if ( wgs->At(i) == focusedWg ) + { + __ALFLOGSTRING3( " [%d] wg:%d %S FOCUSED",i,wgs->At(i), &ptr ); + } + else + { + __ALFLOGSTRING3( " [%d] wg:%d %S",i,wgs->At(i), &ptr ); + } + } + } + + CleanupStack::PopAndDestroy( wgs ); + */ +#endif + } + +MAlfExtension* CAlfAppServer::CreateExtensionL(TInt aImplementationUid, TInt aImplementationId, const RMessage2 & aMessage ) + { + TAlfElementFactory* factory = 0; + + if (iFactories.Count() == 0) + { + TAlfElementFactory ef; + ef.iUid = KNullUid; + ef.iImpl = new (ELeave) TAlfFixedFactory; + ef.iDestructorUid = KNullUid; + iFactories.AppendL(ef); + } + + // Check if factory already loaded + for(TInt ii = iFactories.Count()-1; ii>=0;ii--) + { + if (iFactories[ii].iUid == TUid::Uid(aImplementationUid)) + { + factory = &iFactories[ii]; + break; + } + } + + if (!factory) + { + // Todo should actually perform interface based scan and check that possible candidate (if any) + // implements correct interface also + // K_ALF_FACTORY_INTERFACE + + TAlfElementFactory ef; + ef.iUid = TUid::Uid(aImplementationUid); + ef.iImpl = (MAlfExtensionFactory*)REComSession::CreateImplementationL( + ef.iUid, + ef.iDestructorUid); + User::LeaveIfNull(ef.iImpl); + iFactories.AppendL(ef); + factory = &iFactories[iFactories.Count()-1]; + + if (!iEcomWatcher) + { + iEcomWatcher = CAlfEcomUtil::NewL(*this); + iEcomWatcher->Start(); + } + } + + HBufC8* inBuf = 0; + TInt paramsLenght = aMessage.GetDesLength(1); + if (paramsLenght > 0) + { + inBuf = HBufC8::NewLC(paramsLenght); + TPtr8 ptr = inBuf->Des(); + aMessage.ReadL(1,ptr); + } + + // Create implementation + MAlfExtension* object = 0; + if (inBuf) + { + object = factory->iImpl->CreateExtensionL(aImplementationId, inBuf->Des(), *((CAlfAppSrvSessionBase*)aMessage.Session())); + CleanupStack::PopAndDestroy(inBuf); + } + else + { + object = factory->iImpl->CreateExtensionL(aImplementationId, KNullDesC8, *((CAlfAppSrvSessionBase*)aMessage.Session())); + } + + factory->iAccessCount++; + + if (!object) // actually factory should leave + { + User::Leave(KErrNotSupported); + } + + return object; + } + + +void CAlfAppServer::DestroyedObject(TInt aFactoryUid) + { + if (!aFactoryUid) + { + return; + } + + TInt ii = -1; + for ( ii = iFactories.Count()-1; ii >= 0; ii--) + { + if (iFactories[ii] == aFactoryUid) + { + iFactories[ii].iAccessCount--; + if (iFactories[ii].iAccessCount == 0) + { + iFactories[ii].iImpl->Release(); + if (iFactories[ii].iDestructorUid.iUid) + { + REComSession::DestroyedImplementation( + iFactories[ii].iDestructorUid); + } + iFactories.Remove(ii); + User::Heap().Compress(); + } + break; + } + } + } + +void CAlfAppServer::NotifySessionsAboutDestroyedImplementation(TInt aFactoryUid) + { + iSessionIter.SetToFirst(); + while (iSessionIter) + { + CAlfAppSrvSessionBase* session = + reinterpret_cast(iSessionIter++); + + session->FactoryDestroyed(aFactoryUid); + } + } + + +// --------------------------------------------------------------------------- +// Create a transition effect instance for the server if it does not exist +// --------------------------------------------------------------------------- +// +void CAlfAppServer::CreateTransitionEffectsL() + { + if ( iTransitionEffects == NULL ) + { + iTransitionEffects = CAlfSrvTransEffect::NewL(); + } + } + + +// --------------------------------------------------------------------------- +// Return a pointer to the transition effects instance +// --------------------------------------------------------------------------- +// +CAlfSrvTransEffect* CAlfAppServer::TransitionEffects() + { + return( iTransitionEffects ); + } + +// ----------------------------------------------------------------------------- +// Create Tfx Server client plugin and make a connection to Tfx Server +// ----------------------------------------------------------------------------- +// +TInt CAlfAppServer::CreateTfxServerPlugin() + { + TInt err = KErrNone; + + #ifdef TFXSERVER_API_V2 + if (iTfxServer == NULL) + { + TUid implementationUidSrv = { KTfxSrv2EcomImpl }; + TRAP(err, iTfxServer = (MTransitionServer2*) + REComSession::CreateImplementationL( implementationUidSrv, iTfxServerEComDestructorUID, + NULL )); + } + if (!err && (iTfxServer != NULL)) + { + if (!iTfxServer->IsConnected()) + { + err = iTfxServer->Connect(); + } + } + #endif + + return err; + } + + +// ----------------------------------------------------------------------------- +// Return Tfx Server client pointer if possible +// ----------------------------------------------------------------------------- +// +MTransitionServer2* CAlfAppServer::TfxServer() + { + TInt err = KErrNone; + #ifdef TFXSERVER_API_V2 + if (iTfxServer && !iTfxServer->IsConnected()) + { + err = iTfxServer->Connect(); + } + #endif + return (err ? NULL : iTfxServer); + } + + +// --------------------------------------------------------------------------- +// Triggers sending a system event to clients +// --------------------------------------------------------------------------- +// +void CAlfAppServer::TriggerSystemEvent(TInt aEvent) + { + iSessionIter.SetToFirst(); + while (iSessionIter) + { + CAlfAppSrvSessionBase* session = + reinterpret_cast(iSessionIter++); + + session->TriggerSystemEvent(aEvent); + } + } + +TBool CrossCheckForeground(TAny* aThis) + { + CAlfAppServer* me = (CAlfAppServer*)aThis; + +//#ifdef HUI_FX + if ( me->iOldSession ) + { + TRAP_IGNORE( me->iOldSession->ActivateContainerLayoutL(EFalse); + me->iOldSession = NULL; + me->CancelBackgroundTimer(); ); + return EFalse; + } +//#endif + TRAP_IGNORE(me->FocusedWindowGroupChangedL(0)) // cancels the timer + return EFalse; + } + +void CAlfAppServer::StartBackgroundTimerL(TInt aClientWg) + { + if (aClientWg != iLastActiveClientWg) + { + CancelBackgroundTimer(); + return; + } + + if (!iBackgroundTimer) + { + iBackgroundTimer = CPeriodic::NewL(EPriorityNormal); + } + CancelBackgroundTimer(); // reset the time in case of active timers +/* +#ifdef HUI_FX +*/ + if ( iOldSession ) + { + // longer delay to allow the application to start properly + iBackgroundTimer->Start(1500000,0,TCallBack(CrossCheckForeground, this)); + } + else + { + iBackgroundTimer->Start(20000,0,TCallBack(CrossCheckForeground, this)); + } +/* +#else + iBackgroundTimer->Start(20000,0,TCallBack(CrossCheckForeground, this)); +#endif +*/ + } + +void CAlfAppServer::CancelBackgroundTimer() + { + if(iBackgroundTimer) + { + iBackgroundTimer->Cancel(); + } + } + +TInt CAlfAppServer::CommonCommandBatchBufferMaxLength() const + { + return iCommonCommandBatchBuffer->Des().MaxLength(); + } + +TBool CAlfAppServer::AcquireCommonCommandBatchBuffer( TPtr8& aBuffer ) + { + TBool result = EFalse; + + if ( !iCommonCommandBatchBufferInUse ) + { + // In practice, iCommonCommandBatchBufferInUse might be true only + // if MAlfExtension::HandleCmdL starts active scheduler. + // (but then ServiceL should not be called again) + + result = ETrue; + iCommonCommandBatchBufferInUse = ETrue; + aBuffer.Set( iCommonCommandBatchBuffer->Des() ); + aBuffer.Zero(); + } + + return result; + } + +void CAlfAppServer::ReleaseCommonCommandBatchBuffer() + { + iCommonCommandBatchBufferInUse = EFalse; + } + +CAlfSrvTextureManager& CAlfAppServer::TextureManager() + { + return *iTextureManager; + } + +CAlfSrvScreenBufferManager& CAlfAppServer::ScreenBufferManager() + { + return *iScreenBufferManager; + } + +TBool CAlfAppServer::AlfClientHasFocus() + { + TBool result = EFalse; + TInt focusWindowGroupId = WsSession().GetFocusWindowGroup(); + + iSessionIter.SetToFirst(); + while (iSessionIter) + { + CAlfAppSrvSessionBase* session = reinterpret_cast(iSessionIter++); + if ( session && session->ClientWindowGroup() == focusWindowGroupId ) + { + result = ETrue; + break; + } + } + return result; + } + +CAlfAppSrvSessionBase* CAlfAppServer::UpMostClientAboveWg( TInt aWgId ) + { + if (!iAppUi && !CCoeEnv::Static()) + return 0; + + CAlfAppSrvSessionBase* sessionAboveGivenWgId = NULL; + + CArrayFixFlat* wgs = new CArrayFixFlat(4); + if ( wgs ) + { + iWs->WindowGroupList( 0, wgs); + TInt topmostWgId = wgs->At( 0 ); + for ( TInt ordinal = 0 ; ordinal < wgs->Count(); ordinal++ ) + { + iSessionIter.SetToFirst(); + if( sessionAboveGivenWgId || aWgId == wgs->At( ordinal ) ) + { + // either above client app's wg was found or there wasn't any client app's wg above given aWgId + break; + } + while (iSessionIter) + { + CAlfAppSrvSessionBase* session = reinterpret_cast(iSessionIter++); + if ( session && + session->ClientWindowGroup() == topmostWgId ) + { + sessionAboveGivenWgId = session; + break; + } + } + } + } + delete wgs; + return sessionAboveGivenWgId; + } +