windowing/windowserver/nonnga/SERVER/SERVER.CPP
changeset 0 5d03bc08d59c
child 26 15986eb6c500
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nonnga/SERVER/SERVER.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,900 @@
+// 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 <Graphics/WSGRAPHICDRAWERINTERFACE.H>
+#include <bitdraw.h>
+#include <hal.h>
+#include "inifile.h"
+#include "wspluginmanager.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
+	{
+public:
+	enum TInactivityBehaviour
+		{
+		EStopAnimation,
+		EStopAllDrawing,
+		EIgnore,
+		};
+	class CKickBack;
+	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);
+	TInt RemoveGraphicDrawer(const TGraphicDrawerId &aId);
+	
+private:
+	static TBool OnIdleCallBack(TAny* aAny);
+	void OnIdleCallBack(TBool aForceRedraw);
+	static TBool OnTickCallBack(TAny* aAny);
+	void OnTickCallBack();
+	static TBool OnKickBack(TAny* aAny);
+	void OnKickBack();
+private:
+	MWsGraphicDrawerEnvironment& iEnv;
+	static const TInt64 KRedrawGrace;
+	static const TInt64 KAnimationGrace;
+	static const TInt64 KDsaAnimationGrace;
+	CAsyncCallBack* iIdleInitiator;
+	CPeriodic* iTick;
+	CKickBack* iKickBack;
+	struct TSchedule
+		{
+		MWsScreen* iScreen; // used as a unique index, searching with FindInUnsignedKeyOrder
+		TBool iSchedule;
+		TTime iWhen;
+		TInt iGeneration;
+		};
+	RArray<TSchedule> iSchedule;
+	TInt iGeneration;
+	RArray<TGraphicDrawerId> iInvalidated;
+	TBool iInvalidateAll; // if we could not add to iInvalidated, we have to instead redraw everything
+	TTime iWhenDesired;
+	TBool iInactive;
+	TBool iInactiveDraws;
+	TTime iExpectedTime;
+	TBool iRedrawScheduled;
+	TInt64 iRedrawGracePeriod;
+	TInt64 iAnimationGracePeriod;
+	TInt64 iDsaAnimationGracePeriod;
+	TInactivityBehaviour iInactivityBehaviour;
+	};
+	
+TInt CWindowServer::CDefaultAnimationScheduler::RemoveGraphicDrawer(const TGraphicDrawerId &aId)
+	{
+	TInt index=iInvalidated.Find(aId);
+	if (index!=KErrNotFound)
+		iInvalidated.Remove(index);
+	return index;
+	}	
+	
+class CWindowServer::CDefaultAnimationScheduler::CKickBack: public CActive
+	{
+public:
+	CKickBack(const TCallBack& aCallBack);
+	void ConstructL();
+	void RequestKickBack();
+	~CKickBack();
+private:
+	static TInt IdleThreadFunc(TAny* aAny);
+	void Loop();
+	// from CActive
+	void RunL(); // fires when kicked back by the idle thread
+	void DoCancel();
+private:
+	RThread iWservThread;
+	RThread iIdleThread;
+	TRequestStatus iIdleStatus;
+	TCallBack iCallBack;
+	};
+	
+CWindowServer::CDefaultAnimationScheduler::CKickBack::CKickBack(const TCallBack& aCallBack) :
+CActive(EPriorityNormal),
+iCallBack(aCallBack)
+	{
+	CActiveScheduler::Add(this);
+	}
+	
+void CWindowServer::CDefaultAnimationScheduler::CKickBack::ConstructL()
+	{
+	_LIT(KIdleThreadName,"NearlyIdleKickBack");
+	const TInt KStackSize = 1024;
+	User::LeaveIfError(iWservThread.Open(iWservThread.Id()));
+	User::LeaveIfError(iIdleThread.Create(KIdleThreadName(),IdleThreadFunc,KStackSize,NULL,this));
+	iIdleThread.SetPriority(EPriorityAbsoluteVeryLow);
+	iIdleThread.Resume();
+	}
+	
+void CWindowServer::CDefaultAnimationScheduler::CKickBack::RequestKickBack()
+	{
+	if (!IsActive())
+		{
+		iStatus = KRequestPending;
+		SetActive();
+		TRequestStatus * status = &iIdleStatus;
+		iIdleThread.RequestComplete(status, KErrNone);
+		}
+	}
+
+void CWindowServer::CDefaultAnimationScheduler::CKickBack::Loop()
+	{
+	FOREVER
+		{
+		// This is used here for performance reasons. 
+		User::WaitForRequest(iIdleStatus); 
+		iIdleStatus = KRequestPending;
+		if (IsActive()&& (iStatus == KRequestPending))
+			{
+			TRequestStatus * status = &iStatus;
+			iWservThread.RequestComplete(status,KErrNone);
+			}
+		}
+	}
+
+void CWindowServer::CDefaultAnimationScheduler::CKickBack::RunL()
+	{
+	iCallBack.CallBack();
+	}
+
+void CWindowServer::CDefaultAnimationScheduler::CKickBack::DoCancel()
+	{
+	}
+
+CWindowServer::CDefaultAnimationScheduler::CKickBack::~CKickBack()
+	{
+	Cancel();
+	iWservThread.Close();
+	iIdleThread.Kill(0);
+	iIdleThread.Close();
+	}
+	
+TInt CWindowServer::CDefaultAnimationScheduler::CKickBack::IdleThreadFunc(TAny* aAny)
+	{
+	CKickBack* owner = reinterpret_cast<CKickBack*>(aAny);
+	ASSERT(owner);
+	if(owner)
+		{
+		owner->Loop();
+		}
+	return 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 = 35000; // insist upon 35ms grace for other threads to run when animating
+const TInt64 CWindowServer::CDefaultAnimationScheduler::KDsaAnimationGrace = 35000; // insist upon 35ms grace for other threads to run when animating during DSA
+	
+CWindowServer::CDefaultAnimationScheduler::CDefaultAnimationScheduler(MWsGraphicDrawerEnvironment& aEnv):
+	iEnv(aEnv), iSchedule(1,_FOFF(TSchedule,iScreen))
+	{
+	}
+	
+CWindowServer::CDefaultAnimationScheduler::~CDefaultAnimationScheduler()
+	{
+	iSchedule.Close();
+	iInvalidated.Close();
+	delete iKickBack;
+	delete iIdleInitiator;
+	delete iTick;
+	}
+	
+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;
+	
+	_LIT(KDsaAnimationGracePeriod, "DSAANIMATIONGRACEPERIOD");
+	tmp = KDsaAnimationGrace;
+	WsIniFile->FindVar(KDsaAnimationGracePeriod, tmp);
+	iDsaAnimationGracePeriod = tmp;
+	
+	iIdleInitiator = new(ELeave) CAsyncCallBack(TCallBack(OnIdleCallBack,this),EWsGraphicAnimateAwaitIdlePriority);
+	iTick = CPeriodic::NewL(EWsGraphicAnimatePriority);
+	
+	_LIT(KDisableIdleAnimation, "DISABLEIDLEANIMATION");
+	if (!WsIniFile->FindVar(KDisableIdleAnimation))
+		{
+		iKickBack = new CKickBack(TCallBack(OnKickBack,this));
+		iKickBack->ConstructL();
+		}
+	}
+	
+void CWindowServer::CDefaultAnimationScheduler::Invalidate(const TGraphicDrawerId& aId)
+	{
+	if(!iInvalidateAll)
+		{
+		switch(iInvalidated.InsertInOrder(aId,TLinearOrder<TGraphicDrawerId>(TGraphicDrawerId::Compare)))
+			{
+			case KErrNone:
+				break;
+			case KErrAlreadyExists:
+				break;
+			default:
+				iInvalidateAll = ETrue;
+				iInvalidated.Reset();
+			}
+		}
+	iIdleInitiator->CallBack();
+	}
+
+void CWindowServer::CDefaultAnimationScheduler::OnInactive()
+	{
+	iInactive = ETrue;
+	}
+	
+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);
+	}
+	
+void CWindowServer::CDefaultAnimationScheduler::DoRedrawNow(MWsScreen& /*aScreen*/)
+	{
+	OnIdleCallBack(ETrue);
+	}
+	
+void CWindowServer::CDefaultAnimationScheduler::ScheduleAnimation(MWsScreen& aScreen,const TTime& aWhen)
+	{
+	TSchedule schedule;
+	schedule.iScreen = &aScreen;
+	schedule.iSchedule = ETrue;
+	schedule.iWhen = aWhen;
+	schedule.iGeneration = iGeneration;
+	TBool ok = EFalse;
+	const TInt idx = iSchedule.FindInUnsignedKeyOrder(schedule);
+	if(0 <= idx)
+		{
+		if(iSchedule[idx].iSchedule)
+			{
+			if(iSchedule[idx].iWhen > aWhen)
+				{
+				iSchedule[idx].iWhen = aWhen;
+				}
+			}
+		else
+			{
+			iSchedule[idx] = schedule;
+			}
+		iSchedule[idx].iGeneration = iGeneration;
+		ok = ETrue;
+		}
+	else
+		{
+		ok = (KErrNone == iSchedule.InsertInUnsignedKeyOrder(schedule));
+		}
+	if(ok)
+		{
+		//If the animation runs at very high rate which exceeds the rate WSERV can 
+		//perform the rendering, it is possible that WSERV animation loop will monopolize  
+		//processor time. 
+  		User::After(0);	// to yeild from the animation loop 
+
+		iIdleInitiator->CallBack();
+		}
+	}
+
+void CWindowServer::CDefaultAnimationScheduler::UnscheduleAnimation(MWsScreen& aScreen)
+	{
+	TSchedule schedule;
+	schedule.iScreen = &aScreen;
+	const TInt idx = iSchedule.FindInUnsignedKeyOrder(schedule);
+	if(0 <= idx)
+		{
+		iSchedule[idx].iSchedule = EFalse;
+		}
+	}
+
+TBool CWindowServer::CDefaultAnimationScheduler::OnIdleCallBack(TAny* aAny)
+	{
+	CDefaultAnimationScheduler* self = reinterpret_cast<CDefaultAnimationScheduler*>(aAny);
+	ASSERT(self);
+	if(self)
+		{
+		self->OnIdleCallBack(EFalse);
+		}
+	return EFalse; //ignored by caller
+	}
+	
+void CWindowServer::CDefaultAnimationScheduler::OnIdleCallBack(TBool aForceRedraw)
+	{
+	TBool wasActive = EFalse;
+	if (iTick->IsActive())
+		{
+		wasActive = ETrue;
+		iTick->Cancel(); // stop ticker, as we'll reschedule if necessary
+		}
+	if (aForceRedraw)
+		{
+		// Don't need to update iExpectedTime as we will not schedule a tick.
+		// Don't need to update iWhenDesired as we will not schedule a kick-back.
+		OnTickCallBack();
+		return;
+		}
+	TBool tick = (iInvalidateAll || iInvalidated.Count());
+	TTimeIntervalMicroSeconds next = 0LL;
+	const TInt count = iSchedule.Count();
+	TTime now;
+	now.UniversalTime();
+	if(count)
+		{
+		// work out the next wanted tick
+		TBool animTick = EFalse;
+		for(TInt i=0; i<count; i++)
+			{
+			if(iSchedule[i].iSchedule)
+				{
+				const TTime when = iSchedule[i].iWhen;
+				const TTimeIntervalMicroSeconds fromNow = when.MicroSecondsFrom(now);
+				if(!animTick || (fromNow < next))
+					{
+					animTick = ETrue;
+					tick = ETrue;
+					next = fromNow;
+					iWhenDesired = when;
+					}
+				}
+			}
+		}
+	if(tick)
+		{
+		TInt64 grace;
+		if (iRedrawScheduled)
+			grace = iRedrawGracePeriod;
+		else if (EFalse) // DSA active
+			grace = iDsaAnimationGracePeriod;
+		else
+			grace = iAnimationGracePeriod;
+		if (wasActive)
+			{
+			TInt64 minimum = iExpectedTime.MicroSecondsFrom(now).Int64();
+			if (minimum >= 0 && grace > minimum)
+				grace = minimum;
+			}
+
+		if (next.Int64() <= 0)
+			next = 0LL ;  // No kickback/tick is needed. Make sure next == default grace period.
+
+		if(next < grace)
+			{
+			next = grace;
+			if (iKickBack)
+				iKickBack->RequestKickBack();
+			}
+		else if (next > KHalfHour)
+			next = KHalfHour;
+		
+		iExpectedTime=now + next;
+		if (next.Int64() > 0)
+			{
+			iTick->Start(next.Int64(),0,TCallBack(OnTickCallBack,this));
+			}
+		else
+			{
+			OnTickCallBack(); // scheduling for 0 doesn't actually execute immediately
+			}
+		}
+	}
+	
+TBool CWindowServer::CDefaultAnimationScheduler::OnKickBack(TAny* aAny)
+	{
+	CDefaultAnimationScheduler* self = reinterpret_cast<CDefaultAnimationScheduler*>(aAny);
+	ASSERT(self);
+	if(self)
+		{
+		self->OnKickBack();
+		}
+	return EFalse; //ignored by caller
+	}
+	
+void CWindowServer::CDefaultAnimationScheduler::OnKickBack()
+	{
+	if (iTick->IsActive())
+		{
+		iTick->Cancel();
+		TTime now;
+		now.UniversalTime();
+				
+		TTimeIntervalMicroSeconds fromNow = iWhenDesired.MicroSecondsFrom(now);
+
+		if (fromNow < 0)
+			{
+			OnTickCallBack();
+			}
+		else
+			{
+			if (fromNow > KHalfHour)
+				fromNow = KHalfHour;
+			iTick->Start(fromNow.Int64(),0,TCallBack(OnTickCallBack, this));
+			}
+		}
+	}
+	
+TBool CWindowServer::CDefaultAnimationScheduler::OnTickCallBack(TAny* aAny)
+	{
+	CDefaultAnimationScheduler* self = reinterpret_cast<CDefaultAnimationScheduler*>(aAny);
+	ASSERT(self);
+	if(self)
+		{
+		self->OnTickCallBack();
+		}
+	return EFalse;
+	}
+	
+void CWindowServer::CDefaultAnimationScheduler::OnTickCallBack()
+	{
+	iTick->Cancel();
+
+	switch(iInactivityBehaviour)
+		{
+		case EStopAnimation :
+			// only client redraws if inactive. server side drawing stopped.
+			if(iInactive && !iRedrawScheduled) 
+				{
+				iInactiveDraws = ETrue;
+				return;
+				}
+			break;
+		case EStopAllDrawing :
+			// if screen off, stop both client and server side drawing.
+			if(iInactive) 
+				{
+				iInactiveDraws = ETrue;
+				return;
+				}
+			break;
+		case EIgnore :
+		default :
+			// ignore inactivity and draw as normal
+			break;
+		}
+		
+	iRedrawScheduled = EFalse;
+
+	TTime now;
+	now.UniversalTime();
+	CWsActiveScheduler::Static()->AccumReclaimedIdleTime(Max(0LL,now.MicroSecondsFrom(iExpectedTime).Int64()));
+		
+	TInt drewCount = 0;
+	TInt scheduledCount = 0;
+	/* first redraw any screens that are affected by invalidated graphic IDs */
+	if(iInvalidateAll || iInvalidated.Count())
+		{
+		// cancel idle callback if it's already scheduled as we're going to redraw all invalidated 
+		// request at this point and clear invalidated array
+		if (iIdleInitiator->IsActive())
+			iIdleInitiator->Cancel();
+		const TArray<TGraphicDrawerId> invalidArray = iInvalidated.Array();
+		const TInt screenCount = iEnv.ScreenCount();
+		for(TInt i=0; i<screenCount; i++)
+			{
+			MWsScreen* screen = iEnv.Screen(i);
+			if(screen)
+				{
+				drewCount++;
+				if(iInvalidateAll)
+					{
+					Redraw(*screen);
+					}
+				else
+					{
+					RedrawInvalid(*screen,invalidArray);
+					}
+				}
+			}
+		iInvalidateAll = EFalse;
+		iInvalidated.Reset();
+		}
+	/* iSchedule might resize during this call because an Animate() on a screen might reschedule another animation etc */
+	TInt generation = iGeneration++;
+	TBool drew;
+	do
+		{
+		drew = EFalse;
+		const TInt count = iSchedule.Count();
+		for(TInt i=0; i<count; i++)
+			{
+			if(iSchedule[i].iSchedule)
+				{
+				scheduledCount++;
+				if(iSchedule[i].iGeneration == generation)
+					{
+					iSchedule[i].iSchedule = EFalse; // denote not to tick; it can be rescheduled in the subsequent call to Animate()
+					Animate(*(iSchedule[i].iScreen));
+					drew = ETrue;
+					drewCount++;
+					break; // go back to outer do while(drew)
+					}
+				}
+			}
+		} while(drew);
+	__DEBUG_ONLY(
+		TBool idleIsActive = iIdleInitiator->IsActive();
+		if(scheduledCount || !drewCount)
+			{
+			TBool rescheduled = EFalse;
+			for(TInt i=0; i<iSchedule.Count(); i++)
+				{
+				rescheduled |= iSchedule[i].iSchedule;
+				}
+			if(!rescheduled)
+				{
+				//__DEBUGGER();
+				}
+			})
+	}
+
+// 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.
+//
+	: CPolicyServer(EMainServerPriority,KWsServPolicy)
+	{
+	}
+
+CWindowServer::~CWindowServer()
+	{
+	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
+	delete iPluginManager;
+	}
+	
+void CWindowServer::ConstructL()
+	{
+	iPluginManager = CWsPluginManager::NewL(*this);
+	iDefaultAnimationScheduler = new(ELeave) CDefaultAnimationScheduler(*this);
+	iDefaultAnimationScheduler->ConstructL();
+	RegisterMemoryRelease(this);
+	}
+
+/** Creates a new client for this server. */
+CSession2* CWindowServer::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));
+	}
+
+TInt CWindowServer::SessionCount()
+	{
+	iSessionIter.SetToFirst();
+	TInt count=0;
+	while(iSessionIter++)
+		count++;
+	return(count);
+	}
+
+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);
+	}
+	
+TInt CWindowServer::RegisterRawEventHandler(MEventHandler* aHandler)
+	{
+	if (!aHandler)
+		return KErrArgument;
+	TRAPD(err, TWindowServerEvent::PotentialEventHandlerL(1));
+	if (err != KErrNone)
+		return err;
+	TWindowServerEvent::AddEventHandler(aHandler);
+	return KErrNone;
+	}
+	
+void CWindowServer::UnregisterRawEventHandler(MEventHandler* aHandler)
+	{
+	TWindowServerEvent::RemoveEventHandler(aHandler);
+	TWindowServerEvent::PotentialEventHandlerL(-1); // can't leave for -1
+	}
+
+void CWindowServer::PostRawEvent(const TRawEvent & aEvent)
+	{
+	TWindowServerEvent::ProcessRawEvent(aEvent);
+	}
+	
+void CWindowServer::PostKeyEvent(const TKeyEvent & aEvent)
+	{
+	TWindowServerEvent::ProcessKeyEvent(aEvent, 0);
+	}
+	
+TAny* CWindowServer::ResolveObjectInterface(TUint aTypeId)
+	{
+	switch(aTypeId)
+		{
+		case MWsActiveSchedulerDebug::EWsObjectInterfaceId:
+			return static_cast<MWsActiveSchedulerDebug*>(CWsActiveScheduler::Static());
+		case MWsIniFile::EWsObjectInterfaceId:
+			return static_cast<MWsIniFile*>(WsIniFile);
+		case MWsRawEventServer::EWsObjectInterfaceId:
+			return static_cast<MWsRawEventServer*>(this);
+		}
+	
+	if (iPluginManager)
+		return iPluginManager->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)
+	{
+	iDefaultAnimationScheduler->RemoveGraphicDrawer(aId);
+	return iDrawerMasterIndex.Remove(aId);
+	}
+
+TInt CWindowServer::RemoveAllGraphicDrawers(const MWsClient& aOwner)
+	{
+	return iDrawerMasterIndex.RemoveAll(aOwner);
+	}
+
+CWsPluginManager* CWindowServer::PluginManager()
+	{
+	return iPluginManager;
+	}
+
+TInt CWindowServer::RegisterMemoryRelease(MWsMemoryRelease * aMemoryRelease)
+	{
+	return iMemoryReleases.Append(aMemoryRelease);
+	}
+
+void CWindowServer::UnregisterMemoryRelease(MWsMemoryRelease * aMemoryRelease)
+	{
+	for (TInt i = iMemoryReleases.Count() - 1; i >= 0; --i)
+		{
+		if (iMemoryReleases[i] == aMemoryRelease)
+			{
+			iMemoryReleases.Remove(i);
+			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 i = iMemoryReleases.Count() - 1; !released && i >= 0; --i)
+			{
+			released = iMemoryReleases[i]->ReleaseMemory(static_cast<TMemoryReleaseLevel>(level));
+			}
+		}
+	return released;
+	}
+