1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/windowing/windowserver/nonnga/SERVER/WSTOP.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1043 @@
1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Top level window server code
1.18 +//
1.19 +//
1.20 +
1.21 +#include "wstop.h"
1.22 +
1.23 +#include <hal.h>
1.24 +#include <graphics/fbsdefs.h>
1.25 +#include "ANIM.H"
1.26 +#include "gc.h"
1.27 +#include "playbackgc.h"
1.28 +#include "rootwin.h"
1.29 +#include "windowgroup.h"
1.30 +#include "EVENT.H"
1.31 +#include "KEYCLICK.H"
1.32 +#include <w32std.h>
1.33 +#include "offscreenbitmap.h"
1.34 +#include "panics.h"
1.35 +#include "inifile.h"
1.36 +#include "pointer.h"
1.37 +#include "WSGRAPHICDRAWERFACTORY.H"
1.38 +#include "redrawmsgwindow.h"
1.39 +#include <Graphics/WSGRAPHICDRAWERINTERFACE.H>
1.40 +#include "WsMemMgr.h"
1.41 +#include "backedupwindow.h"
1.42 +#include "wsfont.h"
1.43 +#include "wstraces.h"
1.44 +#ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP
1.45 +#include <e32power.h>
1.46 +#endif
1.47 +#include "graphics/windowserverconstants.h"
1.48 +
1.49 +typedef CDebugLogBase *(*CreateDebugLog)(TBool aIsFirst, TDesC &aParams);
1.50 +
1.51 +CWsActiveScheduler* CWsActiveScheduler::Static()
1.52 + {
1.53 + return static_cast<CWsActiveScheduler*>(CActiveScheduler::Current());
1.54 + }
1.55 +
1.56 +CWsActiveScheduler::CWsActiveScheduler(): iNumSamples(100)
1.57 + {
1.58 + iRun = User::FastCounter();
1.59 + if((KErrNone == HAL::Get(HALData::EFastCounterFrequency,iFastCounterFreq)) && iFastCounterFreq)
1.60 + {
1.61 + iData = reinterpret_cast<TSample*>(User::AllocZ(sizeof(TSample)*iNumSamples));
1.62 + }
1.63 + }
1.64 +
1.65 +CWsActiveScheduler::~CWsActiveScheduler()
1.66 + {
1.67 + User::FreeZ(reinterpret_cast<void*&>(iData));
1.68 + }
1.69 +
1.70 +void CWsActiveScheduler::PrepareDraw()
1.71 + {
1.72 + WS_ASSERT_DEBUG((ENormal == iState)||(EDrawn == iState),EWsPanicActiveScheduler);
1.73 + __DEBUG_ONLY(iState = EPreparingDraw;)
1.74 + iRunDraw = User::FastCounter();
1.75 + }
1.76 +
1.77 +void CWsActiveScheduler::CancelPrepare()
1.78 + {
1.79 + WS_ASSERT_DEBUG(EPreparingDraw == iState,EWsPanicActiveScheduler);
1.80 + __DEBUG_ONLY(iState = ENormal;)
1.81 + }
1.82 +
1.83 +void CWsActiveScheduler::StartDraw()
1.84 + {
1.85 + WS_TRACE_SERVER_STARTDRAW();
1.86 + WS_ASSERT_DEBUG(EPreparingDraw == iState,EWsPanicActiveScheduler);
1.87 + __DEBUG_ONLY(iState = EDrawing;)
1.88 + TTime now;
1.89 + now.UniversalTime();
1.90 + TUint64 duration = now.MicroSecondsFrom(iRunDraw).Int64();
1.91 + iPreparing += duration;
1.92 + iRunDraw = now;
1.93 + if(iData)
1.94 + {
1.95 + iData[iCurrent].iStart = iRunDraw;
1.96 + }
1.97 + iDraws++;
1.98 + }
1.99 +
1.100 +void CWsActiveScheduler::DrawStats(TInt& aUpdatesPerSecond,TInt64& aPixelsPerSecond,TInt aWindowInSeconds) const
1.101 + {
1.102 + aUpdatesPerSecond=0;
1.103 + aPixelsPerSecond=0;
1.104 + if(iData)
1.105 + {
1.106 + // work out statistic
1.107 + TTime window;
1.108 + window.UniversalTime();
1.109 + window-=TTimeIntervalSeconds(aWindowInSeconds);
1.110 + TUint32 pixels=0;
1.111 + TInt64 duration=0;
1.112 + for(TInt ii=0;ii<iNumSamples;++ii)
1.113 + {
1.114 + if (iData[ii].iStart>=window)
1.115 + {
1.116 + pixels+=iData[ii].iPixels;
1.117 + duration+=iData[ii].iDuration;
1.118 + ++aUpdatesPerSecond;
1.119 + }
1.120 + }
1.121 + if (aUpdatesPerSecond && duration)
1.122 + {
1.123 + aPixelsPerSecond=pixels;
1.124 + aPixelsPerSecond=(aPixelsPerSecond*1000000)/duration;
1.125 + aUpdatesPerSecond/=aWindowInSeconds;
1.126 + }
1.127 + }
1.128 + }
1.129 +
1.130 +void CWsActiveScheduler::StopDraw(TInt aPixelsUpdated)
1.131 + {
1.132 + WS_TRACE_SERVER_STOPDRAW();
1.133 + WS_ASSERT_DEBUG(EDrawing == iState,EWsPanicActiveScheduler);
1.134 + __DEBUG_ONLY(iState = EDrawn;)
1.135 + TTime now;
1.136 + now.UniversalTime();
1.137 + TUint32 duration = now.MicroSecondsFrom(iRunDraw).Int64();
1.138 + // do recording
1.139 + if(iData)
1.140 + {
1.141 + iData[iCurrent].iDuration = now.MicroSecondsFrom(iData[iCurrent].iStart).Int64();
1.142 + iData[iCurrent].iPixels = aPixelsUpdated;
1.143 + if(++iCurrent >= iNumSamples)
1.144 + {
1.145 + iCurrent = 0;
1.146 + }
1.147 + }
1.148 + iDrawing += duration;
1.149 + }
1.150 +
1.151 +void CWsActiveScheduler::WaitForAnyRequest()
1.152 + {
1.153 + WS_ASSERT_DEBUG((ENormal == iState)||(EDrawn == iState),EWsPanicActiveScheduler);
1.154 + TTime stop;
1.155 + stop.UniversalTime();
1.156 + iTotal += stop.MicroSecondsFrom(iRun).Int64();
1.157 + CActiveScheduler::WaitForAnyRequest();
1.158 + iRequests++;
1.159 + __DEBUG_ONLY(iState = ENormal;)
1.160 + iRun.UniversalTime();
1.161 + iIdle += iRun.MicroSecondsFrom(stop).Int64();
1.162 + }
1.163 +
1.164 +
1.165 +void CWsActiveScheduler::Error(TInt /*aError*/) const
1.166 + {
1.167 + iErrors++;
1.168 + }
1.169 +
1.170 +void CWsActiveScheduler::AccumReclaimedIdleTime(TInt64 aMicroSeconds)
1.171 + {
1.172 + iReclaimedIdleTime += aMicroSeconds;
1.173 + }
1.174 +
1.175 +
1.176 +GLREF_C void StateDump(CWsRootWindow* aRootWindow);
1.177 +GLREF_C void HeapDump();
1.178 +
1.179 +// Static objects that need to be destroyed on exit
1.180 +GLDEF_D CDebugLogBase *wsDebugLog=NULL;
1.181 +GLDEF_D TInt wsDebugLogLevel=0;
1.182 +GLDEF_D CIniFile *WsIniFile=NULL;
1.183 +//
1.184 +GLDEF_D TPtr nullDescriptor(NULL,0);
1.185 +
1.186 +LOCAL_D CWsActiveScheduler *TheActiveScheduler;
1.187 +#if defined(__WINS__)
1.188 +LOCAL_D TPtrC shellCmd;
1.189 +#endif
1.190 +
1.191 +CScreen* CWsTop::iCurrentFocusScreen;
1.192 +CArrayPtrFlat<CScreen>* CWsTop::iScreens ;
1.193 +TInt CWsTop::iNumberOfScreens ;
1.194 +CWsTop::CShellStarter* CWsTop::iShellStarter;
1.195 +
1.196 +CWindowServer *CWsTop::iServer;
1.197 +RLibrary CWsTop::iDebugLib;
1.198 +CWsShellLogon *CWsTop::iShell;
1.199 +const CWsClient *CWsTop::iShellClient;
1.200 +TBool CWsTop::iPreviousShellClient=EFalse;
1.201 +TInt CWsTop::iShellBootMode;
1.202 +TBool CWsTop::iShuttingDown;
1.203 +TBool CWsTop::iIsFirstLog=ETrue;
1.204 +CWsWindowBase *CWsTop::iWindowToSendOffEventsTo=NULL;
1.205 +RTimer CWsTop::iTimer;
1.206 +TBool CWsTop::iIgnoreSwitchOffEvent=EFalse;
1.207 +TBool CWsTop::iFadeEnabled=ETrue;
1.208 +TBool CWsTop::iFinishEveryFlush=EFalse;
1.209 +TBool CWsTop::iMultiFocusPolicy=EFalse;
1.210 +#if defined(__WINS__)
1.211 +TFullName WsSemName;
1.212 +#endif
1.213 +const CWsClient* CWsTop::iTriggerHeapCheckOnClientExit=NULL;
1.214 +TWsCheckHeapOnDisconnectMode CWsTop::iHeapCheckMode=EWsCheckHeapOnDisconnectModeNone;
1.215 +TInt CWsTop::iCheckHeapResult=KErrNotReady;
1.216 +TBool CWsTop::iDoHeapCheckAndRestart=EFalse;
1.217 +#define RFbsSession_SendCommand_ShutDownMessage 1 // A FBS message that is not published yet and probably never will be.
1.218 +void CWsTop::DeleteStaticsL()
1.219 + {
1.220 + iShuttingDown=ETrue;
1.221 + CClick::DeleteStatics();
1.222 + WsPointer::DeleteStatics();
1.223 + CWsClient::DeleteStatics();
1.224 +//
1.225 + delete iShellStarter;
1.226 + delete iServer;
1.227 +
1.228 + CWsBackedUpWindow::StaticDestroy();
1.229 + TWindowServerEvent::DeleteStatics();
1.230 + delete iShell;
1.231 + DisableLogging();
1.232 +
1.233 + CEventQueue::DeleteStaticsL();
1.234 +
1.235 + CWsSpriteBase::DeleteStatics();
1.236 + CWsGc::DeleteStatics();
1.237 + CPlaybackGc::DeleteStatics();
1.238 + CWsAnim::DeleteStatics(); //This destroys a GC so must be done while FBSERV is still around
1.239 + CWsAnimDll::DeleteStatics();
1.240 + CWsFontCache::DestroyInstance();
1.241 +
1.242 + iScreens->ResetAndDestroy() ;
1.243 + delete iScreens ;
1.244 +
1.245 + if (!iDoHeapCheckAndRestart)
1.246 + {
1.247 + RFbsSession::GetSession()->SendCommand(RFbsSession_SendCommand_ShutDownMessage); //This line is just being tidy, never really does anything useful.
1.248 + }
1.249 +
1.250 + RFbsSession::Disconnect();
1.251 + iDebugLib.Close();
1.252 + iTimer.Close();
1.253 +//
1.254 + delete WsIniFile;
1.255 + delete TheActiveScheduler;
1.256 + WsGraphicDrawer::FinalClose();
1.257 + }
1.258 +
1.259 +RWsTextCursor *CWsTop::CurrentTextCursor()
1.260 + {
1.261 + return(FocusWindowGroup() ? FocusWindowGroup()->TextCursor():NULL);
1.262 + }
1.263 +
1.264 +CWsClient *CWsTop::FocusWindowGroupOwner()
1.265 + {
1.266 + return(FocusWindowGroup() ? FocusWindowGroup()->WsOwner():NULL);
1.267 + }
1.268 +
1.269 +void CWsTop::ClientDestroyed(const CWsClient *aClient)
1.270 + {
1.271 + if (aClient==iShellClient)
1.272 + iShellClient=NULL;
1.273 + }
1.274 +
1.275 +void CWsTop::NewSession(const CWsClient *aClient)
1.276 + {
1.277 + if (iShellClient==NULL && iShell)
1.278 + {
1.279 +#if defined(__WINS__)
1.280 + RThread proc;
1.281 + proc=aClient->Client();
1.282 +#else
1.283 + RProcess proc;
1.284 + aClient->Client().Process(proc);
1.285 +#endif
1.286 + TFullName procName = proc.FullName();
1.287 + // Before comparing the proc name with iShell name , truncate the proc name up to the actual name
1.288 + // referring to the process, by removing the part which starts with ':', if exists.
1.289 + TInt colonLocation = procName.Locate(':');
1.290 + if( KErrNotFound != colonLocation)
1.291 + {
1.292 + procName = procName.Left(colonLocation);
1.293 + }
1.294 + if (procName ==iShell->FullName())
1.295 + {
1.296 + iShellClient=aClient;
1.297 + if (!iPreviousShellClient)
1.298 + {
1.299 + iPreviousShellClient=ETrue;
1.300 + aClient->Screen()->RootWindow()->SetColorIfClear();
1.301 + }
1.302 + }
1.303 +#if !defined(__WINS__)
1.304 + proc.Close();
1.305 +#endif
1.306 + }
1.307 + }
1.308 +
1.309 +void CWsTop::SessionExited(CWsClient *aClient)
1.310 + {
1.311 + if (iShuttingDown)
1.312 + {
1.313 + RProcess proc;
1.314 + TInt err=aClient->Client().Process(proc);
1.315 + if (err==KErrNone && proc.Id()!=RProcess().Id())
1.316 + proc.Kill(0);
1.317 + else
1.318 + const_cast<RThread&>(aClient->Client()).Kill(0);
1.319 + if (err==KErrNone)
1.320 + proc.Close();
1.321 + }
1.322 + else if (iHeapCheckMode!=EWsCheckHeapOnDisconnectModeNone && aClient==iTriggerHeapCheckOnClientExit)
1.323 + {
1.324 + if (iHeapCheckMode==EWsCheckHeapOnDisconnectModeOnce)
1.325 + {
1.326 + iHeapCheckMode=EWsCheckHeapOnDisconnectModeNone;
1.327 + }
1.328 + iTriggerHeapCheckOnClientExit=NULL;
1.329 + iDoHeapCheckAndRestart=ETrue;
1.330 + Exit();
1.331 + }
1.332 + if (iServer->SessionCount()==1 && iShellBootMode==EShellBootModeNoReboot && iShell==NULL)
1.333 + StartShell();
1.334 + }
1.335 +
1.336 +
1.337 +void CWsTop::RunServerL()
1.338 + {
1.339 + InitStaticsL();
1.340 + CWsMemoryManager* memMgr = CWsMemoryManager::NewLC();
1.341 + CActiveScheduler::Start();
1.342 + CleanupStack::PopAndDestroy(memMgr);
1.343 + DeleteStaticsL();
1.344 + }
1.345 +
1.346 +void CWsTop::InitStaticsL()
1.347 + {
1.348 + iShuttingDown=EFalse;
1.349 + // By default shell should be started.
1.350 + TBool startShell = ETrue;
1.351 +
1.352 + // The windows server has been invoked.
1.353 + // This may have been from the system starter (via a
1.354 + // start up rss file)
1.355 + // This block looks for a "-NoShell" argument in the invocation.
1.356 + // The existence of the argument means that shell does not need to be
1.357 + // invoked from here because the new system starter
1.358 + // is in charge, and it will do it if required.
1.359 +
1.360 + _LIT(KNoShell,"-NOSHELL");
1.361 +
1.362 + TInt argLen = User::CommandLineLength();
1.363 + if(argLen)
1.364 + {
1.365 + HBufC* arg = HBufC::NewLC(argLen);
1.366 + TPtr argPtr = arg->Des();
1.367 + User::CommandLine(argPtr);
1.368 + argPtr.UpperCase();
1.369 +
1.370 + if(KErrNotFound != argPtr.Find(KNoShell))
1.371 + {
1.372 + // Don't start the shell. It will be started if required by
1.373 + // the system starter.
1.374 + startShell = EFalse;
1.375 + }
1.376 + CleanupStack::PopAndDestroy(arg);
1.377 + }
1.378 +
1.379 + TheActiveScheduler=new(ELeave) CWsActiveScheduler;
1.380 + CActiveScheduler::Install(TheActiveScheduler);
1.381 +
1.382 +//
1.383 + WsIniFile=CIniFile::NewL();
1.384 + _LIT(KWSERVIniFileVarLogEnable,"LOGENABLE");
1.385 + TInt loggingLevel;
1.386 + if (WsIniFile->FindVar(KWSERVIniFileVarLogEnable,loggingLevel))
1.387 + {
1.388 + EnableLogging(EDoNotReloadWsIni);
1.389 + if (wsDebugLog)
1.390 + {
1.391 + wsDebugLog->SetLoggingLevel(loggingLevel);
1.392 + }
1.393 + }
1.394 +
1.395 + _LIT(KWSERVIniFileVarFadeEnable,"FADEDISABLE");
1.396 + iFadeEnabled = !WsIniFile->FindVar(KWSERVIniFileVarFadeEnable);
1.397 +
1.398 + _LIT(KWSERVIniFileVarFinishEveryFlush,"FINISHEVERYFLUSH");
1.399 + iFinishEveryFlush = WsIniFile->FindVar(KWSERVIniFileVarFinishEveryFlush);
1.400 +
1.401 + _LIT(KWSERVIniFileVarSwitchOffEvent,"IGNORESWITCHOFFEVENT");
1.402 + iIgnoreSwitchOffEvent = WsIniFile->FindVar(KWSERVIniFileVarSwitchOffEvent);
1.403 +
1.404 + iServer=CWindowServer::NewL();
1.405 + CClick::InitStaticsL();
1.406 +
1.407 + RProcess wservProc;
1.408 + if (!wservProc.DefaultDataPaged())
1.409 + {
1.410 + iServer->SetPinClientDescriptors(ETrue);
1.411 + }
1.412 +//
1.413 + iServer->StartL(KWSERVServerName);
1.414 +//
1.415 + User::LeaveIfError(FbsStartup());
1.416 + User::LeaveIfError(RFbsSession::Connect());
1.417 + User::LeaveIfError(iTimer.CreateLocal());
1.418 +
1.419 + TWindowServerEvent::InitStaticsL();
1.420 + //-------------------------------------------
1.421 + User::LeaveIfError( HAL::Get( HAL::EDisplayNumberOfScreens, iNumberOfScreens ) ) ;
1.422 + // Check that the INI file matches the HAL
1.423 + WS_ASSERT_ALWAYS(WsIniFile->NumberOfScreens()<=iNumberOfScreens, EWsPanicScreenInformationError);
1.424 +
1.425 + iScreens = new (ELeave) CArrayPtrFlat<CScreen>( iNumberOfScreens ) ; //
1.426 + // now construct screens for as long as there is information
1.427 +
1.428 + TInt ii ;
1.429 + for ( ii = 0 ; ii < iNumberOfScreens ; ++ii )
1.430 + {
1.431 + InitScreenL( ii ) ;
1.432 + }
1.433 + //---------------------------------------------
1.434 + iCurrentFocusScreen = (*iScreens)[0] ;
1.435 +
1.436 + CWsFontCache::CreateInstanceL();
1.437 + CWsGc::InitStaticsL();
1.438 + CPlaybackGc::InitStaticsL();
1.439 + CWsSpriteBase::InitStaticsL();
1.440 + CEventQueue::InitStaticsL();
1.441 +
1.442 +//
1.443 + CWsAnimDll::InitStaticsL();
1.444 + CWsAnim::InitStaticsL();
1.445 +//
1.446 + TInt bootMode=0;
1.447 + _LIT(KWSERVIniFileVarReboot,"REBOOT");
1.448 + WsIniFile->FindVar(KWSERVIniFileVarReboot,bootMode);
1.449 + if (bootMode>=0 && bootMode<=2)
1.450 + iShellBootMode=bootMode;
1.451 +//
1.452 + CWsBackedUpWindow::StaticInitL();
1.453 + CWsRedrawMsgWindow::StaticInitL();
1.454 +//
1.455 + WsPointer::InitStaticsL();
1.456 + iShellStarter=new (ELeave) CShellStarter;
1.457 + iShellStarter->ConstructL();
1.458 + _LIT(KPreProcess,"REMOVEFADINGONFOCUSGAIN");
1.459 + CWsWindowGroup::SetFocusGainPreprocessing(WsIniFile->FindVar(KPreProcess));
1.460 + _LIT(KAbsFade,"ABSOLUTEFADING");
1.461 + CWsClientWindow::SetAbsoluteFading(WsIniFile->FindVar(KAbsFade));
1.462 +
1.463 +//Set the focus policy
1.464 + _LIT(KFocusPolicy,"MULTIFOCUSPOLICY");
1.465 + if(WsIniFile->FindVar(KFocusPolicy))
1.466 + {
1.467 + iMultiFocusPolicy = ETrue;
1.468 + }
1.469 + RProcess::Rendezvous(KErrNone);
1.470 + // Start the shell from here unless the 'NoShell' option has been
1.471 + // received indicating that the system starter will start the shell directly.
1.472 + if(startShell)
1.473 + {
1.474 + StartShell();
1.475 + }
1.476 + UserSvr::WsRegisterSwitchOnScreenHandling(ETrue);
1.477 + }
1.478 +
1.479 +
1.480 +void CWsTop::InitScreenL( TInt aScreenNumber) // static
1.481 + {
1.482 + // create a new screen, read ini file for aScreenNumber (this happens in CScreen - just need to pass a screen number from here
1.483 + CScreen* screen = new (ELeave) CScreen() ;
1.484 + CleanupStack::PushL( screen ) ;
1.485 + TRect digitiserArea;
1.486 + if (aScreenNumber==0)
1.487 + {
1.488 + TMachineInfoV1Buf machineBuf;
1.489 + UserHal::MachineInfo(machineBuf);
1.490 + TMachineInfoV1& machineInfo=*(TMachineInfoV1*)machineBuf.Ptr();
1.491 + digitiserArea = TRect(-machineInfo.iOffsetToDisplayInPixels,machineInfo.iXYInputSizeInPixels);
1.492 + }
1.493 + screen->ConstructL(digitiserArea, aScreenNumber);
1.494 + iScreens->AppendL( screen ) ;
1.495 + CleanupStack::Pop( screen ) ;
1.496 + }
1.497 +
1.498 +void CWsTop::UpdateAllScreens()
1.499 + {
1.500 + TInt ii;
1.501 + for (ii=0; ii<iNumberOfScreens; ++ii)
1.502 + {
1.503 + (*iScreens)[ii]->Update();
1.504 + }
1.505 + }
1.506 +
1.507 +void CWsTop::ClearAllRedrawStores()
1.508 + {
1.509 + TInt ii;
1.510 + for (ii=0; ii<iNumberOfScreens; ++ii)
1.511 + {
1.512 + CScreen *screen=(*iScreens)[ii];
1.513 + CWsWindowGroup* group=screen->RootWindow()->Child();
1.514 + while (group!=NULL)
1.515 + {
1.516 + CWsWindowBase* win=group->Child();
1.517 + if (win)
1.518 + {
1.519 + while (win!=group)
1.520 + {
1.521 + static_cast<CWsWindow*>(win)->Redraw()->ClearRedrawStore(ETrue);
1.522 + if (win->BaseChild())
1.523 + win=win->BaseChild();
1.524 + else
1.525 + {
1.526 + do
1.527 + {
1.528 + if (win->NextSibling())
1.529 + {
1.530 + win=win->NextSibling();
1.531 + break;
1.532 + }
1.533 + win=win->BaseParent();
1.534 + }
1.535 + while (win!=group);
1.536 + }
1.537 + }
1.538 + }
1.539 + group=group->NextSibling();
1.540 + }
1.541 + TriggerRedraws(screen->RootWindow());
1.542 + }
1.543 + }
1.544 +
1.545 +void CWsTop::Exit()
1.546 + {
1.547 + CActiveScheduler::Stop();
1.548 + }
1.549 +
1.550 +void CWsTop::TriggerRedraws(CWsRootWindow* aRootWindow)
1.551 + {
1.552 + for(CWsWindowGroup *group=aRootWindow->Child();group!=NULL;group=group->NextSibling())
1.553 + group->WsOwner()->TriggerRedraw();
1.554 + }
1.555 +
1.556 +void CWsTop::StartShell()
1.557 + {
1.558 + TRAPD(err,iShell=new(ELeave) CWsShellLogon());
1.559 + if (err==KErrNone)
1.560 + {
1.561 + RFs fs;
1.562 + if ((err=fs.Connect())==KErrNone)
1.563 + {
1.564 + fs.SetNotifyUser(EFalse);
1.565 + TRAP(err,iShell->ConstructL(fs));
1.566 + fs.Close();
1.567 + }
1.568 + }
1.569 + if (err!=KErrNone)
1.570 + {
1.571 +#ifdef _DEBUG
1.572 + RDebug::Print(_L("Failed to start shell: err=%d\n"),err);
1.573 +#endif
1.574 + delete iShell;
1.575 + iShell=NULL;
1.576 + iShellStarter->After(TTimeIntervalMicroSeconds32(1000000));
1.577 + }
1.578 + }
1.579 +
1.580 +void CWsTop::ShellExited()
1.581 + {
1.582 + delete iShell;
1.583 + iShell=NULL;
1.584 + switch(iShellBootMode)
1.585 + {
1.586 + case EShellBootModeReboot:
1.587 + StartShell();
1.588 + break;
1.589 + case EShellBootModeNoReboot:
1.590 + if (iServer->SessionCount()==0)
1.591 + StartShell();
1.592 + break;
1.593 + case EShellBootModeExit:
1.594 + Exit();
1.595 + break;
1.596 + }
1.597 + }
1.598 +
1.599 +TInt CWsTop::SetSendOffEventsToShell(CWsClient *aClient,const TWsClCmdOffEventsToShell &aData)
1.600 + {
1.601 + CWsWindowBase *window=NULL;
1.602 + if (aData.window==0)
1.603 + {
1.604 + if (aData.on)
1.605 + aClient->PPanic(EWservPanicNoWindowSpecifed);
1.606 + }
1.607 + else
1.608 + aClient->HandleToWindow(aData.window,&window);
1.609 + if (aData.on)
1.610 + {
1.611 + if (iWindowToSendOffEventsTo!=NULL && aClient!=iShellClient) //Allow the shell to pinch it
1.612 + return KErrAlreadyExists;
1.613 + iWindowToSendOffEventsTo=window;
1.614 + }
1.615 + else
1.616 + {
1.617 + if (iWindowToSendOffEventsTo==window || (!window && aClient==iWindowToSendOffEventsTo->WsOwner()))
1.618 + iWindowToSendOffEventsTo=NULL;
1.619 + }
1.620 + return KErrNone;
1.621 + }
1.622 +
1.623 +void CWsTop::StopWindowGettingOffEvents(CWsWindowBase* aWindow)
1.624 + {
1.625 + if (aWindow==iWindowToSendOffEventsTo)
1.626 + iWindowToSendOffEventsTo=NULL;
1.627 + }
1.628 +
1.629 +/** Routes "Off" events to the shutdown manager if one is registered. Othwerwise calls Power API's directly to
1.630 +set the power mode of the device accordingly.
1.631 +@internalTechnology
1.632 +@released
1.633 +@param aEvent Type of event that Wserv passes to client as OFF events.
1.634 +It can be EEventSwitchOff, EEventCaseClosed, EEventKeySwitchOff or EEventRestartSystem.
1.635 +@param aDoSwitchOff ETrue if the switch-off should be performed when no shutdown manager is registered
1.636 +and IGNORESWITCHOFFEVENT is not defined in wsini.ini
1.637 +*/
1.638 +void CWsTop::HandleSwitchOff(TInt aEvent,TBool aDoSwitchOff)
1.639 + {
1.640 + // If any shutdown manager is registered, forward the event to it
1.641 + if (iWindowToSendOffEventsTo && iWindowToSendOffEventsTo->QueueEvent(aEvent))
1.642 + return;
1.643 + // Otherwise, do the shutdown here
1.644 + if(!iIgnoreSwitchOffEvent && aDoSwitchOff)
1.645 + {
1.646 +#ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP
1.647 + // if LaF is not registered, restart or shutdown using Power API
1.648 + if (aEvent == EEventRestartSystem) // restart
1.649 + {
1.650 + if (Power::EnableWakeupEvents(EPwRestart) == KErrNone)
1.651 + {
1.652 + // Should reboot/power-cycle the system, so no need to RequestWakeupEventNotification
1.653 + Power::PowerDown();
1.654 + }
1.655 + }
1.656 + else // everything else maps to standby for now
1.657 + {
1.658 + if (Power::EnableWakeupEvents(EPwStandby) == KErrNone)
1.659 + {
1.660 + // Prepare to wake up from standby
1.661 + TRequestStatus s;
1.662 + Power::RequestWakeupEventNotification(s);
1.663 + Power::PowerDown();
1.664 + User::WaitForRequest(s);
1.665 + }
1.666 + }
1.667 +#else
1.668 + UserHal::SwitchOff();
1.669 +#endif
1.670 + }
1.671 + }
1.672 +
1.673 +void CWsTop::RedrawScreens()
1.674 + {
1.675 + // apply to all screens
1.676 + TInt screenNo;
1.677 + for(screenNo=0; screenNo<iNumberOfScreens; ++screenNo)
1.678 + {
1.679 + CScreen* screen = Screen(screenNo);
1.680 + TRegionFix<1> screenArea(TRect(screen->DrawableArea()));
1.681 + screen->Update(screenArea);
1.682 + }
1.683 + }
1.684 +
1.685 +void CWsTop::EnableLogging(TReloadWsIni aSetting)
1.686 + {
1.687 + TInt errorLoc=0;
1.688 + if (wsDebugLog)
1.689 + {
1.690 + if (wsDebugLogLevel==CDebugLogBase::ELogEverything)
1.691 + {
1.692 + wsDebugLogLevel=CDebugLogBase::ELogImportant;
1.693 + wsDebugLog->SetLoggingLevel(wsDebugLogLevel);
1.694 + return;
1.695 + }
1.696 + DisableLogging();
1.697 + }
1.698 +
1.699 + if (aSetting == EDoReloadWsIni)
1.700 + {
1.701 + CIniFile* temp = NULL;
1.702 + TRAPD(err, temp = CIniFile::NewL());
1.703 + if (err == KErrNone)
1.704 + {
1.705 + //loading successful, replace the previous one
1.706 + delete WsIniFile;
1.707 + WsIniFile = temp;
1.708 + }
1.709 + }
1.710 +
1.711 + TPtrC dlog;
1.712 + _LIT(KWSERVDebugLogFileName,"DLOG");
1.713 + TBuf<KMaxFileName> fname(KWSERVDebugLogFileName);
1.714 + _LIT(KWSERVIniFileVarLog,"LOG");
1.715 + if (WsIniFile->FindVar(KWSERVIniFileVarLog,dlog) && dlog.Length()==2)
1.716 + {
1.717 + fname.Append(dlog);
1.718 + TInt err=iDebugLib.Load(fname);
1.719 + if (err==KErrNone)
1.720 + {
1.721 + TUidType uid=iDebugLib.Type();
1.722 + if (uid[1]!=KWservLoggingDllUid)
1.723 + {
1.724 + err=KErrNotSupported;
1.725 + errorLoc=2;
1.726 + }
1.727 + else
1.728 + {
1.729 + TPtrC params;
1.730 + _LIT(KWSERVIniFileVarLogP,"LOGP");
1.731 + if (!WsIniFile->FindVar(KWSERVIniFileVarLogP,params))
1.732 + params.Set(NULL,0);
1.733 + CreateDebugLog func=(CreateDebugLog)iDebugLib.Lookup(1);
1.734 + if (func!=NULL)
1.735 + {
1.736 + TRAP(err,wsDebugLog=(*func)(iIsFirstLog, params));
1.737 + if (err==KErrNone)
1.738 + {
1.739 + iIsFirstLog=EFalse;
1.740 + wsDebugLogLevel=CDebugLogBase::ELogEverything;
1.741 + }
1.742 + else
1.743 + errorLoc=4;
1.744 + }
1.745 + else
1.746 + errorLoc=3;
1.747 + }
1.748 + }
1.749 + else
1.750 + errorLoc=1;
1.751 + if (iCurrentFocusScreen)
1.752 + {
1.753 + TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::ELogging,(errorLoc<<8)-err);
1.754 + }
1.755 + }
1.756 + }
1.757 +
1.758 +void CWsTop::DisableLogging()
1.759 + {
1.760 + delete wsDebugLog;
1.761 + wsDebugLog=NULL;
1.762 + iDebugLib.Close();
1.763 + }
1.764 +
1.765 +void CWsTop::LogCommand(RWsSession::TLoggingCommand aCommand)
1.766 + {
1.767 + switch(aCommand)
1.768 + {
1.769 + case RWsSession::ELoggingEnable:
1.770 + EnableLogging();
1.771 + break;
1.772 + case RWsSession::ELoggingDisable:
1.773 + DisableLogging();
1.774 + break;
1.775 + case RWsSession::ELoggingStatusDump:
1.776 + StateDump();
1.777 + break;
1.778 + case RWsSession::ELoggingHeapDump:
1.779 + HeapDump();
1.780 + break;
1.781 + }
1.782 + }
1.783 +
1.784 +void CWsTop::StateDump()
1.785 + {
1.786 + TInt screenNo;
1.787 + for (screenNo=0; screenNo<iNumberOfScreens; ++screenNo)
1.788 + ::StateDump( (*iScreens)[screenNo]->RootWindow());
1.789 + }
1.790 +
1.791 +void CWsTop::SetCurrentFocusScreen(CScreen* aScreen)
1.792 + {
1.793 + iCurrentFocusScreen = aScreen;
1.794 + }
1.795 +
1.796 +TInt CWsTop::SetCurrentFocusScreen(TInt aScreenNo)
1.797 + {
1.798 + CScreen* newFocusScreen=CWsTop::Screen(aScreenNo);
1.799 + if (newFocusScreen==iCurrentFocusScreen)
1.800 + return KErrNone;
1.801 +
1.802 + CWsWindowGroup* newFocusGroup=newFocusScreen->FocusWindowGroup();
1.803 + if (!newFocusGroup)
1.804 + return KErrNotReady;
1.805 +
1.806 + CWsWindowGroup* oldFocusGroup=iCurrentFocusScreen->FocusWindowGroup();
1.807 + if (oldFocusGroup)
1.808 + oldFocusGroup->LostFocus();
1.809 + iCurrentFocusScreen=newFocusScreen;
1.810 + newFocusGroup->ReceivedFocus();
1.811 + WsPointer::UpdatePointerCursor();
1.812 + TWindowServerEvent::SendFocusChangedEvents();
1.813 + return KErrNone;
1.814 + }
1.815 +
1.816 +void CWsTop::SetCheckHeapOnDisconnectClient(const CWsClient* aClient)
1.817 + {
1.818 + iTriggerHeapCheckOnClientExit=aClient;
1.819 + }
1.820 +
1.821 +void CWsTop::SetCheckHeapOnDisconnectMode(TWsCheckHeapOnDisconnectMode aCheckHeapOnDisconnectMode)
1.822 + {
1.823 + iHeapCheckMode=aCheckHeapOnDisconnectMode;
1.824 + }
1.825 +
1.826 +TBool CWsTop::NeedsHeapCheckAndRestart(TInt aStartHeapCount)
1.827 + {
1.828 + if (!iDoHeapCheckAndRestart)
1.829 + return(EFalse);
1.830 + iDoHeapCheckAndRestart=EFalse;
1.831 + iCheckHeapResult=User::Heap().Count()-aStartHeapCount;
1.832 + if(iCheckHeapResult > 0)
1.833 + {
1.834 + const TUint32 orphanedCell = User::Heap().__DbgMarkEnd(aStartHeapCount);
1.835 + RDebug::Printf("Memory leak detected in wserv. First orphaned cell: 0x%8x", orphanedCell);
1.836 + }
1.837 + return(ETrue);;
1.838 + }
1.839 +
1.840 +TInt CWsTop::FetchCheckHeapResult()
1.841 + {
1.842 + TInt ret=iCheckHeapResult;
1.843 + iCheckHeapResult=KErrNotReady;
1.844 + return(ret);
1.845 + }
1.846 +
1.847 +/**
1.848 +This function looks for memory which isn't essential to the correct running of the window server
1.849 +and frees some of it.
1.850 +Returns true if some memory was freed, and false if it was unable to free anything.
1.851 +Called from the memory manager in low memory conditions.
1.852 +*/
1.853 +TBool CWsTop::ReleaseMemory()
1.854 + {
1.855 + return iServer->ReleaseMemory();
1.856 + }
1.857 +
1.858 +TBool CWsTop::MultiFocusPolicy()
1.859 + {
1.860 + return iMultiFocusPolicy;
1.861 + }
1.862 +
1.863 +typedef TInt (*ShellEntryPoint)(TAny *);
1.864 +
1.865 +#if defined(__WINS__)
1.866 +LOCAL_D const TUint KHeapSize=0x10000;
1.867 +LOCAL_D const TUint KMaxHeapSize=0x400000;
1.868 +#endif
1.869 +
1.870 +CWsShellLogon::CWsShellLogon() : CActive(EWsShellLogonPriority)
1.871 + {
1.872 +#if defined (__WINS__)
1.873 + // Clear handles to NULL so we can later detect which one gets used
1.874 + iShellThread.SetHandle(NULL);
1.875 + iShellProcess.SetHandle(NULL);
1.876 +#endif
1.877 + }
1.878 +
1.879 +CWsShellLogon::~CWsShellLogon()
1.880 + {
1.881 + Cancel();
1.882 +#if defined (__WINS__)
1.883 + iShellThread.Close();
1.884 + iShellProcess.Close();
1.885 +#else
1.886 + iShell.Close();
1.887 +#endif
1.888 +#if defined(__WINS__)
1.889 + iLib.Close();
1.890 +#endif
1.891 + }
1.892 +
1.893 +void CWsShellLogon::ConstructL(RFs &)
1.894 + {
1.895 + CActiveScheduler::Add(this);
1.896 +#if !defined(__WINS__)
1.897 + TPtrC shellCmd;
1.898 +#endif
1.899 + _LIT(KWSERVIniFileVarShellCmd,"SHELLCMD");
1.900 + WsIniFile->FindVar(KWSERVIniFileVarShellCmd,shellCmd);
1.901 + _LIT(KWSERVShellName,"SHELL");
1.902 + TPtrC startUp(KWSERVShellName);
1.903 + _LIT(KWSERVIniFileVarStartUp,"STARTUP");
1.904 + WsIniFile->FindVar(KWSERVIniFileVarStartUp,startUp);
1.905 +
1.906 +
1.907 + TParse fileName;
1.908 + _LIT(KWSERVArmShellLocationPattern,"Z:\\sys\\bin\\.EXE");
1.909 + User::LeaveIfError(fileName.SetNoWild(startUp,&KWSERVArmShellLocationPattern,NULL));
1.910 +#if defined(__WINS__)
1.911 + TInt err=iShellProcess.Create(fileName.FullName(),shellCmd);
1.912 + if (err == KErrNone)
1.913 + {
1.914 + Request();
1.915 + iShellProcess.Resume();
1.916 + }
1.917 + else
1.918 + {
1.919 + // Try loading the matching DLL name instead?
1.920 + _LIT(KWSERVShellExtension,"Z:.DLL");
1.921 + User::LeaveIfError(fileName.Set(KWSERVShellExtension,&startUp,NULL));
1.922 + User::LeaveIfError(iLib.Load(fileName.FullName()));
1.923 + ShellEntryPoint libFunc=(ShellEntryPoint)iLib.Lookup(1);
1.924 + if (!libFunc)
1.925 + User::Leave(KErrGeneral);
1.926 + TBuf<256> name;
1.927 + TInt num=0;
1.928 + TInt ret=KErrNone;
1.929 + do
1.930 + {
1.931 + _LIT(KWSERVWinsShellInstanceName,"Shell%d");
1.932 + name.Format(KWSERVWinsShellInstanceName,num++);
1.933 + ret=iShellThread.Create(name,libFunc,KDefaultStackSize,&shellCmd,&iLib,NULL,KHeapSize,KMaxHeapSize,EOwnerProcess);
1.934 + } while(ret==KErrAlreadyExists);
1.935 + User::LeaveIfError(ret);
1.936 + Request();
1.937 + iShellThread.Resume();
1.938 + }
1.939 +#else // not __WINS__
1.940 + User::LeaveIfError(iShell.Create(fileName.FullName(),shellCmd));
1.941 + Request();
1.942 + iShell.Resume();
1.943 +#endif
1.944 + return;
1.945 +
1.946 + }
1.947 +
1.948 +void CWsShellLogon::DoCancel()
1.949 + {
1.950 +#if defined (__WINS__)
1.951 + if(iShellThread.Handle())
1.952 + iShellThread.LogonCancel(iStatus);
1.953 + else
1.954 + iShellProcess.LogonCancel(iStatus);
1.955 +#else
1.956 + iShell.LogonCancel(iStatus);
1.957 +#endif
1.958 + }
1.959 +
1.960 +void CWsShellLogon::RunL()
1.961 + {
1.962 + if (iStatus.Int()!=KErrCancel)
1.963 + CWsTop::ShellExited();
1.964 + }
1.965 +
1.966 +void CWsShellLogon::Request()
1.967 + {
1.968 +#if defined (__WINS__)
1.969 + if(iShellThread.Handle())
1.970 + iShellThread.Logon(iStatus);
1.971 + else
1.972 + iShellProcess.Logon(iStatus);
1.973 +#else
1.974 + iShell.Logon(iStatus);
1.975 +#endif
1.976 + SetActive();
1.977 + }
1.978 +
1.979 +#if defined(__WINS__)
1.980 +TFullName CWsShellLogon::FullName()
1.981 + {
1.982 + if(iShellThread.Handle())
1.983 + return(iShellThread.FullName());
1.984 + else
1.985 + return(iShellProcess.FullName());
1.986 + }
1.987 +#else
1.988 +TFullName CWsShellLogon::FullName()
1.989 + {return(iShell.FullName());}
1.990 +#endif
1.991 +
1.992 +
1.993 +
1.994 +TInt E32Main()
1.995 + {
1.996 + __UHEAP_MARK;
1.997 +
1.998 + UserSvr::WsRegisterThread();
1.999 +
1.1000 + RThread thread;
1.1001 + // Set wserv's main thread to system permanent
1.1002 + TInt err;
1.1003 + err = User::SetCritical(User::ESystemPermanent);
1.1004 + if (err!=KErrNone)
1.1005 + {
1.1006 + WS_PANIC_ALWAYS(EWsPanicFailedToSetThread);
1.1007 + }
1.1008 +// If in the future wserv becomes multi-threaded,
1.1009 +// we can uncomment the following lines to set any new threads to be system permanent as well.
1.1010 +// err = User::SetProcessCritical(User::ESystemPermanent);
1.1011 +// if (err!=KErrNone)
1.1012 +// {
1.1013 +// WS_PANIC_ALWAYS(EWsPanicFailedToSetProcess);
1.1014 +// }
1.1015 +
1.1016 + thread.SetPriority(EPriorityMore);
1.1017 + err = User::RenameThread(KWSERVThreadName);
1.1018 + if (err==KErrNone)
1.1019 + {
1.1020 + thread.Close();
1.1021 + }
1.1022 + else
1.1023 + {
1.1024 + return err;
1.1025 + }
1.1026 + TInt startCount;
1.1027 + do
1.1028 + {
1.1029 + User::Heap().__DbgMarkStart();
1.1030 + startCount=User::Heap().Count();
1.1031 + CTrapCleanup* CleanUpStack=CTrapCleanup::New();
1.1032 + TRAP(err,CWsTop::RunServerL());
1.1033 + if (err!=KErrNone)
1.1034 + {
1.1035 + WS_PANIC_ALWAYS(EWsPanicFailedToInitialise);
1.1036 + }
1.1037 + UserSvr::ReleaseEventHook();
1.1038 + delete CleanUpStack;
1.1039 + } while (CWsTop::NeedsHeapCheckAndRestart(startCount));
1.1040 +
1.1041 + __UHEAP_MARKEND;
1.1042 +
1.1043 + return(err);
1.1044 + }
1.1045 +
1.1046 +