os/graphics/windowing/windowserver/nga/SERVER/POINTER.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Copyright (c) 1995-2010 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
// Pointer functions
sl@0
    15
// 
sl@0
    16
//
sl@0
    17
sl@0
    18
#include <e32std.h>
sl@0
    19
#include <e32hal.h>
sl@0
    20
#include "W32CLICK.H"
sl@0
    21
#include "pointer.h"
sl@0
    22
#include "rootwin.h"
sl@0
    23
#include "windowgroup.h"
sl@0
    24
#include "KEYCLICK.H"
sl@0
    25
#include "ScrDev.H"
sl@0
    26
#include "EVENT.H"
sl@0
    27
#include "panics.h"
sl@0
    28
#include "wstop.h"
sl@0
    29
#include "inifile.h"
sl@0
    30
#include <hal.h>
sl@0
    31
#include "advancedpointereventhelper.h"
sl@0
    32
#include "graphics/pointereventdata.h"
sl@0
    33
#include "debughelper.h"
sl@0
    34
sl@0
    35
TTimeIntervalMicroSeconds32 TWsPointer::iDoubleClickMaxInterval;
sl@0
    36
TInt 			   TWsPointer::iDoubleClickMaxDistance;
sl@0
    37
CWsPointerCursor*  TWsPointer::iCursorSprite;
sl@0
    38
TPointerCursorMode TWsPointer::iPointerCursorMode=EPointerCursorNormal;
sl@0
    39
TXYInputType       TWsPointer::iXyInputType;
sl@0
    40
TBool 			   TWsPointer::iTimerQueued;
sl@0
    41
TBool 			   TWsPointer::iUpdateRequired;
sl@0
    42
CPeriodic* 		   TWsPointer::iPeriodicTimer;
sl@0
    43
CWsRootWindow*     TWsPointer::iRootWindow;
sl@0
    44
TInt			   TWsPointer::iMaxPointers;
sl@0
    45
TBool			   TWsPointer::iIs3DPointer;
sl@0
    46
RArray<TWsPointer> TWsPointer::iPointers;
sl@0
    47
TInt 			   TWsPointer::iPrimaryPointer = TAdvancedPointerEvent::EDefaultPointerNumber;
sl@0
    48
TInt			   TWsPointer::iPreviousPrimaryPointer;
sl@0
    49
TInt			   TWsPointer::iEnterCloseProximityThreshold;
sl@0
    50
TInt			   TWsPointer::iExitCloseProximityThreshold;
sl@0
    51
TInt			   TWsPointer::iEnterHighPressureThreshold;
sl@0
    52
TInt			   TWsPointer::iExitHighPressureThreshold;
sl@0
    53
TBool			   CWsPointerBuffer::iSignalled=EFalse;
sl@0
    54
CWsPointerBuffer*  CWsPointerBuffer::iCurrentBuffer=NULL;
sl@0
    55
CCirBuf<TPoint>*   CWsPointerBuffer::iPointerBuffer=NULL;
sl@0
    56
TSglQue<CWsPointerBuffer> CWsPointerBuffer::iList(_FOFF(CWsPointerBuffer,iQue));
sl@0
    57
TInt                TWsPointer::iYOffset;
sl@0
    58
#if defined(__WINS__)
sl@0
    59
TBool               TWsPointer::iEmulatorRotatePointerCoords;
sl@0
    60
#endif
sl@0
    61
sl@0
    62
static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_SwEvent,ECapabilitySwEvent);
sl@0
    63
sl@0
    64
void TWsPointer::InitStaticsL()
sl@0
    65
	{
sl@0
    66
	//This iYOffset setting is specific for capacitive touch screens, where user's finger is the pointer device.
sl@0
    67
	//This is typically used so that the pointer event location is more inline with where the user perceives their 
sl@0
    68
	//finger to be on the screen (for example, due to refraction and the relatively large touch area of a finger).
sl@0
    69
	iYOffset = 0;
sl@0
    70
    _LIT( KWSERVIniFileVarYShifting, "YSHIFTING");
sl@0
    71
    TBool fetchingSucceeded = WsIniFile->FindVar(KWSERVIniFileVarYShifting, iYOffset);
sl@0
    72
    WS_ASSERT_ALWAYS(iYOffset>=0, EWsPanicInvalidPointerOffset);
sl@0
    73
    if ( !fetchingSucceeded )
sl@0
    74
       {
sl@0
    75
       iYOffset = 0;
sl@0
    76
       }
sl@0
    77
sl@0
    78
#if defined(__WINS__)    
sl@0
    79
	//An emulator may or may not deploy a renderchain or displaydriver that supports rotated drawing.
sl@0
    80
	//On a real device target the coordinate system is always rotated together with wserv's screendevice.
sl@0
    81
	_LIT( KWSERVIniFileVarEmulatorRotPointCoords, "EMULATOR_ROTATE_POINTER_COORDS");
sl@0
    82
	iEmulatorRotatePointerCoords = WsIniFile->FindVar(KWSERVIniFileVarEmulatorRotPointCoords);
sl@0
    83
#endif
sl@0
    84
sl@0
    85
	const CScreen* screen = CWsTop::Screen();
sl@0
    86
	WS_ASSERT_ALWAYS(screen, EWsPanicNoScreen);
sl@0
    87
	iRootWindow = screen->RootWindow();
sl@0
    88
	
sl@0
    89
	TMachineInfoV1Buf machineInfo;
sl@0
    90
	UserHal::MachineInfo(machineInfo);
sl@0
    91
	iXyInputType=machineInfo().iXYInputType;
sl@0
    92
	
sl@0
    93
	// Read EPointerMaxPointers from HAL and check if reported value is consistent
sl@0
    94
	// with iXyInputType.
sl@0
    95
	// Even if HAL reports that device doesn't support any pointer, WSERV
sl@0
    96
	// always has to support at least one pointer for compatibility reasons
sl@0
    97
	// and for keeping state of pointer cursor.
sl@0
    98
	if(HAL::Get(HALData::EPointerMaxPointers,iMaxPointers)!=KErrNone)
sl@0
    99
		{
sl@0
   100
		iMaxPointers = 1;
sl@0
   101
		}
sl@0
   102
	else
sl@0
   103
		{
sl@0
   104
		WS_ASSERT_ALWAYS(iMaxPointers >= 0 && iMaxPointers <= TAdvancedPointerEvent::EMaximumWServNumberOfPointers,
sl@0
   105
						 EWsPanicMaxPointersOutOfRange);
sl@0
   106
		WS_ASSERT_ALWAYS(( XyInput() && iMaxPointers >  0) || (!XyInput() && iMaxPointers == 0),
sl@0
   107
						 EWsPanicMaxPointersInconsistent);
sl@0
   108
		if (iMaxPointers == 0)
sl@0
   109
			{
sl@0
   110
			iMaxPointers = 1;
sl@0
   111
			}
sl@0
   112
		}
sl@0
   113
	
sl@0
   114
	//** Log the number of pointers here i,e iMaxPointers
sl@0
   115
#ifdef LOG_WSERV_EVENTS
sl@0
   116
	RDebug::Printf("_WSEVENT_POINTER: Number of pointers system supports %d", iMaxPointers);
sl@0
   117
#endif
sl@0
   118
	
sl@0
   119
	// Does device support Z coordinate of the pointers?
sl@0
   120
	if(HAL::Get(HALData::EPointer3D,iIs3DPointer)!=KErrNone)
sl@0
   121
		{
sl@0
   122
		iIs3DPointer=EFalse; // No API, then no 3D pointers
sl@0
   123
		}
sl@0
   124
	WS_ASSERT_ALWAYS(!iIs3DPointer || XyInput(), EWsPanicPointer3DInconsistent);
sl@0
   125
	
sl@0
   126
#ifdef LOG_WSERV_EVENTS
sl@0
   127
	RDebug::Printf("_WSEVENT_POINTER: Z coordinate supported %d", iIs3DPointer);
sl@0
   128
#endif	
sl@0
   129
	
sl@0
   130
	// Initialize thresholds for EEnterCloseProximity, EExitCloseProximity,
sl@0
   131
	// EEnterHighPressure and EExitHightPressure events.
sl@0
   132
	if(HAL::Get(HALData::EPointer3DEnterCloseProximityThreshold,
sl@0
   133
			iEnterCloseProximityThreshold) != KErrNone)
sl@0
   134
		{
sl@0
   135
		iEnterCloseProximityThreshold = KMaxTInt;
sl@0
   136
		}
sl@0
   137
	if(HAL::Get(HALData::EPointer3DExitCloseProximityThreshold,
sl@0
   138
			iExitCloseProximityThreshold) != KErrNone)
sl@0
   139
		{
sl@0
   140
		iExitCloseProximityThreshold  = KMinTInt;
sl@0
   141
		}
sl@0
   142
	if(HAL::Get(HALData::EPointer3DEnterHighPressureThreshold,
sl@0
   143
			iEnterHighPressureThreshold)  != KErrNone)
sl@0
   144
		{
sl@0
   145
		iEnterHighPressureThreshold   = KMaxTInt;
sl@0
   146
		}
sl@0
   147
	if(HAL::Get(HALData::EPointer3DExitHighPressureThreshold,
sl@0
   148
			iExitHighPressureThreshold)   != KErrNone)
sl@0
   149
		{
sl@0
   150
		iExitHighPressureThreshold    = KMinTInt;
sl@0
   151
		}
sl@0
   152
	
sl@0
   153
	iPointers = RArray<TWsPointer>(iMaxPointers);
sl@0
   154
	TWsPointer emptyPointer;	
sl@0
   155
	emptyPointer.iRepeatTimer = NULL;
sl@0
   156
	emptyPointer.Clear();
sl@0
   157
	for (TInt ii = 0; ii < iMaxPointers; ii++)
sl@0
   158
		{
sl@0
   159
		emptyPointer.iNumber = ii;
sl@0
   160
		User::LeaveIfError(iPointers.Append(emptyPointer));
sl@0
   161
		RepeatTimer(ii) = CWsPointerTimer::NewL(iPointers[ii]);
sl@0
   162
		}
sl@0
   163
	
sl@0
   164
	iPeriodicTimer=CPeriodic::NewL(EPointerCursorPriority);
sl@0
   165
	}
sl@0
   166
sl@0
   167
void TWsPointer::Clear()
sl@0
   168
	{
sl@0
   169
	iState = EPointerStateOutOfRange;
sl@0
   170
	iPos.iX = 0;
sl@0
   171
	iPos.iY = 0;
sl@0
   172
	iPressureProximity = 0;
sl@0
   173
	iCurrentWindow=MovesAvailable() ? iRootWindow : NULL;
sl@0
   174
	iActualWinPointerIsOver = NULL;
sl@0
   175
	iGrabWindow = NULL;
sl@0
   176
	iLastUnmatchedDown1 = NULL;
sl@0
   177
	iLastUnmatchedDown2 = NULL;
sl@0
   178
	iLastUnmatchedDown3 = NULL;
sl@0
   179
	iLastUnmatchedEnterHighPressure = NULL;
sl@0
   180
	iPrevClickWindow = NULL;
sl@0
   181
	iInCloseProximity = EFalse;
sl@0
   182
	iInHighPressure = EFalse;
sl@0
   183
	CancelPointerRepeatEventRequest();	
sl@0
   184
	}
sl@0
   185
sl@0
   186
/**
sl@0
   187
Turns off pointer cursor, deletes permenently pointer cursor update timer and pointer event repeat timer.
sl@0
   188
*/
sl@0
   189
void TWsPointer::Stop()
sl@0
   190
	{
sl@0
   191
	SetPointerCursorMode(EPointerCursorNone);
sl@0
   192
	UpdatePointerCursor();
sl@0
   193
	delete iPeriodicTimer;
sl@0
   194
	}
sl@0
   195
sl@0
   196
void TWsPointer::DeleteStatics()
sl@0
   197
	{
sl@0
   198
	for (TInt ii = 0; ii < iMaxPointers; ii++)
sl@0
   199
		{
sl@0
   200
		delete RepeatTimer(ii);	
sl@0
   201
		}		
sl@0
   202
	iPointers.Close();
sl@0
   203
	}
sl@0
   204
sl@0
   205
void TWsPointer::SetPointerCursorPos(TPoint aPos)
sl@0
   206
	{
sl@0
   207
	RestrictPos(aPos,EFalse);
sl@0
   208
	iPointers[iPrimaryPointer].iPos=aPos; 
sl@0
   209
	iPointers[iPrimaryPointer].ReLogCurrentWindow();
sl@0
   210
	UpdatePointerCursor();
sl@0
   211
	}
sl@0
   212
sl@0
   213
void TWsPointer::SendEnterExitEvent(TEventCode aType)
sl@0
   214
	{
sl@0
   215
	if (iCurrentWindow
sl@0
   216
		&& (iState != EPointerStateOutOfRange)
sl@0
   217
		&& (iNumber == iPrimaryPointer || iCurrentWindow->AdvancedPointersEnabled())
sl@0
   218
		&& !(iCurrentWindow->PointerFilter()&EPointerFilterEnterExit)
sl@0
   219
		&& !iCurrentWindow->ShutDownInProgress())
sl@0
   220
		{
sl@0
   221
		iCurrentWindow->QueueEvent(aType, iNumber);
sl@0
   222
		}
sl@0
   223
	}
