windowing/windowserver/nga/SERVER/EVENT.CPP
changeset 0 5d03bc08d59c
child 4 15986eb6c500
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/EVENT.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1741 @@
+// Copyright (c) 1994-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:
+// Top level window server code
+// 
+//
+
+#include "EVENT.H"
+
+#include "W32STD.H"
+#include <hal.h>
+#include <w32adll.h>
+#include "W32CLICK.H"
+#include "server.h"
+#include "windowgroup.h"
+#include "KEYCLICK.H"
+#include "wstop.h"
+#include "panics.h"
+#include "screen.h"
+#include "inifile.h"
+#include "password.h"
+#include "pointer.h"
+#include "debugbar.h"
+#include "advancedpointereventhelper.h"
+
+GLREF_D CDebugLogBase *wsDebugLog;
+
+GLREF_C void StateDump();
+GLREF_C void HeapDump();
+
+#define IMPOSSIBLE 0xFFFFFFFF
+
+const TWsWinCmdCaptureKey ImpossibleKeyPress=
+	{
+	IMPOSSIBLE,	// Impossible to hit key combination, used for disabling Hot Keys
+	IMPOSSIBLE,
+	IMPOSSIBLE};
+
+const TWsWinCmdCaptureKey DefaultHotKeys[TWindowServerEvent::ENumHotKeys]={
+	{	// Enable logging
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	5}, // E
+	{	// Disable logging
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	4}, // D
+	{	// Window server internal dump to log
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	23},// W
+	{	// The key of death
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	11},// K
+	{	// Shutdown window server
+#if defined(_DEBUG)
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	24},// X
+#else
+	IMPOSSIBLE,	// Impossible to hit key combination, effectively disables shutdown key in release builds
+	IMPOSSIBLE,
+	IMPOSSIBLE},
+#endif
+	{	// Heap dump
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	8}, // H
+	{	// Inc Contrast
+	0,
+	0,
+	EKeyIncContrast},
+	{	// Dec Contrast
+	0,
+	0,
+	EKeyDecContrast},
+	{	// Off
+	0,
+	0,
+	EKeyOff},
+	{	// Backlight on 
+	0,
+	0,
+	EKeyBacklightOn},
+	{	// Backlight off
+	0,
+	0,
+	EKeyBacklightOff},
+	{	// Backlight toggle
+	0,
+	0,
+	EKeyBacklightToggle},
+	{	// Screen Dimension Change
+	0,
+	0,
+	EKeyScreenDimension0},
+	{
+	0,
+	0,
+	EKeyScreenDimension1},
+	{
+	0,
+	0,
+	EKeyScreenDimension2},
+	{
+	0,
+	0,
+	EKeyScreenDimension3},
+#if defined(_DEBUG)
+	{	// Display mode cycle
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	21},// U
+	{	// Orientation cycle
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	15},// O
+#else
+	{	// Display mode cycle
+	IMPOSSIBLE,	// Impossible to hit key combination
+	IMPOSSIBLE,
+	IMPOSSIBLE},
+	{	// Orientation cycle
+	IMPOSSIBLE,	// Impossible to hit key combination
+	IMPOSSIBLE,
+	IMPOSSIBLE},
+#endif
+	{	// Inc Brightness
+	0,
+	0,
+	EKeyIncBrightness},
+	{	// Dec Brightness
+	0,
+	0,
+	EKeyDecBrightness},
+	{	// Cycle focus screen
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	EModifierFunc|EModifierCtrl|EModifierShift,
+	9}, // I
+	};
+
+CKeyTranslator *TWindowServerEvent::iKeyTranslator=NULL;
+TEventRequestQueue TWindowServerEvent::iSwitchOnQueue;
+TEventRequestQueue TWindowServerEvent::iErrorMessageQueue;
+TEventRequestQueue TWindowServerEvent::iModifierChangedQueue;
+TEventRequestQueue TWindowServerEvent::iGroupChangedQueue;
+TEventRequestQueue TWindowServerEvent::iFocusChangedQueue;
+TEventRequestQueue TWindowServerEvent::iGroupListChangedQueue;
+TEventRequestQueue TWindowServerEvent::iScreenDeviceChangedQueue;
+TTime TWindowServerEvent::iPrevOomMessageTime;
+CCaptureKeys *TWindowServerEvent::iCaptureKeys;
+CWsHotKey *TWindowServerEvent::iHotKeys;
+TInt TWindowServerEvent::iModifierState;
+CRawEventReceiver *TWindowServerEvent::iEventReceiver;
+RArray<TWindowServerEvent::TRawEventHandler> TWindowServerEvent::iEventHandlers;
+CArrayFixFlat<SNotificationHandler> *TWindowServerEvent::iNotificationHandlers;
+TInt TWindowServerEvent::iPotentialEventHandlers=0;
+TUint32 TWindowServerEvent::iBinaryFlags=0x00;
+RArray<TDrawerHandler>* TWindowServerEvent::iDrawerHandlers;
+RArray<TWsEventHandler> TWindowServerEvent::iWsEventHandlers;
+TInt TWindowServerEvent::iEventHandlerCount=0;
+TRepeatKey CKeyboardRepeat::iCurrentRepeat;
+TRepeatKey CKeyboardRepeat::iAlternateRepeat;
+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;
+
+
+void TWindowServerEvent::DeleteHotKeys()
+	{
+	CWsHotKey *hotKey=iHotKeys;
+	while(hotKey)
+		{
+		CWsHotKey *next=hotKey->iNext;
+		delete hotKey;
+		hotKey=next;
+		}
+	iHotKeys=NULL;
+	}
+
+void TWindowServerEvent::DeleteStatics()
+	{
+	DeleteHotKeys();
+	delete iCaptureKeys;
+	CKeyboardRepeat::Destroy();
+	delete iKeyTranslator;
+	delete iEventReceiver;
+	iEventHandlers.Close();
+	delete iNotificationHandlers;
+	iDrawerHandlers->Close();
+	delete iDrawerHandlers;
+	iWsEventHandlers.Close();
+	}
+
+void TWindowServerEvent::InitStaticsL()
+//
+// Create the CEvent active object.
+//
+	{
+#if defined(__WINS__)
+	WS_ASSERT_DEBUG(TWindowServerEvent::ENumHotKeys==EHotKeyLastKeyType+1, EWsPanicUnknownCaptureKey);
+#endif
+	iEventReceiver=new(ELeave) CRawEventReceiver(EEventPriority);
+	iEventReceiver->ConstructL();
+	iKeyTranslator=CKeyTranslator::New();
+	User::LeaveIfNull(iKeyTranslator);
+    
+//  Change keyboard mapping according to information the HAL
+	TInt keyboardIndex;
+	if (HAL::Get(HALData::EKeyboardIndex,keyboardIndex)==KErrNone)
+		{
+		_LIT(KLitKeyDataDllName,"EKDATA.%02d");
+		TBuf<16> keyDataDllName;
+		keyDataDllName.Format(KLitKeyDataDllName,keyboardIndex);
+		iKeyTranslator->ChangeKeyData(keyDataDllName);
+		}
+
+	iCaptureKeys=new(ELeave) CCaptureKeys;
+	iCaptureKeys->Construct();
+	for (TInt index=0;index<TWindowServerEvent::ENumHotKeys;index++)
+		ConstructDefaultHotKeyL(index,DefaultHotKeys[index]);
+	CKeyboardRepeat::NewL();
+	CKeyboardRepeat::SetRepeatTime(EDefaultInitialRepeatTime, EDefaultRepeatTime);
+	iEventHandlers=RArray<TRawEventHandler>(2);
+	iNotificationHandlers=new(ELeave) CArrayFixFlat<SNotificationHandler>(2);
+	iDrawerHandlers = new(ELeave) RArray<TDrawerHandler>(4);
+	}
+
+void TWindowServerEvent::LinkHotKey(CWsHotKey *aWsHotKey)
+	{
+	aWsHotKey->SetLink(iHotKeys);
+	iHotKeys=aWsHotKey;
+	}
+
+void TWindowServerEvent::ConstructDefaultHotKeyL(TInt aHotKey, const TWsWinCmdCaptureKey &aSystemKey)
+	{
+	CWsHotKey* hotKey=new(ELeave) CWsHotKey(aHotKey, ETrue);
+	// hotKey is pushed onto the cleanup stack in method ConstructLD.
+	hotKey->ConstructLD(aSystemKey);
+	LinkHotKey(hotKey);
+	}
+
+CWsHotKey* TWindowServerEvent::ClearHotKeysL(TInt aHotKey)
+	{
+	if (aHotKey>ENumHotKeys)
+		{
+		User::Leave(KErrArgument);
+		}
+	CWsHotKey** pHotKey= &iHotKeys;
+	CWsHotKey* defaultHotKey=NULL;
+	while(*pHotKey)
+		{
+		TBool unlinked=EFalse;
+		if ((*pHotKey)->HotKeyType()==aHotKey)
+			{
+			CWsHotKey *free=*pHotKey;
+			if (free->IsDefault())
+				{
+				free->SetL(ImpossibleKeyPress);
+				defaultHotKey=free;
+				}
+			else
+				{
+				*pHotKey=(*pHotKey)->iNext;
+				delete free;
+				unlinked=ETrue;
+				}
+			}
+		if (!unlinked)
+			{
+			pHotKey=&(*pHotKey)->iNext;
+			}
+		}
+	return(defaultHotKey);
+	}
+
+void TWindowServerEvent::ResetDefaultHotKeyL(TInt aHotKey)
+	{
+	if ((aHotKey<0) || (aHotKey>=ENumHotKeys))
+		{
+		User::Leave(KErrArgument);
+		}
+	CWsHotKey* defaultHotKey=ClearHotKeysL(aHotKey);
+	WS_ASSERT_DEBUG(defaultHotKey, EWsPanicDefaultHotKeyNotFound);
+	defaultHotKey->SetL(DefaultHotKeys[aHotKey]);
+	}
+
+void TWindowServerEvent::SetHotKeyL(const TWsClCmdSetHotKey &aHotKey)
+	{
+	if (aHotKey.type>ENumHotKeys)
+		User::Leave(KErrArgument);
+//
+	CWsHotKey *hotKey=new(ELeave) CWsHotKey(aHotKey.type, EFalse);
+//
+	TWsWinCmdCaptureKey captureKey;
+	captureKey.modifiers=aHotKey.modifiers;
+	captureKey.modifierMask=aHotKey.modifierMask;
+	captureKey.key=aHotKey.keycode;
+	hotKey->ConstructLD(captureKey);
+//
+	LinkHotKey(hotKey);
+	}
+
+void TWindowServerEvent::AddEventHandler(MEventHandler *aEventHandler, TBool aAdvancedPointersEnabled)
+	{
+#if defined(_DEBUG)
+	TRAPD(err,iEventHandlers.AppendL(TRawEventHandler(aEventHandler, aAdvancedPointersEnabled)));
+	WS_ASSERT_DEBUG(err==KErrNone, EWsPanicEventHandlerInconsistency);
+#else
+	iEventHandlers.AppendL(TRawEventHandler(aEventHandler, aAdvancedPointersEnabled));	//Shouldn't leave
+#endif
+	}
+
+void TWindowServerEvent::RemoveEventHandler(const MEventHandler *aEventHandler)
+	{
+	TInt count=iEventHandlers.Count();
+	TInt ii;
+	for(ii=0;ii<count;++ii)
+		{
+		if (iEventHandlers[ii].iEventHandler==aEventHandler)
+			{
+			if (iEventHandlerCount>0)  
+				{
+				iBinaryFlags |= ERemovedEventHandlerWhileProcessingRawEvents;
+				iEventHandlers[ii].iEventHandler=NULL; // replace the Handler with null to keep size of the array
+				}
+			else 
+				{
+				iEventHandlers.Remove(ii);
+				}
+			return;
+			}
+		}
+	}
+
+void TWindowServerEvent::PotentialEventHandlerL(TInt aNum)
+	{
+	iPotentialEventHandlers+=aNum;
+	WS_ASSERT_DEBUG(iPotentialEventHandlers>=iEventHandlers.Count(), EWsPanicEventHandlerInconsistency);
+	TRAPD(err,iEventHandlers.Reserve(iPotentialEventHandlers));
+	if (err!=KErrNone)
+		{
+		if (aNum>0)
+			User::Leave(err);
+		}
+	else if (iPotentialEventHandlers==0)
+		iEventHandlers.Compress();
+	}
+
+void SendSwitchOnEvent(TEventRequestItem *aQptr, TInt aEvent, TInt )
+	{
+	aQptr->iWindow->QueueEvent(aEvent);
+	}
+
+/*void SendSwitchOffEvent(TEventRequestItem *aQptr, TInt , TInt )
+	{
+	aQptr->iWindow->QueueEvent(EEventSwitchOff);
+	}*/
+
+void SendErrorMessage(TEventRequestItem *aQptr, TInt aCategory, TInt aError)
+	{
+	TWsEvent event;
+	event.SetType(EEventErrorMessage);
+	event.SetHandle(aQptr->iWindow->ClientHandle());
+	event.ErrorMessage()->iErrorCategory=(TWsErrorMessage::TErrorCategory)aCategory;
+	event.ErrorMessage()->iError=aError;
+	event.SetTimeNow();
+	aQptr->iWindow->EventQueue()->QueueEvent(event,EEventPriorityHigh);
+	}
+
+void SendModifierChangedEvent(TEventRequestItem *aQptr, TInt aChanged, TInt )
+	{
+	TInt tmpChanged=aChanged&aQptr->iParam;
+	if (tmpChanged)
+		{
+		TWsEvent event;
+		event.SetType(EEventModifiersChanged);
+		event.SetHandle(aQptr->iWindow->ClientHandle());
+		event.ModifiersChanged()->iChangedModifiers=tmpChanged;
+		event.ModifiersChanged()->iModifiers=TWindowServerEvent::GetStoredModifierState();
+		event.SetTimeNow();
+		aQptr->iWindow->EventQueue()->QueueEvent(event,EEventPriorityHigh);
+		}
+	}
+
+void TWindowServerEvent::ProcessEventQueue(TEventRequestQueue &aQueue, TSendEventFunc aFunc, TInt aParam1, TInt aParam2)
+	{
+	TSglQueIter<TEventRequestItem> iter(aQueue.Queue());
+	TEventRequestItem *qPtr;
+	CWsWindowGroup *focusWin=CWsTop::FocusWindowGroup();
+	while((qPtr=iter++)!=NULL)
+		{
+		if (qPtr->iCircumstances==EEventControlAlways || 
+			(qPtr->iCircumstances==EEventControlOnlyWithKeyboardFocus && qPtr->iWindow->WinGroup()==focusWin) ||
+			(qPtr->iCircumstances==EEventControlOnlyWhenVisible && !qPtr->iWindow->TreeIsObscured()))
+			aFunc(qPtr, aParam1, aParam2);
+		}
+	}
+
+void TWindowServerEvent::NotifyOom()
+	{
+	TTime now;
+	now.UniversalTime();
+	TTimeIntervalSeconds interval;
+	TInt err=now.SecondsFrom(iPrevOomMessageTime,interval);
+	if (err!=KErrNone || interval.Int()<0 || interval.Int()>EOomEventSecondGap)
+		{
+		ProcessErrorMessages(TWsErrorMessage::EDrawingRegion,KErrNoMemory);
+		iPrevOomMessageTime=now;
+		}
+	}
+
+TBool TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::TErrorCategory aCategory, TInt aError)
+	{
+	if (aError!=KErrNone)
+		{
+		ProcessEventQueue(iErrorMessageQueue, SendErrorMessage, aCategory, aError);
+		return ETrue;
+		}
+	return EFalse;
+	}
+
+void TWindowServerEvent::ProcessModifierChanges()
+	{
+	TInt newState=iKeyTranslator->GetModifierState();
+	if (newState!=iModifierState)
+		{
+		TInt changed=iModifierState^newState;
+		iModifierState=newState;
+		ProcessEventQueue(iModifierChangedQueue, SendModifierChangedEvent, changed, 0);
+		}
+	}
+
+TEventQueueWalkRet FindScreenDeviceChangedEvent(TAny *aHandlePtr, TWsEvent *aEvent)
+	{
+	if (aEvent->Type()==EEventScreenDeviceChanged && aEvent->Handle()==*(TUint *)aHandlePtr)
+		*(TUint *)aHandlePtr=0;	// Indicates event found
+	return(EEventQueueWalkOk);
+	}
+	
+void TWindowServerEvent::SendScreenDeviceChangedEvents(CScreen* aScreen)
+	{
+	TSglQueIter<TEventRequestItem> iter(iScreenDeviceChangedQueue .Queue());
+	TEventRequestItem *qPtr;
+	while((qPtr=iter++)!=NULL)
+		SendScreenDeviceChangedEvent(qPtr->iWindow);
+	if(CClick::IsHandler())
+		{
+		TClickMakerData clickMakerData;
+		clickMakerData.screenDeviceMode=aScreen->ScreenSizeMode();
+		CClick::OtherEvent(EEventScreenDeviceChanged, &clickMakerData);
+		}
+	TWsEvent wsEvent;
+	wsEvent.SetType(EEventScreenDeviceChanged);
+	TWindowServerEvent::PublishNotification(wsEvent);
+	TWservCrEvent crEvent(TWservCrEvent::EScreenSizeModeChanged,aScreen->ScreenSizeMode());
+	TWindowServerEvent::NotifyDrawer(crEvent);
+	}
+
+void TWindowServerEvent::SendScreenDeviceChangedEvent(const CWsWindowBase *aWindow)
+	{
+	CEventQueue *queue=aWindow->EventQueue();
+	TUint32 handle=aWindow->ClientHandle();
+	queue->WalkEventQueue(&FindScreenDeviceChangedEvent,&handle);
+	if (handle!=NULL)	// Indicates event not found
+		queue->QueueEvent(handle, EEventScreenDeviceChanged);
+	}
+
+TEventQueueWalkRet FindGroupChangedEvent(TAny *aHandlePtr, TWsEvent *aEvent)
+	{
+	if (aEvent->Type()==EEventWindowGroupsChanged && aEvent->Handle()==*(TUint *)aHandlePtr)
+		{
+		*(TUint *)aHandlePtr=0;	// Indicates event found
+		}
+	return(EEventQueueWalkOk);
+	}
+	
+void TWindowServerEvent::SendGroupChangedEvents()
+	{
+	TSglQueIter<TEventRequestItem> iter(iGroupChangedQueue.Queue());
+	TEventRequestItem *qPtr;
+	while((qPtr=iter++)!=NULL)
+		{
+		const CWsWindowBase *win=qPtr->iWindow;
+		CEventQueue *queue=win->EventQueue();
+		TUint32 handle=win->ClientHandle();
+		queue->WalkEventQueue(&FindGroupChangedEvent,&handle);
+		if (handle!=NULL)	// Indicates event not found
+			{
+			queue->QueueEvent(handle, EEventWindowGroupsChanged);
+			}
+		}
+	}	
+
+TEventQueueWalkRet FindFocusChangedEvent(TAny *aHandlePtr, TWsEvent *aEvent)
+	{
+	if (aEvent->Type()==EEventFocusGroupChanged && aEvent->Handle()==*(TUint *)aHandlePtr)
+		{
+		*(TUint *)aHandlePtr=0;	// Indicates event found
+		}
+	return(EEventQueueWalkOk);
+	}
+	
+void TWindowServerEvent::SendFocusChangedEvents()
+	{
+	TInt identifier=0;	// Zero Identifier indicates, currently there is no focused window group
+	CScreen* currentFocusScreen=CWsTop::CurrentFocusScreen();	
+	TInt screenNumber=currentFocusScreen->ScreenNumber();
+	CWsWindowGroup* currentFocusWG=currentFocusScreen->FocusWindowGroup();
+	if(currentFocusWG)
+		{
+		identifier=currentFocusWG->Identifier();
+		}
+	TWindowServerEvent::NotifyDrawer(TWservCrEvent(TWservCrEvent::EWindowGroupChanged,
+		screenNumber, reinterpret_cast<TAny*>(identifier)));
+		 
+	TSglQueIter<TEventRequestItem> iter(iFocusChangedQueue.Queue());
+	TEventRequestItem *qPtr;
+	while((qPtr=iter++)!=NULL)
+		{
+		const CWsWindowBase *win=qPtr->iWindow;
+		CEventQueue *queue=win->EventQueue();
+		TUint32 handle=win->ClientHandle();
+		queue->WalkEventQueue(&FindFocusChangedEvent,&handle);
+		if (handle!=NULL)	// Indicates event not found
+			{
+			queue->QueueEvent(handle, EEventFocusGroupChanged);
+			}
+		}
+	}
+
+TEventQueueWalkRet FindGroupListChangedEvent(TAny *aHandlePtr, TWsEvent *aEvent)
+	{
+	if (aEvent->Type()==EEventWindowGroupListChanged && aEvent->Handle()==*(TUint *)aHandlePtr)
+		{
+		*(TUint *)aHandlePtr=0;	// Indicates event found
+		}
+	return(EEventQueueWalkOk);
+	}
+	
+void TWindowServerEvent::SendGroupListChangedEvents()
+	{
+	TSglQueIter<TEventRequestItem> iter(iGroupListChangedQueue.Queue());
+	TEventRequestItem *qPtr;
+	while((qPtr=iter++)!=NULL)
+		{
+		const CWsWindowBase *win=qPtr->iWindow;
+		CEventQueue *queue=win->EventQueue();
+		TUint32 handle=win->ClientHandle();
+		queue->WalkEventQueue(&FindGroupListChangedEvent,&handle);
+		if (handle!=NULL)	// Indicates event not found
+			{
+			queue->QueueEvent(handle, EEventWindowGroupListChanged);
+			}
+		}
+	}	
+
+TEventQueueWalkRet OverrideVisibilityChangedEvent(TAny *aNewEvent, TWsEvent *aOldEvent)
+	{
+	// This replaces the first visibility event it finds for the given window with the
+	// one given.  This is fine, so long as the meaning of all visibility events remains
+	// independent of the ones before.
+	TWsEvent* newEvent = static_cast<TWsEvent*>(aNewEvent);
+	if (aOldEvent->Type()==EEventWindowVisibilityChanged && aOldEvent->Handle()==newEvent->Handle())
+		{
+		aOldEvent->SetTimeNow();
+		aOldEvent->VisibilityChanged()->iFlags = newEvent->VisibilityChanged()->iFlags;
+		newEvent->SetHandle(NULL);
+		}
+	return EEventQueueWalkOk;
+	}
+
+void TWindowServerEvent::SendVisibilityChangedEvents(CWsWindowBase* aWin, TUint aFlags)
+	{
+	CEventQueue *queue=aWin->EventQueue();
+	TWsEvent event;
+	event.SetType(EEventWindowVisibilityChanged);
+	event.SetHandle(aWin->ClientHandle());
+	event.SetTimeNow();
+	TWsVisibilityChangedEvent* visevent = event.VisibilityChanged();
+	visevent->iFlags = aFlags;
+	queue->WalkEventQueue(&OverrideVisibilityChangedEvent,&event);
+	if (event.Handle()!=NULL)
+		{
+		queue->QueueEvent(event);
+		}
+	}
+
+TEventQueueWalkRet OverrideDisplayChangedEvent(TAny *aNewEvent, TWsEvent *aOldEvent)
+	{
+	TWsEvent* newEvent = static_cast<TWsEvent*>(aNewEvent);
+	if (aOldEvent->Type() == EEventDisplayChanged && 
+			aOldEvent->DisplayChanged()->iDisplayNumber == newEvent->DisplayChanged()->iDisplayNumber)
+		{
+		aOldEvent->SetTimeNow();
+		aOldEvent->DisplayChanged()->iConfigurationChangeId = newEvent->DisplayChanged()->iConfigurationChangeId;
+		aOldEvent->DisplayChanged()->iResolutionListChangeId = newEvent->DisplayChanged()->iResolutionListChangeId;
+		newEvent->DisplayChanged()->iDisplayNumber = KErrNotFound; //So the new event won't be placed on event queue again
+		}
+	return EEventQueueWalkOk;
+	}
+
+TBool TWindowServerEvent::SendDisplayChangedEvents(CWsClient* aWsClient, TInt aDisplayNumber, TInt aConfigurationChangeId, TInt aResolutionListChangeId)
+	{
+	CEventQueue *queue = aWsClient->EventQueue();
+	TWsEvent event;
+	event.SetType(EEventDisplayChanged);
+	event.SetTimeNow();
+	TWsDisplayChangedEvent* dispEvent = event.DisplayChanged();
+	dispEvent->iDisplayNumber = aDisplayNumber;
+	dispEvent->iConfigurationChangeId = aConfigurationChangeId;
+	dispEvent->iResolutionListChangeId = aResolutionListChangeId;
+	queue->WalkEventQueue(&OverrideDisplayChangedEvent, &event);
+	//place the new event on the queue only when its display number is valid (!=KErrNotFound)
+	if(event.DisplayChanged()->iDisplayNumber >= 0)
+		{
+		return queue->QueueEvent(event);
+		}
+	return ETrue;
+	}
+
+void TWindowServerEvent::QueueKeyEvent(CWsWindowGroup *aWin, TWsEvent &aEvent, TWservEventPriorities aPriority)
+	{
+	aEvent.SetTimeNow();
+	aWin->EventQueue()->QueueEvent(aEvent, aPriority);
+	}
+
+void TWindowServerEvent::QueueKeyPress(const TKeyData& aKey, TInt aScanCode, CWsWindowGroup* aRepeatFocus, 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)
+		{
+		if (aKey.iApp==NULL)	// Captured by Wserv itself
+			{
+			_LIT(KWSERVDebugLogCapturedKey,"WSERV Captured Key");
+			CScreen* focusScreen=CWsTop::CurrentFocusScreen();
+			TInt screenNo=focusScreen->ScreenNumber();
+			
+			if (wsDebugLog)
+				wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,KWSERVDebugLogCapturedKey);
+			CWsHotKey *hotKey=iHotKeys;
+			while(hotKey)
+				{
+				if (hotKey->KeyHandle()==aKey.iHandle)
+					{
+					switch(hotKey->HotKeyType())
+						{
+						case EHotKeyEnableLogging:
+							CWsTop::EnableLogging();
+							break;
+						case EHotKeyDisableLogging:
+							CWsTop::DisableLogging();
+							break;
+						case EHotKeyStateDump:
+							StateDump();
+							break;
+						case EHotKeyHeapDump:
+							HeapDump();
+							break;
+						case EHotKeyOfDeath:
+							if (!CWsPassword::PasswordModeActive())
+								{
+								const TBool currentJustInTimeValue=User::JustInTime();
+								if (currentJustInTimeValue)
+									{
+									User::SetJustInTime(EFalse);
+									}
+								CWsTop::KillForegroundSession();
+								if (currentJustInTimeValue)
+									{
+									User::SetJustInTime(ETrue);
+									}
+								}
+							break;
+						case EHotKeyShutDown:
+							CWsTop::Exit();
+							break;
+						case EHotKeyIncContrast:
+							focusScreen->IncContrast();
+							break;
+						case EHotKeyDecContrast:
+							focusScreen->DecContrast();
+							break;
+						case EHotKeyOff:
+							CWsTop::HandleSwitchOff(EEventKeySwitchOff,ETrue);
+							break;
+						case EHotKeyBacklightToggle:
+							{
+							TInt state;
+							if (!ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Get(screenNo,HALData::EBacklightState,state)))
+								ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Set(screenNo,HALData::EBacklightState,!state));
+							}
+							break;
+						case EHotKeyBacklightOn:
+							ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Set(screenNo,HALData::EBacklightState,ETrue));
+							break;
+						case EHotKeyBacklightOff:
+							ProcessErrorMessages(TWsErrorMessage::EBackLight, HAL::Set(screenNo,HALData::EBacklightState,EFalse));
+							break;
+						case EHotKeyScreenDimension0:
+						case EHotKeyScreenDimension1:
+						case EHotKeyScreenDimension2:
+						case EHotKeyScreenDimension3:
+							focusScreen->doSetScreenMode(hotKey->HotKeyType()-EHotKeyScreenDimension0);
+							break;
+						case EHotKeyCycleDisplaySize:
+							focusScreen->CycleDisplaySize();
+							break;
+						case EHotKeyCycleOrientation:
+							focusScreen->CycleOrientation();
+							break;
+						case EHotKeyIncBrightness:
+							focusScreen->IncBrightness();
+							break;
+						case EHotKeyDecBrightness:
+							focusScreen->DecBrightness();
+							break;
+						case EHotKeyCycleFocusScreen:
+							CWsTop::SetCurrentFocusScreen((CWsTop::CurrentFocusScreen()->ScreenNumber()+1)%CWsTop::NumberOfScreens());
+							break;
+						}
+					return;
+					}
+				hotKey=hotKey->iNext;
+				}
+			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)
+		{
+		if (longCapture || (aCheckRepeat && !aRepeatFocus && aKey.iModifiers&EModifierAutorepeatable))
+			{
+			if (CKeyboardRepeat::StartRepeat(aKey,aScanCode,focusWin,longCapture))
+				return;
+			}
+		event.SetType(EEventKey);
+		event.SetHandle(focusWin->ClientHandle());
+		if (aRepeats!=0)
+			{
+			CEventQueue* queue=focusWin->EventQueue();
+			queue->Wait();
+			const TWsEvent* prev=queue->PeekLastEvent();
+			if (prev!=NULL && prev->Type()==EEventKey && prev->Key()->iRepeats>0)
+				{
+				event= *prev;
+				event.Key()->iRepeats+=aRepeats;
+				queue->UpdateLastEvent(event);
+				queue->Signal();
+				if (CClick::IsHandler())
+					CClick::KeyEvent(EEventKeyRepeat,*event.Key());
+				return;
+				}
+			queue->Signal();
+			event.Key()->iRepeats=aRepeats;
+			if (CClick::IsHandler())
+				CClick::KeyEvent(EEventKeyRepeat,keyEvent);
+			}
+		QueueKeyEvent(focusWin, event, EEventPriorityLow);
+		}
+	}
+
+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;
+#if defined(__WINS__)
+	if (focusWin && !focusWin->WsOwner()->RemoveKeyCode())
+		event.Key()->iScanCode=aRawEvent.ScanCode();
+	else
+#endif
+	event.Key()->iScanCode=aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE;
+	event.Key()->iModifiers=iModifierState;
+	event.Key()->iRepeats=0;
+	if (CClick::IsHandler())
+		CClick::KeyEvent(type,*event.Key());
+	if (focusWin!=NULL)
+		{
+		event.SetType(type);
+		event.SetHandle(focusWin->ClientHandle());
+		QueueKeyEvent(focusWin, event, EEventPriorityHigh);
+		}
+	}
+
+LOCAL_D void GetPointerEvent(TPointerEvent::TType& aType, const TRawEvent &aRawEvent, TBool& aHandled)
+	{
+	aHandled=ETrue;
+	switch(aRawEvent.Type())
+		{
+	case TRawEvent::EButton1Down:
+		aType=TPointerEvent::EButton1Down;
+		break;
+	case TRawEvent::EButton1Up:
+		aType=TPointerEvent::EButton1Up;
+		break;
+	case TRawEvent::EButton2Down:
+		aType=TPointerEvent::EButton2Down;
+		break;
+	case TRawEvent::EButton2Up:
+		aType=TPointerEvent::EButton2Up;
+		break;
+	case TRawEvent::EButton3Down:
+		aType=TPointerEvent::EButton3Down;
+		break;
+	case TRawEvent::EButton3Up:
+		aType=TPointerEvent::EButton3Up;
+		break;
+	case TRawEvent::EPointerMove:
+		aType=TPointerEvent::EMove;
+		break;
+	case TRawEvent::EPointerSwitchOn:
+		aType=TPointerEvent::ESwitchOn;
+		break;
+	case TRawEvent::EPointer3DOutOfRange:
+		aType=TPointerEvent::EOutOfRange;
+		break;
+	default:
+		aHandled=EFalse;
+		}
+	}
+
+TBool TWindowServerEvent::MousePress(const TRawEvent &aRawEvent, const CWsWindowGroup *aGroupWin)
+	//
+	//Return EFalse if known not to be a Mouse Event
+	//
+	{
+	TBool handled=ETrue;
+	TPointerEvent::TType type;
+	GetPointerEvent(type, aRawEvent, handled);
+	if (handled)
+		{
+		TPoint3D point3D(0,0,0);
+		if (type != TPointerEvent::EOutOfRange)
+			{
+			point3D = aRawEvent.Pos3D();
+			}
+		TWsEvent event;
+		TAdvancedPointerEventHelper::InitAdvancedPointerEvent(event, type,iKeyTranslator->GetModifierState(),point3D,aRawEvent.PointerNumber());
+		TWsPointer::ProcessWsEvent(event, aGroupWin, ETrue);
+		}
+	return handled;
+	}
+
+LOCAL_D void SendEventToKeyClick(const TRawEvent& aRawEvent)
+	{
+	switch(aRawEvent.Type())
+		{
+		case TRawEvent::EKeyDown:
+		case TRawEvent::EKeyUp:
+			{
+			TKeyEvent keyEvent;
+			keyEvent.iCode=0;
+			keyEvent.iScanCode=aRawEvent.ScanCode();
+			keyEvent.iModifiers=0;
+			keyEvent.iRepeats=0;
+			CClick::KeyEvent(EEventKey,keyEvent);
+			}
+			break;
+		case TRawEvent::EButton1Down:
+		case TRawEvent::EButton1Up:
+		case TRawEvent::EButton2Down:
+		case TRawEvent::EButton2Up:
+		case TRawEvent::EButton3Down:
+		case TRawEvent::EButton3Up:
+		case TRawEvent::EPointerMove:
+		case TRawEvent::EPointerSwitchOn:
+			{
+			TBool handled=ETrue;
+			TPointerEvent::TType type;
+			GetPointerEvent(type, aRawEvent, handled);
+			if (handled)
+				{
+				TWsEvent event;
+				TAdvancedPointerEventHelper::InitAdvancedPointerEvent(event, type, 0, aRawEvent.Pos3D(), TPoint(), aRawEvent.PointerNumber());
+				TAdvancedPointerEvent& pointerEvent = *event.Pointer();
+				CClick::PointerEvent(pointerEvent.iPosition,pointerEvent);
+				}
+			}
+			break;
+		default:
+			break;
+		}
+	}
+
+void TWindowServerEvent::ProcessRawEvent(const TRawEvent& aRawEvent)
+//
+// Event has completed.
+//
+	{
+	TRawEvent::TType eventType = aRawEvent.Type();
+	TBool isPointerEvent = TWsPointer::IsPointerEventType(eventType);
+	if (isPointerEvent)
+		{
+		TWsPointer::UpdatePrimaryPointer(aRawEvent);
+		}
+	TInt count=iEventHandlers.Count();
+	TInt ii;
+	TBool eventHandled = EFalse;
+	iEventHandlerCount++;
+	for(ii=0;ii<count;++ii)
+		{
+		TRawEventHandler &handler = iEventHandlers[ii];
+		if (handler.iEventHandler != NULL &&
+			(!isPointerEvent ||
+			 handler.iAdvancedPointersEnabled ||
+			 aRawEvent.PointerNumber() == TWsPointer::PrimaryPointer()) &&
+			handler.iEventHandler->OfferRawEvent(aRawEvent))
+			{
+			if (CClick::IsHandler())
+				{
+				SendEventToKeyClick(aRawEvent);
+				}
+			eventHandled = ETrue;
+			break;
+			}
+		}
+	if (--iEventHandlerCount == 0)
+		{
+		if (ERemovedEventHandlerWhileProcessingRawEvents & iBinaryFlags) // Handler was deleted while previous loop
+			{ 
+			iBinaryFlags &= ~ERemovedEventHandlerWhileProcessingRawEvents;
+			for(ii=count-1;ii>=0;--ii)
+				{
+				if (iEventHandlers[ii].iEventHandler==NULL) iEventHandlers.Remove(ii);
+				}
+			}
+		}
+	if (eventHandled)
+		{
+		if (isPointerEvent)
+			{
+			TWsPointer::RollbackPrimaryPointer();
+			}
+		return;
+		}
+	switch(eventType)
+		{
+		case TRawEvent::ERedraw:
+			CWsTop::RedrawScreens();
+			break;
+		case TRawEvent::ESwitchOn:
+		case TRawEvent::ECaseOpen:
+			{
+			TInt event=EEventCaseOpened;
+			CKeyboardRepeat::CancelRepeat(NULL);
+			CWsPassword::SwitchOn();
+			if (eventType==TRawEvent::ESwitchOn)
+				{
+				UserSvr::WsSwitchOnScreen();
+				HAL::Set(HALData::EDisplayState,1);
+				event=EEventSwitchOn;
+				}
+			ProcessEventQueue(iSwitchOnQueue, SendSwitchOnEvent, event, 0);
+			break;
+			}
+		case TRawEvent::ESwitchOff:
+		case TRawEvent::ECaseClose:
+			{
+			TBool switchOff=(eventType==TRawEvent::ESwitchOff);
+			CWsTop::HandleSwitchOff(switchOff? EEventSwitchOff:EEventCaseClosed,switchOff);
+			break;
+			}
+#ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP			
+		case TRawEvent::ERestartSystem:
+			{ /* restart event being handled */
+			CWsTop::HandleSwitchOff(EEventRestartSystem,ETrue);
+			break;
+			}
+#endif			
+		case TRawEvent::EInactive:
+#ifndef __WINS__
+			CWsTop::WindowServer()->AnimationScheduler()->OnInactive();
+#endif
+			CKeyboardRepeat::CancelRepeat(NULL);
+			break;
+		case TRawEvent::EActive:
+#ifndef __WINS__
+			CWsTop::WindowServer()->AnimationScheduler()->OnActive();
+#endif
+			break;
+		case TRawEvent::EKeyDown:
+			{
+			_LIT(KWSERVDebugLogKeyDownArrival,"Key down arrives %d");
+			if(CDebugBar* dbg = CWsTop::Screen()->DebugBar())
+				dbg->OnKeyEvent();
+			if (wsDebugLog)
+				wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,KWSERVDebugLogKeyDownArrival,aRawEvent.ScanCode());
+			CKeyboardRepeat::KeyDown();
+			TKeyData keyData;
+			TBool translated=iKeyTranslator->TranslateKey(aRawEvent.ScanCode(), EFalse,*iCaptureKeys,keyData);
+			ProcessModifierChanges();
+			QueueKeyUpDown(aRawEvent);
+			if (translated)
+				QueueKeyPress(keyData,aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE,NULL,ETrue,0);
+			}
+			break;
+		case TRawEvent::EKeyUp:
+			{
+			_LIT(KWSERVDebugLogKeyUpArrival,"Key up arrives %d");
+			if(CDebugBar* dbg = CWsTop::Screen()->DebugBar())
+				dbg->OnKeyEvent();
+			if (wsDebugLog)
+				wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything,KWSERVDebugLogKeyUpArrival,aRawEvent.ScanCode());
+			TKeyData keyData;
+			CKeyboardRepeat::KeyUp(aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE);
+			TBool translated=iKeyTranslator->TranslateKey(aRawEvent.ScanCode(), ETrue,*iCaptureKeys,keyData);
+			ProcessModifierChanges();
+			QueueKeyUpDown(aRawEvent);
+			if (translated)
+				{
+				CKeyboardRepeat::CancelRepeat(NULL);
+				QueueKeyPress(keyData,aRawEvent.ScanCode() __REMOVE_WINS_CHARCODE,NULL,EFalse,0);
+				}
+			}
+			break;
+		case TRawEvent::EButton1Down:
+		case TRawEvent::EButton2Down:
+		case TRawEvent::EButton3Down:
+		case TRawEvent::EPointerSwitchOn:
+#ifndef __WINS__
+			CWsTop::WindowServer()->AnimationScheduler()->OnActive();
+#endif
+			// fall through
+		case TRawEvent::EButton1Up:
+		case TRawEvent::EButton2Up:
+		case TRawEvent::EButton3Up:
+		case TRawEvent::EPointerMove:
+		case TRawEvent::EPointer3DOutOfRange:
+			#if defined(_DEBUG)
+				WS_ASSERT_DEBUG(MousePress(aRawEvent,NULL), EWsPanicEventType);
+			#else
+				MousePress(aRawEvent,NULL);
+			#endif
+			break;
+		case TRawEvent::EUpdateModifiers:
+			iKeyTranslator->UpdateModifiers(aRawEvent.Modifiers());
+			break;
+		case TRawEvent::EKeyRepeat:
+ 			{
+ 			_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());
+ 			}
+ 			break;
+		default:
+			break;
+		}
+	}
+
+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);
+	}
+
+void TWindowServerEvent::AddCaptureKeyL(const TCaptureKey &aCaptureKey)
+	{
+	iCaptureKeys->AddCaptureKeyL(aCaptureKey,aCaptureKey.iKeyCodePattern.iFiller);
+	}
+
+void TWindowServerEvent::SetCaptureKey(TUint32 aHandle, const TCaptureKey &aCaptureKey)
+	{
+	iCaptureKeys->SetCaptureKey(aHandle, aCaptureKey,aCaptureKey.iKeyCodePattern.iFiller);
+	}
+
+void TWindowServerEvent::CancelCaptureKey(TUint32 aHandle)
+	{
+	iCaptureKeys->CancelCaptureKey(aHandle);
+	}
+
+TInt TWindowServerEvent::GetModifierState()
+	{
+	return(iKeyTranslator->GetModifierState());
+	}
+
+void TWindowServerEvent::SetModifierState(TEventModifier aModifier,TModifierState aState)
+	{
+	iKeyTranslator->SetModifierState(aModifier,aState);
+	}
+
+TInt TWindowServerEvent::AddNotificationHandler(CAnim* aAnim, TUint32 aNotifications)
+	{
+	SNotificationHandler notif;
+	notif.iAnim = aAnim;
+	notif.iNotifications = aNotifications;
+
+	// update the entry if the anim is already in the array
+	TInt count=iNotificationHandlers->Count();
+	TInt ii;
+	for(ii=0;ii<count;++ii)
+		{
+		if ((*iNotificationHandlers)[ii].iAnim==aAnim)
+			{
+			(*iNotificationHandlers)[ii]=notif;
+			return KErrNone;
+			}
+		}
+	
+	// otherwise add it to the array
+	TRAPD(err,iNotificationHandlers->AppendL(notif));
+	return err;
+	}
+
+void TWindowServerEvent::RemoveNotificationHandler(CAnim* aAnim)
+	{
+	TInt count=iNotificationHandlers->Count();
+	TInt ii;
+	for(ii=0;ii<count;++ii)
+		{
+		if ((*iNotificationHandlers)[ii].iAnim==aAnim)
+			{
+			iNotificationHandlers->Delete(ii);
+			return;
+			}
+		}
+	}
+
+void TWindowServerEvent::PublishNotification(const TWsEvent& aWsEvent)
+	{
+	TInt count=iNotificationHandlers->Count();
+	TInt ii;
+	for(ii=0;ii<count;++ii)
+		{
+		SNotificationHandler notif = (*iNotificationHandlers)[ii];
+		switch (aWsEvent.Type())
+			{
+		case EEventDirectScreenAccessBegin:
+		case EEventDirectScreenAccessEnd:
+			if (notif.iNotifications & EDirectScreenAccess)
+				{
+				notif.iAnim->HandleNotification(aWsEvent);
+				}
+			break;
+		case EEventHeartbeatTimerStateChange:
+			if (notif.iNotifications & EHeartbeatTimer)
+				{
+				notif.iAnim->HandleNotification(aWsEvent);
+				}
+			break;
+		case EEventScreenDeviceChanged:
+			if (notif.iNotifications & EScreenDeviceChange)
+				{
+				notif.iAnim->HandleNotification(aWsEvent);
+				}
+			break;
+		default:
+			break;
+			}
+		}
+
+	}
+
+TBool TWindowServerEvent::DrawerCompareFunc(const TDrawerHandler& lhs, const TDrawerHandler& rhs)
+	{
+	return lhs.iDrawer == rhs.iDrawer;	
+	}
+
+TInt TWindowServerEvent::RegisterDrawerHandler(CWsGraphicDrawer* aDrawer, TUint32 aEvents)
+	{
+	TInt idx = iDrawerHandlers->Find(TDrawerHandler(aDrawer, aEvents),
+		TIdentityRelation<TDrawerHandler>(TWindowServerEvent::DrawerCompareFunc));
+	if (idx != KErrNotFound)
+		{
+		// replace event mask for this drawer
+		(*iDrawerHandlers)[idx].iEvents = aEvents;
+		idx = KErrNone;
+		}
+	else
+		idx = iDrawerHandlers->Append(TDrawerHandler(aDrawer,aEvents));
+	
+	return idx;
+	}
+
+TInt TWindowServerEvent::UnregisterDrawerHandler(CWsGraphicDrawer* aDrawer)
+	{
+	TInt idx = iDrawerHandlers->Find(TDrawerHandler(aDrawer,0),
+		TIdentityRelation<TDrawerHandler>(TWindowServerEvent::DrawerCompareFunc));
+	if (idx == KErrNotFound)
+		return idx;
+	(*iDrawerHandlers)[idx].iDrawer = NULL;		//NotifyDrawer() will clean up the array
+	return KErrNone;
+	}
+
+TInt TWindowServerEvent::RegisterWsEventHandler(MWsEventHandler * aHandler, TUint32 aEvents)
+	{
+	TWsEventHandler handler(aHandler, aEvents);
+	TInt idx = iWsEventHandlers.Find(handler, TIdentityRelation<TWsEventHandler>(TWsEventHandler::CompareHandler));
+	if (idx < 0)
+		{
+		TInt err = iWsEventHandlers.Append(handler);
+		return err;
+		}
+	else
+		{
+		iWsEventHandlers[idx].iEvents = aEvents;
+		return KErrNone;
+		}
+	}
+	
+TInt TWindowServerEvent::UnregisterWsEventHandler(MWsEventHandler * aHandler)
+	{
+	TWsEventHandler handler(aHandler, 0);
+	TInt idx = iWsEventHandlers.Find(handler, TIdentityRelation<TWsEventHandler>(TWsEventHandler::CompareHandler));
+	if (idx < 0)
+		return idx;
+	iWsEventHandlers[idx].iEvents = NULL;	//NotifyDrawer() will clean up the array
+	return KErrNone;
+	}
+
+
+void TWindowServerEvent::NotifyDrawer(const TWservCrEvent& aEvent)
+	{
+	TInt drawerCount = iDrawerHandlers->Count();
+	for (TInt idx = 0; idx < drawerCount; idx++)
+		{
+		TDrawerHandler hd = (*iDrawerHandlers)[idx]; 
+		if (!hd.iDrawer) 
+			{                					//If the handler has been removed 
+			iDrawerHandlers->Remove(idx);       //Remove from the array 
+			drawerCount -= 1;   				//Update the counters 
+			idx -= 1; 
+			} 
+		else 
+			{ 
+			if (hd.iEvents & aEvent.Type()) 
+				{ 
+			    hd.iDrawer->HandleEvent(aEvent); 
+			    } 
+			} 
+		}
+	
+	TInt eventHandlerCount = iWsEventHandlers.Count();
+	for (TInt idx = 0; idx < eventHandlerCount; ++idx)
+		{
+		TWsEventHandler* eh = &iWsEventHandlers[idx];
+		if (!eh->iEvents)
+			{								//If the handler has been removed
+			iWsEventHandlers.Remove(idx);	//Remove from the array
+			eventHandlerCount -= 1;			//Update the counters
+			idx -= 1;
+			}
+		else
+			{
+			if (eh->iEvents & aEvent.Type())
+				{
+				eh->iHandler->DoHandleEvent(aEvent);
+				}
+			}
+		}
+	}
+
+void TWindowServerEvent::NotifyScreenDrawingEvent(const TRegion* aRegion)
+	{
+	if (aRegion && !aRegion->IsEmpty())
+		{
+		TWservCrEvent event(TWservCrEvent::EScreenDrawing,0,const_cast<TRegion*>(aRegion));
+		NotifyDrawer(event);
+		}
+	}
+
+void TWindowServerEvent::NotifyScreenDrawingEvent(const TRect& aRect)
+	{
+	TRegionFix<1> reg(aRect);
+	TWservCrEvent event(TWservCrEvent::EScreenDrawing,0,&reg);
+	NotifyDrawer(event);
+	}
+
+//
+// CRawEventReceiver //
+//
+
+CRawEventReceiver::CRawEventReceiver(TInt aPriority) : CActive(aPriority)
+//
+// Constructor
+//
+	{
+	__DECLARE_NAME(_S("CRawEventReceiver"));
+	}
+
+CRawEventReceiver::~CRawEventReceiver()
+	{
+	CActive::Cancel();
+	}
+
+void CRawEventReceiver::ConstructL()
+	{
+	CActiveScheduler::Add(this);
+	UserSvr::CaptureEventHook();
+	Request();
+	}
+
+void CRawEventReceiver::Request()
+//
+// Issue a request for the next event.
+//
+	{
+	UserSvr::RequestEvent(iEventBuf,iStatus);
+	SetActive();
+	}
+
+void CRawEventReceiver::DoCancel()
+//
+// Cancel a pending event.
+//
+	{
+	UserSvr::RequestEventCancel();
+	}
+
+void CRawEventReceiver::RunL()
+	{
+//__PROFILE_START(11);
+	if (TWsPointer::PreProcessDriverEvent(iEventBuf.Event()
+#if defined(__WINS__)
+													,ETrue
+#endif
+														  ))
+		TWindowServerEvent::ProcessRawEvent(iEventBuf.Event());
+	Request();
+//__PROFILE_END(11);
+	}
+
+//
+// TEventRequestQueue //
+//
+
+TEventRequestQueue::TEventRequestQueue() : iQueue(_FOFF(TEventRequestItem,iQue))
+	{}
+
+inline TSglQue<TEventRequestItem> &TEventRequestQueue::Queue()
+	{return(iQueue);}
+
+TEventRequestItem *TEventRequestQueue::FindInEventRequestQueueList(const CWsWindowBase &aWindow)
+//
+// Return a pointer to the link in the queue for the window, or NULL if not in the queue
+//
+	{
+	TSglQueIter<TEventRequestItem> iter(iQueue);
+	TEventRequestItem *qPtr;
+	while((qPtr=iter++)!=NULL)
+		if (qPtr->iWindow==&aWindow)
+			break;
+	return(qPtr);
+	}
+
+void TEventRequestQueue::AddToEventRequestListL(const CWsWindowBase &aWindow, TInt aParam, TEventControl aCircumstances)
+//
+// Add a link to the on event list
+//
+	{
+	TEventRequestItem *item=FindInEventRequestQueueList(aWindow);
+	if (!item)
+		{
+		item=new(ELeave) TEventRequestItem;
+		item->iWindow= &aWindow;
+		item->iParam=aParam;
+		item->iCircumstances=aCircumstances;
+		iQueue.AddFirst(*item);
+		}
+	item->iCircumstances=aCircumstances;
+	item->iParam=aParam;	// Just update the parameter if already exists
+	}
+
+void TEventRequestQueue::RemoveFromEventRequestListL(const CWsWindowBase &aWindow)
+//
+// Remove a link from the on event list
+//
+	{
+	TEventRequestItem *qPtr=FindInEventRequestQueueList(aWindow);
+	if (qPtr)
+		{
+		iQueue.Remove(*qPtr);
+		delete qPtr;
+		}
+	}
+
+//
+// Keyboard auto repeat class //
+//
+
+CKeyboardRepeat::CKeyboardRepeat() : CTimer(EKeyRepeatPriority)
+	{}
+
+void CKeyboardRepeat::NewL()
+	{
+	iThis=new(ELeave) CKeyboardRepeat();
+	iThis->ConstructL();
+	CActiveScheduler::Add(iThis);
+	_LIT(KWSERVIniFileVarRepeatRollover,"REPEATROLLOVER");
+	WsIniFile->FindVar(KWSERVIniFileVarRepeatRollover,iRepeatRollover);
+	}
+
+void CKeyboardRepeat::Destroy()
+	{
+	delete iThis;
+	}
+
+void CKeyboardRepeat::GetRepeatTime(TTimeIntervalMicroSeconds32 &aInitialTime, TTimeIntervalMicroSeconds32 &aTime)
+	{
+	aInitialTime=iInitialTime;
+	aTime=iTime;
+	}
+
+void CKeyboardRepeat::SetRepeatTime(const TTimeIntervalMicroSeconds32 &aInitialTime, const TTimeIntervalMicroSeconds32 &aTime)
+	{
+	iInitialTime=aInitialTime;
+	iTime=aTime;
+	}
+
+void CKeyboardRepeat::RunL()
+	{
+	User::ResetInactivityTime();
+	//WS_ASSERT_DEBUG(iRepeating!=ERepeatNone, EWsPanicTemp);
+	TBool timer=ETrue;
+	if (iRepeating>=ERepeatLong)
+		{
+		// Defensive programming - iLongCapture should never be NULL if iRepeating >= ERepeatLong
+		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;
+			iRepeating=ERepeatLongRepeated;
+			}
+		else
+			{
+			// Defensive programming - iLongCapture should never be NULL if iRepeating >= ERepeatLong
+			// Stop key repeat if this incorrect condition occurs
+			timer=EFalse; 
+			}		
+		}
+	if (timer)
+		After(iTime);
+	else
+		iRepeating=ERepeatNone;
+	TWindowServerEvent::QueueKeyPress(iCurrentRepeat.iKey,iCurrentRepeat.iScanCode,iFocus,EFalse,1);
+	}
+
+TBool CKeyboardRepeat::StartRepeat(const TKeyData &aKey, TInt aScanCode, CWsWindowGroup *aRepeatFocus, CWsCaptureLongKey* aLongCapture)
+	{
+	TTimeIntervalMicroSeconds32 time;
+	TBool ret=EFalse;
+	iCurrentRepeat.iScanCode=aScanCode;
+	iCurrentRepeat.iKey=aKey;
+
+	if (aLongCapture)
+		{
+		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();
+		}
+	else
+		{
+		iFocus=aRepeatFocus;
+		iRepeating=ERepeatNormal;
+		time=iInitialTime;
+		}
+	iThis->After(time);
+	return ret;
+	}
+
+void CKeyboardRepeat::doCancelRepeat()
+	{
+	iRepeating=ERepeatNone;
+	iThis->Cancel();
+	}
+
+void CKeyboardRepeat::CancelRepeat(CWsWindowGroup *aRepeatFocus)
+	{
+	if (aRepeatFocus==NULL || aRepeatFocus==iFocus)
+		{
+		if (iRepeating)
+			doCancelRepeat();
+		iAlternateRepeatExists=EFalse;
+		}
+	else if (iRepeating >= ERepeatLong)
+		{
+		// Defensive programming - iLongCapture should never be NULL if iRepeating >= ERepeatLong
+		if (iLongCapture && iLongCapture->iWindowGroup == aRepeatFocus)
+			{
+			doCancelRepeat();
+			iAlternateRepeatExists=EFalse;
+			}
+		}
+	}
+
+void CKeyboardRepeat::CancelRepeat(CWsWindowGroup *aRepeatFocus,TUint aScanCode,TBool aLongCaptureFlag,TUint aModifiers)
+	{
+	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;
+					}
+				}
+		}
+	else
+		{
+		// normal capture key is cancelled
+		if (aRepeatFocus==iFocus)
+			{
+			if (iRepeating>=ERepeatNormal && iCurrentRepeat.iScanCode==aScanCode)
+				{
+				doCancelRepeat();
+				}
+			iAlternateRepeatExists=EFalse;
+			}
+		}
+	}
+	
+void CKeyboardRepeat::KeyDown()
+	{
+	if (iRepeating!=ERepeatNone)
+		{
+		if (iRepeating==ERepeatNormal && iRepeatRollover>0) // 1 Allow key repeat rollover
+			{
+			iAlternateRepeat=iCurrentRepeat;
+			iAlternateRepeatExists=ETrue;
+			}
+		doCancelRepeat();
+		}
+	}
+
+void CKeyboardRepeat::KeyUp(TInt aScanCode)
+	{
+	if (iAlternateRepeatExists && iAlternateRepeat.iScanCode==aScanCode)
+		iAlternateRepeatExists=EFalse;
+	if (iRepeating!=ERepeatNone && iCurrentRepeat.iScanCode==aScanCode)
+		{
+		if (iRepeating==ERepeatLong)
+			{
+			// Defensive programming - iLongCapture should never be NULL if iRepeating >= ERepeatLong			
+			if (iLongCapture && !(iLongCapture->iData.flags&ELongCaptureShortEventImmediately))
+				{
+				TWindowServerEvent::QueueKeyPress(iCurrentRepeat.iKey,iCurrentRepeat.iScanCode,NULL,EFalse,0);	
+				}
+			}			
+		if (iAlternateRepeatExists)
+			{
+			iAlternateRepeatExists=EFalse;
+			iCurrentRepeat=iAlternateRepeat;
+			iRepeating=ERepeatNormal;
+			}
+		else
+			doCancelRepeat();
+		}
+	}
+
+//
+// CWsHotKey //
+//
+
+CWsHotKey::CWsHotKey(TInt aHotKeyType, TBool aIsDefault) : 
+	iHotKeyType(aHotKeyType),
+	iIsDefault(aIsDefault)
+	{
+	}
+
+CWsHotKey::~CWsHotKey()
+	{
+	delete iCaptureKey;
+	}
+
+void CWsHotKey::ConstructLD(const TWsWinCmdCaptureKey &aCaptureKey)
+	{
+	CleanupStack::PushL(this);
+	iCaptureKey=new(ELeave) CWsCaptureKey(NULL);
+	iCaptureKey->ConstructL(aCaptureKey);
+	CleanupStack::Pop();
+	}
+
+void CWsHotKey::SetL(const TWsWinCmdCaptureKey &aCaptureKey)
+	{
+	iCaptureKey->SetL(aCaptureKey);
+	}
+
+//
+//CEventQueueRetry//
+//
+CEventQueueRetry* CEventQueueRetry::NewL()
+	{
+	CEventQueueRetry* self = new (ELeave) CEventQueueRetry;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+      
+void CEventQueueRetry::ConstructL()
+	{
+	User::LeaveIfError(iTimer.CreateLocal());
+	CActiveScheduler::Add(this);
+	}
+ 
+CEventQueueRetry::CEventQueueRetry() : CActive(EPriorityStandard), iRetrySpinner(1)
+	{
+	
+	}
+
+CEventQueueRetry::~CEventQueueRetry()
+	{
+	Cancel();
+	iTimer.Close();
+	iClientArray.Close();
+	}
+
+void CEventQueueRetry::DoCancel()
+	{
+	iTimer.Cancel();
+	iRetrySpinner = 0;
+	iClientArray.Reset();
+	}
+
+void CEventQueueRetry::RunL()
+	{
+	//some clients may be no longer interested in listening
+	//so we need to refresh the client list each round of retry
+	iClientArray.Reset();
+	TInt err = iOwner->GetNotificationClients(iClientArray);
+	if(err != KErrNone)
+		{
+		iClientArray.Reset(); //so the retry won't kick off
+		}
+	if(iClientArray.Count() > 0)
+		{
+		TBool eventOnAllQueues = ETrue;
+		for(TInt i = 0; i < iClientArray.Count(); i++)
+			{
+			if(iClientArray[i]->RetryEvent(EEventDisplayChanged))
+				{
+				if(TWindowServerEvent::SendDisplayChangedEvents(iClientArray[i], iOwner->ScreenNumber(),
+						iOwner->ConfigSpinner(), iOwner->DisplaySpinner()))
+					{
+					iClientArray[i]->RemoveRetryFlag(EEventDisplayChanged);
+					}
+				else
+					{
+					eventOnAllQueues = EFalse;
+					}
+				}
+			}
+		
+		if(!eventOnAllQueues)
+			{//another retry needed, but with increased time interval
+			iRetrySpinner++;
+			Retry(KRetryInitialDelay*iRetrySpinner);
+			}
+		}
+	
+	}
+
+void CEventQueueRetry::Retry(TInt aDelay)
+	{
+	//the retry might be infinite, with an increasing interval, as delivery of the event is garuanteed
+	//if aDelay is greater than max TInt, it will be negative number so we reset it to KRetryInitialDelay
+	if(aDelay < 0)
+		{
+		aDelay = KRetryInitialDelay;
+		}
+	iTimer.After(iStatus, aDelay);
+	SetActive();
+	}
+
+void CEventQueueRetry::Init(CScreen *aOwner)
+	{
+	iOwner = aOwner;
+	iRetrySpinner = 0;
+	
+	}
+
+void CEventQueueRetry::CancelRetry()
+	{
+	Cancel();
+	}