201026_1
authorhgs
Fri, 24 Sep 2010 16:44:34 +0300
changeset 188 1b081cb0800b
parent 187 9f66f99ee56f
201026_1
graphicsdeviceinterface/bitgdi/tbit/TDefect2.cpp
graphicshwdrivers/surfacemgr/inc/surface_hints.h
graphicshwdrivers/surfacemgr/test/src/tsurfacemanager.cpp
graphicstest/graphicstestharness/group/bld.inf
graphicstest/graphicstestharness/rom/graphics_sirocco_ne_wsini.iby
graphicstest/graphicstestharness/rom/minigui_chassis_bats.oby
graphicstest/graphicstestharness/rom/minigui_naviengine_smp.oby
graphicstest/graphicstestharness/wsini/wsini_naviengine.ini
graphicstest/uibench/group/te_uibench.mmp
graphicstest/uibench/group/te_uibench_gce.mmp
graphicstest/uibench/scripts/te_uibench_gce.script
graphicstest/uibench/src/tgcesuiteserver.cpp
graphicstest/uibench/src/trenderorientation.cpp
graphicstest/uibench/src/trenderorientation.h
windowing/windowserver/SERVER/openwfc/panics.h
windowing/windowserver/SERVER/w32cmd.h
windowing/windowserver/bwins/WS322U.DEF
windowing/windowserver/bwins/ws32switchu.def
windowing/windowserver/debuglog/DECODER.CPP
windowing/windowserver/eabi/WS322U.DEF
windowing/windowserver/group/openwfc/WServ_nga.MMP
windowing/windowserver/group/openwfc/bld.inf
windowing/windowserver/group/twsthemeserverpropertydefine.mmp
windowing/windowserver/group/wservu_multiscreen.ini
windowing/windowserver/group/wservu_multiscreen_changetracking.ini
windowing/windowserver/inc/Graphics/wskeyrouter.h
windowing/windowserver/inc/W32STD.H
windowing/windowserver/inc/wspublishandsubscribedata.h
windowing/windowserver/nga/CLIENT/RWINDOW.CPP
windowing/windowserver/nga/CLIENT/RWS.CPP
windowing/windowserver/nga/SERVER/CAPKEY.CPP
windowing/windowserver/nga/SERVER/EVENT.CPP
windowing/windowserver/nga/SERVER/EVENT.H
windowing/windowserver/nga/SERVER/PRIKEY.CPP
windowing/windowserver/nga/SERVER/PRIKEY.H
windowing/windowserver/nga/SERVER/openwfc/CLIENT.CPP
windowing/windowserver/nga/SERVER/openwfc/CLIENT.H
windowing/windowserver/nga/SERVER/openwfc/GROUPWIN.CPP
windowing/windowserver/nga/SERVER/openwfc/WSTOP.CPP
windowing/windowserver/nga/SERVER/openwfc/server.h
windowing/windowserver/nga/SERVER/openwfc/wstop.h
windowing/windowserver/nga/SERVER/renderorientationtracker.cpp
windowing/windowserver/nga/SERVER/renderorientationtracker.h
windowing/windowserver/nga/SERVER/windowgroup.h
windowing/windowserver/nonnga/CLIENT/RWS.CPP
windowing/windowserver/test/TAutoServer/TAutoServer.cpp
windowing/windowserver/test/TAutoServer/openwfc/TAutoServer_nga.mmp
windowing/windowserver/test/TAutoServer/openwfc/TAutoServer_nonnga.mmp
windowing/windowserver/test/TAutoServer/tevent_captureapp.mmp
windowing/windowserver/test/scripts/wstest_config.cmd
windowing/windowserver/test/scripts/wstest_t_devicerotation_s0_nga.script
windowing/windowserver/test/tauto/TCapKey.CPP
windowing/windowserver/test/tauto/TCapKey.H
windowing/windowserver/test/tauto/TEVENT.H
windowing/windowserver/test/tauto/TEvent.CPP
windowing/windowserver/test/tauto/TOOM.CPP
windowing/windowserver/test/tauto/TOOM.H
windowing/windowserver/test/tauto/tdevicerotation.cpp
windowing/windowserver/test/tauto/tdevicerotation.h
windowing/windowserver/test/tauto/tevent_captureapp.cpp
windowing/windowserver/test/tauto/themeserverpropertydefine.cpp
windowing/windowserver/test/tauto/themeserverpropertydefine.h
windowing/windowserver/wins_switching/ws32_stubs.h
windowing/windowserverplugins/group/bld.inf
windowing/windowserverplugins/keyeventrouting/bwins/keyrouteru.def
windowing/windowserverplugins/keyeventrouting/eabi/keyrouteru.def
windowing/windowserverplugins/keyeventrouting/group/bld.inf
windowing/windowserverplugins/keyeventrouting/group/keyeventrouting.iby
windowing/windowserverplugins/keyeventrouting/group/keyeventrouting.mmp
windowing/windowserverplugins/keyeventrouting/group/keyeventrouting_test.iby
windowing/windowserverplugins/keyeventrouting/group/keyeventrouting_test.mmp
windowing/windowserverplugins/keyeventrouting/src/keyaliases.h
windowing/windowserverplugins/keyeventrouting/src/keyrouter.cpp
windowing/windowserverplugins/keyeventrouting/src/keyrouterimpl.h
windowing/windowserverplugins/openwfc/group/wserv_std_plugins.iby
--- a/graphicsdeviceinterface/bitgdi/tbit/TDefect2.cpp	Fri Sep 24 16:14:28 2010 +0300
+++ b/graphicsdeviceinterface/bitgdi/tbit/TDefect2.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2003-2010 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"
@@ -2125,13 +2125,18 @@
 	DeleteGraphicsContext();
 	DeleteScreenDevice();
 	TRAPD(err, iScrDev = CFbsScreenDevice::NewL(aScreenNo, aDisplayMode));
-	if(err == KErrNotSupported)
+	if ( !iScrDev )
 		{
+		TESTE( err == KErrNotSupported, err );
 		return err;
 		}
 	TEST(err == KErrNone);
 	TEST(iScrDev->ScreenNo() == aScreenNo);
 	err = iScrDev->CreateContext((CGraphicsContext*&)iGc);
+	if ( !iGc )
+		{
+		return err;
+		}
 	TEST(err == KErrNone);
 	iGc->SetUserDisplayMode(aDisplayMode);
 	iScrDev->ChangeScreenDevice(NULL);
--- a/graphicshwdrivers/surfacemgr/inc/surface_hints.h	Fri Sep 24 16:14:28 2010 +0300
+++ b/graphicshwdrivers/surfacemgr/inc/surface_hints.h	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2007-2010 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"
@@ -47,6 +47,12 @@
 */
 const TInt KSurfaceProtection = 0x3;
 
+/** Hint about the surface’s characteristics or properties,
+   For example if a surface can be persisted by the effects engine.
+   @see TSurfaceCharacteristics for possible values.
+*/
+const TInt KSurfaceCharacteristics = 0x4;
+
 
 /** Values used for the KSurfaceContent key */
 enum TSurfaceContent
@@ -120,6 +126,17 @@
     };
 
 
+/** Values used for the KSurfaceCharacteristics key. The values are bitmasks and can be combined.
+*/
+enum TSurfaceCharacteristics
+    {
+    /**
+    * Surface cannot be persisted once it has been closed by the creator
+    */
+    ENotPersistable = 1,
+    };
+
+
 class TSurfaceUpdate
     {
     /** Constructor.
@@ -185,7 +202,7 @@
     return ( iValue & 0x80000000 ) ? ETrue : EFalse;
     }
 
-}; //namespace surfaceHints
+} //namespace surfaceHints
 
 #endif //__SURFACE_HINTS_H__
 
--- a/graphicshwdrivers/surfacemgr/test/src/tsurfacemanager.cpp	Fri Sep 24 16:14:28 2010 +0300
+++ b/graphicshwdrivers/surfacemgr/test/src/tsurfacemanager.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2007-2010 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"
@@ -21,6 +21,7 @@
  @internalComponent - Internal Symbian test code
 */
 
+
 #include "tsurfacemanager.h"
 #include <e32base.h>
 #include <e32cons.h>
@@ -29,6 +30,9 @@
 #include <e32cmn.h>	  
 #include <hal.h>
 #include <e32def_private.h>
+#include <graphics/surface_hints.h>
+
+using namespace surfaceHints;
 
 const TInt KCountLimit = 10000;
 
@@ -3188,36 +3192,32 @@
 	
 	//Add HintPair1
 	RSurfaceManager::THintPair hintPair1;
-	hintPair1.iKey.iUid = 0x123257;
-	hintPair1.iValue = 300;
-	hintPair1.iMutable = ETrue;
+	hintPair1.Set(TUid::Uid(KSurfaceContent), EStillImage, ETrue);
 	TEST(KErrNone == iSurfaceManager.AddSurfaceHint(surfaceId, hintPair1));
 	
 	RSurfaceManager::THintPair hintPairCheck1;
-	hintPairCheck1.iKey.iUid = 0x123257;
+	hintPairCheck1.iKey.iUid = KSurfaceContent;
 	CheckHintPair(surfaceId, hintPairCheck1, hintPair1);
 	
 	//Add HintPair2
 	RSurfaceManager::THintPair hintPair2;
-	hintPair2.iKey.iUid = 0x123267;
-	hintPair2.iValue = 100;
+	hintPair2.iKey.iUid = KSurfaceProtection;
+	hintPair2.iValue = EAllowAnalog | EAllowDigital;
 	hintPair2.iMutable = EFalse;
 	TEST(KErrNone == iSurfaceManager.AddSurfaceHint(surfaceId, hintPair2));
 		
 	RSurfaceManager::THintPair hintPairCheck2;
-	hintPairCheck2.iKey.iUid = 0x123267;
+	hintPairCheck2.iKey.iUid = KSurfaceProtection;
 	CheckHintPair(surfaceId, hintPairCheck2, hintPair2);
 	CheckHintPair(surfaceId, hintPairCheck1, hintPair1);
 
 	//Add HintPair3
 	RSurfaceManager::THintPair hintPair3;
-	hintPair3.iKey.iUid = 0x123324;
-	hintPair3.iValue = 500;
-	hintPair3.iMutable = ETrue;
+	hintPair3.Set(TUid::Uid(KSurfaceCharacteristics), ENotPersistable, EFalse);
 	TEST(KErrNone == iSurfaceManager.AddSurfaceHint(surfaceId, hintPair3));
 	
 	RSurfaceManager::THintPair hintPairCheck3;
-	hintPairCheck3.iKey.iUid = 0x123324;
+	hintPairCheck3.iKey.iUid = KSurfaceCharacteristics;
 	CheckHintPair(surfaceId, hintPairCheck3, hintPair3);
 	CheckHintPair(surfaceId, hintPairCheck2, hintPair2);
 	CheckHintPair(surfaceId, hintPairCheck1, hintPair1);
@@ -4439,3 +4439,4 @@
     if(!aCondition)
         User::Leave(TEST_ERROR_CODE);   // leave with standard error code
     }
+
--- a/graphicstest/graphicstestharness/group/bld.inf	Fri Sep 24 16:14:28 2010 +0300
+++ b/graphicstest/graphicstestharness/group/bld.inf	Fri Sep 24 16:44:34 2010 +0300
@@ -39,11 +39,15 @@
 ../rom/graphics_imagecomparison.iby	/epoc32/rom/include/graphics_imagecomparison.iby  
 ../rom/graphics_tprofiler.iby  		/epoc32/rom/include/graphics_tprofiler.iby
 ../rom/graphics_simload.iby  		/epoc32/rom/include/graphics_simload.iby
+../rom/minigui_chassis_bats.oby  		/epoc32/rom/include/minigui_chassis_bats.oby
+../rom/minigui_naviengine_smp.oby  		/epoc32/rom/include/minigui_naviengine_smp.oby
 
 // WSINI
 ../rom/graphics_sirocco_wsini.hby  		/epoc32/rom/include/graphics_sirocco_wsini.hby
 ../rom/graphics_sirocco_wsini.iby  		/epoc32/rom/include/graphics_sirocco_wsini.iby
+../rom/graphics_sirocco_ne_wsini.iby  	/epoc32/rom/include/graphics_sirocco_ne_wsini.iby
 ../wsini/wsini_vasco.ini		/epoc32/data/test_wsini/wsini_vasco.ini
+../wsini/wsini_naviengine.ini		/epoc32/data/test_wsini/wsini_naviengine.ini
 
 // ONB batch files
 ../batch/retain_files.cmd z:\graphicstest\retain_files.cmd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/graphicstestharness/rom/graphics_sirocco_ne_wsini.iby	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,37 @@
+// Copyright (c) 2006-2010 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: Config for wsini.ini on NAVIENGINE
+//
+
+#ifndef __GRAPHICS_SIROCCO_NE_WSINI_IBY__
+#define __GRAPHICS_SIROCCO_NE_WSINI_IBY__
+
+#include <graphics_sirocco_wsini.hby>
+
+//#if WSERV_TEST_WSINI == WSERV_TEST_WSINI_ALF
+//	data=DATAZ_\talf\wsini_vasco_alf.ini \system\data\wsini.ini
+//#elif WSERV_TEST_WSINI == WSERV_TEST_WSINI_BITGDIRENDERSTAGE
+//	data=DATAZ_\wstest\tbitgdirenderstage\arm\wsini_bitgdirenderstage_vasco.ini \system\data\wsini.ini
+//#elif WSERV_TEST_WSINI == WSERV_TEST_WSINI_CSC
+//	data=DATAZ_\wstest\wsini_vasco_tcsc.ini \system\data\wsini.ini
+//#elif WSERV_TEST_WSINI == WSERV_TEST_WSINI_GENERICPLUGIN
+//	data=DATAZ_\wstest\genericplugin\wsini_vasco_genericplugin.ini \system\data\wsini.ini
+//#elif WSERV_TEST_WSINI == WSERV_TEST_WSINI_LAYERCOMPOSITION
+//	data=DATAZ_\tlayercomposition\wsini_vasco_layercomposition.ini \system\data\wsini.ini
+//#elif WSERV_TEST_WSINI == WSERV_TEST_WSINI_RATELIMITER
+//	data=DATAZ_\wstest\ratelimiter\wsini_vasco_ratelimiter.ini \system\data\wsini.ini
+//#else
+	data=EPOCROOT##epoc32\data\test_wsini\wsini_naviengine.ini \system\data\wsini.ini
+//#endif
+
+#endif	// __GRAPHICS_SIROCCO_NE_WSINI_IBY__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/graphicstestharness/rom/minigui_chassis_bats.oby	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,185 @@
+#ifndef __MINIGUI_OBY__
+#define __MINIGUI_OBY__
+
+// Copyright (c) 2007-2010 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:
+// This OBY File is used to build Mini-Gui ROM Images.
+// 
+// Use the following buildrom command line, or similar:
+//	buildrom -orombld.img -DUSE_SDIO_SD_MMC -DWITH_TVOUT -DUSE_24UBPP_DISPLAY_VARIANT_TV -D_INTERNAL_MMC -DUSE_DATA_PAGING h4hrp minigui pagedrom platsec
+// Note there is no need to specify -D_NAND2 
+
+define OBEYFILE minigui
+define ROMDATE	##TODAY##
+
+// We used to define _NAND2 on the commandline to buildrom.  However, it
+// does not make rombuild create a rofs image.  Instead it needs to be
+// specified in the oby file itself.
+//#define _NAND2
+
+// Undefine things in global System Include that stops the NCP rom from working.
+#undef USE_CUSTOM_MMC_PARTITION
+#undef SYMBIAN_EXCLUDE_SCDV
+#undef SYMBIAN_GRAPHICS_USE_GCE 
+#undef SYMBIAN_GRAPHICS_ADAPTATION
+#undef SGA_SW_NO_GRAPHICSRESOURCE 
+#undef SYMBIAN_EXCLUDE_KEYMAP  
+
+
+
+#define NO_METROTRK_APP // don't want metrotrk application
+#define HAS_ETHERNET	// include etherDrv, ether802, DHCP
+#define SYMBIAN_EXCLUDE_FAX
+#undef __IPSEC
+#define SYMBIAN_EXCLUDE_OBEX
+
+#ifdef SYMBIAN_SYSTEM_STATE_MANAGEMENT
+#define _SSMSTARTUPMODE 8	//for ssma boot up.
+#else
+#define _STARTUPMODE8		// for sysstart.iby
+#endif
+
+// Various workarounds to avoid dependencies on UIKON
+
+#define __TLS_IBY__			// exclude TLS
+#define __TLSPROVIDER_IBY__		// exclude TLSPROVIDER 
+#define __OBEXPROTOCOL_IBY__	// exclude obex.dll etc
+#define __WLANEAPMETHODS_IBY__	// exclude eap_tls.msy & friends
+// 
+
+#ifndef SYMBIAN_BASE_USE_GCE
+#define SYMBIAN_BASE_USE_GCE
+#endif
+#ifndef SYMBIAN_GRAPHICS_USE_GCE
+#define SYMBIAN_GRAPHICS_USE_GCE
+#endif
+#include <header.iby>				/* ROM header definitions */
+#include <base.iby>					/* The lowest-level of the operating system */
+
+#ifdef SYMBIAN_SYSTEM_STATE_MANAGEMENT
+
+#include <ssma.iby>			/*System State Management Architecture*/
+#include <ssplugins.iby>		/*System State Management Plugins*/
+
+//Include SSM optional components to enable teams to build a plain textshell rom (on the lines of DEF128306), 
+//following removal of h4_textshell_rom.oby.
+#include <amastart.iby>
+
+#include <shma.iby>
+#include <ssrefplugins.iby>
+#else
+#include <sysstart.iby>
+#include <sysstartconfig.iby>
+#endif // SYMBIAN_SYSTEM_STATE_MANAGEMENT
+
+#include <debug.iby>
+
+#include <eshell.iby>
+
+#include <centralrepository.iby>
+	file=ABI_DIR\BUILD_DIR\abclient.dll			sys\bin\abclient.dll
+
+#include <crypto.iby>
+
+#include <c32.iby>
+#include <ecuart.iby>
+#include <irda.iby>
+#include <stdlib.iby>
+#include <gdi.iby>
+#include <fntstore.iby>
+#include <fbserv.iby>
+#include <bitgdi.iby>
+#include <iculayoutengine.iby>
+#include <freetype.iby>
+#include <directgdi.iby>
+#include <wserv.iby>
+#include <econs_wserv.iby>
+//data=DATAZ_\wsini_minigui.ini	\system\data\wsini.ini
+
+#include <printers.iby>
+
+
+
+#include <traces.iby>
+
+#include <inetprotutil.iby>		/* needed for mmfcontrollerframework.dll */
+#include <sysagent.iby>
+#include <network.iby>	
+#include <dial.iby>		// needed by commsdat
+#include <etel.iby>
+#include <smsstack.iby>
+#include <etelmm.iby>
+#include <etelpckt.iby>
+#include <mmtsy.iby>
+#include <etelsat.iby>
+#include <sysawatcher.iby>
+#include <bafl.iby>
+#include <ecom.iby>
+#include <store.iby>
+#include <dbms.iby>
+#include <pwrcli.iby>
+#include <xml.iby>
+#include <ups.iby>
+#include <securitycommonutils.iby>
+
+/* Feature Management run-time */
+#ifdef SYMBIAN_FEATURE_MANAGER
+
+// Include both old and new components when Feature Manager enabled
+#include <featmgr.iby>
+#include <featreg.iby>
+
+#else 
+
+// Include only the original Feature Registry otherwise
+#include <featreg.iby>
+#ifndef ROM_FEATURE_MANAGEMENT
+/* Provide a default configuration file for the feature registry */ 
+data=EPOCROOT##epoc32\data\config\featreg_default.cfg    private\102744CA\featreg.cfg
+#endif
+#endif
+
+// The following section are all indirect dependencies arising from TEF testexecute depending
+// on apparc
+#include <mmcommon.iby>
+#include <ezlib.iby>
+file=ABI_DIR\BUILD_DIR\Http.dll                 System\Libs\Http.dll
+file=ABI_DIR\BUILD_DIR\httputils.dll			System\Libs\httputils.dll
+#include <asnpkcs.iby>
+#include <filetokens.iby>
+#include <imageconversion.iby>
+#include <ocsp.iby>
+#include <certman.iby>
+#include <swi.iby>
+#include <bluetooth.iby>
+#include <openenv.iby>
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+#include <scr.iby>
+#include <sts.iby>
+#include <sif.iby>
+#endif
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+#include <scr.iby>
+#include <sts.iby>
+#include <sif.iby>
+#endif
+#include <caf.iby>
+#include <apparc.iby>		/* Application architecture DLLs */
+#include <emime.iby>		/* Mime recognition */
+// This is the end of the indirect dependencies arising from TEF testexecute
+// depending on apparc
+
+#include <testexecute.iby>		// TEF
+
+#endif /* __MINIGUI_OBY__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/graphicstestharness/rom/minigui_naviengine_smp.oby	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,21 @@
+// Copyright (c) 2007-2010 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:
+// This OBY File is used to build Minigui NaviEngine SMP ROM Images.
+// 
+//
+
+#define SMP
+#include <naviengine.oby>
+#include <minigui_chassis_bats.oby>
+#include <platsec.oby>
Binary file graphicstest/graphicstestharness/wsini/wsini_naviengine.ini has changed
--- a/graphicstest/uibench/group/te_uibench.mmp	Fri Sep 24 16:14:28 2010 +0300
+++ b/graphicstest/uibench/group/te_uibench.mmp	Fri Sep 24 16:44:34 2010 +0300
@@ -43,6 +43,7 @@
 SOURCE	tspriteperf.cpp
 SOURCE	textendedbitmap.cpp
 SOURCE  tfbsglyphdata.cpp
+SOURCE	trenderorientation.cpp
 
 USERINCLUDE   ../src
 USERINCLUDE   ../../../fbs/fontandbitmapserver/inc
--- a/graphicstest/uibench/group/te_uibench_gce.mmp	Fri Sep 24 16:14:28 2010 +0300
+++ b/graphicstest/uibench/group/te_uibench_gce.mmp	Fri Sep 24 16:44:34 2010 +0300
@@ -31,6 +31,7 @@
 SOURCE	tsimpledrawing_directgdi.cpp
 SOURCE	teventhandlingperf.cpp
 SOURCE  tflipframerate.cpp
+SOURCE	trenderorientation.cpp
 
 USERINCLUDE   ../src
 
--- a/graphicstest/uibench/scripts/te_uibench_gce.script	Fri Sep 24 16:14:28 2010 +0300
+++ b/graphicstest/uibench/scripts/te_uibench_gce.script	Fri Sep 24 16:44:34 2010 +0300
@@ -64,6 +64,6 @@
 RUN_TEST_STEP 4000 te_uibench_gce tsimpledrawing_directgdi z:\uibench\te_uibench_gce.ini
 RUN_TEST_STEP 1000 te_uibench_gce teventhandlingperf z:\uibench\te_uibench_gce.ini
 RUN_TEST_STEP 20000 te_uibench_gce tflipframerate z:\uibench\te_uibench_gce.ini
-
+RUN_TEST_STEP 4000 te_uibench_gce trenderoriention z:\uibench\te_uibench_gce.ini
 
 PRINT Complete_te_uibench_gce_Tests
--- a/graphicstest/uibench/src/tgcesuiteserver.cpp	Fri Sep 24 16:14:28 2010 +0300
+++ b/graphicstest/uibench/src/tgcesuiteserver.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -26,6 +26,7 @@
 #include "tdirectgdiperf.h"
 #include "teventhandlingperf.h"
 #include "tflipframerate.h"
+#include "trenderorientation.h"
 
 /**
 Same code for Secure and non-secure variants
@@ -102,6 +103,7 @@
 CTestStep* CGceSuiteServer::CreateTestStep(const TDesC& aStepName)
 	{
 	CTestStep* testStep = NULL;
+	
 	if(aStepName == KTGraphicsResource)
 		testStep = new CTGraphicsResource();
 	else if(aStepName == KTBitBltPerfDirectGdi)
@@ -114,5 +116,8 @@
 		testStep = new CTEventHandlingPerf();
 	else if(aStepName == KTFlipFramerate)
 	    testStep = new CTFlipFramerate();
+	else if(aStepName == KTRenderOrientation)
+	    testStep = new CTRenderOrientation;
+	
 	return testStep;
 	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/uibench/src/trenderorientation.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,269 @@
+// Copyright (c) 2010 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
+ @test
+ @internalComponent - Internal Nokia test code 
+*/
+
+#include <w32std.h>
+
+#include <wspublishandsubscribedata.h>
+#include "trenderorientation.h"
+
+const TInt KPublishTimeout  = 1000000;  // 1 second in microseconds
+const TInt KNumIterations   = 20;
+
+// Values for the device orientation that we receive via P&S from the Theme Server
+// Must match those in renderorientationtracker.h, and, obviously, those used by the real theme server 
+const TUid  KThemeOrientationCategory   = {0x20022E82}; // == KHbPsHardwareCoarseOrientationCategoryUid 
+const TUint KThemeOrientationKey        = 0x4F726965; // == KHbPsHardwareCoarseOrientationKey 
+
+void CWindowStuff::ConstructL()
+    {
+    User::LeaveIfError(iWs.Connect());
+    iWs.SetAutoFlush(ETrue);
+    
+    iWindowGroup = RWindowGroup(iWs);
+    User::LeaveIfError(iWindowGroup.Construct(reinterpret_cast<TUint32>(&iWindowGroup)));
+    
+    iChildWindow = RWindow(iWs);
+    User::LeaveIfError(iChildWindow.Construct(iWindowGroup, reinterpret_cast<TUint32>(&iChildWindow)));
+    }
+
+CWindowStuff::~CWindowStuff()
+    {
+    Destroy();
+    }
+
+void CWindowStuff::Destroy()
+    {
+    iChildWindow.Close();
+    iWindowGroup.Close();
+    iWs.Close();    
+    }
+
+CTRenderOrientation::CTRenderOrientation()
+    {
+    // check that these two enums are aligned
+    __ASSERT_COMPILE(EDisplayOrientationAuto == ENumWindowThings);
+    
+    SetTestStepName(KTRenderOrientation);
+    }
+
+CTRenderOrientation::~CTRenderOrientation()
+    {
+    }
+
+TRenderOrientation CTRenderOrientation::GetRenderOrientationL()
+    {    
+    return GetOrientationL(iWsRenderOrientationProperty);    
+    }
+
+TRenderOrientation CTRenderOrientation::GetThemeOrientationL()
+    {    
+    return GetOrientationL(iThemeOrientationProperty);    
+    }
+
+TRenderOrientation CTRenderOrientation::GetOrientationL(RProperty& aProperty)
+    {
+    TInt orientation=EDisplayOrientationNormal;
+    User::LeaveIfError(aProperty.Get(orientation));
+    
+    TESTL(orientation >= EDisplayOrientationNormal);
+    TESTL(orientation < EDisplayOrientationAuto);    
+    
+    return static_cast<TRenderOrientation>(orientation);    
+    }
+
+void CTRenderOrientation::TestOrientationChangeL(const TDesC& aStepName, TTestPhase aTestPhase)
+    {
+    SetTestStepID(aStepName);
+    
+    if(EThemeOrientationChange == aTestPhase)
+        {               
+        TESTL(EDisplayOrientationNormal == GetThemeOrientationL());
+        iWindowStuff[EFirstWindowThing].Session().IndicateAppOrientation(EDisplayOrientationAuto);        
+        }
+    
+    TInt renderOrientation = GetRenderOrientationL();
+    
+    // For consistancy, check that we are starting from the same orientation
+    TESTL(EDisplayOrientationNormal == renderOrientation);    
+    
+    // Set-up the timer
+    iProfiler->InitResults();
+    iTimingsTaken = 0;    
+    
+    // repeat numerous times to get a decent average
+    for(TInt iterations=0; iterations < KNumIterations; ++iterations)
+        {
+        renderOrientation = GetRenderOrientationL();
+        // For consistancy, check that we are starting from the same orientation
+        TESTL(EDisplayOrientationNormal == renderOrientation);           
+        
+        // loop through the orientations, ending up changing back to normal
+        for(++renderOrientation; renderOrientation <= EDisplayOrientationAuto; ++renderOrientation)
+            {
+            // % can be slow, do it outside of the timing
+            TRenderOrientation testOrientation = static_cast<TRenderOrientation>(renderOrientation%EDisplayOrientationAuto);
+            
+            iWsRenderOrientationProperty.Subscribe(iRenderOrientationStatus);            
+            // start the timeout timer
+            iTimeoutTimer.After(iTimeoutStatus, KPublishTimeout);
+            // start the results timer
+            iProfiler->StartTimer();
+            
+            switch(aTestPhase)
+                {
+                case EIndicatedOrientationChange:
+                    // Do the indicated orientation Change
+                    iWindowStuff[EFirstWindowThing].Session().IndicateAppOrientation(testOrientation);
+                    break;
+                    
+                case EWindowOrdinalChange:
+                    // move the relevant window group to the front
+                    // N.B. this will go wrong if the number of orientations and windows are not equal
+                    iWindowStuff[testOrientation].WindowGroup().SetOrdinalPosition(0);
+                    break;
+                    
+                case EThemeOrientationChange:
+                    // Needs the focus window to be in auto mode
+                    iThemeOrientationProperty.Set(testOrientation);
+                    break;
+                    
+                default:
+                    TESTL(EFalse);
+                }
+        
+            // Wait for the update to have been published ( or time out while waiting )
+            User::WaitForRequest(iRenderOrientationStatus, iTimeoutStatus);
+            
+            iProfiler->MarkResultSetL();
+            ++iTimingsTaken;
+            
+            if(KErrNone != iRenderOrientationStatus.Int())
+                {
+                // timed out
+                iWsRenderOrientationProperty.Cancel();                
+                TESTL(EFalse);
+                }
+            else
+                {
+                // Check that it is actually the expected orientation
+                TESTL(GetRenderOrientationL() == testOrientation);
+                }
+
+            if(KRequestPending == iTimeoutStatus.Int())
+                {
+                // as expected, so cancel the timeout timer
+                iTimeoutTimer.Cancel();
+                }
+            else
+                {
+                // timed out
+                TESTL(EFalse);
+                }
+            }
+        }    
+    
+    // wrap it up    
+    iProfiler->ResultsAnalysis(KTRenderOrientation,KErrNotFound,ENone,ENone,iTimingsTaken);
+    }
+
+TVerdict CTRenderOrientation::doTestStepL()
+    {     
+    INFO_PRINTF1(_L("Testing: Indicated Orientation Change"));
+    TestOrientationChangeL(_L("GRAPHICS-UI-BENCH-0xxx1"), EIndicatedOrientationChange);
+    
+    INFO_PRINTF1(_L("Testing: Window Ordinal Position Change"));
+    TestOrientationChangeL(_L("GRAPHICS-UI-BENCH-0xxx2"), EWindowOrdinalChange);
+    
+    INFO_PRINTF1(_L("Testing: Theme Orientation Change"));
+    TestOrientationChangeL(_L("GRAPHICS-UI-BENCH-0xxx3"), EThemeOrientationChange);
+    
+    return TestStepResult();    
+    }
+
+_LIT(KThemeServerPropertyDefine, "twsthemeserverpropertydefine.exe");
+_LIT(KThemeServerPropertyDefineCmdDefine, "define");
+_LIT(KThemeServerPropertyDefineCmdDelete, "delete");   
+   
+void CTRenderOrientation::ThemeServerProperty(const TDesC& aCmd)
+    {
+    /* This Process called with the argument KThemeServerPropertyDefineCmdDelete, deletes 
+       the theme server RProperty. This is because an RProperty can only be defined and 
+       deleted from within a process with the same UID3 as the RProperty catogory you are 
+       trying to define/delete.*/
+    RProcess themeServerPropertyDefine;
+    TInt err = themeServerPropertyDefine.Create(KThemeServerPropertyDefine, aCmd);
+    if (KErrNone != err)
+        {
+        _LIT(KLog, "themeServerPropertyDefine.Create() failed with error: %d");
+        INFO_PRINTF2(KLog, err);
+        TEST(EFalse);        
+        }
+    
+    //wait for themeServerPropertyDefine process to terminate
+    TRequestStatus themeServerPropertyDefineLogonStatus;
+    themeServerPropertyDefine.Logon(themeServerPropertyDefineLogonStatus);
+    themeServerPropertyDefine.Resume();
+    User::WaitForRequest(themeServerPropertyDefineLogonStatus);
+    if (themeServerPropertyDefineLogonStatus != KErrNone)
+        {
+        _LIT(KLog, "themeServerPropertyDefine.Logon() failed with error: %d");
+        INFO_PRINTF2(KLog, themeServerPropertyDefineLogonStatus);
+        TEST(EFalse);        
+        }
+    themeServerPropertyDefine.Close();    
+    }
+
+TVerdict CTRenderOrientation::doTestStepPreambleL()
+    {
+    // Create in reverse order so that windowThing 0 is at the front
+    for(TInt windowThing = ENumWindowThings - 1; windowThing >= 0 ; --windowThing)
+        {
+        iWindowStuff[windowThing].ConstructL();
+        TRenderOrientation orientation = static_cast<TRenderOrientation>(windowThing%EDisplayOrientationAuto);
+        iWindowStuff[windowThing].Session().IndicateAppOrientation(orientation);
+        iWindowStuff[windowThing].WindowGroup().SetOrdinalPosition(0);
+        }
+    
+    User::LeaveIfError(iWsRenderOrientationProperty.Attach(KRenderOrientationCategory, KRenderOrientationKey));
+    
+    ThemeServerProperty(KThemeServerPropertyDefineCmdDefine);
+    User::LeaveIfError(iThemeOrientationProperty.Attach(KThemeOrientationCategory, KThemeOrientationKey));
+    
+    User::LeaveIfError(iTimeoutTimer.CreateLocal());
+    
+    return CTe_graphicsperformanceSuiteStepBase::doTestStepPreambleL();
+    }
+
+TVerdict CTRenderOrientation::doTestStepPostambleL()
+    {
+    iTimeoutTimer.Close();
+    
+    iThemeOrientationProperty.Close();
+    ThemeServerProperty(KThemeServerPropertyDefineCmdDelete);    
+    iWsRenderOrientationProperty.Close();
+    
+    for(TInt windowThing = 0; windowThing < ENumWindowThings; ++windowThing)
+        {
+        iWindowStuff[windowThing].Destroy();
+        }
+    
+    return CTe_graphicsperformanceSuiteStepBase::doTestStepPostambleL();
+    }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/uibench/src/trenderorientation.h	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,99 @@
+// Copyright (c) 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
+ @test
+ @internalComponent - Internal Symbian test code 
+*/
+
+#ifndef TRENDERORIENTATION_H
+#define TRENDERORIENTATION_H
+
+#include <e32property.h>
+#include "te_graphicsperformanceSuiteStepBase.h"
+
+class CWindowStuff : public CBase
+    {
+public:
+    ~CWindowStuff();
+    void ConstructL();
+    void Destroy();
+
+    inline RWsSession&     Session()
+        {return iWs;};
+    inline RWindowGroup&   WindowGroup()
+        {return iWindowGroup;};
+
+private:
+    RWsSession      iWs;
+    RWindowGroup    iWindowGroup;
+    RWindow         iChildWindow;    
+    };
+
+class CTRenderOrientation : public CTe_graphicsperformanceSuiteStepBase
+    {
+public:
+    CTRenderOrientation();
+    ~CTRenderOrientation();
+
+    // From CTestStep
+    virtual TVerdict doTestStepPreambleL();
+    virtual TVerdict doTestStepPostambleL();
+    
+    virtual TVerdict doTestStepL();
+
+private:
+    enum TWindowThing
+        {
+        // One per orientation
+        EFirstWindowThing,
+        ESecondWindowThing,
+        EThirdWindowThing,
+        EFourthWindowThing,
+        
+        ENumWindowThings
+        };
+    
+    enum TTestPhase
+        {
+        EIndicatedOrientationChange,
+        EWindowOrdinalChange,
+        EThemeOrientationChange,
+        
+        ENumTestPhases
+        };    
+    
+    void TestOrientationChangeL(const TDesC& aStepName, TTestPhase aTestPhase);
+    
+    TRenderOrientation  GetRenderOrientationL();
+    TRenderOrientation  GetThemeOrientationL();
+    TRenderOrientation  GetOrientationL(RProperty& aProperty);
+    void                ThemeServerProperty(const TDesC& aCmd);
+    
+private:    
+    CWindowStuff    iWindowStuff[ENumWindowThings];
+    RProperty       iWsRenderOrientationProperty;
+    RProperty       iThemeOrientationProperty;
+    
+    RTimer          iTimeoutTimer;
+    TRequestStatus  iTimeoutStatus;
+    TRequestStatus  iRenderOrientationStatus;
+    TInt            iTimingsTaken;
+    };
+
+_LIT(KTRenderOrientation,"trenderorientation");
+
+#endif /* TRENDERORIENTATION_H */
--- a/windowing/windowserver/SERVER/openwfc/panics.h	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/SERVER/openwfc/panics.h	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2003-2010 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"
@@ -162,6 +162,10 @@
 	EWsPanicInvalidRotation = 127,			//Invalid rotation used
 	EWsPanicInvalidPointerOffset = 128,      //The pointer offset value in wsini.ini is invalid.
 	EWsPanicArrayInsertFailed = 129,	//Array insert failed.           
+	EWsPanicAccessBeyondCommandBuf = 130,	//Access beyond wserv command buffer
+	EWsPanicKeyEventRouterBadResult = 131,		// Invalid result code from key event routing plug-in
+	EWsPanicKeyEventRouterBadWindowGroup = 132,	// Invalid destination window group from key event routing plug-in
+	EWsPanicKeyEventRouterLeave = 133,			// Invalid leave from Key event routing plug-in
 	};
 
 void Panic(TWservPanic aPanic);
--- a/windowing/windowserver/SERVER/w32cmd.h	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/SERVER/w32cmd.h	Fri Sep 24 16:44:34 2010 +0300
@@ -266,6 +266,7 @@
 	EWsClOpUnregisterAllTFXEffect,
 	EWsClOpOverrideEffectBuf,
 	EWsClOpOverrideEffectIPC,
