windowing/windowserver/tdynamicres/src/t_wsdynamicreswinbase.cpp
changeset 0 5d03bc08d59c
child 45 36b2e23a8629
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/tdynamicres/src/t_wsdynamicreswinbase.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,979 @@
+// Copyright (c) 2008-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:
+//
+
+/**
+ @file
+*/
+
+
+#include <e32std.h>
+#include <e32math.h>
+#include <w32std.h>
+#include <w32debug.h>
+#include "teflogextensions.h"
+#include "t_wsdynamicreswinbase.h"
+#include "globalsettings.h"
+#include <bitdraw.h>
+#include <bitdrawinterfaceid.h>
+#include <u32hal.h>
+#include <dispchannel.h>
+#include <graphics/displaycontrol.h>
+
+#if (!defined(K_DISPLAY_CH_MAJOR_VERSION_NUMBER) && !defined(K_DISPLAY_CH_MINOR_VERSION_NUMBER))
+#define MODE_CHANGE_BASE_FUNCTIONALITY_NOT_PRESENT_IN_HEADER
+#endif
+
+_LIT(KMonospaceTestFontTypefaceName,"Arial");
+const TInt KMaxFontSize = 150;
+TBool	CWsDynamicResWinBase::iTransparencyEnabled=EFalse;
+
+CWsDynamicResWinBase::CWsDynamicResWinBase():
+	iDoTearDown(EFalse),
+	iSession(TGlobalSettings::Instance().iScreen)
+{
+}
+
+void CWsDynamicResWinBase::SetupL()
+	{
+	SetupL(EFalse);
+	}
+CActiveScheduler	CWsDynamicResWinBase::iScheduler;
+
+void CWsDynamicResWinBase::SetupL(TBool aUseOtherScreenForInfo)
+	{	
+	if (CActiveScheduler::Current()!=&iScheduler)
+		{
+		new (&iScheduler) CActiveScheduler;
+		CActiveScheduler::Install(&iScheduler);
+		}
+	iDoTearDown=ETrue;
+	iRed.SetInternal(0xFFFF0000);
+	iGreen.SetInternal(0xFF00FF00);
+	iBlue.SetInternal(0xFF0000FF);
+	iCyan.SetInternal(0xFF00FFFF);
+	iMagenta.SetInternal(0xFFFF00FF);
+	iYellow.SetInternal(0xFFFFFF00);
+	iWhite.SetInternal(0xFFFFFFFF);
+	iLastGceHoleColor.SetInternal(0);
+	TITLE_BACKGROUND=iCyan;
+	COMPARE_BACKGROUND=iBlue;
+
+	ASSERT_EQUALS_X(iSession.Connect(), KErrNone);
+
+		{//Stolen from TAuto CloseAllPanicWindows()
+		TInt idFocus = iSession.GetFocusWindowGroup();
+		TWsEvent event;
+		event.SetType(EEventKey); //EEventKeyDown
+		TKeyEvent *keyEvent = event.Key();
+		keyEvent->iCode = EKeyEscape;
+		keyEvent->iScanCode = EStdKeyEscape;
+		keyEvent->iModifiers = 0;
+		TInt theLimit = 50;
+		while(idFocus != NULL && (theLimit-- > 0))
+			{
+			iSession.SendEventToAllWindowGroups(event);
+			TInt idNewFocus = iSession.GetFocusWindowGroup();
+			if (idNewFocus!=idFocus)
+				{
+				INFO_PRINTF1(_L("A window was closed [probably a panic box from the previous test]."));
+				}
+			idFocus=idNewFocus;
+			}
+		}
+	TInt err = KErrNone;
+
+	TRAP(err, iScreenDevice = new (ELeave) CWsScreenDevice(iSession));
+	PRINT_ON_ERROR2_L(err, _L("Failed to create screen device: %d"), err);
+	ASSERT_EQUALS_X(iScreenDevice->Construct(TGlobalSettings::Instance().iScreen), KErrNone);
+	iDisplayMode = iScreenDevice->DisplayMode();	// Get default display mode
+
+	CheckAndConnectScreen();
+
+	TRAP(err, iGc = new (ELeave) CWindowGc(iScreenDevice));
+	PRINT_ON_ERROR2_L(err, _L("Failed to create graphics context: %d"), err);
+	ASSERT_EQUALS_X(iGc->Construct(), KErrNone);
+	
+	iGroup = RWindowGroup(iSession);
+	ASSERT_EQUALS_X(iGroup.Construct(++iWindowHandle,iScreenDevice), KErrNone);
+	iGroup.SetOrdinalPositionErr(0, KPasswordWindowGroupPriority - 1); // Added code ---- Fastpath
+	iSession.Flush();
+	
+	if (aUseOtherScreenForInfo)
+		{
+		if (iSession.NumberOfScreens()>1)
+			{	//Create server objects for info windows to appear on alternate screen
+			TInt alternateScreenNum=iSession.NumberOfScreens()-1;
+			if (TGlobalSettings::Instance().iScreen==alternateScreenNum)
+				{	//Alternate screen is last screen, or first screen if that is being tested. 
+				alternateScreenNum=0;
+				}
+			
+			TRAP(err, iInfoScreenDevice = new (ELeave) CWsScreenDevice(iSession));
+			PRINT_ON_ERROR2_L(err, _L("Failed to create second screen device: %d"), err);
+			ASSERT_EQUALS_X(iInfoScreenDevice->Construct(alternateScreenNum), KErrNone);
+	
+			TRAP(err, iInfoGc = new (ELeave) CWindowGc(iInfoScreenDevice));
+			PRINT_ON_ERROR2_L(err, _L("Failed to create second graphics context: %d"), err);
+			ASSERT_EQUALS_X(iInfoGc->Construct(), KErrNone);
+
+			iInfoGroupInstance = RWindowGroup(iSession);
+			ASSERT_EQUALS_X(iInfoGroupInstance.Construct(++iWindowHandle,iInfoScreenDevice), KErrNone);
+			iInfoGroup=&iInfoGroupInstance;
+			}
+		else
+			{	//If alternate screen is not available then no text or compare windows should be created!
+			iInfoScreenDevice=iScreenDevice;	//it is "convenient" for the device to still be good.
+			iInfoGc=NULL;
+			iInfoGroup=NULL;
+			}
+		}
+	else
+		{	//
+		iInfoScreenDevice=iScreenDevice;
+		iInfoGc=iGc;
+		iInfoGroup=&iGroup;
+		}
+	
+	if (iInfoGroup && iInfoGc)
+		{
+		// Add a plain background window to obscure anything else that
+		// happens to be behind the test. Setting this window's display mode is also
+		// used to set the screen device display mode, and hence the composition
+		// mode: alpha or chroma key.
+		iBackground = RBlankWindow(iSession);
+		ASSERT_EQUALS_X(iBackground.Construct(*iInfoGroup, ++iWindowHandle), KErrNone);
+	
+		iBackground.SetOrdinalPosition(100);	// Behind anything else in this group.
+		iBackground.SetColor(TRgb(iWhite));
+		//iBackground.SetExtent(TPoint(-1000,-1000),TSize(3000,3000));
+		iBackground.Activate();
+		iBackground.SetVisible(ETrue);
+		}
+	iSession.Flush();
+	
+	RWindow testTrans(iSession);
+	ASSERT_EQUALS_X(testTrans.Construct(iGroup, ++iWindowHandle), KErrNone);
+	iTransparencyEnabled=(testTrans.SetTransparencyFactor(iWhite)==KErrNone);
+	if (iTransparencyEnabled)
+		{
+		TTestName testName;
+		testName.Format(_L("Screen %i, depth %i: Found Trans Man"),
+				TGlobalSettings::Instance().iScreen
+			);
+		UpdateTitleWindowL(testName,KMaxInfoLines-1);
+		}
+	else
+		{
+		TTestName testName;
+		testName.Format(_L("Screen %i, depth %i: No Trans Man"),
+				TGlobalSettings::Instance().iScreen
+			);
+		UpdateTitleWindowL(testName,KMaxInfoLines-1);
+		}
+	testTrans.Close();
+	}
+
+
+void CWsDynamicResWinBase::CheckAndConnectScreen()
+	{
+	if (TGlobalSettings::Instance().iDisconnected) //set from script file to match wsini keyword SIMULATE_STARTUP_DISCONNECTED
+		{
+		//Verify that the display really is disconnected
+		ASSERT_TRUE_X(iScreenDevice != NULL);
+		MDisplayControl* interface = static_cast<MDisplayControl*>(iScreenDevice->GetInterface(MDisplayControl::ETypeId));
+		ASSERT_TRUE_X(interface != NULL);
+		RArray<MDisplayControl::TResolution> resolutions;
+		const TInt err = interface->GetResolutions(resolutions);
+		ASSERT_EQUALS_X(err, KErrDisconnected);
+		resolutions.Close();
+		}
+	
+#ifndef MODE_CHANGE_BASE_FUNCTIONALITY_NOT_PRESENT_IN_HEADER
+	//make sure display is attached to screen (only if I/F is available at compile time...)
+	TInt displayState = ENormalResolution;
+	UserSvr::HalFunction(EHalGroupDisplay | (TGlobalSettings::Instance().iScreen<<16), EDisplayHalSetDisplayState, &displayState, NULL);
+	Pause(200);
+#endif	
+	
+	if (TGlobalSettings::Instance().iDisconnected)
+		{
+		//Verify that the display now is connected
+		MDisplayControl* interface = static_cast<MDisplayControl*>(iScreenDevice->GetInterface(MDisplayControl::ETypeId));
+		RArray<MDisplayControl::TResolution> resolutions;
+		const TInt err = interface->GetResolutions(resolutions);
+		ASSERT_EQUALS_X(err, KErrNone);
+		const_cast<TGlobalSettings&>(TGlobalSettings::Instance()).iDisconnected = EFalse;
+		resolutions.Close();
+		}
+	}
+
+/**
+Common tear down code for all tests.
+
+Windows, group and session created are closed. Screen device is destroyed.
+Surfaces, manager and update session are closed.
+*/
+void CWsDynamicResWinBase::TearDownL()
+	{
+	iDoTearDown=EFalse;
+	if (iInfoGc!=iGc)
+		delete iInfoGc;
+	delete iGc;
+	if (iInfoScreenDevice!=iScreenDevice)
+		delete iInfoScreenDevice;
+	delete iScreenDevice;
+
+	iGroup.Close();
+	if (iInfoGroupInstance.WsHandle())
+		iInfoGroupInstance.Close();
+	iSession.Flush();
+	iSession.Close();
+	}
+/**
+ * Note that this is not the ideal mechanism.
+ * A derived class may thinks its TearDown is safe to do from delete, but in the class it is derived from it may not be safe
+ **/
+void CWsDynamicResWinBase::TearDownFromDeleteL()	
+	{
+	CWsDynamicResWinBase::TearDownL();	//Explicitly call the non-derived implementation.
+	}
+
+CWsDynamicResWinBase::~CWsDynamicResWinBase()
+{
+	if (iDoTearDown)
+		TearDownFromDeleteL();	//This mechanism is not entirely clean to use.
+}
+/**
+Pause for the given number of milliseconds.
+
+@param aMilliseconds	Time to wait in milliseconds.
+*/
+void CWsDynamicResWinBase::Pause(TInt aMilliseconds)
+	{
+	User::After(TTimeIntervalMicroSeconds32(aMilliseconds * 1000));
+	}
+// This handles any non-member uses of the extended ASSERT_XXX macros
+void TefUnitFailLeaveL()
+	{
+	
+	User::Leave(KErrTEFUnitFail);
+	}
+/**
+ * side-effect: log the state info just before I leave!
+ * Note that this only logs intentional assertion failures.
+ * Fails due to panics or throws won't log this info.
+ **/
+void CWsDynamicResWinBase::TefUnitFailLeaveL()
+	{
+	for (TInt line=0;line<KMaxInfoLines;line++)
+		if (iTestInfo[line].Length())
+			Logger().LogExtra((TText8*)"Test state at fail - line",line, ESevrAll, iTestInfo[line]);
+	
+	User::Leave(KErrTEFUnitFail);
+	}
+
+/**	Creates the LHS info window, annd a middle window to display a representation of the expected result.
+ *  Also sets up a rectangle representing the space on the right to be used for the test
+ * 	@param	aTitle	The title to display on the info window
+ *  @param	aDetail	Optional text to display on the first line under the title
+**/
+void CWsDynamicResWinBase::MakeTitleAndCompareWindowsL(TRefByValue<const TDesC16> aTitle,TRefByValue<const TDesC16> aDetail)
+	{	
+	iTestName=aTitle;
+	iTestInfo[0]=aDetail;
+	
+	TRect screenSize(iInfoScreenDevice->SizeInPixels());
+	TPoint oneThird(screenSize.iBr.iX/3,screenSize.iBr.iY/3);
+	TRect winSize(0,0,oneThird.iX,oneThird.iY);
+	
+	if (oneThird.iX>oneThird.iY)
+		{
+		oneThird.iY=0;
+		winSize.iBr.iY=screenSize.iBr.iY;
+		}
+	else
+		{
+		oneThird.iX=0;
+		winSize.iBr.iX=screenSize.iBr.iX;
+		}
+	winSize.Shrink(5,5);
+
+	if (iInfoGc)
+		{
+		iTitle=RWindow(iSession);
+		ASSERT_EQUALS_X(iTitle.Construct(*iInfoGroup, ++iWindowHandle), KErrNone);
+		iTitle.SetBackgroundColor(iCyan);
+		iTitle.SetExtent(winSize.iTl,winSize.Size());
+		iTitle.Activate();
+		
+		RepaintTitleWindowL();
+		iTitle.SetVisible(ETrue);
+	
+		winSize.Move(oneThird);
+		iCompare=RWindow(iSession);
+		ASSERT_EQUALS_X(iCompare.Construct(*iInfoGroup, ++iWindowHandle), KErrNone);
+		iCompare.SetBackgroundColor(COMPARE_BACKGROUND);
+		iCompare.SetExtent(winSize.iTl,winSize.Size());
+		iCompare.Activate();
+		iCompare.BeginRedraw();
+		ActivateWithWipe(iInfoGc,iCompare,COMPARE_BACKGROUND);
+	
+		TFontSpec fspec(KMonospaceTestFontTypefaceName,KMaxFontSize);
+		CFont *font=NULL;
+		ASSERT_EQUALS(iScreenDevice->GetNearestFontToDesignHeightInTwips(font,fspec),KErrNone);
+		iInfoGc->UseFont(font);
+		iInfoGc->DrawText(_L("Simulation"),winSize.Size(),winSize.Size().iHeight-5,iGc->ECenter);
+	
+		iInfoGc->Deactivate();
+		iCompare.EndRedraw();
+		iCompare.SetVisible(ETrue);
+		if (iScreenDevice!=iInfoScreenDevice)
+			{
+			winSize.Move(-oneThird);
+			}
+		else
+			{
+			winSize.Move(oneThird);
+			}
+		}
+	else
+		{
+		winSize=iScreenDevice->SizeInPixels();
+		}
+	
+	iTestPos=winSize;
+	iTestPointCentre=winSize.Center();
+	iCenteredFrontWinRect=winSize;
+	iCenteredFrontWinRect.Shrink(winSize.Size().iWidth/3,winSize.Size().iHeight/3);
+
+	}
+/**	Makes the compare window larger by covering the test window area as well.
+ * 	Copes with vertically aligned screens, but will be naughty if called multiple times!!!
+ *  @param aGoLarger	If set false, resets the size back.
+ **/
+void CWsDynamicResWinBase::LargerCompareWindow(TBool aGoLarger)
+	{
+	TPoint currPos=iCompare.AbsPosition();
+	TSize currSize=iCompare.Size();
+	if (currPos.iX<currPos.iY)
+		{
+		if (aGoLarger)
+			currSize.iHeight<<=1;
+		else
+			currSize.iHeight>>=1;
+		}
+	else
+		{
+		if (aGoLarger)
+			currSize.iWidth<<=1;
+		else
+			currSize.iWidth>>=1;
+		}
+	iCompare.SetSize(currSize);
+	}
+	
+
+/**	Puts a line of text on the LHS window.
+ *  Repaints the window. The line of text will also be shown in the log if the test fails.
+ *	@param	aDetail	The text to display
+ * 	@param	aIndex	The row number to display at
+ **/
+void CWsDynamicResWinBase::UpdateTitleWindowL(TRefByValue<const TDesC16> aDetail,TInt aIndex)
+	{
+	ASSERT(aIndex>=0 && aIndex<KMaxInfoLines);
+	iTestInfo[aIndex]=aDetail;
+
+	RepaintTitleWindowL();
+	
+	}
+/**	Activate the GC onto the Window.
+ *  In non-transparent mode it also performs a wipe background as the WServ system does not necessarily do this.
+ * 	@param	aGc		The GC to associate
+ * 	@param	aWin	The window to associate
+ * 	@param	aColor	The color to use as the wipe. Default is transparent, which means no wipe.
+ **/
+TBool	CWsDynamicResWinBase::ActivateWithWipe(CWindowGc* aGc,RWindow& aWin,TRgb aColor)
+	{
+	aGc->Activate(aWin);
+	aGc->SetBrushColor(aColor);
+	aGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
+	if (aColor!=TRgb(0,0) && !iTransparencyEnabled)	//presume that all redraw-stored windows will draw background
+		{
+		aGc->Clear();
+		return ETrue;	//window was cleared
+		}
+	return EFalse;	
+	}
+
+CWindowGc*	CWsDynamicResWinBase::GcForWindow(RWindow& aWin)
+	{
+	if (aWin.WsHandle()==NULL)
+		return NULL;	//can't activate uninitialised window.
+	CWindowGc* gc=iGc;
+	if (iGc!=iInfoGc)
+		if (&aWin==&iCompare || &aWin==&iTitle)
+			gc=iInfoGc;
+		else if (iInfoGroup && aWin.WindowGroupId()==iInfoGroup->WindowGroupId())
+			gc=iInfoGc;
+	return gc;
+	}
+/** Activates an appropriate predefined GC on the specified window and wipes the background if necessary. 
+ *  @param	aWin	The window to wipe
+ * 	@param	aColor	The colour to wipe with (if necessary)
+ * 	@return	the GC to use for drawing and deactivate at end. This may be NULL if the window is not "live"
+ **/
+CWindowGc*	CWsDynamicResWinBase::BeginActivateWithWipe(TBool aInvalidate,RWindow& aWin,TRgb aColor)
+	{
+	CWindowGc* gc=GcForWindow(aWin);
+	iSession.Flush();
+	if (gc==NULL)
+		return gc;	//can't activate uninitialised window.
+	if (aInvalidate)
+		aWin.Invalidate();
+	iSession.Flush();
+	aWin.BeginRedraw();
+	iSession.Flush();
+	ActivateWithWipe(gc,aWin,aColor);
+	return gc;	
+	}
+
+/** Activates an appropriate predefined GC on the specified window and wipes the background if necessary. 
+ *  @param	aWin	The window to wipe
+ * 	@param	aColor	The colour to wipe with (if necessary)
+ * 	@return	the GC to use for drawing and deactivate at end. This may be NULL if the window is not "live"
+ **/
+CWindowGc*	CWsDynamicResWinBase::BeginActivateWithWipe(TBool aInvalidate,TRect aRect,RWindow& aWin,TRgb aColor)
+	{
+	if (aWin.WsHandle()==NULL)
+		return NULL;	//can't activate uninitialised window.
+	if (aInvalidate)
+		aWin.Invalidate(aRect);
+	aWin.BeginRedraw(aRect);
+	CWindowGc* gc=iGc;
+	if (iGc!=iInfoGc)
+		if (&aWin==&iCompare || &aWin==&iTitle)
+			gc=iInfoGc;
+		else if (aWin.WindowGroupId()==iInfoGroup->WindowGroupId())
+			gc=iInfoGc;
+	ActivateWithWipe(gc,aWin,aColor);
+	return gc;	
+	}
+
+TBool		CWsDynamicResWinBase::InvalidateRegion(const TRegion& aRegion,RWindow& aWin)
+	{
+	if (aWin.WsHandle()==NULL)
+		return false;	//can't activate uninitialised window.
+	for (TInt ii = 0; ii < aRegion.Count(); ii++)
+		{
+		aWin.Invalidate(aRegion[ii]);
+		}
+	return true;
+	}
+
+CWindowGc*	CWsDynamicResWinBase::BeginActivateWithWipe(const TRegion& aRegion,RWindow& aWin,TRgb aColor)
+	{
+	if (!InvalidateRegion(aRegion,aWin))
+		return NULL;	//can't activate uninitialised window.
+
+	aWin.BeginRedraw();
+	CWindowGc* gc=iGc;
+	if (iGc!=iInfoGc)
+		if (&aWin==&iCompare || &aWin==&iTitle)
+			gc=iInfoGc;
+		else if (aWin.WindowGroupId()==iInfoGroup->WindowGroupId())
+			gc=iInfoGc;
+	ActivateWithWipe(gc,aWin,aColor);
+	return gc;	
+	}
+
+
+/**	Paints the LHS window with rows of text.
+ * 
+ **/
+void CWsDynamicResWinBase::RepaintTitleWindowL()
+	{
+	if (iTitle.WsHandle())
+		{
+		iTitle.Invalidate();
+	
+		iTitle.BeginRedraw();
+		ActivateWithWipe(iInfoGc,iTitle,TITLE_BACKGROUND);
+		iInfoGc->SetUnderlineStyle(EUnderlineOn);
+		TSize winSize=iTitle.Size();
+		TRect textRect(winSize);
+		textRect.iBr.iY/=4;
+		TFontSpec fspec(KMonospaceTestFontTypefaceName,KMaxFontSize);
+		CFont *font=NULL;
+		ASSERT_EQUALS(iInfoScreenDevice->GetNearestFontToDesignHeightInTwips(font,fspec),KErrNone);
+		iInfoGc->UseFont(font);
+		iInfoGc->DrawText(iTestName,textRect,textRect.iBr.iY/2,iGc->ECenter);
+		iInfoGc->SetUnderlineStyle(EUnderlineOff);
+		textRect.iTl.iY=textRect.iBr.iY;
+		TInt rowHeight=winSize.iHeight*3/(4*(KMaxInfoLines+1));
+		textRect.iBr.iY+=rowHeight;
+		for (TInt index=0;index<KMaxInfoLines;index++)
+			{
+			if (iTestInfo[index].Length())
+				iInfoGc->DrawText(iTestInfo[index],textRect,textRect.Size().iHeight*3/4,iInfoGc->ECenter);
+			textRect.Move(0,rowHeight);
+			}
+		iInfoGc->DiscardFont();
+		iInfoGc->Deactivate();
+		iTitle.EndRedraw();
+		iInfoScreenDevice->ReleaseFont(font);
+	
+		iSession.Flush();
+		iSession.Finish();
+		}
+	}
+
+/** Useful test culled from other GCE test classes.
+ * 	
+ * 
+ * 
+ **/
+TBool CWsDynamicResWinBase::DisplayHasAlpha() const
+	{
+	return (iDisplayMode == EColor16MA || iDisplayMode == EColor16MAP);
+	}
+/**	Test using an indipendent method that GCE version of WServ is running
+ *  This method can only be called after the testcase is started
+ * 
+ * 	@return	true if WServ version is GCE technology, false if legacy technology
+ **/
+TBool CWsDynamicResWinBase::GCEIsSupported() const
+	{
+	CFbsDrawDevice* screenDevice=NULL;
+	TDisplayMode displayMode=iScreenDevice->DisplayMode();
+	TRAPD(err, screenDevice = CFbsDrawDevice::NewScreenDeviceL(TGlobalSettings::Instance().iScreen, displayMode));
+	TBool rv=EFalse;
+	if(err == KErrNone)
+		{
+		TAny* p=NULL;
+		rv=(screenDevice->GetInterface(KSurfaceInterfaceID, p)==KErrNone);
+		delete screenDevice;
+		}
+	return rv;
+	}
+/**	Test using an indipendent method that GCE version of WServ is running
+ *  This method can be called at any time, even by external code, but creates temporary window session objects
+ * 
+ * 	@return	true if WServ version is GCE technology, false if legacy technology
+ **/
+TBool CWsDynamicResWinBase::GCEIsSupportedStatic()
+	{
+	CFbsDrawDevice* screenDevice=NULL;
+	RWsSession session;
+	if (session.Connect()!=KErrNone)
+		{
+		return EFalse;
+		}
+	TDisplayMode displayMode=ENone;
+		{CWsScreenDevice screen(session);
+		if (screen.Construct(TGlobalSettings::Instance().iScreen)!=KErrNone)
+			{
+			return EFalse;
+			}
+			displayMode=screen.DisplayMode();
+		}//screen destroyed
+		TRAPD(err, screenDevice = CFbsDrawDevice::NewScreenDeviceL(TGlobalSettings::Instance().iScreen, displayMode));
+		TBool rv=EFalse;
+		if(err == KErrNone)
+			{
+			TAny* p=NULL;
+			rv=(screenDevice->GetInterface(KSurfaceInterfaceID, p)==KErrNone);
+			delete screenDevice;
+			}
+	return rv;
+	}//session destroyed
+/**
+Use the full-screen background window to select a display mode that doesn't use
+alpha (anything other than EColor16MA or EColor16MAP). Record the mode for use
+in setting all other windows.
+@return ETrue if an appropriate mode was selected, EFalse otherwise.
+*/
+TBool CWsDynamicResWinBase::SelectChromaCompositionMode()
+	{
+	// Request EColor64K, but as long as the actual mode doesn't use alpha, it
+	// doesn't matter too much which one is used.
+	if (iInfoGc==iGc)
+		{
+		iDisplayMode = (TDisplayMode)iBackground.SetRequiredDisplayMode(EColor64K);
+		iSession.Flush();		// Force switching to the display mode.
+		}
+	return !DisplayHasAlpha();
+	}
+/**	Returns the colour used by WServ to paint holes in UI layer to reveal the GCE behind.
+ * 	The window should have a surface attached.
+ * 	If the method is called after the surface has been detached or the window was removed then 
+ * 	the previous recorded hole color is returned.
+ **/
+TRgb  CWsDynamicResWinBase::GceHoleColor( RWindowBase& aWin)const
+	{
+	if (aWin.WsHandle()==NULL)
+		{
+		return iLastGceHoleColor;
+		}
+	TRgb retVal=aWin.KeyColor();
+	if (retVal==TRgb(0,0))
+		{
+		return iLastGceHoleColor;
+		}
+	else
+		{
+		iLastGceHoleColor=retVal;
+		return retVal;
+		}
+	}
+
+
+/**
+Use the full-screen background window to select a display mode that can use
+alpha (either EColor16MA or EColor16MAP). Record the mode for use in setting all
+other windows.
+@return ETrue if an appropriate mode was selected, EFalse otherwise.
+*/
+TBool CWsDynamicResWinBase::SelectAlphaCompositionMode(TDisplayMode aMode)
+	{
+	// Request EColor16MA, but as long as the actual mode can use alpha, it
+	// doesn't matter too much which one is used.
+	if (iInfoGc==iGc)
+		{
+		iDisplayMode = (TDisplayMode)iBackground.SetRequiredDisplayMode(aMode);
+		iSession.Flush();		// Force switching to the display mode.
+		}
+	return DisplayHasAlpha();
+	}
+
+/**
+ * 	Interesting UI pattern used by other GCE tests.
+ * 
+ * 
+ **/
+void CWsDynamicResWinBase::DrawUIContent(RWindow& aWindow)
+	{
+	aWindow.BeginRedraw();
+	CWindowGc* gc=(&aWindow==&iCompare)?iInfoGc:iGc;
+	
+	gc->Activate(aWindow);
+
+	TBool hasAlpha = DisplayHasAlpha();
+
+	// Draw a red-green graduated box in the central portion of the window,
+	// with alpha if available.
+	TPoint start;
+	TPoint end;
+	TInt halfW = KSurfaceWidth / 2;
+	TInt quarterW = halfW / 2;
+	TInt halfH = KSurfaceHeight / 2;
+	TInt quarterH = halfH / 2;
+
+	// Set constant ordinals for non-alpha case.
+	start.iX = quarterW;
+	end.iX = quarterW + halfW;
+
+	for (TInt yy = 0; yy < halfH; yy++)
+		{
+		TInt yval = yy * 255 / (halfH - 1);
+		start.iY = yy + quarterH;
+		end.iY = start.iY;
+
+		if (hasAlpha)
+			{
+			for (TInt xx = 0; xx < halfW; xx++)
+				{
+				TInt xval = xx * 255 / (halfW - 1);
+				start.iX = xx + quarterW;
+				end.iX = start.iX + 1;
+				gc->SetPenColor(TRgb(yval, 255 - yval, 0, xval));
+				gc->DrawLine(start, end);
+				}
+			}
+		else
+			{
+			gc->SetPenColor(TRgb(yval, 255 - yval, 0));
+			gc->DrawLine(start, end);
+			}
+		}
+
+	gc->Deactivate();
+	aWindow.EndRedraw();
+	}
+
+/**
+ * 	Causes the given window to be redrawn.
+ * 	Doesn't draw anything except the background wipe, when the transparency manager hasn't
+ * 
+ **/
+void CWsDynamicResWinBase::DrawPlainUI(RWindow& aWindow,TBool aInvalidate,TRgb aWipeColor)
+	{
+	if (CWindowGc* gc=BeginActivateWithWipe(aInvalidate,aWindow,aWipeColor))
+		{
+		//actually does nothing!
+		gc->Deactivate();
+		aWindow.EndRedraw();
+		}
+	}
+/**
+ *  	Interesting UI pattern used by other GCE tests.
+ * 
+ * 
+ **/
+void CWsDynamicResWinBase::DrawCross(RWindow& aWindow, TRgb aColor, TInt aThickness)
+	{
+	aWindow.BeginRedraw();
+	CWindowGc* gc=(&aWindow==&iCompare)?iInfoGc:iGc;
+	gc->Activate(aWindow);
+
+	// Draw a red diagonal cross in the window.
+	gc->SetPenColor(aColor);
+	gc->SetPenSize(TSize(aThickness, aThickness));
+	gc->DrawLine(TPoint(0, 0), TPoint(KSurfaceWidth, KSurfaceHeight));
+	gc->DrawLine(TPoint(KSurfaceWidth, 0), TPoint(0, KSurfaceHeight));
+
+	gc->Deactivate();
+	aWindow.EndRedraw();
+	}
+
+/**
+ * 	Checks the RGB value
+ * 
+ * 
+ **/
+void CWsDynamicResWinBase::TestPixelL(TPoint aPt, TRgb aColor, TBool aMatch)
+	{
+	TRect screenArea(iScreenDevice->SizeInPixels());
+	if (aPt.iX < screenArea.iTl.iX)
+		{
+		aPt.iX = screenArea.iTl.iX;
+		}
+	else if (aPt.iX >= screenArea.iBr.iX)
+		{
+		aPt.iX = screenArea.iBr.iX - 1;
+		}
+	if (aPt.iY < screenArea.iTl.iY)
+		{
+		aPt.iY = screenArea.iTl.iY;
+		}
+	else if (aPt.iY >= screenArea.iBr.iY)
+		{
+		aPt.iY = screenArea.iBr.iY - 1;
+		}
+
+	TRgb pixel;
+	iScreenDevice->GetPixel(pixel, aPt);
+	if (aMatch)
+		{
+		ASSERT_EQUALS_X(pixel.Internal(), aColor.Internal());
+		}
+	else
+		{
+		ASSERT_NOT_EQUALS_X(pixel.Internal(), aColor.Internal());
+		}
+	}
+
+struct CountColour
+	{
+	TRgb	iColor;
+	TInt	iCount;
+	TBool operator  < (const CountColour& aRhs)const	
+		{	return iColor.Value()<aRhs.iColor.Value();	}
+	
+	CountColour(TRgb	aColor,TInt	aCount=0): 
+			iColor(aColor),iCount(aCount) {}
+	
+	CountColour(const CountColour& aRhs): 
+			iColor(aRhs.iColor),iCount(aRhs.iCount) {}
+	};
+
+void LogColorL(TRgb aPixel,RArray<CountColour>& aColors)
+	{
+	//I am sure one of the find methods would do this, but life is too short!
+	TInt existingIndex;
+	for (existingIndex=0;existingIndex<aColors.Count();existingIndex++)
+		if (aColors[existingIndex].iColor==aPixel)
+			break;
+	if (existingIndex==aColors.Count())
+		aColors.AppendL(CountColour(aPixel,1));
+	else
+		aColors[existingIndex].iCount++;
+	}
+
+/**
+ * Tests the outline of the given rectangle to verify that it has the expected inner and outer colors
+ * There may be a limited number of other colors present.
+ * If the given count of other colors is exceeded then false is returned
+ * If the majority of inner and outer edge pixels are not the given colors then returns false
+ * If the  colors are repeated on inside and outside then returns false
+ * If there are corners then the insides of the corners are also check for outside color
+ * Note that the right and bottom edge coordinates are outside the rectangle.
+ * Note that I am not performing any safety clipping at present. The rectangle must be on-screen!
+ * A negative value for corner size indicates that the window may or may not have corners that size.
+ * Only leaves if fatal memory condition!
+**/
+TBool CWsDynamicResWinBase::TestRectL(TRect aRect,TRgb aInnerColor,TInt aOtherInnerColors,TRgb aOuterColor,TInt aOtherOuterColors,TInt aExpectedCornerSize)
+	{
+	if (aRect.iTl.iX<=0 || aRect.iTl.iY<=0)
+		return ETrue;	//can't perform the test against the outside of the screen
+	//quantise the expectation based on the current mode.
+	switch (iScreenDevice->DisplayMode())
+	{
+	case EColor4K:
+		aInnerColor=aInnerColor.Color4K(aInnerColor.Color4K());
+		aOuterColor=aOuterColor.Color4K(aOuterColor.Color4K());
+	break;
+	case EColor64K:
+		aInnerColor=aInnerColor.Color64K(aInnerColor.Color64K());
+		aOuterColor=aOuterColor.Color64K(aOuterColor.Color64K());
+	break;
+	case EColor16M:
+	case EColor16MU:
+	case EColor16MA:
+	case EColor16MAP:
+		break;
+	default:
+		ASSERT_TRUE(!"Can't quantise color for this display mode!");
+	
+	}
+	RArray<CountColour> innerColors;
+	innerColors.AppendL(aInnerColor);
+	RArray<CountColour> outerColors;
+	outerColors.AppendL(aOuterColor);
+	TInt cornerSize=aExpectedCornerSize>=0?aExpectedCornerSize:-aExpectedCornerSize;
+	//Check outside first!
+	TRgb pixelVal;
+	for(TPoint pixelPos(aRect.iTl.iX-1,aRect.iTl.iY-1);pixelPos.iX<aRect.iBr.iX;pixelPos.iX++)
+		{
+		iScreenDevice->GetPixel(pixelVal, pixelPos);
+		LogColorL(pixelVal,outerColors);
+		}
+	for(TPoint pixelPos(aRect.iTl.iX,aRect.iBr.iY);pixelPos.iX<=aRect.iBr.iX;pixelPos.iX++)
+		{
+		iScreenDevice->GetPixel(pixelVal, pixelPos);
+		LogColorL(pixelVal,outerColors);
+		}
+	for(TPoint pixelPos(aRect.iTl.iX-1,aRect.iTl.iY);pixelPos.iY<=aRect.iBr.iY;pixelPos.iY++)
+		{
+		iScreenDevice->GetPixel(pixelVal, pixelPos);
+		LogColorL(pixelVal,outerColors);
+		}
+	for(TPoint pixelPos(aRect.iBr.iX,aRect.iTl.iY-1);pixelPos.iY<aRect.iBr.iY;pixelPos.iY++)
+		{
+		iScreenDevice->GetPixel(pixelVal, pixelPos);
+		LogColorL(pixelVal,outerColors);
+		}
+	TInt cornerStart=1;
+	if (cornerSize)
+		{
+		cornerStart=cornerSize;
+		if (aExpectedCornerSize>0)
+			{
+			iScreenDevice->GetPixel(pixelVal, aRect.iTl);
+			LogColorL(pixelVal,outerColors);
+			iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX,aRect.iBr.iY-1));
+			LogColorL(pixelVal,outerColors);
+			iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1,aRect.iTl.iY));
+			LogColorL(pixelVal,outerColors);
+			iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1,aRect.iBr.iY-1));
+			LogColorL(pixelVal,outerColors);
+			}
+		}
+	
+	//test inside edges (excluding 4 corner pixels - do them seperately)
+	for(TPoint pixelPos(aRect.iTl.iX+cornerStart,aRect.iTl.iY);pixelPos.iX<aRect.iBr.iX-cornerStart;pixelPos.iX++)
+		{
+		iScreenDevice->GetPixel(pixelVal, pixelPos);
+		LogColorL(pixelVal,innerColors);
+		}
+	for(TPoint pixelPos(aRect.iTl.iX+cornerStart,aRect.iBr.iY-1);pixelPos.iX<aRect.iBr.iX-cornerStart;pixelPos.iX++)
+		{
+		iScreenDevice->GetPixel(pixelVal, pixelPos);
+		LogColorL(pixelVal,innerColors);
+		}
+	for(TPoint pixelPos(aRect.iTl.iX,aRect.iTl.iY+cornerStart);pixelPos.iY<aRect.iBr.iY-cornerStart;pixelPos.iY++)
+		{
+		iScreenDevice->GetPixel(pixelVal, pixelPos);
+		LogColorL(pixelVal,innerColors);
+		}
+	for(TPoint pixelPos(aRect.iBr.iX-1,aRect.iTl.iY+cornerStart);pixelPos.iY<aRect.iBr.iY-cornerStart;pixelPos.iY++)
+		{
+		iScreenDevice->GetPixel(pixelVal, pixelPos);
+		LogColorL(pixelVal,innerColors);
+		}
+	//the 4 corner cells - not checking the whole corner area...
+	if (aExpectedCornerSize>=0)
+		{
+		iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX+cornerSize,aRect.iTl.iY+cornerSize));
+		LogColorL(pixelVal,innerColors);
+		iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iTl.iX+cornerSize,aRect.iBr.iY-1-cornerSize));
+		LogColorL(pixelVal,innerColors);
+		iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1-cornerSize,aRect.iBr.iY-1-cornerSize));
+		LogColorL(pixelVal,innerColors);
+		iScreenDevice->GetPixel(pixelVal, TPoint(aRect.iBr.iX-1-cornerSize,aRect.iTl.iY+cornerSize));
+		LogColorL(pixelVal,innerColors);
+		}
+	//OK... that has tested all the pixels, now check the result
+	if (innerColors.Count()>aOtherInnerColors+1)
+		return EFalse;
+	if (outerColors.Count()>aOtherOuterColors+1)
+		return EFalse;
+	for (TInt index=1;index<innerColors.Count();index++)
+		if (innerColors[0].iCount<innerColors[index].iCount)
+			{
+			return EFalse;
+			}
+	for (TInt index=1;index<outerColors.Count();index++)
+		if (outerColors[0].iCount<outerColors[index].iCount)
+			{
+			return EFalse;
+			}
+	for (TInt indexIn=1;indexIn<innerColors.Count();indexIn++)
+		for (TInt indexOut=0;indexOut<outerColors.Count();indexOut++)
+			if (innerColors[indexIn].iColor.Value()==outerColors[indexOut].iColor.Value())
+				{
+				return EFalse;
+				}
+	return ETrue;
+	}
+
+TRect CWsDynamicResWinBase::PentCellRect(const TRect& aFullRect,char aStartLetter,char aEndLetter)
+	{
+	if (aEndLetter==0)
+		aEndLetter=aStartLetter;
+	aStartLetter&=0x1f;
+	aEndLetter&=0x1f;
+	TInt startx=(aStartLetter-1)%5;
+	TInt starty=(aStartLetter-1)/5;
+	TInt endx=(aEndLetter-1)%5;
+	TInt endy=(aEndLetter-1)/5;
+	if (starty>endy)
+		{	//swap			//	s		e
+		starty-=endy;		//	s-e
+		endy+=starty;		//			s					
+		starty=endy-starty;	//	e
+		}
+	if (startx>endx)
+		{	//swap			//	s		e
+		startx-=endx;		//	s-e
+		endx+=startx;		//			s					
+		startx=endx-startx;	//	e
+		}
+	TSize fullSize=aFullRect.Size();
+	return TRect(	aFullRect.iTl.iX+fullSize.iWidth*startx/5,
+					aFullRect.iTl.iY+fullSize.iHeight*starty/5,
+					aFullRect.iTl.iX+fullSize.iWidth*(endx+1)/5,
+					aFullRect.iTl.iY+fullSize.iHeight*(endy+1)/5
+				);
+	}