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