+	EWsClOpIndicateAppOrientation,
 	EWsClOpLastEnumValue //Keep this at the end - used by test code
 	};
 	
@@ -1059,6 +1060,7 @@
 	const TWsClCmdRegisterEffect* RegisterEffect;
 	const TWsClCmdUnRegisterEffect* UnRegisterEffect; 
 	const TWsClCmdOverrideEffect* OverrideEffect;
+	const TRenderOrientation* Orientation;
 	};
 
 // Window command structures
@@ -2132,6 +2134,7 @@
 	// Under WINS character code is passed in as HIWORD of the scan code,
 	// and will need to be removed in some situations
 	#define __REMOVE_WINS_CHARCODE &0x0000FFFF
+	#define __WINS_CHARCODE(c)	((c) & 0xFFFF0000)
 #else
 	#define __REMOVE_WINS_CHARCODE
 #endif
--- a/windowing/windowserver/bwins/WS322U.DEF	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/bwins/WS322U.DEF	Fri Sep 24 16:44:34 2010 +0300
@@ -585,5 +585,5 @@
 	?OverrideEffects@RWsSession@@QAEXHHABV?$TBuf@$0BAA@@@00V?$TBitFlagsT@K@@@Z @ 584 NONAME ; void RWsSession::OverrideEffects(int, int, class TBuf<256> const &, class TBuf<256> const &, class TBuf<256> const &, class TBitFlagsT<unsigned long>)
 	?UnregisterEffect@RWsSession@@QAEXHHI@Z @ 585 NONAME ; void RWsSession::UnregisterEffect(int, int, unsigned int)
 	?UnregisterAllEffects@RWsSession@@QAEXXZ @ 586 NONAME ; void RWsSession::UnregisterAllEffects(void)
+	?IndicateAppOrientation@RWsSession@@QAEXW4TRenderOrientation@@@Z @ 587 NONAME ; void RWsSession::IndicateAppOrientation(enum TRenderOrientation)
 
-
--- a/windowing/windowserver/bwins/ws32switchu.def	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/bwins/ws32switchu.def	Fri Sep 24 16:44:34 2010 +0300
@@ -427,8 +427,8 @@
 	call_vector_426 @ 426 NONAME ; void RBlankWindow::SetColor(void)
 	call_vector_427 @ 427 NONAME ; int RWsSession::SetClientCursorMode(enum TPointerCursorMode)
 	call_vector_428 @ 428 NONAME ; class TRect RDrawableWindow::GetDrawRect(void) const
-	call_vector_429 @ 429 NONAME 
-	call_vector_430 @ 430 NONAME 
+	call_vector_429 @ 429 NONAME
+	call_vector_430 @ 430 NONAME
 	call_vector_431 @ 431 NONAME ; void CWindowGc::Reserved_CWindowGc_3(void)
 	call_vector_432 @ 432 NONAME ; void CWindowGc::Reserved_CWindowGc_4(void)
 	call_vector_433 @ 433 NONAME ; void CWindowGc::Reserved_CWindowGc_5(void)
@@ -512,20 +512,20 @@
 	call_vector_511 @ 511 NONAME ; int RWsSession::DebugInfo(int, int) const
 	call_vector_512 @ 512 NONAME ; unsigned long RWindowTreeNode::ClientHandle(void) const
 	call_vector_513 @ 513 NONAME ; int RWindowBase::SetBackgroundSurface(class TSurfaceId const &)
-	call_vector_514 @ 514 NONAME 
+	call_vector_514 @ 514 NONAME
 	call_vector_515 @ 515 NONAME ; class TRgb RWindowBase::KeyColor(void) const
-	call_vector_516 @ 516 NONAME 
-	call_vector_517 @ 517 NONAME 
-	call_vector_518 @ 518 NONAME 
-	call_vector_519 @ 519 NONAME 
-	call_vector_520 @ 520 NONAME 
+	call_vector_516 @ 516 NONAME
+	call_vector_517 @ 517 NONAME
+	call_vector_518 @ 518 NONAME
+	call_vector_519 @ 519 NONAME
+	call_vector_520 @ 520 NONAME
 	call_vector_521 @ 521 NONAME ; int RWindowBase::GetBackgroundSurface(class TSurfaceConfiguration &) const
-	call_vector_522 @ 522 NONAME 
+	call_vector_522 @ 522 NONAME
 	call_vector_523 @ 523 NONAME ; int RWsSession::PreferredSurfaceConfigurationSize(void) const
 	call_vector_524 @ 524 NONAME ; int RWsSession::RegisterSurface(int, class TSurfaceId const &)
-	call_vector_525 @ 525 NONAME 
+	call_vector_525 @ 525 NONAME
 	call_vector_526 @ 526 NONAME ; void RWindowBase::RemoveBackgroundSurface(int)
-	call_vector_527 @ 527 NONAME 
+	call_vector_527 @ 527 NONAME
 	call_vector_528 @ 528 NONAME ; int RWindowBase::SetBackgroundSurface(class TSurfaceConfiguration const &, int)
 	call_vector_529 @ 529 NONAME ; void RWsSession::UnregisterSurface(int, class TSurfaceId const &)
 	call_vector_530 @ 530 NONAME ; void RWindow::ClearRedrawStore(void)
@@ -585,4 +585,5 @@
 	call_vector_584 @ 584 NONAME ; void RWsSession::OverrideEffects(int, int, class TBuf<256> const &, class TBuf<256> const &, class TBuf<256> const &, class TBitFlagsT<unsigned long>)
 	call_vector_585 @ 585 NONAME ; void RWsSession::UnregisterEffect(int, int, unsigned int)
 	call_vector_586 @ 586 NONAME ; void RWsSession::UnregisterAllEffects(void)
+	call_vector_587 @ 587 NONAME ; void RWsSession::IndicateAppOrientation(enum TRenderOrientation)
 
--- a/windowing/windowserver/debuglog/DECODER.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/debuglog/DECODER.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -834,7 +834,13 @@
 		_LIT(LogGetExitHighPressureThreshold,"EWsClOpGetExitHighPressureThreshold()");
 		aText.AppendFormat(LogGetExitHighPressureThreshold);		
 		}
-		break;	
+		break;
+	case EWsClOpIndicateAppOrientation:
+	    {
+        _LIT(LogIndicateAppOrientation,"EWsClOpIndicateAppOrientation(%d)");
+        aText.AppendFormat(LogIndicateAppOrientation, *pData.Orientation);       	    
+	    }
+	    break;
 	case EWsClOpLastEnumValue:
 		{		
 		_LIT(LogLastEnumValue,"EWsClOpLastEnumValue enum");
--- a/windowing/windowserver/eabi/WS322U.DEF	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/eabi/WS322U.DEF	Fri Sep 24 16:44:34 2010 +0300
@@ -659,5 +659,5 @@
 	_ZN10RWsSession16UnregisterEffectEiij @ 658 NONAME
 	_ZN10RWsSession20UnregisterAllEffectsEv @ 659 NONAME
 	_ZN11RWindowBase15OverrideEffectsEiRK4TBufILi256EES3_S3_10TBitFlagsTImE @ 660 NONAME
+	_ZN10RWsSession22IndicateAppOrientationE18TRenderOrientation @ 661 NONAME
 
-
--- a/windowing/windowserver/group/openwfc/WServ_nga.MMP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/group/openwfc/WServ_nga.MMP	Fri Sep 24 16:44:34 2010 +0300
@@ -74,6 +74,7 @@
 SOURCE            drawresource.cpp
 SOURCE            devicemap.cpp
 SOURCE            wsdisplaychangeao.cpp
+SOURCE            renderorientationtracker.cpp
 
 SOURCEPATH        ../../nga/SERVER/openwfc
 
--- a/windowing/windowserver/group/openwfc/bld.inf	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/group/openwfc/bld.inf	Fri Sep 24 16:44:34 2010 +0300
@@ -78,6 +78,7 @@
 ../../inc/Graphics/wsdisplaypolicy.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/wsdisplaypolicy.h)
 ../../inc/Graphics/openwfc/wselement.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/wselement.h)
 ../../inc/Graphics/openwfc/wsscene.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/wsscene.h)
+../../inc/Graphics/wskeyrouter.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/wskeyrouter.h)
 ../../inc/Graphics/wscontentreadyforcomposition.h SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/wscontentreadyforcomposition.h)
 
 //RemoteGc exports for partners
@@ -201,6 +202,7 @@
 #ifdef SYMBIAN_BUILD_GCE
 ../../group/AUTODLL_nga.MMP support
 ../../test/TAutoServer/openwfc/TAutoServer_nga.mmp
+../../test/TAutoServer/tevent_captureapp.mmp
 #endif
 
 #ifdef WINS
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/group/twsthemeserverpropertydefine.mmp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,33 @@
+// Copyright (c) 2010 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:
+// This .exe is to define an RProperty for simulating the Theme Server.
+// It needs to have the same UID3 as the theme server.
+//
+
+TARGET			twsthemeserverpropertydefine.exe
+CAPABILITY 		WriteDeviceData ReadDeviceData
+TARGETTYPE		EXE
+//The UID3 value should be the same as the actual Theme Server UID3
+UID		0x00000000 0x20022E82 
+VENDORID 0x70000001
+
+SOURCEPATH		../test/tauto
+SOURCE			themeserverpropertydefine.cpp
+
+USERINCLUDE		../inc ../test/tauto
+OS_LAYER_SYSTEMINCLUDE
+
+LIBRARY			euser.lib ws32.lib bafl.lib
+
+SMPSAFE
\ No newline at end of file
Binary file windowing/windowserver/group/wservu_multiscreen.ini has changed
Binary file windowing/windowserver/group/wservu_multiscreen_changetracking.ini has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/inc/Graphics/wskeyrouter.h	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,216 @@
+// Copyright (c) 2010 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:
+// Key Event Routing Plug-in API
+
+/**
+@file
+@publishedPartner
+@prototype
+*/
+
+#ifndef WSKEYROUTER_H
+#define WSKEYROUTER_H
+
+#include <e32base.h>
+#include <w32std.h>
+
+/**
+Interface Uid
+*/
+const TUid KKeyRouterPluginUid = { 0x102872e1 };
+
+/**
+Key Capture Type
+*/
+enum TKeyCaptureType
+	{
+	ECaptureTypeKey = 0,
+	ECaptureTypeLongKey = 1,
+	ECaptureTypeKeyUpDown = 2
+	};
+
+/**
+Key Capture Request
+*/
+struct TKeyCaptureRequest
+	{
+	/** Capture type */
+	TKeyCaptureType	iType;
+
+	/** Keycode or scancode to be captured */
+	TUint			iInputCode;
+
+	/** Output keycode or scancode. When iInputCode is captured, RouteKey()
+		places iOutputCode in TKeyEventRouterOutput.iKeyEvent */
+	TUint			iOutputCode;
+
+	/** Bitmask of modifier keys of interest. Key events are captured only
+		when the modifier keys specified by iModifierMask are in the states
+		specified by iModifiers */
+	TUint			iModifierMask;
+
+	/** Bitmask of modifier key states */
+	TUint			iModifiers;
+
+	/** Opaque handle for this request */
+	TAny*			iHandle;
+
+	/** Opaque handle to window group through which request was made */
+	TAny*			iWindowGroup;
+
+	/** Identifier of the window group through which request was made */
+	TInt			iWindowGroupId;
+
+	/** UID of application that made the capture request */
+	TUid			iAppUid;
+
+	/** Capture priority for this request. If more than one window group has
+		requested capture for the same key event, the one with the highest
+		priority will capture it (unless overridden by application specific
+		rules). */
+	TInt			iPriority;
+
+	/** Reserved for future use */
+	TInt			iReserved[2];
+	};
+
+/**
+Input parameters for RouteKey()
+*/
+struct TKeyEventRouterInput
+	{
+	inline TKeyEventRouterInput(TKeyCaptureType aType, const TKeyEvent& aKeyEvent, TAny* aFocusWindowGroup, TUid aFocusAppUid);
+
+	/** Capture type */
+	TKeyCaptureType		iType;
+
+	/** Input key event */
+	TKeyEvent			iKeyEvent;
+
+	/** Opaque handle to current focussed window group */
+	TAny*				iFocusWindowGroup;
+
+	/** UID of client application with current focussed window group */
+	TUid				iFocusAppUid;
+
+	/** Reserved for future use */
+	TInt				iReserved[2];
+	};
+
+/**
+Result codes for RouteKey()
+*/
+enum TKeyEventRouterResult
+	{
+	/** Key routed, no capture */
+	ERouted = 0,
+
+	/** Key captured and routed */
+	ECaptured = 1,
+
+	/** Key consumed, do not deliver event */
+	EConsumed = 2
+	};
+
+/**
+Output parameters for RouteKey()
+*/
+struct TKeyEventRouterOutput
+	{
+	/** Result code */
+	TKeyEventRouterResult	iResult;
+
+	/** Output key event as translated by plug-in. Key code may be set by
+		RWindowGroup::CaptureLongKey() via TKeyCaptureRequest.iOutputCode **/
+	TKeyEvent				iKeyEvent;
+
+	/** Opaque handle to destination window group or NULL if captured by WServ
+		(hotkey). Plug-in must set this to either the window group from the
+		matching capture request or to TKeyEventRouterInput.iFocusWindowGroup */
+	TAny*					iWindowGroup;
+
+	/** Opaque handle from matching capture request or NULL if none */
+	TAny*					iCaptureHandle;
+
+	/** Reserved for future use */
+	TInt					iReserved[2];
+	};
+
+/**
+Key Event Router Interface
+
+This class is implemented by a plug-in DLL in order to perform customised
+routing of window server key events.
+
+The Key Event Routing plug-in is a polymorphic DLL that implements the
+CKeyEventRouter interface. Its UID1 and UID2 must be KDynamicLibraryUid and
+KKeyRouterPluginUid respectively. UID3 identifies a particular implementation
+of the plug-in. The first and only exported function should create and return
+an object of the CKeyEventRouter sub-class.
+*/
+class CKeyEventRouter : public CBase
+	{
+public:
+	/**
+	Create and return an instance of CKeyEventRouter
+
+	@return	Pointer to new router instance
+	*/
+	IMPORT_C static CKeyEventRouter* NewL();
+
+	/**
+	Add a new key capture request
+
+	@param	aRequest	Capture request details
+	*/
+	virtual void AddCaptureKeyL(const TKeyCaptureRequest& aRequest) = 0;
+	   
+	/**
+	Update an existing key capture request
+
+	@param	aRequest	Updated capture request details
+	*/
+	virtual void UpdateCaptureKeyL(const TKeyCaptureRequest& aRequest) = 0;
+
+	/**
+	Cancel a key capture request
+
+	@param	aType		Capture type
+	@param	aHandle		Opaque handle of request to be cancelled
+	*/
+	virtual void CancelCaptureKey(TKeyCaptureType aType, TAny* aHandle) = 0;
+
+	/**
+	Route the key event described by aInput and return its destination
+	in iOutput.
+
+	@param	aInput		Input data with key event to be routed
+	@param	aOutput		Output key event and routing results
+	*/
+	virtual void RouteKey(const TKeyEventRouterInput& aInput,
+						  TKeyEventRouterOutput& aOutput) = 0;
+
+	/**
+	Reserved for future use
+	*/
+private:
+	virtual void Reserved1() {};
+	virtual void Reserved2() {};
+	};
+
+inline TKeyEventRouterInput::TKeyEventRouterInput(TKeyCaptureType aType, const TKeyEvent& aKeyEvent, TAny* aFocusWindowGroup, TUid aFocusAppUid) : iType(aType), iKeyEvent(aKeyEvent), iFocusWindowGroup(aFocusWindowGroup), iFocusAppUid(aFocusAppUid)
+	{
+	}
+
+#endif // WSKEYROUTER_H
--- a/windowing/windowserver/inc/W32STD.H	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/inc/W32STD.H	Fri Sep 24 16:44:34 2010 +0300
@@ -33,6 +33,7 @@
 #include <advancedpointerevent.h>
 #include <sizemode.h>
 #include <babitflags.h>
+#include <wspublishandsubscribedata.h>
 
 #ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
 #include <graphics/windowserverconstants.h>
@@ -1380,6 +1381,7 @@
 		line. */
 		ECustomTextCursorAlignBottom
 		};
+	
 //
 public:
 	IMPORT_C RWsSession();
@@ -1538,6 +1540,9 @@
 	IMPORT_C void UnregisterAllEffects();
 	IMPORT_C void OverrideEffects(TInt aAction, TInt aPurpose, const TFileName& aResourceDir, const TFileName& aFilenameOutgoing, const TFileName& aFilenameIncoming, TBitFlags aFlags=0);
 	
+//Application tells the window server the orientation of rendering it intends to use
+	IMPORT_C void IndicateAppOrientation(TRenderOrientation aOrientation);
+	
 // functions not exported, used by CWsGraphic
 	void GraphicMessageReady(TRequestStatus *aStat);
 	void GetGraphicMessage(TDes8& aData) const;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/inc/wspublishandsubscribedata.h	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,47 @@
+// Copyright (c) 2010 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:
+// Standard window server header file
+// 
+//
+#ifndef WSPUBLISHANDSUBSCRIBEDATA_H
+#define WSPUBLISHANDSUBSCRIBEDATA_H
+
+#include <e32cmn.h>
+
+// Values for the render orientation P&S value that we publish
+// Used when the property is defined, attached to, and deleted
+const TUid  KRenderOrientationCategory  = {268450592};  // WServ UID3
+const TUint KRenderOrientationKey       = 0x102872E5;
+
+/** The orientation of rendering the application intends to use.
+
+@see RWsSession::IndicateAppOrientation(TOrientation aOrientation)*/
+enum TRenderOrientation
+    {
+    /** Fixed default orientation */
+    EDisplayOrientationNormal,
+    /** 90° clockwise */
+    EDisplayOrientation90CW,
+    /** 180° */
+    EDisplayOrientation180,
+    /** 270° clockwise */
+    EDisplayOrientation270CW,
+    /** The orientation is from the P&S Key */
+    EDisplayOrientationAuto,
+    /** use the orientation specified by the next top level window(s) that does not have ignore flag set. 
+    E.g. system dialog on top of foreground app. */
+    EDisplayOrientationIgnore
+    };
+
+#endif // WSPUBLISHANDSUBSCRIBEDATA_H
--- a/windowing/windowserver/nga/CLIENT/RWINDOW.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/CLIENT/RWINDOW.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1363,7 +1363,7 @@
 events from all detected pointers to this window.
 
 This method must be called before the window is activated by calling RWindowBase::Activate().
-Otherwise this will be ignored (release build), or panic (debug build). 
+Otherwise the client is panicked with the code EWservPanicUnableToEnableAdvPointer.
 
 If this method is not called for the window, it is assumed that the window is not
 able to receive events from multiple pointers, and thus only events from a single
@@ -2798,6 +2798,7 @@
 description above. 
 @param aPriority A priority value - if more than one window group has requested 
 capture for the same key event, the one with the highest priority will capture it.
+The value must be greater than KMinTInt.
 @return A handle identifying the capture key, or one of the system-wide error 
 codes (if <0). KErrPermissionDenied indicates that the requested key cannot be 
 captured by this window group, because it has been protected by another window group. 
@@ -2866,6 +2867,7 @@
 aModifierMask need to be set and which need to be unset. 
 @param aPriority A priority value - if more than one window group has requested 
 capture for the same key event, the one with the highest priority will capture it.
+The value must be greater than KMinTInt.
 @return A handle identifying the capture key, or one of the system-wide error 
 codes (if < 0). KErrPermissionDenied indicates that the requested key cannot be captured by this 
 window group, because it has been protected by another window group. For more information, see 
@@ -2937,6 +2939,7 @@
 not set. Modifier key states are defined in TEventModifier. 
 @param aPriority If more than one window group has requested capture for the 
 same long key event, the one with the highest priority will capture the event.
+The value must be greater than KMinTInt.
 @param aFlags Configures the long key capture behaviour. See the TLongCaptureFlags 
 enum.
 @return Identifying value for the long key capture. For use with the CancelCaptureLongKey() 
@@ -2972,6 +2975,7 @@
 not set. Modifier key states are defined in TEventModifier. 
 @param aPriority If more than one window group has requested capture for the 
 same long key event, the one with the highest priority will capture the event.
+The value must be greater than KMinTInt.
 @param aFlags Configures the long key capture behaviour. See the TLongCaptureFlags 
 enum.
 @return Identifying value for the long key capture. For use with the CancelCaptureLongKey() 
--- a/windowing/windowserver/nga/CLIENT/RWS.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/CLIENT/RWS.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -22,6 +22,7 @@
 #include "CLIENT.H"
 #include "graphics/windowserverconstants.h"
 #include "rtfxeffect.h"
+#include <wspublishandsubscribedata.h>
 
 const TInt KMaxWSERVMessagesSlot=-1;
 
@@ -2585,3 +2586,15 @@
 	RTFXEffect tfxEffect(iWsHandle, iBuffer);
 	tfxEffect.OverrideTFXEffect(RTFXEffect::ETFXSession, aAction, aPurpose, aResourceDir, aFilenameOutgoing, aFilenameIncoming, aFlags);
 	}
+
+EXPORT_C void RWsSession::IndicateAppOrientation(TRenderOrientation aOrientation)
+/**
+Application informs window server the orientation of rendering it intends to use
+
+@param aOrientation The orientation the application intends to use
+
+@publishedPartner
+*/
+	{
+	return(WriteInt(aOrientation,EWsClOpIndicateAppOrientation));
+	}
--- a/windowing/windowserver/nga/SERVER/CAPKEY.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/CAPKEY.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-2010 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"
@@ -24,9 +24,6 @@
 _LIT(KWsProtectedKey, "PROTECTEDKEY");
 _LIT(KWsProtectedWindowName, "PROTECTEDKEYWINDOWNAME");
 
-TPriQue<CWsCaptureKeyUpsAndDowns> CWsCaptureKeyUpsAndDowns::iCaptureKeysUpsAndDowns(_FOFF(CWsCaptureKeyUpsAndDowns,iLink));
-TPriQue<CWsCaptureLongKey> CWsCaptureLongKey::iCaptureLongKeys(_FOFF(CWsCaptureLongKey,iLink));
-
 
 /*CWsCaptureKey*/
 
@@ -35,20 +32,38 @@
 
 CWsCaptureKey::~CWsCaptureKey()
 	{
-	TWindowServerEvent::CancelCaptureKey((TUint32)this);
+	TWindowServerEvent::CancelCaptureKey(ECaptureTypeKey, this);
 	}
 
-void CWsCaptureKey::CmdToParams(const TWsWinCmdCaptureKey &aCaptureKey, TCaptureKey &aParams)
+/**
+Convert a window server key capture command to a capture request for the
+key routing plug-in.
+
+@param	aCaptureKey		Input capture command
+@param	aRequest		Output capture request
+*/
+void CWsCaptureKey::CmdToRequest(const TWsWinCmdCaptureKey &aCaptureKey, TKeyCaptureRequest &aRequest)
 	{
-	aParams.iModifiers.iMask=aCaptureKey.modifierMask;
-	aParams.iModifiers.iValue=aCaptureKey.modifiers;
-	aParams.iKeyCodePattern.iKeyCode=(TInt16)aCaptureKey.key;
-	aParams.iKeyCodePattern.iPattern=EMatchKey;
-	aParams.iKeyCodePattern.iFiller=STATIC_CAST(TUint8,aCaptureKey.priority);
-	aParams.iApp=(TUint32)iWindowGroup;
-	aParams.iHandle=(TUint32)this;
+	aRequest.iType = ECaptureTypeKey;
+	aRequest.iModifierMask = aCaptureKey.modifierMask;
+	aRequest.iModifiers = aCaptureKey.modifiers;
+	aRequest.iInputCode = aCaptureKey.key;
+	aRequest.iOutputCode = aCaptureKey.key;
+	aRequest.iPriority = aCaptureKey.priority;
+	aRequest.iWindowGroup = iWindowGroup;
+	aRequest.iWindowGroupId = iWindowGroup ? iWindowGroup->Identifier() : 0;
+	aRequest.iAppUid = iWsOwner ? TUid::Uid(iWsOwner->SecureId().iId) : KNullUid;
+	aRequest.iHandle = this;
 	}
 
