windowing/windowserver/nga/SERVER/SERVER.CPP
changeset 0 5d03bc08d59c
child 26 15986eb6c500
child 110 7f25ef56562d
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Window server 'server' class
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "server.h"
       
    19 #include "panics.h"
       
    20 #include "wstop.h"
       
    21 #include "EVENT.H"
       
    22 #include <Graphics/WSGRAPHICDRAWERINTERFACE.H>
       
    23 #include <bitdraw.h>
       
    24 #include <hal.h>
       
    25 #include "inifile.h"
       
    26 #include "wspluginmanager.h"
       
    27 #include "graphics/windowserverconstants.h"
       
    28 
       
    29 GLREF_D CDebugLogBase *wsDebugLog;
       
    30 
       
    31 const TUint KRangeCount = 1; 
       
    32 // We use a lot of 64 bit time calculations, but a periodic can only cope with signed 32 bit times
       
    33 // which gives them a limit of about 35 minutes.
       
    34 // Fortunately, our animtions are safe if redrawn early.  Every half an hour isn't going to hurt.
       
    35 const TTimeIntervalMicroSeconds KHalfHour = 30 * 60 * 1000 * 1000;
       
    36 
       
    37 const TInt KWsServRanges[KRangeCount] = 
       
    38 	{	
       
    39 	0
       
    40 	};
       
    41 
       
    42 const TUint8 KElementsIndex[KRangeCount] =
       
    43 	{
       
    44 	CPolicyServer::EAlwaysPass,		
       
    45 	};
       
    46 
       
    47 const CPolicyServer::TPolicyElement KPolicyElements[] = 
       
    48 	{ 
       
    49 	{_INIT_SECURITY_POLICY_C1(ECapabilityPowerMgmt), CPolicyServer::EFailClient}, 
       
    50 	{_INIT_SECURITY_POLICY_C1(ECapabilitySwEvent), CPolicyServer::EFailClient}, 
       
    51 	{_INIT_SECURITY_POLICY_C1(ECapabilityWriteDeviceData), CPolicyServer::EFailClient} 
       
    52 	};
       
    53 
       
    54 const CPolicyServer::TPolicy KWsServPolicy =
       
    55 	{
       
    56 	CPolicyServer::EAlwaysPass, 
       
    57 	KRangeCount,
       
    58 	KWsServRanges,
       
    59 	KElementsIndex,
       
    60 	KPolicyElements 	
       
    61 	};
       
    62  	
       
    63 // CWindowServer::CDefaultAnimationScheduler \\\\\\\\\\\\\\\\\\\\\\\\\\\
       
    64 
       
    65 class CWindowServer::CDefaultAnimationScheduler: public CBase, public MWsAnimationScheduler
       
    66 	{
       
    67 	// Associates a screen number with a CActiveSchedulerWait intance. This is used to
       
    68 	// achieve synchronous update completion on a specific screen.
       
    69 	class CScreenUpdateWait : public CActiveSchedulerWait
       
    70 		{
       
    71 		public:
       
    72 			CScreenUpdateWait(TInt aScreenNumber) : iScreenNumber (aScreenNumber) {}
       
    73 			TInt iScreenNumber;	
       
    74 		};
       
    75 	
       
    76 	struct TScreenUpdateDetails
       
    77 		{
       
    78 		CWindowServer::CDefaultAnimationScheduler* iScheduler;
       
    79 		TInt  iScreenNumber;
       
    80 		};
       
    81 	
       
    82 	struct TSchedule
       
    83 		{
       
    84 		MWsScreen* iScreen; // used as a unique index, searching with FindInUnsignedKeyOrder
       
    85 		TInt  iScreenNumber;
       
    86 		TBool iScheduled;
       
    87 		TTime iWhen;
       
    88 		TBool iRedraw;
       
    89 		};
       
    90 public:
       
    91 	enum TInactivityBehaviour
       
    92 		{
       
    93 		EStopAnimation,
       
    94 		EStopAllDrawing,
       
    95 		EIgnore,
       
    96 		};
       
    97 	class CScreenState;
       
    98 
       
    99 	CDefaultAnimationScheduler(MWsGraphicDrawerEnvironment& aEnv);
       
   100 	~CDefaultAnimationScheduler();
       
   101 	void ConstructL();		//LeaveScan:  member of nested class declaration
       
   102 	// implementing MWsAnimationScheduler
       
   103 	void ScheduleAnimation(MWsScreen& aScreen,const TTime& aWhen);
       
   104 	void UnscheduleAnimation(MWsScreen& aScreen);
       
   105 	void Invalidate(const TGraphicDrawerId& aId);
       
   106 	void OnInactive();
       
   107 	void OnActive();
       
   108 	void ScheduleRedraw(MWsScreen& aScreen,const TTime& aWhen);
       
   109 	void DoRedrawNow(MWsScreen& aScreen);
       
   110 private:
       
   111 	static TBool OnIdleCallBack(TAny* aAny);
       
   112 	void ScheduleUpdate (TInt aScreenNumber, TBool aForce);
       
   113 	void OnIdleCallBack(TBool aForce);
       
   114 	static TBool InvokeDueAnimation(TAny* aAny);
       
   115 	void RedrawAllInvalidatedRegions (TInt aScreen);
       
   116 	TSchedule* GetScheduledScreenUpdate(TInt aScreen);
       
   117 	void InvokeDueAnimation(TInt aScreen);
       
   118 	void ProcessUpdateCompletion (TInt aScreenNumber);
       
   119 	TInt ScreenNumber(MWsScreen& aScreen) const;
       
   120 	TTimeIntervalMicroSeconds GetDueDelta (TBool aForceRedraw, TSchedule* aScheduledUpdate);
       
   121 private:
       
   122 	RPointerArray<CScreenUpdateWait> iRedrawWaitLoop; 
       
   123 	RPointerArray<CScreenState> iScreenState;
       
   124 	MWsGraphicDrawerEnvironment& iEnv;
       
   125 	static const TInt64 KRedrawGrace;
       
   126 	static const TInt64 KAnimationGrace;
       
   127 	CAsyncCallBack* iIdleInitiator;
       
   128 	TBool iInRedrawNow;
       
   129 	RArray<TSchedule> iSchedule;
       
   130 	TBool iInactive;
       
   131 	TBool iInactiveDraws;
       
   132 	TBool iRedrawScheduled;
       
   133 	TInt64 iRedrawGracePeriod;
       
   134 	TInt64 iAnimationGracePeriod;
       
   135 	TInactivityBehaviour iInactivityBehaviour;
       
   136 	};
       
   137 
       
   138 class CWindowServer::CDefaultAnimationScheduler::CScreenState : public CActive
       
   139 	{
       
   140 public:
       
   141 	static CScreenState* NewL (CDefaultAnimationScheduler* aScheduler, TInt aScreenOrdinal);
       
   142 	~CScreenState();
       
   143 	void SetActive ();
       
   144 	
       
   145 	CPeriodic* iUpdateOn;
       
   146 	TTime      iExpectedTickTime;
       
   147 	TScreenUpdateDetails iScreenUpdateDetails;
       
   148 	RArray<TGraphicDrawerId> iInvalidated;
       
   149 	TBool 		iInvalidateAll;
       
   150 	
       
   151 private:
       
   152 	CScreenState (CDefaultAnimationScheduler* aScheduler, TInt aScreenOrdinal);
       
   153 	void ConstructL ();
       
   154 	
       
   155 	void RunL();
       
   156 	void DoCancel() 
       
   157 		{
       
   158 		TRequestStatus* tmpTRS = &iStatus;
       
   159 		User::RequestComplete(tmpTRS, KErrNone);
       
   160 		};
       
   161 	};
       
   162 
       
   163 // If using the default animation scheduler on a device, these two numbers may be worth tweaking in the inifile
       
   164 // However, both are maximum periods - wserv will go faster than either if nothing else is using the system.
       
   165 const TInt64 CWindowServer::CDefaultAnimationScheduler::KRedrawGrace = 0; // do redraws immediately
       
   166 const TInt64 CWindowServer::CDefaultAnimationScheduler::KAnimationGrace = 0; // do animation redraws immediately
       
   167 	
       
   168 CWindowServer::CDefaultAnimationScheduler::CDefaultAnimationScheduler(MWsGraphicDrawerEnvironment& aEnv):
       
   169 	iEnv(aEnv), iSchedule(1,_FOFF(TSchedule,iScreen))
       
   170 	{
       
   171 	}
       
   172 
       
   173 CWindowServer::CDefaultAnimationScheduler::~CDefaultAnimationScheduler()
       
   174 	{
       
   175 	iSchedule.Close();
       
   176 	delete iIdleInitiator;
       
   177 	
       
   178 	TInt screenCount = iScreenState.Count();
       
   179 	for (TInt ii = 0; ii < screenCount; ii++)
       
   180 		delete iScreenState[ii];
       
   181 
       
   182 	iScreenState.Close();
       
   183 
       
   184 	// Destroy the redraw wait loops associated each screen, and close
       
   185 	// the associated Array objects.
       
   186 	TInt waitLoopCount = iRedrawWaitLoop.Count();
       
   187 	for (TInt waitLoop = 0; waitLoop < waitLoopCount; waitLoop++)
       
   188 		delete iRedrawWaitLoop[waitLoop];
       
   189 	iRedrawWaitLoop.Close();
       
   190 	}
       
   191 	
       
   192 void CWindowServer::CDefaultAnimationScheduler::ConstructL()
       
   193 	{
       
   194 	_LIT(KOnInactive,"ONINACTIVE");
       
   195 	_LIT(KStopAnimation,"STOPANIMATION");
       
   196 	_LIT(KStopAllDrawing,"STOPALLDRAWING");
       
   197 	_LIT(KIgnore,"IGNORE");
       
   198 	
       
   199 	TPtrC inactivityBehaviourString;
       
   200 	WsIniFile->FindVar(KOnInactive,inactivityBehaviourString);
       
   201 	if(inactivityBehaviourString.CompareF(KStopAnimation)==0)
       
   202 		iInactivityBehaviour = EStopAnimation;
       
   203 	else if(inactivityBehaviourString.CompareF(KStopAllDrawing)==0)
       
   204 		iInactivityBehaviour = EStopAllDrawing;
       
   205 	else if(inactivityBehaviourString.CompareF(KIgnore)==0)
       
   206 		iInactivityBehaviour = EIgnore;
       
   207 		
       
   208 	_LIT(KRedrawGracePeriod, "REDRAWGRACEPERIOD");
       
   209 	TInt tmp = KRedrawGrace;
       
   210 	WsIniFile->FindVar(KRedrawGracePeriod, tmp);
       
   211 	iRedrawGracePeriod = tmp;
       
   212 	
       
   213 	_LIT(KAnimationGracePeriod, "ANIMATIONGRACEPERIOD");
       
   214 	tmp = KAnimationGrace;
       
   215 	WsIniFile->FindVar(KAnimationGracePeriod, tmp);
       
   216 	iAnimationGracePeriod = tmp;
       
   217 	
       
   218 	iIdleInitiator = new(ELeave) CAsyncCallBack(TCallBack(OnIdleCallBack,this),EWsGraphicAnimateAwaitIdlePriority);
       
   219 	
       
   220 	TInt screenCount;
       
   221 	User::LeaveIfError(HAL::Get( HAL::EDisplayNumberOfScreens, screenCount)); 
       
   222 	for (TInt i = 0; i < screenCount; i++)
       
   223 		{
       
   224 		CScreenState* screenState = CScreenState::NewL (this, i);
       
   225 		CleanupStack::PushL(screenState);
       
   226 		iScreenState.AppendL (screenState);
       
   227 		CleanupStack::Pop(screenState);
       
   228 		}
       
   229 		
       
   230 	
       
   231 	// Ensure that the wait loop array has some allocated slots, making it highly 
       
   232 	// unlikely that Append() will fail due to OOM.
       
   233 	iRedrawWaitLoop.ReserveL (8);
       
   234 	}
       
   235 
       
   236 void CWindowServer::CDefaultAnimationScheduler::Invalidate(const TGraphicDrawerId& aId)
       
   237 	{
       
   238 	const TInt screenCount = iEnv.ScreenCount();
       
   239 	for(TInt ii = 0; ii < screenCount; ii++)
       
   240 		{
       
   241 		CScreenState* screenState = iScreenState[ii];
       
   242 		if(!screenState->iInvalidateAll)
       
   243 			{
       
   244 			switch(screenState->iInvalidated.InsertInOrder(aId,TLinearOrder<TGraphicDrawerId>(TGraphicDrawerId::Compare)))
       
   245 				{
       
   246 				case KErrNone:
       
   247 				case KErrAlreadyExists:
       
   248 					break;
       
   249 				default:
       
   250 					screenState->iInvalidateAll = ETrue;
       
   251 					screenState->iInvalidated.Reset();
       
   252 				}
       
   253 			}
       
   254 		}
       
   255 	iIdleInitiator->CallBack();
       
   256 	}
       
   257 
       
   258 CWindowServer::CDefaultAnimationScheduler::CScreenState::CScreenState (CDefaultAnimationScheduler* aScheduler, TInt aScreenNumber):
       
   259 	CActive(EComposeCompletePriority)
       
   260 	{
       
   261 	iScreenUpdateDetails.iScheduler = aScheduler;
       
   262 	iScreenUpdateDetails.iScreenNumber = aScreenNumber;
       
   263 	}
       
   264 
       
   265 CWindowServer::CDefaultAnimationScheduler::CScreenState* 
       
   266 CWindowServer::CDefaultAnimationScheduler::CScreenState::NewL (CDefaultAnimationScheduler* aScheduler, TInt aScreenOrdinal)
       
   267 	{
       
   268 	CScreenState* self = new(ELeave)CScreenState(aScheduler, aScreenOrdinal);
       
   269 	CleanupStack::PushL(self);
       
   270 	self->ConstructL();
       
   271 	CleanupStack::Pop(self);
       
   272 	return self;	
       
   273 	}
       
   274 
       
   275 void CWindowServer::CDefaultAnimationScheduler::CScreenState::ConstructL ()
       
   276 	{
       
   277 	iUpdateOn = CPeriodic::NewL(EComposeCompletePriority);
       
   278 	CActiveScheduler::Add(this);
       
   279 	}
       
   280 
       
   281 CWindowServer::CDefaultAnimationScheduler::CScreenState::~CScreenState()
       
   282 	{
       
   283 	CActive::Cancel();
       
   284 	iInvalidated.Close();
       
   285 	delete iUpdateOn;
       
   286 	}
       
   287 
       
   288 void CWindowServer::CDefaultAnimationScheduler::CScreenState::SetActive()
       
   289 	{
       
   290 	CActive::SetActive ();
       
   291 	}
       
   292 	
       
   293 /** 
       
   294 Invoked when the rendering pipline signals that it is ready to recieve updated.
       
   295 */
       
   296 void CWindowServer::CDefaultAnimationScheduler::CScreenState::RunL() 
       
   297 	{
       
   298 	iScreenUpdateDetails.iScheduler->ProcessUpdateCompletion (iScreenUpdateDetails.iScreenNumber);
       
   299 	}
       
   300 
       
   301 void CWindowServer::CDefaultAnimationScheduler::ProcessUpdateCompletion (TInt aScreenNumber)
       
   302 	{
       
   303 	// Stop all waitloops related to the specified screen.
       
   304 	TInt waitLoopCount = iRedrawWaitLoop.Count();
       
   305 	for (TInt waitLoop = 0; waitLoop < waitLoopCount; waitLoop++)
       
   306 		if (iRedrawWaitLoop[waitLoop]->IsStarted() && (iRedrawWaitLoop[waitLoop]->iScreenNumber == aScreenNumber))
       
   307 			iRedrawWaitLoop[waitLoop]->AsyncStop();
       
   308 	
       
   309 	// Perform any outstanding redraws on the specified screen.
       
   310 	ScheduleUpdate (aScreenNumber, ETrue);
       
   311 	}
       
   312 
       
   313 /**
       
   314 Switch to deactivate animation or drawing (based on setting of iInactivityBehaviour).
       
   315 See InvokeDueAnimation().
       
   316 */
       
   317 void CWindowServer::CDefaultAnimationScheduler::OnInactive()
       
   318 	{
       
   319 	iInactive = ETrue;
       
   320 	}
       
   321 
       
   322 /**
       
   323 Switch to deactivate/activate animation or drawing (based on setting of iInactivityBehaviour).
       
   324 See InvokeDueAnimation().
       
   325 */	
       
   326 void CWindowServer::CDefaultAnimationScheduler::OnActive()
       
   327 	{
       
   328 	iInactive = EFalse;
       
   329 	if(iInactiveDraws)
       
   330 		{
       
   331 		iInactiveDraws = EFalse;
       
   332 		iIdleInitiator->CallBack();
       
   333 		}
       
   334 	}
       
   335 
       
   336 void CWindowServer::CDefaultAnimationScheduler::ScheduleRedraw(MWsScreen& aScreen,const TTime& aWhen)
       
   337 	{
       
   338 	iRedrawScheduled = ETrue;
       
   339 	ScheduleAnimation(aScreen, aWhen);
       
   340 	}
       
   341 
       
   342 /** 
       
   343 Given a MWsScreen pointer, return an integer value representing the ordinal position
       
   344 of the screen in the Window Server.
       
   345 */
       
   346 TInt CWindowServer::CDefaultAnimationScheduler::ScreenNumber(MWsScreen& aScreen) const
       
   347 	{
       
   348 	TInt numberOfScreens = CWsTop::NumberOfScreens();
       
   349 	TInt theScreen;
       
   350 	
       
   351 	for (theScreen = 0; theScreen < numberOfScreens; theScreen++)
       
   352 		if (CWsTop::Screen(theScreen) == &aScreen) 
       
   353 			break;
       
   354 	
       
   355 	WS_ASSERT_DEBUG(theScreen < numberOfScreens, EWsPanicWsGraphic);
       
   356 	return theScreen;
       
   357 	}
       
   358 
       
   359 /**
       
   360 Perform redraw and return only when completed.
       
   361 NOTE: This method uses CActiveSchedulerWait to run a "modal wait loop" while the
       
   362 		redraw complete signal is pending. When the signal is recieved, AsyncStop() is
       
   363 		invoked on all active wait loops for the signalling screen. 
       
   364 */
       
   365 void CWindowServer::CDefaultAnimationScheduler::DoRedrawNow(MWsScreen& aScreen)
       
   366 	{	
       
   367 	TInt screenNumber = ScreenNumber (aScreen);
       
   368 	TInt redrawCount = 0;
       
   369 		
       
   370 	// redrawCount is the number of times we should wait for redraws to complete.
       
   371 	// If a redraw is not currently active then we need to wait (at most) once: for
       
   372 	// any outstanding scheduled update to complete.
       
   373 	// If a redraw is currently active then we need to wait (at most) twice: once for
       
   374 	// the current update to complete, and once for any outstanding scheduled update to complete.	
       
   375 	if (!iScreenState[screenNumber]->IsActive())
       
   376 		{		
       
   377 		// No animation in progress, so force a redraw of due updates.
       
   378 		ScheduleUpdate(screenNumber, ETrue);
       
   379 		
       
   380 		// If there is still nothing drawing, set redrawCount to zero to make sure we do not wait.
       
   381 		if (!iScreenState[screenNumber]->IsActive())
       
   382 			redrawCount = 0;
       
   383 		else
       
   384 			redrawCount = 1;
       
   385 		}
       
   386 	else
       
   387 		redrawCount = 2;
       
   388 	
       
   389 	// Wait for the sepecified number of redraws.
       
   390 	if (redrawCount)
       
   391 		{
       
   392 		// Allocate the wait loop on the stack so we are not subject to heap OOM.
       
   393 		TBuf8<sizeof (CScreenUpdateWait)> buf;
       
   394 		Mem::FillZ(&buf, sizeof (CScreenUpdateWait));
       
   395 		CScreenUpdateWait* waitLoop = new (&buf) CScreenUpdateWait(screenNumber);
       
   396 		if (iRedrawWaitLoop.Append(waitLoop) == KErrNone)
       
   397 			{
       
   398 			// Run the active scheduler while updates are active
       
   399 			while (redrawCount-- && iScreenState[screenNumber]->IsActive())
       
   400 				waitLoop->Start();
       
   401 			
       
   402 			iRedrawWaitLoop.Remove(iRedrawWaitLoop.Count() - 1);			
       
   403 			}
       
   404 		waitLoop->~CScreenUpdateWait();
       
   405 		}
       
   406 	}
       
   407 
       
   408 /**
       
   409 Schedule an update for a specific screen at a given point in time.
       
   410 */ 
       
   411 void CWindowServer::CDefaultAnimationScheduler::ScheduleAnimation(MWsScreen& aScreen, const TTime& aWhen)
       
   412 	{	
       
   413 	TSchedule schedule;
       
   414 	schedule.iScreen = &aScreen;
       
   415 	schedule.iScheduled = ETrue;
       
   416 	schedule.iWhen = aWhen;
       
   417 	schedule.iScreenNumber = ScreenNumber (aScreen);
       
   418 	schedule.iRedraw = iRedrawScheduled;
       
   419 	iRedrawScheduled = EFalse;
       
   420 	TBool ok = EFalse;
       
   421 	const TInt idx = iSchedule.FindInUnsignedKeyOrder(schedule);
       
   422 	if(0 <= idx)
       
   423 		{
       
   424 		TSchedule& currSchedule=iSchedule[idx];
       
   425 		if(currSchedule.iScheduled)
       
   426 			{
       
   427 			if(currSchedule.iWhen > aWhen)
       
   428 				{
       
   429 				currSchedule.iWhen = aWhen;
       
   430 				}
       
   431 			}
       
   432 		else
       
   433 			{
       
   434 			currSchedule = schedule;
       
   435 			}
       
   436 		ok = ETrue;
       
   437 		}
       
   438 	else
       
   439 		ok = (KErrNone == iSchedule.InsertInUnsignedKeyOrder(schedule));
       
   440 
       
   441 	if(ok)
       
   442 		iIdleInitiator->CallBack();
       
   443 	}
       
   444 
       
   445 void CWindowServer::CDefaultAnimationScheduler::UnscheduleAnimation(MWsScreen& aScreen)
       
   446 	{
       
   447 	TSchedule schedule;
       
   448 	schedule.iScreen = &aScreen;
       
   449 	const TInt idx = iSchedule.FindInUnsignedKeyOrder(schedule);
       
   450 	if(0 <= idx)
       
   451 		iSchedule[idx].iScheduled = EFalse;
       
   452 	}
       
   453 
       
   454 TBool CWindowServer::CDefaultAnimationScheduler::OnIdleCallBack(TAny* aAny)
       
   455 	{
       
   456 	WS_ASSERT_DEBUG(aAny, EWsPanicWsGraphic);
       
   457 	
       
   458 	if(aAny)
       
   459 		static_cast<CDefaultAnimationScheduler*>(aAny)->OnIdleCallBack(EFalse);
       
   460 
       
   461 	return EFalse; //ignored by caller
       
   462 	}
       
   463 
       
   464 void CWindowServer::CDefaultAnimationScheduler::OnIdleCallBack(TBool aForce)
       
   465 	{
       
   466 	const TInt screenCount = iEnv.ScreenCount();
       
   467 	for(TInt ii = 0; ii < screenCount; ii++)
       
   468 		ScheduleUpdate (ii, aForce);
       
   469 	}
       
   470 
       
   471 
       
   472 
       
   473 /** 
       
   474 @return The number of microseconds (from now) that the specified scheduled update should be run at. This
       
   475 takes into account any set grace period and protects the scheduler from entering an infinite loop servicing
       
   476 animations with back-to-back frame updates.
       
   477 */
       
   478 TTimeIntervalMicroSeconds CWindowServer::CDefaultAnimationScheduler::GetDueDelta (TBool aForceRedraw, TSchedule* aScheduledUpdate)
       
   479 	{
       
   480 	WS_ASSERT_DEBUG(aScheduledUpdate, EWsPanicWsGraphic);
       
   481 	WS_ASSERT_DEBUG(aScheduledUpdate->iScheduled, EWsPanicWsGraphic);
       
   482 	
       
   483 	TTime now;
       
   484 	TInt64 grace = I64LIT(0); 
       
   485 	TTimeIntervalMicroSeconds thisUpdateDueIn = I64LIT(0); //Microseconds from now
       
   486 	
       
   487 	// Only use grace periods if not forcing due updates.
       
   488 	if (!aForceRedraw)
       
   489 		{
       
   490 		if (aScheduledUpdate->iRedraw)
       
   491 			grace = iRedrawGracePeriod;
       
   492 		else
       
   493 			grace = iAnimationGracePeriod;
       
   494 		}
       
   495 	
       
   496 	now.UniversalTime();
       
   497 	thisUpdateDueIn = aScheduledUpdate->iWhen.MicroSecondsFrom(now);
       
   498 	
       
   499 	// Add the grace period if the update is due in less time than the grace period.
       
   500 	if (thisUpdateDueIn < grace)
       
   501 		thisUpdateDueIn = grace;
       
   502 	else if (thisUpdateDueIn > KHalfHour)
       
   503 		thisUpdateDueIn = KHalfHour;
       
   504 	
       
   505 	return thisUpdateDueIn;
       
   506 	}
       
   507 
       
   508 /**
       
   509 Schedule an actual screen update at the point in time at which it is due. The due time may be modified by
       
   510 this method based on any "grace period" values.
       
   511  
       
   512 @param aScreen		Screen number to update.
       
   513 @param aForceRedraw Force redraws that are due. This causes grace periods not to be used.
       
   514 */
       
   515 void CWindowServer::CDefaultAnimationScheduler::ScheduleUpdate (TInt aScreenNumber, TBool aForceRedraw)
       
   516 	{	
       
   517 	// Schedule updates for any invalidated regions.
       
   518 	RedrawAllInvalidatedRegions (aScreenNumber);
       
   519 	
       
   520 	TSchedule* scheduledUpdate = GetScheduledScreenUpdate(aScreenNumber);
       
   521 	if (scheduledUpdate)
       
   522 		{
       
   523 		WS_ASSERT_DEBUG(scheduledUpdate->iScheduled, EWsPanicWsGraphic);
       
   524 		WS_ASSERT_DEBUG(aScreenNumber < iScreenState.Count(), EWsPanicWsGraphic);
       
   525 		
       
   526 		CScreenState& screenState = *iScreenState[aScreenNumber];
       
   527 				
       
   528 		// Initiate redraw if scheduled and not currently updating the display.
       
   529 		if(!screenState.IsActive())
       
   530 			{
       
   531 			TTimeIntervalMicroSeconds thisUpdateDueIn =	
       
   532 				GetDueDelta (aForceRedraw, scheduledUpdate);
       
   533 			
       
   534 			// Reschedule any preexisting update if this one is due earlier.
       
   535 			// If this update is not due earlier than a preexisting update then 
       
   536 			// there is nothing to do - just let the pending update occur.
       
   537 			TTime now;
       
   538 			now.UniversalTime();
       
   539 			TBool performUpdate = ETrue;
       
   540 			if(screenState.iUpdateOn->IsActive())
       
   541 				{
       
   542 				if (thisUpdateDueIn < screenState.iExpectedTickTime.MicroSecondsFrom(now))
       
   543 					screenState.iUpdateOn->Cancel();
       
   544 				else
       
   545 					performUpdate = EFalse;
       
   546 				}
       
   547 			
       
   548 			if (performUpdate)
       
   549 				{
       
   550 				if (thisUpdateDueIn.Int64() == 0) // Perform an immediate update if we are due.
       
   551 					{
       
   552 					screenState.iExpectedTickTime = now;
       
   553 					InvokeDueAnimation(aScreenNumber);
       
   554 					}
       
   555 				else // Schedule the tick at the appropriate time.
       
   556 					{
       
   557 					WS_ASSERT_DEBUG(thisUpdateDueIn.Int64() > 0, EWsPanicWsGraphic);
       
   558 					screenState.iExpectedTickTime = now + thisUpdateDueIn;
       
   559 					screenState.iUpdateOn->Start(thisUpdateDueIn.Int64(),0,TCallBack(InvokeDueAnimation, &screenState.iScreenUpdateDetails));
       
   560 					}
       
   561 				}
       
   562 			}
       
   563 		}
       
   564 	}
       
   565 
       
   566 /**
       
   567 @return 	A pointer to the scheduled update details currently associated with the specified screen.
       
   568 			If there is no scheduled update then NULL is returned.
       
   569 @note 		There is only ever one scheduled update per screen.
       
   570 */
       
   571 CWindowServer::CDefaultAnimationScheduler::TSchedule* CWindowServer::CDefaultAnimationScheduler::GetScheduledScreenUpdate(TInt aScreenNumber)
       
   572 	{
       
   573 	TSchedule* result = NULL;
       
   574 	const TInt count = iSchedule.Count();
       
   575 	for(TInt ii = 0; ii < count; ii++)
       
   576 		{
       
   577 		if (iSchedule[ii].iScreenNumber == aScreenNumber)
       
   578 			{
       
   579 			if (iSchedule[ii].iScheduled)
       
   580 				result = &iSchedule[ii];
       
   581 			break;
       
   582 			}
       
   583 		}
       
   584 	
       
   585 	return result;
       
   586 	}
       
   587 
       
   588 /**
       
   589 Redraw invalidated graphic IDs. If invalid regions exist, this will cause ScheduleRedraw() to be invoked.
       
   590 */ 
       
   591 void CWindowServer::CDefaultAnimationScheduler::RedrawAllInvalidatedRegions (TInt aScreen)
       
   592 	{	
       
   593 	WS_ASSERT_DEBUG(iScreenState.Count() > aScreen, EWsPanicWsGraphic);
       
   594 	
       
   595 	CScreenState& screenState = *iScreenState[aScreen];
       
   596 	if(screenState.iInvalidateAll || screenState.iInvalidated.Count())
       
   597 		{		
       
   598 		const TArray<TGraphicDrawerId> invalidArray = screenState.iInvalidated.Array();
       
   599 		MWsScreen* screen = iEnv.Screen(aScreen);
       
   600 		WS_ASSERT_DEBUG(screen, EWsPanicWsGraphic);
       
   601 		if(screen)
       
   602 			{
       
   603 			if(screenState.iInvalidateAll)
       
   604 				Redraw(*screen);
       
   605 			else
       
   606 				RedrawInvalid(*screen, screenState.iInvalidated.Array());
       
   607 			}
       
   608 		screenState.iInvalidateAll = EFalse;
       
   609 		}
       
   610 	screenState.iInvalidated.Reset();
       
   611 	}
       
   612 	
       
   613 TBool CWindowServer::CDefaultAnimationScheduler::InvokeDueAnimation(TAny* aAny)
       
   614 	{
       
   615 	WS_ASSERT_DEBUG(aAny, EWsPanicWsGraphic);
       
   616 	TScreenUpdateDetails* args = reinterpret_cast<TScreenUpdateDetails*>(aAny);
       
   617 	if(args)
       
   618 		args->iScheduler->InvokeDueAnimation (args->iScreenNumber);
       
   619 
       
   620 	return EFalse;
       
   621 	}
       
   622 
       
   623 void CWindowServer::CDefaultAnimationScheduler::InvokeDueAnimation(TInt aScreen)
       
   624 	{
       
   625 	WS_ASSERT_DEBUG(aScreen < iScreenState.Count(), EWsPanicWsGraphic);
       
   626 	CScreenState& screenState = *iScreenState[aScreen];
       
   627 	WS_ASSERT_DEBUG(!screenState.IsActive(), EWsPanicWsGraphic);
       
   628 
       
   629 	// All updates are driven through ScheduleRedraw() and ScheduleAnimation().
       
   630 	screenState.iUpdateOn->Cancel();
       
   631 	
       
   632 	TSchedule* scheduledUpdate = GetScheduledScreenUpdate(aScreen);	
       
   633 	if (scheduledUpdate)
       
   634 		{
       
   635 		WS_ASSERT_DEBUG(scheduledUpdate->iScheduled, EWsPanicWsGraphic);
       
   636 		
       
   637 		// Honour any flags that indicate we should not redraw. 
       
   638 		switch(iInactivityBehaviour)
       
   639 			{
       
   640 			case EStopAnimation :
       
   641 				// Stop server side drawing. Only the client may redraw if iInactive is set. 
       
   642 				if(iInactive && !scheduledUpdate->iRedraw)
       
   643 					{
       
   644 					iInactiveDraws = ETrue;
       
   645 					return;
       
   646 					}
       
   647 				break;
       
   648 			case EStopAllDrawing :
       
   649 				// Stop both client and server side drawing.
       
   650 				if(iInactive) 
       
   651 					{
       
   652 					iInactiveDraws = ETrue;
       
   653 					return;
       
   654 					}
       
   655 				break;
       
   656 			case EIgnore :
       
   657 				break;
       
   658 			default :
       
   659 				WS_ASSERT_DEBUG(EFalse, EWsPanicWsGraphic);
       
   660 				break;
       
   661 			}
       
   662 	
       
   663 		scheduledUpdate->iScheduled = EFalse;
       
   664 		screenState.SetActive();
       
   665 		Animate(*scheduledUpdate->iScreen, &(screenState.iStatus));
       
   666 		}
       
   667 	}
       
   668 
       
   669 // CWindowServer::CServer \\\\\\\\\\\\\\\\\\\\\\
       
   670 
       
   671 class CWindowServer::CServer : public CPolicyServer
       
   672 	{
       
   673 public:
       
   674 	static CServer* NewL()
       
   675 		{
       
   676 		return new(ELeave) CServer;
       
   677 		}
       
   678 	void StartL()
       
   679 		{
       
   680 		CPolicyServer::StartL(KWSERVServerName);
       
   681 		}
       
   682 	TInt SessionCount()
       
   683 		{
       
   684 		iSessionIter.SetToFirst();
       
   685 		TInt count=0;
       
   686 		while(iSessionIter++)
       
   687 			++count;
       
   688 		return(count);
       
   689 		}
       
   690 
       
   691 public: //from CPolicyServer
       
   692 	/** Creates a new client for this server. */
       
   693 	CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const
       
   694 		{
       
   695 		TVersion v(KWservMajorVersionNumber, KWservMinorVersionNumber, KWservBuildVersionNumber);
       
   696 		if (User::QueryVersionSupported(v, aVersion)==EFalse)
       
   697 			User::Leave(KErrNotSupported);
       
   698 		RThread thread;
       
   699 		User::LeaveIfError(aMessage.Client(thread));
       
   700 		return(new(ELeave) CWsClient(thread));
       
   701 		}
       
   702 private:
       
   703 	CServer() : CPolicyServer(EMainServerPriority, KWsServPolicy)
       
   704 	{}
       
   705 	};
       
   706 
       
   707 
       
   708 // CWindowServer \\\\\\\\\\\\\\\\\\\\\\\\\\\
       
   709 
       
   710 CWindowServer *CWindowServer::NewL()
       
   711 //
       
   712 // Create a new CWindowServer.
       
   713 //
       
   714 	{
       
   715 	CWindowServer* self = new(ELeave) CWindowServer();
       
   716 	CleanupStack::PushL(self);
       
   717 	self->ConstructL();
       
   718 	CleanupStack::Pop(self);
       
   719 	return self;
       
   720 	}
       
   721 
       
   722 CWindowServer::CWindowServer()
       
   723 //
       
   724 // Constructor.
       
   725 //
       
   726 	{
       
   727 	}
       
   728 
       
   729 CWindowServer::~CWindowServer()
       
   730 	{
       
   731 	delete iServer;
       
   732 
       
   733 	iMemoryReleases.Reset();
       
   734 	WS_ASSERT_DEBUG(iDrawerMasterIndex.IsEmpty(), EWsPanicWsGraphic);
       
   735 	iDrawerMasterIndex.Close();
       
   736 	
       
   737 	delete iDefaultAnimationScheduler;
       
   738 	iDefaultAnimationScheduler = NULL; //might be called from clients during server destruction
       
   739 	iCustomAnimationScheduler = NULL; // not owned	
       
   740 	}
       
   741 	
       
   742 void CWindowServer::ConstructL()
       
   743 	{
       
   744 	iServer = CServer::NewL();
       
   745 	CWsTop::PluginManager()->InitializePluginsL(*this); // plugins are loaded and own by CWsTop
       
   746 	iDefaultAnimationScheduler = new(ELeave) CDefaultAnimationScheduler(*this);
       
   747 	iDefaultAnimationScheduler->ConstructL();
       
   748 	RegisterMemoryRelease(this);
       
   749 	}
       
   750 
       
   751 void CWindowServer::StartL()
       
   752 	{
       
   753 	iServer->StartL();
       
   754 	}
       
   755 
       
   756 void CWindowServer::SetPinClientDescriptors(TBool aPin)
       
   757 	{
       
   758 	iServer->SetPinClientDescriptors(aPin);
       
   759 	}
       
   760 
       
   761 TInt CWindowServer::SessionCount()
       
   762 	{
       
   763 	return iServer->SessionCount();
       
   764 	}
       
   765 
       
   766 const CWsGraphicDrawer* CWindowServer::ResolveGraphic(const TGraphicDrawerId& aId) const
       
   767 	{
       
   768 	return iDrawerMasterIndex.ResolveGraphic(aId);
       
   769 	}
       
   770 	
       
   771 void CWindowServer::Invalidate(const TGraphicDrawerId& aId)
       
   772 	{
       
   773 	AnimationScheduler()->Invalidate(aId);
       
   774 	}
       
   775 	
       
   776 TInt CWindowServer::ScreenCount() const
       
   777 	{
       
   778 	return CWsTop::NumberOfScreens();
       
   779 	}
       
   780 
       
   781 MWsScreen* CWindowServer::Screen(TInt aIndex)
       
   782 	{
       
   783 	if((aIndex >= 0) && (aIndex < ScreenCount()))
       
   784 		{
       
   785 		return CWsTop::Screen(aIndex);
       
   786 		}
       
   787 	return NULL;
       
   788 	}
       
   789 	
       
   790 const MWsScreen* CWindowServer::Screen(TInt aIndex) const
       
   791 	{
       
   792 	if((aIndex >= 0) && (aIndex < ScreenCount()))
       
   793 		{
       
   794 		return CWsTop::Screen(aIndex);
       
   795 		}
       
   796 	return NULL;
       
   797 	}
       
   798 	
       
   799 /**
       
   800 Custom Animation Scheduler
       
   801 */
       
   802 TBool CWindowServer::SetCustomAnimationScheduler(MWsAnimationScheduler* aScheduler)
       
   803 	{
       
   804 	if(!iCustomAnimationScheduler && aScheduler)
       
   805 		{
       
   806 		iCustomAnimationScheduler = aScheduler;
       
   807 		return ETrue;
       
   808 		}
       
   809 	return EFalse;
       
   810 	}
       
   811 
       
   812 TBool CWindowServer::HasCustomAnimationScheduler() const
       
   813 	{
       
   814 	return !!iCustomAnimationScheduler;
       
   815 	}
       
   816 
       
   817 TBool CWindowServer::ClearCustomAnimationScheduler(MWsAnimationScheduler* aCurrentScheduler)
       
   818 	{
       
   819 	if(iCustomAnimationScheduler && (iCustomAnimationScheduler == aCurrentScheduler))
       
   820 		{
       
   821 		iCustomAnimationScheduler = NULL;
       
   822 		return ETrue;
       
   823 		}
       
   824 	return EFalse;
       
   825 	}
       
   826 	
       
   827 MWsAnimationScheduler* CWindowServer::AnimationScheduler()
       
   828 	{
       
   829 	if(iCustomAnimationScheduler)
       
   830 		{
       
   831 		return iCustomAnimationScheduler;
       
   832 		}
       
   833 	return iDefaultAnimationScheduler;
       
   834 	}
       
   835 
       
   836 TInt CWindowServer::RegisterEventHandler(CWsGraphicDrawer* aDrawer, MWsEventHandler* aHandler, TUint32 aEventMask)
       
   837 	{
       
   838 	if (!aDrawer || !aHandler || aEventMask==0)
       
   839 		return KErrArgument;
       
   840 	TInt err = TWindowServerEvent::RegisterDrawerHandler(aDrawer, aEventMask);
       
   841 	if (err != KErrNone)
       
   842 		return err;
       
   843 	aDrawer->SetEventHandler(aHandler);
       
   844 	return KErrNone;
       
   845 	}
       
   846 	
       
   847 TInt CWindowServer::UnregisterEventHandler(CWsGraphicDrawer* aDrawer)
       
   848 	{
       
   849 	if (!aDrawer || (aDrawer && !aDrawer->HasEventHandler()))
       
   850 		return KErrArgument;
       
   851 	TInt err = TWindowServerEvent::UnregisterDrawerHandler(aDrawer);
       
   852 	if (err != KErrNone)
       
   853 		return err;
       
   854 	aDrawer->SetEventHandler(NULL);
       
   855 	return KErrNone;
       
   856 	}
       
   857 	
       
   858 TInt CWindowServer::RegisterWsEventHandler(MWsEventHandler* aHandler, TUint32 aEventMask)
       
   859 	{
       
   860 	if (!aHandler || aEventMask==0)
       
   861 		return KErrArgument;
       
   862 	return TWindowServerEvent::RegisterWsEventHandler(aHandler, aEventMask);
       
   863 	}
       
   864 	
       
   865 TInt CWindowServer::UnregisterWsEventHandler(MWsEventHandler* aHandler)
       
   866 	{
       
   867 	return TWindowServerEvent::UnregisterWsEventHandler(aHandler);
       
   868 	}
       
   869 	
       
   870 TAny* CWindowServer::ResolveObjectInterface(TUint aTypeId)
       
   871 	{
       
   872 	switch(aTypeId)
       
   873 		{
       
   874 		case MWsActiveSchedulerDebug::EWsObjectInterfaceId:
       
   875 			return static_cast<MWsActiveSchedulerDebug*>(CWsActiveScheduler::Static());
       
   876 		case MWsIniFile::EWsObjectInterfaceId:
       
   877 			return static_cast<MWsIniFile*>(WsIniFile);
       
   878 		}
       
   879 	
       
   880 	if (CWsPluginManager *plugMgr=CWsTop::PluginManager())
       
   881 		return plugMgr->ResolveObjectInterface(aTypeId);
       
   882 	
       
   883 	return NULL;
       
   884 	}
       
   885 
       
   886 void CWindowServer::Log(TInt aPriority,const TDesC &aFmt,TInt aParam)
       
   887 	{
       
   888 	if (wsDebugLog)
       
   889 		{
       
   890 		wsDebugLog->MiscMessage(aPriority, aFmt, aParam);
       
   891 		}
       
   892 	}
       
   893 
       
   894 // CWsGraphicDrawer master index
       
   895 
       
   896 TInt CWindowServer::AddGraphicDrawer(CWsGraphicDrawer* aDrawer)
       
   897 	{
       
   898 	return iDrawerMasterIndex.Add(aDrawer);
       
   899 	}
       
   900 
       
   901 TInt CWindowServer::SwapGraphicDrawer(CWsGraphicDrawer* aDrawer)
       
   902 	{
       
   903 	return iDrawerMasterIndex.Swap(aDrawer);
       
   904 	}
       
   905 	
       
   906 TInt CWindowServer::RemoveGraphicDrawer(const TGraphicDrawerId& aId)
       
   907 	{
       
   908 	return iDrawerMasterIndex.Remove(aId);
       
   909 	}
       
   910 
       
   911 TInt CWindowServer::RemoveAllGraphicDrawers(const MWsClient& aOwner)
       
   912 	{
       
   913 	return iDrawerMasterIndex.RemoveAll(aOwner);
       
   914 	}
       
   915 
       
   916 TInt CWindowServer::RegisterMemoryRelease(MWsMemoryRelease * aMemoryRelease)
       
   917 	{
       
   918 	return iMemoryReleases.Append(aMemoryRelease);
       
   919 	}
       
   920 
       
   921 void CWindowServer::UnregisterMemoryRelease(MWsMemoryRelease * aMemoryRelease)
       
   922 	{
       
   923 	for (TInt ii = iMemoryReleases.Count() - 1; ii >= 0; --ii)
       
   924 		{
       
   925 		if (iMemoryReleases[ii] == aMemoryRelease)
       
   926 			{
       
   927 			iMemoryReleases.Remove(ii);
       
   928 			break;
       
   929 			}
       
   930 		}
       
   931 	}
       
   932 
       
   933 TBool CWindowServer::ReleaseMemory(TMemoryReleaseLevel aLevel)
       
   934 	{
       
   935 	return CWsWindow::ReleaseMemory(aLevel);
       
   936 	}
       
   937 
       
   938 TBool CWindowServer::ReleaseMemory()
       
   939 	{
       
   940 	TBool released = EFalse;
       
   941 	for (TInt level = MWsMemoryRelease::ELow; !released && level <= MWsMemoryRelease::EHigh; ++level)
       
   942 		{
       
   943 		for (TInt ii = iMemoryReleases.Count() - 1; !released && ii >= 0; --ii)
       
   944 			{
       
   945 			released = iMemoryReleases[ii]->ReleaseMemory(static_cast<TMemoryReleaseLevel>(level));
       
   946 			}
       
   947 		}
       
   948 	return released;
       
   949 	}
       
   950 
       
   951 void CWindowServer::DestroySessionsForShutdown()
       
   952 	{
       
   953 	delete iServer;
       
   954 	iServer = NULL;
       
   955 	}
       
   956