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