+/**
+Check for protected key in a capture command
+
+@param	aWindowGroup	Window Group of capture request
+@param	aCaptureKey		Key capture command
+
+@leave KErrPermissionDenied		Capture key is protected
+*/
 void CheckProtectedKeyL(CWsWindowGroup* aWindowGroup,const TWsWinCmdCaptureKey &aCaptureKey)
 	{
 	//The key specified in the WSINI file with the keyword: PROTECTEDKEY can only be captured 
@@ -56,7 +71,7 @@
 	TInt protectedKey;
 	if(WsIniFile->FindVar(KWsProtectedKey,protectedKey))
 		{
-		if (aCaptureKey.key == (TUint)protectedKey)
+		if (aCaptureKey.key == static_cast<TUint>(protectedKey))
 			{
 			if (aWindowGroup->GroupName()==NULL)
 				{
@@ -73,20 +88,36 @@
 		}
 	}
 
+/**
+Construct a capture object for normal key events and make a capture request
+to the key routing plug-in.
+
+@param	aCaptureKey		Key capture command from RWindowGroup::CaptureKey(),
+						RWsSession::SetHotKey() or default hot key settings.
+*/
 void CWsCaptureKey::ConstructL(const TWsWinCmdCaptureKey &aCaptureKey)
 	{
 	CheckProtectedKeyL(iWindowGroup, aCaptureKey);
 	NewObjL();
-	TCaptureKey params;
-	CmdToParams(aCaptureKey, params);
-	TWindowServerEvent::AddCaptureKeyL(params);
+
+	TKeyCaptureRequest request;
+	CmdToRequest(aCaptureKey, request);
+	TWindowServerEvent::AddCaptureKeyL(request);
 	}
 
+/**
+Make a capture request update for normal key events to the key routing plug-in.
+
+@param	aCaptureKey		Key capture command from CWsHotKey::SetL()
+
+Note: this function is used only to disable hot key capture requests or to
+reset them to their defaults.
+*/
 void CWsCaptureKey::SetL(const TWsWinCmdCaptureKey &aCaptureKey)
 	{
-	TCaptureKey params;
-	CmdToParams(aCaptureKey, params);
-	TWindowServerEvent::SetCaptureKey((TUint32)this, params);
+	TKeyCaptureRequest request;
+	CmdToRequest(aCaptureKey, request);
+	TWindowServerEvent::UpdateCaptureKeyL(request);
 	}
 
 void CWsCaptureKey::CommandL(TInt , const TAny *)
@@ -101,37 +132,39 @@
 
 CWsCaptureKeyUpsAndDowns::~CWsCaptureKeyUpsAndDowns()
 	{
-	iLink.Deque();
+	TWindowServerEvent::CancelCaptureKey(ECaptureTypeKeyUpDown, this);
 	}
 
+/**
+Construct a capture object for up/down key events and make a capture request
+to the key routing plug-in.
+
+@param	aCaptureKey		Key capture command from
+						RWindowGroup::CaptureKeyUpAndDowns().
+*/
 void CWsCaptureKeyUpsAndDowns::ConstructL(const TWsWinCmdCaptureKey &aCaptureKey)
 	{
 	CheckProtectedKeyL(iWindowGroup, aCaptureKey);
 	NewObjL();
-	iModifierMask=aCaptureKey.modifierMask;
-	iModifierValue=aCaptureKey.modifiers;
-	iScanCode=aCaptureKey.key;
-	iLink.iPriority=aCaptureKey.priority + 1;
-	iCaptureKeysUpsAndDowns.Add(*this);
-	--iLink.iPriority;
+
+	TKeyCaptureRequest request;
+	request.iType = ECaptureTypeKeyUpDown;
+	request.iInputCode = aCaptureKey.key;
+	request.iOutputCode = aCaptureKey.key;
+	request.iModifiers = aCaptureKey.modifiers;
+	request.iModifierMask = aCaptureKey.modifierMask;
+	request.iPriority = aCaptureKey.priority;
+	request.iWindowGroup = iWindowGroup;
+	request.iWindowGroupId = iWindowGroup ? iWindowGroup->Identifier() : 0;
+	request.iAppUid = iWsOwner ? TUid::Uid(iWsOwner->SecureId().iId) : KNullUid;
+	request.iHandle = this;
+	TWindowServerEvent::AddCaptureKeyL(request);
 	}
 
 void CWsCaptureKeyUpsAndDowns::CommandL(TInt , const TAny *)
 	{
 	}
 
-CWsWindowGroup *CWsCaptureKeyUpsAndDowns::CheckForCapture(TUint aScanCode, TUint aModifiers)
-	{
-	TDblQueIter<CWsCaptureKeyUpsAndDowns> iter(iCaptureKeysUpsAndDowns);
-	CWsCaptureKeyUpsAndDowns* cap;
-	while ((cap=iter++)!=NULL)
-		{
-		if (cap->iScanCode==aScanCode && (aModifiers&cap->iModifierMask)==cap->iModifierValue)
-			return(cap->iWindowGroup);
-		}
-	return NULL;
-	}
-
 
 /*CWsCaptureLongKey*/
 
@@ -141,35 +174,40 @@
 
 CWsCaptureLongKey::~CWsCaptureLongKey()
 	{
-	iLink.Deque();
+	TWindowServerEvent::CancelCaptureKey(ECaptureTypeLongKey, this);
 	}
 
+/**
+Construct a capture object for long key events and make a capture request
+to the key routing plug-in.
+
+@param	aCaptureKey		Key capture command from RWindowGroup::CaptureLongKey()
+*/
 void CWsCaptureLongKey::ConstructL(const TWsWinCmdCaptureLongKey &aCaptureKey)
 	{
 	NewObjL();
-	iData=aCaptureKey;
-	if (iData.delay.Int()<0)
+	iFlags = aCaptureKey.flags;
+	iDelay = aCaptureKey.delay;
+	if (iDelay.Int() < 0)
 		{
 		TTimeIntervalMicroSeconds32 time;
-		CKeyboardRepeat::GetRepeatTime(iData.delay,time);
+		CKeyboardRepeat::GetRepeatTime(iDelay, time);
 		}
-	iLink.iPriority=iData.priority + 1;
-	iCaptureLongKeys.Add(*this);
-	--iLink.iPriority;
+
+	TKeyCaptureRequest request;
+	request.iType = ECaptureTypeLongKey;
+	request.iInputCode = aCaptureKey.inputKey;
+	request.iOutputCode = aCaptureKey.outputKey;
+	request.iModifiers = aCaptureKey.modifiers;
+	request.iModifierMask = aCaptureKey.modifierMask;
+	request.iPriority = aCaptureKey.priority;
+	request.iWindowGroup = iWindowGroup;
+	request.iWindowGroupId = iWindowGroup ? iWindowGroup->Identifier() : 0;
+	request.iAppUid = iWsOwner ? TUid::Uid(iWsOwner->SecureId().iId) : KNullUid;
+	request.iHandle = this;
+	TWindowServerEvent::AddCaptureKeyL(request);
 	}
 
 void CWsCaptureLongKey::CommandL(TInt , const TAny *)
 	{
 	}
-
-CWsCaptureLongKey* CWsCaptureLongKey::CheckForCapture(TUint aKeyCode, TInt aModifiers)
-	{
-	TDblQueIter<CWsCaptureLongKey> iter(iCaptureLongKeys);
-	CWsCaptureLongKey* longCapture;
-	while ((longCapture=iter++)!=NULL)
-		{
-		if (aKeyCode==longCapture->iData.inputKey && (aModifiers&longCapture->iData.modifierMask)==longCapture->iData.modifiers)
-			return longCapture;
-		}
-	return NULL;
-	}
--- a/windowing/windowserver/nga/SERVER/EVENT.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/EVENT.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1994-2010 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"
@@ -18,6 +18,7 @@
 #include "EVENT.H"
 
 #include "W32STD.H"
+#include <e32uid.h>
 #include <hal.h>
 #include <w32adll.h>
 #include "W32CLICK.H"
@@ -32,12 +33,16 @@
 #include "pointer.h"
 #include "debugbar.h"
 #include "advancedpointereventhelper.h"
+#include "Graphics/wsgraphicdrawerinternal.h"
 
 GLREF_D CDebugLogBase *wsDebugLog;
 
 GLREF_C void StateDump();
 GLREF_C void HeapDump();
 
+_LIT(KDefaultKeyRouterPluginName, "keyrouter.dll");
+_LIT(KWSERVIniFileVarKeyRouterPlugin, "KEYROUTERPLUGIN");
+
 #define IMPOSSIBLE 0xFFFFFFFF
 
 const TWsWinCmdCaptureKey ImpossibleKeyPress=
@@ -160,6 +165,8 @@
 TEventRequestQueue TWindowServerEvent::iScreenDeviceChangedQueue;
 TTime TWindowServerEvent::iPrevOomMessageTime;
 CCaptureKeys *TWindowServerEvent::iCaptureKeys;
+CKeyEventRouter* TWindowServerEvent::iKeyEventRouter;
+RLibrary TWindowServerEvent::iKeyEventRouterLibrary;
 CWsHotKey *TWindowServerEvent::iHotKeys;
 TInt TWindowServerEvent::iModifierState;
 CRawEventReceiver *TWindowServerEvent::iEventReceiver;
@@ -172,12 +179,12 @@
 TInt TWindowServerEvent::iEventHandlerCount=0;
 TRepeatKey CKeyboardRepeat::iCurrentRepeat;
 TRepeatKey CKeyboardRepeat::iAlternateRepeat;
+TRepeatKey CKeyboardRepeat::iLongRepeat;
 TInt CKeyboardRepeat::iRepeatRollover=1;
 CKeyboardRepeat::TRepeatType CKeyboardRepeat::iRepeating=ERepeatNone;
 CKeyboardRepeat *CKeyboardRepeat::iThis=NULL;
 TTimeIntervalMicroSeconds32 CKeyboardRepeat::iInitialTime;
 TTimeIntervalMicroSeconds32 CKeyboardRepeat::iTime;
-CWsWindowGroup *CKeyboardRepeat::iFocus=NULL;
 TBool CKeyboardRepeat::iAlternateRepeatExists=EFalse;
 CWsCaptureLongKey* CKeyboardRepeat::iLongCapture=NULL;
 
@@ -198,6 +205,8 @@
 	{
 	DeleteHotKeys();
 	delete iCaptureKeys;
+	delete iKeyEventRouter;
+	iKeyEventRouterLibrary.Close();
 	CKeyboardRepeat::Destroy();
 	delete iKeyTranslator;
 	delete iEventReceiver;
@@ -231,8 +240,57 @@
 		iKeyTranslator->ChangeKeyData(keyDataDllName);
 		}
 
+	// CCaptureKeys is no longer used but a dummy object is required for
+	// calls to CKeyTranslator::TranslateKey() until capture functionality
+	// has been removed from ektran.dll.
 	iCaptureKeys=new(ELeave) CCaptureKeys;
 	iCaptureKeys->Construct();
+
+	// Load the key event routing plug-in. The DLL name may be overridden
+	// by setting the keyword KEYROUTERPLUGIN in wsini.ini.
+	TPtrC pluginName(KDefaultKeyRouterPluginName);
+	WsIniFile->FindVar(KWSERVIniFileVarKeyRouterPlugin, pluginName);
+	const TUidType uidType(KDynamicLibraryUid, KKeyRouterPluginUid);
+	TInt err = iKeyEventRouterLibrary.Load(pluginName, uidType);
+
+	if (wsDebugLog)
+		{
+		TLogMessageText buf;
+
+		if (err == KErrNone)
+			{
+			_LIT(KLogLoadOk, "Loaded plugin '%S' UID3 0x%x");
+			const TFileName& pluginPathname = iKeyEventRouterLibrary.FileName();
+			const TUid uid3 = iKeyEventRouterLibrary.Type()[2];
+			buf.Format(KLogLoadOk, &pluginPathname, uid3.iUid);
+			}
+		else
+			{
+			_LIT(KLogLoadError, "Failed to load plugin '%S' (error %d)");
+			buf.Format(KLogLoadError, &pluginName, err);
+			}
+
+		wsDebugLog->MiscMessage(CDebugLogBase::ELogImportant, buf);
+		}
+
+	if (err != KErrNone)
+		{
+#ifdef _DEBUG
+		_LIT(KLoadError, "WServ: failed to load plugin '%S' (error %d)");
+		RDebug::Print(KLoadError, &pluginName, err);
+#endif
+		User::Leave(err);
+		}
+
+	// Create the key event router
+	typedef CKeyEventRouter* (*TCreateFunc)();
+	TCreateFunc newL = reinterpret_cast<TCreateFunc>(iKeyEventRouterLibrary.Lookup(1));
+	if (newL == NULL)
+		{
+		User::Leave(KErrNotFound);
+		}
+	iKeyEventRouter = (*newL)();
+
 	for (TInt index=0;index<TWindowServerEvent::ENumHotKeys;index++)
 		ConstructDefaultHotKeyL(index,DefaultHotKeys[index]);
 	CKeyboardRepeat::NewL();
@@ -312,6 +370,7 @@
 	captureKey.modifiers=aHotKey.modifiers;
 	captureKey.modifierMask=aHotKey.modifierMask;
 	captureKey.key=aHotKey.keycode;
+	captureKey.priority = 0;
 	hotKey->ConstructLD(captureKey);
 //
 	LinkHotKey(hotKey);
@@ -622,6 +681,21 @@
 	TWsEvent event;
 	event.SetType(EEventDisplayChanged);
 	event.SetTimeNow();
+	
+    // fill in the handle otherwise CONE will discard the notification
+    CWsObjectIx* clientObjList = aWsClient->ObjectIndex();
+    const TWsObject* ptr=clientObjList->FirstObject();
+    const TWsObject* end=ptr+clientObjList->Length();
+    while(++ptr<end)    // first one should always have a NULL object
+        {
+        const CWsObject* obj=ptr->iObject;
+        if (obj && obj->Type()==WS_HANDLE_GROUP_WINDOW)
+            {
+            event.SetHandle(ptr->iHandle);
+            break;
+            }
+        }	
+	
 	TWsDisplayChangedEvent* dispEvent = event.DisplayChanged();
 	dispEvent->iDisplayNumber = aDisplayNumber;
 	dispEvent->iConfigurationChangeId = aConfigurationChangeId;
@@ -641,23 +715,68 @@
 	aWin->EventQueue()->QueueEvent(aEvent, aPriority);
 	}
 
-void TWindowServerEvent::QueueKeyPress(const TKeyData& aKey, TInt aScanCode, CWsWindowGroup* aRepeatFocus, TBool aCheckRepeat,TInt aRepeats)
+/**
+Process a key press event.
+
+This function is called for every input key event and uses the Key Event
+Routing plug-in to check for short and long key capture and determine the
+destination window group for the queued event(s).
+Window server hotkeys are also processed.
+Note that the key repeat timer is started here but the key repeat events
+generated by the timer go directly to QueueKeyPress().
+
+@param	aKeyEvent		Input key event
+@param	aCheckRepeat	Check for key repeat and long key capture
+@param	aRepeats		Repeat count
+*/
+void TWindowServerEvent::ProcessKeyPress(const TKeyEvent& aKeyEvent, TBool aCheckRepeat, TInt aRepeats)
  	{
-	CWsWindowGroup* focusWin=CWsTop::FocusWindowGroup();
-	TWsEvent event;
-	TKeyEvent& keyEvent=*event.Key();
-	keyEvent.iCode=aKey.iKeyCode;
-	keyEvent.iScanCode=aScanCode;
-	keyEvent.iModifiers=aKey.iModifiers;
-	keyEvent.iRepeats=aRepeats;
-	if (!aRepeatFocus && CClick::IsHandler())
-		CClick::KeyEvent(EEventKey,keyEvent);
-	CWsCaptureLongKey* longCapture=NULL;
-	if (aCheckRepeat)
-		longCapture=CWsCaptureLongKey::CheckForCapture(aKey.iKeyCode, aKey.iModifiers);
-	if (aKey.iIsCaptureKey)
+	CWsWindowGroup* focusWin = CWsTop::FocusWindowGroup();
+	TUid focusAppUid = focusWin ? TUid::Uid(focusWin->Client()->SecureId().iId) : KNullUid;
+
+	// Route the key event and check for short key capture.
+	// Note that the Key Routing plugin may translate or block key events.
+	TKeyEventRouterInput input(ECaptureTypeKey, aKeyEvent, focusWin, focusAppUid);
+	TKeyEventRouterOutput output;
+
+#ifdef _DEBUG
+	// RouteKey() must not fail. Check for leaves in case the plug-in
+	// is badly behaved.
+	TRAPD(err, iKeyEventRouter->RouteKey(input, output));
+	WS_ASSERT_DEBUG(err == KErrNone, EWsPanicKeyEventRouterLeave);
+#else
+	iKeyEventRouter->RouteKey(input, output);
+#endif
+
+	WS_ASSERT_DEBUG(output.iResult == ERouted || output.iResult == ECaptured || output.iResult == EConsumed, EWsPanicKeyEventRouterBadResult);
+
+	if (output.iResult == EConsumed)
 		{
-		if (aKey.iApp==NULL)	// Captured by Wserv itself
+		focusWin = NULL;
+		}
+	else
+		{
+		focusWin = static_cast<CWsWindowGroup*>(output.iWindowGroup);
+		}
+	WS_ASSERT_DEBUG((focusWin == NULL || focusWin->Type() == WS_HANDLE_GROUP_WINDOW) && (output.iResult != ERouted || focusWin == CWsTop::FocusWindowGroup()), EWsPanicKeyEventRouterBadWindowGroup);
+
+	// Ensure that short event is not marked with EModifierLongKey
+	output.iKeyEvent.iModifiers &= ~EModifierLongKey;
+
+	// Generate key click unless the event is consumed. This is consistent
+	// with the behaviour when CKeyTranslator::TranslateKey() yields no
+	// translation for a particular scan code. (Click events for key up/down
+	// will still be generated by QueueKeyUpDown()). Note however that a long
+	// key press may still be captured even if the short event is consumed.
+	if (CClick::IsHandler() && output.iResult != EConsumed)
+		{
+		output.iKeyEvent.iRepeats = aRepeats;
+		CClick::KeyEvent(EEventKey, output.iKeyEvent);
+		}
+
+	if (output.iResult == ECaptured)
+		{
+		if (output.iWindowGroup == NULL)	// Captured by Wserv itself
 			{
 			_LIT(KWSERVDebugLogCapturedKey,"WSERV Captured Key");
 			CScreen* focusScreen=CWsTop::CurrentFocusScreen();
@@ -668,7 +787,7 @@
 			CWsHotKey *hotKey=iHotKeys;
 			while(hotKey)
 				{
-				if (hotKey->KeyHandle()==aKey.iHandle)
+				if (hotKey->KeyHandle() == reinterpret_cast<TInt>(output.iCaptureHandle))
 					{
 					switch(hotKey->HotKeyType())
 						{
@@ -753,22 +872,85 @@
 			WS_PANIC_ALWAYS(EWsPanicUnknownCaptureKey);
 			return;
 			}
-		focusWin=((CWsWindowGroup *)aKey.iApp);
+
 		_LIT(KWSERVDebugLogKeyCapturedByApp,"Key captured by app %d");
 		if (wsDebugLog)
 			wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,KWSERVDebugLogKeyCapturedByApp,focusWin->Identifier());
 		if (CWsPassword::PasswordModeActive() && focusWin!=CWsPassword::PasswordWindow()->WinGroup())
 			return;
 		}
-	if (aRepeatFocus && aRepeatFocus!=focusWin)
-		CKeyboardRepeat::CancelRepeat(NULL);		// Repeat is going to different window so cancel it and don't deliver this key
-	else if (focusWin!=NULL && focusWin->CheckForPriorityKey(aKey,aScanCode)==EFalse)
+
+	CWsCaptureLongKey* longCapture = NULL;
+	TKeyEventRouterOutput longOutput;
+	if (aCheckRepeat)
 		{
-		if (longCapture || (aCheckRepeat && !aRepeatFocus && aKey.iModifiers&EModifierAutorepeatable))
+		// Check for long key capture.
+		// Note that a long key event can only result from capture, there is
+		// no default detection or routing of long events.
+		input.iType = ECaptureTypeLongKey;
+#ifdef _DEBUG
+		TRAPD(err, iKeyEventRouter->RouteKey(input, longOutput));
+		WS_ASSERT_DEBUG(err == KErrNone, EWsPanicKeyEventRouterLeave);
+#else
+		iKeyEventRouter->RouteKey(input, longOutput);
+#endif
+
+		if (longOutput.iResult == ECaptured)
+			{
+			longCapture = static_cast<CWsCaptureLongKey*>(longOutput.iCaptureHandle);
+
+			// Mark long key events with EModifierLongKey so that applications
+			// can easily distinguish short and long events.
+			longOutput.iKeyEvent.iModifiers |= EModifierLongKey;
+
+			// Start timer to detect long key press
+			CKeyboardRepeat::StartRepeat(aKeyEvent.iScanCode, output, &longOutput);
+			}
+		else if (output.iResult != EConsumed && output.iKeyEvent.iModifiers & EModifierAutorepeatable)
 			{
-			if (CKeyboardRepeat::StartRepeat(aKey,aScanCode,focusWin,longCapture))
-				return;
+			// Start timer for key repeat
+			CKeyboardRepeat::StartRepeat(aKeyEvent.iScanCode, output, NULL);
 			}
+		}
+
+	// Queue the short event
+	if (!longCapture || longCapture->iFlags & ELongCaptureShortEventImmediately)
+		{
+		QueueKeyPress(output, EFalse, aRepeats);
+		}
+	}
+
+/**
+Queue a key press event.
+
+This function is called for each key event produced by ProcessKeyPress(),
+for every key repeat and long key event generated by the timer and also for
+delayed short key events from KeyUp().
+
+@param	aOutput			Output key event from routing plug-in
+@param	aIsRepeat		Event is due to key repeat
+@param	aRepeats		Repeat count
+*/
+void TWindowServerEvent::QueueKeyPress(const TKeyEventRouterOutput& aOutput, TBool aIsRepeat, TInt aRepeats)
+ 	{
+	if (aOutput.iResult == EConsumed)
+		{
+		// Don't deliver this key
+		return;
+		}
+
+	TWsEvent event;
+	TKeyEvent& keyEvent = *event.Key();
+	keyEvent = aOutput.iKeyEvent;
+	keyEvent.iRepeats = aRepeats;
+
+	CWsWindowGroup* focusWin = static_cast<CWsWindowGroup*>(aOutput.iWindowGroup);
+	WS_ASSERT_DEBUG(focusWin == NULL || focusWin->Type() == WS_HANDLE_GROUP_WINDOW, EWsPanicKeyEventRouterBadWindowGroup);
+
+	if (aIsRepeat && aOutput.iResult != ECaptured && focusWin != CWsTop::FocusWindowGroup())
+		CKeyboardRepeat::CancelRepeat(NULL);		// Repeat is going to different window so cancel it and don't deliver this key
+	else if (focusWin != NULL && focusWin->CheckForPriorityKey(keyEvent) == EFalse)
+		{
 		event.SetType(EEventKey);
 		event.SetHandle(focusWin->ClientHandle());
 		if (aRepeats!=0)
@@ -776,18 +958,15 @@
 			CEventQueue* queue=focusWin->EventQueue();
 			queue->Wait();
 			const TWsEvent* prev=queue->PeekLastEvent();
-			if (prev!=NULL && prev->Type()==EEventKey && prev->Key()->iRepeats>0)
+			if (prev != NULL && prev->Type() == EEventKey && prev->Key()->iRepeats > 0 && prev->Key()->iCode == keyEvent.iCode)
 				{
-				event= *prev;
-				event.Key()->iRepeats+=aRepeats;
-				queue->UpdateLastEvent(event);
+				prev->Key()->iRepeats += aRepeats;
 				queue->Signal();
 				if (CClick::IsHandler())
-					CClick::KeyEvent(EEventKeyRepeat,*event.Key());
+					CClick::KeyEvent(EEventKeyRepeat, *prev->Key());
 				return;
 				}
 			queue->Signal();
-			event.Key()->iRepeats=aRepeats;
 			if (CClick::IsHandler())
 				CClick::KeyEvent(EEventKeyRepeat,keyEvent);
 			}
@@ -795,24 +974,69 @@
 		}
 	}
 
+/**
+Queue a key up/down event.
+
+@param	aRawEvent		Raw event
+*/
 void TWindowServerEvent::QueueKeyUpDown(const TRawEvent &aRawEvent)
  	{
-	CWsWindowGroup *focusWin=CWsCaptureKeyUpsAndDowns::CheckForCapture(aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE, iModifierState);
-	if (!focusWin)	// If not captured
-		focusWin=CWsTop::FocusWindowGroup();
-	TWsEvent event;
-	TEventCode type=aRawEvent.Type()==TRawEvent::EKeyUp ? EEventKeyUp : EEventKeyDown;
-	event.Key()->iCode=0;
+	TEventCode type = aRawEvent.Type() == TRawEvent::EKeyUp ? EEventKeyUp : EEventKeyDown;
+
+	// Check for key up/down capture
+	TKeyEvent keyEvent;
+	keyEvent.iScanCode = aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE;
+#if defined(__WINS__)
+	keyEvent.iCode = __WINS_CHARCODE(aRawEvent.ScanCode());
+#else
+	keyEvent.iCode = 0;
+#endif
+	keyEvent.iModifiers = iModifierState;
+	keyEvent.iRepeats = 0;
+
+	CWsWindowGroup* focusWin = CWsTop::FocusWindowGroup();
+	TUid focusAppUid = focusWin ? TUid::Uid(focusWin->Client()->SecureId().iId) : KNullUid;
+
+	TKeyEventRouterInput input(ECaptureTypeKeyUpDown, keyEvent, focusWin, focusAppUid);
+	TKeyEventRouterOutput output;
+#ifdef _DEBUG
+	TRAPD(err, iKeyEventRouter->RouteKey(input, output));
+	WS_ASSERT_DEBUG(err == KErrNone, EWsPanicKeyEventRouterLeave);
+#else
+	iKeyEventRouter->RouteKey(input, output);
+#endif
+
+	if (output.iResult == EConsumed)
+		{
+		// Don't deliver this key. A key click is still generated for the
+		// input event.
+		if (CClick::IsHandler())
+			{
+			CClick::KeyEvent(type, keyEvent);
+			}
+		return;
+		}
+	WS_ASSERT_DEBUG(output.iResult == ERouted || output.iResult == ECaptured, EWsPanicKeyEventRouterBadResult);
+
+	focusWin = static_cast<CWsWindowGroup*>(output.iWindowGroup);
+	WS_ASSERT_DEBUG((focusWin == NULL || focusWin->Type() == WS_HANDLE_GROUP_WINDOW) && (output.iResult != ERouted || focusWin == CWsTop::FocusWindowGroup()), EWsPanicKeyEventRouterBadWindowGroup);
 #if defined(__WINS__)
 	if (focusWin && !focusWin->WsOwner()->RemoveKeyCode())
-		event.Key()->iScanCode=aRawEvent.ScanCode();
-	else
+		{
+		// Restore WINS character code
+		output.iKeyEvent.iScanCode |= output.iKeyEvent.iCode;
+		}
+	output.iKeyEvent.iCode = 0;
 #endif
-	event.Key()->iScanCode=aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE;
-	event.Key()->iModifiers=iModifierState;
-	event.Key()->iRepeats=0;
+
+	output.iKeyEvent.iRepeats = 0;
 	if (CClick::IsHandler())
-		CClick::KeyEvent(type,*event.Key());
+		{
+		CClick::KeyEvent(type, output.iKeyEvent);
+		}
+
+	TWsEvent event;
+	*event.Key() = output.iKeyEvent;
 	if (focusWin!=NULL)
 		{
 		event.SetType(type);
@@ -921,6 +1145,11 @@
 		}
 	}
 
+/*
+Process a raw event
+
+@param	aRawEvent	Raw event
+*/
 void TWindowServerEvent::ProcessRawEvent(const TRawEvent& aRawEvent)
 //
 // Event has completed.
@@ -1020,23 +1249,35 @@
 		case TRawEvent::EKeyDown:
 			{
 			_LIT(KWSERVDebugLogKeyDownArrival,"Key down arrives %d");
-			if(CDebugBar* dbg = CWsTop::Screen()->DebugBar())
+			CScreen* screen = CWsTop::Screen();
+			WS_ASSERT_ALWAYS(screen, EWsPanicNoScreen);
+			if(CDebugBar* dbg = screen->DebugBar())
 				dbg->OnKeyEvent();
 			if (wsDebugLog)
 				wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,KWSERVDebugLogKeyDownArrival,aRawEvent.ScanCode());
 			CKeyboardRepeat::KeyDown();
 			TKeyData keyData;
+			// Note iCaptureKeys is needed as dummy arg only. Key capture is
+			// now handled in ProcessKeyPress().
 			TBool translated=iKeyTranslator->TranslateKey(aRawEvent.ScanCode(), EFalse,*iCaptureKeys,keyData);
 			ProcessModifierChanges();
 			QueueKeyUpDown(aRawEvent);
 			if (translated)
-				QueueKeyPress(keyData,aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE,NULL,ETrue,0);
+				{
+				TKeyEvent keyEvent;
+				keyEvent.iScanCode = aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE;
+				keyEvent.iCode = keyData.iKeyCode;
+				keyEvent.iModifiers = keyData.iModifiers;
+				ProcessKeyPress(keyEvent, ETrue, 0);
+				}
 			}
 			break;
 		case TRawEvent::EKeyUp:
 			{
 			_LIT(KWSERVDebugLogKeyUpArrival,"Key up arrives %d");
-			if(CDebugBar* dbg = CWsTop::Screen()->DebugBar())
+			CScreen* screen = CWsTop::Screen();
+			WS_ASSERT_ALWAYS(screen, EWsPanicNoScreen);
+			if(CDebugBar* dbg = screen->DebugBar())
 				dbg->OnKeyEvent();
 			if (wsDebugLog)
 				wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,KWSERVDebugLogKeyUpArrival,aRawEvent.ScanCode());
@@ -1048,7 +1289,11 @@
 			if (translated)
 				{
 				CKeyboardRepeat::CancelRepeat(NULL);
-				QueueKeyPress(keyData,aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE,NULL,EFalse,0);
+				TKeyEvent keyEvent;
+				keyEvent.iScanCode = aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE;
+				keyEvent.iCode = keyData.iKeyCode;
+				keyEvent.iModifiers = keyData.iModifiers;
+				ProcessKeyPress(keyEvent, EFalse, 0);
 				}
 			}
 			break;
@@ -1079,14 +1324,11 @@
  			_LIT(KWSERVDebugLogRepeatingKeyArrival,"Repeating key arrives %d");
  			if (wsDebugLog)
  				wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,KWSERVDebugLogRepeatingKeyArrival,aRawEvent.ScanCode());
- 			TKeyData keyData;
- 			keyData.iModifiers=iKeyTranslator->GetModifierState();
-			keyData.iApp=0;
-			keyData.iHandle=0;
-			keyData.iIsCaptureKey=EFalse;
-			keyData.iKeyCode=aRawEvent.ScanCode(); 
-			iCaptureKeys->ProcessCaptureKeys(keyData);
-			QueueKeyPress(keyData, aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE,NULL,EFalse,aRawEvent.Repeats());
+			TKeyEvent keyEvent;
+			keyEvent.iScanCode = aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE;
+			keyEvent.iCode = aRawEvent.ScanCode();
+ 			keyEvent.iModifiers = iKeyTranslator->GetModifierState();
+			ProcessKeyPress(keyEvent, EFalse, aRawEvent.Repeats());
  			}
  			break;
 		default:
@@ -1096,33 +1338,26 @@
 
 void TWindowServerEvent::ProcessKeyEvent(const TKeyEvent &aKeyEvent,TInt aRepeats)
 	{
-	TKeyData keyData;
-	keyData.iModifiers=aKeyEvent.iModifiers;
-	keyData.iApp=0;
-	keyData.iHandle=0;
-	keyData.iIsCaptureKey=EFalse;
-	keyData.iKeyCode=aKeyEvent.iCode;
 	if (CKeyboardRepeat::IsAreadyActive())
 		{
 		CKeyboardRepeat::CancelRepeat(NULL);
 		}
-	iCaptureKeys->ProcessCaptureKeys(keyData);
-	QueueKeyPress(keyData,aKeyEvent.iScanCode,NULL,aRepeats==0,aRepeats);
+	ProcessKeyPress(aKeyEvent, aRepeats == 0, aRepeats);
 	}
 
-void TWindowServerEvent::AddCaptureKeyL(const TCaptureKey &aCaptureKey)
+void TWindowServerEvent::AddCaptureKeyL(const TKeyCaptureRequest& aRequest)
 	{
-	iCaptureKeys->AddCaptureKeyL(aCaptureKey,aCaptureKey.iKeyCodePattern.iFiller);
+	iKeyEventRouter->AddCaptureKeyL(aRequest);
 	}
 
-void TWindowServerEvent::SetCaptureKey(TUint32 aHandle, const TCaptureKey &aCaptureKey)
+void TWindowServerEvent::UpdateCaptureKeyL(const TKeyCaptureRequest& aRequest)
 	{
-	iCaptureKeys->SetCaptureKey(aHandle, aCaptureKey,aCaptureKey.iKeyCodePattern.iFiller);
+	iKeyEventRouter->UpdateCaptureKeyL(aRequest);
 	}
 
-void TWindowServerEvent::CancelCaptureKey(TUint32 aHandle)
+void TWindowServerEvent::CancelCaptureKey(TKeyCaptureType aType, TAny* aHandle)
 	{
-	iCaptureKeys->CancelCaptureKey(aHandle);
+	iKeyEventRouter->CancelCaptureKey(aType, aHandle);
 	}
 
 TInt TWindowServerEvent::GetModifierState()
@@ -1463,21 +1698,27 @@
 	iTime=aTime;
 	}
 
+/**
+Process timer events.
+
+Called when the key repeat timer expires, this function generates the
+appropriate long key or repeated key event. If the timer was started for
+normal key repeat or if the long key event was captured with the automatic
+repeat option specified then the timer is restarted.
+*/
 void CKeyboardRepeat::RunL()
 	{
 	User::ResetInactivityTime();
-	//WS_ASSERT_DEBUG(iRepeating!=ERepeatNone, EWsPanicTemp);
+	WS_ASSERT_DEBUG(iRepeating != ERepeatNone, EWsPanicKeyRepeat);
 	TBool timer=ETrue;
 	if (iRepeating>=ERepeatLong)
 		{
 		// Defensive programming - iLongCapture should never be NULL if iRepeating >= ERepeatLong
+		WS_ASSERT_DEBUG(iLongCapture != NULL, EWsPanicKeyRepeat);
 		if (iLongCapture)
 			{
-			iCurrentRepeat.iKey.iApp=REINTERPRET_CAST(TUint32,iLongCapture->iWindowGroup);
-			iCurrentRepeat.iKey.iHandle=0;
-			iCurrentRepeat.iKey.iIsCaptureKey=ETrue;
-			iCurrentRepeat.iKey.iKeyCode=iLongCapture->iData.outputKey;
-			timer=iLongCapture->iData.flags&ELongCaptureRepeatEvents;
+			iCurrentRepeat = iLongRepeat;
+			timer = iLongCapture->iFlags & ELongCaptureRepeatEvents;
 			iRepeating=ERepeatLongRepeated;
 			}
 		else
@@ -1491,53 +1732,67 @@
 		After(iTime);
 	else
 		iRepeating=ERepeatNone;
-	TWindowServerEvent::QueueKeyPress(iCurrentRepeat.iKey,iCurrentRepeat.iScanCode,iFocus,EFalse,1);
+
+	TWindowServerEvent::QueueKeyPress(iCurrentRepeat.iOutput, ETrue, 1);
 	}
 
-TBool CKeyboardRepeat::StartRepeat(const TKeyData &aKey, TInt aScanCode, CWsWindowGroup *aRepeatFocus, CWsCaptureLongKey* aLongCapture)
+/**
+Start key repeat and long key press timer
+
+@param	aInputScanCode	Original scan code (before routing)
+@param	aShortEvent		Short key event (routing plug-in output)
+@param	aLongEvent		Pointer to long key event (routing plug-in output)
+						or NULL if none.
+
+Note: When aLongEvent != NULL, iCurrentRepeat reflects the short key event
+until the timer has expired. This is necessary to allow a delayed short key
+event to be delivered by KeyUp(). CancelRepeat() must therefore examine
+iCurrentRepeat or iLongRepeat according to the repeat type in iRepeat.
+*/
+void CKeyboardRepeat::StartRepeat(TInt aInputScanCode, const TKeyEventRouterOutput& aShortEvent, const TKeyEventRouterOutput* aLongEvent)
 	{
 	TTimeIntervalMicroSeconds32 time;
-	TBool ret=EFalse;
-	iCurrentRepeat.iScanCode=aScanCode;
-	iCurrentRepeat.iKey=aKey;
+	iCurrentRepeat.iInputScanCode = aInputScanCode;
+	iCurrentRepeat.iOutput = aShortEvent;
 
-	if (aLongCapture)
+	if (aLongEvent)
 		{
-		iLongCapture=aLongCapture;
-		iRepeating=ERepeatLong;
-		time=aLongCapture->iData.delay;
-		ret=!(aLongCapture->iData.flags&ELongCaptureShortEventImmediately);
-		//need window group from long capture key or even better delete it altogether.
-		iFocus=aLongCapture->WindowGroup();
+		iRepeating = ERepeatLong;
+		iLongRepeat.iInputScanCode = aInputScanCode;
+		iLongRepeat.iOutput = *aLongEvent;
+		iLongCapture = static_cast<CWsCaptureLongKey*>(aLongEvent->iCaptureHandle);
+		time = iLongCapture->iDelay;
 		}
 	else
 		{
-		iFocus=aRepeatFocus;
+		iLongCapture = NULL;
 		iRepeating=ERepeatNormal;
 		time=iInitialTime;
 		}
 	iThis->After(time);
-	return ret;
 	}
 
+/**
+Cancel key repeat processing
+*/
 void CKeyboardRepeat::doCancelRepeat()
 	{
 	iRepeating=ERepeatNone;
 	iThis->Cancel();
 	}
 
+/**
+Cancel any key repeat associated with the specified window group
+
+@param	aRepeatFocus	Destination window group or NULL for all
+*/
 void CKeyboardRepeat::CancelRepeat(CWsWindowGroup *aRepeatFocus)
 	{
-	if (aRepeatFocus==NULL || aRepeatFocus==iFocus)
+	if (iRepeating != ERepeatNone)
 		{
-		if (iRepeating)
-			doCancelRepeat();
-		iAlternateRepeatExists=EFalse;
-		}
-	else if (iRepeating >= ERepeatLong)
-		{
-		// Defensive programming - iLongCapture should never be NULL if iRepeating >= ERepeatLong
-		if (iLongCapture && iLongCapture->iWindowGroup == aRepeatFocus)
+		if (aRepeatFocus == NULL ||
+			(iRepeating == ERepeatNormal) && (aRepeatFocus == iCurrentRepeat.iOutput.iWindowGroup) ||
+			(iRepeating >= ERepeatLong) && (aRepeatFocus == iLongRepeat.iOutput.iWindowGroup))
 			{
 			doCancelRepeat();
 			iAlternateRepeatExists=EFalse;
@@ -1545,36 +1800,38 @@
 		}
 	}
 
-void CKeyboardRepeat::CancelRepeat(CWsWindowGroup *aRepeatFocus,TUint aScanCode,TBool aLongCaptureFlag,TUint aModifiers)
+/**
+Cancel any key repeat associated with the specified capture handle
+
+@param	aCaptureHandle		Handle to capture request
+@param	aLongCaptureFlag	ETrue for long key capture, EFalse for normal key
+*/
+void CKeyboardRepeat::CancelRepeat(const TAny* aCaptureHandle, TBool aLongCaptureFlag)
 	{
 	if (aLongCaptureFlag)
 		{
-		// long capture key is cancelled
-		if (iRepeating >= ERepeatLong && iCurrentRepeat.iScanCode==aScanCode)			
-				{
-				// Defensive programming - iLongCapture should never be NULL if iRepeating >= ERepeatLong
-				if (iLongCapture && aRepeatFocus == iLongCapture->iWindowGroup &&
-					(aModifiers & iLongCapture->iData.modifierMask) == iLongCapture->iData.modifiers)
-					{
-					doCancelRepeat();
-					iAlternateRepeatExists=EFalse;
-					}
-				}
+		// Cancel repeat for long capture key
+		if (iRepeating >= ERepeatLong && aCaptureHandle == iLongRepeat.iOutput.iCaptureHandle)
+			{
+			doCancelRepeat();
+			iAlternateRepeatExists=EFalse;
+			}
 		}
 	else
 		{
-		// normal capture key is cancelled
-		if (aRepeatFocus==iFocus)
+		// Cancel repeat for normal capture key
+		if (iRepeating == ERepeatNormal && aCaptureHandle == iCurrentRepeat.iOutput.iCaptureHandle)
 			{
-			if (iRepeating>=ERepeatNormal && iCurrentRepeat.iScanCode==aScanCode)
-				{
-				doCancelRepeat();
-				}
+			doCancelRepeat();
 			iAlternateRepeatExists=EFalse;
 			}
 		}
 	}
 	
+/**
+Process a key down event during key repeat.
+The current repeat data is saved for possible restoration after rollover.
+*/
 void CKeyboardRepeat::KeyDown()
 	{
 	if (iRepeating!=ERepeatNone)
@@ -1588,18 +1845,26 @@
 		}
 	}
 
+/**
+Process a key up event during key repeat.
+Send delayed short key event if necessary for long key event processing.
+Switch to alternate repeat if rollover key was released.
+
+@param	aScanCode	Scan code
+*/
 void CKeyboardRepeat::KeyUp(TInt aScanCode)
 	{
-	if (iAlternateRepeatExists && iAlternateRepeat.iScanCode==aScanCode)
+	if (iAlternateRepeatExists && iAlternateRepeat.iInputScanCode == aScanCode)
 		iAlternateRepeatExists=EFalse;
-	if (iRepeating!=ERepeatNone && iCurrentRepeat.iScanCode==aScanCode)
+	if (iRepeating != ERepeatNone && iCurrentRepeat.iInputScanCode == aScanCode)
 		{
 		if (iRepeating==ERepeatLong)
 			{
 			// Defensive programming - iLongCapture should never be NULL if iRepeating >= ERepeatLong			
-			if (iLongCapture && !(iLongCapture->iData.flags&ELongCaptureShortEventImmediately))
+			WS_ASSERT_DEBUG(iLongCapture != NULL, EWsPanicKeyRepeat);
+			if (iLongCapture && !(iLongCapture->iFlags & ELongCaptureShortEventImmediately))
 				{
-				TWindowServerEvent::QueueKeyPress(iCurrentRepeat.iKey,iCurrentRepeat.iScanCode,NULL,EFalse,0);	
+				TWindowServerEvent::QueueKeyPress(iCurrentRepeat.iOutput, EFalse, 0);
 				}
 			}			
 		if (iAlternateRepeatExists)
--- a/windowing/windowserver/nga/SERVER/EVENT.H	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/EVENT.H	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-2010 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"
@@ -28,6 +28,7 @@
 #include "EVQUEUE.H"
 #include <w32adll.h>
 #include "Graphics/WSGRAPHICDRAWER.H"
+#include <graphics/wskeyrouter.h>
 
 class CWsClient;
 class CWsWindowBase;
@@ -78,8 +79,8 @@
 class TRepeatKey
 	{
 public:
-	TKeyData iKey;
-	TInt iScanCode;
+	TKeyEventRouterOutput iOutput;
+	TInt iInputScanCode;
 	};
 
 class CKeyboardRepeat : public CTimer
@@ -90,9 +91,9 @@
 	static void Destroy();
 	static void KeyDown();
 	static void KeyUp(TInt aScanCode);
-	static TBool StartRepeat(const TKeyData &aKey, TInt aScanCode, CWsWindowGroup *aRepeatFocus, CWsCaptureLongKey* longCapture);
+	static void StartRepeat(TInt aInputScanCode, const TKeyEventRouterOutput& aShortEvent, const TKeyEventRouterOutput* aLongEvent);
 	static void CancelRepeat(CWsWindowGroup *aRepeatFocus);
-	static void CancelRepeat(CWsWindowGroup *aRepeatFocus,TUint aScanCode,TBool aLongCaptureFlag,TUint aModifiers=0);
+	static void CancelRepeat(const TAny* aCaptureHandle, TBool aLongCaptureFlag);
 	static void SetRepeatTime(const TTimeIntervalMicroSeconds32 &aInitialTime, const TTimeIntervalMicroSeconds32 &aTime);
 	static void GetRepeatTime(TTimeIntervalMicroSeconds32 &aInitialTime, TTimeIntervalMicroSeconds32 &aTime);
 	static inline TBool IsAreadyActive();
@@ -108,13 +109,13 @@
 	static void doCancelRepeat();
 	void RunL();
 private:
-	static CWsWindowGroup *iFocus;
 	static CKeyboardRepeat *iThis; // Needed as CTimer derived parts can't be static
 	static TTimeIntervalMicroSeconds32 iInitialTime;
 	static TTimeIntervalMicroSeconds32 iTime;
+	static TRepeatType iRepeating;
 	static TRepeatKey iCurrentRepeat;
-	static TRepeatType iRepeating;
 	static TRepeatKey iAlternateRepeat;
+	static TRepeatKey iLongRepeat;
 	static TBool iAlternateRepeatExists;
 	static CWsCaptureLongKey* iLongCapture;
 	static TInt iRepeatRollover;
@@ -174,9 +175,9 @@
 	static CWsHotKey* ClearHotKeysL(TInt aHotKey);
 	static void ResetDefaultHotKeyL(TInt aHotKey);
 	static void SetHotKeyL(const TWsClCmdSetHotKey &aHotKey);
-	static void AddCaptureKeyL(const TCaptureKey &aCaptureKey);
-	static void SetCaptureKey(TUint32 aHandle, const TCaptureKey &aCaptureKey);
-	static void CancelCaptureKey(TUint32 aHandle);
+	static void AddCaptureKeyL(const TKeyCaptureRequest& aRequest);
+	static void UpdateCaptureKeyL(const TKeyCaptureRequest& aRequest);
+	static void CancelCaptureKey(TKeyCaptureType aType, TAny* aHandle);
 	static void ClientDestroyed(CWsClient *aClient);
 	static inline void AddToSwitchOnEventListL(const CWsWindowBase &aWindow, TEventControl aCircumstances);
 	static inline void RemoveFromSwitchOnEventList(const CWsWindowBase &aWindow);
@@ -207,7 +208,8 @@
 	static void SendScreenDeviceChangedEvent(const CWsWindowBase *aWindow);
 	static TBool ProcessErrorMessages(TWsErrorMessage::TErrorCategory aCategory, TInt aError);
 	static void NotifyOom();
-	static void QueueKeyPress(const TKeyData& aKey, TInt aScanCode, CWsWindowGroup* aRepeatFocus, TBool aCheckRepeat,TInt aRepeats);
+	static void ProcessKeyPress(const TKeyEvent& aKeyEvent, TBool aCheckRepeat,TInt aRepeats);
+	static void QueueKeyPress(const TKeyEventRouterOutput& aOutput, TBool aIsRepeat, TInt aRepeats);
 	static void AddEventHandler(MEventHandler *aEventHandler, TBool aAdvancedPointersEnabled);
 	static void RemoveEventHandler(const MEventHandler *aEventHandler);
 	static void PotentialEventHandlerL(TInt aNum);
@@ -250,6 +252,8 @@
 	static TEventRequestQueue iScreenDeviceChangedQueue;
 	static TTime iPrevOomMessageTime;
 	static CCaptureKeys *iCaptureKeys;
+	static CKeyEventRouter *iKeyEventRouter;
+	static RLibrary iKeyEventRouterLibrary;
 	static CWsHotKey *iHotKeys;
 	static TInt iModifierState;
 	static CRawEventReceiver *iEventReceiver;
--- a/windowing/windowserver/nga/SERVER/PRIKEY.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/PRIKEY.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -23,7 +23,7 @@
 	__DECLARE_NAME(_S("CPriorityKey"));
 	}
 
-void CPriorityKey::PriorityKey(TInt aHandle, const TKeyData &aKey, TInt aScanCode)
+void CPriorityKey::PriorityKey(TInt aHandle, const TKeyEvent &aKeyEvent)
 //
 // Called when a priority key is pressed
 //
@@ -31,8 +31,7 @@
 	if (!iEventMsg.IsNull())
 		{
 		iPriorityKeyHandle=aHandle;
-		iPriorityKey=aKey;
-		iScanCode=aScanCode;
+		iPriorityKey = aKeyEvent;
 		SignalEvent();
 		}
 	}
@@ -43,11 +42,8 @@
 //
 	{
 	TWsPriorityKeyEvent event;
-	TKeyEvent *key=event.Key();
-	key->iScanCode=iScanCode;
-	key->iCode=iPriorityKey.iKeyCode;
-	key->iModifiers=iPriorityKey.iModifiers;
-	key->iRepeats=0;
+	*event.Key() = iPriorityKey;
+	event.Key()->iRepeats = 0;
 	event.SetHandle(iPriorityKeyHandle);
 	CEventBase::GetData(&event,sizeof(event));
 	iPriorityKeyHandle=0;
@@ -65,7 +61,7 @@
 	return(iKeyCode==aKeycode && iModifierMask==aModifierMask && iModifiers==aModifiers);
 	}
 
-TInt TPriorityKey::KeyMatches(const TKeyData &aKey)
+TInt TPriorityKey::KeyMatches(const TKeyEvent &aKeyEvent)
 	{
-	return(iKeyCode==aKey.iKeyCode && (iModifierMask&aKey.iModifiers)==iModifiers);
+	return(iKeyCode == aKeyEvent.iCode && (iModifierMask & aKeyEvent.iModifiers) == iModifiers);
 	}
--- a/windowing/windowserver/nga/SERVER/PRIKEY.H	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/PRIKEY.H	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-2010 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"
@@ -37,7 +37,7 @@
 public:
 	TPriorityKey(TUint aKeycode,TUint aModifierMask,TUint aModifiers,TPriorityKey *aPriorityKeys);
 	TInt Equals(TUint aKeycode,TUint aModifierMask,TUint aModifiers);
-	TInt KeyMatches(const TKeyData &aKey);
+	TInt KeyMatches(const TKeyEvent &aKeyEvent);
 public:
 	TPriorityKey *iNext;
 private:
@@ -50,12 +50,11 @@
 	{
 public:
 	CPriorityKey(CWsClient *aOwner);
-	void PriorityKey(TInt aHandle, const TKeyData &aKey, TInt aScanCode);
+	void PriorityKey(TInt aHandle, const TKeyEvent &aKeyEvent);
 	void GetData();
 private:
 	TInt iPriorityKeyHandle;
-	TKeyData iPriorityKey;
-	TInt iScanCode;
+	TKeyEvent iPriorityKey;
 	};
 
 #endif
--- a/windowing/windowserver/nga/SERVER/openwfc/CLIENT.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/openwfc/CLIENT.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1286,6 +1286,9 @@
 		case EWsClOpCreateDrawableSource:
 			CreateDrawableSourceL(*pData.CreateDrawableSource);
 			break;
+		case EWsClOpIndicateAppOrientation:
+			IndicateAppOrientation(*pData.Orientation);
+			break;
 		default:
 			PPanic(EWservPanicOpcode);
 			break;
@@ -2138,6 +2141,17 @@
 	drawableSource->ConstructL(aDrawableSourceData);
 	CleanupStack::Pop();
 	}
