|
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,¶ms); |
|
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 } |