sl@0
   224
sl@0
   225
void TWsPointer::SetCurrentWindow(const CWsWindow* aWin)
sl@0
   226
	{
sl@0
   227
	if (aWin!=iCurrentWindow)
sl@0
   228
		{
sl@0
   229
		SendEnterExitEvent(EEventPointerExit);
sl@0
   230
		iCurrentWindow=aWin;
sl@0
   231
		SendEnterExitEvent(EEventPointerEnter);
sl@0
   232
		}
sl@0
   233
	}
sl@0
   234
sl@0
   235
/**
sl@0
   236
Relogs the current window (sets iCurrentWindow) for this pointer. 
sl@0
   237
Retrieves pointer relative position in current window and pointer position in current 
sl@0
   238
window's parent window. 
sl@0
   239
*/
sl@0
   240
void TWsPointer::ReLogCurrentWindow(TPoint &aPos, TPoint &aParentPos, const CWsWindowGroup* aForceInGroup)
sl@0
   241
	{
sl@0
   242
	if (iRootWindow)
sl@0
   243
		{
sl@0
   244
		SetCurrentWindow(iRootWindow->PointerWindow(iPos,&aPos,&aParentPos,iGrabWindow,
sl@0
   245
				                                    iActualWinPointerIsOver,aForceInGroup));
sl@0
   246
		}
sl@0
   247
	else
sl@0
   248
		{
sl@0
   249
		iCurrentWindow=NULL;
sl@0
   250
		}
sl@0
   251
	}
sl@0
   252
sl@0
   253
/**
sl@0
   254
Relog all pointer's current windows when the window layout has changed.
sl@0
   255
*/
sl@0
   256
void TWsPointer::ReLogPointersCurrentWindows()
sl@0
   257
	{
sl@0
   258
	for (TInt ii = 0; ii < iMaxPointers; ii++)
sl@0
   259
		{
sl@0
   260
		TWsPointer& pointer = iPointers[ii];
sl@0
   261
		pointer.ReLogCurrentWindow();
sl@0
   262
		}
sl@0
   263
	}
sl@0
   264
sl@0
   265
/*
sl@0
   266
Relog this pointer's current pointer window when the window layout has changed.
sl@0
   267
Works similarly to ReLogCurrentWindow(TPoint &aPos, TPoint &aParentPos, const CWsWindowGroup* aForceInGroup),
sl@0
   268
but doesn't set relative positions.
sl@0
   269
*/
sl@0
   270
void TWsPointer::ReLogCurrentWindow()
sl@0
   271
	{
sl@0
   272
	if (iCurrentWindow)
sl@0
   273
		{
sl@0
   274
		SetCurrentWindow(iRootWindow->PointerWindow(iPos,NULL,NULL,iGrabWindow,iActualWinPointerIsOver,NULL));
sl@0
   275
		}
sl@0
   276
	}
sl@0
   277
sl@0
   278
/*
sl@0
   279
Called when a window has changed it's filter state, will trigger a 'Enter' message if the window
sl@0
   280
is the current window
sl@0
   281
*/
sl@0
   282
void TWsPointer::ReLogWindow(const CWsWindow* aWin)
sl@0
   283
	{
sl@0
   284
	for (TInt ii = 0; ii < iMaxPointers; ii++)
sl@0
   285
		{
sl@0
   286
		if (aWin == iPointers[ii].iCurrentWindow)
sl@0
   287
			{
sl@0
   288
			iPointers[ii].SendEnterExitEvent(EEventPointerEnter);
sl@0
   289
			}
sl@0
   290
		}
sl@0
   291
	}
sl@0
   292
sl@0
   293
void TWsPointer::UnmatchedEventPurged(TPointerEvent::TType aPointerType, TUint aHandle)
sl@0
   294
	{
sl@0
   295
	if (aPointerType==TPointerEvent::EButton1Up)
sl@0
   296
		{
sl@0
   297
		if (iGrabWindow && iGrabWindow->ClientHandle()==aHandle)
sl@0
   298
			{
sl@0
   299
			iGrabWindow=NULL;
sl@0
   300
			}
sl@0
   301
		if (iRepeatWindow && iRepeatWindow->ClientHandle()==aHandle)
sl@0
   302
			{
sl@0
   303
			CancelPointerRepeatEventRequest();
sl@0
   304
			}
sl@0
   305
		}
sl@0
   306
	switch(aPointerType)
sl@0
   307
		{
sl@0
   308
		case TPointerEvent::EButton1Up:
sl@0
   309
			iLastUnmatchedDown1=aHandle;
sl@0
   310
			break;
sl@0
   311
		case TPointerEvent::EButton2Up:
sl@0
   312
			iLastUnmatchedDown2=aHandle;
sl@0
   313
			break;
sl@0
   314
		case TPointerEvent::EButton3Up:
sl@0
   315
			iLastUnmatchedDown3=aHandle;
sl@0
   316
			break;
sl@0
   317
		case TPointerEvent::EExitHighPressure:
sl@0
   318
			iLastUnmatchedEnterHighPressure=aHandle;
sl@0
   319
			break;
sl@0
   320
		default:;
sl@0
   321
		}
sl@0
   322
	}
sl@0
   323
sl@0
   324
void TWsPointer::WindowDisconnected(const CWsWindow* deletedWindow)
sl@0
   325
	{
sl@0
   326
	for (TInt pointerNum = 0; pointerNum < iMaxPointers; pointerNum++)
sl@0
   327
		{
sl@0
   328
		TWsPointer& pointer = iPointers[pointerNum];
sl@0
   329
		if (pointer.iRepeatWindow==deletedWindow)
sl@0
   330
			{
sl@0
   331
			pointer.CancelPointerRepeatEventRequest();
sl@0
   332
			}		
sl@0
   333
		if (pointer.iGrabWindow==deletedWindow)
sl@0
   334
			{
sl@0
   335
			pointer.iGrabWindow=NULL;
sl@0
   336
			}
sl@0
   337
		if (pointer.iCurrentWindow==deletedWindow)
sl@0
   338
			{
sl@0
   339
			pointer.ReLogCurrentWindow();
sl@0
   340
			if (pointerNum == iPrimaryPointer)
sl@0
   341
				{
sl@0
   342
				UpdatePointerCursor();
sl@0
   343
				}
sl@0
   344
			}
sl@0
   345
		}
sl@0
   346
	}
sl@0
   347
sl@0
   348
/*
sl@0
   349
Callback function pointer for up event remove event queue walk
sl@0
   350
*/
sl@0
   351
TEventQueueWalkRet RemovePointerUpFunc(TAny* aHandle, TWsEvent* aEvent)
sl@0
   352
	{
sl@0
   353
	if (aEvent->Type()==EEventPointer && aEvent->Pointer()->iType==TPointerEvent::EButton1Up && (*(TUint *)aHandle)==aEvent->Handle())
sl@0
   354
		{
sl@0
   355
		return(EEventQueueWalkDeleteEvent);
sl@0
   356
		}
sl@0
   357
	return(EEventQueueWalkOk);
sl@0
   358
	}
sl@0
   359
sl@0
   360
/*
sl@0
   361
If the specified pointer is down claim grab in aWindow as though the down event had 
sl@0
   362
gone to this window. Also send an up event to the window (if any) that would receive it if the 
sl@0
   363
pointer was released now.
sl@0
   364
If no pointer is specifed do the above for the primary pointer.
sl@0
   365
sl@0
   366
@return	KErrNone if successful,
sl@0
   367
		KErrNotFound if pointernumber out of range,
sl@0
   368
		KErrNotSupported if incorrect pointer grab claimed for window in emulation mode,
sl@0
   369
		KErrPermissionDenied if trying to grab from a different window owner without the required capability.
sl@0
   370
*/
sl@0
   371