+	
+void CWsClient::IndicateAppOrientation(TRenderOrientation aOrientation)
+	{
+	iIndicatedAppOrientation = aOrientation;
+	CWsTop::CheckRenderOrientation();
+	}
+
+TInt CWsClient::GetIndicatedAppOrientation()
+	{
+	return iIndicatedAppOrientation;
+	}
 
 //
 // class CWsCliObj
--- a/windowing/windowserver/nga/SERVER/openwfc/CLIENT.H	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/openwfc/CLIENT.H	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-2010 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"
@@ -146,7 +146,7 @@
 	inline void PurgePointerEvents();
 
 	// Key events
-	inline void PriorityKeyPressed(TInt aHandle, const TKeyData &aKey, TInt aScanCode);
+	inline void PriorityKeyPressed(TInt aHandle, const TKeyEvent &aKeyEvent);
 
 	// Notification of misc events
 	void AddNotificationL(TInt aKey, const RMessage2& aClientMsg);
@@ -168,6 +168,9 @@
 	TBool RetryEvent(TEventCode aEventCode);
 
     inline void WgMsgQueueOverflow();// Set flag  window group message queue is overflow and has pending messages
+    
+    //Get orientation value that app indicated
+    TInt GetIndicatedAppOrientation();
 
 private: // from MWsClient
 	TInt SendMessage(const CWsGraphicDrawer* aOnBehalfOf, const TDesC8& aData);
@@ -255,6 +258,10 @@
 	
 	// Misc
 	void SetComputeMode(RWsSession::TComputeMode aComputeMode);
+	
+	//Set orientation that application indicated
+	void IndicateAppOrientation(TRenderOrientation aOrientation);
+	
 public:
 	static TWsCmdHeaderBase iCurrentCommand;
 private:
@@ -293,6 +300,7 @@
 	RMessage2 iClientMessage;
 	RHandleBase* iResponseHandle;
 	TInt iMessageIdSeq;
+	TInt iIndicatedAppOrientation;
 
 	//Members for procerssing command buffer
 	static CWsClient* iCurrentClient;	// Client who's buffer is currently being processed
@@ -363,8 +371,8 @@
 inline void CWsClient::HandleClientRequestForPriorityKeyData()
 	{iPriorityKeyEvent->GetData();}
 
-inline void CWsClient::PriorityKeyPressed(TInt aHandle, const TKeyData &aKey, TInt aScanCode)
-	{iPriorityKeyEvent->PriorityKey(aHandle,aKey,aScanCode);}
+inline void CWsClient::PriorityKeyPressed(TInt aHandle, const TKeyEvent &aKeyEvent)
+	{iPriorityKeyEvent->PriorityKey(aHandle, aKeyEvent);}
 
 inline TInt CWsClient::ObjectHandle(const CWsObject* aThis) const
 	{return(iObjectIndex->At(aThis));}
--- a/windowing/windowserver/nga/SERVER/openwfc/GROUPWIN.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/openwfc/GROUPWIN.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1995-2010 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"
@@ -515,9 +515,8 @@
 					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt, WS_HANDLE_CAPTURE_KEY);
 					if (destroyObj)
 						{
-						//Cancel any repeat that is underway for this key
-						const TWsWinCmdCaptureKey& capKey(*pData.CaptureKey);
-						CKeyboardRepeat::CancelRepeat(this,capKey.key,EFalse,capKey.modifierMask);
+						// Cancel any repeat that is underway for this capture
+						CKeyboardRepeat::CancelRepeat(destroyObj, EFalse);
 						delete destroyObj;
 						}
 					else
@@ -535,9 +534,6 @@
 					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt, WS_HANDLE_CAPTURE_KEY_UPDOWNS);
 					if (destroyObj)
 						{
-						//Cancel any repeat that is underway for this key
-						const TWsWinCmdCaptureKey& capKey(*pData.CaptureKey);
-						CKeyboardRepeat::CancelRepeat(this,capKey.key,EFalse,capKey.modifierMask);
 						delete destroyObj;
 						}
 					else
@@ -555,9 +551,8 @@
 					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt, WS_HANDLE_CAPTURE_LONG_KEY);
 					if (destroyObj)
 						{
-						//Cancel any repeat that is underway for this key
-						const TWsWinCmdCaptureLongKey& capKey(*pData.CaptureLongKey);
-						CKeyboardRepeat::CancelRepeat(this,capKey.inputKey,ETrue,capKey.modifierMask);
+						// Cancel any repeat that is underway for this capture
+						CKeyboardRepeat::CancelRepeat(destroyObj, ETrue);
 						delete destroyObj;
 						} 
 					else
@@ -906,6 +901,12 @@
 TBool CWsWindowGroup::SetOrdinalPosition(TInt aPos,CWsWindowGroup* aClosingWindow)
 	{
 	TBool ret=ETrue;
+	
+	// Remember if the window group tree is actually changed or not, so that we know whether to 
+	// check the render orientation after the re-ordering is done ( see CWsTop::CheckRenderOrientation()
+	// call at end of this method
+	TBool changed = CheckOrdinalPositionChange(aPos);	
+	
 	if (!iQueue)
 		ret=DoSetOrdinalPosition1(aPos,aClosingWindow);
 	else
@@ -962,6 +963,11 @@
 #endif
 		}
 
+	// If the ordinal positions have changed, check to see if there is a new render orientation
+	// and publish it if so
+	if(changed)
+	    CWsTop::CheckRenderOrientation();
+	
 	return ret;
 	}
 
@@ -1348,13 +1354,13 @@
 		}
 	}
 
-TBool CWsWindowGroup::CheckForPriorityKey(const TKeyData &aKey, TInt aScanCode)
+TBool CWsWindowGroup::CheckForPriorityKey(const TKeyEvent &aKeyEvent)
 	{
 	for(TPriorityKey *pk=iPriorityKeys;pk;pk=pk->iNext)
 		{
-		if (pk->KeyMatches(aKey))
+		if (pk->KeyMatches(aKeyEvent))
 			{	
-			WsOwner()->PriorityKeyPressed(ClientHandle(),aKey, aScanCode);
+			WsOwner()->PriorityKeyPressed(ClientHandle(), aKeyEvent);
 			return(ETrue);
 			}
 		}
--- a/windowing/windowserver/nga/SERVER/openwfc/WSTOP.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/openwfc/WSTOP.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -46,6 +46,7 @@
 #include "registeredsurfacemap.h"
 #include "windowelementset.h"
 #include "wspluginmanager.h"
+#include "renderorientationtracker.h"
 
 // IDs of p&s properties that optionally contain callbacks that may be used
 // to release singletons owned by libraries at shutdown in order to make 
@@ -209,6 +210,7 @@
 TInt CWsTop::iCheckHeapResult=KErrNotReady;
 TBool CWsTop::iDoHeapCheckAndRestart=EFalse;
 #define RFbsSession_SendCommand_ShutDownMessage 1	// A FBS message that is not published yet and probably never will be.
+CWsRenderOrienationTracker* CWsTop::iRenderOrientationTracker=NULL;
 
 static void DefineSingletonKey(const TUid& aSingletonKey)
 /**
@@ -281,6 +283,8 @@
 void CWsTop::DeleteStaticsL()
 	{
 	iShuttingDown=ETrue;
+	delete iRenderOrientationTracker;	
+	
 	CClick::DeleteStatics();
 	TWsPointer::Stop();
 	CWsClient::DeleteStatics();
@@ -553,6 +557,8 @@
 		StartShell();
 		}
 	UserSvr::WsRegisterSwitchOnScreenHandling(ETrue);
+	
+	iRenderOrientationTracker = CWsRenderOrienationTracker::NewL();	
 	}
 
 
@@ -958,6 +964,18 @@
 	return EFalse;
 	}
 
+/**
+Checks to see if the render orientation has changed, and publishes any new orientaion
+via publish and subscribe
+
+@see KRenderOrientationCategory
+@see KRenderOrientationKey 
+*/
+void CWsTop::CheckRenderOrientation()
+    {
+    iRenderOrientationTracker->CheckRenderOrientation();
+    }
+
 typedef TInt (*ShellEntryPoint)(TAny *);
 
 #if defined(__WINS__)
--- a/windowing/windowserver/nga/SERVER/openwfc/server.h	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/openwfc/server.h	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1999-2010 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"
@@ -27,7 +27,9 @@
 #include "OBJECT.H"
 #include "CLIENT.H"
 #include "ScrDev.H"
+#include <graphics/wskeyrouter.h>
 #include <Graphics/WSGRAPHICDRAWERINTERFACE.H>
+#include "Graphics/wsgraphicdrawerinternal.h"
 #include "WSGRAPHICDRAWERARRAY.H"
 #include "panics.h"
 
@@ -150,7 +152,7 @@
 	inline CWsWindowGroup *WindowGroup();
 	inline const CWsWindowGroup *WindowGroup() const;
 private:
-	void CmdToParams(const TWsWinCmdCaptureKey &aCaptureKey, TCaptureKey &aParams);
+	void CmdToRequest(const TWsWinCmdCaptureKey &aCaptureKey, TKeyCaptureRequest &aParams);
 private:
 	CWsWindowGroup *iWindowGroup;
 	};
@@ -181,21 +183,16 @@
 	~CWsCaptureKeyUpsAndDowns();
 	void ConstructL(const TWsWinCmdCaptureKey &aCaptureKey);
 	void CommandL(TInt aOpcode, const TAny *aCmdData);
-	static CWsWindowGroup *CheckForCapture(TUint aScanCode, TUint aModifiers);
 	inline CWsWindowGroup *WindowGroup();
 	inline const CWsWindowGroup *WindowGroup() const;
 private:
-	TUint iModifierValue;
-	TUint iModifierMask;
-	TUint iScanCode;
-	static TPriQue<CWsCaptureKeyUpsAndDowns> iCaptureKeysUpsAndDowns;
-	TPriQueLink iLink;
 	CWsWindowGroup *iWindowGroup;
 	};
 
 class CWsCaptureLongKey : public CWsObject
 	{
 	friend class CKeyboardRepeat;
+	friend class TWindowServerEvent;
 public:
 	CWsCaptureLongKey(CWsWindowGroup *owner);
 	~CWsCaptureLongKey();
@@ -203,13 +200,10 @@
 	void CommandL(TInt aOpcode, const TAny *aCmdData);
 	inline CWsWindowGroup *WindowGroup();
 	inline const CWsWindowGroup *WindowGroup() const;
-	static CWsCaptureLongKey* CheckForCapture(TUint aKeyCode, TInt aModifiers);
-public:
-	static TPriQue<CWsCaptureLongKey> iCaptureLongKeys;
 private:
-	TPriQueLink iLink;
+	TTimeIntervalMicroSeconds32 iDelay;
+	TUint iFlags;
 	CWsWindowGroup *iWindowGroup;
-	TWsWinCmdCaptureLongKey iData;
 	};
 
 //--------------------------------
@@ -340,6 +334,7 @@
 	void StartL();
 	TInt SessionCount();
 	MWsAnimationScheduler* AnimationScheduler();
+	void PrepareShutdown();
 	TBool ReleaseMemory();
 	void DestroySessionsForShutdown();
 	void SetPinClientDescriptors(TBool aPin);
--- a/windowing/windowserver/nga/SERVER/openwfc/wstop.h	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/openwfc/wstop.h	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2003-2010 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"
@@ -56,6 +56,7 @@
 #endif
 	};
 
+class CWsRenderOrienationTracker;
 class CWsTop
 	{
 	enum {EShellBootModeReboot=0,EShellBootModeNoReboot=1,EShellBootModeExit=2};
@@ -122,6 +123,7 @@
 	static TBool MultiFocusPolicy();
 	
 	static inline CWsPluginManager *PluginManager();
+	static void CheckRenderOrientation();
 	
 private:
 	static void InitLogging();
@@ -152,6 +154,7 @@
 	static TInt iCheckHeapResult;
 	static TBool iDoHeapCheckAndRestart;
 	static CWsPluginManager *iPluginManager;
+    static CWsRenderOrienationTracker* iRenderOrientationTracker;	
 	};
 	
 NONSHARABLE_CLASS(CWsActiveScheduler): public CActiveScheduler, public MWsActiveSchedulerDebug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/renderorientationtracker.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,567 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This material, including documentation and any related
+// computer programs, is protected by copyright controlled by
+// Nokia. All rights are reserved. Copying, including
+// reproducing, storing, adapting or translating, any
+// or all of this material requires the prior written consent of
+// Nokia. This material also contains confidential
+// information which may not be disclosed to others without the
+// prior written consent of Nokia.
+//
+// Description:
+// Render Orientation Tracking and Publication
+// 
+
+#include <hal.h>
+#include <e32std.h>
+#include "renderorientationtracker.h"
+#include "rootwin.h"
+#include "windowgroup.h"
+#include "wstop.h"
+#include "..\debuglog\DEBUGLOG.H"
+
+extern CDebugLogBase* wsDebugLog;
+
+/** Convert a TRenderOrientation value into a TDigitiserOrientation.
+Note: The algorithm used makes use of the ordering of the values of the respective enums, 
+thus this is checked for (at compile time) at the start of the function.
+@param aWservOrientation A value from the TRenderOrientation enums.
+@return The equivalent value from the TDigitiserOrientation enums.
+*/
+inline HALData::TDigitiserOrientation WservToDigitiser(TRenderOrientation aWservOrientation)
+	{
+	__ASSERT_COMPILE(EDisplayOrientationNormal+1 == EDisplayOrientation90CW);
+	__ASSERT_COMPILE(EDisplayOrientationNormal+2 == EDisplayOrientation180);
+	__ASSERT_COMPILE(EDisplayOrientationNormal+3 == EDisplayOrientation270CW);
+	__ASSERT_COMPILE(HALData::EDigitiserOrientation_000+1 == HALData::EDigitiserOrientation_090);
+	__ASSERT_COMPILE(HALData::EDigitiserOrientation_000+2 == HALData::EDigitiserOrientation_180);
+	__ASSERT_COMPILE(HALData::EDigitiserOrientation_000+3 == HALData::EDigitiserOrientation_270);
+	HALData::TDigitiserOrientation ret=static_cast<HALData::TDigitiserOrientation>
+			(HALData::EDigitiserOrientation_000 + (aWservOrientation - EDisplayOrientationNormal));
+	return ret;
+	}
+
+// Todo remove/undefine this for release
+#define TECHVIEW_TESTMODE
+
+CWsRenderOrienationTracker* CWsRenderOrienationTracker::NewL()
+    {
+    CWsRenderOrienationTracker* self = new(ELeave)CWsRenderOrienationTracker();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+CWsRenderOrienationTracker::CWsRenderOrienationTracker()
+    : CActive(CActive::EPriorityStandard),
+      iRenderOrientationTrackingType(EDisplayOrientationNormal),
+      iPublishedRenderOrientation(EDisplayOrientationNormal)
+    {
+    CActiveScheduler::Add(this);    
+    }
+
+void CWsRenderOrienationTracker::ConstructL()
+    {    
+    const TSecurityPolicy   KRenderOrientationReadSecurityPolicy(ECapability_None);
+    const TSecurityPolicy   KRenderOrientationWriteSecurityPolicy(ECapabilityWriteDeviceData);
+    
+    // Define P&S Property to publish to
+    TInt error = RProperty::Define( KRenderOrientationCategory,
+                                    KRenderOrientationKey,
+                                    RProperty::EInt,
+                                    KRenderOrientationReadSecurityPolicy,
+                                    KRenderOrientationWriteSecurityPolicy);
+
+    // Attach the publisher for real-time publishing
+    if(KErrNone == error)
+        error = iRenderOrientationPublisher.Attach( KRenderOrientationCategory,
+                                                    KRenderOrientationKey);
+
+    // Publish the initial value
+    if(KErrNone == error)    
+        error = DoPublishOrientation(EDisplayOrientationNormal);
+    
+    //Set the initial value to HAL
+    if(KErrNone == error)
+        SetHALOrientation(EDisplayOrientationNormal);
+    
+    if (wsDebugLog && KErrNone!=error)
+        {
+        _LIT(logText,"Orientation Tracker: failed to initialise with error %d");
+        wsDebugLog->MiscMessage(CDebugLogBase::ELogImportant,logText,error);
+        }    
+    User::LeaveIfError(error);
+    }
+
+CWsRenderOrienationTracker::~CWsRenderOrienationTracker()
+    {
+    Cancel();
+    iRenderOrientationPublisher.Delete(KRenderOrientationCategory, KRenderOrientationKey);
+    iRenderOrientationPublisher.Close();
+    }
+
+/**
+If the orientation of the given window group is useable updates aOrientationTrackingType with the orientation
+
+@param Input: the window group to check
+@param Output: the window group's orientation if usable ( otherwise unchanged )
+@return KErrNone if the orienation is usable, KErrNotFound if the orientation is not useable, KErrNotSupported if the orientation is unknown
+*/
+TInt CWsRenderOrienationTracker::CheckWindowGroupOrientation(const CWsWindowGroup& aWinGroup, TRenderOrientationTrackingType& aOrientationTrackingType)
+    {
+    TInt error = KErrNone;
+    TRenderOrientationTrackingType tempOrientationTrackingType = static_cast<TRenderOrientationTrackingType>(aWinGroup.WsOwner()->GetIndicatedAppOrientation());
+    switch(tempOrientationTrackingType)
+        {
+        case EDisplayOrientationNormal:
+        case EDisplayOrientation90CW:                
+        case EDisplayOrientation180:
+        case EDisplayOrientation270CW:            
+        case EDisplayOrientationAuto:
+            aOrientationTrackingType = tempOrientationTrackingType;
+            break;
+
+        case EDisplayOrientationIgnore:
+            error = KErrNotFound;
+            if (wsDebugLog)
+                {
+                _LIT(logText,"Orientation Tracker: winGroup %08x orientation is set to be ignored");
+                wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,logText,reinterpret_cast<TInt>(&aWinGroup));
+                }            
+            break;
+
+        default:
+            error = KErrNotSupported;
+            if (wsDebugLog)
+                {
+                _LIT(logText,"Orientation Tracker: winGroup %08x has undefined orientation, Error %d");                
+                TBuf<LogTBufSize> buf;
+                buf.Format(logText, &aWinGroup, error);                
+                wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate,buf);
+                }                          
+            break;             
+        }
+    
+    return error;
+    }
+
+/**
+Checks that the given group window is appropriate for dictating the render orientation
+
+@param Input:  The group window to check
+@return ETrue is the group window is usable, else EFalse  
+*/
+TBool CWsRenderOrienationTracker::UseableGroupWindow(const CWsWindowGroup& aWinGroup) const
+    {
+#ifdef TECHVIEW_TESTMODE
+    // for some reason IsFocusable seems to return 0 and 2, not 0 and 1
+    return NULL!=aWinGroup.Child() &&
+            (aWinGroup.IsFocusable() ? ETrue : EFalse);
+#else    
+    return (NULL!=aWinGroup.Child());     
+#endif
+    }
+
+/**
+Finds the topmost usable windowgroup which has a usable orientation, and outputs that orientation
+
+@param Output: The current render orientation
+@return KErrNone if successful, KErrNotFound if the focus window group is not usable, KErrNotSupported if an invalid orientation is found
+*/
+TInt CWsRenderOrienationTracker::GetFocusWindowOrientation(TRenderOrientationTrackingType& aOrientationTrackingType)
+    {
+    TInt error = KErrNone;
+    CWsWindowGroup* focusWinGroup = CWsTop::FocusWindowGroup();    
+    if(!focusWinGroup)
+        {
+        _LIT(logText,"Orientation Tracker: focusWinGroup not found");
+        wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,logText);
+        error = KErrNotFound;
+        }
+    else
+        {
+        error = CheckWindowGroupOrientation(*focusWinGroup, aOrientationTrackingType);
+        }
+    return error;
+    }
+
+/**
+Finds the topmost usable windowgroup which has a usable orientation, and outputs that orientation
+
+@param Output: The current render orientation
+@return KErrNone if successful, KErrNotSupported if an invalid orientation is found
+*/
+TInt CWsRenderOrienationTracker::FindOrientationFromWindowTree(TRenderOrientationTrackingType& aOrientationTrackingType)
+    {
+    TInt error = KErrNone;
+    TRenderOrientationTrackingType tempOrientationTrackingType = iRenderOrientationTrackingType;
+    CWsRootWindow* rootWin = CWsTop::CurrentFocusScreen()->RootWindow();
+    TBool finished = EFalse;
+    for(CWsWindowGroup* winGroup = rootWin->Child(); !finished && NULL != winGroup; winGroup = winGroup->NextSibling())
+        {
+        if (wsDebugLog)
+            {
+            _LIT(logText,"Orientation Tracker: winGroup %08x has priority %d, Orientation %d, Focusable %d, Child %08x");
+            TBuf<LogTBufSize> buf;
+            buf.Format(logText, winGroup, winGroup->OrdinalPriority(), winGroup->WsOwner()->GetIndicatedAppOrientation(),
+                    winGroup->IsFocusable()?ETrue:EFalse, winGroup->Child());                                
+            wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,buf);
+            }               
+        // winGroup is a higher priority ordinal, so see if it has an orientation that can be used
+        // although we're only interested in window groups with child windows otherwise nothing is visible anyway        
+        if(UseableGroupWindow(*winGroup))
+            {
+            error = CheckWindowGroupOrientation(*winGroup, tempOrientationTrackingType);
+            switch(error)
+                {
+                case KErrNone:
+                    {
+                    // List is in order, so just find the first one
+                    if (wsDebugLog)
+                        {
+                        _LIT(logText,"Orientation Tracker: Found winGroup %08x with Orientation %d");
+                        TBuf<LogTBufSize> buf;
+                        buf.Format(logText, winGroup, winGroup->WsOwner()->GetIndicatedAppOrientation());                    
+                        wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,buf);
+                        }
+                    finished = ETrue;
+                    break;
+                    }
+
+                case KErrNotFound:
+                    // so keep searching
+                    break;                    
+                    
+                case KErrNotSupported:
+                default:
+                    finished = ETrue;
+                    break;
+                    
+                }
+            
+            }
+        }
+    // Safe even in error code as won't have been changed by CheckWindowGroupOrientation
+    aOrientationTrackingType = tempOrientationTrackingType;
+    
+    return error;
+    }
+
+/**
+First checks to see if the focus window group has a usable orientation, if so that is output.
+Otherwise, finds the topmost usable windowgroup which has a usable orientation, and outputs that
+
+@param Output: The current render orientation
+@return KErrNone if successful, KErrNotSupported if an invalid orientation is found 
+ */
+TInt CWsRenderOrienationTracker::GetIndicatedOrientation(TRenderOrientationTrackingType& aOrientationTrackingType)
+    {
+    // First check the focus window group
+    TInt error = GetFocusWindowOrientation(aOrientationTrackingType);
+
+    // Don't look for another window if the focus window is usable
+    // or if an error has occured, then don't change current orientation
+    switch(error)
+        {
+        case KErrNone:
+            {
+            if(wsDebugLog)
+                {
+                _LIT(logText,"Orientation Tracker: Using focus window %08x for orientation");
+                wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,logText,reinterpret_cast<TInt>(CWsTop::FocusWindowGroup()));
+                }
+            break;
+            }
+        
+        case KErrNotFound:
+            {
+            // Can't use focus window group, so find the topmost windowgroup with a valid orientation
+            error = FindOrientationFromWindowTree(aOrientationTrackingType);
+            break;
+            }
+            
+        default:
+            // Unrecoverable error, abort and leave published orientation unchanged
+            break;
+        }
+    
+    return error;
+    }
+
+/**
+Checks to see if the render orientation has changed, and publishes any new orientaion
+via publish and subscribe
+
+@see KRenderOrientationCategory
+@see KRenderOrientationKey 
+*/
+void CWsRenderOrienationTracker::CheckRenderOrientation()
+    {
+    TRenderOrientationTrackingType newOrientationTrackingType = iRenderOrientationTrackingType;    
+    TInt error = GetIndicatedOrientation(newOrientationTrackingType);
+
+    // if the tracking type has changed...
+    if(KErrNone == error && iRenderOrientationTrackingType != newOrientationTrackingType)
+        {
+        if(EDisplayOrientationAuto == iRenderOrientationTrackingType)
+            {
+            // change from auto type, so we need to cancel request for updates from the theme server        
+            Cancel();
+            }    
+        iRenderOrientationTrackingType = newOrientationTrackingType;
+        if(EDisplayOrientationAuto == iRenderOrientationTrackingType)
+            {
+            // Change to auto type, so we need to request updates from the theme server            
+            // Attach to the Theme server to get orientation change updates
+            error = iThemeOrientationProperty.Attach( KThemeOrientationCategory, KThemeOrientationKey );
+            if (wsDebugLog)
+                {
+                if(KErrNone == error)
+                    {
+                    // Information Log
+                    _LIT(logText,"Orientation Tracker: Attached to theme orientation property");
+                    wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,logText);
+                    }
+                else
+                    {
+                    // Error Log
+                    _LIT(logText,"Orientation Tracker: Error %d attaching to theme orientation property");
+                    wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate,logText, error);                
+                    }
+                }              
+            
+            RequestDeviceOrientationNotification();
+            }
+        // See if the  has changed, and publish if it has        
+        error = DoOrientationTracking();
+        }
+
+    if (wsDebugLog && KErrNone != error)
+        {
+        _LIT(logText,"Orientation Tracker: Error %d Checking Render Orientation");
+        wsDebugLog->MiscMessage(CDebugLogBase::ELogImportant,logText, error);
+        }  
+    }
+
+/**
+Requests notification of change of the theme server orientation
+
+@Pre iThemeOrientationProperty has had Attach called on it
+*/
+void CWsRenderOrienationTracker::RequestDeviceOrientationNotification()
+    {
+    if(!IsActive())
+        {
+        if (wsDebugLog)
+            {
+            _LIT(logText,"Orientation Tracker: Subscribing to theme orientation property");
+            wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,logText);
+            }          
+        // Request for Theme Server Orientation P&S  
+        iThemeOrientationProperty.Subscribe(iStatus);        
+        SetActive();
+        }
+    }
+
+/**
+Cancels and closes (detaches) from the theme orientation publish and subscribe
+*/
+void CWsRenderOrienationTracker::CancelDeviceOrientationNotification()
+    {
+    // Cancel Request for Theme Server Orientation P&S  
+    iThemeOrientationProperty.Cancel();
+    iThemeOrientationProperty.Close();
+    
+    if (wsDebugLog)
+        {
+        _LIT(logText,"Orientation Tracker: Cancelled/closed theme orientation property");
+        wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,logText);
+        }      
+    }
+
+/**
+Called when the theme servers orientation has changed.
+Re-requests unless cancelled
+*/
+void CWsRenderOrienationTracker::RunL()
+    {
+    TInt error = iStatus.Int();
+    if(KErrNone == error)
+        {
+        // Re-request
+        RequestDeviceOrientationNotification();
+    
+        TInt error = DoOrientationTracking();
+        if (wsDebugLog && KErrNone != error)
+            {
+            _LIT(logText,"Orientation Tracker: Error %d processing theme orientation property");
+            wsDebugLog->MiscMessage(CDebugLogBase::ELogImportant,logText, error);
+            }         
+        }
+    else if (wsDebugLog && KErrCancel != error)
+        {
+        _LIT(logText,"Orientation Tracker: Error %d from theme orientation property, not resubscribed");
+        wsDebugLog->MiscMessage(CDebugLogBase::ELogImportant,logText, error);     
+        }
+    }
+
+/**
+Cancels the request for notification for changes to theme orientation
+*/
+void CWsRenderOrienationTracker::DoCancel()
+    {
+    CancelDeviceOrientationNotification();
+    }
+
+/**
+Gets the orientation published from theme server
+
+@param Output: the theme server orientation
+@return KErrNone if successful, KErrNotSupported if the theme server returns an unknown orientation, else any of the system wide error codes 
+*/
+TInt CWsRenderOrienationTracker::GetThemeOrientation(TRenderOrientation& aThemeOrientation)
+    { 
+    TInt themeOrientation=EDisplayOrientationNormal;
+    TInt error = iThemeOrientationProperty.Get(themeOrientation);
+    if(wsDebugLog && KErrNone != error)
+        {
+        _LIT(logText,"Orientation Tracker: Error %d getting theme orientation property");
+        wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate,logText, error);     
+        }
+    
+    if(KErrNone == error)
+        {
+        // Translate the received orientation    
+        switch(themeOrientation)
+            {           
+            case EDisplayOrientationNormal:
+            case EDisplayOrientation90CW:
+            case EDisplayOrientation180:
+            case EDisplayOrientation270CW:
+                // only update if orientation is supported
+                aThemeOrientation = static_cast<TRenderOrientation>(themeOrientation);
+                break;
+            
+            default:
+                error = KErrNotSupported;
+                if (wsDebugLog)
+                    {
+                    _LIT(logText,"Orientation Tracker: Unsupported orientation %d from theme orientation property, Error %d");
+                    TBuf<LogTBufSize> buf;
+                    buf.Format(logText, themeOrientation, error);
+                    wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate,buf);     
+                    }                
+                break;
+            }
+        }
+    return error;  
+    }
+
+/**
+Processes the indicated orientation into an actual orientation
+
+@return KErrNone for success, KErrNotSupported if the orientation is unknown, else any of the system wide error codes
+*/
+TInt CWsRenderOrienationTracker::DoOrientationTracking()
+    {
+    TInt error = KErrNone;
+    TRenderOrientation newDeviceOrientation;
+    switch(iRenderOrientationTrackingType)
+        {
+        case EDisplayOrientationNormal:
+        case EDisplayOrientation90CW:                
+        case EDisplayOrientation180:
+        case EDisplayOrientation270CW:            
+            newDeviceOrientation = iRenderOrientationTrackingType;
+            break;
+            
+        case EDisplayOrientationAuto:
+            error = GetThemeOrientation(newDeviceOrientation);
+            break;
+                      
+        default:
+            error = KErrNotSupported;
+            if (wsDebugLog)
+                {
+                _LIT(logText,"Orientation Tracker: Unsupported orientation tracking type %d, error %d");
+                TBuf<LogTBufSize> buf;
+                buf.Format(logText, iRenderOrientationTrackingType, error);
+                wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate,buf);     
+                }              
+            break;            
+        }    
+
+    if(KErrNone == error)
+        {
+        error = PublishOrientation(newDeviceOrientation);
+        }
+    
+    return error;
+    }
+
+/**
+Publishes the given value
+
+@param The render orientation to publish
+@return KErrNone for success, else any of the system wide erro codes
+*/
+TInt CWsRenderOrienationTracker::DoPublishOrientation(const TRenderOrientation aRenderOrientation)
+    {
+    TInt error = iRenderOrientationPublisher.Set(aRenderOrientation);
+         
+    // if it's published OK, then remember the newly published value
+    if(KErrNone == error)
+        {
+        iPublishedRenderOrientation = aRenderOrientation;
+        if(wsDebugLog)
+            {
+            _LIT(logText,"Orientation Tracker: Published render orientation %d");
+            wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, logText, aRenderOrientation);
+            }
+        }
+    else if(wsDebugLog)
+        {
+        _LIT(logText,"Orientation Tracker: Error %d setting render orientation property");
+        wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate, logText, error);                   
+        }
+    return error;
+    }
+
+void CWsRenderOrienationTracker::SetHALOrientation(const TRenderOrientation aRenderOrientation)
+    {
+    // If the render orientation is EDisplayOrientationAuto then don't update HAL
+    // The application and HAL should always have the same state for the orientation.
+    if(EDisplayOrientationAuto != aRenderOrientation)
+        {
+        TInt error = HAL::Set(CWsTop::CurrentFocusScreen()->ScreenNumber(), HALData::EDigitiserOrientation, WservToDigitiser(iPublishedRenderOrientation));
+        //Just log the error if there is one.
+        if(wsDebugLog && error != KErrNone)
+            {
+            _LIT(logText,"Orientation Tracker: Error %d setting digitiser orientation");
+            wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate, logText, error);           
+            } 
+        }
+    }
+
+/**
+If the current orientation differs from the previously published value then publishes the current value
+
+@param The render orientation to check and publish
+@return KErrNone for success, else any of the system wide erro codes
+*/
+TInt CWsRenderOrienationTracker::PublishOrientation(const TRenderOrientation aRenderOrientation)
+    {
+    TInt error = KErrNone;
+  
+    if(aRenderOrientation != iPublishedRenderOrientation)
+        {
+        // If the device Orientation has changed, publish it
+        error = DoPublishOrientation(aRenderOrientation);
+        if(KErrNone == error)
+            SetHALOrientation(aRenderOrientation);
+        }
+    return error;
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/renderorientationtracker.h	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,71 @@
+// Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This material, including documentation and any related
+// computer programs, is protected by copyright controlled by
+// Nokia. All rights are reserved. Copying, including
+// reproducing, storing, adapting or translating, any
+// or all of this material requires the prior written consent of
+// Nokia. This material also contains confidential
+// information which may not be disclosed to others without the
+// prior written consent of Nokia.
+//
+// Description:
+// Render Orientation Tracking and Publication
+// 
+
+#ifndef renderorientationtracker_h
+#define renderorientationtracker_h
+
+#include <e32std.h>
+#include <e32base.h>
+#include <e32property.h>
+#include <w32std.h>
+#include <wspublishandsubscribedata.h>
+
+// Values for the device orientation that we receive via P&S from the Theme Server
+// Todo FIX THIS Category UID!!!
+const TUid  KThemeOrientationCategory   = {0x20022E82}; // == KHbPsHardwareCoarseOrientationCategoryUid 
+const TUint KThemeOrientationKey        = 0x4F726965; // == KHbPsHardwareCoarseOrientationKey 
+
+typedef TRenderOrientation TRenderOrientationTrackingType; 
+
+class CWsWindowGroup;
+
+class CWsRenderOrienationTracker : public CActive
+    {
+public:  
+    static CWsRenderOrienationTracker* NewL();
+    ~CWsRenderOrienationTracker();
+
+    void CheckRenderOrientation();
+
+private:   
+    CWsRenderOrienationTracker();
+    void ConstructL();
+    
+    void RequestDeviceOrientationNotification();
+    void CancelDeviceOrientationNotification();
+    
+    // CActive
+    void RunL();
+    void DoCancel();
+    
+    TInt DoOrientationTracking();
+    TInt GetThemeOrientation(TRenderOrientation& aThemeOrientation);
+    TInt PublishOrientation(const TRenderOrientation aRenderOrientation);
+    TInt DoPublishOrientation(const TRenderOrientation aRenderOrientation);
+    TInt GetIndicatedOrientation(TRenderOrientationTrackingType& aOrientationTrackingType);
+    TInt CheckWindowGroupOrientation(const CWsWindowGroup& aWinGroup, TRenderOrientationTrackingType& aOrientationTrackingType);
+    TBool UseableGroupWindow(const CWsWindowGroup& aWinGroup) const;
+    TInt GetFocusWindowOrientation(TRenderOrientationTrackingType& aOrientationTrackingType);
+    TInt FindOrientationFromWindowTree(TRenderOrientationTrackingType& aOrientationTrackingType);    
+    void SetHALOrientation(const TRenderOrientation aRenderOrientation);
+    
+private:    
+    TRenderOrientationTrackingType  iRenderOrientationTrackingType;    
+    TRenderOrientation              iPublishedRenderOrientation;
+    RProperty                       iThemeOrientationProperty;
+    RProperty                       iRenderOrientationPublisher;
+    };
+
+#endif
--- a/windowing/windowserver/nga/SERVER/windowgroup.h	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nga/SERVER/windowgroup.h	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 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"
@@ -82,7 +82,7 @@
 	void AddPriorityKeyL(TUint aKeycode, TUint aModifierMask, TUint aModifiers);
 	void RemovePriorityKey(TUint aKeycode, TUint aModifierMask, TUint aModifiers);
 	void RemoveAllPriorityKeys();
-	TBool CheckForPriorityKey(const TKeyData &aKey, TInt aScanCode);
+	TBool CheckForPriorityKey(const TKeyEvent &aKeyEvent);
 	inline CWsPointerCursor *GroupPointerCursor() const;
 	static CWsWindowGroup *WindowGroupFromIdentifier(TInt aIdentifier);
 	static CWsWindowGroup *WindowGroupFromIdentifierL(TInt aIdentifier);
@@ -110,7 +110,7 @@
 	void SetScreenDevice(DWsScreenDevice *aDevice);
 	static void SetEventQueueTestState(TBool aEventQueState);
 	TBool HasVisibleTranslucentChild();
-	void  ReleasePendedMessage();
+	void  ReleasePendedMessage();	
 private:
 	void SwitchToOwningWindow(CWsWindowGroup *aClosingWindow);
 	void MoveChainedWindows(TDblQueIter<CWsWindowGroup>& aIter,TBool aForward,TInt aPos,CWsWindowGroup* aClosingWindow);
--- a/windowing/windowserver/nonnga/CLIENT/RWS.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/nonnga/CLIENT/RWS.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -22,6 +22,7 @@
 #include "CLIENT.H"
 #include "wstraces.h"
 #include "graphics/windowserverconstants.h"
+#include <wspublishandsubscribedata.h>
 
 const TInt KMaxWSERVMessagesSlot=-1;
 
@@ -2422,3 +2423,10 @@
 	{
 	ASSERT(0);
 	}
+
+EXPORT_C void RWsSession::IndicateAppOrientation(TRenderOrientation aOrientation)
+	/** Dummy implementation in order to preserve compatibility with WSERV NGA.
+	@internalComponent */
+	{
+	ASSERT(0);
+	}
--- a/windowing/windowserver/test/TAutoServer/TAutoServer.cpp	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/TAutoServer/TAutoServer.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -72,6 +72,7 @@
 #include "TMULSCREENS.h"
 #include "TBUFFERSECURITY.H"
 #include "TFLICKERFREE.H"
+#include "tdevicerotation.h"
 #ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
 #include "TFADINGBITMAP.H"
 #endif
@@ -86,6 +87,7 @@
 #include "tdrawresource.h"
 #include "twindowsizecache.h"
 
+
 /* Path to the script
 z:\GraphicsTest\gditest.script
 */
@@ -309,6 +311,8 @@
   		testStep = new CTBufferSecurityStep();
    	else if(aStepName == KTFlickerFreeStep)
   		testStep = new CTFlickerFreeStep();
+    else if(aStepName == KTDeviceRotationStep)
+     testStep = new CTDeviceRotationStep();
 #ifdef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
 	else if(aStepName == KTFadingBitmapStep)
   		testStep = new CTFadingBitmapStep();
--- a/windowing/windowserver/test/TAutoServer/openwfc/TAutoServer_nga.mmp	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/TAutoServer/openwfc/TAutoServer_nga.mmp	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 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"
@@ -24,22 +24,19 @@
 MACRO TEST_GRAPHICS_WSERV_TAUTOSERVER_NGA
 MACRO SYMBIAN_GRAPHICS_GCE
 
-USERINCLUDE		../../../../../graphicstest/graphicstestharness/inc ../../../inc ../../../tauto ../../../tauto/openwfc
-USERINCLUDE		../../../tredir ../../../tlisten ../../../tframerate ../../../tcontaindrawer ../../t_gdcoverage ../../../tbufferdrawer
-USERINCLUDE		../../../tlib ../../
+USERINCLUDE		../../../../../graphicstest/graphicstestharness/inc ../../../inc ../../tauto ../../tauto/openwfc
+USERINCLUDE		../../tredir ../../tlisten ../../tframerate ../../tcontaindrawer ../../t_gdcoverage ../../tbufferdrawer
+USERINCLUDE		../../tlib ../../
 
-APP_LAYER_SYSTEMINCLUDE_SYMBIAN
-MW_LAYER_SYSTEMINCLUDE_SYMBIAN
-OS_LAYER_SYSTEMINCLUDE_SYMBIAN
-OS_LAYER_LIBC_SYSTEMINCLUDE 
-
+OS_LAYER_SYSTEMINCLUDE
+OS_LAYER_LIBC_SYSTEMINCLUDE
 
 SOURCEPATH    ../
 SOURCE        TAutoServer.cpp
 SOURCEPATH    ../../
 SOURCE        PARSEINIDATA.CPP
 
-SOURCEPATH    ../../../tauto
+SOURCEPATH    ../../tauto
 SOURCE        AUTO.CPP
 SOURCE        TAUTODLL.CPP
 SOURCE        TEvent.CPP
@@ -102,6 +99,7 @@
 SOURCE	      tmultiptrevent.cpp
 SOURCE	      tdrawresource.cpp
 SOURCE	      twindowsizecache.cpp
+SOURCE        tdevicerotation.cpp
 
 //Required to test CommamdBuffer::Play using MWsGraphicsContext in tgc
 SOURCE        directgdigcwrapper.cpp
--- a/windowing/windowserver/test/TAutoServer/openwfc/TAutoServer_nonnga.mmp	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/TAutoServer/openwfc/TAutoServer_nonnga.mmp	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2006-2010 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"
@@ -23,12 +23,11 @@
 
 MACRO TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
 
-USERINCLUDE		../../../../../graphicstest/graphicstestharness/inc ../../../inc ../../../tauto ../../../tauto/openwfc
-USERINCLUDE		../../../tredir ../../../tlisten ../../../tframerate ../../../tcontaindrawer ../../t_gdcoverage
-USERINCLUDE		../../../tlib ../../
+USERINCLUDE		../../../../../graphicstest/graphicstestharness/inc ../../../inc ../../tauto ../../tauto/openwfc
+USERINCLUDE		../../tredir ../../tlisten ../../tframerate ../../tcontaindrawer ../../t_gdcoverage
+USERINCLUDE		../../tlib ../../
 
-MW_LAYER_SYSTEMINCLUDE_SYMBIAN
-OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+OS_LAYER_SYSTEMINCLUDE
 OS_LAYER_LIBC_SYSTEMINCLUDE
 
 SOURCEPATH    ../
@@ -36,7 +35,7 @@
 SOURCEPATH    ../../
 SOURCE        PARSEINIDATA.CPP
 
-SOURCEPATH    ../../../tauto
+SOURCEPATH    ../../tauto
 SOURCE        AUTO.CPP
 SOURCE        TAUTODLL.CPP
 SOURCE        TEvent.CPP
@@ -96,6 +95,7 @@
 SOURCE        THeartBeat.CPP
 SOURCE        tgc.cpp
 SOURCE	      TGRAPHICSDRAWER.CPP
+SOURCE        tdevicerotation.cpp
 
 LIBRARY	        bitgdi.lib	efsrv.lib	euser.lib	fbscli.lib
 LIBRARY	        gdi.lib		hal.lib		tlib.lib	ws32.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/TAutoServer/tevent_captureapp.mmp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,29 @@
+// Copyright (c) 2010 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:
+// Helper application for TEvent test case GRAPHICS-WSERV-417-61800-0004
+//
+
+TARGET		tevent_captureapp.exe
+TARGETTYPE	exe
+UID			0x00000000 0x102872e4
+VENDORID	0x70000001
+CAPABILITY	SwEvent
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+SOURCEPATH	../tauto
+SOURCE		tevent_captureapp.cpp
+
+LIBRARY		euser.lib
+LIBRARY		ws32.lib
--- a/windowing/windowserver/test/scripts/wstest_config.cmd	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/scripts/wstest_config.cmd	Fri Sep 24 16:44:34 2010 +0300
@@ -1,22 +1,22 @@
 @echo off
-rem Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+rem Copyright (c) 2006-2010 Nokia Corporation and/or its subsidiary(-ies).
 rem All rights reserved.
 rem This component and the accompanying materials are made available
 rem under the terms of "Eclipse Public License v1.0"
 rem which accompanies this distribution, and is available
 rem at the URL "http://www.eclipse.org/legal/epl-v10.html".
-rem 
+rem
 rem Initial Contributors:
 rem Nokia Corporation - initial contribution.
-rem 
+rem
 rem Contributors:
-rem 
+rem
 rem Description:
 rem @internalComponent - Internal Symbian
 rem 
 rem
 set nonnga=false
-if not defined EPOC_INI set EPOC_INI=\epoc32\data\epoc.ini
+if not defined EPOC_INI set EPOC_INI=%EPOCROOT%epoc32\data\epoc.ini
 if /i "%2"=="nonnga" set nonnga=true
 if /i "%3"=="nonnga" set nonnga=true
 if "%nonnga%"=="true" echo Configuring for Non-NGA
@@ -33,7 +33,7 @@
 	call :doinstall %EMULATOR_DATA_DIR% multiscreen %2 %3
 )
 
