windowing/windowserver/nonnga/SERVER/POINTER.CPP
changeset 0 5d03bc08d59c
child 19 bbf46f59e123
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 "graphics/pointereventdata.h"
       
    31 
       
    32 TPoint WsPointer::iCurrentPos;
       
    33 TBool WsPointer::iPointerDown;
       
    34 const CWsWindow *WsPointer::iCurrentWindow;
       
    35 const CWsWindow *WsPointer::iActualWinPointerIsOver;
       
    36 const CWsWindow *WsPointer::iGrabWindow;
       
    37 const CWsWindow *WsPointer::iPrevClickWindow;
       
    38 TPoint WsPointer::iPrevClickPos;
       
    39 TTime WsPointer::iPrevClickTime;
       
    40 TPointerEvent::TType WsPointer::iPrevClickEventType;
       
    41 TTimeIntervalMicroSeconds32 WsPointer::iDoubleClickMaxInterval;
       
    42 TInt WsPointer::iDoubleClickMaxDistance;
       
    43 CWsPointerCursor *WsPointer::iCursorSprite;
       
    44 CWsPointerTimer *WsPointer::iRepeatTimer=NULL;
       
    45 TPointerCursorMode WsPointer::iPointerCursorMode=EPointerCursorNormal;
       
    46 CWsWindow *WsPointer::iRepeatWindow=NULL;
       
    47 TRect WsPointer::iRepeatRect;
       
    48 TXYInputType WsPointer::iXyInputType;
       
    49 TUint WsPointer::iLastUnmatchedDown1;
       
    50 TUint WsPointer::iLastUnmatchedDown2;
       
    51 TUint WsPointer::iLastUnmatchedDown3;
       
    52 TBool WsPointer::iTimerQueued;
       
    53 TBool WsPointer::iUpdateRequired;
       
    54 CPeriodic *WsPointer::iPeriodicTimer;
       
    55 CWsRootWindow* WsPointer::iRootWindow;
       
    56 
       
    57 TBool CWsPointerBuffer::iSignalled=EFalse;
       
    58 CWsPointerBuffer *CWsPointerBuffer::iCurrentBuffer=NULL;
       
    59 CCirBuf<TPoint> *CWsPointerBuffer::iPointerBuffer=NULL;
       
    60 TSglQue<CWsPointerBuffer> CWsPointerBuffer::iList(_FOFF(CWsPointerBuffer,iQue));
       
    61 
       
    62 void WsPointer::InitStaticsL()
       
    63 	{
       
    64 	iRepeatTimer=new(ELeave) CWsPointerTimer();
       
    65 	iRepeatTimer->ConstructL();
       
    66 	TMachineInfoV1Buf machineInfo;
       
    67 	UserHal::MachineInfo(machineInfo);
       
    68 	iXyInputType=machineInfo().iXYInputType;
       
    69 
       
    70 	iRootWindow = CWsTop::Screen()->RootWindow();
       
    71 
       
    72 	iCurrentWindow=MovesAvailable() ? iRootWindow : NULL;
       
    73 	iPeriodicTimer=CPeriodic::NewL(EPointerCursorPriority);
       
    74 	}
       
    75 
       
    76 void WsPointer::DeleteStatics()
       
    77 	{
       
    78 	SetPointerCursorMode(EPointerCursorNone);
       
    79 	UpdatePointerCursor();
       
    80 	delete iRepeatTimer;
       
    81 	delete iPeriodicTimer;
       
    82 	}
       
    83 
       
    84 void WsPointer::SetPointerCursorPos(TPoint aPos)
       
    85 	{
       
    86 	RestrictPos(aPos,EFalse);
       
    87 	iCurrentPos=aPos;
       
    88 	ReLogCurrentWindow();
       
    89 	UpdatePointerCursor();
       
    90 	}
       
    91 
       
    92 void WsPointer::SendEnterExitEvent(TEventCode aType)
       
    93 	{
       
    94 	if (iCurrentWindow
       
    95 		&& !(iCurrentWindow->PointerFilter()&EPointerFilterEnterExit)
       
    96 		&& !iCurrentWindow->ShutDownInProgress())
       
    97 		iCurrentWindow->QueueEvent(aType);
       
    98 	}
       
    99 
       
   100 void WsPointer::SetCurrentWindow(const CWsWindow *aWin)
       
   101 	{
       
   102 	if (aWin!=iCurrentWindow)
       
   103 		{
       
   104 		SendEnterExitEvent(EEventPointerExit);
       
   105 		iCurrentWindow=aWin;
       
   106 		SendEnterExitEvent(EEventPointerEnter);
       
   107 		}
       
   108 	}
       
   109 
       
   110 void WsPointer::ReLogCurrentWindow(TPoint &aPos, TPoint &aParentPos, const CWsWindowGroup *aForceInGroup)
       
   111 //
       
   112 // Relog the current pointer window, can be used to set a new iCurrentPos or when the window layout has changed.
       
   113 // Sets iCurrentPos to aPos and modifys aPos to the relative position within the new current window
       
   114 //
       
   115 	{
       
   116 	if (iRootWindow)
       
   117 		SetCurrentWindow(iRootWindow->PointerWindow(iCurrentPos,&aPos,&aParentPos,iGrabWindow,iActualWinPointerIsOver
       
   118 																										,aForceInGroup));
       
   119 	else
       
   120 		iCurrentWindow=NULL;
       
   121 	}
       
   122 
       
   123 void WsPointer::ReLogCurrentWindow()
       
   124 //
       
   125 // Relog the current pointer window when the window layout has changed.
       
   126 //
       
   127 	{
       
   128 	if (iCurrentWindow)	// NULL iCurrentWindow means pointer is up so don't relog it
       
   129 		SetCurrentWindow(iRootWindow->PointerWindow(iCurrentPos,NULL,NULL,iGrabWindow,iActualWinPointerIsOver,NULL));
       
   130 	}
       
   131 
       
   132 void WsPointer::ReLogWindow(const CWsWindow *aWin)
       
   133 //
       
   134 // Called when a window has changed it's filter state, will trigger a 'Enter' message if the window
       
   135 // is the current window
       
   136 //
       
   137 	{
       
   138 	if (aWin==iCurrentWindow)
       
   139 		SendEnterExitEvent(EEventPointerEnter);
       
   140 	}
       
   141 
       
   142 void WsPointer::UnmatchedDownPurged(TPointerEvent::TType aPointerType, TUint aHandle)
       
   143 	{
       
   144 	if (aPointerType==TPointerEvent::EButton1Up && iGrabWindow && iGrabWindow->ClientHandle()==aHandle)
       
   145 		{
       
   146 		if (iGrabWindow && iGrabWindow->ClientHandle()==aHandle)
       
   147 			iGrabWindow=NULL;
       
   148 		if (iRepeatWindow && iRepeatWindow->ClientHandle()==aHandle)
       
   149 			CancelPointerRepeatEventRequest();
       
   150 		}
       
   151 	switch(aPointerType)
       
   152 		{
       
   153 		case TPointerEvent::EButton1Up:
       
   154 			iLastUnmatchedDown1=aHandle;
       
   155 			break;
       
   156 		case TPointerEvent::EButton2Up:
       
   157 			iLastUnmatchedDown2=aHandle;
       
   158 			break;
       
   159 		case TPointerEvent::EButton3Up:
       
   160 			iLastUnmatchedDown3=aHandle;
       
   161 			break;
       
   162 		default:;
       
   163 		}
       
   164 	}
       
   165 
       
   166 void WsPointer::WindowDisconected(const CWsWindow *deletedWindow)
       
   167 	{
       
   168 	if (iRepeatWindow==deletedWindow)
       
   169 		CancelPointerRepeatEventRequest();
       
   170 	if (iGrabWindow==deletedWindow)
       
   171 		iGrabWindow=NULL;
       
   172 	if (iCurrentWindow==deletedWindow)
       
   173 		{
       
   174 		ReLogCurrentWindow();
       
   175 		UpdatePointerCursor();
       
   176 		}
       
   177 	}
       
   178 
       
   179 TEventQueueWalkRet RemovePointerUpFunc(TAny *aHandle, TWsEvent *aEvent)
       
   180 //
       
   181 // Callback function pointer for up event remove event queue walk
       
   182 //
       
   183 	{
       
   184 	if (aEvent->Type()==EEventPointer && aEvent->Pointer()->iType==TPointerEvent::EButton1Up && (*(TUint *)aHandle)==aEvent->Handle())
       
   185 		return(EEventQueueWalkDeleteEvent);
       
   186 	return(EEventQueueWalkOk);
       
   187 	}
       
   188 
       
   189 void WsPointer::ClaimGrab(const CWsWindow *aWindow,TBool aSendUpEvent)
       
   190 //
       
   191 // If the pointer is down claim grab in aWindow as though the down event had gone to this window
       
   192 // also send an up event to the window (if any) that would receive it the pointer was released now
       
   193 //
       
   194 	{
       
   195 	TInt modState=TWindowServerEvent::GetModifierState();
       
   196 	TWsEvent event;
       
   197 	TPointerEvent& pointerEvent=*event.Pointer();
       
   198 	pointerEvent.iModifiers=modState;
       
   199 	pointerEvent.iPosition=iCurrentPos;
       
   200 	if (iPointerDown)
       
   201 		{
       
   202 		if (iCurrentWindow!=aWindow)
       
   203 			{
       
   204 			if (aSendUpEvent)
       
   205 				ProcessEvent(TPointerEvent::EButton1Up,iCurrentPos,modState,NULL,EFalse);
       
   206 			else // If up event already in queue purge it
       
   207 				{
       
   208 				TUint handle=iCurrentWindow->ClientHandle();
       
   209 				iCurrentWindow->EventQueue()->WalkEventQueue(&RemovePointerUpFunc,&handle);
       
   210 				}
       
   211 			iPointerDown=ETrue;
       
   212 			if (aWindow->HasPointerGrab())
       
   213 				iGrabWindow=aWindow;
       
   214 			ReLogCurrentWindow(pointerEvent.iPosition,pointerEvent.iParentPosition,NULL);
       
   215 			pointerEvent.iType=TPointerEvent::EDrag;
       
   216 			ProcessPointerEvent(event);
       
   217 			}
       
   218 		}
       
   219 	else
       
   220 		{
       
   221 		const CWsWindow *current=iCurrentWindow;
       
   222 		iCurrentWindow=aWindow;
       
   223 		WS_ASSERT_DEBUG(iGrabWindow==NULL, EWsPanicPointerClaimGrab);
       
   224 		iGrabWindow=aWindow;	// Force the up event to be sent to aWindow
       
   225 		ReLogCurrentWindow(pointerEvent.iPosition,pointerEvent.iParentPosition,NULL);
       
   226 		pointerEvent.iType=TPointerEvent::EButton1Up;
       
   227 		ProcessPointerEvent(event);
       
   228 		iGrabWindow=NULL;
       
   229 		iCurrentWindow=current;
       
   230 		}
       
   231 	}
       
   232 
       
   233 TBool WsPointer::CheckDownEventPurged(TPointerEvent::TType aType)
       
   234 	{
       
   235 	switch(aType)
       
   236 		{
       
   237 		TUint lastUnmatchedDown;
       
   238 		case TPointerEvent::EButton1Up:
       
   239 			lastUnmatchedDown=iLastUnmatchedDown1;
       
   240 			iLastUnmatchedDown1=0;
       
   241 			goto lastUnmatchedDownCheck;
       
   242 		case TPointerEvent::EButton2Up:
       
   243 			lastUnmatchedDown=iLastUnmatchedDown2;
       
   244 			iLastUnmatchedDown2=0;
       
   245 			goto lastUnmatchedDownCheck;
       
   246 		case TPointerEvent::EButton3Up:
       
   247 			lastUnmatchedDown=iLastUnmatchedDown3;
       
   248 			iLastUnmatchedDown3=0;
       
   249 lastUnmatchedDownCheck:
       
   250 		if (lastUnmatchedDown==iCurrentWindow->ClientHandle())
       
   251 			return ETrue; // Don't deliver the event as we've already thrown away the down
       
   252 		default:		//Should never get to default
       
   253 			break;
       
   254 		}
       
   255 	return EFalse;
       
   256 	}
       
   257 
       
   258 TBool WsPointer::QueuePointerEvent(const CWsWindow *aWindow, TWsEvent &aEvent)
       
   259 	{
       
   260 	CWsClient *client=aWindow->WsOwner();
       
   261 	if (client)
       
   262 		{
       
   263 		CEventQueue *queue=aWindow->EventQueue();
       
   264 		aEvent.SetHandle(aWindow->ClientHandle());
       
   265 		if (aEvent.Handle()!=0)
       
   266 			{
       
   267 			if (aEvent.Pointer()->iType==TPointerEvent::EMove || aEvent.Pointer()->iType==TPointerEvent::EDrag)
       
   268 				{
       
   269 				queue->Wait();
       
   270 				const TWsEvent *prev=queue->PeekLastEvent();
       
   271 				if (prev!=NULL && prev->Type()==EEventPointer && prev->Handle()==aEvent.Handle() && prev->Pointer()->iType==aEvent.Pointer()->iType)
       
   272 					{
       
   273 					queue->UpdateLastEvent(aEvent);
       
   274 					return EFalse;
       
   275 					}
       
   276 				queue->Signal();
       
   277 				}
       
   278 			TWservEventPriorities priority=EEventPriorityLow;
       
   279 			switch (aEvent.Pointer()->iType)
       
   280 				{
       
   281 				case TPointerEvent::EButton1Up:
       
   282 				case TPointerEvent::EButton2Up:
       
   283 				case TPointerEvent::EButton3Up:
       
   284 					if (CheckDownEventPurged(aEvent.Pointer()->iType))
       
   285 						return ETrue;
       
   286 					if (queue->CheckRoom())
       
   287 						{
       
   288 						if (CheckDownEventPurged(aEvent.Pointer()->iType))
       
   289 							return ETrue;
       
   290 						} 
       
   291 					/*Fall Through if an event was not purged*/
       
   292 				case TPointerEvent::EButton1Down:
       
   293 				case TPointerEvent::EButton2Down:
       
   294 				case TPointerEvent::EButton3Down:
       
   295 					priority=EEventPriorityHigh;
       
   296 					break;
       
   297 				default:;
       
   298 				}
       
   299 			queue->QueueEvent(aEvent,priority);
       
   300 			}
       
   301 		}
       
   302 	return EFalse;
       
   303 	}
       
   304 
       
   305 void WsPointer::ProcessForegroundCheck()
       
   306 	{
       
   307 	CWsWindowGroup *group=iCurrentWindow->WinGroup();
       
   308 	if (group->iFlags&CWsWindowGroup::EGroupFlagAutoForeground)
       
   309 		group->SetOrdinalPosition(0);
       
   310 	}
       
   311 
       
   312 void WsPointer::ProcessPointerEvent(TWsEvent& aEvent)
       
   313 	{
       
   314 	if (iCurrentWindow && iCurrentWindow!=iRootWindow)
       
   315 		{
       
   316 		aEvent.SetType(EEventPointer);
       
   317 		aEvent.SetTimeNow();
       
   318 		TPointerEvent::TType type=aEvent.Pointer()->iType;
       
   319 		switch(type)
       
   320 			{
       
   321 			//TUint lastUnmatchedDown;
       
   322 			case TPointerEvent::EButton1Down:
       
   323 				ProcessForegroundCheck(); 
       
   324 				/*Fall Through*/
       
   325 			case TPointerEvent::EButton2Down:
       
   326 			case TPointerEvent::EButton3Down:
       
   327 				{
       
   328 				TPoint& pos=aEvent.Pointer()->iPosition;
       
   329 				if (iCurrentWindow==iPrevClickWindow &&
       
   330 					type==iPrevClickEventType &&
       
   331 					(Abs(pos.iX-iPrevClickPos.iX)+Abs(pos.iY-iPrevClickPos.iY))<iDoubleClickMaxDistance &&
       
   332 					aEvent.Time()<(iPrevClickTime+iDoubleClickMaxInterval))
       
   333 					{
       
   334 					aEvent.Pointer()->iModifiers|=EModifierDoubleClick;
       
   335 					iPrevClickWindow=NULL;	// Set to NULL to block a double double click
       
   336 					}
       
   337 				else
       
   338 					iPrevClickWindow=iCurrentWindow;
       
   339 				iPrevClickEventType=type;
       
   340 				iPrevClickPos=pos;
       
   341 				iPrevClickTime=aEvent.Time();
       
   342 				}
       
   343 				break;
       
   344 			default:
       
   345 				break;
       
   346 			}
       
   347 		if (iRepeatWindow)
       
   348 			{
       
   349 			if (PointerEventRepeatCheck(&aEvent, iCurrentWindow->ClientHandle()))
       
   350 				return;
       
   351 			CancelPointerRepeatEventRequest();
       
   352 			}
       
   353 		if (QueuePointerEvent(iCurrentWindow, aEvent))
       
   354 			return;
       
   355 		if (iCurrentWindow->DragDropCapture())
       
   356 			{
       
   357 			aEvent.SetType(EEventDragDrop);
       
   358 			QueuePointerEvent(iActualWinPointerIsOver, aEvent);
       
   359 			}
       
   360 		}
       
   361 	}
       
   362 
       
   363 TInt PointerTimerCallBack(TAny *)
       
   364 	{
       
   365 	WsPointer::TimerExpired();
       
   366 	return(KErrNone);
       
   367 	}
       
   368 
       
   369 void WsPointer::RestrictPos(TPoint& aPos,TBool aWithinDrawableArea/*=ETrue*/)
       
   370 	{
       
   371 	CScreen* screen = iRootWindow->Screen();
       
   372 	WS_ASSERT_DEBUG(screen->IsValidScreenSizeMode(screen->ScreenSizeMode()), EWsPanicInvalidScreenSizeMode);
       
   373 #if defined(__WINS__)
       
   374 	if (aWithinDrawableArea)
       
   375 		{
       
   376 		if (!DeltaMouse() && !TRect(screen->DrawableArea()).Contains(aPos))
       
   377 			{
       
   378 			return;			//Not in the drawable area so user may be trying to click on facia button.
       
   379 			}
       
   380 		}
       
   381 #endif
       
   382 	TRect validRect=screen->GetPointerCursorArea(screen->ScreenSizeMode());
       
   383 	if (aPos.iX<validRect.iTl.iX)
       
   384 		aPos.iX=validRect.iTl.iX;
       
   385 	else if (aPos.iX>=validRect.iBr.iX)
       
   386 		aPos.iX=validRect.iBr.iX-1;
       
   387 	if (aPos.iY<validRect.iTl.iY)
       
   388 		aPos.iY=validRect.iTl.iY;
       
   389 	else if (aPos.iY>=validRect.iBr.iY)
       
   390 		aPos.iY=validRect.iBr.iY-1;
       
   391 	}
       
   392 
       
   393 #if defined(__WINS__)
       
   394 TBool WsPointer::PreProcessEvent(TRawEvent &aRawEvent,TBool aFromHardware/*=EFlase*/)
       
   395 #else
       
   396 TBool WsPointer::PreProcessEvent(TRawEvent &aRawEvent)
       
   397 #endif
       
   398 	{
       
   399 #if defined(__WINS__)
       
   400 	WS_ASSERT_DEBUG(TRawEvent::EPointerMove==1, EWsPanicRawEventsTypeChanged);
       
   401 	WS_ASSERT_DEBUG(TRawEvent::EPointerMove+1==TRawEvent::EPointerSwitchOn, EWsPanicRawEventsTypeChanged);
       
   402 	WS_ASSERT_DEBUG(TRawEvent::EPointerSwitchOn+8==TRawEvent::EButton1Down, EWsPanicRawEventsTypeChanged);
       
   403 	WS_ASSERT_DEBUG(TRawEvent::EButton1Down+5==TRawEvent::EButton3Up, EWsPanicRawEventsTypeChanged);
       
   404 #endif
       
   405 	TRawEvent::TType type=aRawEvent.Type();
       
   406 	if (type<TRawEvent::EPointerMove || (type>TRawEvent::EPointerSwitchOn && type<TRawEvent::EButton1Down)
       
   407 																						|| type>TRawEvent::EButton3Up)
       
   408 		return ETrue;
       
   409 	if (!XyInput())
       
   410 		return EFalse;
       
   411 	TPoint xy=aRawEvent.Pos();
       
   412 	if (DeltaMouse())
       
   413 		{
       
   414 	#if defined(__WINS__)
       
   415 		if (aFromHardware)
       
   416 			return EFalse;
       
   417 	#endif
       
   418 		if (type==TRawEvent::EPointerMove)
       
   419 			{
       
   420 			xy+=iCurrentPos;
       
   421 			RestrictPos(xy);
       
   422 			}
       
   423 		else
       
   424 			xy=iCurrentPos;
       
   425 		}
       
   426 	else
       
   427 		{
       
   428 		CScreen* screen=iRootWindow->Screen();
       
   429 	#if !defined(__WINS__)
       
   430 		TSize screenSize=screen->ScreenDevice()->SizeInPixels()-TSize(1,1);             //This is in the current rotation
       
   431 		switch (screen->Orientation())
       
   432 			{
       
   433 			case CFbsBitGc::EGraphicsOrientationRotated90:
       
   434 				xy.SetXY(xy.iY,screenSize.iHeight-xy.iX);
       
   435 				break;
       
   436 			case CFbsBitGc::EGraphicsOrientationRotated180:
       
   437 				xy=-(xy-screenSize);
       
   438 				break;
       
   439 			case CFbsBitGc::EGraphicsOrientationRotated270:
       
   440 				xy.SetXY(screenSize.iWidth-xy.iY,xy.iX);
       
   441 				break;
       
   442 			default:;		//To stop warning
       
   443 			}
       
   444 	#endif
       
   445 		// Move the raw event position by shifting it by Origin and scale
       
   446 		xy=screen->PhysicalToLogical(xy);
       
   447 		RestrictPos(xy);
       
   448 		}
       
   449 	aRawEvent.Set(type,xy.iX,xy.iY);
       
   450 	return ETrue;
       
   451 	}
       
   452 
       
   453 void WsPointer::ProcessEvent(TPointerEvent::TType aType, const TPoint &aPos, TUint aModifiers
       
   454 																				,const CWsWindowGroup *aForceInGroup,TBool aNatural)
       
   455 	{
       
   456 	iCurrentPos=aPos;
       
   457 	if (aType==TPointerEvent::EMove && !MovesAvailable() && !iPointerDown)
       
   458 		return;
       
   459 	TPoint pos(iCurrentPos);	// We need a non-const TPoint for 'ReLogCurrentWindow'
       
   460 	TPoint parPos;
       
   461 	ReLogCurrentWindow(pos,parPos,aForceInGroup);
       
   462 	TWsEvent event;
       
   463 	TPointerEvent& pointerEvent=*event.Pointer();
       
   464 	pointerEvent.iModifiers=aModifiers;
       
   465 	pointerEvent.iPosition=pos;
       
   466 	pointerEvent.iParentPosition=parPos;
       
   467 	switch(aType)
       
   468 		{
       
   469 		case TPointerEvent::EButton1Down:
       
   470 			iPointerDown=ETrue;
       
   471 			if (iGrabWindow==NULL && iCurrentWindow->HasPointerGrab())
       
   472 				iGrabWindow=iCurrentWindow;
       
   473 			if (!MovesAvailable() && iCurrentWindow->PointerFilter()&EPointerGenerateSimulatedMove)
       
   474 				{
       
   475 				pointerEvent.iType=TPointerEvent::EMove;
       
   476 				ProcessEvent(event);
       
   477 				}
       
   478 			break;
       
   479 		case TPointerEvent::EButton1Up:
       
   480 			iPointerDown=EFalse;
       
   481 			iGrabWindow=NULL;
       
   482 			break;
       
   483 		case TPointerEvent::EMove:
       
   484 			if (iPointerDown)
       
   485 				aType=TPointerEvent::EDrag;
       
   486 			break;
       
   487 		default:;
       
   488 		}
       
   489 	pointerEvent.iType=aType;
       
   490 	if (aNatural && CClick::IsHandler())
       
   491 		{
       
   492 		CClick::PointerEvent(iCurrentPos,pointerEvent);
       
   493 		TPointerEventData params;
       
   494 		params.iVersion=0;
       
   495 		params.iCurrentPos=iCurrentPos;
       
   496 		params.iPointerEvent.iType 		= pointerEvent.iType;
       
   497 		params.iPointerEvent.iModifiers = pointerEvent.iModifiers;
       
   498 		params.iPointerEvent.iPosition  = pointerEvent.iPosition;
       
   499 		params.iPointerEvent.iParentPosition = pointerEvent.iParentPosition;
       
   500 		params.iClientHandle=iCurrentWindow->ClientHandle();
       
   501 		params.iWindowOrigin=iCurrentWindow->Origin();
       
   502 		CWsWindowGroup* groupWin=iCurrentWindow->WinGroup();
       
   503 		params.iWindowGroupId=groupWin ? groupWin->Identifier() : 0;
       
   504 		params.iSource=TPointerEventData::EUnspecified;
       
   505 		CClick::OtherEvent(EEventPointer,&params);
       
   506 		}
       
   507 	ProcessEvent(event);
       
   508 	}
       
   509 
       
   510 void WsPointer::ProcessEvent(TWsEvent& aEvent)
       
   511 	{
       
   512 	TUint filter=iCurrentWindow->PointerFilter();
       
   513 	TPointerEvent::TType type=aEvent.Pointer()->iType;
       
   514 	if ((type!=TPointerEvent::EMove || !(filter&EPointerFilterMove)) &&
       
   515 		 (type!=TPointerEvent::EDrag || !(filter&EPointerFilterDrag)))
       
   516 		{
       
   517 		TPoint pos=aEvent.Pointer()->iPosition;
       
   518 		if ((type==TPointerEvent::EMove || type==TPointerEvent::EDrag) && iCurrentWindow->UsingPointerBuffer())
       
   519 			CWsPointerBuffer::PointerEvent((CWsClientWindow *)iCurrentWindow,pos);
       
   520 		else if (!WsKeyboardEmulator::PointerEvent(type,pos,iCurrentWindow->PointerKeyList()))
       
   521 			ProcessPointerEvent(aEvent);
       
   522 		}
       
   523 	if (!MovesAvailable() && (type==TPointerEvent::EButton1Up || type==TPointerEvent::ESwitchOn))
       
   524 		iCurrentWindow=NULL;
       
   525 	PointerCursorUpdateCheck();
       
   526 	}
       
   527 
       
   528 void WsPointer::TimerExpired()
       
   529 	{
       
   530 	WS_ASSERT_DEBUG(iTimerQueued, EWsPanicPointerTimer);
       
   531 	if (iUpdateRequired)
       
   532 		{
       
   533 		UpdatePointerCursor();
       
   534 		iUpdateRequired=EFalse;
       
   535 		}
       
   536 	else
       
   537 		{
       
   538 		iTimerQueued=EFalse;
       
   539 		iPeriodicTimer->Cancel();
       
   540 		}
       
   541 	}
       
   542 
       
   543 void WsPointer::GetDoubleClickSettings(TTimeIntervalMicroSeconds32 &aTime, TInt &aDistance)
       
   544 	{
       
   545 	aTime=iDoubleClickMaxInterval;
       
   546 	aDistance=iDoubleClickMaxDistance;
       
   547 	}
       
   548 
       
   549 void WsPointer::SetDoubleClick(const TTimeIntervalMicroSeconds32 &aTime, TInt aDistance)
       
   550 	{
       
   551 	iDoubleClickMaxInterval=aTime;
       
   552 	iDoubleClickMaxDistance=aDistance;
       
   553 	}
       
   554 
       
   555 void WsPointer::PointerCursorUpdateCheck()
       
   556 	{
       
   557 	CWsPointerCursor *sprite=CalculatePointerCursor();
       
   558 	if (iCursorSprite || sprite)	// If there either was, or is a pointer cursor we need an update
       
   559 		{
       
   560 		if (!iTimerQueued)
       
   561 			{
       
   562 			UpdatePointerCursorTo(sprite);
       
   563 			iPeriodicTimer->Start(TTimeIntervalMicroSeconds32(EPointerUpdateGapInMicroSeconds),
       
   564 									TTimeIntervalMicroSeconds32(EPointerUpdateGapInMicroSeconds),
       
   565 									  TCallBack(PointerTimerCallBack,NULL));
       
   566 			iTimerQueued=ETrue;
       
   567 			}
       
   568 		else
       
   569 			iUpdateRequired=ETrue;
       
   570 		}
       
   571 	}
       
   572 
       
   573 void WsPointer::UpdatePointerCursor()
       
   574 	{
       
   575 //__PROFILE_START(3);
       
   576 	CWsPointerCursor *sprite=CalculatePointerCursor();
       
   577 	UpdatePointerCursorTo(sprite);
       
   578 //__PROFILE_END(3);
       
   579 	}
       
   580 
       
   581 void WsPointer::UpdatePointerCursorTo(CWsPointerCursor* aNewCursor)
       
   582 	{
       
   583 	CScreen* screen=NULL;
       
   584 	if (iCursorSprite!=aNewCursor)
       
   585 		{
       
   586 		if (iCursorSprite)
       
   587 			{
       
   588 			iCursorSprite->Deactivate();
       
   589 			screen=iCursorSprite->Screen();		//This will need changing ##
       
   590 			}
       
   591 		iCursorSprite=aNewCursor;
       
   592 		if (iCursorSprite)
       
   593 			{
       
   594 			iCursorSprite->SetPos(iCurrentPos);
       
   595 			iCursorSprite->Activate();
       
   596 			}
       
   597 		goto Update;
       
   598 		}
       
   599 	else if (iCursorSprite)
       
   600 		{
       
   601 		iCursorSprite->SetPos(iCurrentPos);
       
   602 	Update:
       
   603 		if (!screen)
       
   604 			screen=iCursorSprite->Screen();
       
   605 		screen->Update();
       
   606 		}
       
   607 	}
       
   608 
       
   609 CWsPointerCursor* WsPointer::CalculatePointerCursor()
       
   610 	{
       
   611 	CWsPointerCursor *sprite=NULL;
       
   612 	if (iCurrentWindow && (iPointerCursorMode==EPointerCursorNormal || iPointerCursorMode==EPointerCursorWindow))
       
   613 		{
       
   614 		const CWsWindowBase* window=iCurrentWindow;
       
   615 		do	{
       
   616 			sprite=window->PointerCursor();
       
   617 			if (window->WinType()!=EWinTypeClient)
       
   618 				break;
       
   619 			window=window->BaseParent();
       
   620 			} while (!sprite);
       
   621 		}
       
   622 	if (!sprite && iCurrentWindow && (iPointerCursorMode==EPointerCursorFixed || iPointerCursorMode==EPointerCursorNormal))
       
   623 		sprite=CWsClient::DefaultSystemPointerCursor();
       
   624 	return sprite;
       
   625 	}
       
   626 
       
   627 TEventQueueWalkRet PointerRepeatPurgeFunc(TAny *, TWsEvent *aEvent)
       
   628 //
       
   629 // Callback function for event queue walk
       
   630 //
       
   631 	{
       
   632 	return(WsPointer::PointerRepeatPurgeCheck(aEvent));
       
   633 	}
       
   634 
       
   635 TBool WsPointer::PointerEventRepeatCheck(const TWsEvent *aEvent, TUint32 aHandle)
       
   636 //
       
   637 // Return ETrue if this pointer event is consumed by the pointer repeat
       
   638 //
       
   639 	{
       
   640 	TPointerEvent *pntEvent=aEvent->Pointer();
       
   641 	if (aHandle==iRepeatWindow->ClientHandle() && 
       
   642 		 (pntEvent->iType==TPointerEvent::EDrag || pntEvent->iType==TPointerEvent::EMove) &&
       
   643 		  iRepeatRect.Contains(pntEvent->iPosition))
       
   644 		return(ETrue);
       
   645 	return(EFalse);
       
   646 	}
       
   647 
       
   648 TEventQueueWalkRet WsPointer::PointerRepeatPurgeCheck(const TWsEvent *aEvent)
       
   649 	{
       
   650 	if (iRepeatWindow && aEvent->Type()==EEventPointer)
       
   651 		{
       
   652 		if (PointerEventRepeatCheck(aEvent,aEvent->Handle()))
       
   653 			return(EEventQueueWalkDeleteEvent);	// Purge the event as it is a move/drag within the repeat rect
       
   654 		CancelPointerRepeatEventRequest();
       
   655 		}
       
   656 	return(EEventQueueWalkOk);
       
   657 	}
       
   658 
       
   659 void WsPointer::RequestPointerRepeatEvent(CWsWindow *aWindow, TTimeIntervalMicroSeconds32 aTime,const TRect &aRect)
       
   660 	{
       
   661 	CancelPointerRepeatEventRequest();
       
   662 	iRepeatWindow=aWindow;
       
   663 	iRepeatRect=aRect;
       
   664 	iRepeatTimer->After(aTime);
       
   665 	aWindow->EventQueue()->WalkEventQueue(&PointerRepeatPurgeFunc,NULL);
       
   666 	if (iRepeatWindow && !iRepeatRect.Contains(iCurrentPos-iRepeatWindow->Origin()))
       
   667 		CancelPointerRepeatEventRequest();
       
   668 	}
       
   669 
       
   670 void WsPointer::CancelPointerRepeatEventRequest()
       
   671 	{
       
   672 	if (iRepeatWindow)
       
   673 		{
       
   674 		iRepeatWindow=NULL;
       
   675 		iRepeatTimer->Cancel();
       
   676 		}
       
   677 	}
       
   678 
       
   679 void WsPointer::RepeatTimerCompleted()
       
   680 	{
       
   681 	TWsEvent event;
       
   682 	event.SetType(EEventPointer);
       
   683 	event.SetTimeNow();
       
   684 	event.Pointer()->iModifiers=TWindowServerEvent::GetModifierState();
       
   685 	event.Pointer()->iPosition=iCurrentPos-iRepeatWindow->Origin();
       
   686 	event.Pointer()->iParentPosition=iCurrentPos-iRepeatWindow->BaseParent()->Origin();
       
   687 	event.Pointer()->iType=TPointerEvent::EButtonRepeat;
       
   688 	QueuePointerEvent(iRepeatWindow, event);
       
   689 	iRepeatWindow=NULL;
       
   690 	}
       
   691 
       
   692 #if defined(__WINS__)
       
   693 void WsPointer::SetXyInputType(TXYInputType aXyInputType)
       
   694 	{
       
   695 	if (iXyInputType>EXYInputPointer && aXyInputType<EXYInputMouse && !iPointerDown)
       
   696 		{
       
   697 		iCurrentWindow=NULL;
       
   698 		UpdatePointerCursor();
       
   699 		}
       
   700 	else if (iXyInputType<EXYInputMouse && aXyInputType>EXYInputPointer && !iPointerDown)
       
   701 		{
       
   702 		TPoint pos(iCurrentPos);
       
   703 		TPoint parPos;
       
   704 		ReLogCurrentWindow(pos,parPos,NULL);
       
   705 		UpdatePointerCursor();
       
   706 		}
       
   707 	iXyInputType=aXyInputType;
       
   708 	}
       
   709 #endif
       
   710 
       
   711 //
       
   712 
       
   713 CWsPointerTimer::CWsPointerTimer() : CTimer(EPointerRepeatPriority)
       
   714 	{}
       
   715 
       
   716 void CWsPointerTimer::ConstructL()
       
   717 	{
       
   718 	CTimer::ConstructL();
       
   719 	CActiveScheduler::Add(this);
       
   720 	}
       
   721 
       
   722 void CWsPointerTimer::RunL()
       
   723 	{
       
   724 	User::ResetInactivityTime();
       
   725 	WS_ASSERT_DEBUG(iStatus.Int()==KErrNone, EWsPanicPointerRepeatTimerStatus);
       
   726 	WsPointer::RepeatTimerCompleted();
       
   727 	}
       
   728 
       
   729 //
       
   730 
       
   731 CWsPointerBuffer::~CWsPointerBuffer()
       
   732 	{
       
   733 	if (this == iCurrentBuffer)
       
   734 		{
       
   735 		// We're about to be destroyed - don't want to be pointed at any more.
       
   736 		iCurrentBuffer = NULL;
       
   737 		}
       
   738 	iList.Remove(*this);
       
   739 	}
       
   740 
       
   741 void CWsPointerBuffer::ConnectL(CWsClientWindow *aWindow, TInt aMaxPoints, TUint aFlags)
       
   742 	{
       
   743 	CWsPointerBuffer *pb=NULL;
       
   744 	for(TSglQueIter<CWsPointerBuffer> iter(iList);(pb=iter++)!=NULL;)
       
   745 		if (pb->iWindow==aWindow)
       
   746 			User::Leave(KErrInUse);
       
   747 	CWsPointerBuffer *pbuf=new(ELeave) CWsPointerBuffer;
       
   748 	pbuf->iWindow=aWindow;
       
   749 	pbuf->iMaxPoints=aMaxPoints;
       
   750 	pbuf->iFlags=aFlags;
       
   751 	iList.AddFirst(*pbuf);
       
   752 	CleanupStack::PushL(pbuf);
       
   753 	AdjustMaxSizeL();
       
   754 	CleanupStack::Pop();
       
   755 	}
       
   756 
       
   757 void CWsPointerBuffer::Disconnect(CWsClientWindow *aWindow)
       
   758 	{
       
   759 	CWsPointerBuffer *pb=NULL;
       
   760 	for(TSglQueIter<CWsPointerBuffer> iter(iList);(pb=iter++)!=NULL;)
       
   761 		{
       
   762 		if (pb->iWindow==aWindow)
       
   763 			{
       
   764 			delete pb; // Note that the destructor also sets iCurrentBuffer to NULL if it is pointing at pb
       
   765 			TRAP_IGNORE(AdjustMaxSizeL());	// Shouldn't fail, but doesn't matter if it does as we simply have a larger buffer than needed
       
   766 			break; // from for loop
       
   767 			}
       
   768 		}
       
   769 	}
       
   770 
       
   771 void CWsPointerBuffer::Reset()
       
   772 	{
       
   773 	iSignalled=EFalse;
       
   774 	iPointerBuffer->Reset();
       
   775 	}
       
   776 
       
   777 void CWsPointerBuffer::SignalBufferReady()
       
   778 	{
       
   779 	if (!iSignalled)
       
   780 		if (iCurrentBuffer && iCurrentBuffer->iWindow->QueueEvent(EEventPointerBufferReady))
       
   781 			iSignalled=ETrue;
       
   782 	}
       
   783 
       
   784 void CWsPointerBuffer::PointerEvent(CWsClientWindow *aWindow,const TPoint &aPoint)
       
   785 	{
       
   786 	if (iCurrentBuffer==NULL || aWindow!=iCurrentBuffer->iWindow)
       
   787 		{
       
   788 		Reset();
       
   789 		CWsPointerBuffer *pb=NULL;
       
   790 		for(TSglQueIter<CWsPointerBuffer> iter(iList);(pb=iter++)!=NULL;)
       
   791 			{
       
   792 			if (pb->iWindow==aWindow)
       
   793 				{
       
   794 				iCurrentBuffer=pb;
       
   795 				break; // from for loop
       
   796 				}
       
   797 			}
       
   798 		}
       
   799 	iPointerBuffer->Add(&aPoint);
       
   800 	SignalBufferReady();
       
   801 	}
       
   802 
       
   803 void CWsPointerBuffer::RetrievePointerMoveBuffer(CWsClientWindow *aWindow,TInt aMaxPoints)
       
   804 	{
       
   805 	enum {KPointerMoveBufferSize=32};	// Puts 256 bytes on the stack
       
   806 	if (iCurrentBuffer && aWindow==iCurrentBuffer->iWindow)
       
   807 		{
       
   808 		iSignalled=EFalse;
       
   809 		TInt max=Min(aMaxPoints,iPointerBuffer->Count());
       
   810 		TInt buflen=0;
       
   811 		aWindow->WsOwner()->SetReply(max);
       
   812 		TPoint point;
       
   813 		TBuf8<KPointerMoveBufferSize*sizeof(TPoint)> pnts;
       
   814 		for(TInt index=0;index<max;index++)
       
   815 			{
       
   816 			iPointerBuffer->Remove(&point);
       
   817 			pnts.Append((TUint8 *)&point,sizeof(TPoint));
       
   818 			buflen++;
       
   819 			if (buflen==KPointerMoveBufferSize)
       
   820 				{
       
   821 				CWsClient::ReplyBuf(pnts);
       
   822 				pnts.Zero();
       
   823 				buflen=0;
       
   824 				}
       
   825 			}
       
   826 		if (buflen>0)
       
   827 			CWsClient::ReplyBuf(pnts);
       
   828 		if (iPointerBuffer->Count())
       
   829 			SignalBufferReady();
       
   830 		}
       
   831 	}
       
   832 
       
   833 void CWsPointerBuffer::DiscardPointerMoveBuffer(TUint aHandle)
       
   834 	{
       
   835 	if (iCurrentBuffer && aHandle==iCurrentBuffer->iWindow->ClientHandle())
       
   836 		Reset();
       
   837 	}
       
   838 
       
   839 void CWsPointerBuffer::DiscardPointerMoveBuffer(CWsClientWindow *aWindow)
       
   840 	{
       
   841 	if (iCurrentBuffer && aWindow==iCurrentBuffer->iWindow)
       
   842 		Reset();
       
   843 	}
       
   844 
       
   845 void CWsPointerBuffer::AdjustMaxSizeL()
       
   846 	{
       
   847 	TInt max=0;
       
   848 	CWsPointerBuffer *pb=NULL;
       
   849 	for(TSglQueIter<CWsPointerBuffer> iter(iList);(pb=iter++)!=NULL;)
       
   850 		if (pb->iMaxPoints>max)
       
   851 			max=pb->iMaxPoints;
       
   852 	if (max==0)
       
   853 		{
       
   854 		delete iPointerBuffer;
       
   855 		iPointerBuffer=NULL;
       
   856 		}
       
   857 	else if (!iPointerBuffer)
       
   858 		{
       
   859 		CCirBuf<TPoint> *pointerBuffer=new(ELeave) CCirBuf<TPoint>;
       
   860 		CleanupStack::PushL(pointerBuffer);
       
   861 		pointerBuffer->SetLengthL(max);
       
   862 		CleanupStack::Pop();
       
   863 		iPointerBuffer=pointerBuffer;
       
   864 		}
       
   865 	else
       
   866 		iPointerBuffer->SetLengthL(max);
       
   867 	}