TInt TWsPointer::ClaimGrab(const CWsWindow *aWindow,const TWsWinCmdGrabControl& aGrabControl)
sl@0
   372
	{
sl@0
   373
	TInt pointerNumber(aGrabControl.HasPointerNumber() ? aGrabControl.pointerNumber : iPrimaryPointer);
sl@0
   374
	TBool advancedPointersEnabled(aWindow->AdvancedPointersEnabled());
sl@0
   375
	TInt errNo(KErrNone);
sl@0
   376
sl@0
   377
	if(!advancedPointersEnabled	&& aGrabControl.HasPointerNumber() && (TAdvancedPointerEvent::EDefaultPointerNumber!=pointerNumber))
sl@0
   378
		{
sl@0
   379
		// The window is in emulation mode, and cannot get events for anything other than the primary pointer		
sl@0
   380
		errNo=KErrNotSupported;
sl@0
   381
		}
sl@0
   382
	else if(advancedPointersEnabled && ((pointerNumber<0) || (pointerNumber>=iMaxPointers)))
sl@0
   383
		{
sl@0
   384
		// Unknown pointer number
sl@0
   385
		errNo=KErrNotFound;
sl@0
   386
		}
sl@0
   387
	else if(aGrabControl.HasPointerNumber()	&& (aWindow->WsOwner()!=iPointers[pointerNumber].iCurrentWindow->WsOwner())
sl@0
   388
			&& !KSecurityPolicy_SwEvent().CheckPolicy(aWindow->WsOwner()->ClientMessage(), __PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowBase::ClaimPointerGrab")))
sl@0
   389
		{
sl@0
   390
		// Trying to grab from a different window owner requires the relevant permission
sl@0
   391
		//     - Only for the multipointer API, RWindowBase::ClaimPointerGrab(TInt, TBool), which provides a pointer number
sl@0
   392
		//     - Doing so for the legacy non-multipointer API, RWindowBase::ClaimPointerGrab(TBool), would be a compatibility break
sl@0
   393
		errNo=KErrPermissionDenied;
sl@0
   394
		}
sl@0
   395
	else
sl@0
   396
		{
sl@0
   397
		iPointers[pointerNumber].ClaimGrab(aWindow,aGrabControl.CheckFlags(TWsWinCmdGrabControl::ESendUpEvent));		
sl@0
   398
		}	
sl@0
   399
	
sl@0
   400
	return errNo;
sl@0
   401
	}
sl@0
   402
sl@0
   403
/*
sl@0
   404
If this pointer is down claim grab in aWindow as though the down event had 
sl@0
   405
gone to this window. Also send an up event to the window (if any) that would receive it if the 
sl@0
   406
pointer was released now.
sl@0
   407
*/
sl@0
   408
void TWsPointer::ClaimGrab(const CWsWindow* aWindow,TBool aSendUpEvent)
sl@0
   409
	{	
sl@0
   410
	TInt modState=TWindowServerEvent::GetModifierState();
sl@0
   411
	TWsEvent event;
sl@0
   412
	TAdvancedPointerEvent& pointerEvent=*event.Pointer();
sl@0
   413
	TAdvancedPointerEventHelper::InitAdvancedPointerEvent(event, TPointerEvent::EButton1Up,modState,TPoint3D(iPos.iX,iPos.iY,iPressureProximity),iNumber);
sl@0
   414
	if (iState == EPointerStateDown)
sl@0
   415
		{
sl@0
   416
		if (iCurrentWindow!=aWindow)
sl@0
   417
			{
sl@0
   418
			if (aSendUpEvent)
sl@0
   419
				{
sl@0
   420
				ProcessEvent(event,NULL,EFalse);
sl@0
   421
				}
sl@0
   422
			else // If up event already in queue purge it
sl@0
   423
				{
sl@0
   424
				CEventQueue* eventQueue = iCurrentWindow->EventQueue();
sl@0
   425
				if (eventQueue)
sl@0
   426
					{
sl@0
   427
					TUint handle=iCurrentWindow->ClientHandle();
sl@0
   428
					eventQueue->WalkEventQueue(&RemovePointerUpFunc,&handle);
sl@0
   429
					}
sl@0
   430
				}
sl@0
   431
			iState = EPointerStateDown;
sl@0
   432
			if (aWindow->HasPointerGrab())
sl@0
   433
				{
sl@0
   434
				iGrabWindow=aWindow;
sl@0
   435
				}
sl@0
   436
			ReLogCurrentWindow(pointerEvent.iPosition,pointerEvent.iParentPosition,NULL);
sl@0
   437
			pointerEvent.iType=TPointerEvent::EDrag;
sl@0
   438
			ProcessPointerEvent(event);
sl@0
   439
			}
sl@0
   440
		}
sl@0
   441
	else if (iState == EPointerStateUp)
sl@0
   442
		{
sl@0
   443
		const CWsWindow *current=iCurrentWindow;
sl@0
   444
		iCurrentWindow=aWindow;
sl@0
   445
		WS_ASSERT_DEBUG(iGrabWindow==NULL, EWsPanicPointerClaimGrab);
sl@0
   446
		iGrabWindow=aWindow;	// Force the up event to be sent to aWindow
sl@0
   447
		ReLogCurrentWindow(pointerEvent.iPosition,pointerEvent.iParentPosition,NULL);
sl@0
   448
		ProcessPointerEvent(event);
sl@0
   449
		iGrabWindow=NULL;
sl@0
   450
		iCurrentWindow=current;
sl@0
   451
		}
sl@0
   452
	}
sl@0
   453
sl@0
   454
/**
sl@0
   455
@return ETrue if matching event has been purged, so current event should not be delivered,
sl@0
   456
        EFalse otherwise.
sl@0
   457
*/
sl@0
   458
TBool TWsPointer::CheckMatchingEventPurged(TPointerEvent::TType aType)
sl@0
   459
	{
sl@0
   460
	switch(aType)
sl@0
   461
		{
sl@0
   462
		TUint lastUnmatchedDown;
sl@0
   463
		case TPointerEvent::EButton1Up:
sl@0
   464
			lastUnmatchedDown=iLastUnmatchedDown1;
sl@0
   465
			iLastUnmatchedDown1=0;
sl@0
   466
			iLastUnmatchedEnterHighPressure=0;
sl@0
   467
			goto lastUnmatchedDownCheck;
sl@0
   468
		case TPointerEvent::EButton2Up:
sl@0
   469
			lastUnmatchedDown=iLastUnmatchedDown2;
sl@0
   470
			iLastUnmatchedDown2=0;
sl@0
   471
			goto lastUnmatchedDownCheck;
sl@0
   472
		case TPointerEvent::EButton3Up:
sl@0
   473
			lastUnmatchedDown=iLastUnmatchedDown3;
sl@0
   474
			iLastUnmatchedDown3=0;
sl@0
   475
			goto lastUnmatchedDownCheck;
sl@0
   476
		case TPointerEvent::EExitHighPressure:
sl@0
   477
			lastUnmatchedDown=iLastUnmatchedEnterHighPressure;
sl@0
   478
			iLastUnmatchedEnterHighPressure=0;
sl@0
   479
lastUnmatchedDownCheck:
sl@0
   480
		if (lastUnmatchedDown==iCurrentWindow->ClientHandle())
sl@0
   481
			{
sl@0
   482
			return ETrue; // Don't deliver the event as we've already thrown away matching event
sl@0
   483
			}
sl@0
   484
		default:		//Should never get to default
sl@0
   485
			break;
sl@0
   486
		}
sl@0
   487
	return EFalse;
sl@0
   488
	}
sl@0
   489
sl@0
   490
TBool TWsPointer::QueuePointerEvent(const CWsWindow* aWindow, TWsEvent &aEvent)
sl@0
   491
	{
sl@0
   492
	if (aWindow->WsOwner() &&
sl@0
   493
		(aWindow->AdvancedPointersEnabled() || 
sl@0
   494
		TAdvancedPointerEventHelper::PointerNumber(aEvent) == iPrimaryPointer))
sl@0
   495
		{
sl@0
   496
		CEventQueue* queue=aWindow->EventQueue();
sl@0
   497
		aEvent.SetHandle(aWindow->ClientHandle());
sl@0
   498
#ifdef LOG_WSERV_EVENTS
sl@0
   499
		RDebug::Printf("_WSEVENT_POINTER: TWsPointer::QueuePointerEvent with AdvancedPointerEnabled");
sl@0
   500
#endif
sl@0
   501
		if (aEvent.Handle()!=0)
sl@0
   502
			{
sl@0
   503
 			if(!aWindow->AdvancedPointersEnabled())
sl@0
   504
 				{
sl@0
   505
 				// Re-assign from WServ primary pointer number, to EDefaultPointerNumber for Cone and other clients.
sl@0
   506
 				// This should not get confused with any real pointer of the same number due to the TWsEvents' window handle
sl@0
   507
 				// being different.
sl@0
   508
 				TAdvancedPointerEventHelper::SetPointerNumber(aEvent,TAdvancedPointerEvent::EDefaultPointerNumber);
sl@0
   509
 				aEvent.Pointer()->iModifiers&=~EModifierAdvancedPointerEvent;  // Clear the advanced pointer flag
sl@0
   510
 				}
sl@0
   511
			if (queue->UpdateLastPointerEvent(aEvent))
sl@0
   512
				{
sl@0
   513
				return EFalse;
sl@0
   514
				}
sl@0
   515
			TWservEventPriorities priority=EEventPriorityLow;
sl@0
   516
			switch (aEvent.Pointer()->iType)
sl@0
   517
				{
sl@0
   518
				case TPointerEvent::EButton1Up:
sl@0
   519
				case TPointerEvent::EButton2Up:
sl@0
   520
				case TPointerEvent::EButton3Up:
sl@0
   521
				case TPointerEvent::EExitHighPressure:
sl@0
   522
					if (CheckMatchingEventPurged(aEvent.Pointer()->iType))
sl@0
   523
						{
sl@0
   524
						#ifdef LOG_WSERV_EVENTS
sl@0
   525
						RDebug::Printf("_WSEVENT_POINTER: Check matching event has been purged so no addition of event 01");
sl@0
   526
						#endif
sl@0
   527
						return ETrue;
sl@0
   528
						}
sl@0
   529
					if (queue->CheckRoom())
sl@0
   530
						{
sl@0
   531
						if (CheckMatchingEventPurged(aEvent.Pointer()->iType))
sl@0
   532
							{
sl@0
   533
							#ifdef LOG_WSERV_EVENTS
sl@0
   534
							RDebug::Printf("_WSEVENT_POINTER: Check matching event has been purged so no addition of event 02");
sl@0
   535
							#endif
sl@0
   536
							return ETrue;
sl@0
   537
							}
sl@0
   538
						}
sl@0
   539
					/*Fall Through if an event was not purged*/
sl@0
   540
				case TPointerEvent::EButton1Down:
sl@0
   541
				case TPointerEvent::EButton2Down:
sl@0
   542
				case TPointerEvent::EButton3Down:
sl@0
   543
				case TPointerEvent::EEnterHighPressure:
sl@0
   544
				case TPointerEvent::EOutOfRange:
sl@0
   545
					priority=EEventPriorityHigh;
sl@0
   546
					break;
sl@0
   547
				default:;
sl@0
   548
				}
sl@0
   549
#ifdef LOG_WSERV_EVENTS
sl@0
   550
			RDebug::Printf("_WSEVENT_POINTER: TWsPointer::QueuePointerEvent After adding event to clientqueue Event State %d ", iState);
sl@0
   551
#endif
sl@0
   552
			queue->QueueEvent(aEvent,priority);
sl@0
   553
			}
sl@0
   554
		}
sl@0
   555
	return EFalse;
sl@0
   556
	}
sl@0
   557
sl@0
   558
/*
sl@0
   559
Moves the window group which contains this pointer's iCurrentWindow on top.
sl@0
   560
*/
sl@0
   561
void TWsPointer::ProcessForegroundCheck()
sl@0
   562
	{
sl@0
   563
	CWsWindowGroup* group=((CWsTopClientWindow *)iCurrentWindow)->TopClientWindow()->Parent();
sl@0
   564
	if (group->iFlags&CWsWindowGroup::EGroupFlagAutoForeground)
sl@0
   565
		{
sl@0
   566
		group->SetOrdinalPosition(0);
sl@0
   567
		}
sl@0
   568
	}
sl@0
   569
sl@0
   570
/*
sl@0
   571
Pointer Event Processing - stage 3 of 3:
sl@0
   572
- setting event's time
sl@0
   573
- auto foreground check
sl@0
   574
- double clicks detection
sl@0
   575
- pointer repeats
sl@0
   576
- add event to client's queue
sl@0
   577
- drag&drop capturing
sl@0
   578
*/
sl@0
   579
void TWsPointer::ProcessPointerEvent(TWsEvent& aEvent)
sl@0
   580
	{
sl@0
   581
	if (iCurrentWindow && iCurrentWindow!=iRootWindow)
sl@0
   582
		{
sl@0
   583
		aEvent.SetType(EEventPointer);
sl@0
   584
		aEvent.SetTimeNow();
sl@0
   585
		TPointerEvent::TType type=aEvent.Pointer()->iType;
sl@0
   586
		switch(type)
sl@0
   587
			{
sl@0
   588
			//TUint lastUnmatchedDown;
sl@0
   589
			case TPointerEvent::EButton1Down:
sl@0
   590
				ProcessForegroundCheck(); 
sl@0
   591
				/*Fall Through*/
sl@0
   592
			case TPointerEvent::EButton2Down:
sl@0
   593
			case TPointerEvent::EButton3Down:
sl@0
   594
				{
sl@0
   595
				TPoint& pos=aEvent.Pointer()->iPosition;
sl@0
   596
				if (iCurrentWindow==iPrevClickWindow &&
sl@0
   597
					type==iPrevClickEventType &&
sl@0
   598
					(Abs(pos.iX-iPrevClickPos.iX)+Abs(pos.iY-iPrevClickPos.iY))<iDoubleClickMaxDistance &&
sl@0
   599
					aEvent.Time()<(iPrevClickTime+iDoubleClickMaxInterval))
sl@0
   600
					{
sl@0
   601
					aEvent.Pointer()->iModifiers|=EModifierDoubleClick;
sl@0
   602
					iPrevClickWindow=NULL;	// Set to NULL to block a double double click
sl@0
   603
					}
sl@0
   604
				else
sl@0
   605
					{
sl@0
   606
					iPrevClickWindow=iCurrentWindow;
sl@0
   607
					}
sl@0
   608
				iPrevClickEventType=type;
sl@0
   609
				iPrevClickPos=pos;
sl@0
   610
				iPrevClickTime=aEvent.Time();
sl@0
   611
				}
sl@0
   612
				break;
sl@0
   613
			default:
sl@0
   614
				break;
sl@0
   615
			}
sl@0
   616
		if (iRepeatWindow)
sl@0
   617
			{
sl@0
   618
			if (PointerEventRepeatCheck(&aEvent, iCurrentWindow->ClientHandle()))
sl@0
   619
				{
sl@0
   620
				return;
sl@0
   621
				}
sl@0
   622
			CancelPointerRepeatEventRequest();
sl@0
   623
			}
sl@0
   624
		if (QueuePointerEvent(iCurrentWindow, aEvent))
sl@0
   625
			{
sl@0
   626
			return;
sl@0
   627
			}
sl@0
   628
		if (iCurrentWindow->DragDropCapture())
sl@0
   629
			{
sl@0
   630
			aEvent.SetType(EEventDragDrop);
sl@0
   631
			QueuePointerEvent(iActualWinPointerIsOver, aEvent);
sl@0
   632
			}
sl@0
   633
		}
sl@0
   634
	}
sl@0
   635
sl@0
   636
TInt PointerTimerCallBack(TAny *)
sl@0
   637
	{
sl@0
   638
	TWsPointer::TimerExpired();
sl@0
   639
	return(KErrNone);
sl@0
   640
	}
sl@0
   641
sl@0
   642
void TWsPointer::RestrictPos(TPoint& aPos,TBool aWithinDrawableArea/*=ETrue*/)
sl@0
   643
	{
sl@0
   644
	CScreen* screen = iRootWindow->Screen();
sl@0
   645
	WS_ASSERT_DEBUG(screen->IsValidScreenSizeMode(screen->ScreenSizeMode()), EWsPanicInvalidScreenSizeMode);
sl@0
   646
#if defined(__WINS__)
sl@0
   647
	if (aWithinDrawableArea)
sl@0
   648
		{
sl@0
   649
	if (!DeltaMouse() && !TRect(screen->DrawableArea()).Contains(aPos))
sl@0
   650
			{
sl@0
   651
		return;			//Not in the drawable area so user may be trying to click on facia button.
sl@0
   652
			}
sl@0
   653
		}
sl@0
   654
#endif
sl@0
   655
	TRect validRect=screen->GetPointerCursorArea(screen->ScreenSizeMode());
sl@0
   656
	if (aPos.iX<validRect.iTl.iX)
sl@0
   657
		aPos.iX=validRect.iTl.iX;
sl@0
   658
	else if (aPos.iX>=validRect.iBr.iX)
sl@0
   659
		aPos.iX=validRect.iBr.iX-1;
sl@0
   660
	if (aPos.iY<validRect.iTl.iY)
sl@0
   661
		aPos.iY=validRect.iTl.iY;
sl@0
   662
	else if (aPos.iY>=validRect.iBr.iY)
sl@0
   663
		aPos.iY=validRect.iBr.iY-1;
sl@0
   664
	}
sl@0
   665
sl@0
   666
#if defined(__WINS__)
sl@0
   667
TBool TWsPointer::PreProcessDriverEvent(TRawEvent &aRawEvent,TBool aFromHardware/*=EFlase*/)
sl@0
   668
#else
sl@0
   669
TBool TWsPointer::PreProcessDriverEvent(TRawEvent &aRawEvent)
sl@0
   670
#endif
sl@0
   671
	{
sl@0
   672
	TRawEvent::TType type=aRawEvent.Type();
sl@0
   673
	
sl@0
   674
	if (!IsPointerEventType(type)) 
sl@0
   675
		return ETrue;
sl@0
   676
	
sl@0
   677
	if (!XyInput())
sl@0
   678
		{
sl@0
   679
		return EFalse;
sl@0
   680
		}
sl@0
   681
	
sl@0
   682
	//** Log the type, pointer number, and its coordinates
sl@0
   683
#ifdef LOG_WSERV_EVENTS
sl@0
   684
	RDebug::Printf("_WSEVENT_POINTER: Pointer number = %d RawEvent Type = %d Coordinates [%d, %d]", 
sl@0
   685
					aRawEvent.PointerNumber(), type, aRawEvent.Pos().iX, aRawEvent.Pos().iY);
sl@0
   686
#endif
sl@0
   687
	
sl@0
   688
	// check correctness of aRawEvent.PointerNumber()
sl@0
   689
	if (iMaxPointers > 1)
sl@0
   690
		{
sl@0
   691
		if (aRawEvent.PointerNumber() >= iMaxPointers)
sl@0
   692
			{
sl@0
   693
			return EFalse;
sl@0
   694
			}
sl@0
   695
		}
sl@0
   696
	else
sl@0
   697
		{
sl@0
   698
		aRawEvent.SetPointerNumber(0);
sl@0
   699
		}
sl@0
   700
	
sl@0
   701
	if (type != TRawEvent::EPointer3DOutOfRange)
sl@0
   702
		{
sl@0
   703
		// operations on coordinates are valid for all types except EPointer3DOutOfRange
sl@0
   704
		TPoint xy=aRawEvent.Pos();
sl@0
   705
		if (DeltaMouse())
sl@0
   706
			{
sl@0
   707
	#if defined(__WINS__)
sl@0
   708
			if (aFromHardware)
sl@0
   709
				return EFalse;
sl@0
   710
	#endif
sl@0
   711
			if (type==TRawEvent::EPointerMove)
sl@0
   712
				{
sl@0
   713
				xy+=iPointers[aRawEvent.PointerNumber()].iPos;
sl@0
   714
				ShiftYCoordinate(xy.iY);
sl@0
   715
				RestrictPos(xy);
sl@0
   716
				}
sl@0
   717
			else
sl@0
   718
				xy=iPointers[aRawEvent.PointerNumber()].iPos;
sl@0
   719
			}
sl@0
   720
		else
sl@0
   721
			{
sl@0
   722
	#if !defined(__WINS__)
sl@0
   723
			TranslateCoordsOnRotation(xy);
sl@0
   724
	#else
sl@0
   725
			if(iEmulatorRotatePointerCoords)
sl@0
   726
				{
sl@0
   727
				//emulators that support rotated drawing and touch may want to enable 
sl@0
   728
				//rotation of pointer events in wsini.
sl@0
   729
				TranslateCoordsOnRotation(xy);
sl@0
   730
				}
sl@0
   731
	#endif
sl@0
   732
			CScreen* screen=iRootWindow->Screen();
sl@0
   733
			ShiftYCoordinate(xy.iY);
sl@0
   734
			// Move the raw event position by shifting it by Origin and scale
sl@0
   735
			xy=screen->PhysicalToLogical(xy);
sl@0
   736
			RestrictPos(xy);
sl@0
   737
			}
sl@0
   738
		aRawEvent.Set(type, xy.iX, xy.iY, 
sl@0
   739
					  iIs3DPointer ? aRawEvent.Pos3D().iZ : 0);
sl@0
   740
		}
sl@0
   741
	
sl@0
   742
#ifdef LOG_WSERV_EVENTS
sl@0
   743
	RDebug::Printf("_WSEVENT_POINTER: Coordinates after Rotation and shift [%d, %d]", 
sl@0
   744
							aRawEvent.Pos().iX, aRawEvent.Pos().iY);
sl@0
   745
#endif
sl@0
   746
	return ETrue;
sl@0
   747
	}
sl@0
   748
sl@0
   749
void TWsPointer::TranslateCoordsOnRotation(TPoint& aPoint)
sl@0
   750
	{
sl@0
   751
	CScreen* screen=iRootWindow->Screen();
sl@0
   752
	TSize screenSize=screen->SizeInPixels()-TSize(1,1);     //This is in the current rotation
sl@0
   753
	switch (screen->Orientation())
sl@0
   754
		{
sl@0
   755
		case CFbsBitGc::EGraphicsOrientationRotated90:
sl@0
   756
			aPoint.SetXY(aPoint.iY,screenSize.iHeight-aPoint.iX);
sl@0
   757
			break;
sl@0
   758
		case CFbsBitGc::EGraphicsOrientationRotated180:
sl@0
   759
			aPoint=-(aPoint-screenSize);
sl@0
   760
			break;
sl@0
   761
		case CFbsBitGc::EGraphicsOrientationRotated270:
sl@0
   762
			aPoint.SetXY(screenSize.iWidth-aPoint.iY,aPoint.iX);
sl@0
   763
			break;
sl@0
   764
		default:;       //To stop warning
sl@0
   765
		}
sl@0
   766
	}
sl@0
   767
sl@0
   768
/**
sl@0
   769
 * Validates events sent to the Window Server by its Client (Anim or Window Group).
sl@0
   770
 * May overwrite aRawEvent's Z coordinate and/or pointer number if Client or digitizer driver
sl@0
   771
 * doesn't support them.
sl@0
   772
 * @param aRawEvent event to validate
sl@0
   773
 * @param aAdvancedPointersEnabled ETrue if Client supports advanced pointer's data (Z coordiante
sl@0
   774
 *                                 and pointer number); EFalse otherwise.
sl@0
   775
 * @return ETrue if aRawEvent should be processed by Window Server. EFalse if it should be ignored.
sl@0
   776
 */
sl@0
   777
TBool TWsPointer::PreProcessClientEvent(TRawEvent &aRawEvent, TBool aAdvancedPointersEnabled)
sl@0
   778
	{
sl@0
   779
	TRawEvent::TType type=aRawEvent.Type();
sl@0
   780
	
sl@0
   781
	if (!IsPointerEventType(type)) 
sl@0
   782
		return ETrue;
sl@0
   783
	
sl@0
   784
	// validate pointer number
sl@0
   785
	if (aAdvancedPointersEnabled)
sl@0
   786
		{
sl@0
   787
		// ignore event if both digitizer driver and Client support pointer numbers, but number is invalid
sl@0
   788
		if (aRawEvent.PointerNumber() >= iMaxPointers)
sl@0
   789
			{
sl@0
   790
			return EFalse;
sl@0
   791
			}		
sl@0
   792
		}
sl@0
   793
	else
sl@0
   794
		{
sl@0
   795
		// set to iPrimaryPointer if Client doesn't support pointer numbers
sl@0
   796
		aRawEvent.SetPointerNumber(iPrimaryPointer);
sl@0
   797
		}
sl@0
   798
	
sl@0
   799
	// validate Z coordinate for all pointer events except EPointer3DOutOfRange
sl@0
   800
	if (type != TRawEvent::EPointer3DOutOfRange)
sl@0
   801
		{
sl@0
   802
		if (!iIs3DPointer)
sl@0
   803
			{
sl@0
   804
			// set Z to 0 for all events when the digitizer driver doesn't support Z coordinate
sl@0
   805
			TPoint3D xyz=aRawEvent.Pos3D();
sl@0
   806
			aRawEvent.Set(type, xyz.iX, xyz.iY, 0);
sl@0
   807
			}
sl@0
   808
		else if (!aAdvancedPointersEnabled)
sl@0
   809
			{
sl@0
   810
			// set Z to actual value if the digitizer driver does support Z coordinate but Client doesn't 
sl@0
   811
			TPoint3D xyz=aRawEvent.Pos3D();
sl@0
   812
			aRawEvent.Set(type, xyz.iX, xyz.iY, iPointers[aRawEvent.PointerNumber()].iPressureProximity);
sl@0
   813
			}
sl@0
   814
		}
sl@0
   815
	
sl@0
   816
	return ETrue;
sl@0
   817
	}
sl@0
   818
sl@0
   819
TBool TWsPointer::IsPointerEventType(TRawEvent::TType aType)
sl@0
   820
	{
sl@0
   821
#if defined(__WINS__)
sl@0
   822
	WS_ASSERT_DEBUG(TRawEvent::EPointerMove==1, EWsPanicRawEventsTypeChanged);
sl@0
   823
	WS_ASSERT_DEBUG(TRawEvent::EPointerMove+1==TRawEvent::EPointerSwitchOn, EWsPanicRawEventsTypeChanged);
sl@0
   824
	WS_ASSERT_DEBUG(TRawEvent::EPointerSwitchOn+8==TRawEvent::EButton1Down, EWsPanicRawEventsTypeChanged);
sl@0
   825
	WS_ASSERT_DEBUG(TRawEvent::EButton1Down+5==TRawEvent::EButton3Up, EWsPanicRawEventsTypeChanged);
sl@0
   826
	WS_ASSERT_DEBUG(TRawEvent::EButton3Up+6==TRawEvent::EPointer3DOutOfRange, EWsPanicRawEventsTypeChanged);
sl@0
   827
#endif
sl@0
   828
	return (aType == TRawEvent::EPointerMove) ||
sl@0
   829
		   (aType == TRawEvent::EPointerSwitchOn) ||
sl@0
   830
		   (aType >= TRawEvent::EButton1Down && aType <= TRawEvent::EButton3Up) ||
sl@0
   831
		   (aType == TRawEvent::EPointer3DOutOfRange);
sl@0
   832
	}
sl@0
   833
sl@0
   834
/*
sl@0
   835
Pointer Event processing.
sl@0
   836
sl@0
   837
This method redirects pointer event processing to proper TWsPointer object.
sl@0
   838
*/
sl@0
   839
void TWsPointer::ProcessWsEvent(TWsEvent& aEvent,const CWsWindowGroup* aForceInGroup,TBool aNatural)
sl@0
   840
	{
sl@0
   841
	if(iPrimaryPointer!=iPreviousPrimaryPointer)
sl@0
   842
		{
sl@0
   843
		// The primary pointer may be updated while the TRawEvent is being processed, but this TRawEvent may be
sl@0
   844
		// then be consumed by an anim.
sl@0
   845
		// If it hasn't then we can leave any repeat request.
sl@0
   846
		CancelPointerRepeatEventRequest(iPreviousPrimaryPointer);
sl@0
   847
		}
sl@0
   848
	
sl@0
   849
	if (aEvent.Pointer()->iType == TPointerEvent::EOutOfRange)
sl@0
   850
		{
sl@0
   851
		iPointers[TAdvancedPointerEventHelper::PointerNumber(aEvent)].ProcessOutOfRangeEvent(aEvent, aForceInGroup, aNatural);
sl@0
   852
		}
sl@0
   853
	else
sl@0
   854
		{
sl@0
   855
		iPointers[TAdvancedPointerEventHelper::PointerNumber(aEvent)].ProcessEvent(aEvent, aForceInGroup, aNatural);
sl@0
   856
		}
sl@0
   857
	}
sl@0
   858
sl@0
   859
/*
sl@0
   860
Pointer Event Processing - stage 1 of 3:
sl@0
   861
- updating this pointer's state: coordinates and grabbing window
sl@0
   862
- updating coordinates of event
sl@0
   863
- updating event type to Drag
sl@0
   864
- simulated moves
sl@0
   865
- generating events: EEnterCloseProximity, EExitCloseProximity, EEnterHighPressure, EExitHighPressure
sl@0
   866
*/
sl@0
   867
void TWsPointer::ProcessEvent(TWsEvent& aEvent,const CWsWindowGroup* aForceInGroup,TBool aNatural)
sl@0
   868
 	{
sl@0
   869
	TAdvancedPointerEvent& pointerEvent = *aEvent.Pointer();
sl@0
   870
	TPointerEvent::TType eventType=pointerEvent.iType;
sl@0
   871
	
sl@0
   872
 	if (iState == EPointerStateOutOfRange)
sl@0
   873
 		{
sl@0
   874
 		// new pointer comes in range, so clear information after previous one 		
sl@0
   875
 		Clear();
sl@0
   876
 		}
sl@0
   877
 	
sl@0
   878
	// update coordinates
sl@0
   879
	iPos=pointerEvent.iPosition;
sl@0
   880
	iPressureProximity=TAdvancedPointerEventHelper::Z(aEvent);
sl@0
   881
	
sl@0
   882
	if (eventType == TPointerEvent::EMove && !MovesAvailable() && iState != EPointerStateDown)
sl@0
   883
		{
sl@0
   884
		return;
sl@0
   885
		}
sl@0
   886
	
sl@0
   887
	// re-log and update parent position
sl@0
   888
	TPoint parPos;
sl@0
   889
	ReLogCurrentWindow(pointerEvent.iPosition,parPos,aForceInGroup);
sl@0
   890
	pointerEvent.iParentPosition=parPos;
sl@0
   891
	
sl@0
   892
	
sl@0
   893
#ifdef LOG_WSERV_EVENTS
sl@0
   894
	RDebug::Printf("_WSEVENT_POINTER: TWsPointer::ProcessEvent Event to be sent to this window %U", reinterpret_cast<TUint32>(iCurrentWindow));
sl@0
   895
	RDebug::Print(_L("_WSEVENT_POINTER: TWsPointer::ProcessEvent EventName %S and Event State %d "), &WsEventName(aEvent), iState);
sl@0
   896
#endif
sl@0
   897
	// update state
sl@0
   898
	switch(eventType)
sl@0
   899
		{
sl@0
   900
		case TPointerEvent::EButton1Down:
sl@0
   901
			if (iGrabWindow==NULL && iCurrentWindow->HasPointerGrab())
sl@0
   902
				{
sl@0
   903
				iGrabWindow=iCurrentWindow;
sl@0
   904
				}
sl@0
   905
			if (!MovesAvailable() && iCurrentWindow->PointerFilter()&EPointerGenerateSimulatedMove)
sl@0
   906
				{
sl@0
   907
				pointerEvent.iType=TPointerEvent::EMove;
sl@0
   908
				ProcessEvent(aEvent, EFalse);
sl@0
   909
				pointerEvent.iType=TPointerEvent::EButton1Down;
sl@0
   910
				}
sl@0
   911
			switch(iState)
sl@0
   912
				{
sl@0
   913
				case EPointerStateOutOfRange:
sl@0
   914
					iState = EPointerStateDown;
sl@0
   915
					SendEnterExitEvent(EEventPointerEnter);
sl@0
   916
					// intentional lack of break statement
sl@0
   917
				case EPointerStateUp:
sl@0
   918
					iState = EPointerStateDown;
sl@0
   919
					ProcessEvent(aEvent, aNatural);
sl@0
   920
					if (iPressureProximity >= iEnterHighPressureThreshold)
sl@0
   921
						{
sl@0
   922
						iInHighPressure = ETrue;
sl@0
   923
						pointerEvent.iType = TPointerEvent::EEnterHighPressure;
sl@0
   924
						ProcessEvent(aEvent, EFalse);
sl@0
   925
						}
sl@0
   926
					else
sl@0
   927
						{
sl@0
   928
						iInHighPressure = EFalse;
sl@0
   929
						}
sl@0
   930
					break;
sl@0
   931
				case EPointerStateDown:
sl@0
   932
					if (iInHighPressure && iPressureProximity < iExitHighPressureThreshold) 
sl@0
   933
						{
sl@0
   934
						iInHighPressure = EFalse;
sl@0
   935
						eventType = TPointerEvent::EExitHighPressure;
sl@0
   936
						}
sl@0
   937
					else if (!iInHighPressure && iPressureProximity >= iEnterHighPressureThreshold)
sl@0
   938
						{
sl@0
   939
						iInHighPressure = ETrue;
sl@0
   940
						eventType = TPointerEvent::EEnterHighPressure;
sl@0
   941
						}
sl@0
   942
					ProcessEvent(aEvent, aNatural);
sl@0
   943
					break;
sl@0
   944
				}
sl@0
   945
			break;
sl@0
   946
		case TPointerEvent::EButton1Up:
sl@0
   947
			iGrabWindow=NULL;
sl@0
   948
			switch(iState)
sl@0
   949
				{
sl@0
   950
				case EPointerStateDown:
sl@0
   951
					iState = EPointerStateUp;
sl@0
   952
					ProcessEvent(aEvent, aNatural);
sl@0
   953
					if (iPressureProximity < iExitCloseProximityThreshold)
sl@0
   954
						{
sl@0
   955
						pointerEvent.iType = TPointerEvent::EExitCloseProximity;
sl@0
   956
						iInCloseProximity = EFalse;
sl@0
   957
						ProcessEvent(aEvent, EFalse);
sl@0
   958
						}
sl@0
   959
					else
sl@0
   960
						{
sl@0
   961
						iInCloseProximity = ETrue;
sl@0
   962
						}
sl@0
   963
					break;
sl@0
   964
				case EPointerStateOutOfRange:
sl@0
   965
					iState = EPointerStateUp;
sl@0
   966
					SendEnterExitEvent(EEventPointerEnter);
sl@0
   967
					// intentional lack of break statement
sl@0
   968
				case EPointerStateUp:
sl@0
   969
					if (iInCloseProximity &&
sl@0
   970
						iPressureProximity < iExitCloseProximityThreshold)
sl@0
   971
						{
sl@0
   972
						iInCloseProximity = EFalse;
sl@0
   973
						pointerEvent.iType = TPointerEvent::EExitCloseProximity;
sl@0
   974
						}
sl@0
   975
					else if (!iInCloseProximity &&
sl@0
   976
							 iPressureProximity >= iEnterCloseProximityThreshold)
sl@0
   977
						{
sl@0
   978
						iInCloseProximity = ETrue;
sl@0
   979
						pointerEvent.iType = TPointerEvent::EEnterCloseProximity;
sl@0
   980
						}
sl@0
   981
					ProcessEvent(aEvent, aNatural);
sl@0
   982
					break;
sl@0
   983
				}
sl@0
   984
			break;
sl@0
   985
		case TPointerEvent::EMove:
sl@0
   986
			switch(iState)
sl@0
   987
				{
sl@0
   988
				case EPointerStateDown:
sl@0
   989
					if (iInHighPressure && 
sl@0
   990
						iPressureProximity < iExitHighPressureThreshold) 
sl@0
   991
						{
sl@0
   992
						iInHighPressure = EFalse;
sl@0
   993
						pointerEvent.iType = TPointerEvent::EExitHighPressure;
sl@0
   994
						}
sl@0
   995
					else if (!iInHighPressure &&
sl@0
   996
							iPressureProximity >= iEnterHighPressureThreshold)
sl@0
   997
						{
sl@0
   998
						iInHighPressure = ETrue;
sl@0
   999
						pointerEvent.iType = TPointerEvent::EEnterHighPressure;
sl@0
  1000
						}
sl@0
  1001
					else
sl@0
  1002
						{
sl@0
  1003
						pointerEvent.iType = TPointerEvent::EDrag;
sl@0
  1004
						}
sl@0
  1005
					break;
sl@0
  1006
				case EPointerStateUp:
sl@0
  1007
					if (iInCloseProximity &&
sl@0
  1008
						iPressureProximity < iExitCloseProximityThreshold)
sl@0
  1009
						{
sl@0
  1010
						iInCloseProximity = EFalse;
sl@0
  1011
						pointerEvent.iType = TPointerEvent::EExitCloseProximity;
sl@0
  1012
						}
sl@0
  1013
					else if (!iInCloseProximity &&
sl@0
  1014
							 iPressureProximity >= iEnterCloseProximityThreshold)
sl@0
  1015
						{
sl@0
  1016
						iInCloseProximity = ETrue;
sl@0
  1017
						pointerEvent.iType = TPointerEvent::EEnterCloseProximity;
sl@0
  1018
						}
sl@0
  1019
					break;
sl@0
  1020
				case EPointerStateOutOfRange:
sl@0
  1021
					iState = EPointerStateUp;
sl@0
  1022
					SendEnterExitEvent(EEventPointerEnter);
sl@0
  1023
					if (iPressureProximity >= iEnterCloseProximityThreshold)
sl@0
  1024
						{
sl@0
  1025
						iInCloseProximity = ETrue;
sl@0
  1026
						pointerEvent.iType = TPointerEvent::EEnterCloseProximity;
sl@0
  1027
						}
sl@0
  1028
					break;
sl@0
  1029
				}
sl@0
  1030
			ProcessEvent(aEvent, aNatural);
sl@0
  1031
			break;
sl@0
  1032
		default:
sl@0
  1033
			ProcessEvent(aEvent, aNatural);
sl@0
  1034
			break;
sl@0
  1035
		}
sl@0
  1036
	}
sl@0
  1037
sl@0
  1038
/**
sl@0
  1039
Processes OutOfRange events:
sl@0
  1040
- injects event to key click plugin
sl@0
  1041
- directs event to the last current window
sl@0
  1042
- sends Exit event
sl@0
  1043
*/
sl@0
  1044
void TWsPointer::ProcessOutOfRangeEvent(TWsEvent& aEvent,const CWsWindowGroup* aForceInGroup, TBool aNatural)
sl@0
  1045
	{
sl@0
  1046
	if (iState != EPointerStateOutOfRange)
sl@0
  1047
		{
sl@0
  1048
#ifdef LOG_WSERV_EVENTS
sl@0
  1049
       RDebug::Printf("_WSEVENT_POINTER: TWsPointer::ProcessOutOfRangeEvent Pointer Number = %d, iState =%d ", iNumber, iState); 
sl@0
  1050
#endif
sl@0
  1051
sl@0
  1052
		// OutOfRange event generated by driver doesn't contain correct coordinates,
sl@0
  1053
		// we update them from last state in order to deliver event to the proper window.
sl@0
  1054
		SendEnterExitEvent(EEventPointerExit);
sl@0
  1055
		
sl@0
  1056
		iState = EPointerStateOutOfRange;
sl@0
  1057
		
sl@0
  1058
		TAdvancedPointerEventHelper::SetPointerNumber(aEvent, iNumber);
sl@0
  1059
		TAdvancedPointerEventHelper::SetZ(aEvent, iPressureProximity);
sl@0
  1060
		
sl@0
  1061
		TAdvancedPointerEvent& pointerEvent = *aEvent.Pointer();		
sl@0
  1062
		iCurrentWindow=iRootWindow->PointerWindow(iPos,&pointerEvent.iPosition,&pointerEvent.iParentPosition,iGrabWindow,
sl@0
  1063
			                   					  iActualWinPointerIsOver,aForceInGroup);
sl@0
  1064
		ProcessEvent(aEvent, aNatural);
sl@0
  1065
		}
sl@0
  1066
	}
sl@0
  1067
sl@0
  1068
void TWsPointer::NotifyCClick(TAdvancedPointerEvent& aPointerEvent)
sl@0
  1069
	{
sl@0
  1070
	if (CClick::IsHandler())
sl@0
  1071
		{
sl@0
  1072
		CClick::PointerEvent(iPos,aPointerEvent);
sl@0
  1073
		TPointerEventData params;
sl@0
  1074
		params.iVersion=0;
sl@0
  1075
		params.iCurrentPos=iPos;
sl@0
  1076
		TAdvancedPointerEventHelper::Copy(aPointerEvent, params.iPointerEvent);
sl@0
  1077
		params.iClientHandle=iCurrentWindow->ClientHandle();
sl@0
  1078
		params.iWindowOrigin=iCurrentWindow->Origin();
sl@0
  1079
		CWsWindowGroup* groupWin=iCurrentWindow->WinGroup();
sl@0
  1080
		params.iWindowGroupId=groupWin ? groupWin->Identifier() : 0;
sl@0
  1081
		params.iSource=TPointerEventData::EUnspecified;
sl@0
  1082
		CClick::OtherEvent(EEventPointer,&params);
sl@0
  1083
		}
sl@0
  1084
	}
sl@0
  1085
sl@0
  1086
/*
sl@0
  1087
Pointer Event Processing - stage 2 of 3:
sl@0
  1088
- injecting events to key click plugin
sl@0
  1089
- pointer filtering
sl@0
  1090
- injection to event buffer
sl@0
  1091
- injection to keyboard emulator
sl@0
  1092
- clearing iCurrentWindow if going up and !MovesAvailable()
sl@0
  1093
- updating pointer cursor
sl@0
  1094
*/
sl@0
  1095
void TWsPointer::ProcessEvent(TWsEvent& aEvent, TBool aNatural)
sl@0
  1096
	{
sl@0
  1097
	if (aNatural)
sl@0
  1098
		{
sl@0
  1099
		NotifyCClick(*aEvent.Pointer());
sl@0
  1100
		}
sl@0
  1101
	
sl@0
  1102
	TUint filter=iCurrentWindow->PointerFilter();
sl@0
  1103
	TPointerEvent::TType type=aEvent.Pointer()->iType;
sl@0
  1104
	if ((type!=TPointerEvent::EMove || !(filter&EPointerFilterMove)) &&
sl@0
  1105
		 (type!=TPointerEvent::EDrag || !(filter&EPointerFilterDrag)))
sl@0
  1106
		{
sl@0
  1107
		if (iNumber == iPrimaryPointer)
sl@0
  1108
			{
sl@0
  1109
			TPoint pos=aEvent.Pointer()->iPosition;
sl@0
  1110
			if ((type==TPointerEvent::EMove || type==TPointerEvent::EDrag) && iCurrentWindow->UsingPointerBuffer())
sl@0
  1111
				{
sl@0
  1112
				CWsPointerBuffer::PointerEvent((CWsClientWindow *)iCurrentWindow,pos);
sl@0
  1113
				}
sl@0
  1114
			else if ((type==TPointerEvent::EEnterCloseProximity || type==TPointerEvent::EExitCloseProximity || 
sl@0
  1115
					  type==TPointerEvent::EEnterHighPressure   || type==TPointerEvent::EExitHighPressure) && 
sl@0
  1116
					 iCurrentWindow->UsingPointerBuffer())
sl@0
  1117
				{
sl@0
  1118
				CWsPointerBuffer::PointerEvent((CWsClientWindow *)iCurrentWindow,pos);
sl@0
  1119
				ProcessPointerEvent(aEvent);
sl@0
  1120
				}
sl@0
  1121
			else if (!WsKeyboardEmulator::PointerEvent(type,pos,iCurrentWindow->PointerKeyList()))
sl@0
  1122
				{
sl@0
  1123
#ifdef LOG_WSERV_EVENTS
sl@0
  1124
				RDebug::Printf("_WSEVENT_POINTER: Calling ProcessPointerEvent for primary pointer");
sl@0
  1125
#endif
sl@0
  1126
				ProcessPointerEvent(aEvent);
sl@0
  1127
				}
sl@0
  1128
			}
sl@0
  1129
		else if (!iCurrentWindow->UsingPointerBuffer() || (type != TPointerEvent::EMove && type != TPointerEvent::EDrag))
sl@0
  1130
			{
sl@0
  1131
#ifdef LOG_WSERV_EVENTS
sl@0
  1132
			RDebug::Printf("_WSEVENT_POINTER: Calling ProcessPointerEvent for non primary pointer");
sl@0
  1133
#endif
sl@0
  1134
			ProcessPointerEvent(aEvent);
sl@0
  1135
			}
sl@0
  1136
		}
sl@0
  1137
	if (!MovesAvailable() && (type==TPointerEvent::EButton1Up || 
sl@0
  1138
			                  type==TPointerEvent::ESwitchOn  ||
sl@0
  1139
			                  type==TPointerEvent::EOutOfRange))
sl@0
  1140
		{
sl@0
  1141
		iCurrentWindow=NULL;
sl@0
  1142
		}
sl@0
  1143
	if (iNumber == iPrimaryPointer)
sl@0
  1144
		{
sl@0
  1145
		PointerCursorUpdateCheck();
sl@0
  1146
		}
sl@0
  1147
	}
sl@0
  1148
sl@0
  1149
void TWsPointer::TimerExpired()
sl@0
  1150
	{
sl@0
  1151
	WS_ASSERT_DEBUG(iTimerQueued, EWsPanicPointerTimer);
sl@0
  1152
	if (iUpdateRequired)
sl@0
  1153
		{
sl@0
  1154
		UpdatePointerCursor();
sl@0
  1155
		iUpdateRequired=EFalse;
sl@0
  1156
		}
sl@0
  1157
	else
sl@0
  1158
		{
sl@0
  1159
		iTimerQueued=EFalse;
sl@0
  1160
		iPeriodicTimer->Cancel();
sl@0
  1161
		}
sl@0
  1162
	}
sl@0
  1163
sl@0
  1164
void TWsPointer::GetDoubleClickSettings(TTimeIntervalMicroSeconds32 &aTime, TInt &aDistance)
sl@0
  1165
	{
sl@0
  1166
	aTime=iDoubleClickMaxInterval;
sl@0
  1167
	aDistance=iDoubleClickMaxDistance;
sl@0
  1168
	}
sl@0
  1169
sl@0
  1170
void TWsPointer::SetDoubleClick(const TTimeIntervalMicroSeconds32 &aTime, TInt aDistance)
sl@0
  1171
	{
sl@0
  1172
	iDoubleClickMaxInterval=aTime;
sl@0
  1173
	iDoubleClickMaxDistance=aDistance;
sl@0
  1174
	}
sl@0
  1175
sl@0
  1176
void TWsPointer::PointerCursorUpdateCheck()
sl@0
  1177
	{
sl@0
  1178
	CWsPointerCursor* sprite=CalculatePointerCursor();
sl@0
  1179
	if (iCursorSprite || sprite)	// If there either was, or is a pointer cursor we need an update
sl@0
  1180
		{
sl@0
  1181
		if (!iTimerQueued)
sl@0
  1182
			{
sl@0
  1183
			UpdatePointerCursorTo(sprite);
sl@0
  1184
			iPeriodicTimer->Start(TTimeIntervalMicroSeconds32(EPointerUpdateGapInMicroSeconds),
sl@0
  1185
									TTimeIntervalMicroSeconds32(EPointerUpdateGapInMicroSeconds),
sl@0
  1186
									  TCallBack(PointerTimerCallBack,NULL));
sl@0
  1187
			iTimerQueued=ETrue;
sl@0
  1188
			}
sl@0
  1189
		else
sl@0
  1190
			{
sl@0
  1191
			iUpdateRequired=ETrue;
sl@0
  1192
			}
sl@0
  1193
		}
sl@0
  1194
	}
sl@0
  1195
sl@0
  1196
void TWsPointer::UpdatePointerCursor()
sl@0
  1197
	{
sl@0
  1198
//__PROFILE_START(3);
sl@0
  1199
	CWsPointerCursor* sprite=iPointers[iPrimaryPointer].CalculatePointerCursor();
sl@0
  1200
	UpdatePointerCursorTo(sprite);
sl@0
  1201
//__PROFILE_END(3);
sl@0
  1202
	}
sl@0
  1203
sl@0
  1204
void TWsPointer::UpdatePointerCursorTo(CWsPointerCursor* aNewCursor)
sl@0
  1205
	{
sl@0
  1206
	if (iCursorSprite!=aNewCursor)
sl@0
  1207
		{
sl@0
  1208
		if (iCursorSprite)
sl@0
  1209
			{
sl@0
  1210
			iCursorSprite->Deactivate();
sl@0
  1211
			}
sl@0
  1212
		iCursorSprite=aNewCursor;
sl@0
  1213
		if (iCursorSprite)
sl@0
  1214
			{
sl@0
  1215
			iCursorSprite->SetPos(iPointers[iPrimaryPointer].iPos);
sl@0
  1216
			iCursorSprite->Activate();
sl@0
  1217
			}
sl@0
  1218
		}
sl@0
  1219
	else if (iCursorSprite)
sl@0
  1220
		{
sl@0
  1221
		iCursorSprite->SetPos(iPointers[iPrimaryPointer].iPos);
sl@0
  1222
		}
sl@0
  1223
	}
sl@0
  1224
sl@0
  1225
CWsPointerCursor* TWsPointer::CalculatePointerCursor()
sl@0
  1226
	{
sl@0
  1227
	CWsPointerCursor* sprite=NULL;
sl@0
  1228
	if (iCurrentWindow && (iPointerCursorMode==EPointerCursorNormal || iPointerCursorMode==EPointerCursorWindow))
sl@0
  1229
		{
sl@0
  1230
		const CWsWindowBase* window=iCurrentWindow;
sl@0
  1231
		do	{
sl@0
  1232
			sprite=window->PointerCursor();
sl@0
  1233
			if (window->WinType()!=EWinTypeClient)
sl@0
  1234
				{
sl@0
  1235
				break;
sl@0
  1236
				}
sl@0
  1237
			window=window->BaseParent();
sl@0
  1238
			} while (!sprite);
sl@0
  1239
		}
sl@0
  1240
	if (!sprite && iCurrentWindow && (iPointerCursorMode==EPointerCursorFixed || iPointerCursorMode==EPointerCursorNormal))
sl@0
  1241
		{
sl@0
  1242
		sprite=CWsClient::DefaultSystemPointerCursor();
sl@0
  1243
		}
sl@0
  1244
	return sprite;
sl@0
  1245
	}
sl@0
  1246
sl@0
  1247
/*
sl@0
  1248
Callback function for event queue walk
sl@0
  1249
*/
sl@0
  1250
TEventQueueWalkRet PointerRepeatPurgeFunc(TAny* aReqPtrNum, TWsEvent* aQueueEvent)
sl@0
  1251
	{
sl@0
  1252
	return(TWsPointer::PointerRepeatPurgeCheck(aQueueEvent, reinterpret_cast<TUint>(aReqPtrNum)));
sl@0
  1253
	}
sl@0
  1254
sl@0
  1255
TBool TWsPointer::PointerEventRepeatCheck(const TWsEvent* aEvent, TUint32 aHandle)
sl@0
  1256
//
sl@0
  1257
// Return ETrue if this pointer event is consumed by the pointer repeat
sl@0
  1258
//
sl@0
  1259
	{
sl@0
  1260
	// Must be a pointer event type in order to get the pointer number,
sl@0
  1261
	// which is needed to check the repeat window.
sl@0
  1262
	WS_ASSERT_DEBUG(aEvent->Type()==EEventPointer,EWsPanicEventType);
sl@0
  1263
	
sl@0
  1264
	const TAdvancedPointerEvent* pntEvent=aEvent->Pointer();
sl@0
  1265
	if (	TAdvancedPointerEventHelper::PointerNumber(*aEvent)==iNumber &&
sl@0
  1266
			aHandle==iRepeatWindow->ClientHandle())
sl@0
  1267
		{
sl@0
  1268
		switch(pntEvent->iType)
sl@0
  1269
			{
sl@0
  1270
			case TPointerEvent::EDrag: // deliberate drop-through
sl@0
  1271
			case TPointerEvent::EMove: // deliberate drop-through
sl@0
  1272
			case TPointerEvent::EEnterCloseProximity: // deliberate drop-through
sl@0
  1273
			case TPointerEvent::EExitCloseProximity: // deliberate drop-through
sl@0
  1274
			case TPointerEvent::EEnterHighPressure: // deliberate drop-through
sl@0
  1275
			case TPointerEvent::EExitHighPressure:
sl@0
  1276
				{
sl@0
  1277
				if(iRepeatRect.Contains(pntEvent->iPosition))
sl@0
  1278
					{
sl@0
  1279
					return(ETrue);
sl@0
  1280
					}
sl@0
  1281
				break;
sl@0
  1282
				}
sl@0
  1283
			default:
sl@0
  1284
				// do nothing and drop through
sl@0
  1285
				break;
sl@0
  1286
			}		
sl@0
  1287
		}
sl@0
  1288
	return(EFalse);
sl@0
  1289
	}
sl@0
  1290
sl@0
  1291
TEventQueueWalkRet TWsPointer::PointerRepeatPurgeCheck(TWsEvent* aQueueEvent, TUint8 aReqPtrNum)
sl@0
  1292
	{
sl@0
  1293
	// Return value is "WalkOK", unless a repeated event is found that needs to be deleted.
sl@0
  1294
	TEventQueueWalkRet eventQueueWalkRet(EEventQueueWalkOk);	
sl@0
  1295
	
sl@0
  1296
	// Check the WSEvent Type	
sl@0
  1297
	if (aQueueEvent->Type()==EEventPointer) // aEvent is a pointer event
sl@0
  1298
		{		
sl@0
  1299
		// It is a pointer event, so we can get the pointer number
sl@0
  1300
		// to check if there is a repeat request for that pointer.
sl@0
  1301
		const TInt eventPtrNum(TAdvancedPointerEventHelper::PointerNumber(*aQueueEvent));		
sl@0
  1302
		// If aEvent's pointer has an active repeat request,
sl@0
  1303
		// then it'll have a repeat window.
sl@0
  1304
		if ((eventPtrNum == aReqPtrNum) && RepeatWindow(eventPtrNum))
sl@0
  1305
			{
sl@0
  1306
			// There is a repeat request for the pointer.
sl@0
  1307
			// Is there a queued repeated event to be deleted?
sl@0
  1308
			TWsPointer& wsPointer = iPointers[eventPtrNum];
sl@0
  1309
			if (wsPointer.PointerEventRepeatCheck(aQueueEvent,aQueueEvent->Handle()))
sl@0
  1310
				{
sl@0
  1311
				// Update the return value to purge the event
sl@0
  1312
				// as it is a move/drag within the repeat rect
sl@0
  1313
				eventQueueWalkRet=EEventQueueWalkDeleteEvent;
sl@0
  1314
				}		
sl@0
  1315
			else
sl@0
  1316
				{
sl@0
  1317
				// No queued repeated event was found, therefore the
sl@0
  1318
				// request is still pending and needs to be cancelled.
sl@0
  1319
				wsPointer.CancelPointerRepeatEventRequest();
sl@0
  1320
				}
sl@0
  1321
			}
sl@0
  1322
		}
sl@0
  1323
	return eventQueueWalkRet;
sl@0
  1324
	}
sl@0
  1325
sl@0
  1326
void TWsPointer::RequestRepeatEvent(CWsWindow* aWindow, const TWsWinCmdRequestPointerRepeatEvent& aRequest)
sl@0
  1327
	{
sl@0
  1328
	CancelPointerRepeatEventRequest();
sl@0
  1329
	iRepeatWindow=aWindow;
sl@0
  1330
	iRepeatRect=aRequest.rect;
sl@0
  1331
	iRepeatTimer->After(aRequest.time);
sl@0
  1332
	aWindow->EventQueue()->WalkEventQueue(&PointerRepeatPurgeFunc,reinterpret_cast<TInt*>(iNumber));
sl@0
  1333
	if (iRepeatWindow && !iRepeatRect.Contains(iPos-iRepeatWindow->Origin()))
sl@0
  1334
		{
sl@0
  1335
		CancelPointerRepeatEventRequest();
sl@0
  1336
		}	
sl@0
  1337
	}
sl@0
  1338
sl@0
  1339
TInt TWsPointer::RequestPointerRepeatEvent(CWsWindow* aWindow, const TWsWinCmdRequestPointerRepeatEvent& aRequest)
sl@0
  1340
	{
sl@0
  1341
	TInt errNo = KErrNone;
sl@0
  1342
	TUint8 pointerNum = aRequest.HasPointerNumber() ? aRequest.pointerNumber : iPrimaryPointer;
sl@0
  1343
	if(PointerNumberInRange(pointerNum))
sl@0
  1344
		{
sl@0
  1345
		iPointers[pointerNum].RequestRepeatEvent(aWindow,aRequest);
sl@0
  1346
		}
sl@0
  1347
	else
sl@0
  1348
		{
sl@0
  1349
		errNo=KErrArgument;
sl@0
  1350
		}
sl@0
  1351
	return errNo;
sl@0
  1352
	}
sl@0
  1353
sl@0
  1354
void TWsPointer::CancelPointerRepeatEventRequest()
sl@0
  1355
	{
sl@0
  1356
	if (iRepeatWindow)
sl@0
  1357
		{
sl@0
  1358
		iRepeatWindow=NULL;
sl@0
  1359
		if(iRepeatTimer)
sl@0
  1360
			iRepeatTimer->Cancel();
sl@0
  1361
		}
sl@0
  1362
	}
sl@0
  1363
sl@0
  1364
TInt TWsPointer::CancelPointerRepeatEventRequest(const TWsWinCmdCancelPointerRepeatEventRequest& aRequest)
sl@0
  1365
	{
sl@0
  1366
	TInt errNo = KErrNone;	
sl@0
  1367
	TUint8 pointerNum = aRequest.HasPointerNumber() ? aRequest.pointerNumber : iPrimaryPointer;
sl@0
  1368
	if(PointerNumberInRange(pointerNum))
sl@0
  1369
		{
sl@0
  1370
		iPointers[pointerNum].CancelPointerRepeatEventRequest();
sl@0
  1371
		}
sl@0
  1372
	else
sl@0
  1373
		{
sl@0
  1374
		errNo=KErrArgument;
sl@0
  1375
		}
sl@0
  1376
	return errNo;
sl@0
  1377
	}
sl@0
  1378
sl@0
  1379
void TWsPointer::RepeatTimerCompleted()
sl@0
  1380
	{
sl@0
  1381
	TWsEvent event;
sl@0
  1382
	event.SetType(EEventPointer);
sl@0
  1383
	event.SetTimeNow();
sl@0
  1384
	TPoint3D point3D(iPos-iRepeatWindow->Origin());
sl@0
  1385
	point3D.iZ=iPressureProximity;
sl@0
  1386
	TAdvancedPointerEventHelper::InitAdvancedPointerEvent(event,
sl@0
  1387
														  TPointerEvent::EButtonRepeat,
sl@0
  1388
														  TWindowServerEvent::GetModifierState(),
sl@0
  1389
														  point3D,
sl@0
  1390
														  (iPos-iRepeatWindow->BaseParent()->Origin()),
sl@0
  1391
														  iNumber);
sl@0
  1392
	QueuePointerEvent(iRepeatWindow, event);
sl@0
  1393
	iRepeatWindow=NULL;
sl@0
  1394
	}
sl@0
  1395
sl@0
  1396
#if defined(__WINS__)
sl@0
  1397
void TWsPointer::SetXyInputType(TXYInputType aXyInputType)
sl@0
  1398
	{
sl@0
  1399
	if (iXyInputType>EXYInputPointer && aXyInputType<EXYInputMouse)
sl@0
  1400
		{
sl@0
  1401
		// change from Mouse types to Pointer/None
sl@0
  1402
		for (TInt ii = 0; ii < iMaxPointers; ii++)
sl@0
  1403
			{
sl@0
  1404
			if (iPointers[ii].iState != EPointerStateDown)
sl@0
  1405
				{
sl@0
  1406
				iPointers[ii].iCurrentWindow=NULL;
sl@0
  1407
				}
sl@0
  1408
			}
sl@0
  1409
		UpdatePointerCursor();
sl@0
  1410
		}
sl@0
  1411
	else if (iXyInputType<EXYInputMouse && aXyInputType>EXYInputPointer)
sl@0
  1412
		{
sl@0
  1413
		// change from Pointer/None types to Mouse types
sl@0
  1414
		for (TInt ii = 0; ii < iMaxPointers; ii++)
sl@0
  1415
			{
sl@0
  1416
			if (iPointers[ii].iState != EPointerStateDown)
sl@0
  1417
				{
sl@0
  1418
				TPoint pos(iPointers[ii].iPos);
sl@0
  1419
				TPoint parPos;
sl@0
  1420
				iPointers[ii].ReLogCurrentWindow(pos,parPos,NULL);
sl@0
  1421
				}
sl@0
  1422
			}
sl@0
  1423
		UpdatePointerCursor();
sl@0
  1424
		}
sl@0
  1425
	iXyInputType=aXyInputType;
sl@0
  1426
	}
sl@0
  1427
#endif
sl@0
  1428
sl@0
  1429
/**
sl@0
  1430
Updates Primary Pointer before aRawEvent is processed. Only events related to Primary
sl@0
  1431
Pointer will be sent to Clients which require single pointer environment.
sl@0
  1432
sl@0
  1433
This method implements single pointer environment emulation rules (see design
sl@0
  1434
documentation for more details).
sl@0
  1435
sl@0
  1436
@param aRawEvent Incoming event used to update the Primary Pointer. It must be a pointer event,
sl@0
  1437
                 as defined by TWsPointer::IsPointerEventType(TRawEvent::TType).
sl@0
  1438
*/
sl@0
  1439
void TWsPointer::UpdatePrimaryPointer(const TRawEvent& aRawEvent)
sl@0
  1440
	{
sl@0
  1441
	iPreviousPrimaryPointer = iPrimaryPointer;
sl@0
  1442
	
sl@0
  1443
	TRawEvent::TType type=aRawEvent.Type();
sl@0
  1444
	TInt pointerNumber = aRawEvent.PointerNumber();
sl@0
  1445
    
sl@0
  1446
#ifdef LOG_WSERV_EVENTS
sl@0
  1447
	RDebug::Printf("_WSEVENT_POINTER: TWsPointer::UpdatePrimaryPointer Current Primary pointer = %d",iPrimaryPointer);
sl@0
  1448
	for(TInt i=0; i< iMaxPointers; i++)
sl@0
  1449
		{
sl@0
  1450
		RDebug::Printf("_WSEVENT_POINTER: TWsPointer::UpdatePrimaryPointer Pointer Number= %d  State = %x XY(%d,%d)",iPointers[i].iNumber,iPointers[i].iState,iPointers[i].iPos.iX,iPointers[i].iPos.iY);
sl@0
  1451
		}
sl@0
  1452
#endif
sl@0
  1453
	
sl@0
  1454
	// If primary pointer is out of range, then the first pointer that will 
sl@0
  1455
	// start being detected (come back in range) will become primary.
sl@0
  1456
	if (iPointers[iPrimaryPointer].iState == EPointerStateOutOfRange)
sl@0
  1457
		{
sl@0
  1458
		if (type != TRawEvent::EPointer3DOutOfRange && iPointers[pointerNumber].iState == EPointerStateOutOfRange)
sl@0
  1459
			{
sl@0
  1460
			iPrimaryPointer = pointerNumber;
sl@0
  1461
#ifdef LOG_WSERV_EVENTS
sl@0
  1462
	        RDebug::Printf("_WSEVENT_POINTER: TWsPointer::UpdatePrimaryPointer New Primary pointer(OutRange) = %d",iPrimaryPointer);
sl@0
  1463
#endif
sl@0
  1464
			}
sl@0
  1465
		return;
sl@0
  1466
		}
sl@0
  1467
	
sl@0
  1468
	// if non-primary pointer sends EButton1Down event, and actual primary pointer
sl@0
  1469
	// is not down, then the pointer which has sent EButton1Down becomes primary.
sl@0
  1470
	if (type == TRawEvent::EButton1Down && 
sl@0
  1471
		iPointers[iPrimaryPointer].iState != EPointerStateDown)
sl@0
  1472
		{
sl@0
  1473
		iPrimaryPointer = pointerNumber;
sl@0
  1474
#ifdef LOG_WSERV_EVENTS
sl@0
  1475
        RDebug::Printf("_WSEVENT_POINTER: TWsPointer::UpdatePrimaryPointer New Primary pointer(ButtonDown) = %d",iPrimaryPointer);
sl@0
  1476
#endif
sl@0
  1477
		return;
sl@0
  1478
		}
sl@0
  1479
	}
sl@0
  1480
sl@0
  1481
/** Sets Z coordinate threshold values for TPointerEvent::EEnterCloseProximity 
sl@0
  1482
and TPointerEvent::EExitCloseProximity events.
sl@0
  1483
@return KErrNone if successful, 
sl@0
  1484
        KErrNotSupported if the device doesn't support threshold values,
sl@0
  1485
        KErrArgument if aEnterCloseProximityThreshold is less than aExitCloseProximityThreshold 
sl@0
  1486
@see RWsSession::SetCloseProximityThresholds which calls this method
sl@0
  1487
*/
sl@0
  1488
TInt TWsPointer::SetCloseProximityThresholds(TInt aEnterCloseProximityThreshold, TInt aExitCloseProximityThreshold)
sl@0
  1489
	{
sl@0
  1490
	if (aEnterCloseProximityThreshold < aExitCloseProximityThreshold)
sl@0
  1491
		{
sl@0
  1492
		return KErrArgument;
sl@0
  1493
		}
sl@0
  1494
	
sl@0
  1495
	TInt ret = HAL::Set(HALData::EPointer3DEnterCloseProximityThreshold, aEnterCloseProximityThreshold);
sl@0
  1496
	if (ret != KErrNone)
sl@0
  1497
		{
sl@0
  1498
		return ret;
sl@0
  1499
		}
sl@0
  1500
	
sl@0
  1501
	ret = HAL::Set(HALData::EPointer3DExitCloseProximityThreshold, aExitCloseProximityThreshold);
sl@0
  1502
	WS_ASSERT_DEBUG(ret == KErrNone, EWsPanicProxThresholdsInconsist);
sl@0
  1503
	if (ret != KErrNone)
sl@0
  1504
		{
sl@0
  1505
		HAL::Set(HALData::EPointer3DEnterCloseProximityThreshold, iEnterCloseProximityThreshold);
sl@0
  1506
		return ret;
sl@0
  1507
		}
sl@0
  1508
	
sl@0
  1509
	iEnterCloseProximityThreshold = aEnterCloseProximityThreshold;
sl@0
  1510
	iExitCloseProximityThreshold  = aExitCloseProximityThreshold; 
sl@0
  1511
	return KErrNone;
sl@0
  1512
	}
sl@0
  1513
sl@0
  1514
/**
sl@0
  1515
@return Z coordinate threshold value for TPointerEvent::EEnterCloseProximity events
sl@0
  1516
@see RWsSession::GetEnterCloseProximityThreshold which calls this method
sl@0
  1517
*/
sl@0
  1518
TInt TWsPointer::GetEnterCloseProximityThreshold()
sl@0
  1519
	{
sl@0
  1520
	return iEnterCloseProximityThreshold;
sl@0
  1521
	}
sl@0
  1522
sl@0
  1523
/**
sl@0
  1524
@return Z coordinate threshold value for TPointerEvent::EExitCloseProximity events
sl@0
  1525
@see RWsSession::GetExitCloseProximityThreshold which calls this method
sl@0
  1526
*/
sl@0
  1527
TInt TWsPointer::GetExitCloseProximityThreshold()
sl@0
  1528
	{
sl@0
  1529
	return iExitCloseProximityThreshold;
sl@0
  1530
	}
sl@0
  1531
sl@0
  1532
/** Sets Z coordinate threshold value for TPointerEvent::EEnterHighPressure and 
sl@0
  1533
TPointerEvent::EExitHighPressure events.
sl@0
  1534
@return KErrNone if successful, 
sl@0
  1535
        KErrNotSupported if the device doesn't support threshold values,
sl@0
  1536
        KErrArgument if aEnterHighPressureThreshold is less than aExitHighPressureThreshold 
sl@0
  1537
@see RWsSession::SetHighPressureThresholds which calls this method
sl@0
  1538
*/
sl@0
  1539
TInt TWsPointer::SetHighPressureThresholds(TInt aEnterHighPressureThreshold, TInt aExitHighPressureThreshold)
sl@0
  1540
	{
sl@0
  1541
	if (aEnterHighPressureThreshold < aExitHighPressureThreshold)
sl@0
  1542
		{
sl@0
  1543
		return KErrArgument;
sl@0
  1544
		}
sl@0
  1545
	
sl@0
  1546
	TInt ret = HAL::Set(HALData::EPointer3DEnterHighPressureThreshold, aEnterHighPressureThreshold);
sl@0
  1547
	if (ret != KErrNone)
sl@0
  1548
		{
sl@0
  1549
		return ret;
sl@0
  1550
		}
sl@0
  1551
	
sl@0
  1552
	ret = HAL::Set(HALData::EPointer3DExitHighPressureThreshold, aExitHighPressureThreshold);
sl@0
  1553
	WS_ASSERT_DEBUG(ret == KErrNone, EWsPanicPressThresholdsInconsist);
sl@0
  1554
	if (ret != KErrNone)
sl@0
  1555
		{
sl@0
  1556
		HAL::Set(HALData::EPointer3DEnterHighPressureThreshold, iEnterHighPressureThreshold);
sl@0
  1557
		return ret;
sl@0
  1558
		}
sl@0
  1559
	
sl@0
  1560
	iEnterHighPressureThreshold = aEnterHighPressureThreshold;
sl@0
  1561
	iExitHighPressureThreshold  = aExitHighPressureThreshold;
sl@0
  1562
	return KErrNone;
sl@0
  1563
	}
sl@0
  1564
sl@0
  1565
/**
sl@0
  1566
@return Z coordinate threshold value for TPointerEvent::EEnterHighPressure events
sl@0
  1567
@see RWsSession::GetEnterHighPressureThreshold which calls this method
sl@0
  1568
*/
sl@0
  1569
TInt TWsPointer::GetEnterHighPressureThreshold()
sl@0
  1570
	{
sl@0
  1571
	return iEnterHighPressureThreshold;
sl@0
  1572
	}
sl@0
  1573
sl@0
  1574
/**
sl@0
  1575
@return Z coordinate threshold value for TPointerEvent::EExitHighPressure events
sl@0
  1576
@see RWsSession::GetExitHighPressureThreshold which calls this method
sl@0
  1577
*/
sl@0
  1578
TInt TWsPointer::GetExitHighPressureThreshold()
sl@0
  1579
	{
sl@0
  1580
	return iExitHighPressureThreshold;
sl@0
  1581
	}
sl@0
  1582
sl@0
  1583
sl@0
  1584
/**
sl@0
  1585
This function is specific for capacitive touch screens, where user's finger is the pointer device. 
sl@0
  1586
Usability studies have shown that the user's perception of the location of the pointer hit is always 
sl@0
  1587
away from few pixels north of the actual hit centre as detected by the digitizer device. So, this function
sl@0
  1588
will shift all pointer events by a specified Y displacement.
sl@0
  1589
sl@0
  1590
@param aY Current y coordinate pointer position.
sl@0
  1591
 
sl@0
  1592
 */
sl@0
  1593
void TWsPointer::ShiftYCoordinate(TInt& aY)
sl@0
  1594
    {
sl@0
  1595
    WS_ASSERT_DEBUG(iYOffset>=0, EWsPanicInvalidPointerOffset);
sl@0
  1596
    if (aY >= iYOffset)
sl@0
  1597
        {
sl@0
  1598
        aY -=iYOffset;
sl@0
  1599
        }
sl@0
  1600
    else
sl@0
  1601
        {
sl@0
  1602
        aY=0;
sl@0
  1603
        }
sl@0
  1604
    }
sl@0
  1605
//
sl@0
  1606
CWsPointerTimer::CWsPointerTimer(MPointerTimerCallback& aPointerTimerCallback)
sl@0
  1607
: CTimer(EPointerRepeatPriority), iPointerTimerCallback(aPointerTimerCallback)
sl@0
  1608
	{}
sl@0
  1609
sl@0
  1610
void CWsPointerTimer::ConstructL()
sl@0
  1611
	{
sl@0
  1612
	CTimer::ConstructL();
sl@0
  1613
	CActiveScheduler::Add(this);
sl@0
  1614
	}
sl@0
  1615
sl@0
  1616
CWsPointerTimer* CWsPointerTimer::NewL(MPointerTimerCallback& aWsPointer)
sl@0
  1617
	{
sl@0
  1618
	CWsPointerTimer* self = new(ELeave) CWsPointerTimer(aWsPointer);
sl@0
  1619
	CleanupStack::PushL(self);
sl@0
  1620
	self->ConstructL();
sl@0
  1621
	CleanupStack::Pop(self);
sl@0
  1622
	return self;
sl@0
  1623
	}
sl@0
  1624
sl@0
  1625
void CWsPointerTimer::RunL()
sl@0
  1626
	{
sl@0
  1627
	User::ResetInactivityTime();
sl@0
  1628
	WS_ASSERT_DEBUG(iStatus.Int()==KErrNone, EWsPanicPointerRepeatTimerStatus);
sl@0
  1629
	iPointerTimerCallback.RepeatTimerCompleted();
sl@0
  1630
	}
sl@0
  1631
//
sl@0
  1632
sl@0
  1633
CWsPointerBuffer::~CWsPointerBuffer()
sl@0
  1634
	{
sl@0
  1635
	if (this == iCurrentBuffer)
sl@0
  1636
		{
sl@0
  1637
		// We're about to be destroyed - don't want to be pointed at any more.
sl@0
  1638
		iCurrentBuffer = NULL;
sl@0
  1639
		}
sl@0
  1640
	iList.Remove(*this);
sl@0
  1641
	}
sl@0
  1642
sl@0
  1643
void CWsPointerBuffer::ConnectL(CWsClientWindow* aWindow, TInt aMaxPoints, TUint aFlags)
sl@0
  1644
	{
sl@0
  1645
	CWsPointerBuffer* pb=NULL;
sl@0
  1646
	for(TSglQueIter<CWsPointerBuffer> iter(iList);(pb=iter++)!=NULL;)
sl@0
  1647
		{
sl@0
  1648
		if (pb->iWindow==aWindow)
sl@0
  1649
			{
sl@0
  1650
			User::Leave(KErrInUse);
sl@0
  1651
			}
sl@0
  1652
		}
sl@0
  1653
	CWsPointerBuffer* pbuf=new(ELeave) CWsPointerBuffer;
sl@0
  1654
	pbuf->iWindow=aWindow;
sl@0
  1655
	pbuf->iMaxPoints=aMaxPoints;
sl@0
  1656
	pbuf->iFlags=aFlags;
sl@0
  1657
	iList.AddFirst(*pbuf);
sl@0
  1658
	CleanupStack::PushL(pbuf);
sl@0
  1659
	AdjustMaxSizeL();
sl@0
  1660
	CleanupStack::Pop();
sl@0
  1661
	}
sl@0
  1662
sl@0
  1663
void CWsPointerBuffer::Disconnect(CWsClientWindow* aWindow)
sl@0
  1664
	{
sl@0
  1665
	CWsPointerBuffer* pb=NULL;
sl@0
  1666
	for(TSglQueIter<CWsPointerBuffer> iter(iList);(pb=iter++)!=NULL;)
sl@0
  1667
		{
sl@0
  1668
		if (pb->iWindow==aWindow)
sl@0
  1669
			{
sl@0
  1670
			delete pb; // Note that the destructor also sets iCurrentBuffer to NULL if it is pointing at pb
sl@0
  1671
			TRAP_IGNORE(AdjustMaxSizeL());	// Shouldn't fail, but doesn't matter if it does as we simply have a larger buffer than needed
sl@0
  1672
			break; // from for loop
sl@0
  1673
			}
sl@0
  1674
		}
sl@0
  1675
	}
sl@0
  1676
sl@0
  1677
void CWsPointerBuffer::Reset()
sl@0
  1678
	{
sl@0
  1679
	iSignalled=EFalse;
sl@0
  1680
	iPointerBuffer->Reset();
sl@0
  1681
	}
sl@0
  1682
sl@0
  1683
void CWsPointerBuffer::SignalBufferReady()
sl@0
  1684
	{
sl@0
  1685
	if (!iSignalled)
sl@0
  1686
		{
sl@0
  1687
		if (iCurrentBuffer && iCurrentBuffer->iWindow->QueueEvent(EEventPointerBufferReady))
sl@0
  1688
			{
sl@0
  1689
			iSignalled=ETrue;
sl@0
  1690
			}
sl@0
  1691
		}
sl@0
  1692
	}
sl@0
  1693
sl@0
  1694
void CWsPointerBuffer::PointerEvent(CWsClientWindow* aWindow,const TPoint &aPoint)
sl@0
  1695
	{
sl@0
  1696
	if (iCurrentBuffer==NULL || aWindow!=iCurrentBuffer->iWindow)
sl@0
  1697
		{
sl@0
  1698
		Reset();
sl@0
  1699
		CWsPointerBuffer* pb=NULL;
sl@0
  1700
		for(TSglQueIter<CWsPointerBuffer> iter(iList);(pb=iter++)!=NULL;)
sl@0
  1701
			{
sl@0
  1702
			if (pb->iWindow==aWindow)
sl@0
  1703
				{
sl@0
  1704
				iCurrentBuffer=pb;
sl@0
  1705
				break; // from for loop
sl@0
  1706
				}
sl@0
  1707
			}
sl@0
  1708
		}
sl@0
  1709
	iPointerBuffer->Add(&aPoint);
sl@0
  1710
	SignalBufferReady();
sl@0
  1711
	}
sl@0
  1712
sl@0
  1713
void CWsPointerBuffer::RetrievePointerMoveBuffer(CWsClientWindow* aWindow,TInt aMaxPoints)
sl@0
  1714
	{
sl@0
  1715
	enum {KPointerMoveBufferSize=32};	// Puts 256 bytes on the stack
sl@0
  1716
	if (iCurrentBuffer && aWindow==iCurrentBuffer->iWindow)
sl@0
  1717
		{
sl@0
  1718
		iSignalled=EFalse;
sl@0
  1719
		TInt max=Min(aMaxPoints,iPointerBuffer->Count());
sl@0
  1720
		TInt buflen=0;
sl@0
  1721
		aWindow->WsOwner()->SetReply(max);
sl@0
  1722
		TPoint point;
sl@0
  1723
		TBuf8<KPointerMoveBufferSize*sizeof(TPoint)> pnts;
sl@0
  1724
		for(TInt index=0;index<max;index++)
sl@0
  1725
			{
sl@0
  1726
			iPointerBuffer->Remove(&point);
sl@0
  1727
			pnts.Append((TUint8 *)&point,sizeof(TPoint));
sl@0
  1728
			buflen++;
sl@0
  1729
			if (buflen==KPointerMoveBufferSize)
sl@0
  1730
				{
sl@0
  1731
				CWsClient::ReplyBuf(pnts);
sl@0
  1732
				pnts.Zero();
sl@0
  1733
				buflen=0;
sl@0
  1734
				}
sl@0
  1735
			}
sl@0
  1736
		if (buflen>0)
sl@0
  1737
			{
sl@0
  1738
			CWsClient::ReplyBuf(pnts);
sl@0
  1739
			}
sl@0
  1740
		if (iPointerBuffer->Count())
sl@0
  1741
			{
sl@0
  1742
			SignalBufferReady();
sl@0
  1743
			}
sl@0
  1744
		}
sl@0
  1745
	}
sl@0
  1746
sl@0
  1747
void CWsPointerBuffer::DiscardPointerMoveBuffer(TUint aHandle)
sl@0
  1748
	{
sl@0
  1749
	if (iCurrentBuffer && aHandle==iCurrentBuffer->iWindow->ClientHandle())
sl@0
  1750
		{
sl@0
  1751
		Reset();
sl@0
  1752
		}
sl@0
  1753
	}
sl@0
  1754
sl@0
  1755
void CWsPointerBuffer::DiscardPointerMoveBuffer(CWsClientWindow* aWindow)
sl@0
  1756
	{
sl@0
  1757
	if (iCurrentBuffer && aWindow==iCurrentBuffer->iWindow)
sl@0
  1758
		{
sl@0
  1759
		Reset();
sl@0
  1760
		}
sl@0
  1761
	}
sl@0
  1762
sl@0
  1763
void CWsPointerBuffer::AdjustMaxSizeL()
sl@0
  1764
	{
sl@0
  1765
	TInt max=0;
sl@0
  1766
	CWsPointerBuffer* pb=NULL;
sl@0
  1767
	for(TSglQueIter<CWsPointerBuffer> iter(iList);(pb=iter++)!=NULL;)
sl@0
  1768
		{
sl@0
  1769
		if (pb->iMaxPoints>max)
sl@0
  1770
			{
sl@0
  1771
			max=pb->iMaxPoints;
sl@0
  1772
			}
sl@0
  1773
		}
sl@0
  1774
	if (max==0)
sl@0
  1775
		{
sl@0
  1776
		delete iPointerBuffer;
sl@0
  1777
		iPointerBuffer=NULL;
sl@0
  1778
		}
sl@0
  1779
	else if (!iPointerBuffer)
sl@0
  1780
		{
sl@0
  1781
		CCirBuf<TPoint>* pointerBuffer=new(ELeave) CCirBuf<TPoint>;
sl@0
  1782
		CleanupStack::PushL(pointerBuffer);
sl@0
  1783
		pointerBuffer->SetLengthL(max);
sl@0
  1784
		CleanupStack::Pop();
sl@0
  1785
		iPointerBuffer=pointerBuffer;
sl@0
  1786
		}
sl@0
  1787
	else
sl@0
  1788
		{
sl@0
  1789
		iPointerBuffer->SetLengthL(max);
sl@0
  1790
		}
sl@0
  1791
	}