// 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"
#include "Graphics/wsgraphicdrawerinternal.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");
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;
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");
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());
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,®);
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();
}