-echo If EPOC.INI isn't already backuped then backup EPOC.INI to EPOC.INI.bak
+rem If EPOC.INI isn't already backed up then backup EPOC.INI to EPOC.INI.bak
 if not exist %EPOC_INI%.bak copy /y %EPOC_INI% %EPOC_INI%.bak
 
 echo Editing EPOC.INI to use multiscreen.
@@ -46,7 +46,7 @@
 
 
 :doinstall
-rem If WSINI.INI(s) aren't already backuped then backup WSINI.INI(s)
+rem If WSINI.INI(s) aren't already backed up then backup WSINI.INI(s)
 if not exist %1\z\system\data\wsini.bak   if exist %1\z\system\data\wsini.ini   copy /y %1\z\system\data\wsini.ini   %1\z\system\data\wsini.bak >nul
 if not exist %1\z\resource\data\wsini.bak if exist %1\z\resource\data\wsini.ini copy /y %1\z\resource\data\wsini.ini %1\z\resource\data\wsini.bak >nul
 
@@ -84,7 +84,7 @@
 	call :doinstall_changetracking %EMULATOR_DATA_DIR% multiscreen %2 %3
 )
 
-echo If EPOC.INI isn't already backuped then backup EPOC.INI to EPOC.INI.bak
+rem If EPOC.INI isn't already backed up then backup EPOC.INI to EPOC.INI.bak
 if not exist %EPOC_INI%.bak copy /y %EPOC_INI% %EPOC_INI%.bak >nul
 
 echo Editing EPOC.INI to use multiscreen.
@@ -128,9 +128,9 @@
 	call :douninstall %EMULATOR_DATA_DIR%
 )
 
-echo If EPOC.INI was already backuped then restore EPOC.INI from EPOC.INI.bak
+rem If EPOC.INI was already backed up then restore EPOC.INI from EPOC.INI.bak
 if exist %EPOC_INI%.bak (
-	echo Restore EPOC.INI from backup
+	echo Restoring EPOC.INI from backup
 	copy /y %EPOC_INI%.bak %EPOC_INI% >nul
 	del /f /q %EPOC_INI%.bak >nul
 )
@@ -139,7 +139,7 @@
 
 :douninstall
 
-rem If WSINI.INI(s) were already backuped then restore WSINI.INI
+rem If WSINI.INI(s) were already backed up then restore WSINI.INI
 if exist %1\z\system\data\wsini.bak (
 copy /y %1\z\system\data\wsini.bak   %1\z\system\data\wsini.ini >nul
 del  /f /q %1\z\system\data\wsini.bak >nul
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/scripts/wstest_t_devicerotation_s0_nga.script	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,31 @@
+// Copyright (c) 2010 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: 
+//
+
+PRINT Run WServ NGA device rotation tests on screen 0
+
+LOAD_SUITE tautoserver_nga
+
+//
+// Uncommenting the TMemLeakCheckEnable test will set Wserv into a mode where
+// between each test it effectively shuts itself down, checks for memory leaks,
+// then restarts. This is especially useful when the final TMemLeakCheckOneShot
+// test indicates a memory leak somewhere in the tests.
+// RUN_TEST_STEP 100 tautoserver_nga TMemLeakCheckEnable
+//
+
+RUN_TEST_STEP 100 tautoserver_nga TDeviceRotation
+
+// Run at the end and it will trigger a Wserv memory leak check
+RUN_TEST_STEP 100 tautoserver_nga TMemLeakCheckOneShot
--- a/windowing/windowserver/test/tauto/TCapKey.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/tauto/TCapKey.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -455,16 +455,39 @@
 	TInt retVal;
 	TInt resCount=Client()->iWs.ResourceCount();
 	for(TInt index=0;index<numErrorKeys;index++)
-	{
-		retVal = Client()->iGroup->GroupWin()->CaptureKey(errorKeys[index].keyCode,errorKeys[index].modifier_mask,errorKeys[index].modifiers);
+		{
+		retVal = Client()->iGroup->GroupWin()->CaptureKey(errorKeys[index].keyCode,errorKeys[index].modifier_mask,errorKeys[index].modifiers, errorKeys[index].priority);
 		TEST(retVal==KErrArgument);
 		if (retVal!=KErrArgument)
-			INFO_PRINTF3(_L("Client()->iGroup->GroupWin()->CaptureKey() return value - Expected: %d, Actual: %d"), KErrArgument, retVal);	
-	}
+			{
+			_LIT(KMsg, "CaptureKey() with bad parameter set %d returned %d - expected KErrArgument (%d)");
+			LOG_MESSAGE4(KMsg, index, retVal, KErrArgument);	
+			}
+
+		retVal = Client()->iGroup->GroupWin()->CaptureKeyUpAndDowns(errorKeys[index].keyCode, errorKeys[index].modifier_mask, errorKeys[index].modifiers, errorKeys[index].priority);
+		TEST(retVal == KErrArgument);
+		if (retVal != KErrArgument)
+			{
+			_LIT(KMsg, "CaptureKeyUpAndDowns() with bad parameter set %d returned %d - expected KErrArgument (%d)");
+			LOG_MESSAGE4(KMsg, index, retVal, KErrArgument);	
+			}
+
+		retVal = Client()->iGroup->GroupWin()->CaptureLongKey(errorKeys[index].keyCode, errorKeys[index].keyCode, errorKeys[index].modifier_mask, errorKeys[index].modifiers, errorKeys[index].priority, ELongCaptureNormal);
+		TEST(retVal == KErrArgument);
+		if (retVal != KErrArgument)
+			{
+			_LIT(KMsg, "CaptureLongKey() with bad parameter set %d returned %d - expected KErrArgument (%d)");
+			LOG_MESSAGE4(KMsg, index, retVal, KErrArgument);	
+			}
+		}
+
 	retVal = Client()->iWs.ResourceCount();
 	TEST(retVal==resCount);
 	if (retVal!=resCount)
-		INFO_PRINTF3(_L("Client()->iWs.ResourceCount() return value - Expected: %d, Actual: %d"), resCount, retVal);	
+		{
+		_LIT(KMsg, "Resource count %d - expected %d");
+		LOG_MESSAGE3(KMsg, retVal, resCount);	
+		}
 	}
 
 void CTCaptureKey::SetMode(TTestMode aMode)
@@ -801,8 +824,10 @@
 @SYMTestStatus      Implemented
 
 @SYMTestActions     Memorizes amount of objects that the server has allocated for that client.
-					Tries to register 3 different capture keys with invalid
-					modifiers and modifirs mask pair.
+					Tries to register capture keys with invalid modifiers and
+					modifier mask pairs, using each of the RWindowGroup capture
+					functions CaptureKey(), CaptureKeyUpAndDowns() and
+					CaptureLongKey().
 
 @SYMTestExpectedResults Makes sure that the number of server-side objects for the 
 					session didn't change.
--- a/windowing/windowserver/test/tauto/TCapKey.H	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/tauto/TCapKey.H	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -157,12 +157,21 @@
 	TInt keyCode;
 	TUint modifier_mask;
 	TUint modifiers;
+	TInt priority;
 	};
 
 LOCAL_D SErrorCapKey errorKeys[]={
-	{'a',EModifierFunc|EModifierShift,EModifierFunc|EModifierCtrl},
-	{'1',0,EModifierFunc},
-	{3,EModifierCtrl,EModifierCtrl|EModifierShift},
+	{'a', EModifierFunc|EModifierShift,EModifierFunc|EModifierCtrl, 0},
+	{'1', 0, EModifierFunc, 0},
+	{3, EModifierCtrl,EModifierCtrl|EModifierShift, 0},
+	// @SYMPREQ 417-61800: Check that attempts to capture keys with
+	// EModifierLong in the modifier mask fail with KErrArgument.
+	{'T', EModifierLongKey, 0, 0},
+	{'u', EModifierLongKey|EModifierAlt, EModifierLongKey, 0},
+	{'V', EModifierLongKey|EModifierShift, EModifierLongKey|EModifierShift, 0},
+	// @SYMPREQ 417-61800: Check that attempts to capture keys with a priority
+	// of KMinTInt fail with KErrArgument.
+	{'W', 0, 0, KMinTInt},
 	};
 
 const TInt numCapKeys=sizeof(capKeys)/sizeof(capKeys[0]);
--- a/windowing/windowserver/test/tauto/TEVENT.H	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/tauto/TEVENT.H	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -38,6 +38,7 @@
 
 const TInt EMaxEventQueueSize=32;
 const TInt EMinQueueSize = 2;
+const TUint KModifiersIgnore = 0xffffffff;
 
 
 class CTEventTest;
@@ -263,6 +264,11 @@
 		// Add additional enum values before this line
 		EMaxCancelCaptureKeyApis
 		};
+	enum TLongkeyCapPriorityTests
+		{
+		ELongkeyCaptureSamePriority,
+		ELongkeyCaptureDiffPriority
+		};
 private:
 	void RunTestsL(TBool aNeedChildWindows=EFalse);
 	void RunTestsRestoreAreaL(TBool aNeedChildWindows);
@@ -285,13 +291,17 @@
 	void Password_NextSetOfEvents();
 	void GroupListChanged_NextSetOfEventsL();
 	void VisibilityChanged_NextSetOfEventsL();
+#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA  	
+	void KeyEventTranslation_NextSetOfEventsL();
+	void KeyEventBlocking_NextSetOfEventsL();
+	void KeyEventAppRestriction_NextSetOfEventsL();
+	void KeyEventAppPriority_NextSetOfEventsL();
 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS	
-#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA  	
 	void SurfaceVisibilityChanged1_NextSetOfEventsL();
 	void SurfaceVisibilityChanged2_NextSetOfEventsL();
 	void SurfaceVisibilityChanged3_NextSetOfEventsL();
+#endif //SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
 #endif //TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
-#endif //SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
 	void CheckTimeStamp_NextSetOfEventsL();
 	void RepeatableKeysL();
 	void PointerCapture_NextSetOfEventsL();
@@ -311,8 +321,8 @@
 	void EventHandlerRemoval_AddEventHandlerMultipleTimes();
 	void CheckPointerCursorInDifferentScreenMode(TSizeMode aMode,TPoint aOrigin);
 	void SimulateAndCheck(TPoint aOrigin,TSize aScale,TInt aXOffset,TInt aYOffset,TPointerEvent::TType aEventType,TRect aPointerCursorArea);
-	void AddExpectedKey(TInt aEventCode, TInt aScanCode, TInt aCode=0, TInt aRepeats=0, TUint aModifiers=0);
-	void AddExpectedKeyDownUp(TInt aScanCode, TInt aCode=0, TInt aRepeats=0, TUint aModifiers=0);
+	void AddExpectedKey(TInt aEventCode, TInt aScanCode, TInt aCode=0, TInt aRepeats=0, TUint aModifiers=KModifiersIgnore);
+	void AddExpectedKeyDownUp(TInt aScanCode, TInt aCode=0, TInt aRepeats=0, TUint aModifiers=KModifiersIgnore);
 	void AddExpectedEvent(TInt aEventCode, CTWinBase* aWin);
 	void AddExpectedEvent(TInt aEventCode);
 	void AddExpectedEvent(TInt aEventCode,RWindowGroup* aWindow);
@@ -358,6 +368,11 @@
 #endif
 	void TestCaptureAndCancelCapturePair(TCaptureKeyApis aCaptureApi, TCancelCaptureKeyApis aCancelCaptureApi);
 	static TInt GenerateAnEvent(TAny* aEventTest);
+	void CheckLongkeyCaptureWithPriority(TLongkeyCapPriorityTests aTestType);
+	void DelayForRepeatEvents(TInt aNumeratorFracVal, TInt aDenominatorFracVal);
+#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA 	
+	void SpawnCaptureAppL(RProcess& aProcess);
+#endif
 private:
 	CTBlankWindow* iBlankWin;
 	RBlankWindow iBackingWindow;
@@ -390,13 +405,17 @@
 	TBool iIs3DPointer;
 	TBool iPtrPluginLoaded;
 	TInt iYOffset;
+	TTimeIntervalMicroSeconds32 iKeyBoardRepeatInitialDelay;
+	TTimeIntervalMicroSeconds32 iKeyBoardRepeatNextDelay;
+#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA 	
+	RProcess iCaptureApp1;
+	RProcess iCaptureApp2;
 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS	
-#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA 	
 	TSurfaceId iSurfaceId;
 	RSurfaceManager iSurfaceManager;
 	CPeriodic* iTimeOutCallback;
+#endif // SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
 #endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
-#endif // SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
 	};
 
 class CTQueueWindowGroup : public CTWindowGroup
--- a/windowing/windowserver/test/tauto/TEvent.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/tauto/TEvent.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -37,6 +37,9 @@
 
 _LIT(KKeyClickPluginDll, "click.dll");
 
+const TInt KLongKeyCaptureLowPriority = 1;
+const TInt KLongKeyCaptureHighPriority = 2;
+
 CTQueueClient::CTQueueClient(CTEventTest *aTest) : iTest(aTest)
 	{
 	}
@@ -203,6 +206,7 @@
 		TestL(wsEvent.Type()==expectedEvent.Type() && wsEvent.Handle()==expectedEvent.Handle());
 		}		
 	iLastEventError=(wsEvent.Type()==EEventErrorMessage);
+
 	switch(wsEvent.Type())
 		{
 		case EEventKey:
@@ -212,7 +216,7 @@
 				{
 				_LIT(KKeysDiff,"Count=%d  Key Code Exp=%d (%c)  Act=%d (%c)");
 				buf.Copy(KStartString);
-				buf.AppendFormat(KKeysDiff,iEventCount,iEventCount,eKeyCode,eKeyCode,wsKeyCode,wsKeyCode);
+				buf.AppendFormat(KKeysDiff,iEventCount,eKeyCode,eKeyCode,wsKeyCode,wsKeyCode);
 				iTest->LOG_MESSAGE(buf);
 				}
 			wsKeyRepeat=wsEvent.Key()->iRepeats,eKeyRepeat=expectedEvent.Key()->iRepeats;
@@ -224,10 +228,15 @@
 				iTest->LOG_MESSAGE(buf);
 				}
 		#endif
-			TestL(wsEvent.Key()->iCode==expectedEvent.Key()->iCode && wsEvent.Key()->iRepeats>=expectedEvent.Key()->iRepeats
-								&& (wsEvent.Key()->iRepeats>0)==(expectedEvent.Key()->iRepeats>0));		//Fall Through
+			TestL(wsEvent.Key()->iCode==expectedEvent.Key()->iCode &&
+				wsEvent.Key()->iRepeats>=expectedEvent.Key()->iRepeats &&
+				(wsEvent.Key()->iRepeats>0)==(expectedEvent.Key()->iRepeats>0));
+			// Fall Through
 		case EEventKeyDown:
 		case EEventKeyUp:
+			{
+			TUint wsModifiers = wsEvent.Key()->iModifiers;
+			TUint eModifiers = expectedEvent.Key()->iModifiers;
 		#if defined(FAIL_LOGGING)
 			wsKeyScan=wsEvent.Key()->iScanCode,eKeyScan=expectedEvent.Key()->iScanCode;
 			if (wsKeyScan!=eKeyScan)
@@ -237,8 +246,18 @@
 				buf.AppendFormat(KScanDiff,iEventCount,eKeyScan,eKeyScan,wsKeyScan,wsKeyScan);
 				iTest->LOG_MESSAGE(buf);
 				}
+
+			if (eModifiers != KModifiersIgnore && wsModifiers != eModifiers)
+				{
+				_LIT(KModDiff,"Count=%d  Modifiers Exp=0x%x  Act=0x%x");
+				buf.Copy(KStartString);
+				buf.AppendFormat(KModDiff, iEventCount, eModifiers, wsModifiers);
+				iTest->LOG_MESSAGE(buf);
+				}
 		#endif
-			TestL(wsEvent.Key()->iScanCode==expectedEvent.Key()->iScanCode);
+			TestL(wsEvent.Key()->iScanCode == expectedEvent.Key()->iScanCode &&
+				(eModifiers == KModifiersIgnore || wsModifiers == eModifiers));
+			}
 			break;
 		case EEventModifiersChanged:
 			{
@@ -708,7 +727,8 @@
 		{
 		iIs3DPointer=EFalse;
 		}
-#endif		
+#endif
+	TheClient->iWs.GetKeyboardRepeatRate(iKeyBoardRepeatInitialDelay, iKeyBoardRepeatNextDelay);
 	}
 
 void CTEventTest::Failed()
@@ -820,7 +840,7 @@
 	group.SetOrdinalPosition(position,priority);
 	}
 
-void CTEventTest::AddExpectedKey(TInt aEventCode, TInt aScanCode, TInt aCode/*=0*/, TInt aRepeats/*=0*/, TUint aModifiers/*=0*/)
+void CTEventTest::AddExpectedKey(TInt aEventCode, TInt aScanCode, TInt aCode/*=0*/, TInt aRepeats/*=0*/, TUint aModifiers/*=KModifiersIgnore*/)
 	{
 	TPckgBuf<TWsEvent> evtPkg;
 	TWsEvent& event=evtPkg();
@@ -834,15 +854,27 @@
 	event.Key()->iRepeats=aRepeats;
 	iQueueClient->AddExpectedEvent(event);
 	if (iAddToClick)
+		{
+		if (aModifiers == KModifiersIgnore)
+			{
+			// Key click tests assume zero modifiers in click event by default
+			event.Key()->iModifiers = 0;
+			}
 		iClick.CommandReply(EClickEventAdd,evtPkg);
-	}
-
-void CTEventTest::AddExpectedKeyDownUp(TInt aScanCode, TInt aCode/*=0*/, TInt aRepeats/*=0*/, TUint aModifiers/*=0*/)
+		}
+	}
+
+void CTEventTest::AddExpectedKeyDownUp(TInt aScanCode, TInt aCode/*=0*/, TInt aRepeats/*=0*/, TUint aModifiers/*=KModifiersIgnore*/)
 	{
 	__ASSERT_DEBUG(aScanCode<'a' || aScanCode>'z',AutoPanic(EAutoPanicScanCapital));
-	AddExpectedKey(EEventKeyDown,aScanCode,0,aRepeats,aModifiers);
+	// EModiferAutorepeatable can be present in EEventKey but is never valid
+	// in EEventKeyDown and EEventKeyUp. 
+	TUint modifiersDownUp = (aModifiers == KModifiersIgnore) ?
+		aModifiers : aModifiers & ~EModifierAutorepeatable;
+
+	AddExpectedKey(EEventKeyDown,aScanCode,0,aRepeats,modifiersDownUp);
 	AddExpectedKey(EEventKey,aScanCode,aCode,aRepeats,aModifiers);
-	AddExpectedKey(EEventKeyUp,aScanCode,0,aRepeats,aModifiers);
+	AddExpectedKey(EEventKeyUp,aScanCode,0,aRepeats,modifiersDownUp);
 	}
 
 void CTEventTest::AddExpectedEvent(TInt aEventCode, CTWinBase* aWin)
@@ -1160,20 +1192,32 @@
 	case 27:
 	    RawEventRepeatTest_NextSetOfEventsL();
 	    break;
-	    
-#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS	    
+
 #ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA 	    
     case 28:
-        SurfaceVisibilityChanged1_NextSetOfEventsL();
+        KeyEventTranslation_NextSetOfEventsL();
         break;
     case 29:
-        SurfaceVisibilityChanged2_NextSetOfEventsL();
+        KeyEventBlocking_NextSetOfEventsL();
         break;
     case 30:
+        KeyEventAppRestriction_NextSetOfEventsL();
+        break;
+    case 31:
+        KeyEventAppPriority_NextSetOfEventsL();
+        break;
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS	    
+    case 32:
+        SurfaceVisibilityChanged1_NextSetOfEventsL();
+        break;
+    case 33:
+        SurfaceVisibilityChanged2_NextSetOfEventsL();
+        break;
+    case 34:
         SurfaceVisibilityChanged3_NextSetOfEventsL();
         break;
+#endif // SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
 #endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
-#endif // SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
         
 	default:
 		AutoPanic(EAutoPanicWrongTest);
@@ -3545,8 +3589,8 @@
 			break;
 		case 2:
 			AddExpectedKey(EEventKeyDown,EStdKeyRightShift,0,0,EModifierRightShift|EModifierShift);
-			AddExpectedKeyDownUp('B','B',0,EModifierRightShift|EModifierShift);
-			AddExpectedKeyDownUp('W','W',0,EModifierRightShift|EModifierShift);
+			AddExpectedKeyDownUp('B','B',0,EModifierRightShift|EModifierShift|EModifierAutorepeatable);
+			AddExpectedKeyDownUp('W','W',0,EModifierRightShift|EModifierShift|EModifierAutorepeatable);
 			AddExpectedKey(EEventKeyUp,EStdKeyRightShift);
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeyRightShift);		//1 event
@@ -3854,11 +3898,9 @@
 
 void CTEventTest::CaptureLong_NextSetOfEventsL()
 	{
-	TTimeIntervalMicroSeconds32 initialTime,time;
-	TheClient->iWs.GetKeyboardRepeatRate(initialTime,time);
 	#if defined(LOGGING)
 		TLogMessageText logMessageText;
-		_LIT(KSet,"CaptureLong SetOfEvents: %d of 14");
+		_LIT(KSet,"CaptureLong SetOfEvents: %d of 23");
 		logMessageText.Format(KSet,iEventSet);
 		INFO_PRINTF1(logMessageText);
 	#endif
@@ -3872,53 +3914,72 @@
 			AddExpectedKeyDownUp('A','a');
 			break;
 		case 1:
-			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureLongKey(' ','a',0,0,2,ELongCaptureNormal);
+			// Test CaptureLongKey() with modifier value EModifierShift and flag value ELongCaptureNormal
+			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureLongKey(' ','a',EModifierShift,EModifierShift,2,ELongCaptureNormal);
 			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeyLeftShift);
 			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeySpace);
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+time.Int()/3);
+			DelayForRepeatEvents(1, 3);
 			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeySpace);
+			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeyLeftShift);
+			AddExpectedKey(EEventKeyDown,EStdKeyLeftShift);
 			AddExpectedKey(EEventKeyDown,EStdKeySpace);
-			AddExpectedKey(EEventKey,EStdKeySpace,' ');
-			AddExpectedKey(EEventKey,EStdKeySpace,'a',1);
+			AddExpectedKey(EEventKey,EStdKeySpace,' ',0,EModifierLeftShift|EModifierShift|EModifierAutorepeatable);
+			AddExpectedKey(EEventKey,EStdKeySpace,'a',1,EModifierLongKey|EModifierLeftShift|EModifierShift|EModifierAutorepeatable);
 			AddExpectedKey(EEventKeyUp,EStdKeySpace);
+			AddExpectedKey(EEventKeyUp,EStdKeyLeftShift);
 			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
 			break;
-		case 2:
-			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureLongKey(' ','a',0,0,2,ELongCaptureWaitShort);
+		case 2:	
+			// Test CaptureLongKey() with modifier value EModifierFunc and flag value ELongCaptureWaitShort
+			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureLongKey(EKeyEnter,'a',EModifierFunc,EModifierFunc,2,ELongCaptureWaitShort);
 			iQueueClient->iWs.Flush();
-			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeySpace);
+			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeyLeftFunc);
+			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeyEnter);
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+time.Int()/3);
-			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeySpace);
+			DelayForRepeatEvents(1, 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeyEnter);
+			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeyLeftFunc);
 			iTest->SimulateKeyDownUp(EStdKeySpace);
-			AddExpectedKey(EEventKeyDown,EStdKeySpace);
-			AddExpectedKey(EEventKey,EStdKeySpace,'a',1);
-			AddExpectedKey(EEventKeyUp,EStdKeySpace);
+			AddExpectedKey(EEventKeyDown,EStdKeyLeftFunc);
+			AddExpectedKey(EEventKeyDown,EStdKeyEnter);
+			AddExpectedKey(EEventKey,EStdKeyEnter,'a',1,EModifierLongKey|EModifierLeftFunc|EModifierFunc|EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp,EStdKeyEnter);
+			AddExpectedKey(EEventKeyUp,EStdKeyLeftFunc);
 			AddExpectedKeyDownUp(EStdKeySpace,' ');
 			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
 			break;
 		case 3:
-			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureLongKey(' ','a',0,0,2,ELongCaptureNormal|ELongCaptureRepeatEvents);
+			// Test CaptureLongKey() with modifier values EModifierFunc|EModifierAlt and flag values ELongCaptureNormal|ELongCaptureRepeatEvents)
+			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureLongKey(EKeyEnter,'a',EModifierFunc|EModifierAlt,EModifierFunc|EModifierAlt,2,ELongCaptureNormal|ELongCaptureRepeatEvents);
 			iQueueClient->iWs.Flush();
-			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeySpace);
+			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeyLeftFunc);
+			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeyLeftAlt);
+			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeyEnter);
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+5*time.Int());
-			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeySpace);
-			AddExpectedKey(EEventKeyDown,EStdKeySpace);
-			AddExpectedKey(EEventKey,EStdKeySpace,' ');
-			AddExpectedKey(EEventKey,EStdKeySpace,'a',2);
-			AddExpectedKey(EEventKeyUp,EStdKeySpace);
+			DelayForRepeatEvents(5, 1);
+			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeyEnter);
+			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeyLeftAlt);
+			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeyLeftFunc);
+			AddExpectedKey(EEventKeyDown,EStdKeyLeftFunc);
+			AddExpectedKey(EEventKeyDown,EStdKeyLeftAlt);
+			AddExpectedKey(EEventKeyDown,EStdKeyEnter);
+			AddExpectedKey(EEventKey,EStdKeyEnter,EKeyEnter,0,EModifierLeftFunc|EModifierFunc|EModifierLeftAlt|EModifierAlt|EModifierAutorepeatable);
+			AddExpectedKey(EEventKey,EStdKeyEnter,'a',2,EModifierLongKey|EModifierLeftFunc|EModifierFunc|EModifierLeftAlt|EModifierAlt|EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp,EStdKeyEnter);
+			AddExpectedKey(EEventKeyUp,EStdKeyLeftAlt);
+			AddExpectedKey(EEventKeyUp,EStdKeyLeftFunc);
 			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
 			break;
 		case 4:
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,'Z');
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+3*time.Int());
+			DelayForRepeatEvents(3, 1);
 			iTest->SimulateKey(TRawEvent::EKeyDown,'Y');
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+2*time.Int());
+			DelayForRepeatEvents(2, 1);
 			iTest->SimulateKey(TRawEvent::EKeyUp,'Z');
 			iTest->SimulateKey(TRawEvent::EKeyUp,'Y');
 			AddExpectedKey(EEventKeyDown,'Z');
@@ -3934,13 +3995,13 @@
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,'Z');
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+3*time.Int());
+			DelayForRepeatEvents(3, 1);
 			iTest->SimulateKey(TRawEvent::EKeyDown,'Y');
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+5*time.Int()/2);
+			DelayForRepeatEvents(5, 2);
 			iTest->SimulateKey(TRawEvent::EKeyUp,'Y');
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+2*time.Int());
+			DelayForRepeatEvents(2, 1);
 			iTest->SimulateKey(TRawEvent::EKeyUp,'Z');
 			AddExpectedKey(EEventKeyDown,'Z');
 			AddExpectedKey(EEventKey,'Z','z');
@@ -3957,12 +4018,12 @@
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,'X');
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+3*time.Int());
+			DelayForRepeatEvents(3, 1);
 			iTest->SimulateKeyDownUp(EStdKeySpace);
 			TheClient->iWs.Flush();
 			if(!iTest->IsFullRomL())
 				{
-				User::After(initialTime.Int()+2*time.Int());
+				DelayForRepeatEvents(2, 1);
 				}
 			iTest->SimulateKey(TRawEvent::EKeyUp,'X');
 			AddExpectedKey(EEventKeyDown,'X');
@@ -3983,14 +4044,14 @@
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,'X');
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+5*time.Int());
+			DelayForRepeatEvents(5, 1);
 			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeySpace);
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+time.Int()/3);
+			DelayForRepeatEvents(1, 3);
 			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeySpace);
 			TheClient->iWs.Flush();
 			User::ResetInactivityTime();
-			User::After(initialTime.Int()+4*time.Int());
+			DelayForRepeatEvents(4, 1);
 			iTest->SimulateKey(TRawEvent::EKeyUp,'X');
 			AddExpectedKey(EEventKeyDown,'X');
 			AddExpectedKey(EEventKey,'X','x');
@@ -4008,7 +4069,7 @@
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeySpace);
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+5*time.Int());
+			DelayForRepeatEvents(5, 1);
 			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeySpace);
 			AddExpectedKey(EEventKeyDown,EStdKeySpace);
 			AddExpectedKey(EEventKey,EStdKeySpace,'c',1);
@@ -4022,10 +4083,10 @@
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeySpace);
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+5*time.Int()/2);
+			DelayForRepeatEvents(5, 2);
 			iTest->SimulateKeyDownUp(EStdKeyEscape);
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+3*time.Int());
+			DelayForRepeatEvents(3, 1);
 			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeySpace);
 			AddExpectedKey(EEventKeyDown,EStdKeySpace);
 			AddExpectedKey(EEventKey,EStdKeySpace,' ');
@@ -4045,33 +4106,36 @@
 			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeySpace);
 			TheClient->iWs.Flush();
 			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
-			User::After(initialTime.Int()+5*time.Int());
+			DelayForRepeatEvents(5, 1);
 			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeySpace);
 			AddExpectedKey(EEventKeyDown,EStdKeySpace);
 			AddExpectedKey(EEventKey,EStdKeySpace,' ');
 			AddExpectedKey(EEventKeyUp,EStdKeySpace);
 			break;
 		case 11:
-			//Cancel a capture key up and down event whilst a repeat is underway
-			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureKeyUpAndDowns(EStdKeySpace,0,0);
+			// Cancel a key up/down capture whilst a repeat is underway.
+			// This should have no effect since only key press events are
+			// repeated.
+			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureKeyUpAndDowns('X',0,0);
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,'X');
 			TheClient->iWs.Flush();
 			iQueueClient->iGroup->GroupWin()->CancelCaptureKeyUpAndDowns(iCaptureKey);
-			User::After(initialTime.Int()+5*time.Int());
+			DelayForRepeatEvents(5, 1);
 			iTest->SimulateKey(TRawEvent::EKeyUp,'X');
 			AddExpectedKey(EEventKeyDown,'X');
 			AddExpectedKey(EEventKey,'X','x');
+			AddExpectedKey(EEventKey,'X','x',2);
 			AddExpectedKey(EEventKeyUp,'X');
 			break;
 		case 12:
 			//Cancel a capture key event whilst a repeat is underway
-			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureKey(EStdKeySpace,0,0);
+			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureKey('y',0,0);
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,'Y');
 			TheClient->iWs.Flush();
 			iQueueClient->iGroup->GroupWin()->CancelCaptureKey(iCaptureKey);
-			User::After(initialTime.Int()+5*time.Int());
+			DelayForRepeatEvents(5, 1);
 			iTest->SimulateKey(TRawEvent::EKeyUp,'Y');
 			AddExpectedKey(EEventKeyDown,'Y');
 			AddExpectedKey(EEventKey,'Y','y');
@@ -4079,13 +4143,13 @@
 			break;
 		case 13:
 			//Variation on case 12 i.e. change in the timing of the CancelCaptureKey call
-			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureKey(EStdKeySpace,0,0);
+			iCaptureKey=iQueueClient->iGroup->GroupWin()->CaptureKey('z',0,0);
 			iQueueClient->iWs.Flush();
 			iTest->SimulateKey(TRawEvent::EKeyDown,'Z');
 			TheClient->iWs.Flush();
