diff -r 000000000000 -r 5d03bc08d59c windowing/windowserver/nga/SERVER/SERVER.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/windowing/windowserver/nga/SERVER/SERVER.CPP Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,956 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Window server 'server' class +// +// + +#include "server.h" +#include "panics.h" +#include "wstop.h" +#include "EVENT.H" +#include +#include +#include +#include "inifile.h" +#include "wspluginmanager.h" +#include "graphics/windowserverconstants.h" + +GLREF_D CDebugLogBase *wsDebugLog; + +const TUint KRangeCount = 1; +// We use a lot of 64 bit time calculations, but a periodic can only cope with signed 32 bit times +// which gives them a limit of about 35 minutes. +// Fortunately, our animtions are safe if redrawn early. Every half an hour isn't going to hurt. +const TTimeIntervalMicroSeconds KHalfHour = 30 * 60 * 1000 * 1000; + +const TInt KWsServRanges[KRangeCount] = + { + 0 + }; + +const TUint8 KElementsIndex[KRangeCount] = + { + CPolicyServer::EAlwaysPass, + }; + +const CPolicyServer::TPolicyElement KPolicyElements[] = + { + {_INIT_SECURITY_POLICY_C1(ECapabilityPowerMgmt), CPolicyServer::EFailClient}, + {_INIT_SECURITY_POLICY_C1(ECapabilitySwEvent), CPolicyServer::EFailClient}, + {_INIT_SECURITY_POLICY_C1(ECapabilityWriteDeviceData), CPolicyServer::EFailClient} + }; + +const CPolicyServer::TPolicy KWsServPolicy = + { + CPolicyServer::EAlwaysPass, + KRangeCount, + KWsServRanges, + KElementsIndex, + KPolicyElements + }; + +// CWindowServer::CDefaultAnimationScheduler \\\\\\\\\\\\\\\\\\\\\\\\\\\ + +class CWindowServer::CDefaultAnimationScheduler: public CBase, public MWsAnimationScheduler + { + // Associates a screen number with a CActiveSchedulerWait intance. This is used to + // achieve synchronous update completion on a specific screen. + class CScreenUpdateWait : public CActiveSchedulerWait + { + public: + CScreenUpdateWait(TInt aScreenNumber) : iScreenNumber (aScreenNumber) {} + TInt iScreenNumber; + }; + + struct TScreenUpdateDetails + { + CWindowServer::CDefaultAnimationScheduler* iScheduler; + TInt iScreenNumber; + }; + + struct TSchedule + { + MWsScreen* iScreen; // used as a unique index, searching with FindInUnsignedKeyOrder + TInt iScreenNumber; + TBool iScheduled; + TTime iWhen; + TBool iRedraw; + }; +public: + enum TInactivityBehaviour + { + EStopAnimation, + EStopAllDrawing, + EIgnore, + }; + class CScreenState; + + CDefaultAnimationScheduler(MWsGraphicDrawerEnvironment& aEnv); + ~CDefaultAnimationScheduler(); + void ConstructL(); //LeaveScan: member of nested class declaration + // implementing MWsAnimationScheduler + void ScheduleAnimation(MWsScreen& aScreen,const TTime& aWhen); + void UnscheduleAnimation(MWsScreen& aScreen); + void Invalidate(const TGraphicDrawerId& aId); + void OnInactive(); + void OnActive(); + void ScheduleRedraw(MWsScreen& aScreen,const TTime& aWhen); + void DoRedrawNow(MWsScreen& aScreen); +private: + static TBool OnIdleCallBack(TAny* aAny); + void ScheduleUpdate (TInt aScreenNumber, TBool aForce); + void OnIdleCallBack(TBool aForce); + static TBool InvokeDueAnimation(TAny* aAny); + void RedrawAllInvalidatedRegions (TInt aScreen); + TSchedule* GetScheduledScreenUpdate(TInt aScreen); + void InvokeDueAnimation(TInt aScreen); + void ProcessUpdateCompletion (TInt aScreenNumber); + TInt ScreenNumber(MWsScreen& aScreen) const; + TTimeIntervalMicroSeconds GetDueDelta (TBool aForceRedraw, TSchedule* aScheduledUpdate); +private: + RPointerArray iRedrawWaitLoop; + RPointerArray iScreenState; + MWsGraphicDrawerEnvironment& iEnv; + static const TInt64 KRedrawGrace; + static const TInt64 KAnimationGrace; + CAsyncCallBack* iIdleInitiator; + TBool iInRedrawNow; + RArray iSchedule; + TBool iInactive; + TBool iInactiveDraws; + TBool iRedrawScheduled; + TInt64 iRedrawGracePeriod; + TInt64 iAnimationGracePeriod; + TInactivityBehaviour iInactivityBehaviour; + }; + +class CWindowServer::CDefaultAnimationScheduler::CScreenState : public CActive + { +public: + static CScreenState* NewL (CDefaultAnimationScheduler* aScheduler, TInt aScreenOrdinal); + ~CScreenState(); + void SetActive (); + + CPeriodic* iUpdateOn; + TTime iExpectedTickTime; + TScreenUpdateDetails iScreenUpdateDetails; + RArray iInvalidated; + TBool iInvalidateAll; + +private: + CScreenState (CDefaultAnimationScheduler* aScheduler, TInt aScreenOrdinal); + void ConstructL (); + + void RunL(); + void DoCancel() + { + TRequestStatus* tmpTRS = &iStatus; + User::RequestComplete(tmpTRS, KErrNone); + }; + }; + +// If using the default animation scheduler on a device, these two numbers may be worth tweaking in the inifile +// However, both are maximum periods - wserv will go faster than either if nothing else is using the system. +const TInt64 CWindowServer::CDefaultAnimationScheduler::KRedrawGrace = 0; // do redraws immediately +const TInt64 CWindowServer::CDefaultAnimationScheduler::KAnimationGrace = 0; // do animation redraws immediately + +CWindowServer::CDefaultAnimationScheduler::CDefaultAnimationScheduler(MWsGraphicDrawerEnvironment& aEnv): + iEnv(aEnv), iSchedule(1,_FOFF(TSchedule,iScreen)) + { + } + +CWindowServer::CDefaultAnimationScheduler::~CDefaultAnimationScheduler() + { + iSchedule.Close(); + delete iIdleInitiator; + + TInt screenCount = iScreenState.Count(); + for (TInt ii = 0; ii < screenCount; ii++) + delete iScreenState[ii]; + + iScreenState.Close(); + + // Destroy the redraw wait loops associated each screen, and close + // the associated Array objects. + TInt waitLoopCount = iRedrawWaitLoop.Count(); + for (TInt waitLoop = 0; waitLoop < waitLoopCount; waitLoop++) + delete iRedrawWaitLoop[waitLoop]; + iRedrawWaitLoop.Close(); + } + +void CWindowServer::CDefaultAnimationScheduler::ConstructL() + { + _LIT(KOnInactive,"ONINACTIVE"); + _LIT(KStopAnimation,"STOPANIMATION"); + _LIT(KStopAllDrawing,"STOPALLDRAWING"); + _LIT(KIgnore,"IGNORE"); + + TPtrC inactivityBehaviourString; + WsIniFile->FindVar(KOnInactive,inactivityBehaviourString); + if(inactivityBehaviourString.CompareF(KStopAnimation)==0) + iInactivityBehaviour = EStopAnimation; + else if(inactivityBehaviourString.CompareF(KStopAllDrawing)==0) + iInactivityBehaviour = EStopAllDrawing; + else if(inactivityBehaviourString.CompareF(KIgnore)==0) + iInactivityBehaviour = EIgnore; + + _LIT(KRedrawGracePeriod, "REDRAWGRACEPERIOD"); + TInt tmp = KRedrawGrace; + WsIniFile->FindVar(KRedrawGracePeriod, tmp); + iRedrawGracePeriod = tmp; + + _LIT(KAnimationGracePeriod, "ANIMATIONGRACEPERIOD"); + tmp = KAnimationGrace; + WsIniFile->FindVar(KAnimationGracePeriod, tmp); + iAnimationGracePeriod = tmp; + + iIdleInitiator = new(ELeave) CAsyncCallBack(TCallBack(OnIdleCallBack,this),EWsGraphicAnimateAwaitIdlePriority); + + TInt screenCount; + User::LeaveIfError(HAL::Get( HAL::EDisplayNumberOfScreens, screenCount)); + for (TInt i = 0; i < screenCount; i++) + { + CScreenState* screenState = CScreenState::NewL (this, i); + CleanupStack::PushL(screenState); + iScreenState.AppendL (screenState); + CleanupStack::Pop(screenState); + } + + + // Ensure that the wait loop array has some allocated slots, making it highly + // unlikely that Append() will fail due to OOM. + iRedrawWaitLoop.ReserveL (8); + } + +void CWindowServer::CDefaultAnimationScheduler::Invalidate(const TGraphicDrawerId& aId) + { + const TInt screenCount = iEnv.ScreenCount(); + for(TInt ii = 0; ii < screenCount; ii++) + { + CScreenState* screenState = iScreenState[ii]; + if(!screenState->iInvalidateAll) + { + switch(screenState->iInvalidated.InsertInOrder(aId,TLinearOrder(TGraphicDrawerId::Compare))) + { + case KErrNone: + case KErrAlreadyExists: + break; + default: + screenState->iInvalidateAll = ETrue; + screenState->iInvalidated.Reset(); + } + } + } + iIdleInitiator->CallBack(); + } + +CWindowServer::CDefaultAnimationScheduler::CScreenState::CScreenState (CDefaultAnimationScheduler* aScheduler, TInt aScreenNumber): + CActive(EComposeCompletePriority) + { + iScreenUpdateDetails.iScheduler = aScheduler; + iScreenUpdateDetails.iScreenNumber = aScreenNumber; + } + +CWindowServer::CDefaultAnimationScheduler::CScreenState* +CWindowServer::CDefaultAnimationScheduler::CScreenState::NewL (CDefaultAnimationScheduler* aScheduler, TInt aScreenOrdinal) + { + CScreenState* self = new(ELeave)CScreenState(aScheduler, aScreenOrdinal); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +void CWindowServer::CDefaultAnimationScheduler::CScreenState::ConstructL () + { + iUpdateOn = CPeriodic::NewL(EComposeCompletePriority); + CActiveScheduler::Add(this); + } + +CWindowServer::CDefaultAnimationScheduler::CScreenState::~CScreenState() + { + CActive::Cancel(); + iInvalidated.Close(); + delete iUpdateOn; + } + +void CWindowServer::CDefaultAnimationScheduler::CScreenState::SetActive() + { + CActive::SetActive (); + } + +/** +Invoked when the rendering pipline signals that it is ready to recieve updated. +*/ +void CWindowServer::CDefaultAnimationScheduler::CScreenState::RunL() + { + iScreenUpdateDetails.iScheduler->ProcessUpdateCompletion (iScreenUpdateDetails.iScreenNumber); + } + +void CWindowServer::CDefaultAnimationScheduler::ProcessUpdateCompletion (TInt aScreenNumber) + { + // Stop all waitloops related to the specified screen. + TInt waitLoopCount = iRedrawWaitLoop.Count(); + for (TInt waitLoop = 0; waitLoop < waitLoopCount; waitLoop++) + if (iRedrawWaitLoop[waitLoop]->IsStarted() && (iRedrawWaitLoop[waitLoop]->iScreenNumber == aScreenNumber)) + iRedrawWaitLoop[waitLoop]->AsyncStop(); + + // Perform any outstanding redraws on the specified screen. + ScheduleUpdate (aScreenNumber, ETrue); + } + +/** +Switch to deactivate animation or drawing (based on setting of iInactivityBehaviour). +See InvokeDueAnimation(). +*/ +void CWindowServer::CDefaultAnimationScheduler::OnInactive() + { + iInactive = ETrue; + } + +/** +Switch to deactivate/activate animation or drawing (based on setting of iInactivityBehaviour). +See InvokeDueAnimation(). +*/ +void CWindowServer::CDefaultAnimationScheduler::OnActive() + { + iInactive = EFalse; + if(iInactiveDraws) + { + iInactiveDraws = EFalse; + iIdleInitiator->CallBack(); + } + } + +void CWindowServer::CDefaultAnimationScheduler::ScheduleRedraw(MWsScreen& aScreen,const TTime& aWhen) + { + iRedrawScheduled = ETrue; + ScheduleAnimation(aScreen, aWhen); + } + +/** +Given a MWsScreen pointer, return an integer value representing the ordinal position +of the screen in the Window Server. +*/ +TInt CWindowServer::CDefaultAnimationScheduler::ScreenNumber(MWsScreen& aScreen) const + { + TInt numberOfScreens = CWsTop::NumberOfScreens(); + TInt theScreen; + + for (theScreen = 0; theScreen < numberOfScreens; theScreen++) + if (CWsTop::Screen(theScreen) == &aScreen) + break; + + WS_ASSERT_DEBUG(theScreen < numberOfScreens, EWsPanicWsGraphic); + return theScreen; + } + +/** +Perform redraw and return only when completed. +NOTE: This method uses CActiveSchedulerWait to run a "modal wait loop" while the + redraw complete signal is pending. When the signal is recieved, AsyncStop() is + invoked on all active wait loops for the signalling screen. +*/ +void CWindowServer::CDefaultAnimationScheduler::DoRedrawNow(MWsScreen& aScreen) + { + TInt screenNumber = ScreenNumber (aScreen); + TInt redrawCount = 0; + + // redrawCount is the number of times we should wait for redraws to complete. + // If a redraw is not currently active then we need to wait (at most) once: for + // any outstanding scheduled update to complete. + // If a redraw is currently active then we need to wait (at most) twice: once for + // the current update to complete, and once for any outstanding scheduled update to complete. + if (!iScreenState[screenNumber]->IsActive()) + { + // No animation in progress, so force a redraw of due updates. + ScheduleUpdate(screenNumber, ETrue); + + // If there is still nothing drawing, set redrawCount to zero to make sure we do not wait. + if (!iScreenState[screenNumber]->IsActive()) + redrawCount = 0; + else + redrawCount = 1; + } + else + redrawCount = 2; + + // Wait for the sepecified number of redraws. + if (redrawCount) + { + // Allocate the wait loop on the stack so we are not subject to heap OOM. + TBuf8 buf; + Mem::FillZ(&buf, sizeof (CScreenUpdateWait)); + CScreenUpdateWait* waitLoop = new (&buf) CScreenUpdateWait(screenNumber); + if (iRedrawWaitLoop.Append(waitLoop) == KErrNone) + { + // Run the active scheduler while updates are active + while (redrawCount-- && iScreenState[screenNumber]->IsActive()) + waitLoop->Start(); + + iRedrawWaitLoop.Remove(iRedrawWaitLoop.Count() - 1); + } + waitLoop->~CScreenUpdateWait(); + } + } + +/** +Schedule an update for a specific screen at a given point in time. +*/ +void CWindowServer::CDefaultAnimationScheduler::ScheduleAnimation(MWsScreen& aScreen, const TTime& aWhen) + { + TSchedule schedule; + schedule.iScreen = &aScreen; + schedule.iScheduled = ETrue; + schedule.iWhen = aWhen; + schedule.iScreenNumber = ScreenNumber (aScreen); + schedule.iRedraw = iRedrawScheduled; + iRedrawScheduled = EFalse; + TBool ok = EFalse; + const TInt idx = iSchedule.FindInUnsignedKeyOrder(schedule); + if(0 <= idx) + { + TSchedule& currSchedule=iSchedule[idx]; + if(currSchedule.iScheduled) + { + if(currSchedule.iWhen > aWhen) + { + currSchedule.iWhen = aWhen; + } + } + else + { + currSchedule = schedule; + } + ok = ETrue; + } + else + ok = (KErrNone == iSchedule.InsertInUnsignedKeyOrder(schedule)); + + if(ok) + iIdleInitiator->CallBack(); + } + +void CWindowServer::CDefaultAnimationScheduler::UnscheduleAnimation(MWsScreen& aScreen) + { + TSchedule schedule; + schedule.iScreen = &aScreen; + const TInt idx = iSchedule.FindInUnsignedKeyOrder(schedule); + if(0 <= idx) + iSchedule[idx].iScheduled = EFalse; + } + +TBool CWindowServer::CDefaultAnimationScheduler::OnIdleCallBack(TAny* aAny) + { + WS_ASSERT_DEBUG(aAny, EWsPanicWsGraphic); + + if(aAny) + static_cast(aAny)->OnIdleCallBack(EFalse); + + return EFalse; //ignored by caller + } + +void CWindowServer::CDefaultAnimationScheduler::OnIdleCallBack(TBool aForce) + { + const TInt screenCount = iEnv.ScreenCount(); + for(TInt ii = 0; ii < screenCount; ii++) + ScheduleUpdate (ii, aForce); + } + + + +/** +@return The number of microseconds (from now) that the specified scheduled update should be run at. This +takes into account any set grace period and protects the scheduler from entering an infinite loop servicing +animations with back-to-back frame updates. +*/ +TTimeIntervalMicroSeconds CWindowServer::CDefaultAnimationScheduler::GetDueDelta (TBool aForceRedraw, TSchedule* aScheduledUpdate) + { + WS_ASSERT_DEBUG(aScheduledUpdate, EWsPanicWsGraphic); + WS_ASSERT_DEBUG(aScheduledUpdate->iScheduled, EWsPanicWsGraphic); + + TTime now; + TInt64 grace = I64LIT(0); + TTimeIntervalMicroSeconds thisUpdateDueIn = I64LIT(0); //Microseconds from now + + // Only use grace periods if not forcing due updates. + if (!aForceRedraw) + { + if (aScheduledUpdate->iRedraw) + grace = iRedrawGracePeriod; + else + grace = iAnimationGracePeriod; + } + + now.UniversalTime(); + thisUpdateDueIn = aScheduledUpdate->iWhen.MicroSecondsFrom(now); + + // Add the grace period if the update is due in less time than the grace period. + if (thisUpdateDueIn < grace) + thisUpdateDueIn = grace; + else if (thisUpdateDueIn > KHalfHour) + thisUpdateDueIn = KHalfHour; + + return thisUpdateDueIn; + } + +/** +Schedule an actual screen update at the point in time at which it is due. The due time may be modified by +this method based on any "grace period" values. + +@param aScreen Screen number to update. +@param aForceRedraw Force redraws that are due. This causes grace periods not to be used. +*/ +void CWindowServer::CDefaultAnimationScheduler::ScheduleUpdate (TInt aScreenNumber, TBool aForceRedraw) + { + // Schedule updates for any invalidated regions. + RedrawAllInvalidatedRegions (aScreenNumber); + + TSchedule* scheduledUpdate = GetScheduledScreenUpdate(aScreenNumber); + if (scheduledUpdate) + { + WS_ASSERT_DEBUG(scheduledUpdate->iScheduled, EWsPanicWsGraphic); + WS_ASSERT_DEBUG(aScreenNumber < iScreenState.Count(), EWsPanicWsGraphic); + + CScreenState& screenState = *iScreenState[aScreenNumber]; + + // Initiate redraw if scheduled and not currently updating the display. + if(!screenState.IsActive()) + { + TTimeIntervalMicroSeconds thisUpdateDueIn = + GetDueDelta (aForceRedraw, scheduledUpdate); + + // Reschedule any preexisting update if this one is due earlier. + // If this update is not due earlier than a preexisting update then + // there is nothing to do - just let the pending update occur. + TTime now; + now.UniversalTime(); + TBool performUpdate = ETrue; + if(screenState.iUpdateOn->IsActive()) + { + if (thisUpdateDueIn < screenState.iExpectedTickTime.MicroSecondsFrom(now)) + screenState.iUpdateOn->Cancel(); + else + performUpdate = EFalse; + } + + if (performUpdate) + { + if (thisUpdateDueIn.Int64() == 0) // Perform an immediate update if we are due. + { + screenState.iExpectedTickTime = now; + InvokeDueAnimation(aScreenNumber); + } + else // Schedule the tick at the appropriate time. + { + WS_ASSERT_DEBUG(thisUpdateDueIn.Int64() > 0, EWsPanicWsGraphic); + screenState.iExpectedTickTime = now + thisUpdateDueIn; + screenState.iUpdateOn->Start(thisUpdateDueIn.Int64(),0,TCallBack(InvokeDueAnimation, &screenState.iScreenUpdateDetails)); + } + } + } + } + } + +/** +@return A pointer to the scheduled update details currently associated with the specified screen. + If there is no scheduled update then NULL is returned. +@note There is only ever one scheduled update per screen. +*/ +CWindowServer::CDefaultAnimationScheduler::TSchedule* CWindowServer::CDefaultAnimationScheduler::GetScheduledScreenUpdate(TInt aScreenNumber) + { + TSchedule* result = NULL; + const TInt count = iSchedule.Count(); + for(TInt ii = 0; ii < count; ii++) + { + if (iSchedule[ii].iScreenNumber == aScreenNumber) + { + if (iSchedule[ii].iScheduled) + result = &iSchedule[ii]; + break; + } + } + + return result; + } + +/** +Redraw invalidated graphic IDs. If invalid regions exist, this will cause ScheduleRedraw() to be invoked. +*/ +void CWindowServer::CDefaultAnimationScheduler::RedrawAllInvalidatedRegions (TInt aScreen) + { + WS_ASSERT_DEBUG(iScreenState.Count() > aScreen, EWsPanicWsGraphic); + + CScreenState& screenState = *iScreenState[aScreen]; + if(screenState.iInvalidateAll || screenState.iInvalidated.Count()) + { + const TArray invalidArray = screenState.iInvalidated.Array(); + MWsScreen* screen = iEnv.Screen(aScreen); + WS_ASSERT_DEBUG(screen, EWsPanicWsGraphic); + if(screen) + { + if(screenState.iInvalidateAll) + Redraw(*screen); + else + RedrawInvalid(*screen, screenState.iInvalidated.Array()); + } + screenState.iInvalidateAll = EFalse; + } + screenState.iInvalidated.Reset(); + } + +TBool CWindowServer::CDefaultAnimationScheduler::InvokeDueAnimation(TAny* aAny) + { + WS_ASSERT_DEBUG(aAny, EWsPanicWsGraphic); + TScreenUpdateDetails* args = reinterpret_cast(aAny); + if(args) + args->iScheduler->InvokeDueAnimation (args->iScreenNumber); + + return EFalse; + } + +void CWindowServer::CDefaultAnimationScheduler::InvokeDueAnimation(TInt aScreen) + { + WS_ASSERT_DEBUG(aScreen < iScreenState.Count(), EWsPanicWsGraphic); + CScreenState& screenState = *iScreenState[aScreen]; + WS_ASSERT_DEBUG(!screenState.IsActive(), EWsPanicWsGraphic); + + // All updates are driven through ScheduleRedraw() and ScheduleAnimation(). + screenState.iUpdateOn->Cancel(); + + TSchedule* scheduledUpdate = GetScheduledScreenUpdate(aScreen); + if (scheduledUpdate) + { + WS_ASSERT_DEBUG(scheduledUpdate->iScheduled, EWsPanicWsGraphic); + + // Honour any flags that indicate we should not redraw. + switch(iInactivityBehaviour) + { + case EStopAnimation : + // Stop server side drawing. Only the client may redraw if iInactive is set. + if(iInactive && !scheduledUpdate->iRedraw) + { + iInactiveDraws = ETrue; + return; + } + break; + case EStopAllDrawing : + // Stop both client and server side drawing. + if(iInactive) + { + iInactiveDraws = ETrue; + return; + } + break; + case EIgnore : + break; + default : + WS_ASSERT_DEBUG(EFalse, EWsPanicWsGraphic); + break; + } + + scheduledUpdate->iScheduled = EFalse; + screenState.SetActive(); + Animate(*scheduledUpdate->iScreen, &(screenState.iStatus)); + } + } + +// CWindowServer::CServer \\\\\\\\\\\\\\\\\\\\\\ + +class CWindowServer::CServer : public CPolicyServer + { +public: + static CServer* NewL() + { + return new(ELeave) CServer; + } + void StartL() + { + CPolicyServer::StartL(KWSERVServerName); + } + TInt SessionCount() + { + iSessionIter.SetToFirst(); + TInt count=0; + while(iSessionIter++) + ++count; + return(count); + } + +public: //from CPolicyServer + /** Creates a new client for this server. */ + CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const + { + TVersion v(KWservMajorVersionNumber, KWservMinorVersionNumber, KWservBuildVersionNumber); + if (User::QueryVersionSupported(v, aVersion)==EFalse) + User::Leave(KErrNotSupported); + RThread thread; + User::LeaveIfError(aMessage.Client(thread)); + return(new(ELeave) CWsClient(thread)); + } +private: + CServer() : CPolicyServer(EMainServerPriority, KWsServPolicy) + {} + }; + + +// CWindowServer \\\\\\\\\\\\\\\\\\\\\\\\\\\ + +CWindowServer *CWindowServer::NewL() +// +// Create a new CWindowServer. +// + { + CWindowServer* self = new(ELeave) CWindowServer(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CWindowServer::CWindowServer() +// +// Constructor. +// + { + } + +CWindowServer::~CWindowServer() + { + delete iServer; + + iMemoryReleases.Reset(); + WS_ASSERT_DEBUG(iDrawerMasterIndex.IsEmpty(), EWsPanicWsGraphic); + iDrawerMasterIndex.Close(); + + delete iDefaultAnimationScheduler; + iDefaultAnimationScheduler = NULL; //might be called from clients during server destruction + iCustomAnimationScheduler = NULL; // not owned + } + +void CWindowServer::ConstructL() + { + iServer = CServer::NewL(); + CWsTop::PluginManager()->InitializePluginsL(*this); // plugins are loaded and own by CWsTop + iDefaultAnimationScheduler = new(ELeave) CDefaultAnimationScheduler(*this); + iDefaultAnimationScheduler->ConstructL(); + RegisterMemoryRelease(this); + } + +void CWindowServer::StartL() + { + iServer->StartL(); + } + +void CWindowServer::SetPinClientDescriptors(TBool aPin) + { + iServer->SetPinClientDescriptors(aPin); + } + +TInt CWindowServer::SessionCount() + { + return iServer->SessionCount(); + } + +const CWsGraphicDrawer* CWindowServer::ResolveGraphic(const TGraphicDrawerId& aId) const + { + return iDrawerMasterIndex.ResolveGraphic(aId); + } + +void CWindowServer::Invalidate(const TGraphicDrawerId& aId) + { + AnimationScheduler()->Invalidate(aId); + } + +TInt CWindowServer::ScreenCount() const + { + return CWsTop::NumberOfScreens(); + } + +MWsScreen* CWindowServer::Screen(TInt aIndex) + { + if((aIndex >= 0) && (aIndex < ScreenCount())) + { + return CWsTop::Screen(aIndex); + } + return NULL; + } + +const MWsScreen* CWindowServer::Screen(TInt aIndex) const + { + if((aIndex >= 0) && (aIndex < ScreenCount())) + { + return CWsTop::Screen(aIndex); + } + return NULL; + } + +/** +Custom Animation Scheduler +*/ +TBool CWindowServer::SetCustomAnimationScheduler(MWsAnimationScheduler* aScheduler) + { + if(!iCustomAnimationScheduler && aScheduler) + { + iCustomAnimationScheduler = aScheduler; + return ETrue; + } + return EFalse; + } + +TBool CWindowServer::HasCustomAnimationScheduler() const + { + return !!iCustomAnimationScheduler; + } + +TBool CWindowServer::ClearCustomAnimationScheduler(MWsAnimationScheduler* aCurrentScheduler) + { + if(iCustomAnimationScheduler && (iCustomAnimationScheduler == aCurrentScheduler)) + { + iCustomAnimationScheduler = NULL; + return ETrue; + } + return EFalse; + } + +MWsAnimationScheduler* CWindowServer::AnimationScheduler() + { + if(iCustomAnimationScheduler) + { + return iCustomAnimationScheduler; + } + return iDefaultAnimationScheduler; + } + +TInt CWindowServer::RegisterEventHandler(CWsGraphicDrawer* aDrawer, MWsEventHandler* aHandler, TUint32 aEventMask) + { + if (!aDrawer || !aHandler || aEventMask==0) + return KErrArgument; + TInt err = TWindowServerEvent::RegisterDrawerHandler(aDrawer, aEventMask); + if (err != KErrNone) + return err; + aDrawer->SetEventHandler(aHandler); + return KErrNone; + } + +TInt CWindowServer::UnregisterEventHandler(CWsGraphicDrawer* aDrawer) + { + if (!aDrawer || (aDrawer && !aDrawer->HasEventHandler())) + return KErrArgument; + TInt err = TWindowServerEvent::UnregisterDrawerHandler(aDrawer); + if (err != KErrNone) + return err; + aDrawer->SetEventHandler(NULL); + return KErrNone; + } + +TInt CWindowServer::RegisterWsEventHandler(MWsEventHandler* aHandler, TUint32 aEventMask) + { + if (!aHandler || aEventMask==0) + return KErrArgument; + return TWindowServerEvent::RegisterWsEventHandler(aHandler, aEventMask); + } + +TInt CWindowServer::UnregisterWsEventHandler(MWsEventHandler* aHandler) + { + return TWindowServerEvent::UnregisterWsEventHandler(aHandler); + } + +TAny* CWindowServer::ResolveObjectInterface(TUint aTypeId) + { + switch(aTypeId) + { + case MWsActiveSchedulerDebug::EWsObjectInterfaceId: + return static_cast(CWsActiveScheduler::Static()); + case MWsIniFile::EWsObjectInterfaceId: + return static_cast(WsIniFile); + } + + if (CWsPluginManager *plugMgr=CWsTop::PluginManager()) + return plugMgr->ResolveObjectInterface(aTypeId); + + return NULL; + } + +void CWindowServer::Log(TInt aPriority,const TDesC &aFmt,TInt aParam) + { + if (wsDebugLog) + { + wsDebugLog->MiscMessage(aPriority, aFmt, aParam); + } + } + +// CWsGraphicDrawer master index + +TInt CWindowServer::AddGraphicDrawer(CWsGraphicDrawer* aDrawer) + { + return iDrawerMasterIndex.Add(aDrawer); + } + +TInt CWindowServer::SwapGraphicDrawer(CWsGraphicDrawer* aDrawer) + { + return iDrawerMasterIndex.Swap(aDrawer); + } + +TInt CWindowServer::RemoveGraphicDrawer(const TGraphicDrawerId& aId) + { + return iDrawerMasterIndex.Remove(aId); + } + +TInt CWindowServer::RemoveAllGraphicDrawers(const MWsClient& aOwner) + { + return iDrawerMasterIndex.RemoveAll(aOwner); + } + +TInt CWindowServer::RegisterMemoryRelease(MWsMemoryRelease * aMemoryRelease) + { + return iMemoryReleases.Append(aMemoryRelease); + } + +void CWindowServer::UnregisterMemoryRelease(MWsMemoryRelease * aMemoryRelease) + { + for (TInt ii = iMemoryReleases.Count() - 1; ii >= 0; --ii) + { + if (iMemoryReleases[ii] == aMemoryRelease) + { + iMemoryReleases.Remove(ii); + break; + } + } + } + +TBool CWindowServer::ReleaseMemory(TMemoryReleaseLevel aLevel) + { + return CWsWindow::ReleaseMemory(aLevel); + } + +TBool CWindowServer::ReleaseMemory() + { + TBool released = EFalse; + for (TInt level = MWsMemoryRelease::ELow; !released && level <= MWsMemoryRelease::EHigh; ++level) + { + for (TInt ii = iMemoryReleases.Count() - 1; !released && ii >= 0; --ii) + { + released = iMemoryReleases[ii]->ReleaseMemory(static_cast(level)); + } + } + return released; + } + +void CWindowServer::DestroySessionsForShutdown() + { + delete iServer; + iServer = NULL; + } +