AArch64 support
[platform/adaptation/xf86-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 #include <stdio.h>
62 #include <sys/stat.h>
63 #include <sys/syscall.h>
64 #include <unistd.h>
65 #include <errno.h>
66 #include <sys/types.h>
67 #include <fcntl.h>
68 #include <xorg-server.h>
69 #include <xorgVersion.h>
70 #include <xf86Module.h>
71 #include <X11/Xatom.h>
72 #include "gesture.h"
73 #include <xorg/mi.h>
74
75 //Basic functions
76 static InputInfoPtr GesturePreInit(InputDriverPtr  drv, InputInfoPtr pInfo, int flags);
77 static void GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags);
78 static pointer GesturePlug(pointer module, pointer options, int *errmaj, int  *errmin);
79 static void GestureUnplug(pointer p);
80 static int GestureControl(DeviceIntPtr    device,int what);
81 static int GestureInit(DeviceIntPtr device);
82 static void GestureFini(DeviceIntPtr device);
83 static void GestureReadInput(InputInfoPtr pInfo);
84
85 //other initializers
86 ErrorStatus GestureRegionsInit(void);
87
88 //event queue handling functions
89 ErrorStatus GestureInitEQ(void);
90 ErrorStatus GestureFiniEQ(void);
91 ErrorStatus GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
92 ErrorStatus GestureEventsFlush(void);
93 void GestureEventsDrop(void);
94
95 //utility functions
96 ErrorStatus GestureRegionsReinit(void);
97 void GestureEnable(int enable, Bool prop, DeviceIntPtr dev);
98 static inline void GestureEnableDisable();
99 void GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent);
100 void GestureCbEventsSelected(Window win, Mask *pEventMask);
101 WindowPtr GestureGetEventsWindow(void);
102
103 //Enqueued event handlers and enabler/disabler
104 static ErrorStatus GestureEnableEventHandler(InputInfoPtr pInfo);
105 static ErrorStatus GestureDisableEventHandler(void);
106 static CARD32 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
107 static CARD32 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
108 void GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
109 void GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
110 void GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
111 void GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
112
113 //Gesture recognizer helper
114 static Bool PointInBorderSize(WindowPtr pWin, int x, int y);
115 static WindowPtr GestureWindowOnXY(int x, int y);
116 Bool GestureHasFingerEventMask(int eventType, int num_finger);
117 static double get_angle(int x1, int y1, int x2, int y2);
118
119 //Gesture recognizer and handlers
120 void GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
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, int kinds);
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 void
177 printk(const char* fmt, ...)
178 {
179         static FILE* fp = NULL;
180         static char init = 0;
181         va_list argptr;
182
183         if(!init && !fp)
184         {
185                 fp = fopen("/dev/kmsg", "wt");
186                 init = 1;
187         }
188
189         if(!fp) return;
190
191         va_start(argptr, fmt);
192         vfprintf(fp, fmt, argptr);
193         fflush(fp);
194         va_end(argptr);
195 }
196
197 static Bool
198 PointInBorderSize(WindowPtr pWin, int x, int y)
199 {
200     BoxRec box;
201     if( pixman_region_contains_point (&pWin->borderSize, x, y, &box) )
202         return TRUE;
203
204     return FALSE;
205 }
206
207 static WindowPtr
208 GestureWindowOnXY(int x, int y)
209 {
210     WindowPtr pWin;
211     BoxRec box;
212     SpritePtr pSprite;
213     DeviceIntPtr pDev = g_pGesture->master_pointer;
214
215     pSprite = pDev->spriteInfo->sprite;
216     pSprite->spriteTraceGood = 1;       /* root window still there */
217     pWin = RootWindow(pDev)->firstChild;
218
219     while (pWin)
220     {
221         if ((pWin->mapped) &&
222             (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
223             (x < pWin->drawable.x + (int)pWin->drawable.width +
224              wBorderWidth(pWin)) &&
225             (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
226             (y < pWin->drawable.y + (int)pWin->drawable.height +
227              wBorderWidth (pWin))
228             /* When a window is shaped, a further check
229              * is made to see if the point is inside
230              * borderSize
231              */
232             && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
233             && (!wInputShape(pWin) ||
234                 RegionContainsPoint(wInputShape(pWin),
235                                     x - pWin->drawable.x,
236                                     y - pWin->drawable.y, &box))
237 #ifdef ROOTLESS
238     /* In rootless mode windows may be offscreen, even when
239      * they're in X's stack. (E.g. if the native window system
240      * implements some form of virtual desktop system).
241      */
242                 && !pWin->rootlessUnhittable
243 #endif
244             )
245         {
246             if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
247             {
248                 pSprite->spriteTraceSize += 10;
249                 pSprite->spriteTrace = realloc(pSprite->spriteTrace,
250                                     pSprite->spriteTraceSize*sizeof(WindowPtr));
251             }
252             pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
253             pWin = pWin->firstChild;
254         }
255         else
256             pWin = pWin->nextSib;
257     }
258     return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
259 }
260
261 Bool
262 GestureHasFingerEventMask(int eventType, int num_finger)
263 {
264         Bool ret = FALSE;
265         Mask eventmask = (1L << eventType);
266
267         if( (g_pGesture->grabMask & eventmask) &&
268                 (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[num_finger].window != None) )
269         {
270 #ifdef __DETAIL_DEBUG__
271                 ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has grabMask\n");
272 #endif//__DETAIL_DEBUG__
273                 return TRUE;
274         }
275
276         if( g_pGesture->eventMask & eventmask )
277         {
278 #ifdef __DETAIL_DEBUG__
279                 ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has eventMask\n");
280 #endif//__DETAIL_DEBUG__
281                 return TRUE;
282         }
283
284 #ifdef __DETAIL_DEBUG__
285         ErrorF("[X11][GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger);
286 #endif//__DETAIL_DEBUG__
287
288         return ret;
289 }
290
291 static double
292 get_angle(int x1, int y1, int x2, int y2)
293 {
294    double a, xx, yy;
295    xx = fabs(x2 - x1);
296    yy = fabs(y2 - y1);
297
298    if (((int) xx) && ((int) yy))
299      {
300         a = atan(yy / xx);
301         if (x1 < x2)
302           {
303              if (y1 < y2)
304                {
305                   return (RAD_360DEG - a);
306                }
307              else
308                {
309                   return (a);
310                }
311           }
312         else
313           {
314              if (y1 < y2)
315                {
316                   return (RAD_180DEG + a);
317                }
318              else
319                {
320                   return (RAD_180DEG - a);
321                }
322           }
323      }
324
325    if (((int) xx))
326      {  /* Horizontal line */
327         if (x2 < x1)
328           {
329              return (RAD_180DEG);
330           }
331         else
332           {
333              return (0.0);
334           }
335      }
336
337    /* Vertical line */
338    if (y2 < y1)
339      {
340         return (RAD_90DEG);
341      }
342    else
343      {
344         return (RAD_270DEG);
345      }
346 }
347
348 void
349 GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction)
350 {
351         Window target_win;
352         WindowPtr target_pWin;
353         xGestureNotifyFlickEvent fev;
354
355 #ifdef __DETAIL_DEBUG__
356         ErrorF("[X11][GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n",
357                 num_of_fingers, distance, duration, direction);
358 #endif//__DETAIL_DEBUG__
359
360         g_pGesture->recognized_gesture |= FlickFilterMask;
361         memset(&fev, 0, sizeof(xGestureNotifyFlickEvent));
362         fev.type = GestureNotifyFlick;
363         fev.kind = GestureDone;
364         fev.num_finger = num_of_fingers;
365         fev.distance = distance;
366         fev.duration = duration;
367         fev.direction = direction;
368
369         target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window;
370         target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin;
371
372         if( g_pGesture->grabMask && (target_win != None) )
373         {
374                 fev.window = target_win;
375         }
376         else
377         {
378                 fev.window = g_pGesture->gestureWin;
379         }
380
381 #ifdef __DETAIL_DEBUG__
382         ErrorF("[X11][GestureHandleGesture_Flick] fev.window=0x%x, g_pGesture->grabMask=0x%x\n", fev.window, g_pGesture->grabMask);
383 #endif//__DETAIL_DEBUG__
384
385         GestureSendEvent(target_pWin, GestureNotifyFlick, GestureFlickMask, (xGestureCommonEvent *)&fev);
386 }
387
388 void
389 GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy)
390 {
391         Window target_win;
392         WindowPtr target_pWin;
393         xGestureNotifyTapEvent tev;
394
395         //skip non-tap events and single finger tap
396         if( !tap_repeat || num_finger <= 1 )
397                 return;
398
399 #ifdef __DETAIL_DEBUG__
400         ErrorF("[X11][GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n",
401                 num_finger, tap_repeat, cx, cy);
402 #endif//__DETAIL_DEBUG__
403
404         g_pGesture->recognized_gesture |= TapFilterMask;
405         memset(&tev, 0, sizeof(xGestureNotifyTapEvent));
406         tev.type = GestureNotifyTap;
407         tev.kind = GestureDone;
408         tev.num_finger = num_finger;
409         tev.tap_repeat = tap_repeat;
410         tev.interval = 0;
411         tev.cx = cx;
412         tev.cy = cy;
413
414         target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window;
415         target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin;
416
417         if( g_pGesture->grabMask && (target_win != None) )
418         {
419                 tev.window = target_win;
420         }
421         else
422         {
423                 tev.window = g_pGesture->gestureWin;
424         }
425
426 #ifdef __DETAIL_DEBUG__
427         ErrorF("[X11][GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", tev.window, g_pGesture->grabMask);
428 #endif//__DETAIL_DEBUG__
429
430         GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev);
431 }
432
433 void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy, int kinds)
434 {
435         Window target_win;
436         WindowPtr target_pWin;
437         xGestureNotifyPinchRotationEvent prev;
438
439 #ifdef __DETAIL_DEBUG__
440         ErrorF("[X11][GestureHandleGesture_PinchRotation] num_fingers=%d, zoom=%.2f, angle=%.2f(deg=%.2f), distance=%d, cx=%d, cy=%d\n",
441                                 num_of_fingers, zoom, angle, rad2degree(angle), distance, cx, cy);
442 #endif//__DETAIL_DEBUG__
443
444         g_pGesture->recognized_gesture |= PinchRotationFilterMask;
445         memset(&prev, 0, sizeof(xGestureNotifyPinchRotationEvent));
446         prev.type = GestureNotifyPinchRotation;
447         prev.kind = kinds;
448         prev.num_finger = num_of_fingers;
449         prev.zoom = XDoubleToFixed(zoom);
450         prev.angle = XDoubleToFixed(angle);
451         prev.distance = distance;
452         prev.cx = cx;
453         prev.cy = cy;
454
455         target_win = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].window;
456         target_pWin = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].pWin;
457
458         if( g_pGesture->grabMask && (target_win != None) )
459         {
460                 prev.window = target_win;
461         }
462         else
463         {
464                 prev.window = g_pGesture->gestureWin;
465         }
466
467 #ifdef __DETAIL_DEBUG__
468         ErrorF("[X11][GestureHandleGesture_PinchRotation] prev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)prev.window, (unsigned int)g_pGesture->grabMask);
469 #endif//__DETAIL_DEBUG__
470
471         GestureSendEvent(target_pWin, GestureNotifyPinchRotation, GesturePinchRotationMask, (xGestureCommonEvent *)&prev);
472 }
473
474 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds)
475 {
476         Window target_win;
477         WindowPtr target_pWin;
478         xGestureNotifyHoldEvent hev;
479
480 #ifdef __DETAIL_DEBUG__
481         ErrorF("[X11][GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n",
482                                 num_fingers, cx, cy, holdtime, kinds);
483 #endif//__DETAIL_DEBUG__
484
485         g_pGesture->recognized_gesture |= HoldFilterMask;
486         memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
487         hev.type = GestureNotifyHold;
488         hev.kind = kinds;
489         hev.num_finger = num_fingers;
490         hev.holdtime = holdtime;
491         hev.cx = cx;
492         hev.cy = cy;
493
494         target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window;
495         target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin;
496
497         if( g_pGesture->grabMask && (target_win != None) )
498         {
499                 hev.window = target_win;
500         }
501         else
502         {
503                 hev.window = g_pGesture->gestureWin;
504         }
505
506 #ifdef __DETAIL_DEBUG__
507         ErrorF("[X11][GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask);
508 #endif//__DETAIL_DEBUG__
509
510         GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev);
511 }
512
513 void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds)
514 {
515         Window target_win;
516         WindowPtr target_pWin;
517         xGestureNotifyTapNHoldEvent thev;
518
519 #ifdef __DETAIL_DEBUG__
520         ErrorF("[X11][GestureHandleGesture_TapNHold] num_fingers=%d, cx=%d, cy=%d, interval=%d, holdtime=%d, kinds=%d\n",
521                                 num_fingers, cx, cy, interval, holdtime, kinds);
522 #endif//__DETAIL_DEBUG__
523
524         g_pGesture->recognized_gesture |= TapNHoldFilterMask;
525         memset(&thev, 0, sizeof(xGestureNotifyTapNHoldEvent));
526         thev.type = GestureNotifyTapNHold;
527         thev.kind = kinds;
528         thev.num_finger = num_fingers;
529         thev.holdtime = holdtime;
530         thev.cx = cx;
531         thev.cy = cy;
532         thev.interval = interval;
533
534         target_win = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].window;
535         target_pWin = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].pWin;
536
537         if( g_pGesture->grabMask && (target_win != None) )
538         {
539                 thev.window = target_win;
540         }
541         else
542         {
543                 thev.window = g_pGesture->gestureWin;
544         }
545
546 #ifdef __DETAIL_DEBUG__
547         ErrorF("[X11][GestureHandleGesture_TapNHold] thev.window=0x%x, g_pGesture->grabMask=0x%x\n", thev.window, g_pGesture->grabMask);
548 #endif//__DETAIL_DEBUG__
549
550         GestureSendEvent(target_pWin, GestureNotifyTapNHold, GestureTapNHoldMask, (xGestureCommonEvent *)&thev);
551 }
552
553 void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds)
554 {
555         Window target_win;
556         WindowPtr target_pWin;
557         xGestureNotifyPanEvent pev;
558
559 #ifdef __DETAIL_DEBUG__
560         ErrorF("[X11][GestureHandleGesture_Pan] num_fingers=%d, dx=%d, dy=%d, direction=%d, distance=%d, duration=%d, kinds=%d\n",
561                                 num_fingers, dx, dy, direction, distance, duration, kinds);
562 #endif//__DETAIL_DEBUG__
563
564         g_pGesture->recognized_gesture |= PanFilterMask;
565         memset(&pev, 0, sizeof(xGestureNotifyPanEvent));
566         pev.type = GestureNotifyPan;
567         pev.kind = kinds;
568         pev.num_finger = num_fingers;
569         pev.direction = direction;
570         pev.distance = distance;
571         pev.duration = duration;
572         pev.dx = dx;
573         pev.dy = dy;
574
575         target_win = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].window;
576         target_pWin = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].pWin;
577
578         if( g_pGesture->grabMask && (target_win != None) )
579         {
580                 pev.window = target_win;
581         }
582         else
583         {
584                 pev.window = g_pGesture->gestureWin;
585         }
586
587 #ifdef __DETAIL_DEBUG__
588         ErrorF("[X11][GestureHandleGesture_Pan] pev.window=0x%x, g_pGesture->grabMask=0x%x\n", pev.window, g_pGesture->grabMask);
589 #endif//__DETAIL_DEBUG__
590
591         GestureSendEvent(target_pWin, GestureNotifyPan, GesturePanMask, (xGestureCommonEvent *)&pev);
592 }
593
594 void
595 GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
596 {
597         static int cx, cy;
598
599         static int num_pressed = 0;
600         static int state = GestureEnd;
601         static int event_type = GestureNotifyPinchRotation;
602         static OsTimerPtr pinchrotation_event_timer = NULL;
603
604         static pixman_region16_t base_area;
605         static pixman_region16_t cur_area;
606
607         static double base_distance = 0.0f;
608         static double base_angle = 0.0f;
609
610         static double prev_distance = 0.0f;
611         static double prev_angle = 0.0f;
612
613         static double cur_distance = 0.0f;
614         static double cur_angle = 0.0f;
615
616         double diff_distance = 0.0f;
617         double diff_angle = 0.0f;
618
619         static int has_event_mask = 0;
620
621         static Time base_time = 0;
622         Time current_time;
623
624         if( timer_expired )
625         {
626                 if( state == GestureEnd )
627                 {
628                         current_time = GetTimeInMillis();
629                         if( (current_time - base_time) >= PINCHROTATION_TIME_THRESHOLD )
630                         {
631 #ifdef __DETAIL_DEBUG__
632                                 ErrorF("[GroupPinchRotation][Timer] You must move farther than dist threshold(=%.2f) or angle threshold(=%2f) within time threshold(=%d) !\n", PINCHROTATION_DIST_THRESHOLD, PINCHROTATION_ANGLE_THRESHOLD, PINCHROTATION_TIME_THRESHOLD);
633 #endif//__DETAIL_DEBUG__
634                                 goto cleanup_pinchrotation;
635                         }
636                 }
637
638                 return;
639         }
640
641         switch( type )
642         {
643                 case ET_ButtonPress:
644                         g_pGesture->fingers[idx].flags |= PressFlagPinchRotation;
645
646                         if( g_pGesture->num_pressed < 2 )
647                                 return;
648
649                         if( g_pGesture->num_pressed < num_pressed && state != GestureEnd )
650                         {
651 #ifdef __DETAIL_DEBUG__
652                                 ErrorF("[GroupPinchRotation][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
653 #endif//__DETAIL_DEBUG__
654                                 goto cleanup_pinchrotation;
655                         }
656
657                         if( base_distance == 0.0f && g_pGesture->num_pressed == 2 )
658                         {
659 #ifdef __DETAIL_DEBUG__
660                                 ErrorF("[GroupPinchRotation][First Time !!!] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
661 #endif//__DETAIL_DEBUG__
662
663                                 base_time = GetTimeInMillis();
664                                 pixman_region_init(&base_area);
665                                 pixman_region_union(&base_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]);
666
667                                 prev_distance = base_distance = AREA_DIAG_LEN(&base_area.extents);
668
669 #ifdef __DETAIL_DEBUG__
670                                 ErrorF("[GroupPinchRotation][P] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].px, g_pGesture->fingers[1].px,
671                                 g_pGesture->fingers[0].py, g_pGesture->fingers[1].py);
672 #endif//__DETAIL_DEBUG__
673
674                                 prev_angle = base_angle = get_angle(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py, g_pGesture->fingers[1].px, g_pGesture->fingers[1].py);
675 #ifdef __DETAIL_DEBUG__
676                                 ErrorF("[GroupPinchRotation][P] base_angle=%.2f(deg=%.2f)\n", base_angle, rad2degree(base_angle));
677 #endif//__DETAIL_DEBUG__
678                                 event_type = GestureNotifyPinchRotation;
679                                 pinchrotation_event_timer = TimerSet(pinchrotation_event_timer, 0, PINCHROTATION_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
680                         }
681                         num_pressed = g_pGesture->num_pressed;
682
683 #ifdef __DETAIL_DEBUG__
684                         ErrorF("[GroupPinchRotation][P][num_pressed=%d] AREA_SIZE(base_area.extents)=%d\n", num_pressed, AREA_SIZE(&base_area.extents));
685                         ErrorF("[GroupPinchRotation][P][num_pressed=%d] base_distance=%.2f, base_angle=%.2f(deg=%.2f)\n", num_pressed, base_distance, base_angle, rad2degree(base_angle));
686 #endif//__DETAIL_DEBUG__
687                         break;
688
689                 case ET_Motion:
690                         if( !(g_pGesture->fingers[idx].flags & PressFlagPinchRotation) )
691                                 break;
692
693                         if( (num_pressed != g_pGesture->num_pressed) && (state != GestureEnd) )
694                         {
695 #ifdef __DETAIL_DEBUG__
696                                 ErrorF("[GroupPinchRotation][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
697 #endif//__DETAIL_DEBUG__
698                                 goto cleanup_pinchrotation;
699                         }
700
701                         if( num_pressed < 2 )
702                                 return;
703
704                         if( g_pGesture->fingers[0].mx && g_pGesture->fingers[0].my && g_pGesture->fingers[1].mx && g_pGesture->fingers[1].my )
705                         {
706                                 pixman_region_init(&cur_area);
707                                 pixman_region_union(&cur_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]);
708
709                                 cur_distance = AREA_DIAG_LEN(&cur_area.extents);
710
711 #ifdef __DETAIL_DEBUG__
712                                 ErrorF("[GroupPinchRotation][M] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].mx, g_pGesture->fingers[1].mx,
713                                 g_pGesture->fingers[0].my, g_pGesture->fingers[1].my);
714 #endif//__DETAIL_DEBUG__
715
716                                 cur_angle = get_angle(g_pGesture->fingers[0].mx, g_pGesture->fingers[0].my, g_pGesture->fingers[1].mx, g_pGesture->fingers[1].my);
717 #ifdef __DETAIL_DEBUG__
718                                 ErrorF("[GroupPinchRotation][M] cur_angle=%.2f(deg=%.2f)\n", cur_angle, rad2degree(cur_angle));
719 #endif//__DETAIL_DEBUG__
720
721                                 diff_distance = prev_distance - cur_distance;
722                                 diff_angle = prev_angle - cur_angle;
723
724                                 cx = AREA_CENTER_X(&cur_area.extents);
725                                 cy = AREA_CENTER_Y(&cur_area.extents);
726
727 #ifdef __DETAIL_DEBUG__
728                                 ErrorF("[GroupPinchRotation][M][state=%d] cx=%d, cy=%d\n", state, cx, cy);
729 #endif//__DETAIL_DEBUG__
730
731 #ifdef __DETAIL_DEBUG__
732                                 ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_distance=%.2f, cur_distance=%.2f, diff=%.2f\n", num_pressed, prev_distance, cur_distance, diff_distance);
733                                 ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_angle=%.2f(deg=%.2f), cur_angle=%.2f(deg=%.2f), diff=%.2f(deg=%.2f)\n", num_pressed, prev_angle, rad2degree(prev_angle), cur_angle, rad2degree(cur_angle), diff_angle, rad2degree(diff_angle));
734 #endif//__DETAIL_DEBUG__
735
736                                 switch( state )
737                                 {
738                                         case GestureEnd:
739                                                 if( (ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD) || (ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD) )
740                                                 {
741 #ifdef __DETAIL_DEBUG__
742                                                         if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD )
743                                                                 ErrorF("[GroupPinchRotation][M] zoom changed !\n");
744
745                                                         if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD )
746                                                                 ErrorF("[GroupPinchRotation][M] angle changed !\n");
747 #endif//__DETAIL_DEBUG__
748
749                                                         TimerCancel(pinchrotation_event_timer);
750                                                         state = GestureBegin;
751                                                         goto gesture_begin_handle;
752                                                 }
753                                                 break;
754
755                                         case GestureBegin:
756 gesture_begin_handle:
757 #ifdef __DETAIL_DEBUG__
758                                                 ErrorF("[GroupPinchRotation] PINCHROTATION Begin !cx=%d, cy=%d, state=%d\n", cx, cy, state);
759 #endif//__DETAIL_DEBUG__
760                                                 if( GestureHasFingerEventMask(GestureNotifyPinchRotation, num_pressed) )
761                                                 {
762                                                         GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureBegin);
763                                                         prev_distance = cur_distance;
764                                                         prev_angle = cur_angle;
765                                                         state = GestureUpdate;
766                                                         has_event_mask = 1;
767                                                 }
768                                                 else
769                                                 {
770                                                         has_event_mask = 0;
771                                                         goto cleanup_pinchrotation;
772                                                 }
773                                                 break;
774
775                                         case GestureUpdate:
776                                                 //if( ABS(diff_distance) < PINCHROTATION_DIST_THRESHOLD && ABS(diff_angle) < PINCHROTATION_ANGLE_THRESHOLD )
777                                                 //      break;
778
779 #ifdef __DETAIL_DEBUG__
780                                                 if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD )
781                                                         ErrorF("[GroupPinchRotation][M] zoom changed !\n");
782
783                                                 if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD )
784                                                         ErrorF("[GroupPinchRotation][M] angle changed !\n");
785 #endif//__DETAIL_DEBUG__
786
787 #ifdef __DETAIL_DEBUG__
788                                                 ErrorF("[GroupPinchRotation] PINCHROTATION Update ! cx=%d, cy=%d, state=%d\n", cx, cy, state);
789 #endif//__DETAIL_DEBUG__
790                                                 GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureUpdate);
791                                                 prev_distance = cur_distance;
792                                                 prev_angle = cur_angle;
793                                                 break;
794
795                                         case GestureDone:
796                                         default:
797                                                 break;
798                                 }
799                         }
800                         break;
801
802                 case ET_ButtonRelease:
803                         if( state != GestureEnd && num_pressed >= 2)
804                         {
805 #ifdef __DETAIL_DEBUG__
806                                 ErrorF("[GroupPinchRotation][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
807 #endif//__DETAIL_DEBUG__
808                                 goto cleanup_pinchrotation;
809                         }
810
811                         if( g_pGesture->num_pressed )
812                                 break;
813
814                         goto cleanup_pinchrotation;
815                         break;
816         }
817
818         return;
819
820 cleanup_pinchrotation:
821
822         if(  has_event_mask  && (state == GestureBegin || state == GestureUpdate) )
823         {
824                 state = GestureEnd;
825 #ifdef __DETAIL_DEBUG__
826                 ErrorF("[GroupPinchRotation] PINCHROTATION End ! cx=%d, cy=%d, state=%d\n", cx, cy, state);
827 #endif//__DETAIL_DEBUG__
828                 GestureHandleGesture_PinchRotation(num_pressed, cur_distance / base_distance, (cur_angle > base_angle) ? (cur_angle-base_angle) : (RAD_360DEG + cur_angle - base_angle), cur_distance, cx, cy, GestureEnd);
829         }
830         else
831         {
832                 g_pGesture->recognized_gesture &= ~PinchRotationFilterMask;
833         }
834
835         g_pGesture->filter_mask |= PinchRotationFilterMask;
836
837         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
838         {
839 #if 1//def __DETAIL_DEBUG__
840                 ErrorF("[GroupPinchRotation][cleanup] GestureFlushOrDrop() !\n");
841 #endif//__DETAIL_DEBUG__
842
843                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
844                 {
845                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
846                 }
847         }
848
849         prev_distance = base_distance = 0.0f;
850         prev_angle = base_angle = 0.0f;
851         has_event_mask = num_pressed = 0;
852         state = GestureEnd;
853         cx = cy = 0;
854         TimerCancel(pinchrotation_event_timer);
855         return;
856 }
857
858 void
859 GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
860 {
861         static int num_pressed = 0;
862         static int mbits = 0;
863         static int base_area_size = 0;
864         static Time base_time = 0;
865         static int base_x, base_y;
866         Time current_time;
867         Time duration;
868         int distx, disty;
869         int distance, direction;
870         int area_size;
871         int flicked = 0;
872
873         switch( type )
874         {
875                 case ET_ButtonPress:
876                         g_pGesture->fingers[idx].flags |= PressFlagFlick;
877
878                         if( g_pGesture->num_pressed < 2 )
879                                 return;
880
881                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
882                         {
883                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
884                                 base_x = g_pGesture->area.extents.x1;
885                                 base_y = g_pGesture->area.extents.y1;
886                                 base_time = GetTimeInMillis();
887                         }
888                         num_pressed = g_pGesture->num_pressed;
889
890 #ifdef __DETAIL_DEBUG__
891                         ErrorF("[GroupFlick][P]][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, base_area_size);
892 #endif//__DETAIL_DEBUG__
893                         break;
894
895                 case ET_Motion:
896                         if( !(g_pGesture->fingers[idx].flags & PressFlagFlick ) )
897                                 break;
898
899 #ifdef __DETAIL_DEBUG__
900                         if( num_pressed > g_pGesture->num_pressed )
901                         {
902                                 ErrorF("[GroupFlick][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
903                                 //goto cleanup_flick;
904                         }
905 #endif//__DETAIL_DEBUG__
906
907                         if( num_pressed < 2 )
908                                 return;
909
910                         mbits |= (1 << idx);
911                         if( mbits == (pow(2, num_pressed)-1) )
912                         {
913                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
914 #ifdef __DETAIL_DEBUG__
915                                 ErrorF("[M][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, area_size);
916 #endif//__DETAIL_DEBUG__
917                                 if( ABS(base_area_size - area_size) >= FLICK_AREA_THRESHOLD )
918                                 {
919 #ifdef __DETAIL_DEBUG__
920                                         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);
921 #endif//__DETAIL_DEBUG__
922                                         goto cleanup_flick;
923                                 }
924
925                                 current_time = GetTimeInMillis();
926                                 if( (current_time - base_time) >= FLICK_AREA_TIMEOUT )
927                                 {
928 #ifdef __DETAIL_DEBUG__
929                                         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);
930 #endif//__DETAIL_DEBUG__
931                                         goto cleanup_flick;
932                                 }
933                                 mbits = 0;
934                         }
935                         break;
936
937                 case ET_ButtonRelease:
938                         if( g_pGesture->num_pressed )
939                                 break;
940
941                         duration = GetTimeInMillis() - base_time;
942                         distx = g_pGesture->area.extents.x1 - base_x;
943                         disty = g_pGesture->area.extents.y1 - base_y;
944
945 #ifdef __DETAIL_DEBUG__
946                         ErrorF("[GroupFlick] duration=%d, distx=%d, disty=%d\n", duration, distx, disty);
947 #endif//__DETAIL_DEBUG__
948
949                         if( duration <= 0 || duration >= FLICK_AREA_TIMEOUT )
950                                 goto cleanup_flick;
951
952                         if( ABS(distx) >= FLICK_MOVE_THRESHOLD )
953                         {
954                                 direction = (distx > 0) ? FLICK_EASTWARD : FLICK_WESTWARD;
955                                 distance = ABS(distx);
956                                 flicked++;
957                         }
958                         else if( ABS(disty) >= FLICK_MOVE_THRESHOLD )
959                         {
960                                 direction = (disty > 0) ? FLICK_SOUTHWARD : FLICK_NORTHWARD;
961                                 distance = ABS(disty);
962                                 flicked++;
963                         }
964
965                         if( !flicked )
966                                 goto cleanup_flick;
967
968                         if( GestureHasFingerEventMask(GestureNotifyFlick, num_pressed) )
969                                 GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
970                         goto cleanup_flick_recognized;
971                         break;
972         }
973
974         return;
975
976 cleanup_flick:
977
978         g_pGesture->recognized_gesture &= ~FlickFilterMask;
979
980 cleanup_flick_recognized:
981
982         g_pGesture->filter_mask |= FlickFilterMask;
983         num_pressed = 0;
984         base_area_size = 0;
985         base_time = 0;
986         mbits = 0;
987         return;
988 }
989
990 void
991 GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
992 {
993         static int num_pressed = 0;
994         static int mbits = 0;
995         static int base_area_size = 0;
996         static Time base_time = 0;
997         static pixman_box16_t base_box_ext;
998         static int base_cx;
999         static int base_cy;
1000         static int prev_cx;
1001         static int prev_cy;
1002         static int cx = 0;
1003         static int cy = 0;
1004         int dx, dy;
1005         static Time prev_time = 0;
1006         Time current_time = 0;
1007         int distance = 0;
1008         int direction = 0;
1009         int area_size;
1010         static int time_checked = 0;
1011         static int state = GestureEnd;
1012
1013         static OsTimerPtr pan_event_timer = NULL;
1014         static int event_type = GestureNotifyPan;
1015
1016         if( timer_expired )
1017         {
1018                 if( !time_checked )
1019                 {
1020                         current_time = GetTimeInMillis();
1021                         if( (current_time - base_time) >= PAN_TIME_THRESHOLD )
1022                         {
1023                                 if( (!cx && !cy) || INBOX(&base_box_ext, cx, cy) )
1024                                 {
1025 #ifdef __DETAIL_DEBUG__
1026                                         ErrorF("[GroupPan][Timer] You must move farther than move threshold(=%d) within time threshold(=%d) !\n", PAN_MOVE_THRESHOLD*2, PAN_TIME_THRESHOLD);
1027 #endif//__DETAIL_DEBUG__
1028                                         goto cleanup_pan;
1029                                 }
1030                                 time_checked = 1;
1031                         }
1032                 }
1033                 return;
1034         }
1035
1036         switch( type )
1037         {
1038                 case ET_ButtonPress:
1039                         g_pGesture->fingers[idx].flags |= PressFlagPan;
1040
1041                         if( g_pGesture->num_pressed < 2 )
1042                                 return;
1043
1044                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1045                         {
1046                                 if( state != GestureEnd )
1047                                 {
1048 #ifdef __DETAIL_DEBUG__
1049                                         ErrorF("[GroupPan][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1050 #endif//__DETAIL_DEBUG__
1051                                         goto cleanup_pan;
1052                                 }
1053                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1054                                 prev_cx = base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1055                                 prev_cy = base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1056                                 prev_time = base_time = GetTimeInMillis();
1057                                 base_box_ext.x1 = base_cx-PAN_MOVE_THRESHOLD;
1058                                 base_box_ext.y1 = base_cy-PAN_MOVE_THRESHOLD;
1059                                 base_box_ext.x2 = base_cx+PAN_MOVE_THRESHOLD;
1060                                 base_box_ext.y2 = base_cy+PAN_MOVE_THRESHOLD;
1061                                 event_type = GestureNotifyPan;
1062                                 pan_event_timer = TimerSet(pan_event_timer, 0, PAN_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1063                         }
1064                         num_pressed = g_pGesture->num_pressed;
1065
1066 #ifdef __DETAIL_DEBUG__
1067                         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);
1068 #endif//__DETAIL_DEBUG__
1069                         break;
1070
1071                 case ET_Motion:
1072                         if( !(g_pGesture->fingers[idx].flags & PressFlagPan ) )
1073                                 break;
1074
1075                         if( num_pressed != g_pGesture->num_pressed )
1076                         {
1077                                 if( state != GestureEnd )
1078                                 {
1079 #ifdef __DETAIL_DEBUG__
1080                                 ErrorF("[GroupPan][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1081 #endif//__DETAIL_DEBUG__
1082                                         goto cleanup_pan;
1083                                 }
1084                         }
1085
1086                         if( num_pressed < 2 )
1087                                 return;
1088
1089                         mbits |= (1 << idx);
1090                         if( mbits == (pow(2, num_pressed)-1) )
1091                         {
1092                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1093 #ifdef __DETAIL_DEBUG__
1094                                 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));
1095 #endif//__DETAIL_DEBUG__
1096
1097                                 if( (state != GestureUpdate) && (ABS(base_area_size - area_size) >= PAN_AREA_THRESHOLD) )
1098                                 {
1099 #ifdef __DETAIL_DEBUG__
1100                                         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);
1101 #endif//__DETAIL_DEBUG__
1102                                         goto cleanup_pan;
1103                                 }
1104
1105                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1106                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1107 #ifdef __DETAIL_DEBUG__
1108                                 ErrorF("[GroupPan][M] cx=%d, prev_cx=%d, diff=%d\n", cx, prev_cx, ABS(cx-prev_cx));
1109                                 ErrorF("[GroupPan][M] cy=%d, prev_cy=%d, diff=%d\n", cy, prev_cy, ABS(cy-prev_cy));
1110 #endif//__DETAIL_DEBUG__
1111
1112                                 if( state <= GestureBegin )
1113                                 {
1114                                         if( !INBOX(&base_box_ext, cx, cy) )
1115                                         {
1116                                                 TimerCancel(pan_event_timer);
1117                                                 pan_event_timer = NULL;
1118                                                 
1119                                                 if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
1120                                                 {
1121                                                         GestureHandleGesture_Pan(num_pressed, prev_cx, prev_cy, direction, distance, current_time-prev_time, GestureBegin);
1122                                                         state = GestureUpdate;
1123                                                 }
1124                                                 else
1125                                                         goto cleanup_pan;
1126                                         }
1127                                 }
1128                                 else
1129                                 {
1130                                         dx = cx-prev_cx;
1131                                         dy = cy-prev_cy;
1132
1133                                         //if( ABS(dx) >= PAN_UPDATE_MOVE_THRESHOLD || ABS(dy) >= PAN_UPDATE_MOVE_THRESHOLD )
1134                                         {
1135 #ifdef __DETAIL_DEBUG__
1136                                                 ErrorF("[GroupPan] PAN Update !dx=%d, dy=%d, state=%d\n", dx, dy, state);
1137 #endif//__DETAIL_DEBUG__
1138
1139                                                 GestureHandleGesture_Pan(num_pressed, dx, dy, direction, distance, current_time-prev_time, GestureUpdate);
1140                                         }
1141                                 }
1142
1143                                 prev_cx = cx;
1144                                 prev_cy = cy;
1145                                 mbits = 0;
1146                         }
1147                         break;
1148
1149                 case ET_ButtonRelease:
1150                         if( state != GestureEnd && num_pressed >= 2)
1151                         {
1152 #ifdef __DETAIL_DEBUG__
1153                                 ErrorF("[GroupPan][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1154 #endif//__DETAIL_DEBUG__
1155                                 goto cleanup_pan;
1156                         }
1157
1158                         if( g_pGesture->num_pressed )
1159                                 break;
1160
1161                         goto cleanup_pan;
1162                         break;
1163         }
1164
1165         return;
1166
1167 cleanup_pan:
1168
1169         if( state == GestureBegin || state == GestureUpdate )
1170         {
1171                 state = GestureEnd;
1172                 if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
1173                 {
1174                         GestureHandleGesture_Pan(num_pressed, (short int)(cx-prev_cx), (short int)(cy-prev_cy), direction, distance, GetTimeInMillis()-prev_time, GestureEnd);
1175                 }
1176         }
1177         else
1178         {
1179                 g_pGesture->recognized_gesture &= ~PanFilterMask;
1180         }
1181
1182         g_pGesture->filter_mask |= PanFilterMask;
1183         num_pressed = 0;
1184         base_area_size = 0;
1185         base_time = 0;
1186         mbits = 0;
1187         time_checked = 0;
1188         state = GestureEnd;
1189         cx = cy = 0;
1190         prev_time = 0;
1191         base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
1192         if( pan_event_timer )
1193         {
1194                 TimerCancel(pan_event_timer);
1195                 pan_event_timer = NULL;
1196         }
1197         return;
1198 }
1199
1200 void
1201 GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1202 {
1203         static int num_pressed = 0;
1204         static int base_area_size = 0;
1205
1206         static Time base_time = 0;
1207         Time current_time;
1208
1209         int cx, cy;
1210         int area_size;
1211
1212         static int state = 0;
1213         static int mbits = 0;
1214         static int base_cx;
1215         static int base_cy;
1216         static pixman_box16_t base_box_ext;
1217
1218         static int tap_repeat = 0;
1219         static int prev_tap_repeat = 0;
1220         static int prev_num_pressed = 0;
1221
1222         static OsTimerPtr tap_event_timer = NULL;
1223         static int event_type = GestureNotifyTap;
1224
1225         if( timer_expired )
1226         {
1227 #ifdef __DETAIL_DEBUG__
1228                 ErrorF("[GroupTap][Timer] state=%d\n", state);
1229 #endif//__DETAIL_DEBUG__
1230
1231                 switch( state )
1232                 {
1233                         case 1://first tap initiation check
1234                                 if( num_pressed )
1235                                 {
1236 #ifdef __DETAIL_DEBUG__
1237                                         ErrorF("[GroupTap][Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", tap_repeat, num_pressed, tap_repeat);
1238 #endif//__DETAIL_DEBUG__
1239                                         state = 0;
1240                                         goto cleanup_tap;
1241                                 }
1242                                 break;
1243
1244                         case 2:
1245                                 if( tap_repeat <= 1 )
1246                                 {
1247 #ifdef __DETAIL_DEBUG__
1248                                         ErrorF("[GroupTap][Timer][state=2] %d finger SINGLE TAP !(ignored)\n", prev_num_pressed);
1249 #endif//__DETAIL_DEBUG__
1250                                         state = 0;
1251                                         goto cleanup_tap;
1252                                 }
1253
1254 #ifdef __DETAIL_DEBUG__
1255                                 ErrorF("[GroupTap][Timer][state=2]  tap_repeat=%d, prev_tap_repeat=%d, num_pressed=%d\n", tap_repeat, prev_tap_repeat, num_pressed);
1256 #endif//__DETAIL_DEBUG__
1257                                 if( GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed) )
1258                                         GestureHandleGesture_Tap(prev_num_pressed, tap_repeat, base_cx, base_cy);
1259                                 goto cleanup_tap;
1260                                 break;
1261                 }
1262
1263                 return;
1264         }
1265
1266         switch( type )
1267         {
1268                 case ET_ButtonPress:
1269                         g_pGesture->fingers[idx].flags |= PressFlagTap;
1270
1271                         if( g_pGesture->num_pressed < 2 )
1272                                 return;
1273
1274                         if( !prev_num_pressed && (!base_area_size || g_pGesture->num_pressed > num_pressed) )
1275                         {
1276                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1277                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1278                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1279                                 base_time = GetTimeInMillis();
1280                                 base_box_ext.x1 = base_cx-TAP_MOVE_THRESHOLD;
1281                                 base_box_ext.y1 = base_cy-TAP_MOVE_THRESHOLD;
1282                                 base_box_ext.x2 = base_cx+TAP_MOVE_THRESHOLD;
1283                                 base_box_ext.y2 = base_cy+TAP_MOVE_THRESHOLD;
1284                                 state = 1;
1285                                 TimerCancel(tap_event_timer);
1286                                 tap_event_timer = TimerSet(tap_event_timer, 0, SGL_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1287                         }
1288
1289                         num_pressed = g_pGesture->num_pressed;
1290
1291                         current_time = GetTimeInMillis();
1292
1293 #ifdef __DETAIL_DEBUG__
1294                         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);
1295 #endif//__DETAIL_DEBUG__
1296                         break;
1297
1298                 case ET_Motion:
1299                         if( !(g_pGesture->fingers[idx].flags & PressFlagTap ) )
1300                                 break;
1301
1302                         if( num_pressed < 2 )
1303                                 return;
1304
1305                         if( num_pressed != g_pGesture->num_pressed )
1306                         {
1307 #ifdef __DETAIL_DEBUG__
1308                                 ErrorF("[GroupTap][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1309 #endif//__DETAIL_DEBUG__
1310                                 //goto cleanup_tap;
1311                         }
1312
1313                         mbits |= (1 << idx);
1314                         if( mbits == (pow(2, num_pressed)-1) )
1315                         {
1316                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1317                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1318                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1319 #ifdef __DETAIL_DEBUG__
1320                                 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));
1321                                 ErrorF("[GroupTap][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1322                                 ErrorF("[GroupTap][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1323 #endif//__DETAIL_DEBUG__
1324
1325                                 if( ABS(base_area_size-area_size) >= TAP_AREA_THRESHOLD )
1326                                 {
1327 #ifdef __DETAIL_DEBUG__
1328                                         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));
1329 #endif//__DETAIL_DEBUG__
1330                                         goto cleanup_tap;
1331                                 }
1332
1333                                 if( !INBOX(&base_box_ext, cx, cy) )
1334                                 {
1335 #ifdef __DETAIL_DEBUG__
1336                                         ErrorF("[GroupTap][M] current center coordinates is not in base coordinates box !\n");
1337 #endif//__DETAIL_DEBUG__
1338                                         goto cleanup_tap;
1339                                 }
1340                         }
1341                         break;
1342
1343                 case ET_ButtonRelease:
1344                         if( g_pGesture->num_pressed )
1345                                 break;
1346
1347                         if( !tap_repeat )
1348                         {
1349                                 prev_num_pressed = num_pressed;
1350                         }
1351
1352                         prev_tap_repeat = tap_repeat;
1353                         tap_repeat++;
1354
1355 #ifdef __DETAIL_DEBUG__
1356                         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);
1357 #endif//__DETAIL_DEBUG__
1358
1359                         if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
1360                         {
1361 #ifdef __DETAIL_DEBUG__
1362                                 ErrorF("[GroupTap][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
1363                                         num_pressed, prev_num_pressed, num_pressed);
1364 #endif//__DETAIL_DEBUG__
1365                                 goto cleanup_tap;
1366                         }
1367
1368                         if( tap_repeat < MAX_TAP_REPEATS )
1369                         {
1370                                 state = 2;
1371                                 TimerCancel(tap_event_timer);
1372                                 tap_event_timer = TimerSet(tap_event_timer, 0, DBL_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1373                                 num_pressed = 0;
1374                                 break;
1375                         }
1376
1377 #ifdef __DETAIL_DEBUG__
1378                         ErrorF("[GroupTap][R] %d finger %s\n", num_pressed, (tap_repeat==2) ? "DBL_TAP" : "TRIPLE_TAP");
1379 #endif//__DETAIL_DEBUG__
1380
1381                         if( GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
1382                                 GestureHandleGesture_Tap(num_pressed, tap_repeat, base_cx, base_cy);
1383
1384                         if( tap_repeat >= MAX_TAP_REPEATS )
1385                         {
1386                                 goto cleanup_tap;
1387                         }
1388
1389                         prev_num_pressed = num_pressed;
1390                         num_pressed = 0;
1391                         break;
1392         }
1393
1394         return;
1395
1396 cleanup_tap:
1397
1398         if( 0 == state )
1399                 g_pGesture->recognized_gesture &= ~TapFilterMask;
1400         g_pGesture->filter_mask |= TapFilterMask;
1401
1402         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
1403         {
1404 #ifdef __DETAIL_DEBUG__
1405                 ErrorF("[GroupTap][cleanup] GestureFlushOrDrop() !\n");
1406 #endif//__DETAIL_DEBUG__
1407
1408                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
1409                 {
1410                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
1411                 }
1412         }
1413
1414         num_pressed = 0;
1415         tap_repeat = 0;
1416         prev_num_pressed = 0;
1417         mbits = 0;
1418         base_time = 0;
1419         state = 0;
1420         TimerCancel(tap_event_timer);
1421         return;
1422 }
1423
1424 void
1425 GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1426 {
1427         static int num_pressed = 0;
1428         static int base_area_size = 0;
1429         static Time base_time = 0;
1430         static int base_cx;
1431         static int base_cy;
1432         int cx, cy;
1433         static pixman_box16_t base_box_ext;
1434         int area_size;
1435         static int mbits = 0;
1436
1437         static int tap_repeat = 0;
1438         static int prev_num_pressed = 0;
1439
1440         static OsTimerPtr tapnhold_event_timer = NULL;
1441         static int event_type = GestureNotifyTapNHold;
1442         static int state = GestureEnd;
1443
1444         Time interval = 0;
1445         Time holdtime = 0;
1446
1447         if( timer_expired )
1448         {
1449                 if( (state == GestureEnd) && num_pressed )
1450                 {
1451 #ifdef __DETAIL_DEBUG__
1452                         ErrorF("[GroupTapNHold][Timer][state=%d] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", GestureEnd, tap_repeat, num_pressed, tap_repeat);
1453 #endif//__DETAIL_DEBUG__
1454                         state = 0;
1455                         goto cleanup_tapnhold;
1456                 }
1457
1458                 if( state == GestureDone )
1459                 {
1460 #ifdef __DETAIL_DEBUG__
1461                         ErrorF("[GroupTapNHold][Timer][state=%d] Interval between Tap and Hold is too long !\n");
1462 #endif//__DETAIL_DEBUG__
1463                         goto cleanup_tapnhold;
1464                 }
1465
1466 #ifdef __DETAIL_DEBUG__
1467                 switch( state )
1468                 {
1469                         case GestureBegin:
1470                                 ErrorF("[GroupTapNHold][Timer] TapNHold Begin !\n");
1471                                 break;
1472
1473                         case GestureUpdate:
1474                                 ErrorF("[GroupTapNHold][Timer] TapNHold Update !\n");
1475                                 break;
1476                 }
1477 #endif//__DETAIL_DEBUG__
1478
1479                 if( GestureHasFingerEventMask(GestureNotifyTapNHold, prev_num_pressed) )
1480                 {
1481                         GestureHandleGesture_TapNHold(prev_num_pressed, base_cx, base_cy, interval, holdtime, state);
1482                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1483                 }
1484                 else
1485                 {
1486 #ifdef __DETAIL_DEBUG__
1487                         ErrorF("[GroupTapNHold][Timer] %d finger TapNHold event was not grabbed/selected !\n", prev_num_pressed);
1488 #endif//__DETAIL_DEBUG__
1489                         goto cleanup_tapnhold;
1490                 }
1491
1492                 if( state <= GestureBegin )
1493                         state++;
1494                 return;
1495         }
1496
1497         switch( type )
1498         {
1499                 case ET_ButtonPress:
1500                         g_pGesture->fingers[idx].flags |= PressFlagTapNHold;
1501
1502                         if( g_pGesture->num_pressed < 2 )
1503                                 return;
1504
1505                         //if( !prev_num_pressed && (!base_area_size || g_pGesture->num_pressed > num_pressed) )
1506                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1507                         {
1508
1509                                 if( state == GestureUpdate )
1510                                 {
1511 #ifdef __DETAIL_DEBUG__
1512                                         ErrorF("[GroupTapNHold][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1513 #endif//__DETAIL_DEBUG__
1514                                         goto cleanup_tapnhold;
1515                                 }
1516
1517                                 if( state == GestureDone )
1518                                         state = GestureBegin;
1519
1520                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1521                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1522                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1523                                 base_time = GetTimeInMillis();
1524                                 base_box_ext.x1 = base_cx-TAPNHOLD_MOVE_THRESHOLD;
1525                                 base_box_ext.y1 = base_cy-TAPNHOLD_MOVE_THRESHOLD;
1526                                 base_box_ext.x2 = base_cx+TAPNHOLD_MOVE_THRESHOLD;
1527                                 base_box_ext.y2 = base_cy+TAPNHOLD_MOVE_THRESHOLD;
1528                                 if( state == GestureEnd )
1529                                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_TAP_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1530                                 else
1531                                 {
1532                                         TimerCancel(tapnhold_event_timer);
1533                                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1534                                 }
1535 #ifdef __DETAIL_DEBUG__
1536                                 ErrorF("[GroupTapNHold][P] Create Timer !(state=%d)\n", state);
1537 #endif//__DETAIL_DEBUG__
1538                         }
1539
1540                         num_pressed = g_pGesture->num_pressed;
1541
1542 #ifdef __DETAIL_DEBUG__
1543                         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);
1544 #endif//__DETAIL_DEBUG__
1545                         break;
1546
1547                 case ET_Motion:
1548                         if( !(g_pGesture->fingers[idx].flags & PressFlagTapNHold ) )
1549                                 break;
1550
1551                         if( num_pressed < 2 )
1552                                 return;
1553
1554                         if( num_pressed != g_pGesture->num_pressed )
1555                         {
1556                                 if( state != GestureEnd )
1557                                 {
1558 #ifdef __DETAIL_DEBUG__
1559                                 ErrorF("[GroupTapNHold][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1560 #endif//__DETAIL_DEBUG__
1561                                         goto cleanup_tapnhold;
1562                                 }
1563 #ifdef __DETAIL_DEBUG__
1564                                 ErrorF("[GroupTapNHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1565 #endif//__DETAIL_DEBUG__
1566                                 //goto cleanup_tapnhold;
1567                         }
1568
1569                         mbits |= (1 << idx);
1570                         if( mbits == (pow(2, num_pressed)-1) )
1571                         {
1572                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1573                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1574                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1575 #ifdef __DETAIL_DEBUG__
1576                                 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));
1577                                 ErrorF("[GroupTapNHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1578                                 ErrorF("[GroupTapNHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1579 #endif//__DETAIL_DEBUG__
1580
1581                                 if( ABS(base_area_size-area_size) >= TAPNHOLD_AREA_THRESHOLD )
1582                                 {
1583 #ifdef __DETAIL_DEBUG__
1584                                         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));
1585 #endif//__DETAIL_DEBUG__
1586                                         goto cleanup_tapnhold;
1587                                 }
1588
1589                                 if( !INBOX(&base_box_ext, cx, cy) )
1590                                 {
1591 #ifdef __DETAIL_DEBUG__
1592                                         ErrorF("[GroupTapNHold][M] current center coordinates is not in base coordinates box !\n");
1593 #endif//__DETAIL_DEBUG__
1594                                         goto cleanup_tapnhold;
1595                                 }
1596                         }
1597                         break;
1598
1599                 case ET_ButtonRelease:
1600                         if( state != GestureEnd && num_pressed >= 2)
1601                         {
1602 #ifdef __DETAIL_DEBUG__
1603                                 ErrorF("[GroupTapNHold][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1604 #endif//__DETAIL_DEBUG__
1605                                 goto cleanup_tapnhold;
1606                         }
1607
1608                         if( g_pGesture->num_pressed )
1609                                 break;
1610
1611                         if( !tap_repeat )
1612                         {
1613                                 prev_num_pressed = num_pressed;
1614                         }
1615
1616                         tap_repeat++;
1617
1618 #ifdef __DETAIL_DEBUG__
1619                         ErrorF("[GroupTapNHold][R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed);
1620 #endif//__DETAIL_DEBUG__
1621
1622                         if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTapNHold, num_pressed) )
1623                         {
1624 #ifdef __DETAIL_DEBUG__
1625                                 ErrorF("[GroupTapNHold][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
1626                                         num_pressed, prev_num_pressed, num_pressed);
1627 #endif//__DETAIL_DEBUG__
1628                                 goto cleanup_tapnhold;
1629                         }
1630
1631                         if( tap_repeat > 1 )
1632                         {
1633 #ifdef __DETAIL_DEBUG__
1634                                 ErrorF("[GroupTapNHold][R] Tap events(tap_repeat=%d) were put twice or more !(ignored)\n", tap_repeat);
1635 #endif//__DETAIL_DEBUG__
1636                                 goto cleanup_tapnhold;
1637                         }
1638
1639                         prev_num_pressed = num_pressed;
1640                         num_pressed = 0;
1641                         state = GestureDone;
1642
1643                         TimerCancel(tapnhold_event_timer);
1644                         tapnhold_event_timer = TimerSet(tapnhold_event_timer, 0, TAPNHOLD_INTV_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1645
1646 #ifdef __DETAIL_DEBUG__
1647                         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);
1648 #endif//__DETAIL_DEBUG__
1649                         break;
1650         }
1651
1652         return;
1653
1654 cleanup_tapnhold:
1655
1656         if( state == GestureUpdate )
1657         {
1658                 state = GestureEnd;
1659                 if( GestureHasFingerEventMask(GestureNotifyTapNHold, prev_num_pressed) )
1660                 {
1661                         GestureHandleGesture_TapNHold(prev_num_pressed, base_cx, base_cy, interval, holdtime, state);
1662                 }
1663         }
1664         else
1665         {
1666                 g_pGesture->recognized_gesture &= ~TapNHoldFilterMask;
1667         }
1668
1669         g_pGesture->filter_mask |= TapNHoldFilterMask;
1670         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
1671         {
1672 #ifdef __DETAIL_DEBUG__
1673                 ErrorF("[GroupTapNHold][cleanup] GestureFlushOrDrop() !\n");
1674 #endif//__DETAIL_DEBUG__
1675
1676                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
1677                 {
1678                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
1679                 }
1680         }
1681
1682         TimerCancel(tapnhold_event_timer);
1683         num_pressed = 0;
1684         tap_repeat = 0;
1685         prev_num_pressed = 0;
1686         mbits = 0;
1687         base_time = 0;
1688         state = 0;
1689
1690         return;
1691 }
1692
1693 void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
1694 {
1695         static int num_pressed = 0;
1696         static int base_area_size = 0;
1697         static Time base_time = 0;
1698         static int base_cx;
1699         static int base_cy;
1700         int cx, cy;
1701         static pixman_box16_t base_box_ext;
1702         int area_size;
1703         static int state = GestureEnd;
1704
1705         static OsTimerPtr hold_event_timer = NULL;
1706         static int event_type = GestureNotifyHold;
1707
1708         if( timer_expired )
1709         {
1710                 if( state <= GestureBegin )
1711                         state++;
1712
1713 #ifdef __DETAIL_DEBUG__
1714                 switch( state )
1715                 {
1716                         case GestureBegin:
1717                                 ErrorF("[GroupHold] HOLD Begin !\n");
1718                                 break;
1719
1720                         case GestureUpdate:
1721                                 ErrorF("[GroupHold] HOLD Update !\n");
1722                                 break;
1723                 }
1724 #endif//__DETAIL_DEBUG__
1725
1726                 if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
1727                 {
1728                         GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
1729                         hold_event_timer = TimerSet(hold_event_timer, 0, HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1730                 }
1731                 return;
1732         }
1733
1734         switch( type )
1735         {
1736                 case ET_ButtonPress:
1737                         g_pGesture->fingers[idx].flags |= PressFlagHold;
1738
1739                         if( g_pGesture->num_pressed < 2 )
1740                                 return;
1741
1742                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1743                         {
1744                                 if( state != GestureEnd )
1745                                 {
1746 #ifdef __DETAIL_DEBUG__
1747                                         ErrorF("[GroupHold][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1748 #endif//__DETAIL_DEBUG__
1749                                         goto cleanup_hold;
1750                                 }
1751
1752                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1753                                 base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1754                                 base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1755                                 base_time = GetTimeInMillis();
1756                                 base_box_ext.x1 = base_cx-HOLD_MOVE_THRESHOLD;
1757                                 base_box_ext.y1 = base_cy-HOLD_MOVE_THRESHOLD;
1758                                 base_box_ext.x2 = base_cx+HOLD_MOVE_THRESHOLD;
1759                                 base_box_ext.y2 = base_cy+HOLD_MOVE_THRESHOLD;
1760                                 event_type = GestureNotifyHold;
1761                                 hold_event_timer = TimerSet(hold_event_timer, 0, HOLD_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1762                         }
1763                         num_pressed = g_pGesture->num_pressed;
1764
1765 #ifdef __DETAIL_DEBUG__
1766                         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);
1767 #endif//__DETAIL_DEBUG__
1768                         break;
1769
1770                 case ET_Motion:
1771                         if( !(g_pGesture->fingers[idx].flags & PressFlagHold ) )
1772                                 break;
1773
1774                         if( num_pressed < 2 )
1775                                 return;
1776
1777                         if( num_pressed != g_pGesture->num_pressed )
1778                         {
1779                                 if( state != GestureEnd )
1780                                 {
1781 #ifdef __DETAIL_DEBUG__
1782                                 ErrorF("[GroupHold][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1783 #endif//__DETAIL_DEBUG__
1784                                         goto cleanup_hold;
1785                                 }
1786 #ifdef __DETAIL_DEBUG__
1787                                 ErrorF("[GroupHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1788 #endif//__DETAIL_DEBUG__
1789                                 //goto cleanup_hold;
1790                         }
1791
1792                         area_size = AREA_SIZE(&g_pGesture->area.extents);
1793                         cx = AREA_CENTER_X(&g_pGesture->area.extents);
1794                         cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1795 #ifdef __DETAIL_DEBUG__
1796                         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));
1797                         ErrorF("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
1798                         ErrorF("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
1799 #endif//__DETAIL_DEBUG__
1800
1801                         if( ABS(base_area_size-area_size) >= HOLD_AREA_THRESHOLD )
1802                         {
1803 #ifdef __DETAIL_DEBUG__
1804                                 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));
1805 #endif//__DETAIL_DEBUG__
1806                                 goto cleanup_hold;
1807                         }
1808
1809                         if( !INBOX(&base_box_ext, cx, cy) )
1810                         {
1811 #ifdef __DETAIL_DEBUG__
1812                                 ErrorF("[GroupHold][M] current center coordinates is not in base coordinates box !\n");
1813 #endif//__DETAIL_DEBUG__
1814                                 goto cleanup_hold;
1815                         }
1816                         break;
1817
1818                 case ET_ButtonRelease:
1819                         if( state != GestureEnd && num_pressed >= 2)
1820                         {
1821 #ifdef __DETAIL_DEBUG__
1822                                 ErrorF("[GroupHold][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1823 #endif//__DETAIL_DEBUG__
1824                                 goto cleanup_hold;
1825                         }
1826
1827                         //ErrorF("[GroupHold][R] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1828                         if( g_pGesture->num_pressed )
1829                                 break;
1830
1831                         goto cleanup_hold;
1832                         break;
1833         }
1834
1835         return;
1836
1837 cleanup_hold:
1838
1839         if( state == GestureBegin || state == GestureUpdate )
1840         {
1841                 state = GestureEnd;
1842                 if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
1843                 {
1844                         GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
1845                 }
1846         }
1847         else
1848         {
1849                 g_pGesture->recognized_gesture &= ~HoldFilterMask;
1850         }
1851
1852         g_pGesture->filter_mask |= HoldFilterMask;
1853         num_pressed = 0;
1854         base_area_size = 0;
1855         base_time = 0;
1856         base_cx = base_cy = 0;
1857         state = GestureEnd;
1858         base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
1859         TimerCancel(hold_event_timer);
1860         return;
1861 }
1862
1863 static inline void
1864 GestureEnableDisable()
1865 {
1866         if((g_pGesture->grabMask) || (g_pGesture->lastSelectedWin != None))
1867         {
1868                 GestureEnable(1, FALSE, g_pGesture->this_device);
1869         }
1870         else
1871         {
1872                 GestureEnable(0, FALSE, g_pGesture->this_device);
1873         }
1874 }
1875
1876 void
1877 GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent)
1878 {
1879         g_pGesture->grabMask = *pGrabMask;
1880         g_pGesture->GrabEvents = pGrabEvent;
1881         GestureEnableDisable();
1882 }
1883
1884 void
1885 GestureCbEventsSelected(Window win, Mask *pEventMask)
1886 {
1887         g_pGesture->lastSelectedWin = win;
1888         g_pGesture->lastSelectedMask = (pEventMask) ? *pEventMask : 0;
1889         GestureEnableDisable();
1890 }
1891
1892 WindowPtr
1893 GestureGetEventsWindow(void)
1894 {
1895         Mask mask;
1896         WindowPtr pWin;
1897
1898         pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py);
1899
1900         if( pWin )
1901         {
1902 #ifdef __DETAIL_DEBUG__
1903                 ErrorF("[X11][GestureGetEventsWindow] pWin->drawable.id=0x%x\n", pWin->drawable.id);
1904 #endif//__DETAIL_DEBUG__
1905                 g_pGesture->gestureWin = pWin->drawable.id;
1906         }
1907         else
1908         {
1909 #ifdef __DETAIL_DEBUG__
1910                 ErrorF("[X11][GestureGetEventsWindow] GestureWindowOnXY returns NULL !\n");
1911 #endif//__DETAIL_DEBUG__
1912                 return NULL;
1913         }
1914
1915         if(g_pGesture->gestureWin == g_pGesture->lastSelectedWin)
1916         {
1917                 g_pGesture->eventMask = g_pGesture->lastSelectedMask;
1918                 goto nonempty_eventmask;
1919         }
1920
1921         //check selected event(s)
1922         if( !GestureHasSelectedEvents(pWin, &g_pGesture->eventMask) )
1923         {
1924                 g_pGesture->eventMask = 0;
1925         }
1926         else
1927         {
1928                 g_pGesture->lastSelectedWin = g_pGesture->gestureWin;
1929                 g_pGesture->lastSelectedMask = g_pGesture->eventMask;
1930         }
1931
1932         if( !g_pGesture->eventMask && !g_pGesture->grabMask)
1933         {
1934 #ifdef __DETAIL_DEBUG__
1935                 ErrorF("[X11][GestureGetEventsWindow] No grabbed events or no events were selected for window(0x%x) !\n", pWin->drawable.id);
1936 #endif//__DETAIL_DEBUG__
1937                 return NULL;
1938         }
1939
1940 nonempty_eventmask:
1941
1942 #ifdef __DETAIL_DEBUG__
1943         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->eventMask=0x%x\n", g_pGesture->eventMask);
1944 #endif//__DETAIL_DEBUG__
1945
1946         mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask));
1947
1948 #ifdef __DETAIL_DEBUG__
1949         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x, mask=0x%x\n", g_pGesture->filter_mask, mask);
1950 #endif//__DETAIL_DEBUG__
1951
1952         g_pGesture->filter_mask = mask;
1953
1954 #ifdef __DETAIL_DEBUG__
1955         ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x\n", g_pGesture->filter_mask);
1956 #endif//__DETAIL_DEBUG__
1957
1958         return pWin;
1959 }
1960
1961 static CARD32
1962 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
1963 {
1964         int event_type = *(int *)arg;
1965
1966         switch( event_type )
1967         {
1968                 case GestureNotifyHold:
1969 #ifdef __DETAIL_DEBUG__
1970                         ErrorF("[GestureEventTimerHandler] GestureNotifyHold (event_type = %d)\n", event_type);
1971 #endif//__DETAIL_DEBUG__
1972                         GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1);
1973                         break;
1974
1975                 case GestureNotifyPan:
1976 #ifdef __DETAIL_DEBUG__
1977                         ErrorF("[GestureEventTimerHandler] GestureNotifyPan (event_type = %d)\n", event_type);
1978 #endif//__DETAIL_DEBUG__
1979                         GestureRecognize_GroupPan(event_type, NULL, NULL, 0, 1);
1980                         break;
1981
1982                 case GestureNotifyTap:
1983 #ifdef __DETAIL_DEBUG__
1984                         ErrorF("[GestureEventTimerHandler] GestureNotifyTap (event_type = %d)\n", event_type);
1985 #endif//__DETAIL_DEBUG__
1986                         GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1);
1987                         break;
1988
1989                 case GestureNotifyTapNHold:
1990 #ifdef __DETAIL_DEBUG__
1991                         ErrorF("[GestureEventTimerHandler] GestureNotifyTapNHold (event_type = %d)\n", event_type);
1992 #endif//__DETAIL_DEBUG__
1993                         GestureRecognize_GroupTapNHold(event_type, NULL, NULL, 0, 1);
1994                         break;
1995
1996                 case GestureNotifyPinchRotation:
1997 #ifdef __DETAIL_DEBUG__
1998                         ErrorF("[GestureEventTimerHandler] GestureNotifyPinchRotation (event_type = %d)\n", event_type);
1999 #endif//__DETAIL_DEBUG__
2000                         GestureRecognize_GroupPinchRotation(event_type, NULL, NULL, 0, 1);
2001                         break;
2002
2003                 default:
2004 #ifdef __DETAIL_DEBUG__
2005                         ErrorF("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type);
2006 #endif//__DETAIL_DEBUG__
2007                         if(timer)
2008                                 ErrorF("[GestureEventTimerHandler] timer=%p\n", timer);
2009         }
2010
2011         return 0;
2012 }
2013
2014 static CARD32
2015 GestureSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
2016 {
2017         g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
2018         g_pGesture->recognized_gesture = 0;
2019
2020         if( ERROR_INVALPTR == GestureFlushOrDrop() )
2021         {
2022                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2023         }
2024
2025 #ifdef __DETAIL_DEBUG__
2026         ErrorF("[X11][Single] expired !\n");
2027 #endif//__DETAIL_DEBUG__
2028
2029         return 0;
2030 }
2031
2032 void
2033 GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
2034 {
2035         int i;
2036         static OsTimerPtr single_finger_timer = NULL;
2037         int idx = -1;
2038
2039         if( PROPAGATE_EVENTS == g_pGesture->ehtype ||
2040                 device->id < g_pGesture->first_fingerid )
2041                 return;
2042
2043         for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ )
2044         {
2045                 if( device->id == g_pGesture->mt_devices[i]->id )
2046                 {
2047                         idx = i;
2048                         break;
2049                 }
2050         }
2051
2052         if( idx < 0 )
2053                 return;
2054
2055         switch( type )
2056         {
2057                 case ET_ButtonPress:
2058                         if( idx == 0 )
2059                                 g_pGesture->event_sum[0] = BTN_PRESSED;
2060                         g_pGesture->fingers[idx].ptime = ev->any.time;
2061                         g_pGesture->fingers[idx].px = ev->device_event.root_x;
2062                         g_pGesture->fingers[idx].py = ev->device_event.root_y;
2063
2064                         g_pGesture->num_pressed++;
2065                         if( g_pGesture->num_pressed == 1 )
2066                         {
2067                                 single_finger_timer = TimerSet(single_finger_timer, 0, 50, GestureSingleFingerTimerHandler, NULL);
2068                         }
2069                         else
2070                         {
2071                                 TimerCancel(single_finger_timer);
2072                         }
2073
2074                         if( g_pGesture->num_pressed > g_pGesture->num_mt_devices )
2075                                 g_pGesture->num_pressed = g_pGesture->num_mt_devices;
2076
2077                         if( !g_pGesture->pTempWin || g_pGesture->num_pressed != g_pGesture->inc_num_pressed )
2078                         {
2079                                 g_pGesture->pTempWin = GestureGetEventsWindow();
2080
2081                                 if( NULL == g_pGesture->pTempWin )
2082                                 {
2083 #ifdef __DETAIL_DEBUG__
2084                                         ErrorF("[X11][GestureRecognize][g_pGesture->num_pressed=%d] No events were selected !\n", g_pGesture->num_pressed);
2085 #endif//__DETAIL_DEBUG__
2086                                         g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
2087                                         goto flush_or_drop;
2088                                 }
2089                         }
2090
2091                         g_pGesture->inc_num_pressed = g_pGesture->num_pressed;
2092
2093                         g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
2094                         g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
2095                         g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
2096                         g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
2097
2098                         if( g_pGesture->inc_num_pressed == 1 )
2099                         {
2100                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2101 #ifdef __DETAIL_DEBUG__
2102                                 ErrorF("[P][g_pGesture->inc_num_pressed=1] AREA_SIZE(area.extents)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
2103 #endif//__DETAIL_DEBUG__
2104                         }
2105                         else
2106                         {
2107                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2108                                 for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
2109                                 {
2110                                         pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
2111                                 }
2112 #ifdef __DETAIL_DEBUG__
2113                                 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));
2114 #endif//__DETAIL_DEBUG__
2115                         }
2116                         break;
2117
2118                 case ET_Motion:
2119                         if( !g_pGesture->fingers[idx].ptime )
2120                                 return;
2121
2122                         g_pGesture->fingers[idx].mx = ev->device_event.root_x;
2123                         g_pGesture->fingers[idx].my = ev->device_event.root_y;
2124
2125                         if( idx == 0 && g_pGesture->event_sum[0] )
2126                         {
2127                                 g_pGesture->event_sum[0] += BTN_MOVING;
2128 #ifdef __DETAIL_DEBUG__
2129                                 ErrorF("[X11][GestureRecognize] moving !\n");
2130 #endif//__DETAIL_DEBUG__
2131                                 if( g_pGesture->event_sum[0] >= 7 )
2132                                 {
2133                                if( (g_pGesture->event_sum[0] >= 7) && (g_pGesture->inc_num_pressed < 2) )
2134                                 {
2135  #ifdef __DETAIL_DEBUG__
2136                                        ErrorF("[X11][GestureRecognize] moving limit!\n");
2137  #endif//__DETAIL_DEBUG__
2138                                        g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
2139                                             goto flush_or_drop;
2140                                 }
2141                                 }
2142                         }
2143
2144                         g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
2145                         g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
2146                         g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
2147                         g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
2148
2149                         if( g_pGesture->inc_num_pressed == 1 )
2150                         {
2151                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2152 #ifdef __DETAIL_DEBUG__
2153                                 ErrorF("[M][g_pGesture->inc_num_pressed=1] AREA_SIZE(area)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
2154 #endif//__DETAIL_DEBUG__
2155                         }
2156                         else
2157                         {
2158                                 pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
2159                                 for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
2160                                 {
2161                                         pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
2162                                 }
2163 #ifdef __DETAIL_DEBUG__
2164                                 ErrorF("[M][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
2165 #endif//__DETAIL_DEBUG__
2166                         }
2167                         break;
2168
2169                 case ET_ButtonRelease:
2170                         g_pGesture->fingers[idx].rtime = ev->any.time;
2171                         g_pGesture->fingers[idx].rx = ev->device_event.root_x;
2172                         g_pGesture->fingers[idx].ry = ev->device_event.root_y;
2173
2174                         g_pGesture->num_pressed--;
2175                         if( g_pGesture->num_pressed <= 0 )
2176                         {
2177 #ifdef __DETAIL_DEBUG__
2178         ErrorF("[X11][GestureRecognize] All fingers were released !\n");
2179 #endif//__DETAIL_DEBUG__
2180                                 if( g_pGesture->inc_num_pressed == 1 )
2181                                         goto flush_or_drop;
2182                         }
2183                         break;
2184         }
2185
2186         if( g_pGesture->filter_mask != GESTURE_FILTER_MASK_ALL )
2187         {
2188                 if( !(g_pGesture->filter_mask & FlickFilterMask) )
2189                 {
2190                         GestureRecognize_GroupFlick(type, ev, device, idx);
2191                 }
2192                 if( !(g_pGesture->filter_mask & PanFilterMask) )
2193                 {
2194                         GestureRecognize_GroupPan(type, ev, device, idx, 0);
2195                 }
2196                 if( !(g_pGesture->filter_mask & PinchRotationFilterMask) )
2197                 {
2198                         GestureRecognize_GroupPinchRotation(type, ev, device, idx, 0);
2199                 }
2200                 if( !(g_pGesture->filter_mask & TapFilterMask) )
2201                 {
2202                         GestureRecognize_GroupTap(type, ev, device, idx, 0);
2203                 }
2204                 if( !(g_pGesture->filter_mask & TapNHoldFilterMask) )
2205                 {
2206                         GestureRecognize_GroupTapNHold(type, ev, device, idx, 0);
2207                 }
2208                 if( !(g_pGesture->filter_mask & HoldFilterMask) )
2209                 {
2210                         GestureRecognize_GroupHold(type, ev, device, idx, 0);
2211                 }
2212         }
2213
2214 #ifdef __DETAIL_DEBUG__
2215         ErrorF("[X11][GestureRecognize][N] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
2216         ErrorF("[X11][GestureRecognize][N] g_pGesture->GESTURE_FILTER_MASK_ALL = 0x%x\n", GESTURE_FILTER_MASK_ALL);
2217         ErrorF("[X11][GestureRecognize][N] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
2218 #endif//__DETAIL_DEBUG__
2219
2220         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
2221         {
2222                 if( !g_pGesture->recognized_gesture )
2223                         goto flush_or_drop;
2224                 else if( !g_pGesture->num_pressed )
2225                         goto flush_or_drop;
2226         }
2227
2228         if( g_pGesture->recognized_gesture )
2229         {
2230                 if( g_pGesture->ehtype == KEEP_EVENTS )
2231                         GestureEventsDrop();
2232                 g_pGesture->ehtype = IGNORE_EVENTS;
2233         }
2234
2235         return;
2236
2237 flush_or_drop:
2238
2239 #ifdef __DETAIL_DEBUG__
2240         ErrorF("[GestureRecognize] GestureFlushOrDrop() !\n");
2241 #endif//__DETAIL_DEBUG__
2242         if( ERROR_INVALPTR == GestureFlushOrDrop() )
2243         {
2244                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2245         }
2246 }
2247
2248
2249 ErrorStatus GestureFlushOrDrop(void)
2250 {
2251         ErrorStatus err;
2252
2253         if( g_pGesture->recognized_gesture )
2254         {
2255                 GestureEventsDrop();
2256         }
2257         else
2258         {
2259                 g_pGesture->ehtype = PROPAGATE_EVENTS;
2260
2261                 err = GestureEventsFlush();
2262                 if( ERROR_NONE != err )
2263                         return err;
2264
2265 #ifdef __DETAIL_DEBUG__
2266                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
2267                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->GESTURE_FILTER_MASK_ALL = 0x%x\n", GESTURE_FILTER_MASK_ALL);
2268                 ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
2269 #endif//__DETAIL_DEBUG__
2270         }
2271
2272         err = GestureRegionsReinit();
2273         if( ERROR_NONE != err )
2274                 return err;
2275
2276         g_pGesture->pTempWin = NULL;
2277         g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
2278         g_pGesture->event_sum[0] = 0;
2279
2280         return ERROR_NONE;
2281 }
2282
2283 void
2284 GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2285 {
2286         int i;
2287
2288 #ifdef __DEBUG_EVENT_HANDLER__
2289         ErrorF("\n[X11][GestureHandleMTSyncEvent] (%d:%d) time:%d cur:%d\n",
2290                         ev->any_event.deviceid, ev->any_event.sync, (int)ev->any.time, (int)GetTimeInMillis());
2291 #endif//__DEBUG_EVENT_HANDLER__
2292
2293         if( MTOUCH_FRAME_SYNC_BEGIN == ev->any_event.sync )
2294         {
2295                 g_pGesture->ehtype = KEEP_EVENTS;
2296                 g_pGesture->filter_mask = 0;
2297                 g_pGesture->recognized_gesture = 0;
2298                 g_pGesture->num_pressed = 0;
2299
2300                 for( i=0 ; i < g_pGesture->num_mt_devices ; i++ )
2301                         g_pGesture->fingers[i].ptime = 0;
2302         }
2303         else if( MTOUCH_FRAME_SYNC_END == ev->any_event.sync )
2304         {
2305                 g_pGesture->ehtype = PROPAGATE_EVENTS;
2306         }
2307 }
2308
2309 void
2310 GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2311 {
2312 #ifdef __DEBUG_EVENT_HANDLER__
2313         ErrorF("[X11][GestureHandleButtonPEvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
2314 #endif//__DEBUG_EVENT_HANDLER__
2315
2316         switch( g_pGesture->ehtype )
2317         {
2318                 case KEEP_EVENTS:
2319                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
2320                         {
2321                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2322                                 return;
2323                         }
2324
2325                         if( g_pGesture->num_mt_devices )
2326                                 GestureRecognize(ET_ButtonPress, ev, device);
2327                         else
2328                                 device->public.processInputProc(ev, device);
2329                         break;
2330
2331                 case PROPAGATE_EVENTS:
2332                         device->public.processInputProc(ev, device);
2333                         break;
2334
2335                 case IGNORE_EVENTS:
2336                         GestureRecognize(ET_ButtonPress, ev, device);
2337                         break;
2338
2339                 default:
2340                         break;
2341         }
2342 }
2343
2344 void
2345 GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2346 {
2347 #ifdef __DEBUG_EVENT_HANDLER__
2348         ErrorF("[X11][GestureHandleMotionEvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
2349 #endif//__DEBUG_EVENT_HANDLER__
2350
2351         switch( g_pGesture->ehtype )
2352         {
2353                 case KEEP_EVENTS:
2354                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
2355                         {
2356                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2357                                 return;
2358                         }
2359
2360                         if( g_pGesture->num_mt_devices )
2361                                 GestureRecognize(ET_Motion, ev, device);
2362                         else
2363                                 device->public.processInputProc(ev, device);
2364                         break;
2365
2366                 case PROPAGATE_EVENTS:
2367                         device->public.processInputProc(ev, device);
2368                         break;
2369
2370                 case IGNORE_EVENTS:
2371                         GestureRecognize(ET_Motion, ev, device);
2372                         break;
2373
2374                 default:
2375                         break;
2376         }
2377
2378 }
2379
2380 void
2381 GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2382 {
2383 #ifdef __DEBUG_EVENT_HANDLER__
2384         ErrorF("[X11][GestureHandleButtonREvent] devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
2385 #endif//__DEBUG_EVENT_HANDLER__
2386
2387         switch( g_pGesture->ehtype )
2388         {
2389                 case KEEP_EVENTS:
2390                         if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
2391                         {
2392                                 GestureControl(g_pGesture->this_device, DEVICE_OFF);
2393                                 return;
2394                         }
2395
2396                         if( g_pGesture->num_mt_devices )
2397                                 GestureRecognize(ET_ButtonRelease, ev, device);
2398                         else
2399                                 device->public.processInputProc(ev, device);
2400                         break;
2401
2402                 case PROPAGATE_EVENTS:
2403                         device->public.processInputProc(ev, device);
2404                         break;
2405
2406                 case IGNORE_EVENTS:
2407                         GestureRecognize(ET_ButtonRelease, ev, device);
2408                         break;
2409
2410                 default:
2411                         break;
2412         }
2413 }
2414
2415 static ErrorStatus
2416 GestureEnableEventHandler(InputInfoPtr pInfo)
2417  {
2418         Bool res;
2419         GestureDevicePtr pGesture = pInfo->private;
2420
2421         res = GestureInstallResourceStateHooks();
2422
2423         if( !res )
2424         {
2425                 ErrorF("[X11][GestureEnableEventHandler] Failed on GestureInstallResourceStateHooks() !\n");
2426                 return ERROR_ABNORMAL;
2427         }
2428
2429         res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES);
2430
2431         if( !res )
2432         {
2433                 ErrorF("[X11][GestureEnableEventHandler] Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES);
2434                 goto failed;
2435         }
2436
2437         res = GestureRegisterCallbacks(GestureCbEventsGrabbed, GestureCbEventsSelected);
2438
2439         if( !res )
2440         {
2441                 ErrorF("[X11][GestureEnableEventHandler] Failed to register callbacks for GestureEventsGrabbed(), GestureEventsSelected() !\n");
2442                 goto failed;
2443         }
2444
2445         pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 5000, GestureTimerHandler, pInfo);
2446
2447         if( !pGesture->device_setting_timer )
2448         {
2449                 ErrorF("[X11][GestureEnableEventHandler] Failed to allocate memory for timer !\n");
2450                 goto failed;
2451         }
2452
2453         return ERROR_NONE;
2454
2455 failed:
2456         GestureUninstallResourceStateHooks();
2457         GestureUnsetMaxNumberOfFingers();
2458
2459         return ERROR_ABNORMAL;
2460 }
2461
2462 static ErrorStatus
2463 GestureDisableEventHandler(void)
2464 {
2465         ErrorStatus err = ERROR_NONE;
2466
2467         mieqSetHandler(ET_ButtonPress, NULL);
2468         mieqSetHandler(ET_ButtonRelease, NULL);
2469         mieqSetHandler(ET_Motion, NULL);
2470         mieqSetHandler(ET_MTSync, NULL);
2471
2472         err = GestureFiniEQ();
2473
2474         if( ERROR_INVALPTR == err )
2475         {
2476                 ErrorF("[X11][GestureDisableEventHandler] EQ is invalid or was freed already !\n");
2477         }
2478
2479         GestureRegisterCallbacks(NULL, NULL);
2480         GestureUninstallResourceStateHooks();
2481
2482         return err;
2483 }
2484
2485 static CARD32
2486 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
2487 {
2488         InputInfoPtr pInfo = (InputInfoPtr)arg;
2489         GestureDevicePtr pGesture = pInfo->private;
2490
2491         int idx = 0;
2492         DeviceIntPtr dev;
2493         for( dev = inputInfo.pointer ; dev; dev = dev->next )
2494         {
2495                 if(IsMaster(dev) && IsPointerDevice(dev))
2496                 {
2497                         pGesture->master_pointer = dev;
2498                         ErrorF("[X11][GestureTimerHandler][id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name);
2499                         continue;
2500                 }
2501
2502                 if(IsXTestDevice(dev, NULL) && IsPointerDevice(dev))
2503                 {
2504                         pGesture->xtest_pointer = dev;
2505                         ErrorF("[X11][GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name);
2506                         continue;
2507                 }
2508
2509                 if(IsPointerDevice(dev))
2510                 {
2511                         if( idx >= MAX_MT_DEVICES )
2512                         {
2513                                 ErrorF("[X11][GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n",
2514                                         MAX_MT_DEVICES);
2515                                 continue;
2516                         }
2517                         pGesture->mt_devices[idx] = dev;
2518                         ErrorF("[X11][GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
2519                         idx++;
2520                 }
2521         }
2522
2523         if( !pGesture->master_pointer || !pGesture->xtest_pointer )
2524         {
2525                 ErrorF("[X11][GestureTimerHandler] Failed to get info of master pointer or XTest pointer !\n");
2526                 pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2527                 pGesture->num_mt_devices = 0;
2528
2529                 return 0;
2530         }
2531
2532         pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2533         pGesture->num_mt_devices = idx;
2534
2535         if( !pGesture->num_mt_devices )
2536         {
2537                 ErrorF("[X11][GestureTimerHandler] Failed to mt device information !\n");
2538                 pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2539                 pGesture->num_mt_devices = 0;
2540         pGesture->first_fingerid = -1;
2541                 return 0;
2542         }
2543
2544         pGesture->first_fingerid = pGesture->mt_devices[0]->id;
2545         memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
2546         pGesture->pRootWin = RootWindow(pGesture->master_pointer);
2547         g_pGesture->pTempWin = NULL;
2548         g_pGesture->inc_num_pressed = 0;
2549
2550         if( ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ() )
2551         {
2552                 goto failed;
2553         }
2554
2555         mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
2556         mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
2557         mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
2558
2559         if( pGesture->is_active )
2560                 mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
2561
2562         return 0;
2563
2564 failed:
2565
2566         GestureUninstallResourceStateHooks();
2567         GestureUnsetMaxNumberOfFingers();
2568
2569         return 0;
2570 }
2571
2572 BOOL
2573 IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
2574 {
2575         if (IsMaster(dev))
2576                 return FALSE;
2577
2578         if (master)
2579                 return (dev->xtest_master_id == master->id);
2580
2581         return (dev->xtest_master_id != 0);
2582 }
2583
2584 void
2585 GestureEnable(int enable, Bool prop, DeviceIntPtr dev)
2586 {
2587         if((!enable) && (g_pGesture->is_active))
2588         {
2589                 g_pGesture->ehtype = PROPAGATE_EVENTS;
2590                 mieqSetHandler(ET_MTSync, NULL);
2591                 g_pGesture->is_active = 0;
2592                 ErrorF("[X11][GestureEnable] Disabled !\n");
2593         }
2594         else if((enable) && (!g_pGesture->is_active))
2595         {
2596                 g_pGesture->ehtype = KEEP_EVENTS;
2597                 mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
2598                 g_pGesture->is_active = 1;
2599                 ErrorF("[X11][GestureEnable] Enabled !\n");
2600         }
2601
2602         if(!prop)
2603                  XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
2604 }
2605
2606 ErrorStatus
2607 GestureRegionsInit(void)
2608 {
2609         int i;
2610
2611         if( !g_pGesture )
2612                 return ERROR_INVALPTR;
2613
2614         pixman_region_init(&g_pGesture->area);
2615
2616         for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
2617         {
2618                 pixman_region_init_rect (&g_pGesture->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T);
2619         }
2620
2621         return ERROR_NONE;
2622 }
2623
2624 ErrorStatus
2625 GestureRegionsReinit(void)
2626 {
2627         if( !g_pGesture )
2628         {
2629                 ErrorF("[X11][GestureRegionsReinit] Invalid pointer access !\n");
2630                 return ERROR_INVALPTR;
2631         }
2632
2633         pixman_region_init(&g_pGesture->area);
2634
2635         return ERROR_NONE;
2636 }
2637
2638 ErrorStatus
2639 GestureInitEQ(void)
2640 {
2641         int i;
2642         IEventPtr tmpEQ;
2643
2644         tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec));
2645
2646         if( !tmpEQ )
2647         {
2648                 ErrorF("[X11][GestureInitEQ] Failed to allocate memory for EQ !\n");
2649                 return ERROR_ALLOCFAIL;
2650         }
2651
2652         for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
2653         {
2654                 tmpEQ[i].event = (InternalEvent *)malloc(sizeof(InternalEvent));
2655                 if( !tmpEQ[i].event )
2656                 {
2657                         ErrorF("[X11][GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n");
2658                         i--;
2659                         while(i >= 0 && tmpEQ[i].event)
2660                         {
2661                                 free(tmpEQ[i].event);
2662                                 tmpEQ[i].event = NULL;
2663                         }
2664                         free (tmpEQ);
2665                         tmpEQ = NULL;
2666                         return ERROR_ALLOCFAIL;
2667                 }
2668         }
2669
2670         g_pGesture->EQ = tmpEQ;
2671         g_pGesture->headEQ = g_pGesture->tailEQ = 0;
2672
2673         return ERROR_NONE;
2674 }
2675
2676 ErrorStatus
2677 GestureFiniEQ(void)
2678 {
2679         int i;
2680
2681         if( !g_pGesture || !g_pGesture->EQ )
2682                 return ERROR_INVALPTR;
2683
2684         for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
2685         {
2686                 if( g_pGesture->EQ[i].event )
2687                 {
2688                         free(g_pGesture->EQ[i].event);
2689                         g_pGesture->EQ[i].event = NULL;
2690                 }
2691         }
2692
2693         free(g_pGesture->EQ);
2694         g_pGesture->EQ = NULL;
2695
2696         return ERROR_NONE;
2697 }
2698
2699 ErrorStatus
2700 GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2701 {
2702         int tail;
2703
2704         if( !g_pGesture || !g_pGesture->EQ )
2705         {
2706                 ErrorF("[X11][GestureEnqueueEvent] Invalid pointer access !\n");
2707                 return ERROR_INVALPTR;
2708         }
2709
2710         tail = g_pGesture->tailEQ;
2711
2712         if( tail >= GESTURE_EQ_SIZE )
2713         {
2714                 ErrorF("[X11][GestureEnqueueEvent] Gesture EQ is full !\n");
2715                 printk("[X11][GestureEnqueueEvent] Gesture EQ is full...Force Gesture Flush !\n");
2716                 GestureEventsFlush();
2717                 return ERROR_EQFULL;
2718         }
2719
2720 #ifdef __DETAIL_DEBUG__
2721         switch( ev->any.type )
2722         {
2723                 case ET_ButtonPress:
2724                         ErrorF("[X11][GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id);
2725                         break;
2726
2727                 case ET_ButtonRelease:
2728                         ErrorF("[X11][GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id);
2729                         break;
2730
2731                 case ET_Motion:
2732                         ErrorF("[X11][GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id);
2733                         break;
2734         }
2735 #endif//__DETAIL_DEBUG__
2736
2737         g_pGesture->EQ[tail].device = device;
2738         g_pGesture->EQ[tail].screen_num = screen_num;
2739         memcpy(g_pGesture->EQ[tail].event, ev, sizeof(InternalEvent));//need to be optimized
2740         g_pGesture->tailEQ++;
2741
2742         return ERROR_NONE;
2743 }
2744
2745 ErrorStatus
2746 GestureEventsFlush(void)
2747 {
2748         int i;
2749         DeviceIntPtr device;
2750
2751         if( !g_pGesture->EQ )
2752         {
2753                 ErrorF("[X11][GestureEventsFlush] Invalid pointer access !\n");
2754                 return ERROR_INVALPTR;
2755         }
2756
2757 #ifdef __DETAIL_DEBUG__
2758         ErrorF("[X11][GestureEventsFlush]\n");
2759 #endif//__DETAIL_DEBUG__
2760
2761         for( i = g_pGesture->headEQ ; i < g_pGesture->tailEQ ; i++)
2762         {
2763                 device = g_pGesture->EQ[i].device;
2764                 device->public.processInputProc(g_pGesture->EQ[i].event, device);
2765         }
2766
2767         for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
2768                 g_pGesture->event_sum[i] = 0;
2769
2770         g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
2771
2772         return ERROR_NONE;
2773 }
2774
2775 void
2776 GestureEventsDrop(void)
2777 {
2778         g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
2779 }
2780
2781 #ifdef HAVE_PROPERTIES
2782 static void
2783 GestureInitProperty(DeviceIntPtr dev)
2784 {
2785         int rc;
2786
2787         prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
2788         rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
2789
2790         if (rc != Success)
2791                 return;
2792
2793         XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
2794 }
2795
2796 static int
2797 GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
2798                  BOOL checkonly)
2799 {
2800         InputInfoPtr pInfo  = dev->public.devicePrivate;
2801
2802         if( prop_gesture_recognizer_onoff == atom )
2803         {
2804                 int data;
2805                 if( val->format != 32 || val->type != XA_INTEGER || val->size != 1 )
2806                         return BadMatch;
2807
2808                 if( !checkonly )
2809                 {
2810                         data = *((int *)val->data);
2811                         GestureEnable(data, TRUE, dev);
2812                 }
2813         }
2814
2815         return Success;
2816 }
2817 #endif//HAVE_PROPERTIES
2818
2819 static int
2820 GestureInit(DeviceIntPtr device)
2821 {
2822         InputInfoPtr pInfo;
2823         pInfo = device->public.devicePrivate;
2824
2825 #ifdef HAVE_PROPERTIES
2826         GestureInitProperty(device);
2827         XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
2828 #endif
2829
2830         return Success;
2831 }
2832
2833 static void
2834 GestureFini(DeviceIntPtr device)
2835 {
2836         XIRegisterPropertyHandler(device, NULL, NULL, NULL);
2837 }
2838
2839 static pointer
2840 GesturePlug(pointer module, pointer options, int *errmaj, int *errmin)
2841 {
2842         xf86AddInputDriver(&GESTURE, module, 0);
2843         return module;
2844 }
2845
2846 static void
2847 GestureUnplug(pointer p)
2848 {
2849 }
2850
2851 static InputInfoPtr
2852 GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2853 {
2854     int rc = BadAlloc;
2855     GestureDevicePtr    pGesture;
2856
2857     pGesture = calloc(1, sizeof(GestureDeviceRec));
2858
2859     if (!pGesture) {
2860         pInfo->private = NULL;
2861         //xf86DeleteInput(pInfo, 0);
2862         goto error;
2863     }
2864
2865     g_pGesture = pGesture;
2866     pInfo->private = pGesture;
2867     pInfo->flags = 0;
2868     pInfo->read_input = GestureReadInput; /* new data avl */
2869     pInfo->switch_mode = NULL; /* toggle absolute/relative mode */
2870     pInfo->device_control = GestureControl; /* enable/disable dev */
2871     /* process driver specific options */
2872     pGesture->device = xf86SetStrOption(pInfo->options, "Device", "/dev/null");
2873     pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0);
2874     pGesture->gestureWin = None;
2875     pGesture->lastSelectedWin = None;
2876     g_pGesture->grabMask = g_pGesture->eventMask = 0;
2877
2878     xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device);
2879
2880     /* process generic options */
2881     xf86CollectInputOptions(pInfo, NULL);
2882     xf86ProcessCommonOptions(pInfo, pInfo->options);
2883
2884     pInfo->fd = -1;
2885
2886     return Success;
2887
2888 error:
2889     if (pInfo->fd >= 0)
2890         close(pInfo->fd);
2891     return rc;
2892 }
2893
2894 static void
2895 GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2896 {
2897         GestureDevicePtr pGesture = pInfo->private;
2898
2899         g_pGesture = pGesture = NULL;
2900         pInfo->private = NULL;
2901
2902         xf86DeleteInput(pInfo, 0);
2903 }
2904
2905 static int
2906 GestureControl(DeviceIntPtr device, int what)
2907 {
2908     InputInfoPtr  pInfo = device->public.devicePrivate;
2909     GestureDevicePtr pGesture = pInfo->private;
2910
2911     switch(what)
2912     {
2913         case DEVICE_INIT:
2914              GestureInit(device);
2915             break;
2916
2917         /* Switch device on.  Establish socket, start event delivery.  */
2918         case DEVICE_ON:
2919             xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
2920
2921             if (device->public.on)
2922                     break;
2923
2924             device->public.on = TRUE;
2925              pGesture->this_device = device;
2926              pGesture->num_mt_devices = 0;
2927              if( ERROR_ABNORMAL == GestureEnableEventHandler(pInfo) )
2928                 goto device_off;
2929             break;
2930
2931        case DEVICE_OFF:
2932 device_off:
2933              GestureDisableEventHandler();
2934              GestureFini(device);
2935              pGesture->this_device = NULL;
2936              xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
2937
2938             if (!device->public.on)
2939                 break;
2940
2941             pInfo->fd = -1;
2942             device->public.on = FALSE;
2943             break;
2944
2945       case DEVICE_CLOSE:
2946             /* free what we have to free */
2947             break;
2948     }
2949     return Success;
2950 }
2951
2952 static void
2953 GestureReadInput(InputInfoPtr pInfo)
2954 {
2955 }
2956