-			User::After(initialTime.Int()+5*time.Int()/2);
+			DelayForRepeatEvents(5, 2);
 			iQueueClient->iGroup->GroupWin()->CancelCaptureKey(iCaptureKey);
-			User::After(initialTime.Int()+5*time.Int()/2);
+			DelayForRepeatEvents(5, 2);
 			iTest->SimulateKey(TRawEvent::EKeyUp,'Z');
 			AddExpectedKey(EEventKeyDown,'Z');
 			AddExpectedKey(EEventKey,'Z','z');
@@ -4102,7 +4166,7 @@
 			iTest->SimulateKey(TRawEvent::EKeyDown,EStdKeySpace);
 			TheClient->iWs.Flush();
 			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
-			User::After(initialTime.Int()+time.Int()/3);
+			DelayForRepeatEvents(1, 3);
 
 			TheClient->iGroup->GroupWin()->CancelCaptureKey(shortCaptKey);
 			iTest->SimulateKey(TRawEvent::EKeyUp,EStdKeySpace);
@@ -4110,6 +4174,132 @@
 			AddExpectedKey(EEventKeyUp,EStdKeySpace);
 			}
 			break;
+		case 15:
+			// @SYMPREQ 417-61800: Check that long key events are marked with
+			// EModifierLongKey and short events are not.
+			iCaptureKey = iQueueClient->iGroup->GroupWin()->CaptureLongKey('m', 'm', 0, 0, 0, ELongCaptureNormal);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, 'M');
+			TheClient->iWs.Flush();
+			DelayForRepeatEvents(1, 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp, 'M');
+			AddExpectedKey(EEventKeyDown, 'M', 0, 0, 0);
+			AddExpectedKey(EEventKey, 'M', 'm', 0, EModifierAutorepeatable);
+			AddExpectedKey(EEventKey, 'M', 'm', 1, EModifierLongKey | EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp, 'M', 0, 0, 0);
+			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
+			break;
+		case 16:
+			CheckLongkeyCaptureWithPriority(ELongkeyCaptureDiffPriority);
+			break;
+		case 17:
+			CheckLongkeyCaptureWithPriority(ELongkeyCaptureSamePriority);
+			break;
+		case 18:
+			// Test CaptureLongKey() with flag value ELongCaptureWaitShort
+			// when key is not held down long enough to generate a long event.
+			// Verify that short event is delivered when the key is released.
+			iCaptureKey = iQueueClient->iGroup->GroupWin()->CaptureLongKey('p', 'p', 0, 0, 0, ELongCaptureWaitShort);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, 'P');
+			TheClient->iWs.Flush();
+			User::After(iKeyBoardRepeatInitialDelay.Int() / 2);
+			iTest->SimulateKey(TRawEvent::EKeyUp, 'P');
+			TheClient->iWs.Flush();
+			iTest->SimulateKeyDownUp(EStdKeySpace);
+			AddExpectedKey(EEventKeyDown, 'P');
+			AddExpectedKey(EEventKey, 'P', 'p', 0, EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp, 'P');
+			AddExpectedKeyDownUp(EStdKeySpace, ' ');
+			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
+			break;
+		case 19:
+			{
+			// Cancel a capture key event whilst a repeat is underway for a
+			// different capture. This should not cancel repeating.
+			iCaptureKey = iQueueClient->iGroup->GroupWin()->CaptureKey('q', 0, 0);
+			TInt captureKey2 = iQueueClient->iGroup->GroupWin()->CaptureKey('r', 0, 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, 'Q');
+			TheClient->iWs.Flush();
+			iQueueClient->iGroup->GroupWin()->CancelCaptureKey(captureKey2);
+			DelayForRepeatEvents(5, 1);
+			iTest->SimulateKey(TRawEvent::EKeyUp, 'Q');
+			AddExpectedKey(EEventKeyDown, 'Q');
+			AddExpectedKey(EEventKey, 'Q', 'q', 0, EModifierAutorepeatable);
+			AddExpectedKey(EEventKey, 'Q', 'q', 2, EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp, 'Q');
+			iQueueClient->iGroup->GroupWin()->CancelCaptureKey(iCaptureKey);
+			}
+			break;
+		case 20:
+			{
+			// Cancel a long capture key event whilst a repeat is underway for
+			// a different capture. This should not cancel repeating.
+			iCaptureKey = iQueueClient->iGroup->GroupWin()->CaptureLongKey('s', 's', 0, 0, 2, ELongCaptureNormal|ELongCaptureRepeatEvents);
+			TInt captureKey2 = iQueueClient->iGroup->GroupWin()->CaptureLongKey('t', 't', 0, 0, 2, ELongCaptureNormal|ELongCaptureRepeatEvents);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, 'S');
+			TheClient->iWs.Flush();
+			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(captureKey2);
+			DelayForRepeatEvents(5, 1);
+			iTest->SimulateKey(TRawEvent::EKeyUp, 'S');
+			AddExpectedKey(EEventKeyDown, 'S');
+			AddExpectedKey(EEventKey, 'S', 's', 0, EModifierAutorepeatable);
+			AddExpectedKey(EEventKey, 'S', 's', 2, EModifierLongKey | EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp, 'S');
+			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
+			}
+			break;
+		case 21:
+			{
+			// Test CaptureLongKey() with a user specified initial repeat time.
+			// Simulate holding down the key for a period shorter than the
+			// specified delay. Verify that a long key event is NOT generated.
+			// (Note that the period is longer than the default initial repeat
+			// time, thus proving that CaptureLongKey() has honoured the delay
+			// argument.)
+			TTimeIntervalMicroSeconds32 delay(iKeyBoardRepeatInitialDelay.Int() * 4);
+			iCaptureKey = iQueueClient->iGroup->GroupWin()->CaptureLongKey(delay, 'u', 'u', 0, 0, 0, ELongCaptureNormal);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, 'U');
+			TheClient->iWs.Flush();
+			User::After(delay.Int() / 2);
+			iTest->SimulateKey(TRawEvent::EKeyUp, 'U');
+			TheClient->iWs.Flush();
+			iTest->SimulateKeyDownUp(EStdKeySpace);
+			AddExpectedKey(EEventKeyDown, 'U');
+			AddExpectedKey(EEventKey, 'U', 'u', 0, EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp, 'U');
+			AddExpectedKeyDownUp(EStdKeySpace, ' ');
+			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
+			}
+			break;
+		case 22:
+			{
+			// Test CaptureLongKey() with a user specified initial repeat time.
+			// Simulate holding down the key for a period longer than the
+			// specified delay. Verify that a long key event is generated.
+			// (Note that the period is shorter than the default initial repeat
+			// time, thus proving that CaptureLongKey() has honoured the delay
+			// argument.)
+			TTimeIntervalMicroSeconds32 delay(iKeyBoardRepeatInitialDelay.Int() / 4);
+			iCaptureKey = iQueueClient->iGroup->GroupWin()->CaptureLongKey(delay, 'v', 'v', 0, 0, 0, ELongCaptureNormal);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, 'V');
+			TheClient->iWs.Flush();
+			User::After(delay.Int() * 2);
+			iTest->SimulateKey(TRawEvent::EKeyUp, 'V');
+			TheClient->iWs.Flush();
+			iTest->SimulateKeyDownUp(EStdKeySpace);
+			AddExpectedKey(EEventKeyDown, 'V');
+			AddExpectedKey(EEventKey, 'V', 'v', 0, EModifierAutorepeatable);
+			AddExpectedKey(EEventKey, 'V', 'v', 1, EModifierLongKey | EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp, 'V');
+			AddExpectedKeyDownUp(EStdKeySpace, ' ');
+			iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
+			}
+			break;
 		default:
 			CActiveScheduler::Stop();
 			break;
@@ -4117,6 +4307,485 @@
 	TheClient->iWs.Flush();
 	}
 
