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