windowing/windowserver/nonnga/SERVER/WSTOP.CPP
changeset 0 5d03bc08d59c
child 116 171fae344dd4
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1994-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 // Top level window server code
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "wstop.h"
       
    19 
       
    20 #include <hal.h>
       
    21 #include "ANIM.H"
       
    22 #include "gc.h"
       
    23 #include "playbackgc.h"
       
    24 #include "rootwin.h"
       
    25 #include "windowgroup.h"
       
    26 #include "EVENT.H"
       
    27 #include "KEYCLICK.H"
       
    28 #include <w32std.h>
       
    29 #include "offscreenbitmap.h"
       
    30 #include "panics.h"
       
    31 #include "inifile.h"
       
    32 #include "pointer.h"
       
    33 #include "WSGRAPHICDRAWERFACTORY.H"
       
    34 #include "redrawmsgwindow.h"
       
    35 #include <Graphics/WSGRAPHICDRAWERINTERFACE.H>
       
    36 #include "WsMemMgr.h"
       
    37 #include "backedupwindow.h"
       
    38 #include "wsfont.h"
       
    39 #include "wstraces.h"
       
    40 #ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP
       
    41 #include <e32power.h>
       
    42 #endif
       
    43 #include "graphics/windowserverconstants.h"
       
    44 
       
    45 typedef CDebugLogBase *(*CreateDebugLog)(TBool aIsFirst, TDesC &aParams);
       
    46 
       
    47 CWsActiveScheduler* CWsActiveScheduler::Static()
       
    48 	{
       
    49 	return static_cast<CWsActiveScheduler*>(CActiveScheduler::Current());
       
    50 	}
       
    51 	
       
    52 CWsActiveScheduler::CWsActiveScheduler(): iNumSamples(100)
       
    53 	{
       
    54 	iRun = User::FastCounter();
       
    55 	if((KErrNone == HAL::Get(HALData::EFastCounterFrequency,iFastCounterFreq)) && iFastCounterFreq)
       
    56 		{
       
    57 		iData = reinterpret_cast<TSample*>(User::AllocZ(sizeof(TSample)*iNumSamples));
       
    58 		}
       
    59 	}
       
    60 
       
    61 CWsActiveScheduler::~CWsActiveScheduler()
       
    62 	{
       
    63 	User::FreeZ(reinterpret_cast<void*&>(iData));
       
    64 	}
       
    65 	
       
    66 void CWsActiveScheduler::PrepareDraw()
       
    67 	{
       
    68 	WS_ASSERT_DEBUG((ENormal == iState)||(EDrawn == iState),EWsPanicActiveScheduler);
       
    69 	__DEBUG_ONLY(iState = EPreparingDraw;)
       
    70 	iRunDraw = User::FastCounter();
       
    71 	}
       
    72 	
       
    73 void CWsActiveScheduler::CancelPrepare()
       
    74 	{
       
    75 	WS_ASSERT_DEBUG(EPreparingDraw == iState,EWsPanicActiveScheduler);
       
    76 	__DEBUG_ONLY(iState = ENormal;)
       
    77 	}
       
    78 	
       
    79 void CWsActiveScheduler::StartDraw()
       
    80 	{
       
    81 	WS_TRACE_SERVER_STARTDRAW();
       
    82 	WS_ASSERT_DEBUG(EPreparingDraw == iState,EWsPanicActiveScheduler);
       
    83 	__DEBUG_ONLY(iState = EDrawing;)
       
    84 	TTime now;
       
    85 	now.UniversalTime();
       
    86 	TUint64 duration = now.MicroSecondsFrom(iRunDraw).Int64();
       
    87 	iPreparing += duration;
       
    88 	iRunDraw = now;
       
    89 	if(iData)
       
    90 		{
       
    91 		iData[iCurrent].iStart = iRunDraw;
       
    92 		}
       
    93 	iDraws++;
       
    94 	}
       
    95 
       
    96 void CWsActiveScheduler::DrawStats(TInt& aUpdatesPerSecond,TInt64& aPixelsPerSecond,TInt aWindowInSeconds) const
       
    97 	{
       
    98 	aUpdatesPerSecond=0;
       
    99 	aPixelsPerSecond=0;
       
   100 	if(iData)
       
   101 		{
       
   102 		// work out statistic
       
   103 		TTime window;
       
   104 		window.UniversalTime();
       
   105 		window-=TTimeIntervalSeconds(aWindowInSeconds);
       
   106 		TUint32 pixels=0;
       
   107 		TInt64 duration=0;
       
   108 		for(TInt ii=0;ii<iNumSamples;++ii)
       
   109 			{
       
   110 			if (iData[ii].iStart>=window)
       
   111 				{
       
   112 				pixels+=iData[ii].iPixels;
       
   113 				duration+=iData[ii].iDuration;
       
   114 				++aUpdatesPerSecond;
       
   115 				}
       
   116 			}
       
   117 		if (aUpdatesPerSecond && duration)
       
   118 			{
       
   119 			aPixelsPerSecond=pixels;
       
   120 			aPixelsPerSecond=(aPixelsPerSecond*1000000)/duration;
       
   121 			aUpdatesPerSecond/=aWindowInSeconds;
       
   122 			}
       
   123 		}
       
   124 	}
       
   125 
       
   126 void CWsActiveScheduler::StopDraw(TInt aPixelsUpdated)
       
   127 	{
       
   128 	WS_TRACE_SERVER_STOPDRAW();
       
   129 	WS_ASSERT_DEBUG(EDrawing == iState,EWsPanicActiveScheduler);
       
   130 	__DEBUG_ONLY(iState = EDrawn;)
       
   131 	TTime now;
       
   132 	now.UniversalTime();
       
   133 	TUint32 duration = now.MicroSecondsFrom(iRunDraw).Int64();
       
   134     // do recording
       
   135 	if(iData)
       
   136 		{
       
   137 		iData[iCurrent].iDuration = now.MicroSecondsFrom(iData[iCurrent].iStart).Int64();
       
   138 		iData[iCurrent].iPixels = aPixelsUpdated;
       
   139 		if(++iCurrent >= iNumSamples)
       
   140 			{
       
   141 			iCurrent = 0;
       
   142 			}
       
   143 		}
       
   144 	iDrawing += duration;
       
   145 	}
       
   146 
       
   147 void CWsActiveScheduler::WaitForAnyRequest()
       
   148 	{
       
   149 	WS_ASSERT_DEBUG((ENormal == iState)||(EDrawn == iState),EWsPanicActiveScheduler);
       
   150 	TTime stop;
       
   151 	stop.UniversalTime();
       
   152 	iTotal += stop.MicroSecondsFrom(iRun).Int64();
       
   153 	CActiveScheduler::WaitForAnyRequest();
       
   154 	iRequests++;
       
   155 	__DEBUG_ONLY(iState = ENormal;)
       
   156 	iRun.UniversalTime();
       
   157 	iIdle += iRun.MicroSecondsFrom(stop).Int64();
       
   158 	}
       
   159 
       
   160 	
       
   161 void CWsActiveScheduler::Error(TInt /*aError*/) const
       
   162 	{
       
   163 	iErrors++;
       
   164 	}
       
   165 
       
   166 void CWsActiveScheduler::AccumReclaimedIdleTime(TInt64 aMicroSeconds)
       
   167 	{
       
   168 	iReclaimedIdleTime += aMicroSeconds;
       
   169 	}
       
   170 	
       
   171 
       
   172 GLREF_C void StateDump(CWsRootWindow* aRootWindow);
       
   173 GLREF_C void HeapDump();
       
   174 
       
   175 // Static objects that need to be destroyed on exit
       
   176 GLDEF_D CDebugLogBase *wsDebugLog=NULL;
       
   177 GLDEF_D TInt wsDebugLogLevel=0;
       
   178 GLDEF_D CIniFile *WsIniFile=NULL;
       
   179 //
       
   180 GLDEF_D TPtr nullDescriptor(NULL,0);
       
   181 
       
   182 LOCAL_D CWsActiveScheduler *TheActiveScheduler;
       
   183 #if defined(__WINS__)
       
   184 LOCAL_D TPtrC shellCmd;
       
   185 #endif
       
   186 
       
   187 CScreen* CWsTop::iCurrentFocusScreen;
       
   188 CArrayPtrFlat<CScreen>* CWsTop::iScreens ;
       
   189 TInt CWsTop::iNumberOfScreens ;
       
   190 CWsTop::CShellStarter* CWsTop::iShellStarter;
       
   191 
       
   192 CWindowServer *CWsTop::iServer;
       
   193 RLibrary CWsTop::iDebugLib;
       
   194 CWsShellLogon *CWsTop::iShell;
       
   195 const CWsClient *CWsTop::iShellClient;
       
   196 TBool CWsTop::iPreviousShellClient=EFalse;
       
   197 TInt CWsTop::iShellBootMode;
       
   198 TBool CWsTop::iShuttingDown;
       
   199 TBool CWsTop::iIsFirstLog=ETrue;
       
   200 CWsWindowBase *CWsTop::iWindowToSendOffEventsTo=NULL;
       
   201 RTimer CWsTop::iTimer;
       
   202 TBool CWsTop::iIgnoreSwitchOffEvent=EFalse;
       
   203 TBool CWsTop::iFadeEnabled=ETrue;
       
   204 TBool CWsTop::iFinishEveryFlush=EFalse;
       
   205 TBool CWsTop::iMultiFocusPolicy=EFalse;
       
   206 #if defined(__WINS__)
       
   207 TFullName WsSemName;
       
   208 #endif
       
   209 const CWsClient* CWsTop::iTriggerHeapCheckOnClientExit=NULL;
       
   210 TWsCheckHeapOnDisconnectMode CWsTop::iHeapCheckMode=EWsCheckHeapOnDisconnectModeNone;
       
   211 TInt CWsTop::iCheckHeapResult=KErrNotReady;
       
   212 TBool CWsTop::iDoHeapCheckAndRestart=EFalse;
       
   213 #define RFbsSession_SendCommand_ShutDownMessage 1	// A FBS message that is not published yet and probably never will be.
       
   214 void CWsTop::DeleteStaticsL()
       
   215 	{
       
   216 	iShuttingDown=ETrue;
       
   217 	CClick::DeleteStatics();
       
   218 	WsPointer::DeleteStatics();
       
   219 	CWsClient::DeleteStatics();
       
   220 //
       
   221 	delete iShellStarter;
       
   222 	delete iServer;
       
   223 
       
   224 	CWsBackedUpWindow::StaticDestroy();
       
   225 	TWindowServerEvent::DeleteStatics();
       
   226 	delete iShell;
       
   227 	DisableLogging();
       
   228 
       
   229 	CEventQueue::DeleteStaticsL();
       
   230 		
       
   231 	CWsSpriteBase::DeleteStatics();
       
   232 	CWsGc::DeleteStatics();
       
   233 	CPlaybackGc::DeleteStatics();
       
   234 	CWsAnim::DeleteStatics();		//This destroys a GC so must be done while FBSERV is still around
       
   235 	CWsAnimDll::DeleteStatics();
       
   236 	CWsFontCache::DestroyInstance();
       
   237 
       
   238 	iScreens->ResetAndDestroy() ;
       
   239 	delete iScreens ;
       
   240 
       
   241 	if (!iDoHeapCheckAndRestart)
       
   242 		{
       
   243 		RFbsSession::GetSession()->SendCommand(RFbsSession_SendCommand_ShutDownMessage);		//This line is just being tidy, never really does anything useful.
       
   244 		}
       
   245 
       
   246 	RFbsSession::Disconnect();
       
   247 	iDebugLib.Close();
       
   248 	iTimer.Close();
       
   249 //
       
   250 	delete WsIniFile;
       
   251 	delete TheActiveScheduler;
       
   252 	WsGraphicDrawer::FinalClose();
       
   253 	}
       
   254 
       
   255 RWsTextCursor *CWsTop::CurrentTextCursor()
       
   256 	{
       
   257 	return(FocusWindowGroup() ? FocusWindowGroup()->TextCursor():NULL);
       
   258 	}
       
   259 
       
   260 CWsClient *CWsTop::FocusWindowGroupOwner()
       
   261 	{
       
   262 	return(FocusWindowGroup() ? FocusWindowGroup()->WsOwner():NULL);
       
   263 	}
       
   264 
       
   265 void CWsTop::ClientDestroyed(const CWsClient *aClient)
       
   266 	{
       
   267 	if (aClient==iShellClient)
       
   268 		iShellClient=NULL;
       
   269 	}
       
   270 
       
   271 void CWsTop::NewSession(const CWsClient *aClient)
       
   272 	{
       
   273 	if (iShellClient==NULL && iShell)
       
   274 		{
       
   275 #if defined(__WINS__)
       
   276 		RThread proc;
       
   277 		proc=aClient->Client();
       
   278 #else
       
   279 		RProcess proc;
       
   280 		aClient->Client().Process(proc);
       
   281 #endif
       
   282 		TFullName procName = proc.FullName();
       
   283 		// Before comparing the proc name with iShell name , truncate the proc name up to the actual name
       
   284 		// referring to the process, by removing the part which starts with ':', if exists.
       
   285 		TInt colonLocation = procName.Locate(':');
       
   286 		if( KErrNotFound != colonLocation)
       
   287 			{
       
   288 			procName = procName.Left(colonLocation);
       
   289 			}
       
   290 		if (procName ==iShell->FullName())
       
   291 			{
       
   292 			iShellClient=aClient;
       
   293 			if (!iPreviousShellClient)
       
   294 				{
       
   295 				iPreviousShellClient=ETrue;
       
   296 				aClient->Screen()->RootWindow()->SetColorIfClear();
       
   297 				}
       
   298 			}
       
   299 #if !defined(__WINS__)
       
   300 		proc.Close();
       
   301 #endif
       
   302 		}	
       
   303 	}
       
   304 
       
   305 void CWsTop::SessionExited(CWsClient *aClient)
       
   306 	{
       
   307 	if (iShuttingDown)
       
   308 		{
       
   309 		RProcess proc;
       
   310 		TInt err=aClient->Client().Process(proc);
       
   311 		if (err==KErrNone && proc.Id()!=RProcess().Id())
       
   312 			proc.Kill(0);
       
   313 		else
       
   314 			const_cast<RThread&>(aClient->Client()).Kill(0);
       
   315 		if (err==KErrNone)
       
   316 			proc.Close();
       
   317 		}
       
   318 	else if (iHeapCheckMode!=EWsCheckHeapOnDisconnectModeNone && aClient==iTriggerHeapCheckOnClientExit)
       
   319 		{
       
   320 		if (iHeapCheckMode==EWsCheckHeapOnDisconnectModeOnce)
       
   321 			{
       
   322 			iHeapCheckMode=EWsCheckHeapOnDisconnectModeNone;
       
   323 			}
       
   324 		iTriggerHeapCheckOnClientExit=NULL;
       
   325 		iDoHeapCheckAndRestart=ETrue;
       
   326 		Exit();
       
   327 		}
       
   328 	if (iServer->SessionCount()==1 && iShellBootMode==EShellBootModeNoReboot && iShell==NULL)
       
   329 		StartShell();
       
   330 	}
       
   331 
       
   332 
       
   333 void CWsTop::RunServerL()
       
   334 	{
       
   335 	InitStaticsL();
       
   336 	CWsMemoryManager* memMgr = CWsMemoryManager::NewLC();
       
   337 	CActiveScheduler::Start();
       
   338 	CleanupStack::PopAndDestroy(memMgr);
       
   339 	DeleteStaticsL();
       
   340 	}
       
   341 
       
   342 void CWsTop::InitStaticsL()
       
   343 	{
       
   344 	iShuttingDown=EFalse;
       
   345 	// By default shell should be started.
       
   346 	TBool startShell = ETrue;
       
   347 
       
   348 	// The windows server has been invoked.
       
   349 	// This may have been from the system starter (via a
       
   350 	// start up rss file)  
       
   351 	// This block looks for a "-NoShell" argument in the invocation.
       
   352 	// The existence of the argument means that shell does not need to be 
       
   353 	// invoked from here because the new system starter
       
   354 	// is in charge, and it will do it if required.
       
   355 	
       
   356 	_LIT(KNoShell,"-NOSHELL");
       
   357 	
       
   358 	TInt argLen = User::CommandLineLength();
       
   359 	if(argLen)
       
   360 		{
       
   361 		HBufC* arg = HBufC::NewLC(argLen);
       
   362 		TPtr argPtr = arg->Des();
       
   363 		User::CommandLine(argPtr);
       
   364 		argPtr.UpperCase();
       
   365 
       
   366 		if(KErrNotFound != argPtr.Find(KNoShell))
       
   367 			{
       
   368 			// Don't start the shell. It will be started if required by 
       
   369 			// the system starter.
       
   370 			startShell = EFalse;
       
   371 			}
       
   372 		CleanupStack::PopAndDestroy(arg);
       
   373 		}
       
   374 		
       
   375 	TheActiveScheduler=new(ELeave) CWsActiveScheduler;
       
   376 	CActiveScheduler::Install(TheActiveScheduler);
       
   377 	
       
   378 //
       
   379 	WsIniFile=CIniFile::NewL();
       
   380 	_LIT(KWSERVIniFileVarLogEnable,"LOGENABLE");
       
   381 	TInt loggingLevel;
       
   382 	if (WsIniFile->FindVar(KWSERVIniFileVarLogEnable,loggingLevel))
       
   383 		{
       
   384 		EnableLogging(EDoNotReloadWsIni);
       
   385 		if (wsDebugLog)
       
   386 			{
       
   387 			wsDebugLog->SetLoggingLevel(loggingLevel);
       
   388 			}
       
   389 		}
       
   390 		
       
   391 	_LIT(KWSERVIniFileVarFadeEnable,"FADEDISABLE");
       
   392 	iFadeEnabled = !WsIniFile->FindVar(KWSERVIniFileVarFadeEnable);
       
   393 
       
   394 	_LIT(KWSERVIniFileVarFinishEveryFlush,"FINISHEVERYFLUSH");
       
   395 	iFinishEveryFlush = WsIniFile->FindVar(KWSERVIniFileVarFinishEveryFlush);
       
   396 	
       
   397 	_LIT(KWSERVIniFileVarSwitchOffEvent,"IGNORESWITCHOFFEVENT");
       
   398 	iIgnoreSwitchOffEvent = WsIniFile->FindVar(KWSERVIniFileVarSwitchOffEvent);	
       
   399 
       
   400 	iServer=CWindowServer::NewL();
       
   401 	CClick::InitStaticsL();
       
   402 	
       
   403 	RProcess wservProc;
       
   404 	if (!wservProc.DefaultDataPaged())
       
   405 	{
       
   406 		iServer->SetPinClientDescriptors(ETrue);
       
   407 	}
       
   408 //
       
   409 	iServer->StartL(KWSERVServerName);
       
   410 //
       
   411 	User::LeaveIfError(FbsStartup());
       
   412 	User::LeaveIfError(RFbsSession::Connect());
       
   413 	User::LeaveIfError(iTimer.CreateLocal());
       
   414 
       
   415 	TWindowServerEvent::InitStaticsL();
       
   416 	//-------------------------------------------
       
   417 	User::LeaveIfError(  HAL::Get( HAL::EDisplayNumberOfScreens, iNumberOfScreens ) ) ; 
       
   418 	// Check that the INI file matches the HAL
       
   419 	WS_ASSERT_ALWAYS(WsIniFile->NumberOfScreens()<=iNumberOfScreens, EWsPanicScreenInformationError);
       
   420 
       
   421 	iScreens = new (ELeave) CArrayPtrFlat<CScreen>( iNumberOfScreens ) ;  //
       
   422 	// now construct screens for as long as there is information
       
   423 	
       
   424 	TInt ii ;
       
   425 	for ( ii = 0 ; ii < iNumberOfScreens ; ++ii )
       
   426 		{
       
   427 		InitScreenL( ii ) ;
       
   428 		}
       
   429 	//---------------------------------------------
       
   430 	iCurrentFocusScreen = (*iScreens)[0] ;
       
   431 
       
   432 	CWsFontCache::CreateInstanceL();
       
   433 	CWsGc::InitStaticsL();
       
   434 	CPlaybackGc::InitStaticsL();
       
   435 	CWsSpriteBase::InitStaticsL();
       
   436 	CEventQueue::InitStaticsL();
       
   437 
       
   438 //
       
   439 	CWsAnimDll::InitStaticsL();
       
   440 	CWsAnim::InitStaticsL();
       
   441 //
       
   442 	TInt bootMode=0;
       
   443 	_LIT(KWSERVIniFileVarReboot,"REBOOT");
       
   444 	WsIniFile->FindVar(KWSERVIniFileVarReboot,bootMode);
       
   445 	if (bootMode>=0 && bootMode<=2)
       
   446 		iShellBootMode=bootMode;
       
   447 //
       
   448 	CWsBackedUpWindow::StaticInitL();
       
   449 	CWsRedrawMsgWindow::StaticInitL();
       
   450 //
       
   451 	WsPointer::InitStaticsL();
       
   452 	iShellStarter=new (ELeave) CShellStarter;
       
   453 	iShellStarter->ConstructL();
       
   454 	_LIT(KPreProcess,"REMOVEFADINGONFOCUSGAIN");
       
   455 	CWsWindowGroup::SetFocusGainPreprocessing(WsIniFile->FindVar(KPreProcess));
       
   456 	_LIT(KAbsFade,"ABSOLUTEFADING");
       
   457 	CWsClientWindow::SetAbsoluteFading(WsIniFile->FindVar(KAbsFade));
       
   458 
       
   459 //Set the focus policy
       
   460 	_LIT(KFocusPolicy,"MULTIFOCUSPOLICY");
       
   461 	if(WsIniFile->FindVar(KFocusPolicy))
       
   462 		{
       
   463 		iMultiFocusPolicy = ETrue;	
       
   464 		}
       
   465 	RProcess::Rendezvous(KErrNone);
       
   466 	// Start the shell from here unless the 'NoShell' option has been 
       
   467 	// received indicating that the system starter will start the shell directly.
       
   468 	if(startShell)
       
   469 		{
       
   470 		StartShell();
       
   471 		}
       
   472 	UserSvr::WsRegisterSwitchOnScreenHandling(ETrue);
       
   473 	}
       
   474 
       
   475 
       
   476 void CWsTop::InitScreenL( TInt aScreenNumber)  // static
       
   477 	{
       
   478 	// create a new screen,  read ini file for aScreenNumber (this happens in CScreen - just need to pass a screen number from here
       
   479 	CScreen* screen = new (ELeave) CScreen() ;
       
   480 	CleanupStack::PushL( screen ) ;
       
   481 	TRect digitiserArea;
       
   482 	if (aScreenNumber==0)
       
   483 		{
       
   484 		TMachineInfoV1Buf machineBuf;
       
   485 		UserHal::MachineInfo(machineBuf);
       
   486 		TMachineInfoV1& machineInfo=*(TMachineInfoV1*)machineBuf.Ptr();
       
   487 		digitiserArea = TRect(-machineInfo.iOffsetToDisplayInPixels,machineInfo.iXYInputSizeInPixels);
       
   488 		}
       
   489 	screen->ConstructL(digitiserArea, aScreenNumber);
       
   490 	iScreens->AppendL( screen ) ; 
       
   491 	CleanupStack::Pop( screen ) ;
       
   492 	}
       
   493 
       
   494 void CWsTop::UpdateAllScreens()
       
   495 	{
       
   496 	TInt ii;
       
   497 	for (ii=0; ii<iNumberOfScreens; ++ii)
       
   498 		{
       
   499 		(*iScreens)[ii]->Update();
       
   500 		}
       
   501 	}
       
   502 
       
   503 void CWsTop::ClearAllRedrawStores()
       
   504 	{
       
   505 	TInt ii;
       
   506 	for (ii=0; ii<iNumberOfScreens; ++ii)
       
   507 		{
       
   508 		CScreen *screen=(*iScreens)[ii];
       
   509 		CWsWindowGroup* group=screen->RootWindow()->Child();
       
   510 		while (group!=NULL)
       
   511 			{
       
   512 			CWsWindowBase* win=group->Child();
       
   513 			if (win)
       
   514 				{
       
   515 				while (win!=group)
       
   516 					{
       
   517 					static_cast<CWsWindow*>(win)->Redraw()->ClearRedrawStore(ETrue);
       
   518 					if (win->BaseChild())
       
   519 						win=win->BaseChild();
       
   520 					else
       
   521 						{
       
   522 						do	
       
   523 							{
       
   524 							if (win->NextSibling())
       
   525 								{
       
   526 								win=win->NextSibling();
       
   527 								break;
       
   528 								}
       
   529 							win=win->BaseParent();
       
   530 							}
       
   531 						while (win!=group);
       
   532 						}
       
   533 					}
       
   534 				}
       
   535 			group=group->NextSibling();
       
   536 			}
       
   537 		TriggerRedraws(screen->RootWindow());
       
   538 		}
       
   539 	}
       
   540 
       
   541 void CWsTop::Exit()
       
   542 	{
       
   543 	CActiveScheduler::Stop();
       
   544 	}
       
   545 
       
   546 void CWsTop::TriggerRedraws(CWsRootWindow* aRootWindow)
       
   547 	{
       
   548 	for(CWsWindowGroup *group=aRootWindow->Child();group!=NULL;group=group->NextSibling())
       
   549 		group->WsOwner()->TriggerRedraw();
       
   550 	}
       
   551 
       
   552 void CWsTop::StartShell()
       
   553 	{
       
   554 	TRAPD(err,iShell=new(ELeave) CWsShellLogon());
       
   555 	if (err==KErrNone)
       
   556 		{
       
   557 		RFs fs;
       
   558 		if ((err=fs.Connect())==KErrNone)
       
   559 			{
       
   560 			fs.SetNotifyUser(EFalse);
       
   561 			TRAP(err,iShell->ConstructL(fs));
       
   562 			fs.Close();
       
   563 			}
       
   564 		}
       
   565 	if (err!=KErrNone)
       
   566 		{
       
   567 #ifdef _DEBUG
       
   568 		RDebug::Print(_L("Failed to start shell: err=%d\n"),err);
       
   569 #endif
       
   570 		delete iShell;
       
   571 		iShell=NULL;
       
   572 		iShellStarter->After(TTimeIntervalMicroSeconds32(1000000));
       
   573 		}
       
   574 	}
       
   575 
       
   576 void CWsTop::ShellExited()
       
   577 	{
       
   578 	delete iShell;
       
   579 	iShell=NULL;
       
   580 	switch(iShellBootMode)
       
   581 		{
       
   582 		case EShellBootModeReboot:
       
   583 			StartShell();
       
   584 			break;
       
   585 		case EShellBootModeNoReboot:
       
   586 			if (iServer->SessionCount()==0)
       
   587 				StartShell();
       
   588 			break;
       
   589 		case EShellBootModeExit:
       
   590 			Exit();
       
   591 			break;
       
   592 		}
       
   593 	}
       
   594 
       
   595 TInt CWsTop::SetSendOffEventsToShell(CWsClient *aClient,const TWsClCmdOffEventsToShell &aData)
       
   596 	{
       
   597 	CWsWindowBase *window=NULL;
       
   598 	if (aData.window==0)
       
   599 		{
       
   600 		if (aData.on)
       
   601 			aClient->PPanic(EWservPanicNoWindowSpecifed);
       
   602 		}
       
   603 	else
       
   604 		aClient->HandleToWindow(aData.window,&window);
       
   605 	if (aData.on)
       
   606 		{
       
   607 		if (iWindowToSendOffEventsTo!=NULL && aClient!=iShellClient)		//Allow the shell to pinch it
       
   608 			return KErrAlreadyExists;
       
   609 		iWindowToSendOffEventsTo=window;
       
   610 		}
       
   611 	else
       
   612 		{
       
   613 		if (iWindowToSendOffEventsTo==window || (!window && aClient==iWindowToSendOffEventsTo->WsOwner()))
       
   614 			iWindowToSendOffEventsTo=NULL;
       
   615 		}
       
   616 	return KErrNone;
       
   617 	}
       
   618 
       
   619 void CWsTop::StopWindowGettingOffEvents(CWsWindowBase* aWindow)
       
   620 	{
       
   621 	if (aWindow==iWindowToSendOffEventsTo)
       
   622 		iWindowToSendOffEventsTo=NULL;
       
   623 	}
       
   624 
       
   625 /** Routes "Off" events to the shutdown manager if one is registered. Othwerwise calls Power API's directly to
       
   626 set the power mode of the device accordingly.
       
   627 @internalTechnology
       
   628 @released
       
   629 @param aEvent Type of event that Wserv passes to client as OFF events. 
       
   630 It can be EEventSwitchOff, EEventCaseClosed, EEventKeySwitchOff or EEventRestartSystem.
       
   631 @param aDoSwitchOff ETrue if the switch-off should be performed when no shutdown manager is registered
       
   632 and IGNORESWITCHOFFEVENT is not defined in wsini.ini
       
   633 */
       
   634 void CWsTop::HandleSwitchOff(TInt aEvent,TBool aDoSwitchOff)
       
   635 	{
       
   636 	// If any shutdown manager is registered, forward the event to it
       
   637 	if (iWindowToSendOffEventsTo && iWindowToSendOffEventsTo->QueueEvent(aEvent))
       
   638 		return;
       
   639 	// Otherwise, do the shutdown here
       
   640 	if(!iIgnoreSwitchOffEvent && aDoSwitchOff)
       
   641 		{
       
   642 #ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP		
       
   643 		// if LaF is not registered, restart or shutdown using Power API 
       
   644 		if (aEvent == EEventRestartSystem) // restart
       
   645 			{
       
   646 			if (Power::EnableWakeupEvents(EPwRestart) == KErrNone)
       
   647 				{
       
   648 				// Should reboot/power-cycle the system, so no need to RequestWakeupEventNotification
       
   649 				Power::PowerDown();
       
   650 				}
       
   651 			}
       
   652 		else // everything else maps to standby for now
       
   653 			{
       
   654 			if (Power::EnableWakeupEvents(EPwStandby) == KErrNone)
       
   655 				{
       
   656 				// Prepare to wake up from standby
       
   657 				TRequestStatus s;
       
   658 				Power::RequestWakeupEventNotification(s);
       
   659 				Power::PowerDown();
       
   660 				User::WaitForRequest(s);
       
   661 				}
       
   662 			}
       
   663 #else
       
   664 		UserHal::SwitchOff();
       
   665 #endif			
       
   666 		}
       
   667 	}
       
   668 
       
   669 void CWsTop::RedrawScreens()
       
   670 	{
       
   671 	// apply to all screens
       
   672 	TInt screenNo;
       
   673 	for(screenNo=0; screenNo<iNumberOfScreens; ++screenNo)
       
   674 		{
       
   675 		CScreen* screen = Screen(screenNo);
       
   676 		TRegionFix<1> screenArea(TRect(screen->DrawableArea()));
       
   677 		screen->Update(screenArea);
       
   678 		}
       
   679 	}
       
   680 
       
   681 void CWsTop::EnableLogging(TReloadWsIni aSetting)
       
   682 	{
       
   683 	TInt errorLoc=0;
       
   684 	if (wsDebugLog)
       
   685 		{
       
   686 		if (wsDebugLogLevel==CDebugLogBase::ELogEverything)
       
   687 			{
       
   688 			wsDebugLogLevel=CDebugLogBase::ELogImportant;
       
   689 			wsDebugLog->SetLoggingLevel(wsDebugLogLevel);
       
   690 			return;
       
   691 			}
       
   692 		DisableLogging();
       
   693 		}
       
   694 
       
   695      if (aSetting == EDoReloadWsIni)
       
   696         {
       
   697         CIniFile* temp = NULL;
       
   698         TRAPD(err, temp = CIniFile::NewL());
       
   699         if (err == KErrNone)
       
   700             {
       
   701             //loading successful, replace the previous one
       
   702             delete WsIniFile;
       
   703             WsIniFile = temp;
       
   704             }
       
   705         }
       
   706 
       
   707 	TPtrC dlog;
       
   708 	_LIT(KWSERVDebugLogFileName,"DLOG");
       
   709 	TBuf<KMaxFileName> fname(KWSERVDebugLogFileName);
       
   710 	_LIT(KWSERVIniFileVarLog,"LOG");
       
   711 	if (WsIniFile->FindVar(KWSERVIniFileVarLog,dlog) && dlog.Length()==2)
       
   712 		{
       
   713 		fname.Append(dlog);
       
   714 		TInt err=iDebugLib.Load(fname);
       
   715 		if (err==KErrNone)
       
   716 			{
       
   717 			TUidType uid=iDebugLib.Type();
       
   718 			if (uid[1]!=KWservLoggingDllUid)
       
   719 				{
       
   720 				err=KErrNotSupported;
       
   721 				errorLoc=2;
       
   722 				}
       
   723 			else
       
   724 				{
       
   725 				TPtrC params;
       
   726 				_LIT(KWSERVIniFileVarLogP,"LOGP");
       
   727 				if (!WsIniFile->FindVar(KWSERVIniFileVarLogP,params))
       
   728 					params.Set(NULL,0);
       
   729 				CreateDebugLog func=(CreateDebugLog)iDebugLib.Lookup(1);
       
   730 				if (func!=NULL)
       
   731 					{
       
   732 					TRAP(err,wsDebugLog=(*func)(iIsFirstLog, params));
       
   733 					if (err==KErrNone)
       
   734 						{
       
   735 						iIsFirstLog=EFalse;
       
   736 						wsDebugLogLevel=CDebugLogBase::ELogEverything;
       
   737 						}
       
   738 					else
       
   739 						errorLoc=4;
       
   740 					}
       
   741 				else
       
   742 					errorLoc=3;
       
   743 				}
       
   744 			}
       
   745 		else
       
   746 			errorLoc=1;
       
   747 		if (iCurrentFocusScreen)
       
   748 			{
       
   749 			TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::ELogging,(errorLoc<<8)-err);
       
   750 			}
       
   751 		}
       
   752 	}
       
   753 
       
   754 void CWsTop::DisableLogging()
       
   755 	{
       
   756 	delete wsDebugLog;
       
   757 	wsDebugLog=NULL;
       
   758 	iDebugLib.Close();
       
   759 	}
       
   760 
       
   761 void CWsTop::LogCommand(RWsSession::TLoggingCommand aCommand)
       
   762 	{
       
   763 	switch(aCommand)
       
   764 		{
       
   765 	case RWsSession::ELoggingEnable:
       
   766 		EnableLogging();
       
   767 		break;
       
   768 	case RWsSession::ELoggingDisable:
       
   769 		DisableLogging();
       
   770 		break;
       
   771 	case RWsSession::ELoggingStatusDump:
       
   772 		StateDump();
       
   773 		break;
       
   774 	case RWsSession::ELoggingHeapDump:
       
   775 		HeapDump();
       
   776 		break;
       
   777 		}
       
   778 	}
       
   779 
       
   780 void CWsTop::StateDump()
       
   781 	{
       
   782 	TInt screenNo;
       
   783 	for (screenNo=0; screenNo<iNumberOfScreens; ++screenNo)
       
   784 		::StateDump( (*iScreens)[screenNo]->RootWindow());
       
   785 	}
       
   786 	
       
   787 void CWsTop::SetCurrentFocusScreen(CScreen* aScreen)	
       
   788 	{
       
   789 	iCurrentFocusScreen = aScreen;
       
   790 	}
       
   791 
       
   792 TInt CWsTop::SetCurrentFocusScreen(TInt aScreenNo)
       
   793 	{
       
   794 	CScreen* newFocusScreen=CWsTop::Screen(aScreenNo);
       
   795 	if (newFocusScreen==iCurrentFocusScreen)
       
   796 		return KErrNone;
       
   797 
       
   798 	CWsWindowGroup* newFocusGroup=newFocusScreen->FocusWindowGroup();
       
   799 	if (!newFocusGroup)
       
   800 		return KErrNotReady;
       
   801 
       
   802 	CWsWindowGroup* oldFocusGroup=iCurrentFocusScreen->FocusWindowGroup();
       
   803 	if (oldFocusGroup)
       
   804 		oldFocusGroup->LostFocus();
       
   805 	iCurrentFocusScreen=newFocusScreen;
       
   806 	newFocusGroup->ReceivedFocus();
       
   807 	WsPointer::UpdatePointerCursor();
       
   808 	TWindowServerEvent::SendFocusChangedEvents();
       
   809 	return KErrNone;
       
   810 	}
       
   811 
       
   812 void CWsTop::SetCheckHeapOnDisconnectClient(const CWsClient* aClient)
       
   813 	{
       
   814 	iTriggerHeapCheckOnClientExit=aClient;
       
   815 	}
       
   816 
       
   817 void CWsTop::SetCheckHeapOnDisconnectMode(TWsCheckHeapOnDisconnectMode aCheckHeapOnDisconnectMode)
       
   818 	{
       
   819 	iHeapCheckMode=aCheckHeapOnDisconnectMode;
       
   820 	}
       
   821 
       
   822 TBool CWsTop::NeedsHeapCheckAndRestart(TInt aStartHeapCount)
       
   823 	{
       
   824 	if (!iDoHeapCheckAndRestart)
       
   825 		return(EFalse);
       
   826 	iDoHeapCheckAndRestart=EFalse;
       
   827 	iCheckHeapResult=User::Heap().Count()-aStartHeapCount;
       
   828 	if(iCheckHeapResult > 0)
       
   829 	    {
       
   830         const TUint32 orphanedCell = User::Heap().__DbgMarkEnd(aStartHeapCount);
       
   831         RDebug::Printf("Memory leak detected in wserv. First orphaned cell: 0x%8x", orphanedCell);
       
   832         }
       
   833 	return(ETrue);;
       
   834 	}
       
   835 
       
   836 TInt CWsTop::FetchCheckHeapResult()
       
   837 	{
       
   838 	TInt ret=iCheckHeapResult;
       
   839 	iCheckHeapResult=KErrNotReady;
       
   840 	return(ret);
       
   841 	}
       
   842 
       
   843 /**
       
   844 This function looks for memory which isn't essential to the correct running of the window server
       
   845 and frees some of it.
       
   846 Returns true if some memory was freed, and false if it was unable to free anything.
       
   847 Called from the memory manager in low memory conditions.
       
   848 */
       
   849 TBool CWsTop::ReleaseMemory()
       
   850 	{
       
   851 	return iServer->ReleaseMemory();
       
   852 	}
       
   853 	
       
   854 TBool CWsTop::MultiFocusPolicy()
       
   855 	{
       
   856 	return	iMultiFocusPolicy;
       
   857 	}
       
   858 	
       
   859 typedef TInt (*ShellEntryPoint)(TAny *);
       
   860 
       
   861 #if defined(__WINS__)
       
   862 LOCAL_D const TUint KHeapSize=0x10000;
       
   863 LOCAL_D const TUint KMaxHeapSize=0x400000;
       
   864 #endif
       
   865 
       
   866 CWsShellLogon::CWsShellLogon() : CActive(EWsShellLogonPriority)
       
   867 	{
       
   868 #if defined (__WINS__)
       
   869 	// Clear handles to NULL so we can later detect which one gets used
       
   870 	iShellThread.SetHandle(NULL);
       
   871 	iShellProcess.SetHandle(NULL);
       
   872 #endif
       
   873 	}
       
   874 
       
   875 CWsShellLogon::~CWsShellLogon()
       
   876 	{
       
   877 	Cancel();
       
   878 #if defined (__WINS__)
       
   879 	iShellThread.Close();
       
   880 	iShellProcess.Close();
       
   881 #else
       
   882 	iShell.Close();
       
   883 #endif
       
   884 #if defined(__WINS__)
       
   885 	iLib.Close();
       
   886 #endif
       
   887 	}
       
   888 
       
   889 void CWsShellLogon::ConstructL(RFs &)
       
   890 	{
       
   891 	CActiveScheduler::Add(this);
       
   892 #if !defined(__WINS__)
       
   893 	TPtrC shellCmd;
       
   894 #endif
       
   895 	_LIT(KWSERVIniFileVarShellCmd,"SHELLCMD");
       
   896 	WsIniFile->FindVar(KWSERVIniFileVarShellCmd,shellCmd);
       
   897 	_LIT(KWSERVShellName,"SHELL");
       
   898 	TPtrC startUp(KWSERVShellName);
       
   899 	_LIT(KWSERVIniFileVarStartUp,"STARTUP");
       
   900 	WsIniFile->FindVar(KWSERVIniFileVarStartUp,startUp);
       
   901 
       
   902 
       
   903 	TParse fileName;
       
   904 	_LIT(KWSERVArmShellLocationPattern,"Z:\\sys\\bin\\.EXE");
       
   905 	User::LeaveIfError(fileName.SetNoWild(startUp,&KWSERVArmShellLocationPattern,NULL));
       
   906 #if defined(__WINS__)
       
   907 	TInt err=iShellProcess.Create(fileName.FullName(),shellCmd);
       
   908 	if (err == KErrNone)
       
   909 		{
       
   910 		Request();
       
   911 		iShellProcess.Resume();
       
   912 		}
       
   913 	else
       
   914 		{
       
   915 		// Try loading the matching DLL name instead?
       
   916 		_LIT(KWSERVShellExtension,"Z:.DLL");
       
   917 		User::LeaveIfError(fileName.Set(KWSERVShellExtension,&startUp,NULL));
       
   918 		User::LeaveIfError(iLib.Load(fileName.FullName()));
       
   919 		ShellEntryPoint libFunc=(ShellEntryPoint)iLib.Lookup(1);
       
   920 		if (!libFunc)
       
   921 			User::Leave(KErrGeneral);
       
   922 		TBuf<256> name;
       
   923 		TInt num=0;
       
   924 		TInt ret=KErrNone;
       
   925 		do
       
   926 			{
       
   927 			_LIT(KWSERVWinsShellInstanceName,"Shell%d");
       
   928 			name.Format(KWSERVWinsShellInstanceName,num++);
       
   929 			ret=iShellThread.Create(name,libFunc,KDefaultStackSize,&shellCmd,&iLib,NULL,KHeapSize,KMaxHeapSize,EOwnerProcess);
       
   930 			} while(ret==KErrAlreadyExists);
       
   931 		User::LeaveIfError(ret);
       
   932 		Request();
       
   933 		iShellThread.Resume();
       
   934 		}
       
   935 #else // not __WINS__
       
   936 	User::LeaveIfError(iShell.Create(fileName.FullName(),shellCmd));
       
   937 	Request();
       
   938 	iShell.Resume();
       
   939 #endif	
       
   940 	return;
       
   941 
       
   942 	}
       
   943 
       
   944 void CWsShellLogon::DoCancel()
       
   945 	{
       
   946 #if defined (__WINS__)
       
   947 	if(iShellThread.Handle())
       
   948 		iShellThread.LogonCancel(iStatus);
       
   949 	else
       
   950 		iShellProcess.LogonCancel(iStatus);
       
   951 #else
       
   952 	iShell.LogonCancel(iStatus);
       
   953 #endif
       
   954 	}
       
   955 
       
   956 void CWsShellLogon::RunL()
       
   957 	{
       
   958 	if (iStatus.Int()!=KErrCancel)
       
   959 		CWsTop::ShellExited();
       
   960 	}
       
   961 
       
   962 void CWsShellLogon::Request()
       
   963 	{
       
   964 #if defined (__WINS__)
       
   965 	if(iShellThread.Handle())
       
   966 		iShellThread.Logon(iStatus);
       
   967 	else
       
   968 		iShellProcess.Logon(iStatus);
       
   969 #else
       
   970 	iShell.Logon(iStatus);
       
   971 #endif
       
   972 	SetActive();
       
   973 	}
       
   974 
       
   975 #if defined(__WINS__) 
       
   976 TFullName CWsShellLogon::FullName()
       
   977 	{
       
   978 	if(iShellThread.Handle())
       
   979 		return(iShellThread.FullName());
       
   980 	else
       
   981 		return(iShellProcess.FullName());
       
   982 	}
       
   983 #else
       
   984 TFullName CWsShellLogon::FullName()
       
   985 	{return(iShell.FullName());}
       
   986 #endif
       
   987 
       
   988 
       
   989 
       
   990 TInt E32Main()
       
   991 	{
       
   992 	__UHEAP_MARK;
       
   993 
       
   994 	UserSvr::WsRegisterThread();
       
   995 
       
   996 	RThread thread;
       
   997 	// Set wserv's main thread to system permanent
       
   998 	TInt err;
       
   999 	err = User::SetCritical(User::ESystemPermanent);
       
  1000 	if (err!=KErrNone)
       
  1001 		{
       
  1002 		WS_PANIC_ALWAYS(EWsPanicFailedToSetThread);
       
  1003 		}
       
  1004 // If in the future wserv becomes multi-threaded,
       
  1005 // we can uncomment the following lines to set any new threads to be system permanent as well.
       
  1006 //	err = User::SetProcessCritical(User::ESystemPermanent); 
       
  1007 //	if (err!=KErrNone)
       
  1008 //		{
       
  1009 //		WS_PANIC_ALWAYS(EWsPanicFailedToSetProcess);
       
  1010 //		}
       
  1011 
       
  1012 	thread.SetPriority(EPriorityMore);
       
  1013 	err = User::RenameThread(KWSERVThreadName);
       
  1014 	if (err==KErrNone)
       
  1015 		{
       
  1016 		thread.Close();
       
  1017 		}
       
  1018 	else
       
  1019 		{
       
  1020 		return err;
       
  1021 		}
       
  1022 	TInt startCount;
       
  1023 	do
       
  1024 		{
       
  1025 		User::Heap().__DbgMarkStart();
       
  1026 		startCount=User::Heap().Count();
       
  1027 		CTrapCleanup* CleanUpStack=CTrapCleanup::New();
       
  1028 		TRAP(err,CWsTop::RunServerL());
       
  1029 		if (err!=KErrNone)
       
  1030 			{
       
  1031 			WS_PANIC_ALWAYS(EWsPanicFailedToInitialise);
       
  1032 			}
       
  1033 		UserSvr::ReleaseEventHook();
       
  1034 		delete CleanUpStack;
       
  1035 		} while	(CWsTop::NeedsHeapCheckAndRestart(startCount));
       
  1036 
       
  1037 	__UHEAP_MARKEND;
       
  1038 
       
  1039 	return(err);
       
  1040 	}
       
  1041 
       
  1042