--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/openwfc/screen.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,2269 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include "screen.h"
+
+#include <hal.h>
+#include <graphics/wsscreendevice.h>
+#include <graphics/wsscene.h>
+#include <graphics/wselement.h>
+#include "server.h"
+#include "wstop.h"
+#include "rootwin.h"
+#include "walkwindowtree.h"
+#include "EVENT.H"
+#include "windowgroup.h"
+#include "inifile.h"
+#include "pointer.h"
+#include "windowelementset.h"
+#include "registeredsurfacemap.h"
+#include "debugbar.h"
+#include "ScreenRedraw.h"
+#include "wspluginmanager.h"
+#include "devicemap.h"
+#include <graphics/wsdisplaymapping.h>
+#if defined(__WINS__) && defined(_DEBUG)
+#include "../../debuglog/osbwin.h"
+#endif
+#include <graphics/wsdisplaycontrol.h>
+
+GLREF_D CDebugLogBase *wsDebugLog;
+
+LOCAL_C inline MWsScene::TSceneRotation GcToScreen(CFbsBitGc::TGraphicsOrientation aGcOrientation)
+ {
+ MWsScene::TSceneRotation screenRotation = MWsScene::ESceneAntiClockwise0;
+
+ switch (aGcOrientation)
+ {
+ case CFbsBitGc::EGraphicsOrientationRotated90:
+ screenRotation = MWsScene::ESceneAntiClockwise90;
+ break;
+ case CFbsBitGc::EGraphicsOrientationRotated180:
+ screenRotation = MWsScene::ESceneAntiClockwise180;
+ break;
+ case CFbsBitGc::EGraphicsOrientationRotated270:
+ screenRotation = MWsScene::ESceneAntiClockwise270;
+ break;
+ }
+
+ return screenRotation;
+ }
+
+LOCAL_C inline TDeviceOrientation GcToDevice(CFbsBitGc::TGraphicsOrientation aGcOrientation)
+ {
+ // Each device orientation is defined to be the value where just the bit
+ // corresponding to the GDI orientation value is set.
+ return (TDeviceOrientation)(1 << aGcOrientation);
+ }
+
+LOCAL_D TBool FindNextValue(TLex& aLex, TInt& aValue) // assumes the list cannot contain *negative* integers
+ {
+ while (!aLex.Eos())
+ {
+ const TUint character=aLex.Peek();
+ if (Rng(TUint('0'), character, TUint('9')) || (character=='-'))
+ {
+ break;
+ }
+ aLex.Inc();
+ }
+
+ return (aLex.Val(aValue)==KErrNone);
+ }
+
+CScreen::CFallbackMap * CScreen::CFallbackMap::NewL(CScreen* aScreen)
+ {
+ CFallbackMap * self = new (ELeave) CFallbackMap(aScreen);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CScreen::CFallbackMap::CFallbackMap(CScreen* aScreen) :
+ iScreen(aScreen),
+ iRegion(TRect(TPoint(0,0), TSize(1,1))),
+ iCount(0)
+ {
+ }
+
+CScreen::CFallbackMap::~CFallbackMap()
+ {
+ delete iMap;
+ }
+
+void CScreen::CFallbackMap::ConstructL()
+ {
+ iMapSize = 0;
+
+ for (TInt num = 0; num < iScreen->NumScreenSizeModes(); ++num)
+ {
+ if (iScreen->IsValidScreenSizeMode(num))
+ {
+ const TSizeMode & mode = iScreen->ScreenSizeModeData(num);
+ TInt width = mode.iScreenSize.iWidth / 32;
+ if (mode.iScreenSize.iWidth & (32 - 1))
+ ++width;
+ TInt size = width * mode.iScreenSize.iHeight;
+ if (size > iMapSize)
+ iMapSize = size;
+ }
+ }
+
+ iMap = new (ELeave) TInt [iMapSize];
+ }
+
+void CScreen::CFallbackMap::Prepare()
+ {
+ const TSizeMode & mode = iScreen->ScreenSizeModeData();
+ Mem::FillZ(iMap, iMapSize * sizeof(TInt));
+ iCount = mode.iScreenSize.iHeight * mode.iScreenSize.iWidth;
+ WS_ASSERT_DEBUG(iRegion.Count() == 1, EWsPanicScreenFallback);
+ iRegion.Clear();
+ iRegion.AddRect(TRect(mode.iOrigin, mode.iScreenSize));
+ }
+
+TBool CScreen::CFallbackMap::FillRegion(const TRegion& aRegion)
+ {
+ WS_ASSERT_DEBUG(!aRegion.CheckError(), EWsPanicScreenFallback);
+ if (aRegion.Count() > 20 || aRegion.CheckError())
+ return ETrue;
+ TBool hit = EFalse;
+ if (iCount > 0)
+ {
+ const TRect * rect = aRegion.RectangleList();
+ for (TInt num = 0; num < aRegion.Count(); ++num)
+ {
+ hit = FillRect(*rect) || hit;
+ if (iCount < 1)
+ break;
+ ++rect;
+ }
+ }
+ return hit;
+ }
+
+// x >> 5 is equivalent to x / 32
+// 0x1F is the rounding error when dividing by 32
+// 0x20 is 32.
+// The compiler might do all the optimizations for us - not checked.
+TBool CScreen::CFallbackMap::FillRect(const TRect& aRect)
+ {
+ TBool hit = EFalse;
+ const TSizeMode & mode = iScreen->ScreenSizeModeData();
+ TRect scrrect(mode.iOrigin, mode.iScreenSize);
+ TRect rect = aRect;
+ rect.Intersection(scrrect);
+ TInt rowWidthInInts = mode.iScreenSize.iWidth;
+ if (rowWidthInInts & 0x1F)
+ rowWidthInInts += 0x20;
+ rowWidthInInts >>= 5;
+
+ TInt colStartInInts = rect.iTl.iX >> 5;
+ TInt firstOffsetInBits = rect.iTl.iX & 0x1F;
+
+ for(TInt row = rect.iTl.iY; row < rect.iBr.iY; ++row)
+ {
+ TInt * map = iMap + row * rowWidthInInts + colStartInInts;
+ TInt offsetShift = 31 - firstOffsetInBits;
+ for (TInt col = rect.iTl.iX; col < rect.iBr.iX; ++col)
+ {
+ WS_ASSERT_DEBUG(map - iMap < iMapSize, EWsPanicScreenFallback);
+ if (!(*map & 1 << offsetShift))
+ {
+ --iCount;
+ hit = ETrue;
+ if (iCount < 1)
+ break;
+ (*map) |= (1 << offsetShift);
+ }
+ --offsetShift;
+ if (offsetShift < 0)
+ {
+ offsetShift = 31;
+ ++map;
+ }
+ }
+ }
+ return hit;
+ }
+
+TInt CScreen::CFallbackMap::Count() const
+ {
+ return iCount;
+ }
+
+const TRect * CScreen::CFallbackMap::Rect() const
+ {
+ return iRegion.RectangleList();
+ }
+
+const RRegion * CScreen::CFallbackMap::Region() const
+ {
+ return &iRegion;
+ }
+
+TInt CScreen::CFallbackMap::Resize(const TSize& aSize)
+ {
+ TInt err = KErrNone;
+ TInt width = (aSize.iWidth+31) >> 5; // divide by 32
+ TInt invertedWidth = (aSize.iHeight+31) >> 5; // divide by 32
+
+ TInt maxSize = Max(width * aSize.iHeight,invertedWidth * aSize.iWidth);
+ if (maxSize > iMapSize)
+ {
+ TInt* newMap=NULL;
+ newMap = new TInt [maxSize];
+ if (newMap)
+ {
+ delete iMap;
+ iMap = newMap;
+ iMapSize = maxSize;
+ }
+ else
+ {
+ err = KErrNoMemory;
+ }
+ }
+ return err;
+ }
+
+//
+// CScreen
+//
+CScreen::CScreen(): iDirects(_FOFF(CWsDirectScreenAccess,iLink)), iMaxContrast(-1), iMaxBrightness(-1)
+, iDisplayChangeSpinner(0), iConfigChangeSpinner(0)
+ {
+ }
+
+CScreen::~CScreen()
+ {
+ delete iDebugBar;
+ TInt ii;
+ if(iModes)
+ {
+ for(ii=iNumScreenSizeModes-1;ii>=0;--ii)
+ {
+ delete (*iModes)[ii];
+ }
+ iModes->Close();
+ delete iModes;
+ }
+ delete iRootWindow;
+ iScreenDevice = NULL;
+ delete iDsaDevice;
+ delete iDeviceMap;
+ delete iFallbackMap;
+ delete iSpriteManager;
+ delete iWindowElementSet;
+ if (!iDsaSurface.IsNull())
+ {
+ TInt err = iScene->UnregisterSurface(iDsaSurface);
+ WS_ASSERT_DEBUG(KErrNone == err, EWsPanicDirectScreenAccess);
+ }
+
+ delete iSurfaceMap;
+ delete iRedraw;
+#if defined(__WINS__) && defined(_DEBUG)
+ delete iDebugWin;
+#endif
+
+ if(iDisplayChangeNotifier)
+ delete iDisplayChangeNotifier;
+ if(iConfigChangeNotifier)
+ delete iConfigChangeNotifier;
+ iWsClientList.Close();
+ }
+
+void CScreen::ConstructL(const TRect& aDigitiserArea, TInt aScreenNumber)
+ {
+ iScreenNumber = aScreenNumber ;
+
+ if (wsDebugLog)
+ {
+ _LIT(KWSERVInitScreen,"Initialising for Screen %d");
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogImportant, KWSERVInitScreen, aScreenNumber);
+ }
+
+ // create screen redraw with render stages
+ iRedraw = CScreenRedraw::NewL(*this);
+ iScreenDevice = iRedraw->ObjectInterface<MWsScreenDevice>();
+ WS_ASSERT_ALWAYS(iScreenDevice, EWsPanicScreenDeviceMissing);
+ iScene = iRedraw->ObjectInterface<MWsScene>();
+ WS_ASSERT_ALWAYS(iScene, EWsPanicSceneMissing);
+
+ iDeviceMap = CGraphicsDeviceMap::NewL(*iScreenDevice);
+
+ iDisplayControl = MWsScreen::ObjectInterface<MWsDisplayControl>();
+ iDisplayMapping = MWsScreen::ObjectInterface<MWsDisplayMapping>();
+ iDisplayPolicy = MWsScreen::ObjectInterface<MWsDisplayPolicy>();
+
+
+ // initialize screen size mode data
+ LoadScreenSizesL(iScreenDevice->SizeInPixels());
+ iFallbackMap = CFallbackMap::NewL(this);
+
+ LoadScreenSizeProperties(iScreenDevice->DisplayMode());
+
+ if (iDisplayPolicy)
+ {
+ iDisplayPolicy->NewAppModesAvailable();
+ }
+
+ iDigitiserArea = aDigitiserArea;
+ SetInitialScreenSizeModeAndRotation(); //get the first/lowest valid mode. Also calls SetDigitiserAreas
+
+ ApplyRemainingWsiniSettingsL();
+
+ iRootWindow = new (ELeave) CWsRootWindow(NULL, this);
+ iRootWindow->ConstructL();
+
+ // Default fading parameters
+ iBlackMap=128;
+ iWhiteMap=255;
+
+ iSpriteManager = CWsSpriteManager::NewL();
+
+ InitializeSceneL();
+ InitializeUiElementsL();
+ iSurfaceMap = new (ELeave) CRegisteredSurfaceMap(*iScene);
+
+ //if the interface for notification is available. start notification AO.
+ if (iDisplayControl)
+ {
+ iDisplayChangeNotifier = CWsDisplayChangeNotifier::NewL(iDisplayControl, this);
+ iDisplayChangeNotifier->IssueNotificationRequest();
+ iConfigChangeNotifier = CWsConfigChangeNotifier::NewL(iDisplayControl, this);
+ iConfigChangeNotifier->IssueNotificationRequest();
+ }
+ doSetScreenMode(iScreenSizeMode,ETrue);
+ }
+
+void CScreen::ApplyRemainingWsiniSettingsL()
+ {
+#if defined(__WINS__) && defined(_DEBUG)
+ _LIT(KDebugOsb,"DEBUGOSB");
+ if(WsIniFile->FindVar(iScreenNumber, KDebugOsb))
+ {
+ _LIT(KDebugWinTitleFormat, "Screen %d, DSA surface");
+ TBuf<32> title;
+ title.Format(KDebugWinTitleFormat, iScreenNumber);
+ iDebugWin = CDebugOsbWin::NewL(title, iScreenDevice->SizeInPixels());
+ }
+#endif
+
+ TInt autoClear = 1;
+ _LIT(KWSERVIniFileVarAutoClear,"AUTOCLEAR");
+ WsIniFile->FindVar(iScreenNumber,KWSERVIniFileVarAutoClear,autoClear);
+ if (autoClear != 0)
+ {
+ iFlags|=EAutoClear;
+ }
+
+ _LIT(KBackLight,"BACKLIGHTCONTROL");
+ iBackLightFlag=WsIniFile->FindVar( iScreenNumber, KBackLight);
+
+ _LIT(KWSERVIniFileVarBlankScreen, "BLANKSCREENONROTATION");
+ if (WsIniFile->FindVar(iScreenNumber, KWSERVIniFileVarBlankScreen))
+ {
+ iFlags|=EBlankScreenOnRotation;
+ }
+
+ //Cache pointers to renderstage APIs required in CHANGETRACKING mode
+ iWindowTreeObserver = iRedraw->ObjectInterface<MWsWindowTreeObserver>();
+ iDrawAnnotationObserver = iRedraw->ObjectInterface<MWsDrawAnnotationObserver>();
+ iWindowVisibilityNotifier = iRedraw->ObjectInterface<MWsWindowVisibilityNotifier>();
+ if(iWindowVisibilityNotifier)
+ {
+ iWindowVisibilityNotifier->RegisterWindowVisibilityObserver(iRedraw);
+ }
+ if (WsIniFile->FindVar(iScreenNumber, KWSERVIniFileVarChangeTracking))
+ {
+ iFlags|=EChangeTracking;
+ }
+
+ //coverity[const]
+ TInt refreshRate = 1000000;
+ _LIT(KDebugBar, "DEBUGBAR");
+ if (WsIniFile->FindVar(KDebugBar, refreshRate))
+ {
+ if (refreshRate < 100000)
+ // coverity [dead_error_line]
+ refreshRate = 50000;
+ iDebugBar = CDebugBar::NewL(this, refreshRate);
+ }
+ }
+
+void CScreen::AcquireDsaScreenDeviceL()
+ {
+ //creates WSERV's DSA buffer handle
+ //registers the DSA surface into the scene accordingly to the value of aRegisterSurface
+ if(!iDsaDevice)
+ {
+ TDisplayMode screenMode = ENone;
+ screenMode = iScreenDevice->DisplayMode();
+ if(screenMode != ENone)
+ {
+ CreateDsaScreenDeviceIfSupportedL(screenMode);
+ // initialize DSA
+ iDsaDevice->SetAutoUpdate(EFalse);
+ iDsaDevice->SetDeviceOrientation(GcToDevice(ScreenSizeModeData().iRotation));
+ iDsaDevice->ChangeScreenDevice(NULL); //This is necessary to initialise the screen
+ // register DSA Surface
+ TInt err = InitializeDsaSurface();
+ // create a graphics context to clear the DSA surface
+ if (!err)
+ err = iDsaDevice->CreateContext(iDsaGc);
+ if (!err)
+ iDsaGc->Activate(iDsaDevice);
+ if (err != KErrNone)
+ {
+ //Creation of the DSA surface failed
+ //Cleanup the DSA Surface ID
+ iDsaSurface = TSurfaceId::CreateNullId();
+ //and the iDsaDevice
+ delete iDsaDevice;
+ iDsaDevice = NULL;
+ User::Leave(err);
+ }
+ }
+ else
+ {
+ User::Leave(KErrNotSupported);
+ }
+ }
+ iNumberDrawingDsa++;
+ }
+
+void CScreen::CreateDsaScreenDeviceIfSupportedL(TDisplayMode aScreenMode)
+ {
+ if(DoCreateDsaScreenDevice(aScreenMode))
+ return;
+ // Try creating the screen device with all available display modes, going from best to worst
+ __ASSERT_COMPILE(EColorLast == 14); // if any display mode is added to TDisplayMode we must update the list below
+ // (the list below contains all enums in TDisplayMode except ENone, ERgb, EColorLast)
+ if(DoCreateDsaScreenDevice(EColor16MAP))
+ return;
+ if(DoCreateDsaScreenDevice(EColor16MA))
+ return;
+ if(DoCreateDsaScreenDevice(EColor16MU))
+ return;
+ if(DoCreateDsaScreenDevice(EColor16M))
+ return;
+ if(DoCreateDsaScreenDevice(EColor64K))
+ return;
+ if(DoCreateDsaScreenDevice(EColor4K))
+ return;
+ if(DoCreateDsaScreenDevice(EColor256))
+ return;
+ if(DoCreateDsaScreenDevice(EColor16))
+ return;
+ if(DoCreateDsaScreenDevice(EGray256))
+ return;
+ if(DoCreateDsaScreenDevice(EGray16))
+ return;
+ if(DoCreateDsaScreenDevice(EGray4))
+ return;
+ if(DoCreateDsaScreenDevice(EGray2))
+ return;
+ User::Leave(KErrNotSupported);
+ }
+
+TBool CScreen::DoCreateDsaScreenDevice(TDisplayMode aScreenMode)
+ {
+ TRAPD(err, iDsaDevice = CFbsScreenDevice::NewL(iScreenNumber, aScreenMode));
+ if(err == KErrNone)
+ {
+ TUint supportedDsaRotationModes = iDsaDevice->DeviceOrientationsAvailable();
+ MWsScene::TSceneRotation currenTSceneRotation = iScene->SceneRotation();
+ TBool doesDsaSupportThisMode = EFalse;
+ switch(currenTSceneRotation)
+ {
+ case MWsScene::ESceneAntiClockwise0:
+ if(supportedDsaRotationModes & EDeviceOrientationNormal)
+ {
+ doesDsaSupportThisMode = ETrue;
+ }
+ break;
+ case MWsScene::ESceneAntiClockwise90:
+ if(supportedDsaRotationModes & EDeviceOrientation90CW)
+ {
+ doesDsaSupportThisMode = ETrue;
+ }
+ break;
+ case MWsScene::ESceneAntiClockwise180:
+ if(supportedDsaRotationModes & EDeviceOrientation180)
+ {
+ doesDsaSupportThisMode = ETrue;
+ }
+ break;
+ case MWsScene::ESceneAntiClockwise270:
+ if(supportedDsaRotationModes & EDeviceOrientation270CW)
+ {
+ doesDsaSupportThisMode = ETrue;
+ }
+ break;
+ default:
+ RDebug::Print(_L("** CScreen::DoCreateDsaScreenDevice Panic, non existing rotation mode"));
+ WS_PANIC_ALWAYS(EWsPanicInvalidOperation);
+ break;
+ }
+ if(!doesDsaSupportThisMode)
+ {
+ delete iDsaDevice;
+ iDsaDevice = NULL;
+ RDebug::Print(_L("** Current Rotation Mode not supported by the DSA device"));
+ err = KErrNotSupported;
+ }
+ }
+ return (err == KErrNone);
+ }
+
+void CScreen::AbortDSAs(RDirectScreenAccess::TTerminationReasons aReason, TSglQue<CWsDirectScreenAccess>& aDirects)
+ {
+ if (aDirects.IsEmpty())
+ return;
+
+ TInt nofDSAs = 0;
+ CWsDirectScreenAccess* direct= NULL;
+ TSglQueIter<CWsDirectScreenAccess> iter(aDirects);
+ while ((direct=iter++)!=NULL)
+ {
+ nofDSAs++;
+ direct->SignalAbort(aReason);
+ }
+
+ TRequestStatus timerStatus;
+ RTimer& timer=CWsTop::Timer();
+ timer.Cancel();
+
+ TRequestStatus** cancelReqList = (TRequestStatus**) User::AllocZ(sizeof(TRequestStatus*) * (nofDSAs + 1));
+ if (NULL != cancelReqList)
+ {
+ TInt dsaNo = 1;
+ timer.After(timerStatus, KDSAAbortingImmediateRespAwaitFrameMicrosec);
+ iter.SetToFirst();
+ while ((direct=iter++)!=NULL)
+ {
+ WS_ASSERT_DEBUG((dsaNo<=(nofDSAs)),EWsPanicDirectScreenAccess);
+ cancelReqList[ dsaNo ] = &direct->AbortStatus();
+ dsaNo++;
+ }
+ cancelReqList[ 0 ] = &timerStatus;
+
+ //wait for response or timeout
+ User::WaitForNRequest(cancelReqList, nofDSAs + 1);
+
+ iter.SetToFirst();
+ while ((direct=iter++)!=NULL)
+ {
+ if (direct->AbortStatus() != KRequestPending)
+ direct->CancelAbortObject(); // responded
+ else
+ direct->Abort();
+ }
+
+ if (timerStatus == KRequestPending)
+ {
+ timer.Cancel();
+ User::WaitForRequest(timerStatus);
+ }
+
+ User::Free(cancelReqList);
+ }
+ else
+ {
+ iter.SetToFirst();
+ while ((direct=iter++) != NULL)
+ {
+ TRequestStatus timerStatus;
+ RTimer& timer=CWsTop::Timer();
+ timer.Cancel();
+ timer.After(timerStatus, KDSAAbortingImmediateRespAwaitFrameMicrosec);
+
+ //wait for response or timeout
+ User::WaitForRequest(direct->AbortStatus(), timerStatus);
+
+ if (direct->AbortStatus() != KRequestPending)
+ direct->CancelAbortObject(); //responded
+ else
+ direct->Abort(); //timed out
+
+ if (timerStatus == KRequestPending)
+ {
+ timer.Cancel();
+ User::WaitForRequest(timerStatus);
+ }
+ }
+ }
+ }
+
+void CScreen::AbortAllDirectDrawing(RDirectScreenAccess::TTerminationReasons aReason)
+ {
+ AbortDSAs(aReason,iDirects);
+ }
+
+void CScreen::AddDirect(CWsDirectScreenAccess& aDirect)
+ {
+ TBool emptyBefore = iDirects.IsEmpty();
+ iDirects.AddLast(aDirect);
+ TBool emptyAfter = iDirects.IsEmpty();
+ if (emptyBefore && ! emptyAfter)
+ {
+ TWsEvent wsevent;
+ wsevent.SetType(EEventDirectScreenAccessBegin);
+ *(wsevent.Int()) = iScreenNumber;
+ TWindowServerEvent::PublishNotification(wsevent);
+ }
+
+ if (iDsaDrawState==EDsaDrawStateIdle && aDirect.IsVisible())
+ {
+ iDsaDrawState = EDsaDrawStateDrawing;
+ TWindowServerEvent::NotifyDrawer(TWservCrEvent(TWservCrEvent::EDsaDrawingBegin, iScreenNumber));
+ }
+ }
+
+void CScreen::RemoveDirect(CWsDirectScreenAccess& aDirect)
+ {
+ TBool emptyBefore = iDirects.IsEmpty();
+ iDirects.Remove(aDirect);
+ TBool emptyAfter = iDirects.IsEmpty();
+ if (emptyAfter && ! emptyBefore)
+ {
+ TWsEvent wsevent;
+ wsevent.SetType(EEventDirectScreenAccessEnd);
+ *(wsevent.Int()) = iScreenNumber;
+ TWindowServerEvent::PublishNotification(wsevent);
+ }
+
+ if (iDsaDrawState==EDsaDrawStateDrawing && aDirect.IsVisible() && !HasVisibleDirectOnQueue())
+ {
+ iDsaDrawState = EDsaDrawStateIdle;
+ TWindowServerEvent::NotifyDrawer(TWservCrEvent(TWservCrEvent::EDsaDrawingEnd, iScreenNumber));
+ }
+ }
+
+TBool CScreen::HasVisibleDirectOnQueue()
+ {
+ if (iDirects.IsEmpty())
+ return EFalse;
+
+ TSglQueIter<CWsDirectScreenAccess> iter(iDirects);
+ CWsDirectScreenAccess* dsa;
+ while ((dsa=iter++)!=NULL)
+ {
+ if (dsa->IsVisible())
+ return ETrue;
+ }
+
+ return EFalse;
+ }
+
+#if defined(_DEBUG)
+TBool CScreen::IsDirectOnQueue(const CWsDirectScreenAccess* aDirect)
+ {
+ TSglQueIter<CWsDirectScreenAccess> iter(iDirects);
+ CWsDirectScreenAccess* direct;
+ while ((direct=iter++)!=NULL)
+ {
+ if (direct==aDirect)
+ return ETrue;
+ }
+ return EFalse;
+ }
+#endif
+
+void CScreen::KillForegroundSession()
+ {
+ if (iCurrentFocus)
+ {
+ _LIT(KWSERVKillWinGp,"Killing Session owning Window Group with Id=%d");
+ if (wsDebugLog)
+ wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,KWSERVKillWinGp,iCurrentFocus->Identifier());
+ iCurrentFocus->WsOwner()->SessionTerminate();
+ }
+ }
+
+CWsWindowGroup* CScreen::FindNewFocus(CWsRootWindow* aRootWindow)
+ {
+ CWsWindowGroup* newFocus;
+ for(newFocus=aRootWindow->Child();newFocus && newFocus->CanReceiveFocus()==EFalse;newFocus=newFocus->NextSibling()) {}
+
+ return newFocus;
+ }
+
+void CScreen::ResetFocus(CWsWindowGroup* aClosingWindow)
+ {
+ CWsWindowGroup* oldFocus=iCurrentFocus;
+ CWsWindowGroup* newFocus=NULL;
+ CScreen* newFocusedScreen=NULL;
+ iCurrentFocus=FindNewFocus(iRootWindow);
+ TBool focusedScreen= EFalse;
+ /*Focus policy is specified in the wsini.ini file using the keyword 'MULTIFOCUSPOLICY'.
+ If the keyword is not specified, then the default policy is run.
+ */
+ if(!CWsTop::MultiFocusPolicy())
+ {
+ focusedScreen=(this==CWsTop::CurrentFocusScreen()); //check if this screen is the focus screen
+ if (!iCurrentFocus && focusedScreen)
+ {
+ /*If this screen is the focused screen but does not have a focusable window group, then search for the
+ next screen that has a focusable window group and set that screen as the focused screen.
+ */
+ CScreen* screen=NULL;
+ TInt screenNo;
+ for (screenNo=0; screenNo<CWsTop::NumberOfScreens() && !newFocus; ++screenNo)
+ {
+ if (screenNo!=iScreenNumber)
+ {
+ screen=CWsTop::Screen(screenNo);
+ newFocus=FindNewFocus(screen->RootWindow());
+ }
+ }
+ if (newFocus)
+ newFocusedScreen=screen;
+ }
+ }
+ /*Scenario A: multi-focus policy
+ newFocusedScreen is NULL
+ focusedScreen is EFalse
+ CWsTop::MultiFocusPolicy() returns ETrue
+ Check if the new focusable window group is not the same, send focus lost message to window group
+ that has just lost focus and send focus gain message to window group that can receive focus.
+ Scenario B: single-focus policy (default)
+ CWsTop::MultiFocusPolicy() returns EFalse
+ Check if the new focusable window group is not the same or if there is a new focused screen, send focus lost
+ message to window group that has just lost focus and send focus gain message to window group that can receive focus.
+ */
+ if (iCurrentFocus!=oldFocus || newFocusedScreen)
+ {
+ if (oldFocus && (focusedScreen || CWsTop::MultiFocusPolicy()) && oldFocus!=aClosingWindow)
+ {
+ oldFocus->LostFocus();
+ }
+ if (newFocusedScreen)
+ {
+ CWsTop::SetCurrentFocusScreen(newFocusedScreen);
+ newFocus->ReceivedFocus();
+ }
+ else if (iCurrentFocus && (focusedScreen || CWsTop::MultiFocusPolicy()))
+ {
+ iCurrentFocus->ReceivedFocus();
+ }
+ TWsPointer::UpdatePointerCursor();
+ TWindowServerEvent::SendFocusChangedEvents();
+ }
+ TWindowServerEvent::SendGroupListChangedEvents();
+ }
+
+void CScreen::RemoveFromDefaultOwningList(CWsWindowGroup *aDestroyedGroup)
+ {
+ for (CWsWindowGroup **group=&iDefaultOwningWindow;*group;group=(*group)->NextDefaultOwningWindowPtr())
+ {
+ if (*group==aDestroyedGroup)
+ {
+ *group=*aDestroyedGroup->NextDefaultOwningWindowPtr();
+ break;
+ }
+ }
+ }
+
+void CScreen::SetDefaultOwningWindow(CWsWindowGroup *aGroup)
+ {
+ RemoveFromDefaultOwningList(aGroup);
+ aGroup->SetNextDefaultOwningWindow(iDefaultOwningWindow);
+ iDefaultOwningWindow=aGroup;
+ }
+
+void CScreen::GetScanLine(const TWsSdCmdGetScanLine *aGetScanLine)
+ {
+ TRgb buf[EGetScanLineBufLen];
+ TPtr8 des((TUint8 *)&buf[0],EGetScanLineBufLen*sizeof(TRgb));
+ TPoint pos(aGetScanLine->pos);
+ TInt read=0;
+ TInt len=(des.MaxLength()*EGetScanLineBufLen)/CFbsBitmap::ScanLineLength(EGetScanLineBufLen,aGetScanLine->dispMode);
+ if (aGetScanLine->len < 0 || (CFbsBitmap::ScanLineLength(aGetScanLine->len, aGetScanLine->dispMode) >
+ CWsClient::CurrentClient()->ClientMessage().GetDesMaxLength(1)))
+ {
+ CWsClient::PanicCurrentClient(EWservPanicInvalidParameter);
+ }
+ FOREVER
+ {
+ if ((aGetScanLine->len-read)<len)
+ len=aGetScanLine->len-read;
+ iScreenDevice->GetScanLine(des,pos,len,aGetScanLine->dispMode);
+ CWsClient::ReplyBuf(des);
+ read+=len;
+ if (read==aGetScanLine->len)
+ break;
+ pos.iX+=len;
+ }
+ }
+
+void CScreen::MaxNumColors(TInt& aColors,TInt& aGrays)
+ {
+ aGrays=0;
+ aColors=TDisplayModeUtils::NumDisplayModeColors(DisplayMode());
+ if (!TDisplayModeUtils::IsDisplayModeColor(DisplayMode()))
+ {
+ aGrays=aColors;
+ aColors=0;
+ }
+ }
+
+#define MODE_TO_FLAG(x) 1<<(x-1)
+#define ROTATION_TO_FLAG(x) 1<<x
+const TUint allRotationsMask = ROTATION_TO_FLAG(CFbsBitGc::EGraphicsOrientationNormal)
+ | ROTATION_TO_FLAG(CFbsBitGc::EGraphicsOrientationRotated90)
+ | ROTATION_TO_FLAG(CFbsBitGc::EGraphicsOrientationRotated180)
+ | ROTATION_TO_FLAG(CFbsBitGc::EGraphicsOrientationRotated270);
+const TUint KRotation0_180Mask = ROTATION_TO_FLAG(CFbsBitGc::EGraphicsOrientationNormal)
+ | ROTATION_TO_FLAG(CFbsBitGc::EGraphicsOrientationRotated180);
+const TUint KRotation90_270Mask = ROTATION_TO_FLAG(CFbsBitGc::EGraphicsOrientationRotated90)
+ | ROTATION_TO_FLAG(CFbsBitGc::EGraphicsOrientationRotated270);
+TInt CScreen::ColorModesFlag()
+ {
+ return MODE_TO_FLAG(DisplayMode());
+ }
+
+void CScreen::UpdateDsa()
+ {
+ if(iDsaDevice)
+ {
+ #if defined(__WINS__) && defined(_DEBUG)
+ if (iDebugWin)
+ iDebugWin->Refresh(iDsaDevice->SizeInPixels(), iDsaDevice->DisplayMode(), iDsaDevice->Bits());
+ #endif
+
+ iDsaDevice->Update();
+ }
+ }
+
+const CGraphicsDeviceMap& CScreen::DeviceMap() const
+ {
+ return *iDeviceMap;
+ }
+
+const MWsScreenDevice& CScreen::ScreenDevice() const
+ {
+ return *iScreenDevice;
+ }
+
+void CScreen::SetPointerCursorArea(TInt aMode,const TRect& aRect)
+ {
+ (*iModes)[aMode]->iPointerCursorArea=aRect;
+ (*iModes)[aMode]->iFlags |= EClientDefinedDigitiserArea;
+ TWsPointer::SetPointerCursorPos(TWsPointer::PointerCursorPos());
+ }
+
+CFbsBitGc::TGraphicsOrientation CScreen::Orientation() const
+ {
+ WS_ASSERT_DEBUG(IsValidScreenSizeMode(iScreenSizeMode),EWsPanicInvalidScreenSizeMode);
+ return (*iModes)[iScreenSizeMode]->iRotation;
+ }
+
+TRect CScreen::DrawableArea() const
+ {
+ TRect drawRect=iScreenDevice->SizeInPixels();
+ if (iDisplayMapping)
+ {
+ iDisplayMapping->MapCoordinates(EFullScreenSpace,drawRect,EApplicationSpace,drawRect);
+ }
+ return drawRect;
+ }
+
+TClientPanic CScreen::SetModeRotation(TInt aMode,CFbsBitGc::TGraphicsOrientation aRotation)
+ {
+ if (!IsValidScreenSizeMode(aMode))
+ return EWservPanicScreenModeNumber;
+ TSizeMode& mode=*(*iModes)[aMode];
+ if (!(ROTATION_TO_FLAG(aRotation)&mode.iAlternativeRotations))
+ return EWservPanicRotation;
+ CFbsBitGc::TGraphicsOrientation oldRotation=mode.iRotation;
+ mode.iRotation=aRotation;
+ CWsWindowGroup::NewOrientation(aMode,aRotation, iRootWindow);
+ if (aMode==ScreenSizeMode())
+ {
+ if(iDisplayPolicy && iDisplayControl && (mode.iAlternativeRotations == allRotationsMask))
+ {
+ //square mode supports all 4 rotations. We'd better do a complete Setconfiguration
+ //all parameters are recalculated for 90 degree rotation
+ //The most important one is the offset, since we need to re-center the appmode and it's a policy behaviour
+ TDisplayConfiguration config;
+ iDisplayControl->GetConfiguration(config);
+ //update rotation
+ config.SetRotation((TDisplayConfiguration::TRotation)aRotation);
+ SetConfiguration(config);
+ }
+ else if (!UpdateOrientation())
+ {
+ // Roll back earlier change
+ mode.iRotation=oldRotation;
+ CWsWindowGroup::NewOrientation(aMode, oldRotation, iRootWindow);
+ }
+ }
+ return EWservNoPanic;
+ }
+
+void CScreen::CycleDisplaySize()
+ {
+ TInt newMode = iScreenSizeMode;
+ TSizeMode* sizeMode = NULL;
+ do
+ {
+ newMode = (newMode+1)%iModes->Count();
+ sizeMode = (*iModes)[newMode];
+ }
+ while (sizeMode==NULL);
+ doSetScreenMode(newMode);
+ }
+
+void CScreen::doSetScreenMode(TInt aMode,TBool aInsideStartup)
+ {
+ WS_ASSERT_DEBUG(IsValidScreenSizeMode(aMode),EWsPanicInvalidScreenSizeMode);
+ TWindowServerEvent::NotifyDrawer(TWservCrEvent(TWservCrEvent::EScreenSizeModeAboutToChange, aMode));
+
+ if (iDisplayControl && iDisplayPolicy)
+ {
+ TDisplayConfiguration config;
+ TRect sizeModePosition;
+ TInt error;
+ TSizeMode& mode=*(*iModes)[aMode];
+ config.SetRotation((TDisplayConfiguration::TRotation)mode.iRotation);
+ //This will return suitable config when display is connected
+ //and UI size equal to smallest appmode when disconnected
+ error = iDisplayPolicy->GetSizeModeConfiguration(aMode,config,sizeModePosition);
+ //set appmode in policy
+ if (iDisplayMapping)
+ {
+ iDisplayMapping->SetSizeModeExtent(sizeModePosition,MWsDisplayMapping::KOffsetAll);
+ }
+ MWsScene::TSceneRotation oldRotation;
+ TSize newUiSize;
+ config.GetResolution(newUiSize);
+ if (error == KErrNone)
+ {
+ oldRotation = iScene->SceneRotation();
+ //The config info will always be set in policy. If display is connected, policy will have
+ //correct composition, Ui and app res. otherwise Ui and appmode will be both set to smallest
+ //app mode, composition will be set to zero
+ if (iFlags&EHasDynamicSizeModes)
+ {
+ error = iFallbackMap->Resize(newUiSize);
+ }
+ if (error == KErrNone)
+ {
+ error = iDisplayControl->SetConfiguration(config);
+ }
+ }
+ if (error == KErrNone)
+ {
+ UpdateDynamicScreenModes();
+ AbortAllDirectDrawing(RDirectScreenAccess::ETerminateScreenMode);
+
+ if(iDsaDevice && iDsaDevice->GraphicsAccelerator())
+ {
+ iDsaDevice->ChangeScreenDevice(iDsaDevice); // orientation has changed, therefore we need to re-initialise the screen device's graphics accelerator
+ }
+
+ iScreenSizeMode=aMode;
+ //This could fail (to set orientation on the context, or to register the rotated DSA).
+ //Previously, the update rotation was deferred, leaving the size mode out of step with the actual rotation
+ //It also returns false if the orientation is "intentionally" not modified.
+ (void) UpdateOrientation(&oldRotation);
+
+ //SetDigitiserAreas needs revisiting if/when we support dynamic resolutions
+ //on a screen with touch input.
+ //SetDigitiserAreas(newUiSize);
+
+ CWsWindowGroup::SetScreenDeviceValidStates(this);
+
+ if (!aInsideStartup)
+ {
+ iWindowElementSet->ResubmitAllElementExtents();
+ //TODO jonas: we'd like to not have to clear at all... make the actual change to compositor etc lazily!
+ if(BlankScreenOnRotation())
+ {
+ iRootWindow->ClearDisplay();
+ }
+
+ CWsTop::ClearAllRedrawStores();
+ DiscardAllSchedules();
+ iRootWindow->InvalidateWholeScreen();
+ }
+ }
+ }
+ else
+ {
+ if (iDisplayMapping)
+ {
+ TRect sizeModePosition;
+ TRAPD(err,sizeModePosition=TRect(OriginL(aMode),ScreenModeSizeInPixelsL(aMode)));
+ if (err==KErrNone)
+ {
+ iDisplayMapping->SetSizeModeExtent(sizeModePosition,MWsDisplayMapping::KOffsetAll);
+ }
+ }
+ if (!aInsideStartup && (*iModes)[aMode]->iOrigin != (*iModes)[iScreenSizeMode]->iOrigin)
+ {
+ iWindowElementSet->ResubmitAllElementExtents();
+ if ((*iModes)[aMode]->iRotation == (*iModes)[iScreenSizeMode]->iRotation)
+ {
+ //TODO jonas: we'd like to not have to clear at all... make the actual change to compositor etc lazily!
+ if(BlankScreenOnRotation())
+ {
+ iRootWindow->ClearDisplay();
+ }
+
+ CWsTop::ClearAllRedrawStores();
+ DiscardAllSchedules();
+ iRootWindow->InvalidateWholeScreen();
+ }
+ }
+ iScreenSizeMode=aMode;
+ //This could fail (to set orientation on the context, or to register the rotated DSA).
+ //Previously, the update rotation was deferred, leaving the size mode out of step with the actual rotation
+ //It also returns false if the orientation is not modified.
+ (void)UpdateOrientation();
+ CWsWindowGroup::SetScreenDeviceValidStates(this);
+ }
+ TWindowServerEvent::SendScreenDeviceChangedEvents(this);
+ ResetFocus(NULL);
+ }
+
+void CScreen::CycleOrientation()
+ {
+ WS_ASSERT_DEBUG(IsValidScreenSizeMode(iScreenSizeMode),EWsPanicInvalidScreenSizeMode);
+ TSizeMode& currentSizeMode=*(*iModes)[iScreenSizeMode];
+ TUint rotations=currentSizeMode.iAlternativeRotations;
+ TInt currentRotation=currentSizeMode.iRotation;
+ TInt rotation=currentRotation+1;
+ while (rotation!=currentRotation)
+ {
+ if (rotation>CFbsBitGc::EGraphicsOrientationRotated270)
+ rotation=CFbsBitGc::EGraphicsOrientationNormal;
+ if (ROTATION_TO_FLAG(rotation)&rotations)
+ break;
+ ++rotation;
+ }
+ if (rotation==currentRotation)
+ {
+ if (rotation>CFbsBitGc::EGraphicsOrientationRotated90)
+ rotation-=2;
+ else
+ rotation+=2;
+ }
+ currentSizeMode.iRotation=REINTERPRET_CAST(CFbsBitGc::TGraphicsOrientation&,rotation);
+ CWsWindowGroup::NewOrientation(iScreenSizeMode,currentSizeMode.iRotation, iRootWindow);
+
+ if (!UpdateOrientation())
+ {
+ // Roll back earlier changes
+ currentSizeMode.iRotation=REINTERPRET_CAST(CFbsBitGc::TGraphicsOrientation&,currentRotation);
+ CWsWindowGroup::NewOrientation(iScreenSizeMode, currentSizeMode.iRotation, iRootWindow);
+ }
+ }
+
+/**
+ * This method is called either when switching screen size mode, or when the
+ * orientation of the currently active screen size mode is changed.
+ */
+TBool CScreen::UpdateOrientation(MWsScene::TSceneRotation* aOldRotation)
+ {
+ CFbsBitGc::TGraphicsOrientation gcOrientation = Orientation();
+
+ MWsScene::TSceneRotation oldRotation = aOldRotation? (*aOldRotation):(iScene->SceneRotation());
+ MWsScene::TSceneRotation newRotation = GcToScreen(gcOrientation);
+ TDeviceOrientation newDeviceOrientation = GcToDevice(gcOrientation);
+
+ // We have to disable the text cursor here while we are still in the
+ // same orientation or offset as we drew it.
+ RWsTextCursor* cursor = CWsTop::CurrentTextCursor();
+ if (cursor)
+ {
+ cursor->Disable();
+ }
+
+// Some of this method has to be done when changing mode even if not changing rotation
+ TBool rotating=(oldRotation != newRotation);
+ if (rotating)
+ {
+
+ // Set the new screen rotation and update the UI element extent
+ if (iScene->SetSceneRotation(newRotation) != KErrNone)
+ return EFalse;
+ // Set the new orientation for the DSA device and update the DSA surface
+ if(iDsaDevice)
+ {
+ iDsaDevice->SetDeviceOrientation(newDeviceOrientation);
+
+ TSurfaceId newSurface;
+ iDsaDevice->GetSurface(newSurface);
+ TInt errRegister = iScene->RegisterSurface(newSurface);
+ WS_ASSERT_DEBUG(KErrNone == errRegister, EWsPanicDirectScreenAccess);
+ // This will remove all the DSA elements from the scene
+ AbortAllDirectDrawing(RDirectScreenAccess::ETerminateRotation);
+
+ TInt errUnregister = iScene->UnregisterSurface(iDsaSurface);
+ WS_ASSERT_DEBUG(KErrNone == errUnregister, EWsPanicDirectScreenAccess);
+ iDsaSurface = newSurface;
+ }
+
+ //updaterotation should not fail after this point (no cleanup)
+
+ TWservCrEvent crEvent(TWservCrEvent::EDeviceOrientationChanged,iScreenNumber,&gcOrientation);
+ TWindowServerEvent::NotifyDrawer(crEvent);
+
+ if(iDsaDevice && iDsaDevice->GraphicsAccelerator())
+ {
+ iDsaDevice->ChangeScreenDevice(iDsaDevice); // orientation has changed, therefore we need to re-initialise the screen device's graphics accelerator
+ }
+
+ }
+
+ iRootWindow->AdjustCoordsDueToRotation();
+ if (rotating)
+ {
+ if(BlankScreenOnRotation())
+ {
+ iRootWindow->ClearDisplay();
+ }
+
+ CWsTop::ClearAllRedrawStores();
+ DiscardAllSchedules();
+ iRootWindow->InvalidateWholeScreen();
+ }
+ return ETrue;
+ }
+
+TPoint CScreen::PhysicalToLogical(TPoint aPhysicalPt)
+ {
+ const TSizeMode& mode=ScreenSizeModeData();
+ TPoint logicalPt;
+ if(!iDisplayMapping)
+ {
+ //old behaviour
+ logicalPt=aPhysicalPt-mode.iOrigin;
+ if (mode.iScreenScale.iWidth!=1)
+ logicalPt.iX=(logicalPt.iX>=0 ? logicalPt.iX/mode.iScreenScale.iWidth : (logicalPt.iX-(mode.iScreenScale.iWidth-1))/mode.iScreenScale.iWidth);
+ if (mode.iScreenScale.iHeight!=1)
+ logicalPt.iY=(logicalPt.iY>=0 ? logicalPt.iY/mode.iScreenScale.iHeight : (logicalPt.iY-(mode.iScreenScale.iHeight-1))/mode.iScreenScale.iHeight);
+ }
+ else
+ {
+ //rect with dummy size for coordinates mapping purpose
+ TRect rectInComp(aPhysicalPt, TSize(1,1));
+ TRect rectInApp;
+ iDisplayMapping->MapCoordinates(ECompositionSpace, rectInComp, EApplicationSpace,rectInApp);
+ logicalPt = rectInApp.iTl;
+ }
+
+ return logicalPt;
+ }
+
+void CScreen::LoadScreenSizesL(TSize aScreenSize)
+ {
+ _LIT(KWSERVNumScrSizeMode, "NUMSCREENMODES");
+ TBool allowScrGap=WsIniFile->FindVar(iScreenNumber, KWSERVNumScrSizeMode, iNumScreenSizeModes);
+ iModes=new(ELeave) RPointerArray<TInternalSizeMode>(1);
+ WS_ASSERT_DEBUG(!allowScrGap || (allowScrGap && iNumScreenSizeModes>0), EWsPanicInvalidScreenSizeMode);
+ TInt screenNum=0;
+ FOREVER
+ {
+ ++screenNum;
+ TBuf<32> varNameWidth;
+ TBuf<32> varNameHeight;
+ _LIT(KWSERVScreenWidthPattern,"SCR_WIDTH%d");
+ varNameWidth.Format(KWSERVScreenWidthPattern,screenNum);
+ _LIT(KWSERVScreenHeightPattern,"SCR_HEIGHT%d");
+ varNameHeight.Format(KWSERVScreenHeightPattern,screenNum);
+ TSize screenSize;
+ if (!WsIniFile->FindVar(iScreenNumber, varNameWidth, screenSize.iWidth) ||
+ !WsIniFile->FindVar(iScreenNumber, varNameHeight, screenSize.iHeight))
+ {
+ if (allowScrGap && screenNum<=iNumScreenSizeModes)
+ {
+ iModes->AppendL(NULL);
+ continue;
+ }
+ else
+ break;
+ }
+ TInt flags=0;
+ if (screenSize.iWidth==0 && screenSize.iHeight==0)
+ {
+ screenSize=aScreenSize;
+ flags|=EHalDefault;
+ }
+ if (screenSize.iWidth==-1 && screenSize.iHeight==-1)
+ {
+ screenSize=aScreenSize;
+ flags|=EDynamic;
+ iFlags|=EHasDynamicSizeModes;
+ }
+ TInternalSizeMode* newSizeMode=new(ELeave) TInternalSizeMode(screenSize);
+ newSizeMode->iFlags|=flags;
+ CleanupStack::PushL(newSizeMode);
+ iModes->AppendL(newSizeMode);
+ CleanupStack::Pop(newSizeMode);
+ ++iNumSupportedScreenSizeModes;
+ }
+ // If sparse index is enabled and no screen size mode defined, all iModes entries will be NULL
+ // Otherwise iModes will be empty
+ if (iModes->Count()==0 || iNumSupportedScreenSizeModes==0)
+ {
+ TInternalSizeMode* defaultSizeMode=new(ELeave) TInternalSizeMode(aScreenSize);
+ defaultSizeMode->iFlags|=EHalDefault;
+ if (iModes->Count()>0)
+ (*iModes)[0]=defaultSizeMode;
+ else
+ {
+ CleanupStack::PushL(defaultSizeMode);
+ iModes->AppendL(defaultSizeMode);
+ CleanupStack::Pop(defaultSizeMode);
+ }
+ ++iNumSupportedScreenSizeModes;
+ }
+ if (!allowScrGap)
+ iNumScreenSizeModes=iNumSupportedScreenSizeModes;
+ }
+
+void CScreen::LoadScreenRotationProperties(TInternalSizeMode& aMode, const TInt aModeIndex)
+ {
+ TBuf<32> varRotation;
+ _LIT(KWSERVScreenRotationPattern,"SCR_ROTATION%d");
+ varRotation.Format(KWSERVScreenRotationPattern,aModeIndex+1);
+ TInt rotation=CFbsBitGc::EGraphicsOrientationNormal;
+ TUint allRotations=0;
+ TPtrC rotList(NULL,0);
+ if (WsIniFile->FindVar( iScreenNumber, varRotation,rotList))
+ {
+ TLex lex(rotList);
+ TBool foundOne=EFalse;
+ TInt rot;
+
+ while (!lex.Eos())
+ {
+ if (!FindNextValue(lex, rot))
+ {
+ break;
+ }
+ if (rot<0 || rot>360)
+ {
+ continue;
+ }
+ if (rot>4)
+ {
+ rot/=90;
+ }
+ if (!foundOne)
+ {
+ rotation=rot;
+ foundOne=ETrue;
+ }
+ if (rot<=CFbsBitGc::EGraphicsOrientationRotated270)
+ {
+ allRotations|=ROTATION_TO_FLAG(rot);
+ }
+ }
+ }
+ if (allRotations==0)
+ allRotations=ROTATION_TO_FLAG(rotation);
+ const TInt KAllRotationsMask = 0xF; //Used to keep the old behaviour
+ WS_ASSERT_ALWAYS((ROTATION_TO_FLAG(rotation)&KAllRotationsMask)>0, EWsPanicFailedToInitialise);
+ aMode.iRotation=reinterpret_cast<CFbsBitGc::TGraphicsOrientation&>(rotation);
+ aMode.iAlternativeRotations=allRotations&KAllRotationsMask;
+ }
+
+void CScreen::LoadScreenTwipsProperties(TInternalSizeMode& aMode, const TInt aModeIndex)
+ {
+ TBuf<32> varNameWidth;
+ _LIT(KWSERVScreenTwipWidthPattern,"SCR_TWIP_WIDTH%d");
+ varNameWidth.Format(KWSERVScreenTwipWidthPattern,aModeIndex+1);
+ TBuf<32> varNameHeight;
+ _LIT(KWSERVScreenTwipHeightPattern,"SCR_TWIP_HEIGHT%d");
+ varNameHeight.Format(KWSERVScreenTwipHeightPattern,aModeIndex+1);
+
+ TSize twipsSize;
+ TBool widthFound = WsIniFile->FindVar(iScreenNumber,varNameWidth,twipsSize.iWidth);
+ TBool heightFound = WsIniFile->FindVar(iScreenNumber,varNameHeight,twipsSize.iHeight);
+
+ // if either of the width or height wsini reads has failed we need to generate default values
+ switch(aMode.iRotation)
+ {
+ // CFbsBitGc::TGraphicsOrientation
+ case CFbsBitGc::EGraphicsOrientationRotated90: // deliberate drop-through
+ case CFbsBitGc::EGraphicsOrientationRotated270:
+ {
+ // CFbsScreenDevice knows nothing about rotation, so we can't use it's PixelsTo Twips methods
+ // So swap the axis here to use the correct twips per pixel ratio
+ if (!widthFound)
+ twipsSize.iWidth = DeviceMap().VerticalPixelsToTwips(aMode.iScreenSize.iWidth);
+ if (!heightFound)
+ twipsSize.iHeight = DeviceMap().HorizontalPixelsToTwips(aMode.iScreenSize.iHeight);
+ break;
+ }
+ case CFbsBitGc::EGraphicsOrientationNormal: // deliberate drop-through
+ case CFbsBitGc::EGraphicsOrientationRotated180:
+ if (!widthFound)
+ twipsSize.iWidth = DeviceMap().HorizontalPixelsToTwips(aMode.iScreenSize.iWidth);
+ if (!heightFound)
+ twipsSize.iHeight = DeviceMap().VerticalPixelsToTwips(aMode.iScreenSize.iHeight);
+ break;
+ default:
+ RDebug::Print(_L("** CScreen::LoadScreenTwipsProperties Panic"));
+ WS_PANIC_ALWAYS(EWsPanicFailedToInitialise);
+ break;
+ }
+ if (widthFound&&heightFound)
+ {
+ aMode.iFlags|=this->ETwipsSpecified;
+ }
+ aMode.iScreenTwipsSize=twipsSize;
+ }
+
+
+void CScreen::LoadScreenSizeProperties(TDisplayMode aDefaultDisplayMode)
+ {
+ for(TInt sizeLoop=0;sizeLoop<iModes->Count();sizeLoop++)
+ {
+ TInternalSizeMode* modePtr=(*iModes)[sizeLoop];
+ if (!modePtr)
+ continue;
+ TInternalSizeMode& mode=*modePtr;
+ TBuf<32> varDisplayMode;
+ _LIT(KWSERVScreenDisplayModePattern,"SCR_WINDOWMODE%d");
+
+ varDisplayMode.Format(KWSERVScreenDisplayModePattern,sizeLoop+1);
+ mode.iScreenScale.iWidth=1;
+ mode.iScreenScale.iHeight=1;
+
+ TBuf<32> varLeft;
+ TBuf<32> varTop;
+ _LIT(KWSERVScreenLeftPattern,"SCR_LEFT%d");
+ _LIT(KWSERVScreenTopPattern,"SCR_TOP%d");
+ varLeft.Format(KWSERVScreenLeftPattern,sizeLoop+1);
+ varTop.Format(KWSERVScreenTopPattern,sizeLoop+1);
+ if (!WsIniFile->FindVar( iScreenNumber, varLeft,mode.iOrigin.iX))
+ mode.iOrigin.iX=0;
+ if (!WsIniFile->FindVar( iScreenNumber, varTop,mode.iOrigin.iY))
+ mode.iOrigin.iY=0;
+
+ TPtrC displayModeName(NULL,0);
+ mode.iDefaultDisplayMode = aDefaultDisplayMode;
+ // must know rotation before parsing twips
+ LoadScreenRotationProperties(mode, sizeLoop);
+ LoadScreenTwipsProperties(mode, sizeLoop);
+
+
+ if(mode.iScreenSize.iWidth == mode.iScreenSize.iHeight && mode.iAlternativeRotations == allRotationsMask)
+ {
+ //square appmode with all four rotations allowed must have square twipsize
+ if((mode.iFlags&ETwipsSpecified) && mode.iScreenTwipsSize.iWidth != mode.iScreenTwipsSize.iHeight)
+ {
+ RDebug::Print(_L("**Panic: Square appmode with all four rotations must have square twip size"));
+ WS_PANIC_ALWAYS(EWsPanicFailedToInitialise);
+ }
+ //square appmode with all four rotations allowed must have square offset
+ if(mode.iOrigin.iX != mode.iOrigin.iY)
+ {
+ RDebug::Print(_L("**Panic: Square appmode with all four rotations must have square offset"));
+ WS_PANIC_ALWAYS(EWsPanicFailedToInitialise);
+ }
+ }
+ else
+ {
+ //Everything else is treated as rectangle appmode. Square appmode not supporting all 4 rotations is considered
+ //as rectangle appmode as well. Rectangle appmode suports 2 rotations at most (0 and 180, or 90 and 270)
+ //first rotation of the appmode is taken to apply the corresponding rotation mask
+ if(!((mode.iAlternativeRotations&KRotation0_180Mask) == mode.iAlternativeRotations
+ || (mode.iAlternativeRotations&KRotation90_270Mask) == mode.iAlternativeRotations))
+ {
+ RDebug::Print(_L("**Panic_DEBUG: non square appmode can only define (0,180) or (90,270) rotations"));
+ WS_PANIC_DEBUG(EWsPanicFailedToInitialise);
+ //in relase build, no panic, just correct the rotations set
+
+ }
+ //correct the rotations set
+ mode.iAlternativeRotations &= ((ROTATION_TO_FLAG(mode.iRotation) & KRotation0_180Mask)? KRotation0_180Mask:
+ KRotation90_270Mask);
+ }
+
+ }
+//
+ TInt intForFindVar=0;
+ _LIT(KWSERVIniFileVarSizeMode,"SIZE_MODE");
+ WsIniFile->FindVar( iScreenNumber, KWSERVIniFileVarSizeMode,intForFindVar);
+ iSizeEnforcementMode=(TScreenModeEnforcement)intForFindVar;
+ }
+
+void CScreen::SetDigitiserAreas(const TSize& aUiSize)
+ { //aUiSize should be the unrotated current ui size
+ //SetDigitiserAreas needs revisiting if/when we support dynamic resolutions on a screen
+ //with touch input. It is not known how digitiser coordinates will be represented if the
+ //physical display resolution changes. Currently digitisers are only supported on screen 0,
+ //and dynamic resolution only applies to higher screen numbers on real hardware.
+ for(TInt sizeLoop=0;sizeLoop<iModes->Count();sizeLoop++)
+ {
+ TInternalSizeMode* modePtr=(*iModes)[sizeLoop];
+ if (!modePtr)
+ continue;
+ TInternalSizeMode& mode=*modePtr;
+ if(mode.iFlags & EClientDefinedDigitiserArea)
+ {
+ //if it's client set, keep it unchanged.
+ continue;
+ }
+ switch (mode.iRotation)
+ {
+ case CFbsBitGc::EGraphicsOrientationNormal:
+ mode.iPointerCursorArea=iDigitiserArea;
+ continue;
+ case CFbsBitGc::EGraphicsOrientationRotated90:
+ mode.iPointerCursorArea.SetRect(iDigitiserArea.iTl.iY,aUiSize.iWidth-iDigitiserArea.iBr.iX,
+ iDigitiserArea.iBr.iY,aUiSize.iWidth-iDigitiserArea.iTl.iX);
+ break;
+ case CFbsBitGc::EGraphicsOrientationRotated180:
+ mode.iPointerCursorArea.SetRect(-(iDigitiserArea.iBr-aUiSize),-(iDigitiserArea.iTl-aUiSize));
+ break;
+ case CFbsBitGc::EGraphicsOrientationRotated270:
+ mode.iPointerCursorArea.SetRect(aUiSize.iHeight-iDigitiserArea.iBr.iY,iDigitiserArea.iTl.iX,
+ aUiSize.iHeight-iDigitiserArea.iTl.iY,iDigitiserArea.iBr.iX);
+ break;
+ default:
+ WS_PANIC_ALWAYS(EWsPanicInvalidRotation);
+ }
+ }
+ }
+
+void CScreen::GetScreenSizeAndRotation(TPixelsTwipsAndRotation &aSar, TInt aScreenMode)
+ {
+ TSizeMode& mode=*(*iModes)[aScreenMode];
+ aSar.iRotation=mode.iRotation;
+ aSar.iPixelSize=mode.iScreenSize;
+ aSar.iTwipsSize=mode.iScreenTwipsSize;
+ if (aSar.iTwipsSize.iWidth==0)
+ {
+ aSar.iTwipsSize.iWidth = iDeviceMap->HorizontalPixelsToTwips(aSar.iPixelSize.iWidth);
+ aSar.iTwipsSize.iHeight = iDeviceMap->VerticalPixelsToTwips(aSar.iPixelSize.iHeight);
+ }
+ }
+
+void CScreen::GetScreenSizeAndRotation(TPixelsAndRotation &aSar, TInt aScreenMode)
+ {
+ TSizeMode& mode=*(*iModes)[aScreenMode];
+ aSar.iRotation=mode.iRotation;
+ aSar.iPixelSize=mode.iScreenSize;
+ }
+
+TBool CScreen::SetScreenModeEnforcement(TInt aMode)
+ {
+ if (aMode<0 || aMode>ESizeEnforcementPixelsTwipsAndRotation)
+ return EFalse;
+ TScreenModeEnforcement newMode=(TScreenModeEnforcement)aMode;
+ if (newMode!=iSizeEnforcementMode)
+ {
+ iSizeEnforcementMode=newMode;
+ CWsWindowGroup::SetScreenDeviceValidStates(this);
+ ResetFocus(NULL);
+ }
+ return ETrue;
+ }
+
+void CScreen::IncContrast()
+ {
+ TInt contrast;
+ if (iMaxContrast<0) //If failed to get it sofar get it again
+ TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EContrast, HAL::Get(iScreenNumber,HALData::EDisplayContrastMax,iMaxContrast));
+ if (TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EContrast, HAL::Get(iScreenNumber,HALData::EDisplayContrast,contrast)))
+ return;
+ if (contrast==iMaxContrast)
+ contrast=-1;
+ TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EContrast, HAL::Set(iScreenNumber,HALData::EDisplayContrast,++contrast));
+ }
+
+void CScreen::DecContrast()
+ {
+ TInt contrast;
+ if (TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EContrast, HAL::Get(iScreenNumber,HALData::EDisplayContrast,contrast)))
+ return;
+ if (contrast==0)
+ {
+ if (iMaxContrast<0 && TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EContrast,
+ HAL::Get(iScreenNumber,HALData::EDisplayContrastMax,iMaxContrast)))
+ return;
+ contrast=iMaxContrast+1;
+ }
+ TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EContrast, HAL::Set(iScreenNumber,HALData::EDisplayContrast,--contrast));
+ }
+
+void CScreen::IncBrightness()
+ {
+ TInt brightness;
+ if (iMaxBrightness<0) //If failed to get it sofar get it again
+ TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Get(iScreenNumber,HALData::EDisplayBrightnessMax,iMaxBrightness));
+ if (TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Get(iScreenNumber,HALData::EDisplayBrightness,brightness)))
+ return;
+ if (brightness==iMaxBrightness)
+ brightness=-1;
+ TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Set(iScreenNumber,HALData::EDisplayBrightness,++brightness));
+ }
+
+void CScreen::DecBrightness()
+ {
+ TInt brightness;
+ if (TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Get(iScreenNumber,HALData::EDisplayBrightness,brightness)))
+ return;
+ if (brightness==0)
+ {
+ if (iMaxBrightness<0 && TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EBackLight,
+ HAL::Get(iScreenNumber,HALData::EDisplayBrightnessMax,iMaxBrightness)))
+ return;
+ brightness=iMaxBrightness+1;
+ }
+ TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Set(iScreenNumber,HALData::EDisplayBrightness,--brightness));
+ }
+TInt CScreen::GetScreenSizeModeList(RArray<TInt>& aList) const
+ {
+ aList.Reset();
+ TInt numModes=iNumScreenSizeModes;
+ TInt err=aList.Reserve(numModes);
+ if (err!=KErrNone)
+ return err;
+ TInt index;
+ for (index=0; index<numModes; ++index)
+ {
+ TSizeMode* modePtr=(*iModes)[index];
+ if (modePtr)
+ aList.Append(index); //Can't fail due to reserve
+ }
+ TInt count=aList.Count();
+ return count;
+ }
+
+TInt CScreen::GetScreenSizeModeListL()
+ {
+ RArray<TInt> list;
+ CleanupClosePushL(list);
+ TInt count=GetScreenSizeModeList(list);
+ User::LeaveIfError(count);
+ CWsClient::ReplyBuf(&list[0], count*sizeof(TInt));
+ CleanupStack::PopAndDestroy(&list);
+ return count;
+ }
+
+void CScreen::SetInitialScreenSizeModeAndRotation()
+ { //Set first app mode that supports current supported rotations if available
+ TInt index;
+ TInt firstMode = -1;
+ TInt bestMode = -1;
+ // Since all screen rotation modes are supported.
+ TBitFlags32 rotationFlags = CFbsBitGc::EGraphicsOrientationNormal|CFbsBitGc::EGraphicsOrientationRotated90|CFbsBitGc::EGraphicsOrientationRotated180|CFbsBitGc::EGraphicsOrientationRotated270;
+ for (index=0; index<iModes->Count(); ++index)
+ {
+ TSizeMode* modePtr=(*iModes)[index];
+ if (modePtr)
+ {
+ if (firstMode == -1)
+ {
+ firstMode = index;
+ }
+ if (rotationFlags.IsSet((TInt)modePtr->iRotation))
+ {
+ bestMode = index;
+ break;
+ }
+ }
+ }
+
+ if (bestMode != -1) //found a mode that supports current supported rotations
+ {
+ iScreenSizeMode = bestMode;
+ }
+ else
+ {
+ if (firstMode != -1) //could only find a mode that doesnt support current supported rotations
+ {
+ iScreenSizeMode = firstMode;
+ }
+ else
+ {
+ return; //couldn't find a mode at all
+ }
+ }
+ if(iDisplayPolicy)
+ {
+ iDisplayPolicy->SetLastAppMode(iScreenSizeMode);
+ }
+
+ SetDigitiserAreas(iScreenDevice->SizeInPixels()); //unrotated size in pixels
+
+ // Here we are mixing CFbsBitGc::TGraphicsOrientation with MWsScene::TSceneRotation
+ // As they both have same values it is fine for now
+ iScene->SetSceneRotation(GcToScreen(ScreenSizeModeData().iRotation)); //set rotation
+ }
+
+
+TDisplayMode CScreen::FirstDefaultDisplayMode() const
+ {
+ TInt mode=-1;
+ while ((*iModes)[++mode]==NULL)
+ {
+ WS_ASSERT_DEBUG(mode<iModes->Count()-1,EWsPanicInvalidScreenSizeMode);
+ }
+ return((*iModes)[mode]->iDefaultDisplayMode);
+ }
+
+void CScreen::AddRedrawRegion(const TRegion& aRegion, TBool aSchedule, TRedrawDepth aDepth)
+ {
+ iRedraw->AddRedrawRegion(aRegion, aSchedule, aDepth);
+ }
+
+void CScreen::ScheduleRender(const TTimeIntervalMicroSeconds& aFromNow)
+ {
+ iRedraw->ScheduleRender(aFromNow);
+ }
+
+void CScreen::DoRedrawNow()
+ {
+ iRedraw->DoRedrawNow();
+ }
+
+// See CScreenRedraw::IsUpdatePending() for important notes on usage.
+void CScreen::RedrawNowIfPending()
+ {
+ if(iRedraw->IsUpdatePending())
+ DoRedrawNow();
+ }
+
+TBool CScreen::IsQuickFadeScheduled( CWsWindow* aWin ) const
+ {
+ return iRedraw->IsQuickFadeScheduled( aWin );
+ }
+
+void CScreen::RemoveFromQuickFadeList( CWsWindow* aWin )
+ {
+ iRedraw->RemoveFromQuickFadeList( aWin );
+ }
+
+void CScreen::AcceptFadeRequest( CWsWindow* aWin, TBool aIsFaded )
+ {
+ iRedraw->AcceptFadeRequest( aWin, aIsFaded );
+ }
+
+// implementing MWsScreen
+
+const TTime& CScreen::Now() const
+ {
+ return iRedraw->Now();
+ }
+
+void CScreen::ScheduleAnimation(TAnimType aType, const TRect& aRect,const TTimeIntervalMicroSeconds& aFromNow,const TTimeIntervalMicroSeconds& aFreq,const TTimeIntervalMicroSeconds& aStop, CWsWindow* aWindow)
+ {
+ iRedraw->ScheduleAnimation(aType, aRect,aFromNow,aFreq,aStop, aWindow);
+ }
+
+TBool CScreen::IsScheduled(TAnimType aType, const TRect& aRect, CWsWindow* aWindow) const
+ {
+ return iRedraw->IsScheduled(aType, aRect, aWindow);
+ }
+
+void CScreen::OnAnimation(TRequestStatus* aFinished)
+ {
+ iRedraw->OnAnimation(aFinished);
+ }
+
+void CScreen::Redraw()
+ {
+ STACK_REGION bounds;
+ bounds.AddRect(DrawableArea());
+ AddRedrawRegion(bounds);
+ bounds.Close();
+ }
+
+TBool CScreen::RedrawInvalid(const TArray<TGraphicDrawerId>& aInvalid)
+ {
+ TBool wasDirty = EFalse;
+ STACK_REGION bounds;
+ bounds.AddRect(DrawableArea());
+ STACK_REGION dirty;
+ TWalkWindowTreeCalcInvalidGraphics calc(&bounds,dirty,aInvalid);
+ if(calc.CreateSubRegion())
+ {
+ calc.CalcInvalid(*this);
+ if(dirty.CheckError() || dirty.Count())
+ {
+ Redraw();
+ wasDirty = ETrue;
+ }
+ calc.DestroyRegions();
+ }
+ dirty.Close();
+ bounds.Close();
+ return wasDirty;
+ }
+
+/**
+ Overidding MWsObjectProvider
+*/
+TAny* CScreen::ResolveObjectInterface(TUint aTypeId)
+ {
+ TAny* interface = NULL;
+
+ switch (aTypeId)
+ {
+ case MWsWindow::EWsObjectInterfaceId:
+ interface = static_cast<MWsWindow*>(RootWindow());
+ break;
+ case MWsScreenConfigList::EWsObjectInterfaceId:
+ interface = static_cast<MWsScreenConfigList*>(this);
+ break;
+ case MWsScreenConfig::EWsObjectInterfaceId:
+ interface = static_cast<MWsScreenConfig*>(this);
+ break;
+ case MWsWindowTree::EWsObjectInterfaceId:
+ interface = static_cast<MWsWindowTree*>(this);
+ }
+
+ if (!interface)
+ interface = iRedraw->ResolveObjectInterface(aTypeId);
+
+ return interface;
+ }
+
+void CScreen::SendTree() const
+ {
+ if(!iWindowTreeObserver)
+ return;
+
+ TWalkWindowTreeSendState wtw(*iWindowTreeObserver);
+ RootWindow()->WalkWindowTreeBackToFront(wtw, EVisitParentNodesFirst);
+
+ //Standard text cursors
+ RWsTextCursor* cursor = CWsTop::CurrentTextCursor();
+ if(cursor)
+ cursor->SendState(*iWindowTreeObserver);
+
+ //Floating Sprites
+ SpriteManager()->SendState(*iWindowTreeObserver);
+
+ //Window Group Chains
+ for(CWsWindowGroup *group=RootWindow()->Child(); group!=NULL; group=group->NextSibling())
+ {
+ group->SendStateWindowGroupChain(*iWindowTreeObserver);
+ }
+ }
+
+TDisplayMode CScreen::DisplayMode() const
+ {
+ return iScreenDevice->DisplayMode();
+ }
+
+TSize CScreen::SizeInPixels() const
+ {
+ return iScreenDevice->SizeInPixels();
+ }
+
+TSize CScreen::SizeInTwips() const
+ {
+ return iScreenDevice->SizeInTwips();
+ }
+
+void CScreen::DiscardAllSchedules()
+ {
+ iRedraw->DiscardAllSchedules();
+ }
+
+void CScreen::ScheduleRegionUpdate(const TRegion* aDefinitelyDirty)
+ {
+ iRedraw->ScheduleRegionUpdate(aDefinitelyDirty);
+ }
+
+TBool CScreen::IsDSAClientWindow( const CWsClientWindow* aWin ) const
+ {
+ TBool res = EFalse;
+ if ( ! iDirects.IsEmpty() )
+ {
+ TSglQueIter<CWsDirectScreenAccess> iter( (TSglQueBase&)iDirects );
+ iter.SetToFirst();
+ CWsDirectScreenAccess* dsa;
+ while ( (dsa = iter++) != NULL && !res )
+ {
+ res = (dsa->ClientWindow() == aWin) && (dsa->IsVisible());
+ }
+ }
+ return res;
+ }
+
+/**
+Update the UI element composition method based on whether
+there are any externals surfaces present and the current display mode.
+If the method changes, recomposition is triggered.
+*/
+void CScreen::UpdateCompositionMode()
+ {
+ // do nothing
+ }
+
+void CScreen::ElementAdded()
+ {
+ UpdateCompositionMode();
+ }
+
+void CScreen::ElementRemoved()
+ {
+ UpdateCompositionMode();
+ }
+
+CRegisteredSurfaceMap* CScreen::SurfaceMap()
+ {
+ return iSurfaceMap;
+ }
+
+void CScreen::InitializeSceneL()
+ {
+ // Ensure the surface is not valid to start with.
+ iDsaSurface = TSurfaceId::CreateNullId();
+ iWindowElementSet = CWindowElementSet::NewL(*iScene);
+ }
+
+MWsElement* CScreen::CreateUiElementL(const TRect& aExtent)
+ {
+ MWsElement* pElement = iScene->CreateSceneElementL();
+
+ TUint32 flags = 0;
+ pElement->GetRenderStageFlags(flags);
+ flags |= MWsElement::EElementIsIndirectlyRenderedUserInterface;
+ pElement->SetRenderStageFlags(flags);
+
+ iScene->InsertSceneElement(pElement, NULL);
+
+ pElement->SetDestinationRectangle(aExtent);
+ pElement->SetSourceRectangle(aExtent); //initial guess... updated by PositionUiElements
+
+ return pElement;
+ }
+
+void CScreen::InitializeUiElementsL()
+ {
+ const TRect screenRect(iScreenDevice->SizeInPixels());
+ MWsElement* pElement = CreateUiElementL(screenRect);
+
+ if(HasAlpha())
+ {
+ TUint32 flags = 0;
+ pElement->GetTargetRendererFlags(flags);
+ flags |= MWsElement::EElementTransparencySource;
+ pElement->SetTargetRendererFlags(flags);
+ }
+ }
+
+TInt CScreen::InitializeDsaSurface()
+ {
+ WS_ASSERT_DEBUG(iDsaSurface.IsNull(),EWsPanicInvalidOperation);
+ iDsaDevice->GetSurface(iDsaSurface);
+ // Currently Surface Manager does not recognise DSA surface IDs originating
+ // from the Screen Driver. This causes it to fail to register such
+ // surfaces. OpenWF should be amended to properly register DSA surfaces.
+ iScene->RegisterSurface(iDsaSurface);
+
+ return KErrNone;
+ }
+
+TSize CScreen::DSASizeInPixels() const
+ {
+ if(iDsaDevice)
+ {
+ return iDsaDevice->SizeInPixels();
+ }
+ else
+ {
+ return TSize(0,0);
+ }
+ }
+
+MWsTextCursor* CScreen::RenderStageTextCursor() const
+ {
+ return iRedraw->RenderStageTextCursor();
+ }
+
+void CScreen::ClearDsaSurface(const TRect& area, const TRgb& color)
+ {
+ WS_ASSERT_DEBUG(iDsaGc, EWsPanicInvalidOperation);
+ iDsaGc->SetBrushStyle(CFbsBitGc::ESolidBrush);
+ iDsaGc->SetPenStyle(CFbsBitGc::ENullPen);
+ iDsaGc->SetBrushColor(color);
+ iDsaGc->DrawRect(area);
+ iDsaDevice->Update();
+ }
+
+void CScreen::ReleaseDsaScreenDevice()
+ {
+ //This function checks if any of the DSA currently active on the screen is actually used to draw
+ //If not it unregister the DSA surface and destroys the iDsaDevice.
+ //This function should be called only by a drawing DSA so a surface should be in place.
+ iNumberDrawingDsa--;
+ if(iNumberDrawingDsa == 0)
+ {
+ WS_ASSERT_DEBUG(!iDsaSurface.IsNull(),EWsPanicInvalidOperation);
+ delete iDsaGc;
+ iDsaGc = NULL;
+ // Currently Surface Manager does not recognise DSA surface IDs originating
+ // from the Screen Driver. This causes it to fail to unregister such
+ // surfaces. OpenWF should be amended to properly register DSA surfaces.
+ iScene->UnregisterSurface(iDsaSurface);
+
+ delete iDsaDevice;
+ iDsaDevice = NULL;
+ //the old surface Id is now meaningless
+ iDsaSurface = TSurfaceId::CreateNullId();
+ }
+ }
+
+TInt CScreen::SetConfiguration(const TDisplayConfiguration& aConfigInput)
+ {
+ TInt reply = KErrNone;
+ if(iDisplayControl)
+ {
+ TDisplayConfiguration config(aConfigInput);
+ TRect sizeModePosition;
+ if (iDisplayPolicy)
+ { //validate config and update to a valid hardware config
+ reply = iDisplayPolicy->GetSizeModeConfiguration(iScreenSizeMode,config,sizeModePosition);
+ if (reply >= KErrNone)
+ {//set appmode in policy
+ if (iDisplayMapping)
+ {
+ iDisplayMapping->SetSizeModeExtent(sizeModePosition,MWsDisplayMapping::KOffsetAll);
+ }
+ }
+ }
+ else
+ { //exessive strategy: limit rotation agains curr app mode.
+ //really we want the system to accept the rotation change regardless of the app mode.
+ TDisplayConfiguration::TRotation newRot;
+ if (aConfigInput.GetRotation(newRot))
+ { //This should cast between rotation enumertaions "properly"
+ if (!(iModes[0][iScreenSizeMode]->iAlternativeRotations&(1<<newRot)))
+ {
+ reply=KErrArgument;
+ }
+ }
+ }
+ if (reply < KErrNone)
+ {
+ return reply;
+ }
+ MWsScene::TSceneRotation oldRotation;
+ oldRotation = iScene->SceneRotation();
+ TSize newUiSize;
+ config.GetResolution(newUiSize);
+ TDisplayConfiguration oldConfig;
+ iDisplayControl->GetConfiguration(oldConfig);
+ if(iFlags&EHasDynamicSizeModes)
+ {
+ reply = iFallbackMap->Resize(newUiSize);
+ }
+ if (reply >= KErrNone)
+ {
+ reply=iDisplayControl->SetConfiguration(config);
+ }
+ if (reply==KErrNone)
+ {
+ TSize oldConfigRes;
+ oldConfig.GetResolution(oldConfigRes);
+ if (oldConfigRes.iWidth == 0 || oldConfigRes.iHeight == 0)
+ {
+ TDisplayConfiguration newConfig;
+ iDisplayControl->GetConfiguration(newConfig);
+ RecalculateModeTwips(&newConfig); //needs res and twips information
+ }
+ UpdateDynamicScreenModes();
+
+ TWindowServerEvent::NotifyDrawer(TWservCrEvent(TWservCrEvent::EScreenSizeModeAboutToChange, iScreenSizeMode));
+ // This will remove all the DSA elements from the scene
+ AbortAllDirectDrawing(RDirectScreenAccess::ETerminateRotation);
+
+ //SetDigitiserAreas needs revisiting if/when we support dynamic resolutions
+ //on a screen with touch input.
+ //SetDigitiserAreas(newUiSize);
+
+ //failure here should only be because of DSA orientation change failure, which shouldn't happen, either.
+ //Or there may be no change to do.
+ (void)UpdateOrientation(&oldRotation);
+
+ iWindowElementSet->ResubmitAllElementExtents();
+ if(iDsaDevice && iDsaDevice->GraphicsAccelerator())
+ {
+ iDsaDevice->ChangeScreenDevice(iDsaDevice); // orientation has changed, therefore we need to re-initialise the screen device's graphics accelerator
+ }
+
+ iRootWindow->AdjustCoordsDueToRotation();
+
+ //TODO jonas: we'd like to not have to clear at all... make the actual change to compositor etc lazily!
+ if(BlankScreenOnRotation())
+ {
+ iRootWindow->ClearDisplay();
+ }
+
+ CWsTop::ClearAllRedrawStores();
+ DiscardAllSchedules();
+ iRootWindow->InvalidateWholeScreen();
+ CWsWindowGroup::SetScreenDeviceValidStates(this);
+ TWindowServerEvent::SendScreenDeviceChangedEvents(this);
+ }
+ else
+ {
+ return reply;
+ }
+ }
+ else
+ {
+ reply = KErrNotSupported;
+ }
+ return reply;
+ }
+
+void CScreen::UpdateDynamicScreenModes()
+ {
+ WS_ASSERT_DEBUG(iDisplayControl,EWsPanicNoDisplayControl);
+ TDisplayConfiguration newConfig;
+ iDisplayControl->GetConfiguration(newConfig);
+ TSize res;
+ TSize twips;
+ newConfig.GetResolution(res);
+ newConfig.GetResolutionTwips(twips);
+ for (TInt i=0; i<iModes->Count(); i++)
+ {
+ if ((*iModes)[i] && ((*iModes)[i]->iFlags & EDynamic))
+ {
+ (*iModes)[i]->iScreenSize = res;
+ (*iModes)[i]->iScreenTwipsSize = twips;
+ }
+ }
+ }
+
+void CScreen::RecalculateModeTwips(const TDisplayConfiguration* aConfig)
+ {
+ TDisplayConfiguration config;
+ iDisplayControl->GetConfiguration(config);
+ TSize res;
+ TSize twips;
+ if (aConfig) //called from SetConfiguration
+ {
+ aConfig->GetResolution(res);
+ if (res.iWidth == 0 || res.iHeight == 0)
+ {
+ return;
+ }
+ aConfig->GetResolutionTwips(twips);
+ }
+ else //called from DisplayChangeNotifier during attach
+ {
+ config.GetResolution(res);
+ if ((res.iWidth == 0 || res.iHeight == 0) && !iDisplayPolicy)
+ {
+ return;
+ }
+ config.GetResolutionTwips(twips);
+ }
+ TInt err=KErrNone;
+ TInt flags=0;
+ for (TInt ii=0; ii<iModes->Count(); ii++)
+ { //for every mode
+ TRAP(err, flags = ModePtrL(ii)->iFlags);
+ if (err != KErrNone || flags&(ETwipsSpecified|EDynamic))
+ { //continue if mode doesnt exist,twips specified or dynamic mode specified
+ continue;
+ }
+
+ if (iDisplayPolicy)
+ { //get ideal config for app mode from policy
+ TRect modePosition;
+ config.ClearAll();
+ TInt err = iDisplayPolicy->GetSizeModeConfiguration(ii,config,modePosition);
+ if (err != KErrNone)
+ { //nothing we can do, the twips will not be calculated correctly
+ continue;
+ }
+ config.GetResolution(res);
+ config.GetResolutionTwips(twips);
+ }
+ TSizeMode* modePtr=(*iModes)[ii];
+ modePtr->iScreenTwipsSize.iWidth = (twips.iWidth * modePtr->iScreenSize.iWidth)/
+ res.iWidth;
+ modePtr->iScreenTwipsSize.iHeight = (twips.iHeight * modePtr->iScreenSize.iHeight)/
+ res.iHeight;
+ }
+
+ }
+
+TInt CScreen::AddNotificationClient(CWsClient *aClient)
+ {
+ TInt err = iWsClientList.InsertInAddressOrder(aClient);
+ if(!(err == KErrNone || err == KErrAlreadyExists))
+ {
+ return err;
+ }
+ return KErrNone;
+ }
+void CScreen::RemoveNotificationClient(CWsClient *aClient)
+ {
+ TInt index = iWsClientList.FindInAddressOrder(aClient);
+ if(index != KErrNotFound)
+ {
+ iWsClientList.Remove(index);
+ }
+ }
+TInt CScreen::GetNotificationClients(RPointerArray<CWsClient>& aClientsArray)
+ {
+ TInt err = aClientsArray.Reserve(iWsClientList.Count());
+ if(err != KErrNone)
+ return err;
+
+ for(TInt i = 0; i < iWsClientList.Count(); i++)
+ {
+ aClientsArray.Append(iWsClientList[i]);
+ }
+ return KErrNone;
+ }
+
+TInt CScreen::FindNotificationClient (CWsClient *aClient)
+ {
+ return iWsClientList.FindInAddressOrder(aClient);
+ }
+
+// implementing MWsScreenConfig... this might be better as RS interface
+TSize CScreen::ScreenModeSizeInPixels() const
+ {
+ return (*iModes)[iScreenSizeMode]->iScreenSize;
+ }
+TInt CScreen::Stride() const
+ {
+ return 0;
+ }
+TInt CScreen::SizeMode() const
+ {
+ return iScreenSizeMode;
+
+ }
+TSize CScreen::ScalingFactor() const
+ {
+ return (*iModes)[iScreenSizeMode]->iScreenScale;
+ }
+TPoint CScreen::Origin() const
+ {
+ return (*iModes)[iScreenSizeMode]->iOrigin;
+ }
+TPoint CScreen::ScaledOrigin() const
+ {
+ return (*iModes)[iScreenSizeMode]->ScaledOrigin();
+ }
+
+const CScreen::TInternalSizeMode* CScreen::ModePtrL(TInt aIndex) const
+ {
+ if (aIndex>=iModes->Count() || aIndex<0)
+ {
+ User::Leave(KErrArgument);
+ }
+ if (iModes==NULL)
+ {
+ User::Leave(KErrNotReady);
+ }
+ TInternalSizeMode* modePtr=(*iModes)[aIndex];
+ if (modePtr==NULL)
+ {
+ User::Leave(KErrArgument);
+ }
+ return modePtr;
+ }
+
+TDisplayMode CScreen::DisplayModeL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->iDefaultDisplayMode;
+ }
+TSize CScreen::ScreenModeSizeInPixelsL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->iScreenSize;
+ }
+TSize CScreen::ScreenModeSizeInTwipsL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->iScreenTwipsSize;
+ }
+
+CFbsBitGc::TGraphicsOrientation CScreen::OrientationL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->iRotation;
+ }
+TInt CScreen::AvailableOrientationsL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->iAlternativeRotations;
+ }
+TSize CScreen::ScalingFactorL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->iScreenScale;
+ }
+TPoint CScreen::OriginL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->iOrigin;
+ }
+TPoint CScreen::ScaledOriginL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->ScaledOrigin();
+ }
+TInt CScreen::ModeFlagsL(TInt aIndex) const
+ {
+ return ModePtrL(aIndex)->iFlags;
+ }
+void CScreen::SetCurrentScreenModeAttributes(const TSizeMode &aModeData)
+ {
+ TSizeMode* modeToOverwrite=(*iModes)[iScreenSizeMode];
+ *modeToOverwrite=aModeData;
+ }
+
+void CScreen::ScheduleWindow(CWsWindow* aWindow)
+ {
+ iRedraw->ScheduleWindow(aWindow);
+ }
+
+void CScreen::RemoveFromScheduledList(CWsWindow* aWindow)
+ {
+ iRedraw->RemoveFromScheduledList(aWindow);
+ }
+
+void CScreen::RemoveFromTimedDrawList(CWsWindow* aWindow)
+ {
+ iRedraw->RemoveFromTimedDrawList(aWindow);
+ }
+
+void CScreen::SetupVisibleRegionTracking(CWsWindow& aWindow, TBool aRegister) const
+ {
+ if(ChangeTracking() && iWindowVisibilityNotifier)
+ {
+ if(aRegister)
+ {
+ iWindowVisibilityNotifier->RegisterWindow(aWindow);
+ }
+ else
+ {
+ iWindowVisibilityNotifier->UnregisterWindow(aWindow);
+ }
+ }
+ }
+
+TBool CScreen::IsAnimating() const
+ {
+ return iRedraw->IsAnimating();
+ }