Git init
[adaptation/xorg/driver/xserver-xorg-input-gesture.git] / src / gesture.c
1 /**************************************************************************
2
3 xserver-xorg-input-gesture
4
5 Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
6
7 Contact: Sung-Jin Park <sj76.park@samsung.com>
8          Sangjin LEE <lsj119@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35
36 #include <linux/input.h>
37 #include <linux/types.h>
38
39 #include <xf86_OSproc.h>
40
41 #include <unistd.h>
42
43 #include <xf86.h>
44 #include <xf86Xinput.h>
45 #include <exevents.h>
46 #include <xorgVersion.h>
47 #include <xkbsrv.h>
48
49 #ifdef HAVE_PROPERTIES
50 #include <X11/Xatom.h>
51 #include <xserver-properties.h>
52 /* 1.6 has properties, but no labels */
53 #ifdef AXIS_LABEL_PROP
54 #define HAVE_LABELS
55 #else
56 #undef HAVE_LABELS
57 #endif
58
59 #endif
60
61 #define __DEBUG__
62 //#define __DETAIL_DEBUG__
63 //#define __DEBUG_EVENT_HANDLER__
64
65 #include <stdio.h>
66 #include <sys/stat.h>
67 #include <sys/syscall.h>
68 #include <unistd.h>
69 #include <errno.h>
70 #include <sys/types.h>
71 #include <fcntl.h>
72 #include <xorg-server.h>
73 #include <xorgVersion.h>
74 #include <xf86Module.h>
75 #include <X11/Xatom.h>
76 #include "gesture.h"
77 #include <xorg/mi.h>
78
79 //Basic functions
80 static InputInfoPtr GesturePreInit(InputDriverPtr  drv, IDevPtr dev, int flags);
81 static void GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
82 static pointer GesturePlug(pointer module, pointer options, int *errmaj, int  *errmin);
83 static void GestureUnplug(pointer p);
84 static int GestureControl(DeviceIntPtr    device,int what);
85 static int GestureInit(DeviceIntPtr device);
86 static void GestureFini(DeviceIntPtr device);
87 static void GestureReadInput(InputInfoPtr pInfo);
88
89 //other initializers
90 ErrorStatus GestureRegionsInit(void);
91
92 //event queue handling functions
93 ErrorStatus GestureInitEQ(void);
94 ErrorStatus GestureFiniEQ(void);
95 ErrorStatus GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
96 ErrorStatus GestureEventsFlush(void);
97 void GestureEventsDrop(void);
98
99 //utility functions
100 ErrorStatus GestureRegionsReinit(void);
101 void GestureSetDisable(InputInfoPtr pInfo, int enable);
102 WindowPtr GestureGetEventsWindow(void);
103
104 //Enqueued event handlers and enabler/disabler
105 static ErrorStatus GestureEnableEventHandler(InputInfoPtr pInfo);
106 static ErrorStatus GestureDisableEventHandler(void);
107 static CARD32 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
108 static CARD32 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
109 void GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
110 void GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
111 void GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
112 void GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
113
114 //Gesture recognizer helper
115 static Bool PointInBorderSize(WindowPtr pWin, int x, int y);
116 static WindowPtr GestureWindowOnXY(int x, int y);
117 Bool GestureHasFingerEventMask(int eventType, int num_finger);
118
119 //Gesture recognizer and handlers
120 void GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx);
121 void GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx);
122 void GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
123 void GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
124 void GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
125 void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
126 void GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction);
127 void GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy);
128 void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy);
129 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds);
130 void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds);
131 void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds);
132 void GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device);
133 ErrorStatus GestureFlushOrDrop(void);
134
135 #ifdef HAVE_PROPERTIES
136 //function related property handling
137 static void GestureInitProperty(DeviceIntPtr dev);
138 static int GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val, BOOL checkonly);
139 #endif
140
141 static Atom prop_gesture_recognizer_onoff = None;
142
143 GestureDevicePtr g_pGesture = NULL;
144 _X_EXPORT InputDriverRec GESTURE = {
145     1,
146     "gesture",
147     NULL,
148     GesturePreInit,
149     GestureUnInit,
150     NULL,
151     0
152 };
153
154 static XF86ModuleVersionInfo GestureVersionRec =
155 {
156     "gesture",
157     MODULEVENDORSTRING,
158     MODINFOSTRING1,
159     MODINFOSTRING2,
160     XORG_VERSION_CURRENT,
161     PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR,
162     PACKAGE_VERSION_PATCHLEVEL,
163     ABI_CLASS_XINPUT,
164     ABI_XINPUT_VERSION,
165     MOD_CLASS_XINPUT,
166     {0, 0, 0, 0}
167 };
168
169 _X_EXPORT XF86ModuleData gestureModuleData =
170 {
171     &GestureVersionRec,
172     &GesturePlug,
173     &GestureUnplug
174 };
175
176 static Bool
177 PointInBorderSize(WindowPtr pWin, int x, int y)
178 {
179     BoxRec box;
180     if( pixman_region_contains_point (&pWin->borderSize, x, y, &box) )
181         return TRUE;
182
183     return FALSE;
184 }
185
186 static WindowPtr
187 GestureWindowOnXY(int x, int y)
188 {
189     WindowPtr pWin;
190     BoxRec box;
191     SpritePtr pSprite;
192     DeviceIntPtr pDev = g_pGesture->master_pointer;
193
194     pSprite = pDev->spriteInfo->sprite;
195     pSprite->spriteTraceGood = 1;       /* root window still there */
196     pWin = RootWindow(pDev)->firstChild;
197
198     while (pWin)
199     {
200         if ((pWin->mapped) &&
201             (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
202             (x < pWin->drawable.x + (int)pWin->drawable.width +
203              wBorderWidth(pWin)) &&
204             (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
205             (y < pWin->drawable.y + (int)pWin->drawable.height +
206              wBorderWidth (pWin))
207             /* When a window is shaped, a further check
208              * is made to see if the point is inside
209              * borderSize
210              */
211             && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
212             && (!wInputShape(pWin) ||
213                 RegionContainsPoint(wInputShape(pWin),
214                                     x - pWin->drawable.x,
215                                     y - pWin->drawable.y, &box))
216 #ifdef ROOTLESS
217     /* In rootless mode windows may be offscreen, even when
218      * they're in X's stack. (E.g. if the native window system
219      * implements some form of virtual desktop system).
220      */
221                 && !pWin->rootlessUnhittable
222 #endif
223             )
224         {
225             if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
226             {
227                 pSprite->spriteTraceSize += 10;
228                 pSprite->spriteTrace = realloc(pSprite->spriteTrace,
229                                     pSprite->spriteTraceSize*sizeof(WindowPtr));
230             }
231             pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
232             pWin = pWin->firstChild;
233         }
234         else
235             pWin = pWin->nextSib;
236     }
237     return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
238 }
239
240 Bool
241 GestureHasFingerEventMask(int eventType, int num_finger)
242 {
243         Bool ret = FALSE;
244         Mask eventmask = (1L << eventType);
245
246         if( (g_pGesture->grabMask & eventmask) &&
247                 (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[num_finger].window != None) )
248         {
249 #ifdef __DETAIL_DEBUG__
250                 ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has grabMask\n");
251 #endif//__DETAIL_DEBUG__
252                 return TRUE;
253         }
254
255         if( g_pGesture->eventMask & eventmask )
256         {
257 #ifdef __DETAIL_DEBUG__
258                 ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has eventMask\n");
259 #endif//__DETAIL_DEBUG__
260                 return TRUE;
261         }
262
263 #ifdef __DETAIL_DEBUG__
264         ErrorF("[X11][GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger);
265 #endif//__DETAIL_DEBUG__
266
267         return ret;
268 }
269
270 void
271 GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction)
272 {
273         Window target_win;
274         WindowPtr target_pWin;
275         xGestureNotifyFlickEvent fev;
276
277 #ifdef __DETAIL_DEBUG__
278         ErrorF("[X11][GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n",
279                 num_of_fingers, distance, duration, direction);
280 #endif//__DETAIL_DEBUG__
281
282         g_pGesture->recognized_gesture |= FlickFilterMask;
283         memset(&fev, 0, sizeof(xGestureNotifyFlickEvent));
284         fev.type = GestureNotifyFlick;
285         fev.kind = GestureDone;
286         fev.num_finger = num_of_fingers;
287         fev.distance = distance;
288         fev.duration = duration;
289         fev.direction = direction;
290
291         target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window;
292         target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin;
293
294         if( g_pGesture->grabMask && (target_win != None) )
295         {
296                 fev.window = target_win;
297         }
298         else
299         {
300                 fev.window = g_pGesture->gestureWin;
301         }
302
303 #ifdef __DETAIL_DEBUG__
304         ErrorF("[X11][GestureHandleGesture_Flick] fev.window=0x%x, g_pGesture->grabMask=0x%x\n", fev.window, g_pGesture->grabMask);
305 #endif//__DETAIL_DEBUG__
306
307         GestureSendEvent(target_pWin, GestureNotifyFlick, GestureFlickMask, (xGestureCommonEvent *)&fev);
308 }
309
310 void
311 GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy)
312 {
313         Window target_win;
314         WindowPtr target_pWin;
315         xGestureNotifyTapEvent tev;
316
317         //skip non-tap events and single finger tap
318         if( !tap_repeat || num_finger <= 1 )
319                 return;
320
321 #ifdef __DETAIL_DEBUG__
322         ErrorF("[X11][GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n",
323                 num_finger, tap_repeat, cx, cy);
324 #endif//__DETAIL_DEBUG__
325
326         g_pGesture->recognized_gesture |= TapFilterMask;
327         memset(&tev, 0, sizeof(xGestureNotifyTapEvent));
328         tev.type = GestureNotifyTap;
329         tev.kind = GestureDone;
330         tev.num_finger = num_finger;
331         tev.tap_repeat = tap_repeat;
332         tev.interval = 0;
333         tev.cx = cx;
334         tev.cy = cy;
335
336         target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window;
337         target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin;
338
339         if( g_pGesture->grabMask && (target_win != None) )
340         {
341                 tev.window = target_win;
342         }
343         else
344         {
345                 tev.window = g_pGesture->gestureWin;
346         }
347
348 #ifdef __DETAIL_DEBUG__
349         ErrorF("[X11][GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", tev.window, g_pGesture->grabMask);
350 #endif//__DETAIL_DEBUG__
351
352         GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev);
353 }
354
355 void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy)
356 {
357         Window target_win;
358         WindowPtr target_pWin;
359         xGestureNotifyPinchRotationEvent prev;
360
361 #ifdef __DETAIL_DEBUG__
362         ErrorF("[X11][GestureHandleGesture_PinchRotation] num_fingers=%d, zoom=%.2f, angle=%.2f, distance=%d\n",
363                                 num_of_fingers, zoom, angle, distance, cx, cy);
364 #endif//__DETAIL_DEBUG__
365
366         g_pGesture->recognized_gesture |= PinchRotationFilterMask;
367         memset(&prev, 0, sizeof(xGestureNotifyPinchRotationEvent));
368         prev.type = GestureNotifyPinchRotation;
369         prev.kind = GestureDone;
370         prev.num_finger = num_of_fingers;
371         prev.zoom = XDoubleToFixed(zoom);
372         prev.angle = XDoubleToFixed(angle);
373         prev.distance = distance;
374         prev.cx = cx;
375         prev.cy = cy;
376
377         target_win = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].window;
378         target_pWin = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].pWin;
379
380         if( g_pGesture->grabMask && (target_win != None) )
381         {
382                 prev.window = target_win;
383         }
384         else
385         {
386                 prev.window = g_pGesture->gestureWin;
387         }
388
389 #ifdef __DETAIL_DEBUG__
390         ErrorF("[X11][GestureHandleGesture_PinchRotation] prev.window=0x%x, g_pGesture->grabMask=0x%x\n", prev.window, g_pGesture->grabMask);
391 #endif//__DETAIL_DEBUG__
392
393         GestureSendEvent(target_pWin, GestureNotifyPinchRotation, GesturePinchRotationMask, (xGestureCommonEvent *)&prev);
394 }
395
396 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds)
397 {
398         Window target_win;
399         WindowPtr target_pWin;
400         xGestureNotifyHoldEvent hev;
401
402 #ifdef __DETAIL_DEBUG__
403         ErrorF("[X11][GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n",
404                                 num_fingers, cx, cy, holdtime, kinds);
405 #endif//__DETAIL_DEBUG__
406
407         g_pGesture->recognized_gesture |= HoldFilterMask;
408         memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
409         hev.type = GestureNotifyHold;
410         hev.kind = kinds;
411         hev.num_finger = num_fingers;
412         hev.holdtime = holdtime;
413         hev.cx = cx;
414         hev.cy = cy;
415
416         target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window;
417         target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin;
418
419         if( g_pGesture->grabMask && (target_win != None) )
420         {
421                 hev.window = target_win;
422         }
423         else
424         {
425                 hev.window = g_pGesture->gestureWin;
426         }
427
428 #ifdef __DETAIL_DEBUG__
429         ErrorF("[X11][GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask);
430 #endif//__DETAIL_DEBUG__
431
432         GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev);
433 }
434
435 void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds)
436 {
437         Window target_win;
438         WindowPtr target_pWin;
439         xGestureNotifyTapNHoldEvent thev;
440
441 #ifdef __DETAIL_DEBUG__
442         ErrorF("[X11][GestureHandleGesture_TapNHold] num_fingers=%d, cx=%d, cy=%d, interval=%d, holdtime=%d, kinds=%d\n",
443                                 num_fingers, cx, cy, interval, holdtime, kinds);
444 #endif//__DETAIL_DEBUG__
445
446         g_pGesture->recognized_gesture |= TapNHoldFilterMask;
447         memset(&thev, 0, sizeof(xGestureNotifyTapNHoldEvent));
448         thev.type = GestureNotifyTapNHold;
449         thev.kind = kinds;
450         thev.num_finger = num_fingers;
451         thev.holdtime = holdtime;
452         thev.cx = cx;
453         thev.cy = cy;
454         thev.interval = interval;
455
456         target_win = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].window;
457         target_pWin = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].pWin;
458
459         if( g_pGesture->grabMask && (target_win != None) )
460         {
461                 thev.window = target_win;
462         }
463         else
464         {
465                 thev.window = g_pGesture->gestureWin;
466         }
467
468 #ifdef __DETAIL_DEBUG__
469         ErrorF("[X11][GestureHandleGesture_TapNHold] thev.window=0x%x, g_pGesture->grabMask=0x%x\n", thev.window, g_pGesture->grabMask);
470 #endif//__DETAIL_DEBUG__
471
472         GestureSendEvent(target_pWin, GestureNotifyTapNHold, GestureTapNHoldMask, (xGestureCommonEvent *)&thev);
473 }
474
475 void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds)
476 {
477         Window target_win;
478         WindowPtr target_pWin;
479         xGestureNotifyPanEvent pev;
480
481 #ifdef __DETAIL_DEBUG__
482         ErrorF("[X11][GestureHandleGesture_Pan] num_fingers=%d, dx=%d, dy=%d, direction=%d, distance=%d, duration=%d, kinds=%d\n",
483                                 num_fingers, dx, dy, direction, distance, duration, kinds);
484 #endif//__DETAIL_DEBUG__
485
486         g_pGesture->recognized_gesture |= PanFilterMask;
487         memset(&pev, 0, sizeof(xGestureNotifyPanEvent));
488         pev.type = GestureNotifyPan;
489         pev.kind = kinds;
490         pev.num_finger = num_fingers;
491         pev.direction = direction;
492         pev.distance = distance;
493         pev.duration = duration;
494         pev.dx = dx;
495         pev.dy = dy;
496
497         target_win = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].window;
498         target_pWin = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].pWin;
499
500         if( g_pGesture->grabMask && (target_win != None) )
501         {
502                 pev.window = target_win;
503         }
504         else
505         {
506                 pev.window = g_pGesture->gestureWin;
507         }
508
509 #ifdef __DETAIL_DEBUG__
510         ErrorF("[X11][GestureHandleGesture_Pan] pev.window=0x%x, g_pGesture->grabMask=0x%x\n", pev.window, g_pGesture->grabMask);
511 #endif//__DETAIL_DEBUG__
512
513         GestureSendEvent(target_pWin, GestureNotifyPan, GesturePanMask, (xGestureCommonEvent *)&pev);
514 }
515
516 void
517 GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
518 {
519
520         g_pGesture->recognized_gesture &= ~PinchRotationFilterMask;
521         g_pGesture->filter_mask |= PinchRotationFilterMask;
522         return;
523 }
524
525 void
526 GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
527 {
528         static int num_pressed = 0;
529         static int mbits = 0;
530         static int base_area_size = 0;
531         static Time base_time = 0;
532         static int base_x, base_y;
533         Time current_time;
534         Time duration;
535         int distx, disty;
536         int distance, direction;
537         int area_size;
538         int flicked = 0;
539
540         switch( type )
541         {
542                 case ET_ButtonPress:
543                         g_pGesture->fingers[idx].flags |= PressFlagFlick;
544
545                         if( g_pGesture->num_pressed < 2 )
546                                 return;
547
548                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
549                         {
550                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
551                                 base_x = g_pGesture->area.extents.x1;
552                                 base_y = g_pGesture->area.extents.y1;
553                                 base_time = GetTimeInMillis();
554                         }
555                         num_pressed = g_pGesture->num_pressed;
556
557 #ifdef __DETAIL_DEBUG__
558                         ErrorF("[GroupFlick][P]][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, base_area_size);
559 #endif//__DETAIL_DEBUG__
560                         break;
561
562                 case ET_Motion:
563                         if( !(g_pGesture->fingers[idx].flags & PressFlagFlick ) )
564                                 break;
565
566 #ifdef __DETAIL_DEBUG__
567                         if( num_pressed > g_pGesture->num_pressed )
568                         {
569                                 ErrorF("[GroupFlick][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
570                                 //goto cleanup_flick;
571                         }
572 #endif//__DETAIL_DEBUG__
573
574                         if( num_pressed < 2 )
575                                 return;
576
577                         mbits |= (1 << idx);
578                         if( mbits == (pow(2, num_pressed)-1) )
579                         {
580                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
581 #ifdef __DETAIL_DEBUG__
582                                 ErrorF("[M][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, area_size);
583 #endif//__DETAIL_DEBUG__
584                                 if( ABS(base_area_size - area_size) >= FLICK_AREA_THRESHOLD )
585                                 {
586 #ifdef __DETAIL_DEBUG__
587                                         ErrorF("[GroupFlick][M] diff between Area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, FLICK_AREA_THRESHOLD);
588 #endif//__DETAIL_DEBUG__
589                                         goto cleanup_flick;
590                                 }
591
592                                 current_time = GetTimeInMillis();
593                                 if( (current_time - base_time) >= FLICK_AREA_TIMEOUT )
594                                 {
595 #ifdef __DETAIL_DEBUG__
596                                         ErrorF("[GroupFlick][M] diff between current time(=%d) and base time(=%d) is bigger than threashold(=%d) !\n", current_time, base_time, FLICK_AREA_TIMEOUT);
597 #endif//__DETAIL_DEBUG__
598                                         goto cleanup_flick;
599                                 }
600                                 mbits = 0;
601                         }
602                         break;
603
604                 case ET_ButtonRelease:
605                         if( g_pGesture->num_pressed )
606                                 break;
607
608                         duration = GetTimeInMillis() - base_time;
609                         distx = g_pGesture->area.extents.x1 - base_x;
610                         disty = g_pGesture->area.extents.y1 - base_y;
611
612 #ifdef __DETAIL_DEBUG__
613                         ErrorF("[GroupFlick] duration=%d, distx=%d, disty=%d\n", duration, distx, disty);
614 #endif//__DETAIL_DEBUG__
615
616                         if( duration <= 0 || duration >= FLICK_AREA_TIMEOUT )
617                                 goto cleanup_flick;
618
619                         if( ABS(distx) >= FLICK_MOVE_THRESHOLD )
620                         {
621                                 direction = (distx > 0) ? FLICK_EASTWARD : FLICK_WESTWARD;
622                                 distance = ABS(distx);
623                                 flicked++;
624                         }
625                         else if( ABS(disty) >= FLICK_MOVE_THRESHOLD )
626                         {
627                                 direction = (disty > 0) ? FLICK_SOUTHWARD : FLICK_NORTHWARD;
628                                 distance = ABS(disty);
629                                 flicked++;
630                         }
631
632                         if( !flicked )
633                                 goto cleanup_flick;
634
635                         if( GestureHasFingerEventMask(GestureNotifyFlick, num_pressed) )
636                                 GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
637                         goto cleanup_flick_recognized;
638                         break;
639         }
640
641         return;
642
643 cleanup_flick:
644
645         g_pGesture->recognized_gesture &= ~FlickFilterMask;
646
647 cleanup_flick_recognized:
648
649         g_pGesture->filter_mask |= FlickFilterMask;
650         num_pressed = 0;
651         base_area_size = 0;
652         base_time = 0;
653         mbits = 0;
654         return;
655 }
656
657 void
658 GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
659 {
660         static int num_pressed = 0;
661         static int mbits = 0;
662         static int base_area_size = 0;
663         static Time base_time = 0;
664         static pixman_box16_t base_box_ext;
665         static int base_cx;
666         static int base_cy;
667         static int prev_cx;
668         static int prev_cy;
669         static int cx = 0;
670         static int cy = 0;
671         int dx, dy;
672         static Time prev_time = 0;
673         Time current_time = 0;
674         int distance = 0;
675         int direction = 0;
676         int area_size;
677         static int time_checked = 0;
678         static int state = GestureEnd;
679
680         static OsTimerPtr pan_event_timer = NULL;
681         static int event_type = GestureNotifyPan;
682
683         if( timer_expired )
684         {
685                 if( !time_checked )
686                 {
687                         current_time = GetTimeInMillis();
688                         if( (current_time - base_time) >= PAN_TIME_THRESHOLD )
689                         {
690                                 if( (!cx && !cy) || INBOX(&base_box_ext, cx, cy) )
691                                 {
692 #ifdef __DETAIL_DEBUG__
693                                         ErrorF("[GroupPan][Timer] You must move farther than move threshold(=%d) within time threshold(=%d) !\n", PAN_MOVE_THRESHOLD*2, PAN_TIME_THRESHOLD);
694 #endif//__DETAIL_DEBUG__
695                                         goto cleanup_pan;
696                                 }
697                                 time_checked = 1;
698                         }
699                 }
700                 return;
701         }
702
703         switch( type )
704         {
705                 case ET_ButtonPress:
706                         g_pGesture->fingers[idx].flags |= PressFlagPan;
707
708                         if( g_pGesture->num_pressed < 2 )
709                                 return;
710
711                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
712                         {
713                                 if( state != GestureEnd )
714                                 {
715 #ifdef __DETAIL_DEBUG__
716                                         ErrorF("[GroupPan][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
717 #endif//__DETAIL_DEBUG__
718                                         goto cleanup_pan;
719                                 }
720                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
721                                 prev_cx = base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
722                                 prev_cy = base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
723                                 prev_time = base_time = GetTimeInMillis();
724                                 base_box_ext.x1 = base_cx-PAN_MOVE_THRESHOLD;
725                                 base_box_ext.y1 = base_cy-PAN_MOVE_THRESHOLD;
726                                 base_box_ext.x2 = base_cx+PAN_MOVE_THRESHOLD;
727                                 base_box_ext.y2 = base_cy+PAN_MOVE_THRESHOLD;
728                                 event_type = GestureNotifyPan;
729                                 pan_event_timer = TimerSet(pan_event_timer, 0, PAN_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
730                         }
731                         num_pressed = g_pGesture->num_pressed;
732
733 #ifdef __DETAIL_DEBUG__
734                         ErrorF("[GroupPan][P][num_pressed=%d] AREA_SIZE(area.extents)=%d, base_cx=%d, base_cy=%d\n", num_pressed, base_area_size, base_cx, base_cy);
735 #endif//__DETAIL_DEBUG__
736                         break;
737
738                 case ET_Motion:
739                         if( !(g_pGesture->fingers[idx].flags & PressFlagPan ) )
740                                 break;
741
742                         if( num_pressed != g_pGesture->num_pressed )
743                         {
744                                 if( state != GestureEnd )
745                                 {
746 #ifdef __DETAIL_DEBUG__
747                                 ErrorF("[GroupPan][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
748 #endif//__DETAIL_DEBUG__
749                                         goto cleanup_pan;
750                                 }
751                         }
752
753                         if( num_pressed < 2 )
754                                 return;
755
756                         mbits |= (1 << idx);
757                         if( mbits == (pow(2, num_pressed)-1) )
758                         {
759                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
760 #ifdef __DETAIL_DEBUG__
761                                 ErrorF("[GroupPan][M][num_pressed=%d] area_size=%d, base_area_size=%d, diff=%d\n", num_pressed, area_size, base_area_size, ABS(base_area_size - area_size));
762 #endif//__DETAIL_DEBUG__
763
764                                 if( (state != GestureUpdate) && (ABS(base_area_size - area_size) >= PAN_AREA_THRESHOLD) )
765                                 {
766 #ifdef __DETAIL_DEBUG__
767                                         ErrorF("[GroupPan][M] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, PAN_AREA_THRESHOLD);
768 #endif//__DETAIL_DEBUG__
769                                         goto cleanup_pan;
770                                 }
771
772                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
773                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
774
775 #ifdef __DETAIL_DEBUG__
776                                 ErrorF("[GroupPan][M] cx=%d, prev_cx=%d, diff=%d\n", cx, prev_cx, ABS(cx-prev_cx));
777                                 ErrorF("[GroupPan][M] cy=%d, prev_cy=%d, diff=%d\n", cy, prev_cy, ABS(cy-prev_cy));
778 #endif//__DETAIL_DEBUG__
779
780                                 if( !time_checked )
781                                 {
782                                         current_time = GetTimeInMillis();
783                                         if( (current_time - base_time) >= PAN_TIME_THRESHOLD )
784                                         {
785                                                 if( INBOX(&base_box_ext, cx, cy) )
786                                                 {
787 #ifdef __DETAIL_DEBUG__
788                                                         ErrorF("[GroupPan][M] You must move farther than move threshold(=%d) within time threshold(=%d) !\n", PAN_MOVE_THRESHOLD*2, PAN_TIME_THRESHOLD);
789 #endif//__DETAIL_DEBUG__
790                                                         goto cleanup_pan;
791                                                 }
792                                                 time_checked = 1;
793                                         }
794                                 }
795
796                                 if( time_checked )
797                                 {
798                                         if( state <= GestureBegin )
799                                         {
800                                                 base_box_ext.x1 = prev_cx-PAN_MOVE_THRESHOLD;
801                                                 base_box_ext.y1 = prev_cy-PAN_MOVE_THRESHOLD;
802                                                 base_box_ext.x2 = prev_cx+PAN_MOVE_THRESHOLD;
803                                                 base_box_ext.y2 = prev_cy+PAN_MOVE_THRESHOLD;
804
805                                                 if( !INBOX(&base_box_ext, cx, cy) )
806                                                 {
807                                                         current_time = GetTimeInMillis();
808 #ifdef __DETAIL_DEBUG__
809                                                         ErrorF("[GroupPan] PAN Begin !dx=%d, dy=%d, state=%d\n", prev_cx, prev_cy, state);
810 #endif//__DETAIL_DEBUG__
811                                                         if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
812                                                         {
813                                                                 GestureHandleGesture_Pan(num_pressed, prev_cx, prev_cy, direction, distance, current_time-prev_time, GestureBegin);
814                                                                 state = GestureUpdate;
815                                                         }
816                                                         else
817                                                                 goto cleanup_pan;
818                                                 }
819                                         }
820                                         else
821                                         {
822                                                 dx = cx-prev_cx;
823                                                 dy = cy-prev_cy;
824                                                 //if( ABS(dx) >= PAN_UPDATE_MOVE_THRESHOLD || ABS(dy) >= PAN_UPDATE_MOVE_THRESHOLD )
825                                                 {
826 #ifdef __DETAIL_DEBUG__
827                                                         ErrorF("[GroupPan] PAN Update !dx=%d, dy=%d, state=%d\n", dx, dy, state);
828 #endif//__DETAIL_DEBUG__
829
830                                                         GestureHandleGesture_Pan(num_pressed, dx, dy, direction, distance, current_time-prev_time, GestureUpdate);
831                                                 }
832                                         }
833                                         prev_cx = cx;
834                                         prev_cy = cy;
835                                         prev_time = current_time;
836                                 }
837                                 mbits = 0;
838                         }
839                         break;
840
841                 case ET_ButtonRelease:
842                         if( state != GestureEnd && num_pressed >= 2)
843                         {
844 #ifdef __DETAIL_DEBUG__
845                                 ErrorF("[GroupPan][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
846 #endif//__DETAIL_DEBUG__
847                                 goto cleanup_pan;
848                         }
849
850                         if( g_pGesture->num_pressed )
851                                 break;
852
853                         goto cleanup_pan;
854                         break;
855         }
856
857         return;
858
859 cleanup_pan:
860
861         if( state == GestureBegin || state == GestureUpdate )
862         {
863                 state = GestureEnd;
864                 if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
865                 {
866                         GestureHandleGesture_Pan(num_pressed, (short int)(cx-prev_cx), (short int)(cy-prev_cy), direction, distance, GetTimeInMillis()-prev_time, GestureEnd);
867                 }
868         }
869         else
870         {
871                 g_pGesture->recognized_gesture &= ~PanFilterMask;
872         }
873
874         g_pGesture->filter_mask |= PanFilterMask;
875         num_pressed = 0;
876         base_area_size = 0;
877         base_time = 0;
878         mbits = 0;
879         time_checked = 0;
880         state = GestureEnd;
881         cx = cy = 0;
882         prev_time = 0;
883         base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
884         TimerCancel(pan_event_timer);
885         return;
886 }
887
888 void
889 GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
890 {
891         static int num_pressed = 0;
892         static int base_area_size = 0;
893
894         static Time base_time = 0;
895         Time current_time;
896
897         int cx, cy;
898         int area_size;
899
900         static int state = 0;
901         static int mbits = 0;
902         static int base_cx;
903         static int base_cy;
904         static pixman_box16_t base_box_ext;
905
906         static int tap_repeat = 0;
907         static int prev_tap_repeat = 0;
908         static int prev_num_pressed = 0;
909
910         static OsTimerPtr tap_event_timer = NULL;
911         static int event_type = GestureNotifyTap;
912
913         if( timer_expired )
914         {
915 #ifdef __DETAIL_DEBUG__
916                 ErrorF("[GroupTap][Timer] state=%d\n", state);
917 #endif//__DETAIL_DEBUG__
918
919                 switch( state )
920                 {
921                         case 1://first tap initiation check
922                                 if( num_pressed )
923                                 {
924 #ifdef __DETAIL_DEBUG__
925                                         ErrorF("[GroupTap][Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", tap_repeat, num_pressed, tap_repeat);
926 #endif//__DETAIL_DEBUG__
927                                         state = 0;
928                                         goto cleanup_tap;
929                                 }
930                                 break;
931
932                         case 2:
933                                 if( tap_repeat <= 1 )
934                                 {
935 #ifdef __DETAIL_DEBUG__
936                                         ErrorF("[GroupTap][Timer][state=2] %d finger SINGLE TAP !(ignored)\n", prev_num_pressed);
937 #endif//__DETAIL_DEBUG__
938                                         state = 0;
939                                         goto cleanup_tap;
940                                 }
941
942 #ifdef __DETAIL_DEBUG__
943                                 ErrorF("[GroupTap][Timer][state=2]  tap_repeat=%d, prev_tap_repeat=%d, num_pressed=%d\n", tap_repeat, prev_tap_repeat, num_pressed);
944 #endif//__DETAIL_DEBUG__
945                                 if( GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed) )
946                                         GestureHandleGesture_Tap(prev_num_pressed, tap_repeat, base_cx, base_cy);
947                                 goto cleanup_tap;
948                                 break;
949                 }
950
951                 return;
952         }
953
954         switch( type )
955         {
956                 case ET_ButtonPress:
957                         g_pGesture->fingers[idx].flags |= PressFlagTap;
958
959                         if( g_pGesture->num_pressed < 2 )
960                                 return;
961
962                         if( !prev_num_pressed && (!base_area_size || g_pGesture->num_pressed > num_pressed) )
963                         {
964                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
965                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
966                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
967                                 base_time = GetTimeInMillis();
968                                 base_box_ext.x1 = base_cx-TAP_MOVE_THRESHOLD;
969                                 base_box_ext.y1 = base_cy-TAP_MOVE_THRESHOLD;
970                                 base_box_ext.x2 = base_cx+TAP_MOVE_THRESHOLD;
971                                 base_box_ext.y2 = base_cy+TAP_MOVE_THRESHOLD;
972                                 state = 1;
973                                 TimerCancel(tap_event_timer);
974                                 tap_event_timer = TimerSet(tap_event_timer, 0, SGL_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
975                         }
976
977                         num_pressed = g_pGesture->num_pressed;
978
979                         current_time = GetTimeInMillis();
980
981 #ifdef __DETAIL_DEBUG__
982                         ErrorF("[GroupTap][P][num_pressed=%d] AREA_SIZE(area.extents)=%d, base_cx=%d, base_cy=%d, base_time=%d, current_time=%d\n", num_pressed, base_area_size, base_cx, base_cy, base_time, current_time);
983 #endif//__DETAIL_DEBUG__
984                         break;
985
986                 case ET_Motion:
987                         if( !(g_pGesture->fingers[idx].flags & PressFlagTap ) )
988                                 break;
989
990                         if( num_pressed < 2 )
991                                 return;
992
993                         if( num_pressed != g_pGesture->num_pressed )
994                         {
995 #ifdef __DETAIL_DEBUG__
996                                 ErrorF("[GroupTap][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
997 #endif//__DETAIL_DEBUG__
998                                 //goto cleanup_tap;
999                         }
1000
1001                         mbits |= (1 << idx);
1002                         if( mbits == (pow(2, num_pressed)-1) )
1003                         {
1004                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1005                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1006                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1007 #ifdef __DETAIL_DEBUG__
1008                                 ErrorF("[GroupTap][M][num_pressed=%d] area_size=%d, base_area_size=%d, diff=%d\n", num_pressed, area_size, base_area_size, ABS(base_area_size - area_size));
1009                                 ErrorF("[GroupTap][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1010                                 ErrorF("[GroupTap][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1011 #endif//__DETAIL_DEBUG__
1012
1013                                 if( ABS(base_area_size-area_size) >= TAP_AREA_THRESHOLD )
1014                                 {
1015 #ifdef __DETAIL_DEBUG__
1016                                         ErrorF("[GroupTap][M] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, ABS(base_area_size-area_size));
1017 #endif//__DETAIL_DEBUG__
1018                                         goto cleanup_tap;
1019                                 }
1020
1021                                 if( !INBOX(&base_box_ext, cx, cy) )
1022                                 {
1023 #ifdef __DETAIL_DEBUG__
1024                                         ErrorF("[GroupTap][M] current center coordinates is not in base coordinates box !\n");
1025 #endif//__DETAIL_DEBUG__
1026                                         goto cleanup_tap;
1027                                 }
1028                         }
1029                         break;
1030
1031                 case ET_ButtonRelease:
1032                         if( g_pGesture->num_pressed )
1033                                 break;
1034
1035                         if( !tap_repeat )
1036                         {
1037                                 prev_num_pressed = num_pressed;
1038                         }
1039
1040                         prev_tap_repeat = tap_repeat;
1041                         tap_repeat++;
1042
1043 #ifdef __DETAIL_DEBUG__
1044                         ErrorF("[GroupTap][R] tap_repeat=%d, prev_tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, prev_tap_repeat, num_pressed, prev_num_pressed);
1045 #endif//__DETAIL_DEBUG__
1046
1047                         if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
1048                         {
1049 #ifdef __DETAIL_DEBUG__
1050                                 ErrorF("[GroupTap][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
1051                                         num_pressed, prev_num_pressed, num_pressed);
1052 #endif//__DETAIL_DEBUG__
1053                                 goto cleanup_tap;
1054                         }
1055
1056                         if( tap_repeat < MAX_TAP_REPEATS )
1057                         {
1058                                 state = 2;
1059                                 TimerCancel(tap_event_timer);
1060                                 tap_event_timer = TimerSet(tap_event_timer, 0, DBL_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1061                                 num_pressed = 0;
1062                                 break;
1063                         }
1064
1065 #ifdef __DETAIL_DEBUG__
1066                         ErrorF("[GroupTap][R] %d finger %s\n", num_pressed, (tap_repeat==2) ? "DBL_TAP" : "TRIPLE_TAP");
1067 #endif//__DETAIL_DEBUG__
1068
1069                         if( GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
1070                                 GestureHandleGesture_Tap(num_pressed, tap_repeat, base_cx, base_cy);
1071
1072                         if( tap_repeat >= MAX_TAP_REPEATS )
1073                         {
1074                                 goto cleanup_tap;
1075                         }
1076
1077                         prev_num_pressed = num_pressed;
1078                         num_pressed = 0;
1079                         break;
1080         }
1081
1082         return;
1083
1084 cleanup_tap:
1085
1086         if( 0 == state )
1087                 g_pGesture->recognized_gesture &= ~TapFilterMask;
1088         g_pGesture->filter_mask |= TapFilterMask;
1089
1090         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
1091         {
1092 #ifdef __DETAIL_DEBUG__
1093                 ErrorF("[GroupTap][cleanup] GestureFlushOrDrop() !\n");
1094 #endif//__DETAIL_DEBUG__
1095
1096                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
1097                 {
1098                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
1099                 }
1100         }
1101
1102         num_pressed = 0;
1103         tap_repeat = 0;
1104         prev_num_pressed = 0;
1105         mbits = 0;
1106         base_time = 0;
1107         state = 0;
1108         TimerCancel(tap_event_timer);
1109         return;
1110 }
1111
1112 void
1113 GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1114 {
1115         static int num_pressed = 0;
1116         static int base_area_size = 0;
1117         static Time base_time = 0;
1118         static int base_cx;
1119         static int base_cy;
1120         int cx, cy;
1121         static pixman_box16_t base_box_ext;
1122         int area_size;
1123         static int mbits = 0;
1124
1125         static int tap_repeat = 0;
1126         static int prev_num_pressed = 0;
1127
1128         static OsTimerPtr tapnhold_event_timer = NULL;
1129         static int event_type = GestureNotifyTapNHold;
1130         static int state = GestureEnd;
1131
1132         Time interval = 0;
1133         Time holdtime = 0;
1134
1135         if( timer_expired )
1136         {
1137                 if( (state == GestureEnd) && num_pressed )
1138                 {
1139 #ifdef __DETAIL_DEBUG__
1140                         ErrorF("[GroupTapNHold][Timer][state=%d] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", GestureEnd, tap_repeat, num_pressed, tap_repeat);
1141 #endif//__DETAIL_DEBUG__
1142                         state = 0;
1143                         goto cleanup_tapnhold;
1144                 }
1145
1146                 if( state == GestureDone )
1147                 {
1148 #ifdef __DETAIL_DEBUG__
1149                         ErrorF("[GroupTapNHold][Timer][state=%d] Interval between Tap and Hold is too long !\n");
1150 #endif//__DETAIL_DEBUG__
1151                         goto cleanup_tapnhold;
1152                 }
1153
1154 #ifdef __DETAIL_DEBUG__
1155                 switch( state )
1156                 {
1157                         case GestureBegin:
1158                                 ErrorF("[GroupTapNHold][Timer] TapNHold Begin !\n");
1159                                 break;
1160
1161                         case GestureUpdate:
1162                                 ErrorF("[GroupTapNHold][Timer] TapNHold Update !\n");
1163                                 break;
1164                 }
1165 #endif//__DETAIL_DEBUG__
1166
1167                 if( GestureHasFingerEventMask(GestureNotifyTapNHold, prev_num_pressed) )
1168                 {
1169                         GestureHandleGesture_TapNHold(prev_num_pressed, base_cx, base_cy, interval, holdtime, state);
1170                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1171                 }
1172                 else
1173                 {
1174 #ifdef __DETAIL_DEBUG__
1175                         ErrorF("[GroupTapNHold][Timer] %d finger TapNHold event was not grabbed/selected !\n", prev_num_pressed);
1176 #endif//__DETAIL_DEBUG__
1177                         goto cleanup_tapnhold;
1178                 }
1179
1180                 if( state <= GestureBegin )
1181                         state++;
1182                 return;
1183         }
1184
1185         switch( type )
1186         {
1187                 case ET_ButtonPress:
1188                         g_pGesture->fingers[idx].flags |= PressFlagTapNHold;
1189
1190                         if( g_pGesture->num_pressed < 2 )
1191                                 return;
1192
1193                         //if( !prev_num_pressed && (!base_area_size || g_pGesture->num_pressed > num_pressed) )
1194                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1195                         {
1196
1197                                 if( state == GestureUpdate )
1198                                 {
1199 #ifdef __DETAIL_DEBUG__
1200                                         ErrorF("[GroupTapNHold][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1201 #endif//__DETAIL_DEBUG__
1202                                         goto cleanup_tapnhold;
1203                                 }
1204
1205                                 if( state == GestureDone )
1206                                         state = GestureBegin;
1207
1208                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1209                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1210                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1211                                 base_time = GetTimeInMillis();
1212                                 base_box_ext.x1 = base_cx-TAPNHOLD_MOVE_THRESHOLD;
1213                                 base_box_ext.y1 = base_cy-TAPNHOLD_MOVE_THRESHOLD;
1214                                 base_box_ext.x2 = base_cx+TAPNHOLD_MOVE_THRESHOLD;
1215                                 base_box_ext.y2 = base_cy+TAPNHOLD_MOVE_THRESHOLD;
1216                                 if( state == GestureEnd )
1217                                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1218                                 else
1219                                 {
1220                                         TimerCancel(tapnhold_event_timer);
1221                                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1222                                 }
1223 #ifdef __DETAIL_DEBUG__
1224                                 ErrorF("[GroupTapNHold][P] Create Timer !(state=%d)\n", state);
1225 #endif//__DETAIL_DEBUG__
1226                         }
1227
1228                         num_pressed = g_pGesture->num_pressed;
1229
1230 #ifdef __DETAIL_DEBUG__
1231                         ErrorF("[GroupTapNHold][P][num_pressed=%d] AREA_SIZE(area.extents)=%d, base_cx=%d, base_cy=%d, base_time=%d\n", num_pressed, base_area_size, base_cx, base_cy, base_time);
1232 #endif//__DETAIL_DEBUG__
1233                         break;
1234
1235                 case ET_Motion:
1236                         if( !(g_pGesture->fingers[idx].flags & PressFlagTapNHold ) )
1237                                 break;
1238
1239                         if( num_pressed < 2 )
1240                                 return;
1241
1242                         if( num_pressed != g_pGesture->num_pressed )
1243                         {
1244                                 if( state != GestureEnd )
1245                                 {
1246 #ifdef __DETAIL_DEBUG__
1247                                 ErrorF("[GroupTapNHold][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1248 #endif//__DETAIL_DEBUG__
1249                                         goto cleanup_tapnhold;
1250                                 }
1251 #ifdef __DETAIL_DEBUG__
1252                                 ErrorF("[GroupTapNHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1253 #endif//__DETAIL_DEBUG__
1254                                 //goto cleanup_tapnhold;
1255                         }
1256
1257                         mbits |= (1 << idx);
1258                         if( mbits == (pow(2, num_pressed)-1) )
1259                         {
1260                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1261                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1262                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1263 #ifdef __DETAIL_DEBUG__
1264                                 ErrorF("[GroupTapNHold][M][num_pressed=%d] area_size=%d, base_area_size=%d, diff=%d\n", num_pressed, area_size, base_area_size, ABS(base_area_size - area_size));
1265                                 ErrorF("[GroupTapNHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1266                                 ErrorF("[GroupTapNHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1267 #endif//__DETAIL_DEBUG__
1268
1269                                 if( ABS(base_area_size-area_size) >= TAPNHOLD_AREA_THRESHOLD )
1270                                 {
1271 #ifdef __DETAIL_DEBUG__
1272                                         ErrorF("[GroupTapNHold][M] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, ABS(base_area_size-area_size));
1273 #endif//__DETAIL_DEBUG__
1274                                         goto cleanup_tapnhold;
1275                                 }
1276
1277                                 if( !INBOX(&base_box_ext, cx, cy) )
1278                                 {
1279 #ifdef __DETAIL_DEBUG__
1280                                         ErrorF("[GroupTapNHold][M] current center coordinates is not in base coordinates box !\n");
1281 #endif//__DETAIL_DEBUG__
1282                                         goto cleanup_tapnhold;
1283                                 }
1284                         }
1285                         break;
1286
1287                 case ET_ButtonRelease:
1288                         if( state != GestureEnd && num_pressed >= 2)
1289                         {
1290 #ifdef __DETAIL_DEBUG__
1291                                 ErrorF("[GroupTapNHold][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1292 #endif//__DETAIL_DEBUG__
1293                                 goto cleanup_tapnhold;
1294                         }
1295
1296                         if( g_pGesture->num_pressed )
1297                                 break;
1298
1299                         if( !tap_repeat )
1300                         {
1301                                 prev_num_pressed = num_pressed;
1302                         }
1303
1304                         tap_repeat++;
1305
1306 #ifdef __DETAIL_DEBUG__
1307                         ErrorF("[GroupTapNHold][R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed);
1308 #endif//__DETAIL_DEBUG__
1309
1310                         if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTapNHold, num_pressed) )
1311                         {
1312 #ifdef __DETAIL_DEBUG__
1313                                 ErrorF("[GroupTapNHold][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
1314                                         num_pressed, prev_num_pressed, num_pressed);
1315 #endif//__DETAIL_DEBUG__
1316                                 goto cleanup_tapnhold;
1317                         }
1318
1319                         if( tap_repeat > 1 )
1320                         {
1321 #ifdef __DETAIL_DEBUG__
1322                                 ErrorF("[GroupTapNHold][R] Tap events(tap_repeat=%d) were put twice or more !(ignored)\n", tap_repeat);
1323 #endif//__DETAIL_DEBUG__
1324                                 goto cleanup_tapnhold;
1325                         }
1326
1327                         prev_num_pressed = num_pressed;
1328                         num_pressed = 0;
1329                         state = GestureDone;
1330
1331                         TimerCancel(tapnhold_event_timer);
1332                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_INTV_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1333
1334 #ifdef __DETAIL_DEBUG__
1335                         ErrorF("[GroupTapNHold][R][Last] state=%d, tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", state,  tap_repeat, num_pressed, prev_num_pressed);
1336 #endif//__DETAIL_DEBUG__
1337                         break;
1338         }
1339
1340         return;
1341
1342 cleanup_tapnhold:
1343
1344         if( state == GestureUpdate )
1345         {
1346                 state = GestureEnd;
1347                 if( GestureHasFingerEventMask(GestureNotifyTapNHold, prev_num_pressed) )
1348                 {
1349                         GestureHandleGesture_TapNHold(prev_num_pressed, base_cx, base_cy, interval, holdtime, state);
1350                 }
1351         }
1352         else
1353         {
1354                 g_pGesture->recognized_gesture &= ~TapNHoldFilterMask;
1355         }
1356
1357         g_pGesture->filter_mask |= TapNHoldFilterMask;
1358         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
1359         {
1360 #ifdef __DETAIL_DEBUG__
1361                 ErrorF("[GroupTapNHold][cleanup] GestureFlushOrDrop() !\n");
1362 #endif//__DETAIL_DEBUG__
1363
1364                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
1365                 {
1366                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
1367                 }
1368         }
1369
1370         TimerCancel(tapnhold_event_timer);
1371         num_pressed = 0;
1372         tap_repeat = 0;
1373         prev_num_pressed = 0;
1374         mbits = 0;
1375         base_time = 0;
1376         state = 0;
1377
1378         return;
1379 }
1380
1381 void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1382 {
1383         static int num_pressed = 0;
1384         static int base_area_size = 0;
1385         static Time base_time = 0;
1386         static int base_cx;
1387         static int base_cy;
1388         int cx, cy;
1389         static pixman_box16_t base_box_ext;
1390         int area_size;
1391         static int state = GestureEnd;
1392
1393         static OsTimerPtr hold_event_timer = NULL;
1394         static int event_type = GestureNotifyHold;
1395
1396         if( timer_expired )
1397         {
1398                 if( state <= GestureBegin )
1399                         state++;
1400
1401 #ifdef __DETAIL_DEBUG__
1402                 switch( state )
1403                 {
1404                         case GestureBegin:
1405                                 ErrorF("[GroupHold] HOLD Begin !\n");
1406                                 break;
1407
1408                         case GestureUpdate:
1409                                 ErrorF("[GroupHold] HOLD Update !\n");
1410                                 break;
1411                 }
1412 #endif//__DETAIL_DEBUG__
1413
1414                 if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
1415                 {
1416                         GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
1417                         hold_event_timer = TimerSet(hold_event_timer, 0, HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1418                 }
1419                 return;
1420         }
1421
1422         switch( type )
1423         {
1424                 case ET_ButtonPress:
1425                         g_pGesture->fingers[idx].flags |= PressFlagHold;
1426
1427                         if( g_pGesture->num_pressed < 2 )
1428                                 return;
1429
1430                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1431                         {
1432                                 if( state != GestureEnd )
1433                                 {
1434 #ifdef __DETAIL_DEBUG__
1435                                         ErrorF("[GroupHold][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1436 #endif//__DETAIL_DEBUG__
1437                                         goto cleanup_hold;
1438                                 }
1439
1440                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1441                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1442                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1443                                 base_time = GetTimeInMillis();
1444                                 base_box_ext.x1 = base_cx-HOLD_MOVE_THRESHOLD;
1445                                 base_box_ext.y1 = base_cy-HOLD_MOVE_THRESHOLD;
1446                                 base_box_ext.x2 = base_cx+HOLD_MOVE_THRESHOLD;
1447                                 base_box_ext.y2 = base_cy+HOLD_MOVE_THRESHOLD;
1448                                 event_type = GestureNotifyHold;
1449                                 hold_event_timer = TimerSet(hold_event_timer, 0, HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1450                         }
1451                         num_pressed = g_pGesture->num_pressed;
1452
1453 #ifdef __DETAIL_DEBUG__
1454                         ErrorF("[GroupHold][P]][num_pressed=%d] AREA_SIZE(area.extents)=%d, base_cx=%d, base_cy=%d\n", num_pressed, base_area_size, base_cx, base_cy);
1455 #endif//__DETAIL_DEBUG__
1456                         break;
1457
1458                 case ET_Motion:
1459                         if( !(g_pGesture->fingers[idx].flags & PressFlagHold ) )
1460                                 break;
1461
1462                         if( num_pressed < 2 )
1463                                 return;
1464
1465                         if( num_pressed != g_pGesture->num_pressed )
1466                         {
1467                                 if( state != GestureEnd )
1468                                 {
1469 #ifdef __DETAIL_DEBUG__
1470                                 ErrorF("[GroupHold][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1471 #endif//__DETAIL_DEBUG__
1472                                         goto cleanup_hold;
1473                                 }
1474 #ifdef __DETAIL_DEBUG__
1475                                 ErrorF("[GroupHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1476 #endif//__DETAIL_DEBUG__
1477                                 //goto cleanup_hold;
1478                         }
1479
1480                         area_size = AREA_SIZE(&g_pGesture->area.extents);
1481                         cx = AREA_CENTER_X(&g_pGesture->area.extents);
1482                         cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1483 #ifdef __DETAIL_DEBUG__
1484                         ErrorF("[GroupHold][M][num_pressed=%d] area_size=%d, base_area_size=%d, diff=%d\n", num_pressed, area_size, base_area_size, ABS(base_area_size - area_size));
1485                         ErrorF("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1486                         ErrorF("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1487 #endif//__DETAIL_DEBUG__
1488
1489                         if( ABS(base_area_size-area_size) >= HOLD_AREA_THRESHOLD )
1490                         {
1491 #ifdef __DETAIL_DEBUG__
1492                                 ErrorF("[GroupHold][M] diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%d)!\n", area_size, base_area_size, ABS(base_area_size-area_size));
1493 #endif//__DETAIL_DEBUG__
1494                                 goto cleanup_hold;
1495                         }
1496
1497                         if( !INBOX(&base_box_ext, cx, cy) )
1498                         {
1499 #ifdef __DETAIL_DEBUG__
1500                                 ErrorF("[GroupHold][M] current center coordinates is not in base coordinates box !\n");
1501 #endif//__DETAIL_DEBUG__
1502                                 goto cleanup_hold;
1503                         }
1504                         break;
1505
1506                 case ET_ButtonRelease:
1507                         if( state != GestureEnd && num_pressed >= 2)
1508                         {
1509 #ifdef __DETAIL_DEBUG__
1510                                 ErrorF("[GroupHold][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1511 #endif//__DETAIL_DEBUG__
1512                                 goto cleanup_hold;
1513                         }
1514
1515                         //ErrorF("[GroupHold][R] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1516                         if( g_pGesture->num_pressed )
1517                                 break;
1518
1519                         goto cleanup_hold;
1520                         break;
1521         }
1522
1523         return;
1524
1525 cleanup_hold:
1526
1527         if( state == GestureBegin || state == GestureUpdate )
1528         {
1529                 state = GestureEnd;
1530                 if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
1531                 {
1532                         GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
1533                 }
1534         }
1535         else
1536         {
1537                 g_pGesture->recognized_gesture &= ~HoldFilterMask;
1538         }
1539
1540         g_pGesture->filter_mask |= HoldFilterMask;
1541         num_pressed = 0;
1542         base_area_size = 0;
1543         base_time = 0;
1544         base_cx = base_cy = 0;
1545         state = GestureEnd;
1546         base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
1547         TimerCancel(hold_event_timer);
1548         return;
1549 }
1550
1551 WindowPtr
1552 GestureGetEventsWindow(void)
1553 {
1554         Mask mask;
1555         WindowPtr pWin;
1556
1557         //check grabbed event(s)
1558         if( !GestureHasGrabbedEvents(&g_pGesture->grabMask, &g_pGesture->GrabEvents) )
1559                 g_pGesture->grabMask = 0;
1560
1561         pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py);
1562
1563         if( pWin )
1564         {
1565 #ifdef __DETAIL_DEBUG__
1566                 ErrorF("[X11][GestureGetEventsWindow] pWin->drawable.id=0x%x\n", pWin->drawable.id);
1567 #endif//__DETAIL_DEBUG__
1568                 g_pGesture->gestureWin = pWin->drawable.id;
1569         }
1570         else
1571         {
1572 #ifdef __DETAIL_DEBUG__
1573                 ErrorF("[X11][GestureGetEventsWindow] GestureWindowOnXY returns NULL !\n");
1574 #endif//__DETAIL_DEBUG__
1575                 return NULL;
1576         }
1577
1578         //check selected event(s)
1579         if( !GestureHasSelectedEvents(pWin, &g_pGesture->eventMask) )
1580                 g_pGesture->eventMask = 0;
1581
1582         if( !g_pGesture->grabMask && !g_pGesture->eventMask )
1583         {
1584 #ifdef __DETAIL_DEBUG__
1585                 ErrorF("[X11][GestureGetEventsWindow] No events were grabbed/selected for window(0x%x) !\n", pWin->drawable.id);
1586 #endif//__DETAIL_DEBUG__
1587                 return NULL;
1588         }
1589
1590 #ifdef __DETAIL_DEBUG__
1591         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->grabMask=0x%x, g_pGesture->eventMask=0x%x\n",
1592                         g_pGesture->grabMask, g_pGesture->eventMask);
1593 #endif//__DETAIL_DEBUG__
1594
1595         mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask));
1596
1597 #ifdef __DETAIL_DEBUG__
1598         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x, mask=0x%x\n", g_pGesture->filter_mask, mask);
1599 #endif//__DETAIL_DEBUG__
1600
1601         g_pGesture->filter_mask = mask;
1602
1603 #ifdef __DETAIL_DEBUG__
1604         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x\n", g_pGesture->filter_mask);
1605 #endif//__DETAIL_DEBUG__
1606
1607         return pWin;
1608 }
1609
1610 static CARD32
1611 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
1612 {
1613         int event_type = *(int *)arg;
1614
1615         switch( event_type )
1616         {
1617                 case GestureNotifyHold:
1618 #ifdef __DETAIL_DEBUG__
1619                         ErrorF("[GestureEventTimerHandler] GestureNotifyHold (event_type = %d)\n", event_type);
1620 #endif//__DETAIL_DEBUG__
1621                         GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1);
1622                         break;
1623
1624                 case GestureNotifyPan:
1625 #ifdef __DETAIL_DEBUG__
1626                         ErrorF("[GestureEventTimerHandler] GestureNotifyPan (event_type = %d)\n", event_type);
1627 #endif//__DETAIL_DEBUG__
1628                         GestureRecognize_GroupPan(event_type, NULL, NULL, 0, 1);
1629                         break;
1630
1631                 case GestureNotifyTap:
1632 #ifdef __DETAIL_DEBUG__
1633                         ErrorF("[GestureEventTimerHandler] GestureNotifyTap (event_type = %d)\n", event_type);
1634 #endif//__DETAIL_DEBUG__
1635                         GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1);
1636                         break;
1637
1638                 case GestureNotifyTapNHold:
1639 #ifdef __DETAIL_DEBUG__
1640                         ErrorF("[GestureEventTimerHandler] GestureNotifyTapNHold (event_type = %d)\n", event_type);
1641 #endif//__DETAIL_DEBUG__
1642                         GestureRecognize_GroupTapNHold(event_type, NULL, NULL, 0, 1);
1643                         break;
1644
1645                 default:
1646 #ifdef __DETAIL_DEBUG__
1647                         ErrorF("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type);
1648 #endif//__DETAIL_DEBUG__
1649                         if(timer)
1650                                 ErrorF("[GestureEventTimerHandler] timer=%x\n", (unsigned int)timer);
1651         }
1652
1653         return 0;
1654 }
1655
1656 static CARD32
1657 GestureSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
1658 {
1659         g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
1660         g_pGesture->recognized_gesture = 0;
1661
1662         if( ERROR_INVALPTR == GestureFlushOrDrop() )
1663         {
1664                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
1665         }
1666
1667 #ifdef __DETAIL_DEBUG__
1668         ErrorF("[X11][Single] expired !\n");
1669 #endif//__DETAIL_DEBUG__
1670
1671         return 0;
1672 }
1673
1674 void
1675 GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
1676 {
1677         int i;
1678         int idx = device->id - g_pGesture->first_fingerid;
1679         static OsTimerPtr single_finger_timer = NULL;
1680
1681         if( PROPAGATE_EVENTS == g_pGesture->ehtype )
1682                 return;
1683
1684         if( device->id < g_pGesture->first_fingerid )//filtering device id : 2
1685                 return;
1686
1687         switch( type )
1688         {
1689                 case ET_ButtonPress:
1690                         if( idx == 0 )
1691                                 g_pGesture->event_sum[0] = BTN_PRESSED;
1692                         g_pGesture->fingers[idx].ptime = ev->any.time;
1693                         g_pGesture->fingers[idx].px = ev->device_event.root_x;
1694                         g_pGesture->fingers[idx].py = ev->device_event.root_y;
1695
1696                         g_pGesture->num_pressed++;
1697                         if( g_pGesture->num_pressed == 1 )
1698                         {
1699                                 single_finger_timer = TimerSet(single_finger_timer, 0, 50, GestureSingleFingerTimerHandler, NULL);
1700                         }
1701                         else
1702                         {
1703                                 TimerCancel(single_finger_timer);
1704                         }
1705
1706                         if( g_pGesture->num_pressed > g_pGesture->num_mt_devices )
1707                                 g_pGesture->num_pressed = g_pGesture->num_mt_devices;
1708
1709                         if( !g_pGesture->pTempWin || g_pGesture->num_pressed != g_pGesture->inc_num_pressed )
1710                         {
1711                                 g_pGesture->pTempWin = GestureGetEventsWindow();
1712
1713                                 if( NULL == g_pGesture->pTempWin )
1714                                 {
1715 #ifdef __DETAIL_DEBUG__
1716                                         ErrorF("[X11][GestureRecognize][g_pGesture->num_pressed=%d] No grabbed events and no event masks !\n", g_pGesture->num_pressed);
1717 #endif//__DETAIL_DEBUG__
1718                                         g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
1719                                         goto flush_or_drop;
1720                                 }
1721                         }
1722
1723                         g_pGesture->inc_num_pressed = g_pGesture->num_pressed;
1724
1725                         g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
1726                         g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
1727                         g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
1728                         g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
1729
1730                         if( g_pGesture->inc_num_pressed == 1 )
1731                         {
1732                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
1733 #ifdef __DETAIL_DEBUG__
1734                                 ErrorF("[P][g_pGesture->inc_num_pressed=1] AREA_SIZE(area.extents)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
1735 #endif//__DETAIL_DEBUG__
1736                         }
1737                         else
1738                         {
1739                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
1740                                 for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
1741                                 {
1742                                         pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
1743                                 }
1744 #ifdef __DETAIL_DEBUG__
1745                                 ErrorF("[P][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area.extents)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
1746 #endif//__DETAIL_DEBUG__
1747                         }
1748                         break;
1749
1750                 case ET_Motion:
1751                         if( !g_pGesture->fingers[idx].ptime )
1752                                 return;
1753
1754                         g_pGesture->fingers[idx].mx = ev->device_event.root_x;
1755                         g_pGesture->fingers[idx].my = ev->device_event.root_y;
1756
1757                         if( idx == 0 && g_pGesture->event_sum[0] )
1758                         {
1759                                 g_pGesture->event_sum[0] += BTN_MOVING;
1760 #ifdef __DETAIL_DEBUG__
1761                                 ErrorF("[X11][GestureRecognize] moving !\n");
1762 #endif//__DETAIL_DEBUG__
1763                                 if( g_pGesture->event_sum[0] >= 7 )
1764                                 {
1765                                if( (g_pGesture->event_sum[0] >= 7) && (g_pGesture->inc_num_pressed < 2) )
1766                                 {
1767  #ifdef __DETAIL_DEBUG__
1768                                        ErrorF("[X11][GestureRecognize] moving limit!\n");
1769  #endif//__DETAIL_DEBUG__
1770                                        g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
1771                                             goto flush_or_drop;
1772                                 }
1773                                 }
1774                         }
1775
1776                         g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
1777                         g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
1778                         g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
1779                         g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
1780
1781                         if( g_pGesture->inc_num_pressed == 1 )
1782                         {
1783                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
1784 #ifdef __DETAIL_DEBUG__
1785                                 ErrorF("[M][g_pGesture->inc_num_pressed=1] AREA_SIZE(area)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
1786 #endif//__DETAIL_DEBUG__
1787                         }
1788                         else
1789                         {
1790                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
1791                                 for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
1792                                 {
1793                                         pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
1794                                 }
1795 #ifdef __DETAIL_DEBUG__
1796                                 ErrorF("[M][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
1797 #endif//__DETAIL_DEBUG__
1798                         }
1799                         break;
1800
1801                 case ET_ButtonRelease:
1802                         g_pGesture->fingers[idx].rtime = ev->any.time;
1803                         g_pGesture->fingers[idx].rx = ev->device_event.root_x;
1804                         g_pGesture->fingers[idx].ry = ev->device_event.root_y;
1805
1806                         g_pGesture->num_pressed--;
1807                         if( g_pGesture->num_pressed <= 0 )
1808                         {
1809 #ifdef __DETAIL_DEBUG__
1810         ErrorF("[X11][GestureRecognize] All fingers were released !\n");
1811 #endif//__DETAIL_DEBUG__
1812                                 if( g_pGesture->inc_num_pressed == 1 )
1813                                         goto flush_or_drop;
1814                         }
1815                         break;
1816         }
1817
1818         if( g_pGesture->filter_mask != GESTURE_FILTER_MASK_ALL )
1819         {
1820                 if( !(g_pGesture->filter_mask & FlickFilterMask) )
1821                 {
1822                         GestureRecognize_GroupFlick(type, ev, device, idx);
1823                 }
1824                 if( !(g_pGesture->filter_mask & PanFilterMask) )
1825                 {
1826                         GestureRecognize_GroupPan(type, ev, device, idx, 0);
1827                 }
1828                 if( !(g_pGesture->filter_mask & PinchRotationFilterMask) )
1829                 {
1830                         GestureRecognize_GroupPinchRotation(type, ev, device, idx);
1831                 }
1832                 if( !(g_pGesture->filter_mask & TapFilterMask) )
1833                 {
1834                         GestureRecognize_GroupTap(type, ev, device, idx, 0);
1835                 }
1836                 if( !(g_pGesture->filter_mask & TapNHoldFilterMask) )
1837                 {
1838                         GestureRecognize_GroupTapNHold(type, ev, device, idx, 0);
1839                 }
1840                 if( !(g_pGesture->filter_mask & HoldFilterMask) )
1841                 {
1842                         GestureRecognize_GroupHold(type, ev, device, idx, 0);
1843                 }
1844         }
1845
1846 #ifdef __DETAIL_DEBUG__
1847         ErrorF("[X11][GestureRecognize][N] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
1848         ErrorF("[X11][GestureRecognize][N] g_pGesture->GESTURE_FILTER_MASK_ALL = 0x%x\n", GESTURE_FILTER_MASK_ALL);
1849         ErrorF("[X11][GestureRecognize][N] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
1850 #endif//__DETAIL_DEBUG__
1851
1852         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
1853         {
1854                 if( !g_pGesture->recognized_gesture )
1855                         goto flush_or_drop;
1856                 else if( !g_pGesture->num_pressed )
1857                         goto flush_or_drop;
1858         }
1859
1860         if( g_pGesture->recognized_gesture )
1861         {
1862                 if( g_pGesture->ehtype == KEEP_EVENTS )
1863                         GestureEventsDrop();
1864                 g_pGesture->ehtype = IGNORE_EVENTS;
1865         }
1866
1867         return;
1868
1869 flush_or_drop:
1870
1871 #ifdef __DETAIL_DEBUG__
1872         ErrorF("[GestureRecognize] GestureFlushOrDrop() !\n");
1873 #endif//__DETAIL_DEBUG__
1874         if( ERROR_INVALPTR == GestureFlushOrDrop() )
1875         {
1876                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
1877         }
1878 }
1879
1880
1881 ErrorStatus GestureFlushOrDrop(void)
1882 {
1883         ErrorStatus err;
1884
1885         if( g_pGesture->recognized_gesture )
1886         {
1887                 GestureEventsDrop();
1888         }
1889         else
1890         {
1891                 g_pGesture->ehtype = PROPAGATE_EVENTS;
1892
1893                 err = GestureEventsFlush();
1894                 if( ERROR_NONE != err )
1895                         return err;
1896
1897 #ifdef __DETAIL_DEBUG__
1898                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
1899                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->GESTURE_FILTER_MASK_ALL = 0x%x\n", GESTURE_FILTER_MASK_ALL);
1900                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
1901 #endif//__DETAIL_DEBUG__
1902         }
1903
1904         err = GestureRegionsReinit();
1905         if( ERROR_NONE != err )
1906                 return err;
1907
1908         g_pGesture->pTempWin = NULL;
1909         g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
1910         g_pGesture->event_sum[0] = 0;
1911
1912         return ERROR_NONE;
1913 }
1914
1915 void
1916 GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
1917 {
1918         int i;
1919
1920 #ifdef __DEBUG_EVENT_HANDLER__
1921         ErrorF("\n[X11][GestureHandleMTSyncEvent] (%d:%d) time:%d cur:%d\n",
1922                         ev->any_event.deviceid, ev->any_event.sync, (int)ev->any.time, (int)GetTimeInMillis());
1923 #endif//__DEBUG_EVENT_HANDLER__
1924
1925         if( MTOUCH_FRAME_SYNC_BEGIN == ev->any_event.sync )
1926         {
1927                 g_pGesture->ehtype = KEEP_EVENTS;
1928                 g_pGesture->filter_mask = 0;
1929                 g_pGesture->recognized_gesture = 0;
1930                 g_pGesture->num_pressed = 0;
1931
1932                 for( i=0 ; i < g_pGesture->num_mt_devices ; i++ )
1933                         g_pGesture->fingers[i].ptime = 0;
1934         }
1935         else if( MTOUCH_FRAME_SYNC_END == ev->any_event.sync )
1936         {
1937                 g_pGesture->ehtype = PROPAGATE_EVENTS;
1938         }
1939 }
1940
1941 void
1942 GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
1943 {
1944 #ifdef __DEBUG_EVENT_HANDLER__
1945         ErrorF("[X11][GestureHandleButtonPEvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
1946 #endif//__DEBUG_EVENT_HANDLER__
1947
1948         switch( g_pGesture->ehtype )
1949         {
1950                 case KEEP_EVENTS:
1951                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
1952                         {
1953                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
1954                                 return;
1955                         }
1956
1957                         if( g_pGesture->num_mt_devices )
1958                                 GestureRecognize(ET_ButtonPress, ev, device);
1959                         else
1960                                 device->public.processInputProc(ev, device);
1961                         break;
1962
1963                 case PROPAGATE_EVENTS:
1964                         device->public.processInputProc(ev, device);
1965                         break;
1966
1967                 case IGNORE_EVENTS:
1968                         GestureRecognize(ET_ButtonPress, ev, device);
1969                         break;
1970
1971                 default:
1972                         break;
1973         }
1974 }
1975
1976 void
1977 GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
1978 {
1979 #ifdef __DEBUG_EVENT_HANDLER__
1980         ErrorF("[X11][GestureHandleMotionEvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
1981 #endif//__DEBUG_EVENT_HANDLER__
1982
1983         switch( g_pGesture->ehtype )
1984         {
1985                 case KEEP_EVENTS:
1986                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
1987                         {
1988                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
1989                                 return;
1990                         }
1991
1992                         if( g_pGesture->num_mt_devices )
1993                                 GestureRecognize(ET_Motion, ev, device);
1994                         else
1995                                 device->public.processInputProc(ev, device);
1996                         break;
1997
1998                 case PROPAGATE_EVENTS:
1999                         device->public.processInputProc(ev, device);
2000                         break;
2001
2002                 case IGNORE_EVENTS:
2003                         GestureRecognize(ET_Motion, ev, device);
2004                         break;
2005
2006                 default:
2007                         break;
2008         }
2009
2010 }
2011
2012 void
2013 GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2014 {
2015 #ifdef __DEBUG_EVENT_HANDLER__
2016         ErrorF("[X11][GestureHandleButtonREvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
2017 #endif//__DEBUG_EVENT_HANDLER__
2018
2019         switch( g_pGesture->ehtype )
2020         {
2021                 case KEEP_EVENTS:
2022                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
2023                         {
2024                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2025                                 return;
2026                         }
2027
2028                         if( g_pGesture->num_mt_devices )
2029                                 GestureRecognize(ET_ButtonRelease, ev, device);
2030                         else
2031                                 device->public.processInputProc(ev, device);
2032                         break;
2033
2034                 case PROPAGATE_EVENTS:
2035                         device->public.processInputProc(ev, device);
2036                         break;
2037
2038                 case IGNORE_EVENTS:
2039                         GestureRecognize(ET_ButtonRelease, ev, device);
2040                         break;
2041
2042                 default:
2043                         break;
2044         }
2045 }
2046
2047 static ErrorStatus
2048 GestureEnableEventHandler(InputInfoPtr pInfo)
2049  {
2050         Bool res;
2051         GestureDevicePtr pGesture = pInfo->private;
2052
2053         res = GestureInstallResourceStateHooks();
2054
2055         if( !res )
2056         {
2057                 ErrorF("[X11][GestureEnableEventHandler] Failed on GestureInstallResourceStateHooks() !\n");
2058                 return ERROR_ABNORMAL;
2059         }
2060
2061         res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES);
2062
2063         if( !res )
2064         {
2065                 ErrorF("[X11][GestureEnableEventHandler] Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES);
2066                 goto failed;
2067         }
2068
2069         pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 500, GestureTimerHandler, pInfo);
2070
2071         if( !pGesture->device_setting_timer )
2072         {
2073                 ErrorF("[X11][GestureEnableEventHandler] Failed to allocate memory for timer !\n");
2074                 goto failed;
2075         }
2076
2077         if( ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ() )
2078         {
2079                 goto failed;
2080         }
2081
2082         mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
2083         mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
2084         mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
2085         if( pGesture->is_active )
2086                 mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
2087
2088         return ERROR_NONE;
2089
2090 failed:
2091         GestureUninstallResourceStateHooks();
2092         GestureUnsetMaxNumberOfFingers();
2093
2094         return ERROR_ABNORMAL;
2095 }
2096
2097 static ErrorStatus
2098 GestureDisableEventHandler(void)
2099 {
2100         ErrorStatus err = ERROR_NONE;
2101
2102         mieqSetHandler(ET_ButtonPress, NULL);
2103         mieqSetHandler(ET_ButtonRelease, NULL);
2104         mieqSetHandler(ET_Motion, NULL);
2105         mieqSetHandler(ET_MTSync, NULL);
2106
2107         err = GestureFiniEQ();
2108
2109         if( ERROR_INVALPTR == err )
2110         {
2111                 ErrorF("[X11][GestureDisableEventHandler] EQ is invalid or was freed already !\n");
2112         }
2113
2114         GestureUninstallResourceStateHooks();
2115         GestureUnsetMaxNumberOfFingers();
2116
2117         return err;
2118 }
2119
2120 static CARD32
2121 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
2122 {
2123         InputInfoPtr pInfo = (InputInfoPtr)arg;
2124         GestureDevicePtr pGesture = pInfo->private;
2125
2126         int idx = 0;
2127         DeviceIntPtr dev;
2128         for( dev = inputInfo.pointer ; dev; dev = dev->next )
2129         {
2130                 if(IsMaster(dev) && IsPointerDevice(dev))
2131                 {
2132                         pGesture->master_pointer = dev;
2133                         ErrorF("[X11][GestureTimerHandler][id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name);
2134                         continue;
2135                 }
2136
2137                 if(IsXTestDevice(dev, NULL) && IsPointerDevice(dev))
2138                 {
2139                         pGesture->xtest_pointer = dev;
2140                         ErrorF("[X11][GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name);
2141                         continue;
2142                 }
2143
2144                 if(IsPointerDevice(dev))
2145                 {
2146                         if( idx >= MAX_MT_DEVICES )
2147                         {
2148                                 ErrorF("[X11][GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n",
2149                                         MAX_MT_DEVICES);
2150                                 continue;
2151                         }
2152                         pGesture->mt_devices[idx] = dev;
2153                         ErrorF("[X11][GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
2154                         idx++;
2155                 }
2156         }
2157
2158         if( !pGesture->master_pointer || !pGesture->xtest_pointer )
2159         {
2160                 ErrorF("[X11][GestureTimerHandler] Failed to get info of master pointer or XTest pointer !\n");
2161                 pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2162                 pGesture->num_mt_devices = 0;
2163
2164                 return 0;
2165         }
2166
2167         pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2168         pGesture->first_fingerid = pGesture->mt_devices[0]->id;
2169         pGesture->num_mt_devices = idx;
2170
2171         if( !pGesture->num_mt_devices )
2172         {
2173                 ErrorF("[X11][GestureTimerHandler] Failed to mt device information !\n");
2174                 pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2175                 pGesture->num_mt_devices = 0;
2176
2177                 return 0;
2178         }
2179
2180         memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
2181         pGesture->pRootWin = RootWindow(pGesture->master_pointer);
2182         g_pGesture->grabMask = g_pGesture->eventMask = 0;
2183         g_pGesture->pTempWin = NULL;
2184         g_pGesture->inc_num_pressed = 0;
2185
2186         return 0;
2187 }
2188
2189 BOOL
2190 IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
2191 {
2192         if (IsMaster(dev))
2193                 return FALSE;
2194
2195         if (master)
2196                 return (dev->xtest_master_id == master->id);
2197
2198         return (dev->xtest_master_id != 0);
2199 }
2200
2201 void
2202 GestureSetDisable(InputInfoPtr pInfo, int enable)
2203 {
2204         if( !enable )
2205         {
2206                 g_pGesture->ehtype = PROPAGATE_EVENTS;
2207                 mieqSetHandler(ET_MTSync, NULL);
2208                 g_pGesture->is_active = 0;
2209                 ErrorF("[X11][GestureSetDisable] Disabled !\n");
2210         }
2211         else
2212         {
2213                 g_pGesture->ehtype = KEEP_EVENTS;
2214                 mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
2215                 g_pGesture->is_active = 1;
2216                 ErrorF("[X11][GestureSetDisable] Enabled !\n");
2217         }
2218 }
2219
2220 ErrorStatus
2221 GestureRegionsInit(void)
2222 {
2223         int i;
2224
2225         if( !g_pGesture )
2226                 return ERROR_INVALPTR;
2227
2228         pixman_region_init(&g_pGesture->area);
2229
2230         for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
2231         {
2232                 pixman_region_init_rect (&g_pGesture->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T);
2233         }
2234
2235         return ERROR_NONE;
2236 }
2237
2238 ErrorStatus
2239 GestureRegionsReinit(void)
2240 {
2241         if( !g_pGesture )
2242         {
2243                 ErrorF("[X11][GestureRegionsReinit] Invalid pointer access !\n");
2244                 return ERROR_INVALPTR;
2245         }
2246
2247         pixman_region_init(&g_pGesture->area);
2248
2249         return ERROR_NONE;
2250 }
2251
2252 ErrorStatus
2253 GestureInitEQ(void)
2254 {
2255         int i;
2256         IEventPtr tmpEQ;
2257
2258         tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec));
2259
2260         if( !tmpEQ )
2261         {
2262                 ErrorF("[X11][GestureInitEQ] Failed to allocate memory for EQ !\n");
2263                 return ERROR_ALLOCFAIL;
2264         }
2265
2266         for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
2267         {
2268                 tmpEQ[i].event = (InternalEvent *)malloc(sizeof(InternalEvent));
2269                 if( !tmpEQ[i].event )
2270                 {
2271                         ErrorF("[X11][GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n");
2272                         return ERROR_ALLOCFAIL;
2273                 }
2274         }
2275
2276         g_pGesture->EQ = tmpEQ;
2277         g_pGesture->headEQ = g_pGesture->tailEQ = 0;
2278
2279         return ERROR_NONE;
2280 }
2281
2282 ErrorStatus
2283 GestureFiniEQ(void)
2284 {
2285         int i;
2286
2287         if( !g_pGesture || !g_pGesture->EQ )
2288                 return ERROR_INVALPTR;
2289
2290         for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
2291         {
2292                 if( g_pGesture->EQ[i].event )
2293                 {
2294                         free(g_pGesture->EQ[i].event);
2295                         g_pGesture->EQ[i].event = NULL;
2296                 }
2297         }
2298
2299         free(g_pGesture->EQ);
2300         g_pGesture->EQ = NULL;
2301
2302         return ERROR_NONE;
2303 }
2304
2305 ErrorStatus
2306 GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2307 {
2308         int tail;
2309
2310         if( !g_pGesture || !g_pGesture->EQ )
2311         {
2312                 ErrorF("[X11][GestureEnqueueEvent] Invalid pointer access !\n");
2313                 return ERROR_INVALPTR;
2314         }
2315
2316         tail = g_pGesture->tailEQ;
2317
2318         if( tail >= GESTURE_EQ_SIZE )
2319         {
2320                 ErrorF("[X11][GestureEnqueueEvent] Gesture EQ is full !\n");
2321                 return ERROR_EQFULL;
2322         }
2323
2324 #ifdef __DETAIL_DEBUG__
2325         switch( ev->any.type )
2326         {
2327                 case ET_ButtonPress:
2328                         ErrorF("[X11][GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id);
2329                         break;
2330
2331                 case ET_ButtonRelease:
2332                         ErrorF("[X11][GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id);
2333                         break;
2334
2335                 case ET_Motion:
2336                         ErrorF("[X11][GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id);
2337                         break;
2338         }
2339 #endif//__DETAIL_DEBUG__
2340
2341         g_pGesture->EQ[tail].device = device;
2342         g_pGesture->EQ[tail].screen_num = screen_num;
2343         memcpy(g_pGesture->EQ[tail].event, ev, sizeof(InternalEvent));//need to be optimized
2344         g_pGesture->tailEQ++;
2345
2346         return ERROR_NONE;
2347 }
2348
2349 ErrorStatus
2350 GestureEventsFlush(void)
2351 {
2352         int i;
2353         DeviceIntPtr device;
2354
2355         if( !g_pGesture->EQ )
2356         {
2357                 ErrorF("[X11][GestureEventsFlush] Invalid pointer access !\n");
2358                 return ERROR_INVALPTR;
2359         }
2360
2361 #ifdef __DETAIL_DEBUG__
2362         ErrorF("[X11][GestureEventsFlush]\n");
2363 #endif//__DETAIL_DEBUG__
2364
2365         for( i = g_pGesture->headEQ ; i < g_pGesture->tailEQ ; i++)
2366         {
2367                 device = g_pGesture->EQ[i].device;
2368                 device->public.processInputProc(g_pGesture->EQ[i].event, device);
2369         }
2370
2371         for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
2372                 g_pGesture->event_sum[i] = 0;
2373
2374         g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
2375
2376         return ERROR_NONE;
2377 }
2378
2379 void
2380 GestureEventsDrop(void)
2381 {
2382         g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
2383 }
2384
2385 #ifdef HAVE_PROPERTIES
2386 static void
2387 GestureInitProperty(DeviceIntPtr dev)
2388 {
2389         int rc;
2390
2391         prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
2392         rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
2393
2394         if (rc != Success)
2395                 return;
2396
2397         XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
2398 }
2399
2400 static int
2401 GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
2402                  BOOL checkonly)
2403 {
2404         InputInfoPtr pInfo  = dev->public.devicePrivate;
2405
2406         if( prop_gesture_recognizer_onoff == atom )
2407         {
2408                 int data;
2409                 if( val->format != 32 || val->type != XA_INTEGER || val->size != 1 )
2410                         return BadMatch;
2411
2412                 if( !checkonly )
2413                 {
2414                         data = *((int *)val->data);
2415                         GestureSetDisable(pInfo, data);
2416                 }
2417         }
2418
2419         return Success;
2420 }
2421 #endif//HAVE_PROPERTIES
2422
2423 static int
2424 GestureInit(DeviceIntPtr device)
2425 {
2426         InputInfoPtr pInfo;
2427         pInfo = device->public.devicePrivate;
2428
2429 #ifdef HAVE_PROPERTIES
2430         GestureInitProperty(device);
2431         XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
2432 #endif
2433
2434         return Success;
2435 }
2436
2437 static void
2438 GestureFini(DeviceIntPtr device)
2439 {
2440         XIRegisterPropertyHandler(device, NULL, NULL, NULL);
2441 }
2442
2443 static pointer
2444 GesturePlug(pointer module, pointer options, int *errmaj, int *errmin)
2445 {
2446         xf86AddInputDriver(&GESTURE, module, 0);
2447         return module;
2448 }
2449
2450 static void
2451 GestureUnplug(pointer p)
2452 {
2453 }
2454
2455 static InputInfoPtr
2456 GesturePreInit(InputDriverPtr drv, IDevPtr dev, int flags)
2457 {
2458     InputInfoPtr        pInfo;
2459     GestureDevicePtr    pGesture;
2460
2461     if (!(pInfo = xf86AllocateInput(drv, 0)))
2462         return NULL;
2463
2464     pGesture = calloc(1, sizeof(GestureDeviceRec));
2465     if (!pGesture) {
2466         pInfo->private = NULL;
2467         xf86DeleteInput(pInfo, 0);
2468         return NULL;
2469     }
2470
2471     g_pGesture = pGesture;
2472     pInfo->private = pGesture;
2473     pInfo->name = xstrdup(dev->identifier);
2474     pInfo->flags = 0;
2475     pInfo->type_name = XI_MOUSE; /* see XI.h */
2476     pInfo->conf_idev = dev;
2477     pInfo->read_input = GestureReadInput; /* new data avl */
2478     pInfo->switch_mode = NULL; /* toggle absolute/relative mode */
2479     pInfo->device_control = GestureControl; /* enable/disable dev */
2480     /* process driver specific options */
2481     pGesture->device = xf86SetStrOption(dev->commonOptions, "Device", "/dev/null");
2482     pGesture->is_active = xf86SetIntOption(dev->commonOptions, "Activate", 0);
2483     pGesture->gestureWin = None;
2484
2485     xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device);
2486
2487     /* process generic options */
2488     xf86CollectInputOptions(pInfo, NULL, NULL);
2489     xf86ProcessCommonOptions(pInfo, pInfo->options);
2490
2491     pInfo->fd = -1;
2492     pInfo->flags |= XI86_POINTER_CAPABLE;
2493     pInfo->flags |= XI86_OPEN_ON_INIT;
2494     pInfo->flags |= XI86_CONFIGURED;
2495     return pInfo;
2496 }
2497
2498 static void
2499 GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2500 {
2501         GestureDevicePtr pGesture = pInfo->private;
2502
2503         g_pGesture = pGesture = NULL;
2504         pInfo->private = NULL;
2505
2506         xf86DeleteInput(pInfo, 0);
2507 }
2508
2509 static int
2510 GestureControl(DeviceIntPtr device, int what)
2511 {
2512     InputInfoPtr  pInfo = device->public.devicePrivate;
2513     GestureDevicePtr pGesture = pInfo->private;
2514
2515     switch(what)
2516     {
2517         case DEVICE_INIT:
2518              GestureInit(device);
2519             break;
2520
2521         /* Switch device on.  Establish socket, start event delivery.  */
2522         case DEVICE_ON:
2523             xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
2524
2525             if (device->public.on)
2526                     break;
2527
2528             device->public.on = TRUE;
2529              pGesture->this_device = device;
2530              pGesture->num_mt_devices = 0;
2531              if( ERROR_ABNORMAL == GestureEnableEventHandler(pInfo) )
2532                 goto device_off;
2533             break;
2534
2535        case DEVICE_OFF:
2536 device_off:
2537              GestureDisableEventHandler();
2538              GestureFini(device);
2539              pGesture->this_device = NULL;
2540              xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
2541
2542             if (!device->public.on)
2543                 break;
2544
2545             pInfo->fd = -1;
2546             device->public.on = FALSE;
2547             break;
2548
2549       case DEVICE_CLOSE:
2550             /* free what we have to free */
2551             break;
2552     }
2553     return Success;
2554 }
2555
2556 static void
2557 GestureReadInput(InputInfoPtr pInfo)
2558 {
2559 }
2560