+/** Function used for checking CaptureLongKey() works fine with different priorities.
+
+If two window groups have requested capture of the same key with different priorities, 
+then the event should be delivered to the group that specified higher priority 
+(even if it is in the background).
+
+If two window groups have requested capture of the same key with same priorities,
+then the event should be delivered to the group that requested capture most recently.
+
+@param aTestType Enum value specifying test with same priority or with different priority
+*/
+void CTEventTest::CheckLongkeyCaptureWithPriority(TLongkeyCapPriorityTests aTestType)
+	{
+	TInt ordinalPriority = TheClient->iGroup->GroupWin()->OrdinalPriority();
+	TInt ordinalPosition = TheClient->iGroup->GroupWin()->OrdinalPosition();
+	// Bring other window group to foreground and request capture with lower/same priority
+	// And request capture from iQueueClient group window with higher priority
+	TheClient->iGroup->GroupWin()->SetOrdinalPosition(0, 10);
+	TInt capKeyFrontWin = TheClient->iGroup->GroupWin()->CaptureLongKey('m', 'm', 0, 0, (aTestType == ELongkeyCaptureDiffPriority ? KLongKeyCaptureLowPriority : KLongKeyCaptureHighPriority), ELongCaptureNormal);
+	iCaptureKey = iQueueClient->iGroup->GroupWin()->CaptureLongKey('m', 'm', 0, 0, KLongKeyCaptureHighPriority, ELongCaptureNormal);
+	iQueueClient->iWs.Flush();
+	iTest->SimulateKey(TRawEvent::EKeyDown, 'M');
+	TheClient->iWs.Flush();
+	DelayForRepeatEvents(1, 3);
+	iTest->SimulateKey(TRawEvent::EKeyUp, 'M');
+	AddExpectedEvent(EEventFocusLost);
+	//Note: Button down/up events along with immediate key events are not delivered to iQueueCLient's window group
+	//as they are sent to foreground/focused window group
+	AddExpectedKey(EEventKey, 'M', 'm', 1, EModifierLongKey | EModifierAutorepeatable);
+	iQueueClient->iGroup->GroupWin()->CancelCaptureLongKey(iCaptureKey);
+	TheClient->iGroup->GroupWin()->CancelCaptureLongKey(capKeyFrontWin);
+	TheClient->iGroup->GroupWin()->SetOrdinalPosition(ordinalPosition, ordinalPriority);
+	AddExpectedEvent(EEventFocusGained);
+	}
+
+/** Function used for delaying current thread so that repeat events can be generated.
+
+It uses iKeyBoardRepeatInitialDelay and iKeyBoardRepeatNextDelay variables to get the desired delay.
+The idea is to wait for initial delay + some extra value so that first repeat is generated.
+For more than one repeat events, wait will be initial delay + next delay + some extra value, and so on.
+
+The extra value is taken as fraction of iKeyBoardRepeatNextDelay.
+
+@param aNumeratorFracVal Numerator value of the fraction.
+@param aDenominatorFracVal Denominator value of the fraction.
+*/
+void CTEventTest::DelayForRepeatEvents(TInt aNumeratorFracVal, TInt aDenominatorFracVal)
+	{
+	if (!aNumeratorFracVal || !aDenominatorFracVal)
+		return;
+	User::After(iKeyBoardRepeatInitialDelay.Int() + (iKeyBoardRepeatNextDelay.Int()*aNumeratorFracVal/aDenominatorFracVal));
+	}
+
+#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA  	
+void CTEventTest::KeyEventTranslation_NextSetOfEventsL()
+	{
+	TTimeIntervalMicroSeconds32 initialTime;
+	TTimeIntervalMicroSeconds32 time;
+	TheClient->iWs.GetKeyboardRepeatRate(initialTime, time);
+
+	RWindowGroup* wg = iQueueClient->iGroup->GroupWin();
+
+	#if defined(LOGGING)
+		TLogMessageText logMessageText;
+		_LIT(KSet,"KeyEventTranslation SetOfEvents: %d of 5");
+		logMessageText.Format(KSet,iEventSet);
+		INFO_PRINTF1(logMessageText);
+	#endif
+
+	switch (iEventSet++)
+		{
+		case 0:
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKeyDownUp('A');
+			AddExpectedEvent(EEventFocusGained);
+			AddExpectedKeyDownUp('A','a');
+			break;
+		case 1:
+			// Test key event translation using CaptureKey()
+			iCaptureKey = wg->CaptureKey(EKeyDevice0, 0, 0);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKeyDownUp(EStdKeyDevice1);
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKeyDown, EStdKeyDevice1, 0, 0);
+			AddExpectedKey(EEventKey, EStdKeyDevice1, EKeyDevice0, 0);
+			AddExpectedKey(EEventKeyUp, EStdKeyDevice1, 0, 0);
+			wg->CancelCaptureKey(iCaptureKey);
+			break;
+		case 2:
+			// Test key event translation using CaptureKeyUpAndDowns()
+			iCaptureKey = wg->CaptureKeyUpAndDowns(EStdKeyDevice0, 0, 0);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKeyDownUp(EStdKeyDevice1);
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKeyDown, EStdKeyDevice0, 0, 0);
+			AddExpectedKey(EEventKey, EStdKeyDevice1, EKeyDevice1, 0);
+			AddExpectedKey(EEventKeyUp, EStdKeyDevice0, 0, 0);
+			wg->CancelCaptureKeyUpAndDowns(iCaptureKey);
+			break;
+		case 3:
+			// Test key event translation using CaptureLongKey()
+			iCaptureKey = wg->CaptureLongKey(EKeyDevice0, EKeyDevice0, 0, 0, 0, ELongCaptureNormal);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyDevice1);
+			TheClient->iWs.Flush();
+			User::After(initialTime.Int() + time.Int() / 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyDevice1);
+			TheClient->iWs.Flush();
+
+			AddExpectedKey(EEventKeyDown, EStdKeyDevice1, 0, 0);
+			AddExpectedKey(EEventKey, EStdKeyDevice1, EKeyDevice1, 0, EModifierAutorepeatable);
+			AddExpectedKey(EEventKey, EStdKeyDevice1, EKeyDevice0, 1, EModifierLongKey | EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp, EStdKeyDevice1, 0, 0);
+
+			wg->CancelCaptureLongKey(iCaptureKey);
+			break;
+		case 4:
+			// Negative test: check that the capture key code listed in the
+			// translation table of the Key Routing Plug-in is not translated
+			// in the absence of any capture request for the mapped key.
+			iTest->SimulateKeyDownUp(EStdKeyDevice1);
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKeyDown, EStdKeyDevice1, 0, 0);
+			AddExpectedKey(EEventKey, EStdKeyDevice1, EKeyDevice1, 0);
+			AddExpectedKey(EEventKeyUp, EStdKeyDevice1, 0, 0);
+			break;
+		default:
+			CActiveScheduler::Stop();
+			break;
+		}
+
+	TheClient->iWs.Flush();
+	}
+
+void CTEventTest::KeyEventBlocking_NextSetOfEventsL()
+	{
+	TTimeIntervalMicroSeconds32 initialTime;
+	TTimeIntervalMicroSeconds32 time;
+	TheClient->iWs.GetKeyboardRepeatRate(initialTime, time);
+
+	RWindowGroup* wg = iQueueClient->iGroup->GroupWin();
+
+	#if defined(LOGGING)
+		TLogMessageText logMessageText;
+		_LIT(KSet,"KeyEventBlocking SetOfEvents: %d of 5");
+		logMessageText.Format(KSet,iEventSet);
+		INFO_PRINTF1(logMessageText);
+	#endif
+
+	switch (iEventSet++)
+		{
+		case 0:
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKeyDownUp('A');
+			AddExpectedEvent(EEventFocusGained);
+			AddExpectedKeyDownUp('A','a');
+			break;
+		case 1:
+			// Simulate pressing a blocked key (Device3) while no
+			// key capture is in effect.
+			iTest->SimulateKeyDownUp(EStdKeyDevice3);
+			iTest->SimulateKeyDownUp('B');
+			TheClient->iWs.Flush();
+			AddExpectedKeyDownUp('B','b');
+			break;
+		case 2:
+			// Use RWindowGroup::CaptureKey() to capture EKeyDevice3
+			// and simulate pressing the blocked key again.
+			iCaptureKey = wg->CaptureKey(EKeyDevice3, 0, 0);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKeyDownUp(EStdKeyDevice3);
+			iTest->SimulateKeyDownUp('B');
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKey, EStdKeyDevice3, EKeyDevice3, 0);
+			AddExpectedKeyDownUp('B','b');
+			wg->CancelCaptureKey(iCaptureKey);
+			break;
+		case 3:
+			// Repeat using CaptureKeyUpAndDowns()
+			iCaptureKey = wg->CaptureKeyUpAndDowns(EStdKeyDevice3, 0, 0);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKeyDownUp(EStdKeyDevice3);
+			iTest->SimulateKeyDownUp('B');
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKeyDown, EStdKeyDevice3, 0, 0);
+			AddExpectedKey(EEventKeyUp, EStdKeyDevice3, 0, 0);
+			AddExpectedKeyDownUp('B','b');
+			wg->CancelCaptureKeyUpAndDowns(iCaptureKey);
+			break;
+		case 4:
+			// Repeat using CaptureLongKey()
+			iCaptureKey = wg->CaptureLongKey(EKeyDevice3, EKeyDevice3, 0, 0, 0, ELongCaptureNormal);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyDevice3);
+			TheClient->iWs.Flush();
+			User::After(initialTime.Int() + time.Int() / 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyDevice3);
+			iTest->SimulateKeyDownUp('B');
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKey, EStdKeyDevice3, EKeyDevice3, 1, EModifierLongKey | EModifierAutorepeatable);
+			AddExpectedKeyDownUp('B','b');
+			wg->CancelCaptureLongKey(iCaptureKey);
+			break;
+		default:
+			CActiveScheduler::Stop();
+			break;
+		}
+
+	TheClient->iWs.Flush();
+	}
+
+void CTEventTest::KeyEventAppRestriction_NextSetOfEventsL()
+	{
+	TTimeIntervalMicroSeconds32 initialTime;
+	TTimeIntervalMicroSeconds32 time;
+	TheClient->iWs.GetKeyboardRepeatRate(initialTime, time);
+
+	RWindowGroup* wg = iQueueClient->iGroup->GroupWin();
+
+	#if defined(LOGGING)
+		TLogMessageText logMessageText;
+		_LIT(KSet,"KeyEventAppRestriction SetOfEvents: %d of 4");
+		logMessageText.Format(KSet,iEventSet);
+		INFO_PRINTF1(logMessageText);
+	#endif
+
+	switch (iEventSet++)
+		{
+		case 0:
+			// Make window group non-focusable so that it receives only
+			// keys that are captured and not those that are default-routed.
+			wg->EnableReceiptOfFocus(EFalse);
+			iQueueClient->iWs.Flush();
+			AddExpectedEvent(EEventFocusGained);
+			AddExpectedEvent(EEventFocusLost);
+			break;
+		case 1:
+			// Using RWindowGroup::CaptureKey(), attempt to capture a key
+			// that is restricted by UID to another application.
+			iCaptureKey = wg->CaptureKey(EKeyF20, 0, 0);
+			TEST(iCaptureKey == KErrPermissionDenied);
+			// Now capture a key that is restricted to the current
+			// application's UID and simulate pressing the restricted key.
+			iCaptureKey = wg->CaptureKey(EKeyF21, 0, 0);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+			// Can't use SimulateKeyDownUp() here due to its check that scan
+			// codes are not in the range corresponding to lower case letters
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF21);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF21);
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKey, EStdKeyF21, EKeyF21, 0);
+			wg->CancelCaptureKey(iCaptureKey);
+			break;
+		case 2:
+			// Repeat using CaptureKeyUpAndDowns()
+			iCaptureKey = wg->CaptureKeyUpAndDowns(EStdKeyF20, 0, 0);
+			TEST(iCaptureKey == KErrPermissionDenied);
+			iCaptureKey = wg->CaptureKeyUpAndDowns(EStdKeyF21, 0, 0);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF21);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF21);
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKeyDown, EStdKeyF21, 0, 0);
+			AddExpectedKey(EEventKeyUp, EStdKeyF21, 0, 0);
+			wg->CancelCaptureKeyUpAndDowns(iCaptureKey);
+			break;
+		case 3:
+			// Repeat using CaptureLongKey()
+			iCaptureKey = wg->CaptureLongKey(EKeyF20, EKeyF20, 0, 0, 0, ELongCaptureNormal);
+			TEST(iCaptureKey == KErrPermissionDenied);
+			iCaptureKey = wg->CaptureLongKey(EKeyF21, EKeyF21, 0, 0, 0, ELongCaptureNormal);
+			TEST(iCaptureKey >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF21);
+			TheClient->iWs.Flush();
+			User::After(initialTime.Int() + time.Int() / 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF21);
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKey, EStdKeyF21, EKeyF21, 1, EModifierLongKey | EModifierAutorepeatable);
+			wg->CancelCaptureLongKey(iCaptureKey);
+			break;
+		default:
+			CActiveScheduler::Stop();
+			break;
+		}
+
+	TheClient->iWs.Flush();
+	}
+
+void CTEventTest::KeyEventAppPriority_NextSetOfEventsL()
+	{
+	TTimeIntervalMicroSeconds32 initialTime;
+	TTimeIntervalMicroSeconds32 time;
+	TheClient->iWs.GetKeyboardRepeatRate(initialTime, time);
+
+	RWindowGroup* wg = iQueueClient->iGroup->GroupWin();
+	TInt handle1 = 0;
+	TInt handle2 = 0;
+	TInt handle3 = 0;
+	TInt handle4 = 0;
+	TInt handle5 = 0;
+	TInt handle6 = 0;
+
+	#if defined(LOGGING)
+		TLogMessageText logMessageText;
+		_LIT(KSet,"KeyEventAppPriority SetOfEvents: %d of 5");
+		logMessageText.Format(KSet,iEventSet);
+		INFO_PRINTF1(logMessageText);
+	#endif
+
+	switch (iEventSet++)
+		{
+		case 0:
+			SpawnCaptureAppL(iCaptureApp1);
+			iQueueClient->iWs.Flush();
+			AddExpectedEvent(EEventFocusGained);
+			AddExpectedEvent(EEventFocusLost);
+			break;
+		case 1:
+			// Use RWindowGroup::CaptureKey() to capture EKeyF22
+			// and EKeyF23 with priority 0. Simulate pressing both
+			// keys. Since the current application has precedence by UID
+			// for capture of EKeyF22, it should receive that key
+			// but should not receive EKeyF23.
+			handle1 = wg->CaptureKey(EKeyF22, 0, 0);
+			handle2 = wg->CaptureKey(EKeyF23, 0, 0);
+			TEST(handle1 >= 0);
+			TEST(handle2 >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF22);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF22);
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF23);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF23);
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKey, EStdKeyF22, EKeyF22, 0);
+			wg->CancelCaptureKey(handle1);
+			wg->CancelCaptureKey(handle2);
+			break;
+		case 2:
+			// Repeat using CaptureKeyUpAndDowns()
+			handle1 = wg->CaptureKeyUpAndDowns(EStdKeyF22, 0, 0);
+			handle2 = wg->CaptureKeyUpAndDowns(EStdKeyF23, 0, 0);
+			TEST(handle1 >= 0);
+			TEST(handle2 >= 0);
+			iQueueClient->iWs.Flush();
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF22);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF22);
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF23);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF23);
+			TheClient->iWs.Flush();
+			AddExpectedKey(EEventKeyDown, EStdKeyF22, 0, 0);
+			AddExpectedKey(EEventKeyUp, EStdKeyF22, 0, 0);
+			wg->CancelCaptureKeyUpAndDowns(handle1);
+			wg->CancelCaptureKeyUpAndDowns(handle2);
+			break;
+		case 3:
+			// Repeat using CaptureLongKey()
+			handle1 = wg->CaptureLongKey(EKeyF22, EKeyF22, 0, 0, 0, ELongCaptureNormal);
+			handle2 = wg->CaptureLongKey(EKeyF23, EKeyF23, 0, 0, 0, ELongCaptureNormal);
+			TEST(handle1 >= 0);
+			TEST(handle2 >= 0);
+			iQueueClient->iWs.Flush();
+
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF22);
+			TheClient->iWs.Flush();
+			User::After(initialTime.Int() + time.Int() / 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF22);
+
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF23);
+			TheClient->iWs.Flush();
+			User::After(initialTime.Int() + time.Int() / 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF23);
+			TheClient->iWs.Flush();
+
+			AddExpectedKey(EEventKey, EStdKeyF22, EKeyF22, 1, EModifierLongKey | EModifierAutorepeatable);
+			wg->CancelCaptureLongKey(handle1);
+			wg->CancelCaptureLongKey(handle2);
+			break;
+		case 4:
+			// Repeat with additional capture requests for improved code
+			// coverage. (Also verifies that UID-based precedence works even
+			// when another app makes the most recent capture request.)
+			// Spawn a second capture app so that requests occur in the
+			// following order:
+			// 1. CaptureApp1, priority 1 (outstanding)
+			// 2. Current App, priority 0, precedence by UID
+			// 3. CaptureApp2, priority 1
+			// Note that all three capture types are tested together here.
+			handle1 = wg->CaptureKey(EKeyF22, 0, 0);
+			handle2 = wg->CaptureKey(EKeyF23, 0, 0);
+			handle3 = wg->CaptureKeyUpAndDowns(EStdKeyF22, 0, 0);
+			handle4 = wg->CaptureKeyUpAndDowns(EStdKeyF23, 0, 0);
+			handle5 = wg->CaptureLongKey(EKeyF22, EKeyF22, 0, 0, 0, ELongCaptureNormal);
+			handle6 = wg->CaptureLongKey(EKeyF23, EKeyF23, 0, 0, 0, ELongCaptureNormal);
+			TEST(handle1 >= 0);
+			TEST(handle2 >= 0);
+			TEST(handle3 >= 0);
+			TEST(handle4 >= 0);
+			TEST(handle5 >= 0);
+			TEST(handle6 >= 0);
+			iQueueClient->iWs.Flush();
+
+			SpawnCaptureAppL(iCaptureApp2);
+
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF22);
+			TheClient->iWs.Flush();
+			User::After(initialTime.Int() + time.Int() / 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF22);
+
+			iTest->SimulateKey(TRawEvent::EKeyDown, EStdKeyF23);
+			TheClient->iWs.Flush();
+			User::After(initialTime.Int() + time.Int() / 3);
+			iTest->SimulateKey(TRawEvent::EKeyUp, EStdKeyF23);
+			TheClient->iWs.Flush();
+
+			AddExpectedKey(EEventKeyDown, EStdKeyF22, 0, 0);
+			AddExpectedKey(EEventKey, EStdKeyF22, EKeyF22, 0);
+			AddExpectedKey(EEventKey, EStdKeyF22, EKeyF22, 1, EModifierLongKey | EModifierAutorepeatable);
+			AddExpectedKey(EEventKeyUp, EStdKeyF22, 0, 0);
+			wg->CancelCaptureKey(handle1);
+			wg->CancelCaptureKey(handle2);
+			wg->CancelCaptureKeyUpAndDowns(handle3);
+			wg->CancelCaptureKeyUpAndDowns(handle4);
+			wg->CancelCaptureLongKey(handle5);
+			wg->CancelCaptureLongKey(handle6);
+			break;
+		default:
+			iCaptureApp1.Kill(KErrNone);
+			iCaptureApp2.Kill(KErrNone);
+			iCaptureApp1.Close();
+			iCaptureApp2.Close();
+			CActiveScheduler::Stop();
+			break;
+		}
+
+	TheClient->iWs.Flush();
+	}
+
+/**
+Spawn another application that will capture the keys EKeyF22 and
+EKeyF23 with high priority.
+
+@param aProcess		Process to create
+*/
+void CTEventTest::SpawnCaptureAppL(RProcess& aProcess)
+	{
+	_LIT(KCaptureApp, "tevent_captureapp.exe");
+	TInt error = aProcess.Create(KCaptureApp, KNullDesC);
+	if (error != KErrNone)
+		{
+#if defined(LOGGING)
+		TLogMessageText logMessageText;
+		_LIT(KLog, "Cannot create capture app - error %d");
+		logMessageText.Format(KLog, error);
+		INFO_PRINTF1(logMessageText);
+#endif
+		User::Leave(error);
+		}
+
+	// Make rendezvous request to capture app
+	TRequestStatus status;
+	aProcess.Rendezvous(status);
+	aProcess.Resume();
+
+	// Wait for capture app to make its capture requests
+	User::WaitForRequest(status);
+	TEST(status.Int() == KErrNone);
+	}
+#endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA  	
+
 #define PASSWORD_START_OF_DAY 4
 void CTEventTest::Password_NextSetOfEvents()
 	{
@@ -6316,15 +6985,19 @@
 	_LIT(KTest25,"Mismatched Pointer Events");
 	_LIT(KTest26,"Pointer Buffer Purge");
 	_LIT(KTest27,"TRawEvent test for Repeats");
+#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA 
+	_LIT(KTest28,"Translation of key events by routing plug-in");
+	_LIT(KTest29,"Blocking of key events by routing plug-in");
+	_LIT(KTest30,"App UID based restriction of key capture");
+	_LIT(KTest31,"App UID based routing of key events");
 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS            
-#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA 
-	_LIT(KTest28,"Transparent Surface Visibility Changed Events 1");
-	_LIT(KTest29,"Transparent Surface Visibility Changed Events 2");
-	_LIT(KTest30,"Transparent Surface Visibility Changed Events 3");
+	_LIT(KTest32,"Transparent Surface Visibility Changed Events 1");
+	_LIT(KTest33,"Transparent Surface Visibility Changed Events 2");
+	_LIT(KTest34,"Transparent Surface Visibility Changed Events 3");
+#endif // SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
 #endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
-#endif // SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
-	_LIT(KTest31A,"Initialize Queue Size without inactive queue");
-	_LIT(KTest31B,"Initialize Queue Size with inactive queue");	
+	_LIT(KTest35A,"Initialize Queue Size without inactive queue");
+	_LIT(KTest35B,"Initialize Queue Size with inactive queue");	
 	
 	if (!TestBase()->ConfigurationSupportsPointerEventTesting())
 	    {
@@ -6644,15 +7317,16 @@
 
 @SYMDEF             DEF081259
 
-@SYMTestCaseDesc    Send events for capturing large areas of text
+@SYMTestCaseDesc    Test RWindowGroup::CaptureLongKey()
 
 @SYMTestPriority    High
 
 @SYMTestStatus      Implemented
 
-@SYMTestActions     Send events for capturing large areas of text
-
-@SYMTestExpectedResults The events are sent to the window without
+@SYMTestActions     Simulate long key presses and check that long key capture
+					and key repeat work as expected.
+
+@SYMTestExpectedResults The correct key events are sent to the window without
 						error
 */
 		case 15:
@@ -6925,8 +7599,118 @@
 		    RunTestsL();
 		    break;
 		    
+#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA            
+/**
+@SYMTestCaseID      GRAPHICS-WSERV-0751, GRAPHICS-WSERV-0752, GRAPHICS-WSERV-0753
+@SYMPREQ			417-61800
+@SYMTestCaseDesc    Test translation of key events by Key Event Routing plug-in
+@SYMTestPriority    High
+@SYMTestStatus      Implemented
+@SYMTestActions     Use RWindowGroup::CaptureKey() to capture pseudo key
+					Device0 (key code EKeyDevice0, scan code EStdKeyDevice0).
+					Simulate pressing key Device1.
+					Repeat using CaptureKeyUpAndDowns().
+					Repeat using CaptureLongKey().
+					Repeat without any capture requests.
+@SYMTestExpectedResults
+					The key event delivered contains the key or scan code for
+					Device0, if captured. When using CaptureKey() and
+					CaptureLongKey(), only the key code is translated. Using
+					CaptureKeyUpAndDowns(), only the scan code is translated.
+
+Note: this test requires an entry in the translation table of the Key Routing
+Plug-in to map Device0 to Device1 at capture request time.
+*/
+		case 28:
+            ((CTEventTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0751"));
+            iTest->LogSubTest(KTest28);
+            RunTestsL();
+            break;
+
+/**
+@SYMTestCaseID      GRAPHICS-WSERV-0760, GRAPHICS-WSERV-0761, GRAPHICS-WSERV-0762
+@SYMPREQ			417-61800
+@SYMTestCaseDesc    Test blocking of key events by Key Event Routing plug-in
+@SYMTestPriority    High
+@SYMTestStatus      Implemented
+@SYMTestActions     Simulate pressing a blocked key (Device3) while no
+					key capture is in effect.
+					Use RWindowGroup::CaptureKey() to capture EKeyDevice3
+					and simulate pressing the blocked key again.
+					Repeat using CaptureKeyUpAndDowns().
+					Repeat using CaptureLongKey().
+@SYMTestExpectedResults
+					The blocked key event is only delivered when captured and
+					is not routed to the focussed window group by default.
+
+Note: this test requires entries in the Blocked Key Table of the Reference
+Key Routing Plug-in for EKeyDevice3 and EStdKeyDevice3.
+*/
+		case 29:
+            ((CTEventTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0760"));
+            iTest->LogSubTest(KTest29);
+            RunTestsL();
+            break;
+
+/**
+@SYMTestCaseID      GRAPHICS-WSERV-0754, GRAPHICS-WSERV-0755, GRAPHICS-WSERV-0756
+@SYMPREQ			417-61800
+@SYMTestCaseDesc    Test application UID-based restriction of key capture by
+					Key Event Routing plug-in.
+@SYMTestPriority    High
+@SYMTestStatus      Implemented
+@SYMTestActions     Attempt to capture a key that is restricted by UID
+					to another application.
+					Use RWindowGroup::CaptureKey() to capture a key that is
+					restricted to the current application's UID.
+					Simulate pressing the second key.
+					Repeat using CaptureKeyUpAndDowns().
+					Repeat using CaptureLongKey().
+@SYMTestExpectedResults
+					Capture of the first key fails with KErrPermissionDenied.
+					Capture of the second key succeeds and the key event is
+					delivered.
+
+Note: this test requires entries in the Restricted Key Table of the Reference
+Key Routing Plug-in for the chosen keys.
+*/
+		case 30:
+            ((CTEventTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0754"));
+            iTest->LogSubTest(KTest30);
+            RunTestsL();
+            break;
+
+/**
+@SYMTestCaseID      GRAPHICS-WSERV-0757, GRAPHICS-WSERV-0758, GRAPHICS-WSERV-0759
+@SYMPREQ			417-61800
+@SYMTestCaseDesc    Test application UID-based routing of key events by
+					Key Event Routing plug-in.
+@SYMTestPriority    High
+@SYMTestStatus      Implemented
+@SYMTestActions     Invoke another application to capture two different keys
+					with high priority using each of RWindowGroup::CaptureKey(),
+					CaptureKeyUpAndDowns() and CaptureLongKey(). One key of
+					each pair has precedence for capture by the current
+					application's UID (i.e. this test).
+					In the current application, use RWindowGroup::CaptureKey()
+					to capture both keys with lower priority.
+					Simulate pressing the keys.
+					Repeat using CaptureKeyUpAndDowns().
+					Repeat using CaptureLongKey().
+@SYMTestExpectedResults
+					The key event with UID-based precedence is delivered to
+					the current application but the other key is not.
+
+Note: this test requires entries in the Priority Application Table of the
+Reference Key Routing Plug-in for the chosen key.
+*/
+		case 31:
+            ((CTEventTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0757"));
+            iTest->LogSubTest(KTest31);
+            RunTestsL();
+            break;
+
 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS            
-#ifndef TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA            
 /**
 @SYMTestCaseID      GRAPHICS-WSERV-2669-0015
 @SYMREQ             REQ13202: Possibility for external layers to appear above UI layer
@@ -6938,9 +7722,9 @@
 @SYMTestActions     Call SetSurfaceTransparency(ETrue) on win2
 @SYMTestExpectedResults Win1 receives visibility event
 */            
-        case 28:
+        case 32:
             ((CTEventTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-2669-0015"));
-            iTest->LogSubTest(KTest28);
+            iTest->LogSubTest(KTest32);
             RunTestsL();
             break;
 /**
@@ -6955,9 +7739,9 @@
 @SYMTestActions     Delete win3
 @SYMTestExpectedResults Both win1 and win2 receive visibility events
 */            
-        case 29:
+        case 33:
             ((CTEventTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-2669-0016"));
-            iTest->LogSubTest(KTest29);
+            iTest->LogSubTest(KTest33);
             RunTestsL();
             break;
 /**
@@ -6971,13 +7755,13 @@
 @SYMTestActions     Move win2 to overlap win1
 @SYMTestExpectedResults No visibility event is received (win1 is still fully visible)
 */            
-        case 30:
+        case 34:
             ((CTEventTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-2669-0017"));
-            iTest->LogSubTest(KTest30);
+            iTest->LogSubTest(KTest34);
             RunTestsL();
             break;
+#endif // SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS  
 #endif // TEST_GRAPHICS_WSERV_TAUTOSERVER_NONNGA
-#endif // SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS  
 
 /**
 @SYMTestCaseID      GRAPHICS-WSERV-0559
@@ -6994,17 +7778,17 @@
 		case 28:
 #else
 #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
-		case 31:
+		case 35:
 #else
-		case 28:
+		case 32:
 #endif
 #endif
 		    // This test was moved to be the last test in the test suite, because it sometimes leaves events in the event queue, 
 		    //it can affect the results of other tests. This test case should be the last test in the test suite. 
 		    ((CTEventTestStep*)iStep)->SetTestStepID(_L("GRAPHICS-WSERV-0484"));
-		    iTest->LogSubTest(KTest31A);
+		    iTest->LogSubTest(KTest35A);
 		    InitializeQueueSizeTestL(EFalse);
-		    iTest->LogSubTest(KTest31B);
+		    iTest->LogSubTest(KTest35B);
 		    InitializeQueueSizeTestL(ETrue);
 		    break;    
 			
--- a/windowing/windowserver/test/tauto/TOOM.CPP	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/tauto/TOOM.CPP	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -66,6 +66,9 @@
 COomFailBase *CreateOomCaptureKeyUpDown(CTOom *aTest)
 	{return(new(ELeave) COomCaptureKeyUpDown(aTest));}
 
+COomFailBase *CreateOomLongKeyCapture(CTOom *aTest)
+	{return(new(ELeave) COomLongKeyCapture(aTest));}
+
 COomFailBase *CreateOomHotKey(CTOom *aTest)
 	{return(new(ELeave) COomHotKey(aTest));}
 
@@ -113,6 +116,7 @@
 	CreateOomPriorityKey,
 	CreateOomCaptureKey,
 	CreateOomCaptureKeyUpDown,
+	CreateOomLongKeyCapture,
 	CreateOomHotKey,
 	CreateOomGroupName,
 	CreateOomSprite,
@@ -421,7 +425,18 @@
 
 //
 
-COomCaptureKey::COomCaptureKey(CTOom *aTest) : COomSetup(aTest)
+COomCaptureKeyBase::COomCaptureKeyBase(CTOom *aTest) : COomSetup(aTest)
+	{}
+
+COomCaptureKeyBase::~COomCaptureKeyBase()
+	{}
+
+void COomCaptureKeyBase::ConstructL()
+	{
+	COomSetup::ConstructL();
+	}
+
+COomCaptureKey::COomCaptureKey(CTOom *aTest) : COomCaptureKeyBase(aTest)
 	{}
 
 COomCaptureKey::~COomCaptureKey()
@@ -433,11 +448,6 @@
 	return(_L("Capture key"));
 	}
 
-void COomCaptureKey::ConstructL()
-	{
-	COomSetup::ConstructL();
-	}
-
 /** Requests a capture keys for a previously created window group
 */
 TInt COomCaptureKey::Fail()
@@ -460,7 +470,7 @@
 
 //
 
-COomCaptureKeyUpDown::COomCaptureKeyUpDown(CTOom *aTest) : COomSetup(aTest)
+COomCaptureKeyUpDown::COomCaptureKeyUpDown(CTOom *aTest) : COomCaptureKeyBase(aTest)
 	{}
 
 COomCaptureKeyUpDown::~COomCaptureKeyUpDown()
@@ -472,11 +482,6 @@
 	return(_L("Capture up/down keys"));
 	}
 
-void COomCaptureKeyUpDown::ConstructL()
-	{
-	COomSetup::ConstructL();
-	}
-
 /** Requests the capture of key-up and key-down events for a previously created window group
 */
 TInt COomCaptureKeyUpDown::Fail()
@@ -499,6 +504,42 @@
 
 //
 
+COomLongKeyCapture::COomLongKeyCapture(CTOom *aTest) : COomCaptureKeyBase(aTest)
+	{}
+
+COomLongKeyCapture::~COomLongKeyCapture()
+	{
+	}
+
+TOomTestName COomLongKeyCapture::TestName()
+	{
+	_LIT(KLongKeyCapTestName, "Long key capture");
+	return KLongKeyCapTestName();
+	}
+
+/** 
+Requests capture of long key events for a previously created window group
+*/
+TInt COomLongKeyCapture::Fail()
+	{
+	for (iIndex=0; iIndex < KNumCapKeyRequest; iIndex++)
+		{
+		TInt ret=iWinGroup.CaptureLongKey(' ','a',0,0,2,ELongCaptureNormal);
+		if (ret<0)
+			return(ret);
+		iCapKey[iIndex]=ret;
+		}
+	return(KErrNone);
+	}
+
+void COomLongKeyCapture::ClearUpL()
+	{
+	for (TInt index=0;index<iIndex;index++)
+		iWinGroup.CancelCaptureLongKey(iCapKey[index]);
+	}
+
+//
+
 COomHotKey::COomHotKey(CTOom *aTest) : COomSetup(aTest)
 	{}
 
--- a/windowing/windowserver/test/tauto/TOOM.H	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/test/tauto/TOOM.H	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 1996-2010 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"
@@ -33,6 +33,8 @@
 
 class CTOom;
 
+const TInt KNumCapKeyRequest = 20;
+
 
 class COomFailBase : public CBase
 	{
@@ -192,32 +194,45 @@
 	TOomTestName TestName();
 	};
 
-class COomCaptureKey : public COomSetup
+class COomCaptureKeyBase : public COomSetup
+	{
+public:
+	COomCaptureKeyBase(CTOom *aTest);
+	~COomCaptureKeyBase();
+	void ConstructL();
+protected:
+	TInt32 iCapKey[KNumCapKeyRequest];
+	TInt iIndex;	
+	};
+
+class COomCaptureKey : public COomCaptureKeyBase
 	{
 public:
 	COomCaptureKey(CTOom *aTest);
 	~COomCaptureKey();
-	void ConstructL();
 	void ClearUpL();
 	TInt Fail();
 	TOomTestName TestName();
-private:
-	TInt32 iCapKey[20];
-	TInt iIndex;
 	};
 
-class COomCaptureKeyUpDown : public COomSetup
+class COomCaptureKeyUpDown : public COomCaptureKeyBase
 	{
 public:
 	COomCaptureKeyUpDown(CTOom *aTest);
 	~COomCaptureKeyUpDown();
-	void ConstructL();
 	void ClearUpL();
 	TInt Fail();
 	TOomTestName TestName();
-private:
-	TInt32 iCapKey[20];
-	TInt iIndex;
+	};
+
+class COomLongKeyCapture : public COomCaptureKeyBase
+	{
+public:
+	COomLongKeyCapture(CTOom *aTest);
+	~COomLongKeyCapture();
+	void ClearUpL();
+	TInt Fail();
+	TOomTestName TestName();
 	};
 
 class COomHotKey : public COomSetup
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/tauto/tdevicerotation.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,823 @@
+// Copyright (c) 2010 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:
+// Set of tests for Tracing Device Rotation. These tests generally test
+// RWsSession::IndicateAppOrientation(...).
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Nokia test code
+*/
+
+#include "tdevicerotation.h"
+#include "themeserverpropertydefine.h"
+#include "..\..\nga\server\renderorientationtracker.h" 
+#include <hal.h>
+#include <hal_data.h>
+#include <w32std.h>
+
+const TInt KPublishTimeout = 1000000; // 1 second in microseconds
+
+//
+// CTDeviceRotation Definition
+//
+
+CTDeviceRotation::CTDeviceRotation(CTestStep* aStep):
+	CTGraphicsBase(aStep), iWaitForPublishOnNextTest(ETrue)
+	{
+	}
+
+CTDeviceRotation::~CTDeviceRotation()
+	{
+    iPublishTimer.Close();
+    
+    iChildWindow.Close();
+    iWindowGroup.Close();
+    iWs.Close();    
+    
+    iSecondChildWindow.Close();
+    iSecondWindowGroup.Close();    
+    iSecondWs.Close();
+   
+    /* This Process called with the argument KThemeServerPropertyDefineCmdDelete, deletes 
+       the theme server RProperty. This is because an RProperty can only be defined and 
+       deleted from within a process with the same UID3 as the RProperty catogory you are 
+       trying to define/delete.*/
+    RProcess themeServerPropertyDefine;
+    TInt err = themeServerPropertyDefine.Create(KThemeServerPropertyDefine,
+            KThemeServerPropertyDefineCmdDelete);
+    if (KErrNone != err)
+        {
+        _LIT(KLog, "themeServerPropertyDefine.Create() failed with error: %d");
+        INFO_PRINTF2(KLog, err);
+        TEST(EFalse);        
+        }
+    //wait for themeServerPropertyDefine process to terminate
+    TRequestStatus themeServerPropertyDefineLogonStatus;
+    themeServerPropertyDefine.Logon(themeServerPropertyDefineLogonStatus);
+    themeServerPropertyDefine.Resume();
+    User::WaitForRequest(themeServerPropertyDefineLogonStatus);
+    if (themeServerPropertyDefineLogonStatus != KErrNone)
+        {
+        _LIT(KLog, "themeServerPropertyDefine.Logon() failed with error: %d");
+        INFO_PRINTF2(KLog, themeServerPropertyDefineLogonStatus);
+        TEST(EFalse);        
+        }
+    themeServerPropertyDefine.Close();
+    
+    iRenderOrientationProperty.Delete(KRenderOrientationCategory, KRenderOrientationKey);
+    iRenderOrientationProperty.Close();
+    iThemeServerOrientationProperty.Close();
+    }
+
+void CTDeviceRotation::ConstructL()
+    {
+    TInt err = iWs.Connect();
+    TESTL(err == KErrNone);
+            
+    err = iSecondWs.Connect();
+    TESTL(KErrNone == err);
+    
+    iWs.SetAutoFlush(ETrue);
+    iSecondWs.SetAutoFlush(ETrue);
+    
+    iWindowGroup = RWindowGroup(iWs);
+    err = iWindowGroup.Construct(iWs.Handle());
+    TESTL(KErrNone == err);
+    iWindowGroup.SetOrdinalPosition(0,1);
+    
+    iChildWindow = RWindow(iWs);
+    err = iChildWindow.Construct(iWindowGroup, reinterpret_cast<TUint32>(&iChildWindow));
+    TESTL(KErrNone == err);    
+
+    iSecondWindowGroup = RWindowGroup(iSecondWs);
+    err = iSecondWindowGroup.Construct(iSecondWs.Handle());
+    TESTL(KErrNone == err);
+    iSecondWindowGroup.SetOrdinalPosition(1,1);
+    
+    iSecondChildWindow = RWindow(iSecondWs);
+    err = iSecondChildWindow.Construct(iSecondWindowGroup, reinterpret_cast<TUint32>(&iSecondChildWindow));
+    TESTL(KErrNone == err);    
+    
+    err= iRenderOrientationProperty.Attach(KRenderOrientationCategory, KRenderOrientationKey, EOwnerThread);
+    TESTL(KErrNone == err);
+    iRenderOrientationProperty.Subscribe(iRenderOrientationStatus);
+    
+    /* This Process called with the argument KThemeServerPropertyDefineCmdDefine, defines
+       the theme server catagory to be the same as the theme servers process ID. This is 
+       because an RProperty can only be defined and deleted from within a process with the 
+       same UID3 as the RProperty catogory you are trying to define/delete.*/
+    RProcess themeServerPropertyDefine;
+    err = themeServerPropertyDefine.Create(KThemeServerPropertyDefine,KThemeServerPropertyDefineCmdDefine);
+    TESTL(KErrNone == err);
+    TRequestStatus themeServerPropertyDefineLogonStatus;
+    themeServerPropertyDefine.Logon(themeServerPropertyDefineLogonStatus);
+    themeServerPropertyDefine.Resume();
+    User::WaitForRequest(themeServerPropertyDefineLogonStatus);
+    TESTL(KErrNone == themeServerPropertyDefineLogonStatus.Int()); 
+    themeServerPropertyDefine.Close(); 
+
+    err = iThemeServerOrientationProperty.Attach(KThemeOrientationCategory, KThemeOrientationKey, EOwnerThread);
+    TESTL(KErrNone == err);
+    
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    
+    iPublishTimer.CreateLocal();
+    }
+
+void CTDeviceRotation::SimulateThemeServerOrientation(TRenderOrientation aOrientation)
+    {
+    _LIT(KFunctionInfo, "SimulateThemeServerOrientation(aOrientation = %d)");
+    INFO_PRINTF2(KFunctionInfo, aOrientation);
+    TInt err = iThemeServerOrientationProperty.Set(aOrientation);
+    if (KErrNone != err)
+        {
+        _LIT(KLog,"iThemeServerOrientationProperty.Set(%d) failed with err %d");
+        INFO_PRINTF3(KLog,aOrientation,err);
+        TEST(EFalse);
+        }
+    switch(aOrientation)
+        {
+        case EDisplayOrientationNormal:
+        case EDisplayOrientation90CW:
+        case EDisplayOrientation180:
+        case EDisplayOrientation270CW:
+            {
+            if(KErrNone == err)
+                {
+                iCurrentThemeServerOrientation = aOrientation;            
+                }                
+            break;
+            }
+        default:
+            _LIT(KLog, "This orientation is not supported by theme server.");
+        	INFO_PRINTF1(KLog);
+        }
+    }
+
+void CTDeviceRotation::IsOrientationCorrect(TRenderOrientation aExpectedOrientation)
+    {
+    // timer to timeout when nothing is published
+    iPublishTimer.After(iPublishTimerStatus, KPublishTimeout);
+    
+    // wait for either
+    User::WaitForRequest(iRenderOrientationStatus, iPublishTimerStatus);
+    
+    // check that the orientation was published or not, as expected
+    if(iWaitForPublishOnNextTest)
+        {
+        // Check that it really has published
+        if(iRenderOrientationStatus.Int()==KErrNone && iPublishTimerStatus.Int()==KRequestPending)
+            {
+            iPublishTimer.Cancel();
+            // re-subscribe
+            iRenderOrientationProperty.Subscribe(iRenderOrientationStatus);            
+            }
+        else
+            {
+            _LIT(KLog,"Timed out (%d) while waiting for render orientation %d to be published");
+            INFO_PRINTF3(KLog,iRenderOrientationStatus.Int(),aExpectedOrientation);        
+            TEST(EFalse);
+            }
+        }
+    else
+        {
+        // Check that it really hasn't published    
+        if(iRenderOrientationStatus.Int()!=KRequestPending)
+            {
+            _LIT(KLog,"Render Orientation %d was published (%d) when not expected (timeout = %d)");
+            INFO_PRINTF4(KLog,aExpectedOrientation, iRenderOrientationStatus.Int(),iPublishTimerStatus.Int());
+            iPublishTimer.Cancel();
+            TEST(EFalse);
+            }
+        else if(iPublishTimerStatus.Int()!=KErrNone)
+            {
+            _LIT(KLog,"Timeout failure %d");
+            INFO_PRINTF2(KLog,iPublishTimerStatus.Int());           
+            TEST(EFalse);        
+            }
+        
+        // reset to default
+        iWaitForPublishOnNextTest = ETrue;
+        }
+    
+    // Retrieve the value.
+    TInt orientation;
+    TInt err = iRenderOrientationProperty.Get(orientation);
+    if(KErrNone != err)
+           {
+           _LIT(KLog,"iThemeServerOrientationProperty.Get(...) failed with err %d");
+           INFO_PRINTF2(KLog,err);
+           TEST(EFalse);
+           }
+    else if(aExpectedOrientation == EDisplayOrientationAuto)
+        {
+        TEST(orientation == iCurrentThemeServerOrientation);
+        CheckHalSetting(iCurrentThemeServerOrientation);
+        }
+    else
+        {
+        TEST(orientation == aExpectedOrientation);
+        CheckHalSetting(static_cast<TRenderOrientation>(orientation));
+        }
+    }
+
+void CTDeviceRotation::CheckHalSetting(TRenderOrientation aOrientation)
+    {
+    HALData::TDigitiserOrientation halOrientationExp = static_cast<HALData::TDigitiserOrientation>
+            (HALData::EDigitiserOrientation_000 + (aOrientation - EDisplayOrientationNormal));
+    TInt halOrientation;
+    TInt err = HAL::Get(iWs.GetFocusScreen(), HALData::EDigitiserOrientation, halOrientation);
+    if (err != KErrNotSupported)
+        {
+        if (err != KErrNone)
+            {
+            _LIT(KLog,"Getting HAL orientation attribute returned error %d when no error expected");
+            INFO_PRINTF2(KLog,err);
+            }
+        TEST(err==KErrNone);
+        if (halOrientationExp != halOrientation)
+            {
+            _LIT(KLog,"HAL orientation is %d when expected to be %d");
+            INFO_PRINTF3(KLog, halOrientation, halOrientationExp);
+            }
+        TEST(halOrientationExp==halOrientation);
+        }
+    else
+        {
+        _LIT(KLog,"HAL-Orientation HALData::EDigitiserOrientation isn't supported by Driver");
+        INFO_PRINTF1(KLog);
+        }
+    }
+
+void CTDeviceRotation::TestIndicateAppOrientation(TRenderOrientation aOrientation)
+	{
+    _LIT(KTestInfo, "TestIndicateAppOrientation(aOrientation = %d)");
+    INFO_PRINTF2(KTestInfo, aOrientation);
+	if (EDisplayOrientationIgnore == aOrientation)
+	    {
+        TEST(EFalse);
+        _LIT(KLog, "TestIndicateAppOrientation(TRenderOrientation aOrientation) cannot be used with EDisplayOrientationIgnore");
+        INFO_PRINTF1(KLog);
+	    }
+	iWs.IndicateAppOrientation(aOrientation);
+	iWindowGroup.SetOrdinalPosition(0);
+	IsOrientationCorrect(aOrientation);
+	}
+
+void CTDeviceRotation::TestIndicateAppOrientation(TRenderOrientation aOrientation, TRenderOrientation aSecondOrientation)
+    {
+    _LIT(KTestInfo, "TestIndicateAppOrientation(aOrientation = %d, aSecondOrientation = %d)");
+    INFO_PRINTF3(KTestInfo, aOrientation, aSecondOrientation);
+    //Inform window serve the orientation status
+    iWs.IndicateAppOrientation(aOrientation);
+    iSecondWs.IndicateAppOrientation(aSecondOrientation);
+    
+    iWindowGroup.SetOrdinalPosition(0,1);
+    iSecondWindowGroup.SetOrdinalPosition(1,1);
+
+    if(aOrientation != EDisplayOrientationIgnore)
+        {
+        IsOrientationCorrect(aOrientation);
+        }
+    else
+        {
+        IsOrientationCorrect(aSecondOrientation);
+        }
+    }
+
+void CTDeviceRotation::TestAppOrientationOnSwap(TRenderOrientation aOrientation, TRenderOrientation aSecondOrientation)
+    {    
+    _LIT(KTestInfo, "TestAppOrientationOnSwap(aOrientation = %d, aSecondOrientation = %d)");
+    INFO_PRINTF3(KTestInfo, aOrientation, aSecondOrientation);
+    
+    iWs.IndicateAppOrientation(aOrientation);
+    iSecondWs.IndicateAppOrientation(aSecondOrientation);
+    
+    iSecondWindowGroup.SetOrdinalPosition(0);
+    if (aSecondOrientation != EDisplayOrientationIgnore)
+        {
+        IsOrientationCorrect(aSecondOrientation);
+        }
+    else
+        {
+        IsOrientationCorrect(aOrientation);
+        }
+    }
+
+void CTDeviceRotation::RunTestCaseL(TInt aCurTestCase)
+	{
+    _LIT(KNewLine, "\n");
+    (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KUnknownSYMTestCaseIDName);
+	switch(aCurTestCase)
+		{
+	    case 1:
+            _LIT(KTestStepID1,"Test Initial Orientations");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID1);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID1);
+            TestInitialOrientation();
+            break;
+		case 2:
+    	    _LIT(KTestStepID2,"Test Fixed Orientations");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID2);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID2);
+            TestFixedOrientations();
+			break;
+		case 3:
+    	    _LIT(KTestStepID3,"Test Auto Orientation");
+		    (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID3);
+		    INFO_PRINTF1(KNewLine);
+		    INFO_PRINTF1(KTestStepID3);
+		    TestAutoOrientation();
+			break;
+		case 4:
+            _LIT(KTestStepID4,"Test Ignore Orientation");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID4);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID4);
+            TestIgnoreOrientation();
+			break;
+        case 5:
+            _LIT(KTestStepID5,"Test Swap Orientations");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID5);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID5);
+            TestFixedOrientationsOnWindowSwap();
+			break;
+        case 6:
+            _LIT(KTestStepID6,"Test Auto Swap Orientations");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID6);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID6);
+            TestAutoOrientationOnWindowSwap();
+            break;
+        case 7:
+            _LIT(KTestStepID7,"Test Ignore Swap Orientations");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID7);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID7);
+            TestIgnoreOrientationOnWindowSwap();
+			break;
+        case 8:
+            _LIT(KTestStepID8,"Test Auto Swap Orientations");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID8);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID8);
+            TestIgnoreAutoOrientationOnWindowSwap();
+            break;
+        case 9:
+            _LIT(KTestStepID9,"Test Invalid App Orientations");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID9);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID9);
+            TestInvalidAppOrientation();
+            break;
+        case 10:
+            _LIT(KTestStepID10,"Test Invalid Theme Server Orientations");
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KTestStepID10);
+            INFO_PRINTF1(KNewLine);
+            INFO_PRINTF1(KTestStepID10);
+            TestInvalidThemeServerOrientation();
+            break;
+		default:
+            (reinterpret_cast<CTDeviceRotationStep*>(iStep))->SetTestStepID(KNotATestSYMTestCaseIDName);
+			(reinterpret_cast<CTDeviceRotationStep*>(iStep))->CloseTMSGraphicsStep();
+			TestComplete();
+		}
+	(reinterpret_cast<CTDeviceRotationStep*>(iStep))->RecordTestResultL();
+	}
+
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0001
+ @SYMTestCaseDesc           Test Auto Orientation
+ @SYMPREQ                   460936 Tracking Device Rotation
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that we can return the correct initial orientation value from 
+                            the windwoserver.
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            We have set up an RWindowGroup at the foreground and not altered its
+                            indicated orientation.
+ @SYMTestActions            1) Get the value of the orientation as published by window server.
+
+ @SYMTestExpectedResults    The windowserver should return EDisplayOrientationNormal
+ */
+void CTDeviceRotation::TestInitialOrientation()
+    {
+    iWaitForPublishOnNextTest = EFalse;
+    IsOrientationCorrect(EDisplayOrientationNormal);
+    }
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0002
+ @SYMTestCaseDesc           Test Fixed Orientations
+ @SYMPREQ                   460936 Tracking Device Rotation
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that we can return the correct orientation value from 
+                            the windwoserver after we indicate the application orientation
+                            as fixed values using RWsSession::IndicateAppOrientation. Any 
+                            theme server orientations should be ignored.
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            An RProperty is set up to publish Theme server Orientation changes. 
+                            We have set up an RWindowGroup in the foreground.
+                            Windowserver orientation currently set to EDisplayOrientationNormal.
+
+ @SYMTestActions            1) Set Theme Server orientation to EDisplayOrientation90CW.
+                            2) Set the RWindowgroup in ordinal position 0 to a fixed orientation.
+                            3) Check the published orinetation value in windowserver.
+                            4) Repeat steps 2) and 3) for all fixed orientations
+                            3) Set Theme Server orientation to EDisplayOrientationNormal.
+                            4) Repeat Steps 2-4).
+
+ @SYMTestExpectedResults    The orientation set in step 2) should always be the same as the 
+                            orientation set in step 2)
+ */
+void CTDeviceRotation::TestFixedOrientations()
+    {
+    iWaitForPublishOnNextTest = EFalse;
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientation180);
+    TestIndicateAppOrientation(EDisplayOrientation270CW);
+    
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientation180);
+    TestIndicateAppOrientation(EDisplayOrientation270CW);
+    
+    SimulateThemeServerOrientation(EDisplayOrientation180);
+    TestIndicateAppOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientation180);
+    TestIndicateAppOrientation(EDisplayOrientation270CW);
+    
+    SimulateThemeServerOrientation(EDisplayOrientation270CW);
+    TestIndicateAppOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientation180);
+    TestIndicateAppOrientation(EDisplayOrientation270CW);    
+    }
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0003
+ @SYMTestCaseDesc           Test Auto Orientation
+ @SYMPREQ                   460936 Tracking Device Rotation
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that we can return the correct orientation value from 
+                            the windwoserver after we indicate the application orientation
+                            as auto values using RWsSession::IndicateAppOrientation. The wserv
+                            should publish the theme server orientation changes only.
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            An RProperty is set up to publish Theme server Orientation changes.
+                            We have set up an RWindowGroup in the foreground.
+                            WindowServer orinetation is not set to EDisplayOrientation90CW.
+
+ @SYMTestActions            1) Set Theme Server orientation to EDisplayOrientation90CW.
+                            2) Set the RWindowgroup in ordinal position 0 to auto orientation.
+                            3) Check the published orinetation value in windowserver.
+                            4) Set Theme Server orientation to EDisplayOrientationNormal.
+                            5) Check the value of the orientation as published by window server.
+                            6) Repeat 4) and 5) for EDisplayOrientation180 and 
+                               EDisplayOrientation270CW
+                            7) repeat 4) and 5) again for EDisplayOrientation270CW
+
+ @SYMTestExpectedResults    We should get expected notifications where orientations have changed.
+                            The orientation checked in step 3) should be the theme server 
+                            orientation set in step 1).
+                            The orientations checked in step 5) should be the theme server 
+                            orientations set in step 4).
+                            We should recieve no notification for step 7).
+ */
+void CTDeviceRotation::TestAutoOrientation()
+    {
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientationAuto);
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    IsOrientationCorrect(iCurrentThemeServerOrientation);
+    // Now flip it upside down to ensure that nothing assumes this will only be updated incrementally
+    SimulateThemeServerOrientation(EDisplayOrientation180);
+    IsOrientationCorrect(iCurrentThemeServerOrientation);
+    SimulateThemeServerOrientation(EDisplayOrientation270CW);
+    IsOrientationCorrect(iCurrentThemeServerOrientation);
+    
+    // And check that wserv doesn't publish if the theme server publishes the existing orientation
+    SimulateThemeServerOrientation(EDisplayOrientation270CW);
+    iWaitForPublishOnNextTest = EFalse;    
+    IsOrientationCorrect(iCurrentThemeServerOrientation);
+    }
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0004
+ @SYMTestCaseDesc           Test Ignore Orientation
+ @SYMPREQ                   460936 Tracking Device Rotation
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that we can return the correct orientation value from 
+                            the windwoserver after we indicate the front applications 
+                            orientation as ignore.  
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            An RProperty is set up to publish Theme server Orientation changes.
+                            We have set up two RWindowGroups in the ordinal positions 0 and 1. 
+                            WindowServer orinetation is not set to EDisplayOrientationNormal.
+
+ @SYMTestActions            1) Set Theme Server orientation to EDisplayOrientation90CW.
+                            2) Set the RWindowGroup in ordinal position 0 to a ignore orientation.
+                            3) Set the RWindowgroup in ordinal position 1 to a fixed orientation.
+                            4) Check the published orinetation value in windowserver.
+                            5) Repeat steps 2-4) varying the fixed orientation set in step 2).
+                            6) Set Theme Server orientation to EDisplayOrientation90CW.
+                            7) Set the RWindowGroup in ordinal position 0 to a ignore orientation.
+                            8) Set the RWindowgroup in ordinal position 1 to a fixed orientation.
+                            9) Check the published orinetation value in windowserver.
+                            10) Set Theme Server orientation to EDisplayOrientationNormal.
+                            11) Check the published orinetation value in windowserver.
+
+ @SYMTestExpectedResults    We should get expected notifications where orientations have changed.
+                            All orientations checked in step 4) should be the fixed orientations 
+                            of the windows in ordinal position 1, as set in step 3).
+                            The orientation checked in step 9) should be the theme server 
+                            orientation set in step 6).
+                            The orientation checked in step 11) should be the theme server 
+                            orientation set in step 10).
+ */
+void CTDeviceRotation::TestIgnoreOrientation()
+    {
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientationIgnore, EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientationIgnore, EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientationIgnore, EDisplayOrientation180);
+    TestIndicateAppOrientation(EDisplayOrientationIgnore, EDisplayOrientation270CW);
+    
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientationIgnore, EDisplayOrientationAuto);
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    IsOrientationCorrect(iCurrentThemeServerOrientation);
+    }
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0005
+ @SYMTestCaseDesc           Test Fixed Orientations On Swap
+ @SYMPREQ                   460936 Tracking Device Rotation
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that we get notifactation of a change in orientation and can 
+                            return the correct orientation value from the windwoserver after we 
+                            swap windows with varying fixed orienations.  
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            We have set up two RWindowGroups in the ordinal positions 0 and 1. 
+
+ @SYMTestActions            1) Set the RWindowGroup in ordinal position 0 to a fixed orientation.
+                            2) Set the RWindowgroup in ordinal position 1 to a fixed orientation.
+                            3) Check the published orinetation value in windowserver.
+                            4) Move the RWindowGroup ordinal position 1 to the ordinal position 0.
+                            5) Check the published orinetation value in windowserver.
+                            6) Repeat steps 1-5 but vary the values the fixed orientation of the 
+                               RWindows set in steps 1) and 2)
+
+ @SYMTestExpectedResults    We should get expected notifications where orientations have changed.
+                            All orientations checked in step 3) should be the fixed orientations 
+                            of the windows in ordinal position 0, as set in step 1).
+                            The orientations checked in step 5) should be the fixed orientations 
+                            of the windows which was in ordinal position 1 before each swap, as 
+                            set in step 2).
+ */
+void CTDeviceRotation::TestFixedOrientationsOnWindowSwap()
+    {
+    iWaitForPublishOnNextTest = EFalse;
+    TestIndicateAppOrientation(EDisplayOrientationNormal, EDisplayOrientationNormal);
+    iWaitForPublishOnNextTest = EFalse;
+    TestAppOrientationOnSwap(EDisplayOrientationNormal, EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientationNormal, EDisplayOrientation90CW);
+    TestAppOrientationOnSwap(EDisplayOrientationNormal, EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientation90CW, EDisplayOrientationNormal);
+    TestAppOrientationOnSwap(EDisplayOrientation90CW, EDisplayOrientationNormal);
+    }
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0006
+ @SYMTestCaseDesc           Test Auto Orientations On Swap
+ @SYMPREQ                   460936 Tracking Device Rotation
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that we get notifactation of a change in orientation and can 
+                            return the correct orientation value from the windwoserver after we 
+                            swap windows with auto orienations.  
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            An RProperty is set up to publish Theme server Orientation changes.
+                            We have set up two RWindowGroups in the ordinal positions 0 and 1.
+                            WindowServer orinetation is not set to EDisplayOrientation270CW. 
+
+ @SYMTestActions            1) Set the theme server orientation.
+                            2) Set the RWindowGroup in ordinal position 0 to a fixed orientation.
+                            3) Set the RWindowGroup in ordinal position 1 to auto orientation.
+                            4) Check the published orinetation value in windowserver.
+                            5) Move the RWindowGroup ordinal position 1 to the ordinal position 0. 
+                            6) Check the published orinetation value in windowserver.
+                            7) Repeat steps 1-6 but vary the values of the theme server 
+                               orientation in step 1) and the fixed orientation of the frontwindow
+                               in 2)
+ @SYMTestExpectedResults    We should get expected notifications where orientations have changed.
+                            All orientations checked in step 4) should be the fixed orientations 
+                            of the front windows, which have been set in step 2).
+                            All orientations checked in step 6) should be the theme server 
+                            orientations set in step 1)
+ */
+void CTDeviceRotation::TestAutoOrientationOnWindowSwap()
+    {
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientation270CW, EDisplayOrientationAuto);
+    TestAppOrientationOnSwap(EDisplayOrientation270CW, EDisplayOrientationAuto);
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientationAuto, EDisplayOrientation180);
+    TestAppOrientationOnSwap(EDisplayOrientationAuto, EDisplayOrientation180);
+    
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientation90CW, EDisplayOrientationAuto);
+    iWaitForPublishOnNextTest = EFalse;
+    TestAppOrientationOnSwap(EDisplayOrientation90CW, EDisplayOrientationAuto);
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientationAuto, EDisplayOrientationNormal);
+    iWaitForPublishOnNextTest = EFalse;
+    TestAppOrientationOnSwap(EDisplayOrientationAuto, EDisplayOrientationNormal);
+    }
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0007
+ @SYMTestCaseDesc           Test Swap Orientations with Ignore Orientation
+ @SYMPREQ                   460936 Tracking Device Rotation
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that we get notifactation of a change in orientation and can 
+                            return the correct orientation value from the windwoserver after we 
+                            swap windows with ignore orienations.  
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            An RProperty is set up to publish Theme server Orientation changes.
+                            We have set up two RWindowGroups in the ordinal positions 0 and 1. 
+
+ @SYMTestActions            1) Set the theme server orientation.
+                            2) Set the RWindowGroup in ordinal position 0 to ignore orientation.
+                            3) Set the RWindowGroup in ordinal position 1 to a fixed orientation.
+                            4) Check the published orinetation value in windowserver.
+                            5) Move the RWindowGroup ordinal position 1 to the ordinal position 0. 
+                            6) Check the published orinetation value in windowserver.
+                            7) Repeat steps 1-6 but vary the values of the theme server 
+                               orientation in step 1) and the fixed orientation of the frontwindow
+                               in 3)
+                            8) Set the theme server orientation.
+                            9) Set the RWindowGroup in ordinal position 0 to a fixedorientation.
+                            10) Set the RWindowGroup in ordinal position 1 to ignore orienation.
+                            11) Repeat steps 4-6) 
+                            12) Repeat steps 8-11) but vary the values of the theme server 
+                               orientation in step 8) and the fixed orientation of the 
+                               RwindowGroup in 9)                            
+                               
+ @SYMTestExpectedResults    We should get expected notifications where orientations have changed.
+                            All orientations checked in step 4) and 6) should be the fixed 
+                            orientations RWindowGroups which have been set in step 3).
+                            All orientations checked in step 11) should be the fixed orientations 
+                            of the front RWindowGroups which have been set in step 9).
+*/
+void CTDeviceRotation::TestIgnoreOrientationOnWindowSwap()
+    {
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientationIgnore, EDisplayOrientation270CW);
+    TestAppOrientationOnSwap(EDisplayOrientationIgnore, EDisplayOrientation180);
+    
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientationIgnore, EDisplayOrientationNormal);
+    TestAppOrientationOnSwap(EDisplayOrientationIgnore, EDisplayOrientation90CW);
+    
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    TestIndicateAppOrientation(EDisplayOrientation270CW, EDisplayOrientationIgnore);
+    TestAppOrientationOnSwap(EDisplayOrientation180, EDisplayOrientationIgnore);    
+    
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientationNormal, EDisplayOrientationIgnore);
+    TestAppOrientationOnSwap(EDisplayOrientation90CW, EDisplayOrientationIgnore);
+    }
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0008
+ @SYMTestCaseDesc           Test Swap Orientations with Auto and Ignore Orientations
+ @SYMPREQ                   460936 Tracking Device Rotation
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that we get notifactation of a change in orientation and can 
+                            return the correct orientation value from the windwoserver after we 
+                            swap windows with auto and ignore orienations.  
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            An RProperty is set up to publish Theme server Orientation changes.
+                            We have set up two RWindowGroups in the ordinal positions 0 and 1. 
+ @SYMTestActions            1) Set the theme server orientation to EDisplayOrientationNormal.
+                            2) Set the RWindowGroup in ordinal position 0 to auto orientation.
+                            3) Set the RWindowGroup in ordinal position 1 to ignore orientation.
+                            4) Check the published orinetation value in windowserver.
+                            5) Set the theme server orientation to EDisplayOrientation90CW.
+                            6) Check the published orinetation value in windowserver.
+                            7) Set the theme server orientation to EDisplayOrientationNormal.
+                            8) Move the RWindowGroup in ordinal position 1 to ordinal position 0.
+                            9) Check the published orinetation value in windowserver.
+                            10) Set the theme server orientation to EDisplayOrientation90CW.
+                            11) Check the published orinetation value in windowserver.
+
+ @SYMTestExpectedResults    We should get expected notifications where orientations have changed.
+                            The orientations checked in step 4), 6), 9) and  11) should all be 
+                            the orientations set to the themeserver in steps 1), 5), 8) and 10)
+                            respecvtively. 
+*/
+void CTDeviceRotation::TestIgnoreAutoOrientationOnWindowSwap()
+    {
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    TestIndicateAppOrientation(EDisplayOrientationAuto, EDisplayOrientationIgnore);
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    IsOrientationCorrect(iCurrentThemeServerOrientation);
+    
+    SimulateThemeServerOrientation(EDisplayOrientationNormal);
+    iSecondWindowGroup.SetOrdinalPosition(0);
+    IsOrientationCorrect(iCurrentThemeServerOrientation);
+    SimulateThemeServerOrientation(EDisplayOrientation90CW);
+    IsOrientationCorrect(iCurrentThemeServerOrientation);
+    }
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0009
+ @SYMTestCaseDesc           Test Invalid App Orientation
+ @SYMPREQ                   ###TrackingDeviceRotation### TODO replace me
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that an invalid orientation is ignored.
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            An RProperty is set up to publish Theme server Orientation changes.
+                            We have set up an RWindowGroup in ordinal position 0.
+ @SYMTestActions            1) Set the theme server orientation to EDisplayOrientationNormal.
+                            2) Set the RWindowGroup in ordinal position 0 to 
+                               EDisplayOrientation90CW.
+                            4) Check the published orinetation value in windowserver.
+                            5) Set the RWindowGroup in ordinal position 0 to an invalid 
+                               orientation.
+                            6) Check the published orinetation value in windowserver.
+
+ @SYMTestExpectedResults    Wserv should publish an orientation change for 2) but not for 5).
+                            The orientations checked in steps 4) and 6) should both be the 
+                            orientation set in step 2).
+*/
+void CTDeviceRotation::TestInvalidAppOrientation()
+	{
+	SimulateThemeServerOrientation(EDisplayOrientationNormal);
+	TestIndicateAppOrientation(EDisplayOrientation90CW);
+	iWs.IndicateAppOrientation(static_cast<TRenderOrientation>(1000));
+	iWaitForPublishOnNextTest = EFalse;
+	IsOrientationCorrect(EDisplayOrientation90CW);
+	}
+
+/**
+ @SYMTestCaseID             GRAPHICS-WSERV-DEVICEROTATION-0010
+ @SYMTestCaseDesc           Test Invalid Theme Server Orientation
+ @SYMPREQ                   ###TrackingDeviceRotation### TODO replace me
+ @SYMTestPriority           1
+ @SYMTestPurpose            To test that an invalid theme server orientation is ignored when
+                            the app orientation has been set to auto.
+ @SYMPrerequisites          An RProperty is set up to subscribe to notifications of 
+                            windowserver orientation changes.
+                            An RProperty is set up to publish Theme server Orientation changes.
+                            We have set up an RWindowGroup in ordinal position 0.
+ @SYMTestActions            1) Set the theme server orientation to EDisplayOrientationNormal.
+                            2) Set the RWindowGroup in ordinal position 0 to 
+                               EDisplayOrientationAuto.
+                            4) Check the published orinetation value in windowserver.
+                            5) Set the theme server orientation to an invalid orientation.
+                            6) Check the published orinetation value in windowserver.
+
+ @SYMTestExpectedResults    Wserv should publish an orientation change for 2) but not for 5).
+                            The orientations checked in steps 4) and 6) should both be the 
+                            theme server orientation set in step 1).
+*/
+void CTDeviceRotation::TestInvalidThemeServerOrientation()
+	{
+	SimulateThemeServerOrientation(EDisplayOrientationNormal);
+	TestIndicateAppOrientation(EDisplayOrientationAuto);
+	SimulateThemeServerOrientation(static_cast<TRenderOrientation>(5000));
+	iWaitForPublishOnNextTest = EFalse;
+	IsOrientationCorrect(EDisplayOrientationNormal);
+	}
+
+__CONSTRUCT_STEP__(DeviceRotation)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/tauto/tdevicerotation.h	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,110 @@
+// Copyright (c) 2010 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:
+// Set of tests for Tracing Device Rotation. These tests generally test
+// the RWsSession::IndicateAppOrientation(...) API.
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Nokia test code
+*/
+
+#ifndef __TDEVICERORATION_H__
+#define __TDEVICERORATION_H__
+
+#include <e32std.h>
+#include <w32std.h>
+#include <e32property.h>
+#include <test/testexecutestepbase.h>
+#include "../tlib/testbase.h"
+#include "AUTO.H"
+#include "TGraphicsHarness.h"
+#include <wspublishandsubscribedata.h>
+
+//
+// CTDeviceRotation Definition
+//
+
+class CTDeviceRotation: public CTGraphicsBase
+	{
+public:
+    CTDeviceRotation(CTestStep* aStep);
+	~CTDeviceRotation();
+	/*Sets the windowing environment,*/
+	void ConstructL();
+
+protected:
+	//from 	CTGraphicsStep - Calls the device rotation test.
+	virtual void RunTestCaseL(TInt aCurTestCase);
+private: 
+	//tool functions
+	void SimulateThemeServerOrientation(TRenderOrientation aExpectedaOrientation);
+	void CheckHalSetting(TRenderOrientation aOrientation);
+	void IsOrientationCorrect(TRenderOrientation aOrientation);
+	void TestIndicateAppOrientation(TRenderOrientation aOrientation);
+	void TestIndicateAppOrientation(TRenderOrientation aOrientation, TRenderOrientation aSecondOrientation);
+	void TestIgnoredAppOrientation(TRenderOrientation aSecondOrientation, TInt aThemeServerOrientation, TInt aExpectedOrientation);
+	void TestAppOrientationOnSwap(TRenderOrientation aOrientation, TRenderOrientation aSecondOrientation);
+	//For TESTL
+	inline void testBooleanTrueL(TBool aCondition, const TText8* aFile, TInt aLine) 
+	    {
+	    iStep->testBooleanTrueL(aCondition, aFile, aLine, ETrue);
+	    }
+private:
+	//Test Cases
+	void TestInitialOrientation();
+	void TestFixedOrientations();
+	void TestAutoOrientation();
+	void TestIgnoreOrientation();
+	void TestFixedOrientationsOnWindowSwap();
+	void TestAutoOrientationOnWindowSwap();
+	void TestIgnoreOrientationOnWindowSwap();
+	void TestIgnoreAutoOrientationOnWindowSwap();
+	void TestInvalidAppOrientation();
+	void TestInvalidThemeServerOrientation();
+	
+private:
+	//members
+	// First Session and Window Group
+	RWsSession iWs;
+	RWindowGroup iWindowGroup;
+    RWindow iChildWindow;
+    // Second Session and Window Group
+	RWsSession iSecondWs;
+	RWindowGroup iSecondWindowGroup;
+	RWindow iSecondChildWindow;
+		
+	RProperty iRenderOrientationProperty;
+	RTimer iPublishTimer;
+	TRequestStatus iPublishTimerStatus;
+	TRequestStatus iRenderOrientationStatus;
+	RProperty iThemeServerOrientationProperty;
+
+	TRenderOrientation iCurrentThemeServerOrientation;
+	TBool iWaitForPublishOnNextTest; //Set to EFalse to skip waiting for publish on next test, default ETrue, Resets to ETrue on each Test.
+	};
+
+class CTDeviceRotationStep : public CTGraphicsStep
+	{
+public:
+	CTDeviceRotationStep();
+protected:
+	//from CTGraphicsStep
+	virtual CTGraphicsBase* CreateTestL();
+	};
+
+_LIT(KTDeviceRotationStep,"TDeviceRotation");
+
+#endif //TDEVICERORATION
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/tauto/tevent_captureapp.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,67 @@
+// Copyright (c) 2010 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:
+// Helper application for TEvent test case GRAPHICS-WSERV-0757
+//
+
+#include <e32base.h>
+#include <e32debug.h>
+#include <w32std.h>
+
+const TInt KCapturePriority = 1;
+
+LOCAL_C void MainL()
+	{
+	RWsSession session;
+	User::LeaveIfError(session.Connect());
+	CleanupClosePushL(session);
+	RWindowGroup group(session);
+	User::LeaveIfError(group.Construct(0));
+
+	// Capture keys EKeyF22 and EKeyF23 with raised
+	// priority for each of the three capture types.
+	TInt handle1 = User::LeaveIfError(group.CaptureKey(EKeyF22, 0, 0, KCapturePriority));
+	TInt handle2 = User::LeaveIfError(group.CaptureKeyUpAndDowns(EStdKeyF22, 0, 0, KCapturePriority));
+	TInt handle3 = User::LeaveIfError(group.CaptureLongKey(EKeyF22, EKeyF22, 0, 0, KCapturePriority, ELongCaptureNormal));
+	TInt handle4 = User::LeaveIfError(group.CaptureKey(EKeyF23, 0, 0, KCapturePriority));
+	TInt handle5 = User::LeaveIfError(group.CaptureKeyUpAndDowns(EStdKeyF23, 0, 0, KCapturePriority));
+	TInt handle6 = User::LeaveIfError(group.CaptureLongKey(EKeyF23, EKeyF23, 0, 0, KCapturePriority, ELongCaptureNormal));
+
+	// Complete rendezvous with TEvent. This signals that all the capture
+	// requests have been made.
+	RProcess::Rendezvous(KErrNone);
+
+	// Wait until killed by TEvent
+	User::WaitForAnyRequest();
+
+	group.CancelCaptureKey(handle1);
+	group.CancelCaptureKeyUpAndDowns(handle2);
+	group.CancelCaptureLongKey(handle3);
+	group.CancelCaptureKey(handle4);
+	group.CancelCaptureKeyUpAndDowns(handle5);
+	group.CancelCaptureLongKey(handle6);
+
+	CleanupStack::PopAndDestroy(&session);
+	}
+
+GLDEF_C TInt E32Main()
+	{	
+	__UHEAP_MARK;
+
+	CTrapCleanup* cleanupStack = CTrapCleanup::New(); 	
+	TRAPD(ret, MainL());	
+	delete cleanupStack;
+	
+	__UHEAP_MARKEND;
+	return ret;
+	}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/tauto/themeserverpropertydefine.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,88 @@
+// Copyright (c) 2010 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:
+// This Process called with the argument KThemeServerPropertyDefineCmdDefine, defines
+// the theme server RProperty catagory to be the same as the theme servers process ID. 
+// Called with the argument KThemeServerPropertyDefineCmdDelete, it will delete the 
+// theme server RProperty. This is because an RProperty can only be defined and deleted 
+// from within a process with the same UID3 as the RProperty catogory you are trying to 
+// define/delete.
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Nokia test code
+ */
+
+#include <BACLINE.H> 
+#include <e32base.h>
+#include <e32property.h>
+#include "..\..\nga\server\renderorientationtracker.h" //for KThemeOrientationCatagory and KThemeOrientationKey
+#include "themeserverpropertydefine.h"
+
+void DefineThemeServerPropertyL()
+    {
+    RProperty themeServerOrientationProperty;
+    const TSecurityPolicy KThemeOrientationReadSecurityPolicy(
+            TSecurityPolicy::EAlwaysPass);
+    const TSecurityPolicy KThemeOrientationWriteSecurityPolicy(
+            TSecurityPolicy::EAlwaysPass);
+    User::LeaveIfError(RProperty::Define(   KThemeOrientationCategory,
+                                            KThemeOrientationKey, 
+                                            RProperty::EInt,
+                                            KThemeOrientationReadSecurityPolicy,
+                                            KThemeOrientationWriteSecurityPolicy));
+    themeServerOrientationProperty.Close();
+    }
+
+void DeleteThemeServerPropertyL()
+    {
+    TInt err = KErrNone;
+    RProperty themeServerOrientationProperty;
+    User::LeaveIfError(themeServerOrientationProperty.Delete(
+            KThemeOrientationCategory, KThemeOrientationKey));
+    themeServerOrientationProperty.Close();
+    }
+
+void MainL()
+    {
+    CCommandLineArguments* args = CCommandLineArguments::NewLC();
+    TPtrC argumentPrt(args->Arg(1));
+    if (argumentPrt == KThemeServerPropertyDefineCmdDefine)
+        {
+        DefineThemeServerPropertyL();
+        }
+    else if (argumentPrt == KThemeServerPropertyDefineCmdDelete)
+        {
+        DeleteThemeServerPropertyL();
+        }
+    else
+        {
+        User::Leave(KErrNotSupported);
+        }
+    CleanupStack::PopAndDestroy(args);
+    }
+
+GLDEF_C TInt E32Main()
+    {
+    CTrapCleanup* cleanUpStack = CTrapCleanup::New();
+    if (cleanUpStack == NULL)
+        {
+        return KErrNoMemory;
+        }
+    TRAPD(err, MainL());
+    delete cleanUpStack;
+    return (err);
+    }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/test/tauto/themeserverpropertydefine.h	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,29 @@
+// Copyright (c) 2010 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:
+// Header Defines the EXE name as well as the two possible command line 
+// arguments for twsthemeserverdefine.exe
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Nokia test code
+ */
+#ifndef THEMESERVERSIMULATION_H_
+#define THEMESERVERSIMULATION_H_
+
+_LIT(KThemeServerPropertyDefine, "twsthemeserverpropertydefine.exe");
+_LIT(KThemeServerPropertyDefineCmdDefine, "define");
+_LIT(KThemeServerPropertyDefineCmdDelete, "delete");
+
+#endif /* THEMESERVERSIMULATION_H_ */
--- a/windowing/windowserver/wins_switching/ws32_stubs.h	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserver/wins_switching/ws32_stubs.h	Fri Sep 24 16:44:34 2010 +0300
@@ -5292,6 +5292,15 @@
 	_asm jmp common_dispatch
 	}
 
+__declspec(dllexport)
+__declspec(naked)
+void call_vector_587 ()
+	{
+	// ; void RWsSession::IndicateAppOrientation(enum TRenderOrientation)
+	_asm mov eax, 587
+	_asm jmp common_dispatch
+	}
+
 }
-#define MAX_ORDINAL 587
-
+#define MAX_ORDINAL 588
+
--- a/windowing/windowserverplugins/group/bld.inf	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserverplugins/group/bld.inf	Fri Sep 24 16:44:34 2010 +0300
@@ -1,4 +1,4 @@
-// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// Copyright (c) 2008-2010 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"
@@ -30,6 +30,8 @@
 
 PRJ_MMPFILES
 
+#include "../keyeventrouting/group/bld.inf"
+
 #ifndef SYMBIAN_GRAPHICS_BUILD_OPENWF_WSERV
 #include "../restricted/group/BLD.INF"
 #else
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/bwins/keyrouteru.def	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	?NewL@CKeyEventRouter@@SAPAV1@XZ @ 1 NONAME ; class CKeyEventRouter * CKeyEventRouter::NewL(void)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/eabi/keyrouteru.def	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,3 @@
+EXPORTS
+	_ZN15CKeyEventRouter4NewLEv @ 1 NONAME
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/group/bld.inf	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,29 @@
+// Copyright (c) 2010 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:
+// Key Event Routing plug-in for Window Server
+//
+
+PRJ_EXPORTS
+../bwins/keyrouteru.def	SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/def/bwins/keyrouteru.def)
+../eabi/keyrouteru.def	SYMBIAN_OS_LAYER_PLATFORM_EXPORT_PATH(graphics/def/eabi/keyrouteru.def)
+keyeventrouting.iby		/epoc32/rom/include/keyeventrouting.iby
+
+PRJ_TESTEXPORTS
+keyeventrouting_test.iby		/epoc32/rom/include/keyeventrouting_test.iby
+
+PRJ_MMPFILES
+keyeventrouting.mmp
+
+PRJ_TESTMMPFILES
+keyeventrouting_test.mmp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/group/keyeventrouting.iby	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 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: 
+// Key Event Routing plug-in for Window Server
+//
+
+#ifndef __KEYEVENTROUTING_IBY__
+#define __KEYEVENTROUTING_IBY__
+
+file=ABI_DIR\BUILD_DIR\keyrouter.dll		System\Libs\keyrouter.dll
+
+#endif // __KEYEVENTROUTING_IBY__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/group/keyeventrouting.mmp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 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:
+// Key Event Routing plug-in for Window Server
+//
+
+TARGET		keyrouter.dll
+TARGETTYPE	dll
+CAPABILITY  PowerMgmt ReadDeviceData WriteDeviceData ProtServ
+UID			0x102872e1 0x102872e2
+VENDORID	0x70000001
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+SOURCEPATH	../src
+SOURCE		keyrouter.cpp
+
+LIBRARY		euser.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/group/keyeventrouting_test.iby	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,22 @@
+// Copyright (c) 2010 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: 
+// Key Event Routing plug-in for Window Server: test version
+//
+
+#ifndef __KEYEVENTROUTING_TEST_IBY__
+#define __KEYEVENTROUTING_TEST_IBY__
+
+file=ABI_DIR\BUILD_DIR\keyrouter_test.dll		System\Libs\keyrouter_test.dll
+
+#endif // __KEYEVENTROUTING_TEST_IBY__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/group/keyeventrouting_test.mmp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 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:
+// Key Event Routing plug-in for Window Server: test version
+//
+
+TARGET		keyrouter_test.dll
+TARGETTYPE	dll
+CAPABILITY  PowerMgmt ReadDeviceData WriteDeviceData ProtServ
+UID			0x102872e1 0x102872e6
+VENDORID	0x70000001
+
+MACRO		KEYROUTER_TEST
+
+DEFFILE		keyrouter.def
+
+OS_LAYER_SYSTEMINCLUDE_SYMBIAN
+
+SOURCEPATH	../src
+SOURCE		keyrouter.cpp
+
+LIBRARY		euser.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/src/keyaliases.h	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,108 @@
+// Copyright (c) 2010 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:
+// Key code and scan code aliases for platform specific keys.
+// The definitions are as per S60 <mw/eikon.hrh> with the addition of the
+// full set of scan codes.
+
+/**
+@file
+@internalTechnology
+@prototype
+*/
+
+#include <e32keys.h>
+
+/**
+TStdScanCode aliases
+*/
+#define EStdKeyOK				EStdKeyDevice3
+#define EStdKeyCBA1				EStdKeyDevice0
+#define EStdKeyCBA2				EStdKeyDevice1
+#define EStdKeyPhoneSend		EStdKeyYes
+#define EStdKeyPhoneEnd			EStdKeyNo
+#define EStdKeyApplication		EStdKeyApplication0
+#define EStdKeyPowerOff			EStdKeyDevice2
+#define EStdKeyGripOpen			EStdKeyDevice4
+#define EStdKeyGripClose		EStdKeyDevice5
+#define EStdKeySide				EStdKeyDevice6	// Voice key
+#define EStdKeyCamera			EStdKeyDevice7
+#define EStdKeyTwistOpen		EStdKeyDevice8
+#define EStdKeyTwistClose		EStdKeyDevice9
+#define EStdKeyLeftUpArrow		EStdKeyDevice10	// Diagonal arrow event
+#define EStdKeyRightUpArrow		EStdKeyDevice11	// Diagonal arrow event
+#define EStdKeyRightDownArrow	EStdKeyDevice12	// Diagonal arrow event
+#define EStdKeyLeftDownArrow	EStdKeyDevice13	// Diagonal arrow event
+#define EStdKeyVolumeUp			EStdKeyIncVolume
+#define EStdKeyVolumeDown		EStdKeyDecVolume
+#define EStdKeyFlipOpen			EStdKeyDeviceA
+#define EStdKeyFlipClose		EStdKeyDeviceB
+#define EStdKeyPoC				EStdKeyApplication1
+#define EStdKeyPlay				EStdKeyApplication2
+#define EStdKeyStop				EStdKeyApplication3
+#define EStdKeyForward			EStdKeyApplication4
+#define EStdKeyRewind			EStdKeyApplication5
+#define EStdKeyOperator			EStdKeyApplication6
+#define EStdKeyQwertyOn			EStdKeyApplication7
+#define EStdKeyQwertyOff		EStdKeyApplication8
+#define EStdKeyNext				EStdKeyApplication9
+#define EStdKeyPrevious			EStdKeyApplicationA
+#define EStdKeyHoldSwitch		EStdKeyApplicationB
+#define EStdKeyZoomIn			EStdKeyApplicationC
+#define EStdKeyZoomOut			EStdKeyApplicationD
+#define EStdKey4x10QwertyOn		EStdKeyApplicationE
+#define EStdKey3x11QwertyOn		EStdKeyApplication10
+#define EStdKeyHalfQwertyOn		EStdKeyApplication11
+#define EStdKeyCustomKeyboardOn	EStdKeyApplication12
+
+/**
+TKeyCode aliases
+*/
+#define EKeyOK					EKeyDevice3
+#define EKeyCBA1				EKeyDevice0
+#define EKeyCBA2				EKeyDevice1
+#define EKeyPhoneSend			EKeyYes
+#define EKeyPhoneEnd			EKeyNo
+#define EKeyApplication 		EKeyApplication0
+#define EKeyPowerOff			EKeyDevice2
+#define EKeyGripOpen			EKeyDevice4
+#define EKeyGripClose			EKeyDevice5
+#define EKeySide				EKeyDevice6		// Voice key
+#define EKeyCamera				EKeyDevice7
+#define EKeyTwistOpen			EKeyDevice8
+#define EKeyTwistClose			EKeyDevice9
+#define EKeyLeftUpArrow			EKeyDevice10	// Diagonal arrow event
+#define EKeyRightUpArrow		EKeyDevice11	// Diagonal arrow event
+#define EKeyRightDownArrow		EKeyDevice12	// Diagonal arrow event
+#define EKeyLeftDownArrow		EKeyDevice13	// Diagonal arrow event
+#define EKeyVolumeUp			EKeyIncVolume
+#define EKeyVolumeDown			EKeyDecVolume
+#define EKeyFlipOpen			EKeyDeviceA
+#define EKeyFlipClose			EKeyDeviceB
+#define EKeyPoC					EKeyApplication1
+#define EKeyPlay				EKeyApplication2
+#define EKeyStop				EKeyApplication3
+#define EKeyForward				EKeyApplication4
+#define EKeyRewind				EKeyApplication5
+#define EKeyOperator			EKeyApplication6
+#define EKeyQwertyOn			EKeyApplication7
+#define EKeyQwertyOff			EKeyApplication8
+#define EKeyNext				EKeyApplication9
+#define EKeyPrevious			EKeyApplicationA
+#define EKeyHoldSwitch			EKeyApplicationB
+#define EKeyZoomIn				EKeyApplicationC
+#define EKeyZoomOut				EKeyApplicationD
+#define EKey4x10QwertyOn		EKeyApplicationE
+#define EKey3x11QwertyOn		EKeyApplication10
+#define EKeyHalfQwertyOn		EKeyApplication11
+#define EKeyCustomKeyboardOn EKeyApplication12
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/src/keyrouter.cpp	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,431 @@
+// Copyright (c) 2010 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:
+// Reference implementation of Key Event Routing plug-in
+
+/**
+@file
+@internalTechnology
+@prototype
+*/
+
+#include <e32cmn.h>
+#include <e32debug.h>
+#include "keyrouterimpl.h"
+#include "keyaliases.h"
+
+#ifdef KEYROUTER_TEST
+/**
+Privileged application UIDs
+*/
+const TInt KUidTAutoServer = 0x10205152;
+const TInt KUidReservedApp = 0x102872e3;
+
+/**
+Key Capture Translation Table
+
+The following scan codes and key codes are translated at capture-request time.
+
+@note	The data in this table is for example/test purposes only.
+*/
+const TTranslationEntry KTranslations[] =
+	{
+		// Entry for TEvent test case GRAPHICS-WSERV-0751.
+		// Capture requests for psuedo key Device0 are mapped to capture
+		// the real key Device1.
+		// Req. scancode,	Capture scancode,	Req. keycode,	Capture keycode
+		{ EStdKeyDevice0,	EStdKeyDevice1,		EKeyDevice0,	EKeyDevice1 }
+	};
+
+/**
+Restricted Key Table
+
+The following keys may be captured only by the specified application.
+
+@note	The data in this table is for example/test purposes only.
+*/
+const TAppKeyEntry KRestrictedKeys[] =
+	{
+		// Examples:
+		// Only the Phone app is allowed to capture long End key events
+		// { EKeyPhoneEnd,			ECaptureTypeLongKey,	KUidPhoneApp },
+		// Only the Home Screen app is allowed to capture short Apps key events
+		// { EStdKeyApplication,	ECaptureTypeKeyUpDown,	KUidHomeScreenApp },
+		// { EKeyApplication,		ECaptureTypeKey,		KUidHomeScreenApp },
+		// Only SysApp is allowed to capture long Apps key events (for
+		// launching the task switcher).
+		// { EKeyApplication,		ECaptureTypeLongKey,	KUidSysApp },
+
+		// Test Case GRAPHICS-WSERV-0754. Only a reserved UID is allowed to
+		// capture F20 key events.
+		{ EKeyF20,				ECaptureTypeKey,		KUidReservedApp },
+		{ EKeyF20,				ECaptureTypeLongKey,	KUidReservedApp },
+		{ EStdKeyF20,			ECaptureTypeKeyUpDown,	KUidReservedApp },
+		// Only TAuto tests are allowed to capture F21 key events
+		{ EKeyF21,				ECaptureTypeKey,		KUidTAutoServer },
+		{ EKeyF21,				ECaptureTypeLongKey,	KUidTAutoServer },
+		{ EStdKeyF21,			ECaptureTypeKeyUpDown,	KUidTAutoServer }
+	};
+
+/**
+Priority Application Table
+
+The following applications have priority over other applications for capture
+of the specified key.
+
+@note	The data in this table is for example/test purposes only.
+		If a key should be never be delivered to any other application, then
+		it should be placed in KRestrictedKeys[] instead.
+*/
+const TAppKeyEntry KPriorityAppKeys[] =
+	{
+		// Example:
+		// The Phone app has priority for capture of short Send and End
+		// key events
+		// { EStdKeyPhoneSend,	ECaptureTypeKeyUpDown,	KUidPhoneApp },
+		// { EKeyPhoneSend,		ECaptureTypeKey,		KUidPhoneApp },
+		// { EStdKeyPhoneEnd,	ECaptureTypeKeyUpDown,	KUidPhoneApp },
+		// { EKeyPhoneEnd,		ECaptureTypeKey,		KUidPhoneApp },
+
+		// Test Case GRAPHICS-WSERV-0757. TAuto tests have priority for
+		// capture of F22 key events.
+		{ EStdKeyF22,			ECaptureTypeKeyUpDown,	KUidTAutoServer },
+		{ EKeyF22,				ECaptureTypeKey,		KUidTAutoServer },
+		{ EKeyF22,				ECaptureTypeLongKey,	KUidTAutoServer }
+	};
+
+/**
+Blocked key table.
+
+The following keys are not routed by default.
+
+@note	The data in this table is for example/test purposes only.
+		Since long key events are never routed by default, there is no need
+		to list them here.
+*/
+const TBlockedKeyEntry KBlockedKeys[] =
+	{
+		// Entries for TEvent test case GRAPHICS-WSERV-0760
+		{ EStdKeyDevice3,	ECaptureTypeKeyUpDown },
+		{ EKeyDevice3,		ECaptureTypeKey }
+	};
+
+const TInt KNumTranslations = TABLE_SIZE(KTranslations);
+const TInt KNumRestrictedKeys = TABLE_SIZE(KRestrictedKeys);
+const TInt KNumPriorityAppKeys = TABLE_SIZE(KPriorityAppKeys);
+const TInt KNumBlockedKeys = TABLE_SIZE(KBlockedKeys);
+#endif // KEYROUTER_TEST
+
+const TInt KCaptureKeyArrayGranularity = 5;
+
+/**
+Create and return an instance of CKeyEventRouter
+
+@return	Pointer to new router instance
+*/
+EXPORT_C CKeyEventRouter* CKeyEventRouter::NewL()
+	{
+	return new(ELeave) CKeyEventRouterImpl;
+	}
+
+CKeyEventRouterImpl::CKeyEventRouterImpl()
+: iCaptureKeys(KCaptureKeyArrayGranularity, _FOFF(TKeyCaptureRequest, iHandle))
+	{
+	}
+
+CKeyEventRouterImpl::~CKeyEventRouterImpl()
+	{
+	iCaptureKeys.Close();
+	}
+
+/**
+Add a new key capture request
+
+@param	aRequest	Capture request details
+
+@see CKeyEventRouter::AddCaptureKeyL
+*/
+void CKeyEventRouterImpl::AddCaptureKeyL(const TKeyCaptureRequest& aRequest)
+	{
+	CheckCaptureKeyL(aRequest);
+	iCaptureKeys.InsertL(aRequest, 0);
+#ifdef KEYROUTER_TEST
+	TranslateCaptureKey(aRequest.iType, iCaptureKeys[0].iInputCode);
+#endif
+	}
+   
+/**
+Update an existing key capture request
+
+@param	aRequest	Updated capture request details
+
+@see CKeyEventRouter::UpdateCaptureKeyL
+*/
+void CKeyEventRouterImpl::UpdateCaptureKeyL(const TKeyCaptureRequest& aRequest)
+	{
+	CheckCaptureKeyL(aRequest);
+
+	TInt index = iCaptureKeys.Find(aRequest);
+	ASSERT(index != KErrNotFound);
+
+	if (index != KErrNotFound)
+		{
+		iCaptureKeys[index] = aRequest;
+		}
+	}
+
+/**
+Cancel a key capture request
+
+@param	aType		Capture type
+@param	aHandle		Opaque handle of request to be cancelled
+
+@see CKeyEventRouter::CancelCaptureKey
+
+Note: aType is unused in this implementation, but is present to permit
+implementations that use separate lists for each of the three capture types.
+*/
+void CKeyEventRouterImpl::CancelCaptureKey(TKeyCaptureType /*aType*/, TAny* aHandle)
+	{
+	TKeyCaptureRequest request;
+	request.iHandle = aHandle;
+
+	TInt index = iCaptureKeys.Find(request);
+	if (index != KErrNotFound)
+		{
+		iCaptureKeys.Remove(index);
+		}
+	}
+
+/**
+Route the key event described by aInput and return its destination in iOutput
+
+@param	aInput		Input data with key event to be routed
+@param	aOutput		Output key event and routing results
+
+@see CKeyEventRouter::RouteKey
+*/
+void CKeyEventRouterImpl::RouteKey(const TKeyEventRouterInput& aInput, TKeyEventRouterOutput& aOutput)
+	{
+	TUint inputCode = (aInput.iType == ECaptureTypeKeyUpDown) ?
+						aInput.iKeyEvent.iScanCode : aInput.iKeyEvent.iCode;
+#ifdef KEYROUTER_TEST
+	TInt priUid = PriorityAppUid(aInput.iType, inputCode);
+#endif
+	TInt priority = KMinTInt;
+	TInt captureCount = iCaptureKeys.Count();
+	TKeyCaptureRequest* matchRequest = NULL;
+
+	// Find the highest priority matching capture request. If there are
+	// multiple entries with the same priority then use the first one, i.e.
+	// the most recent request. Capture priorities are overridden if a
+	// particular application has precedence for capture of the key.
+	for (TInt index = 0; index < captureCount; index++)
+		{
+		TKeyCaptureRequest& request = iCaptureKeys[index];
+		if (request.iType == aInput.iType &&
+			request.iInputCode == inputCode &&
+		    (aInput.iKeyEvent.iModifiers & request.iModifierMask) == request.iModifiers &&
+			(request.iPriority > priority
+#ifdef KEYROUTER_TEST
+			 || priUid != 0 && request.iAppUid.iUid == priUid
+#endif
+			 ))
+			{
+			matchRequest = &request;
+#ifdef KEYROUTER_TEST
+			if (priUid != 0 && request.iAppUid.iUid == priUid)
+				{
+				break;
+				}
+#endif
+			priority = request.iPriority;
+			}
+		}
+
+	if (matchRequest)
+		{
+		// Found matching capture request. Route the key event to the window
+		// group that made the capture request.
+		aOutput.iWindowGroup = matchRequest->iWindowGroup;
+		if (aInput.iType == ECaptureTypeKeyUpDown)
+			{
+			aOutput.iKeyEvent.iScanCode = matchRequest->iOutputCode;
+			aOutput.iKeyEvent.iCode = aInput.iKeyEvent.iCode;
+			}
+		else
+			{
+			aOutput.iKeyEvent.iScanCode = aInput.iKeyEvent.iScanCode;
+			aOutput.iKeyEvent.iCode = matchRequest->iOutputCode;
+			}
+		aOutput.iKeyEvent.iModifiers = aInput.iKeyEvent.iModifiers;
+		aOutput.iCaptureHandle = matchRequest->iHandle;
+		aOutput.iResult = ECaptured;
+		}
+#ifdef KEYROUTER_TEST
+	else if (IsKeyBlocked(aInput.iType, inputCode))
+		{
+		// No matching capture request and key is blocked. Do not route.
+		aOutput.iResult = EConsumed;
+		}
+#endif
+	else
+		{
+		// No matching capture request. Route the key event to the current
+		// focussed window group.
+		aOutput.iWindowGroup = aInput.iFocusWindowGroup;
+		aOutput.iKeyEvent = aInput.iKeyEvent;
+		aOutput.iCaptureHandle = NULL;
+		aOutput.iResult = ERouted;
+		}
+	}
+
+/**
+Check that capture request arguments are sane and capture is allowed
+
+@param	aRequest	Capture request details
+
+@leave	KErrArgument if modifier state contains bits that are not in the
+		modifier mask or modifier mask contains EModifierLongKey or priority
+		is KMinTInt.
+		KErrPermissionDenied if key is restricted to capture by a specific
+		application UID and the UID of the requesting app does not match.
+
+@note	Requests with a priority of KMinTint would never be captured: this was
+		also true of the previous implementation in ektran.dll but was ignored.
+		Client code must use the appropriate API function to capture short or
+		long key events, so including EModifierLongKey in the modifier mask is
+		not allowed. (Hotkeys are excepted since a mask of 0xffffffff is used
+		to disable them).
+*/
+void CKeyEventRouterImpl::CheckCaptureKeyL(const TKeyCaptureRequest& aRequest)
+	{
+	if ((aRequest.iModifiers & ~aRequest.iModifierMask) != 0 ||
+		(aRequest.iModifierMask & EModifierLongKey) != 0 && aRequest.iWindowGroup != NULL ||
+		aRequest.iPriority == KMinTInt)
+		{
+		User::Leave(KErrArgument);
+		}
+
+#ifdef KEYROUTER_TEST
+	if (aRequest.iWindowGroup != NULL && IsRestrictedKey(aRequest))
+		{
+		User::Leave(KErrPermissionDenied);
+		}
+#endif
+	}
+
+#ifdef KEYROUTER_TEST
+/**
+Check if the requested key capture is restricted by application UID
+
+@param	aRequest	Capture request details
+
+@return	ETrue if key is restricted and requesting UID does not match,
+		otherwise EFalse.
+*/
+TBool CKeyEventRouterImpl::IsRestrictedKey(const TKeyCaptureRequest& aRequest)
+	{
+	for (const TAppKeyEntry* entry = KRestrictedKeys; entry < &KRestrictedKeys[KNumRestrictedKeys]; entry++)
+		{
+		if (entry->iCode == aRequest.iInputCode &&
+			entry->iType == aRequest.iType &&
+			entry->iAppUidValue != aRequest.iAppUid.iUid)
+			{
+			return ETrue;
+			}
+		}
+
+		return EFalse;
+	}
+
+/**
+Return the UID of the application with priority for capture of the specified
+key.
+
+@param	aType	Key capture type
+@param	aCode	Key code or scan code
+
+@return	UID3 of the privileged application or zero if none.
+*/
+TInt CKeyEventRouterImpl::PriorityAppUid(TKeyCaptureType aType, TUint aCode)
+	{
+	for (const TAppKeyEntry* entry = KPriorityAppKeys; entry < &KPriorityAppKeys[KNumPriorityAppKeys]; entry++)
+		{
+		if (entry->iCode == aCode && entry->iType == aType)
+			{
+			return entry->iAppUidValue;
+			}
+		}
+
+		return 0;
+	}
+
+/**
+Check if the specified key is blocked from default routing
+
+@param	aType		Key capture type
+@param	aCode		Scan code or key code
+
+@return	ETrue if key is blocked, otherwise EFalse.
+*/
+TBool CKeyEventRouterImpl::IsKeyBlocked(TKeyCaptureType aType, TUint aCode)
+	{
+	for (const TBlockedKeyEntry* entry = KBlockedKeys; entry < &KBlockedKeys[KNumBlockedKeys]; entry++)
+		{
+		if (entry->iCode == aCode && entry->iType == aType)
+			{
+			return ETrue;
+			}
+		}
+
+		return EFalse;
+	}
+
+/**
+Translate the scan or key code of a capture request
+
+@param	aType	Key capture type
+@param	aCode	Key code or scan code, updated to translated value (if any)
+
+@note	This function is used to translate the input key or scan code of a
+		capture request on addition to the capture list. When a key event that
+		matches the list entry is routed, the output code will be taken from
+		TKeyCaptureRequest.iOutputCode and hence automatically translated again
+		(typically back to the original input code of the request, unless the
+		input and output codes were different). For example, a request to
+		capture key code A will be translated to key code B in the capture list.
+		When RouteKey() processes an event with key code B and selects that
+		list entry, it will output key code A for delivery to the application.
+*/
+void CKeyEventRouterImpl::TranslateCaptureKey(TKeyCaptureType aType, TUint& aCode)
+{
+	for (const TTranslationEntry* entry = KTranslations; entry < &KTranslations[KNumTranslations]; entry++)
+		{
+		if (aType == ECaptureTypeKeyUpDown)
+			{
+			if (aCode == entry->iRequestScanCode)
+				{
+				aCode = entry->iCaptureScanCode;
+				}
+			}
+		else
+			{
+			if (aCode == entry->iRequestKeyCode)
+				{
+				aCode = entry->iCaptureKeyCode;
+				}
+			}
+		}
+	}
+#endif // KEYROUTER_TEST
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserverplugins/keyeventrouting/src/keyrouterimpl.h	Fri Sep 24 16:44:34 2010 +0300
@@ -0,0 +1,84 @@
+// Copyright (c) 2010 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:
+// Reference implementation of Key Event Routing plug-in
+
+/**
+@file
+@internalTechnology
+@prototype
+*/
+
+#ifndef KEYROUTERIMPL_H
+#define KEYROUTERIMPL_H
+
+#include <graphics/wskeyrouter.h>
+
+#ifdef KEYROUTER_TEST
+/** Key Capture Translation Table entry */
+struct TTranslationEntry
+	{
+	TUint	iRequestScanCode;
+	TUint	iCaptureScanCode;
+	TUint	iRequestKeyCode;
+	TUint	iCaptureKeyCode;
+	};
+
+/** Entry for Restricted Key and Priority Application tables */
+struct TAppKeyEntry
+	{
+	TUint			iCode;
+	TKeyCaptureType	iType;
+	TInt			iAppUidValue;
+	};
+
+/** Blocked Key Table entry */
+struct TBlockedKeyEntry
+	{
+	TUint			iCode;
+	TKeyCaptureType	iType;
+	};
+
+#define TABLE_SIZE(table) (sizeof(table) / sizeof((table)[0]))
+
+#endif // KEYROUTER_TEST
+
+/**
+Key Event Router implementation class
+*/
+NONSHARABLE_CLASS(CKeyEventRouterImpl) : public CKeyEventRouter
+	{
+public:
+	CKeyEventRouterImpl();
+	~CKeyEventRouterImpl();
+
+	// From CKeyEventRouter
+	void AddCaptureKeyL(const TKeyCaptureRequest& aRequest);
+	void UpdateCaptureKeyL(const TKeyCaptureRequest& aRequest);
+	void CancelCaptureKey(TKeyCaptureType aType, TAny* aHandle);
+	void RouteKey(const TKeyEventRouterInput& aInput,
+				  TKeyEventRouterOutput& aOutput);
+private:
+	void CheckCaptureKeyL(const TKeyCaptureRequest& aRequest);
+#ifdef KEYROUTER_TEST
+	TBool IsRestrictedKey(const TKeyCaptureRequest& aRequest);
+	TBool IsKeyBlocked(TKeyCaptureType aType, TUint aCode);
+	TInt PriorityAppUid(TKeyCaptureType aType, TUint aCode);
+	void TranslateCaptureKey(TKeyCaptureType aType, TUint& aCode);
+#endif
+
+private:
+	RArray<TKeyCaptureRequest>	iCaptureKeys;
+	};
+
+#endif // KEYROUTERIMPL_H
--- a/windowing/windowserverplugins/openwfc/group/wserv_std_plugins.iby	Fri Sep 24 16:14:28 2010 +0300
+++ b/windowing/windowserverplugins/openwfc/group/wserv_std_plugins.iby	Fri Sep 24 16:44:34 2010 +0300
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* Copyright (c) 2010 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"
@@ -30,4 +30,6 @@
 ECOM_PLUGIN(10286378.dll,10286378.rsc)
 #endif
 
+#include <keyeventrouting.iby>
+
 #endif // __WSERV_STD_PLUGINS_IBY__