Tizen 2.0 Release
[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 void
174 printk(const char* fmt, ...)
175 {
176         static FILE* fp = NULL;
177         static char init = 0;
178         va_list argptr;
179
180         if(!init && !fp)
181         {
182                 fp = fopen("/dev/kmsg", "wt");
183                 init = 1;
184         }
185
186         if(!fp) return;
187
188         va_start(argptr, fmt);
189         vfprintf(fp, fmt, argptr);
190         fflush(fp);
191         va_end(argptr);
192 }
193
194 static Bool
195 PointInBorderSize(WindowPtr pWin, int x, int y)
196 {
197     BoxRec box;
198     if( pixman_region_contains_point (&pWin->borderSize, x, y, &box) )
199         return TRUE;
200
201     return FALSE;
202 }
203
204 static WindowPtr
205 GestureWindowOnXY(int x, int y)
206 {
207     WindowPtr pWin;
208     BoxRec box;
209     SpritePtr pSprite;
210     DeviceIntPtr pDev = g_pGesture->master_pointer;
211
212     pSprite = pDev->spriteInfo->sprite;
213     pSprite->spriteTraceGood = 1;       /* root window still there */
214     pWin = RootWindow(pDev)->firstChild;
215
216     while (pWin)
217     {
218         if ((pWin->mapped) &&
219             (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
220             (x < pWin->drawable.x + (int)pWin->drawable.width +
221              wBorderWidth(pWin)) &&
222             (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
223             (y < pWin->drawable.y + (int)pWin->drawable.height +
224              wBorderWidth (pWin))
225             /* When a window is shaped, a further check
226              * is made to see if the point is inside
227              * borderSize
228              */
229             && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
230             && (!wInputShape(pWin) ||
231                 RegionContainsPoint(wInputShape(pWin),
232                                     x - pWin->drawable.x,
233                                     y - pWin->drawable.y, &box))
234 #ifdef ROOTLESS
235     /* In rootless mode windows may be offscreen, even when
236      * they're in X's stack. (E.g. if the native window system
237      * implements some form of virtual desktop system).
238      */
239                 && !pWin->rootlessUnhittable
240 #endif
241             )
242         {
243             if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
244             {
245                 pSprite->spriteTraceSize += 10;
246                 pSprite->spriteTrace = realloc(pSprite->spriteTrace,
247                                     pSprite->spriteTraceSize*sizeof(WindowPtr));
248             }
249             pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
250             pWin = pWin->firstChild;
251         }
252         else
253             pWin = pWin->nextSib;
254     }
255     return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
256 }
257
258 Bool
259 GestureHasFingerEventMask(int eventType, int num_finger)
260 {
261         Bool ret = FALSE;
262         Mask eventmask = (1L << eventType);
263
264         if( (g_pGesture->grabMask & eventmask) &&
265                 (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[num_finger].window != None) )
266         {
267 #ifdef __DETAIL_DEBUG__
268                 ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has grabMask\n");
269 #endif//__DETAIL_DEBUG__
270                 return TRUE;
271         }
272
273         if( g_pGesture->eventMask & eventmask )
274         {
275 #ifdef __DETAIL_DEBUG__
276                 ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has eventMask\n");
277 #endif//__DETAIL_DEBUG__
278                 return TRUE;
279         }
280
281 #ifdef __DETAIL_DEBUG__
282         ErrorF("[X11][GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger);
283 #endif//__DETAIL_DEBUG__
284
285         return ret;
286 }
287
288 static double
289 get_angle(int x1, int y1, int x2, int y2)
290 {
291    double a, xx, yy;
292    xx = fabs(x2 - x1);
293    yy = fabs(y2 - y1);
294
295    if (((int) xx) && ((int) yy))
296      {
297         a = atan(yy / xx);
298         if (x1 < x2)
299           {
300              if (y1 < y2)
301                {
302                   return (RAD_360DEG - a);
303                }
304              else
305                {
306                   return (a);
307                }
308           }
309         else
310           {
311              if (y1 < y2)
312                {
313                   return (RAD_180DEG + a);
314                }
315              else
316                {
317                   return (RAD_180DEG - a);
318                }
319           }
320      }
321
322    if (((int) xx))
323      {  /* Horizontal line */
324         if (x2 < x1)
325           {
326              return (RAD_180DEG);
327           }
328         else
329           {
330              return (0.0);
331           }
332      }
333
334    /* Vertical line */
335    if (y2 < y1)
336      {
337         return (RAD_90DEG);
338      }
339    else
340      {
341         return (RAD_270DEG);
342      }
343 }
344
345 void
346 GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction)
347 {
348         Window target_win;
349         WindowPtr target_pWin;
350         xGestureNotifyFlickEvent fev;
351
352 #ifdef __DETAIL_DEBUG__
353         ErrorF("[X11][GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n",
354                 num_of_fingers, distance, duration, direction);
355 #endif//__DETAIL_DEBUG__
356
357         g_pGesture->recognized_gesture |= FlickFilterMask;
358         memset(&fev, 0, sizeof(xGestureNotifyFlickEvent));
359         fev.type = GestureNotifyFlick;
360         fev.kind = GestureDone;
361         fev.num_finger = num_of_fingers;
362         fev.distance = distance;
363         fev.duration = duration;
364         fev.direction = direction;
365
366         target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window;
367         target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin;
368
369         if( g_pGesture->grabMask && (target_win != None) )
370         {
371                 fev.window = target_win;
372         }
373         else
374         {
375                 fev.window = g_pGesture->gestureWin;
376         }
377
378 #ifdef __DETAIL_DEBUG__
379         ErrorF("[X11][GestureHandleGesture_Flick] fev.window=0x%x, g_pGesture->grabMask=0x%x\n", fev.window, g_pGesture->grabMask);
380 #endif//__DETAIL_DEBUG__
381
382         GestureSendEvent(target_pWin, GestureNotifyFlick, GestureFlickMask, (xGestureCommonEvent *)&fev);
383 }
384
385 void
386 GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy)
387 {
388         Window target_win;
389         WindowPtr target_pWin;
390         xGestureNotifyTapEvent tev;
391
392         //skip non-tap events and single finger tap
393         if( !tap_repeat || num_finger <= 1 )
394                 return;
395
396 #ifdef __DETAIL_DEBUG__
397         ErrorF("[X11][GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n",
398                 num_finger, tap_repeat, cx, cy);
399 #endif//__DETAIL_DEBUG__
400
401         g_pGesture->recognized_gesture |= TapFilterMask;
402         memset(&tev, 0, sizeof(xGestureNotifyTapEvent));
403         tev.type = GestureNotifyTap;
404         tev.kind = GestureDone;
405         tev.num_finger = num_finger;
406         tev.tap_repeat = tap_repeat;
407         tev.interval = 0;
408         tev.cx = cx;
409         tev.cy = cy;
410
411         target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window;
412         target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin;
413
414         if( g_pGesture->grabMask && (target_win != None) )
415         {
416                 tev.window = target_win;
417         }
418         else
419         {
420                 tev.window = g_pGesture->gestureWin;
421         }
422
423 #ifdef __DETAIL_DEBUG__
424         ErrorF("[X11][GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", tev.window, g_pGesture->grabMask);
425 #endif//__DETAIL_DEBUG__
426
427         GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev);
428 }
429
430 void GestureHandleGesture_PinchRotation(int num_of_fingers, double zoom, double angle, int distance, int cx, int cy, int kinds)
431 {
432         Window target_win;
433         WindowPtr target_pWin;
434         xGestureNotifyPinchRotationEvent prev;
435
436 #ifdef __DETAIL_DEBUG__
437         ErrorF("[X11][GestureHandleGesture_PinchRotation] num_fingers=%d, zoom=%.2f, angle=%.2f(deg=%.2f), distance=%d, cx=%d, cy=%d\n",
438                                 num_of_fingers, zoom, angle, rad2degree(angle), distance, cx, cy);
439 #endif//__DETAIL_DEBUG__
440
441         g_pGesture->recognized_gesture |= PinchRotationFilterMask;
442         memset(&prev, 0, sizeof(xGestureNotifyPinchRotationEvent));
443         prev.type = GestureNotifyPinchRotation;
444         prev.kind = kinds;
445         prev.num_finger = num_of_fingers;
446         prev.zoom = XDoubleToFixed(zoom);
447         prev.angle = XDoubleToFixed(angle);
448         prev.distance = distance;
449         prev.cx = cx;
450         prev.cy = cy;
451
452         target_win = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].window;
453         target_pWin = g_pGesture->GrabEvents[GestureNotifyPinchRotation].pGestureGrabWinInfo[num_of_fingers].pWin;
454
455         if( g_pGesture->grabMask && (target_win != None) )
456         {
457                 prev.window = target_win;
458         }
459         else
460         {
461                 prev.window = g_pGesture->gestureWin;
462         }
463
464 #ifdef __DETAIL_DEBUG__
465         ErrorF("[X11][GestureHandleGesture_PinchRotation] prev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)prev.window, (unsigned int)g_pGesture->grabMask);
466 #endif//__DETAIL_DEBUG__
467
468         GestureSendEvent(target_pWin, GestureNotifyPinchRotation, GesturePinchRotationMask, (xGestureCommonEvent *)&prev);
469 }
470
471 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds)
472 {
473         Window target_win;
474         WindowPtr target_pWin;
475         xGestureNotifyHoldEvent hev;
476
477 #ifdef __DETAIL_DEBUG__
478         ErrorF("[X11][GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n",
479                                 num_fingers, cx, cy, holdtime, kinds);
480 #endif//__DETAIL_DEBUG__
481
482         g_pGesture->recognized_gesture |= HoldFilterMask;
483         memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
484         hev.type = GestureNotifyHold;
485         hev.kind = kinds;
486         hev.num_finger = num_fingers;
487         hev.holdtime = holdtime;
488         hev.cx = cx;
489         hev.cy = cy;
490
491         target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window;
492         target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin;
493
494         if( g_pGesture->grabMask && (target_win != None) )
495         {
496                 hev.window = target_win;
497         }
498         else
499         {
500                 hev.window = g_pGesture->gestureWin;
501         }
502
503 #ifdef __DETAIL_DEBUG__
504         ErrorF("[X11][GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask);
505 #endif//__DETAIL_DEBUG__
506
507         GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev);
508 }
509
510 void GestureHandleGesture_TapNHold(int num_fingers, int cx, int cy, Time interval, Time holdtime, int kinds)
511 {
512         Window target_win;
513         WindowPtr target_pWin;
514         xGestureNotifyTapNHoldEvent thev;
515
516 #ifdef __DETAIL_DEBUG__
517         ErrorF("[X11][GestureHandleGesture_TapNHold] num_fingers=%d, cx=%d, cy=%d, interval=%d, holdtime=%d, kinds=%d\n",
518                                 num_fingers, cx, cy, interval, holdtime, kinds);
519 #endif//__DETAIL_DEBUG__
520
521         g_pGesture->recognized_gesture |= TapNHoldFilterMask;
522         memset(&thev, 0, sizeof(xGestureNotifyTapNHoldEvent));
523         thev.type = GestureNotifyTapNHold;
524         thev.kind = kinds;
525         thev.num_finger = num_fingers;
526         thev.holdtime = holdtime;
527         thev.cx = cx;
528         thev.cy = cy;
529         thev.interval = interval;
530
531         target_win = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].window;
532         target_pWin = g_pGesture->GrabEvents[GestureNotifyTapNHold].pGestureGrabWinInfo[num_fingers].pWin;
533
534         if( g_pGesture->grabMask && (target_win != None) )
535         {
536                 thev.window = target_win;
537         }
538         else
539         {
540                 thev.window = g_pGesture->gestureWin;
541         }
542
543 #ifdef __DETAIL_DEBUG__
544         ErrorF("[X11][GestureHandleGesture_TapNHold] thev.window=0x%x, g_pGesture->grabMask=0x%x\n", thev.window, g_pGesture->grabMask);
545 #endif//__DETAIL_DEBUG__
546
547         GestureSendEvent(target_pWin, GestureNotifyTapNHold, GestureTapNHoldMask, (xGestureCommonEvent *)&thev);
548 }
549
550 void GestureHandleGesture_Pan(int num_fingers, short int dx, short int dy, int direction, int distance, Time duration, int kinds)
551 {
552         Window target_win;
553         WindowPtr target_pWin;
554         xGestureNotifyPanEvent pev;
555
556 #ifdef __DETAIL_DEBUG__
557         ErrorF("[X11][GestureHandleGesture_Pan] num_fingers=%d, dx=%d, dy=%d, direction=%d, distance=%d, duration=%d, kinds=%d\n",
558                                 num_fingers, dx, dy, direction, distance, duration, kinds);
559 #endif//__DETAIL_DEBUG__
560
561         g_pGesture->recognized_gesture |= PanFilterMask;
562         memset(&pev, 0, sizeof(xGestureNotifyPanEvent));
563         pev.type = GestureNotifyPan;
564         pev.kind = kinds;
565         pev.num_finger = num_fingers;
566         pev.direction = direction;
567         pev.distance = distance;
568         pev.duration = duration;
569         pev.dx = dx;
570         pev.dy = dy;
571
572         target_win = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].window;
573         target_pWin = g_pGesture->GrabEvents[GestureNotifyPan].pGestureGrabWinInfo[num_fingers].pWin;
574
575         if( g_pGesture->grabMask && (target_win != None) )
576         {
577                 pev.window = target_win;
578         }
579         else
580         {
581                 pev.window = g_pGesture->gestureWin;
582         }
583
584 #ifdef __DETAIL_DEBUG__
585         ErrorF("[X11][GestureHandleGesture_Pan] pev.window=0x%x, g_pGesture->grabMask=0x%x\n", pev.window, g_pGesture->grabMask);
586 #endif//__DETAIL_DEBUG__
587
588         GestureSendEvent(target_pWin, GestureNotifyPan, GesturePanMask, (xGestureCommonEvent *)&pev);
589 }
590
591 void
592 GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
593 {
594         static int cx, cy;
595
596         static int num_pressed = 0;
597         static int state = GestureEnd;
598         static int event_type = GestureNotifyPinchRotation;
599         static OsTimerPtr pinchrotation_event_timer = NULL;
600
601         static pixman_region16_t base_area;
602         static pixman_region16_t cur_area;
603
604         static double base_distance = 0.0f;
605         static double base_angle = 0.0f;
606
607         static double prev_distance = 0.0f;
608         static double prev_angle = 0.0f;
609
610         static double cur_distance = 0.0f;
611         static double cur_angle = 0.0f;
612
613         double diff_distance = 0.0f;
614         double diff_angle = 0.0f;
615
616         static int has_event_mask = 0;
617
618         static Time base_time = 0;
619         Time current_time;
620
621         if( timer_expired )
622         {
623                 if( state == GestureEnd )
624                 {
625                         current_time = GetTimeInMillis();
626                         if( (current_time - base_time) >= PINCHROTATION_TIME_THRESHOLD )
627                         {
628 #ifdef __DETAIL_DEBUG__
629                                 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);
630 #endif//__DETAIL_DEBUG__
631                                 goto cleanup_pinchrotation;
632                         }
633                 }
634
635                 return;
636         }
637
638         switch( type )
639         {
640                 case ET_ButtonPress:
641                         g_pGesture->fingers[idx].flags |= PressFlagPinchRotation;
642
643                         if( g_pGesture->num_pressed < 2 )
644                                 return;
645
646                         if( g_pGesture->num_pressed < num_pressed && state != GestureEnd )
647                         {
648 #ifdef __DETAIL_DEBUG__
649                                 ErrorF("[GroupPinchRotation][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
650 #endif//__DETAIL_DEBUG__
651                                 goto cleanup_pinchrotation;
652                         }
653
654                         if( base_distance == 0.0f && g_pGesture->num_pressed == 2 )
655                         {
656 #ifdef __DETAIL_DEBUG__
657                                 ErrorF("[GroupPinchRotation][First Time !!!] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
658 #endif//__DETAIL_DEBUG__
659
660                                 base_time = GetTimeInMillis();
661                                 pixman_region_init(&base_area);
662                                 pixman_region_union(&base_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]);
663
664                                 prev_distance = base_distance = AREA_DIAG_LEN(&base_area.extents);
665
666 #ifdef __DETAIL_DEBUG__
667                                 ErrorF("[GroupPinchRotation][P] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].px, g_pGesture->fingers[1].px,
668                                 g_pGesture->fingers[0].py, g_pGesture->fingers[1].py);
669 #endif//__DETAIL_DEBUG__
670
671                                 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);
672 #ifdef __DETAIL_DEBUG__
673                                 ErrorF("[GroupPinchRotation][P] base_angle=%.2f(deg=%.2f)\n", base_angle, rad2degree(base_angle));
674 #endif//__DETAIL_DEBUG__
675                                 event_type = GestureNotifyPinchRotation;
676                                 pinchrotation_event_timer = TimerSet(pinchrotation_event_timer, 0, PINCHROTATION_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
677                         }
678                         num_pressed = g_pGesture->num_pressed;
679
680 #ifdef __DETAIL_DEBUG__
681                         ErrorF("[GroupPinchRotation][P][num_pressed=%d] AREA_SIZE(base_area.extents)=%d\n", num_pressed, AREA_SIZE(&base_area.extents));
682                         ErrorF("[GroupPinchRotation][P][num_pressed=%d] base_distance=%.2f, base_angle=%.2f(deg=%.2f)\n", num_pressed, base_distance, base_angle, rad2degree(base_angle));
683 #endif//__DETAIL_DEBUG__
684                         break;
685
686                 case ET_Motion:
687                         if( !(g_pGesture->fingers[idx].flags & PressFlagPinchRotation) )
688                                 break;
689
690                         if( (num_pressed != g_pGesture->num_pressed) && (state != GestureEnd) )
691                         {
692 #ifdef __DETAIL_DEBUG__
693                                 ErrorF("[GroupPinchRotation][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
694 #endif//__DETAIL_DEBUG__
695                                 goto cleanup_pinchrotation;
696                         }
697
698                         if( num_pressed < 2 )
699                                 return;
700
701                         if( g_pGesture->fingers[0].mx && g_pGesture->fingers[0].my && g_pGesture->fingers[1].mx && g_pGesture->fingers[1].my )
702                         {
703                                 pixman_region_init(&cur_area);
704                                 pixman_region_union(&cur_area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[1]);
705
706                                 cur_distance = AREA_DIAG_LEN(&cur_area.extents);
707
708 #ifdef __DETAIL_DEBUG__
709                                 ErrorF("[GroupPinchRotation][M] x1=%d, x2=%d, y1=%d, y2=%d\n", g_pGesture->fingers[0].mx, g_pGesture->fingers[1].mx,
710                                 g_pGesture->fingers[0].my, g_pGesture->fingers[1].my);
711 #endif//__DETAIL_DEBUG__
712
713                                 cur_angle = get_angle(g_pGesture->fingers[0].mx, g_pGesture->fingers[0].my, g_pGesture->fingers[1].mx, g_pGesture->fingers[1].my);
714 #ifdef __DETAIL_DEBUG__
715                                 ErrorF("[GroupPinchRotation][M] cur_angle=%.2f(deg=%.2f)\n", cur_angle, rad2degree(cur_angle));
716 #endif//__DETAIL_DEBUG__
717
718                                 diff_distance = prev_distance - cur_distance;
719                                 diff_angle = prev_angle - cur_angle;
720
721                                 cx = AREA_CENTER_X(&cur_area.extents);
722                                 cy = AREA_CENTER_Y(&cur_area.extents);
723
724 #ifdef __DETAIL_DEBUG__
725                                 ErrorF("[GroupPinchRotation][M][state=%d] cx=%d, cy=%d\n", state, cx, cy);
726 #endif//__DETAIL_DEBUG__
727
728 #ifdef __DETAIL_DEBUG__
729                                 ErrorF("[GroupPinchRotation][M][num_pressed=%d] prev_distance=%.2f, cur_distance=%.2f, diff=%.2f\n", num_pressed, prev_distance, cur_distance, diff_distance);
730                                 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));
731 #endif//__DETAIL_DEBUG__
732
733                                 switch( state )
734                                 {
735                                         case GestureEnd:
736                                                 if( (ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD) || (ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD) )
737                                                 {
738 #ifdef __DETAIL_DEBUG__
739                                                         if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD )
740                                                                 ErrorF("[GroupPinchRotation][M] zoom changed !\n");
741
742                                                         if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD )
743                                                                 ErrorF("[GroupPinchRotation][M] angle changed !\n");
744 #endif//__DETAIL_DEBUG__
745
746                                                         TimerCancel(pinchrotation_event_timer);
747                                                         state = GestureBegin;
748                                                         goto gesture_begin_handle;
749                                                 }
750                                                 break;
751
752                                         case GestureBegin:
753 gesture_begin_handle:
754 #ifdef __DETAIL_DEBUG__
755                                                 ErrorF("[GroupPinchRotation] PINCHROTATION Begin !cx=%d, cy=%d, state=%d\n", cx, cy, state);
756 #endif//__DETAIL_DEBUG__
757                                                 if( GestureHasFingerEventMask(GestureNotifyPinchRotation, num_pressed) )
758                                                 {
759                                                         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);
760                                                         prev_distance = cur_distance;
761                                                         prev_angle = cur_angle;
762                                                         state = GestureUpdate;
763                                                         has_event_mask = 1;
764                                                 }
765                                                 else
766                                                 {
767                                                         has_event_mask = 0;
768                                                         goto cleanup_pinchrotation;
769                                                 }
770                                                 break;
771
772                                         case GestureUpdate:
773                                                 //if( ABS(diff_distance) < PINCHROTATION_DIST_THRESHOLD && ABS(diff_angle) < PINCHROTATION_ANGLE_THRESHOLD )
774                                                 //      break;
775
776 #ifdef __DETAIL_DEBUG__
777                                                 if( ABS(diff_distance) >= PINCHROTATION_DIST_THRESHOLD )
778                                                         ErrorF("[GroupPinchRotation][M] zoom changed !\n");
779
780                                                 if( ABS(diff_angle) >= PINCHROTATION_ANGLE_THRESHOLD )
781                                                         ErrorF("[GroupPinchRotation][M] angle changed !\n");
782 #endif//__DETAIL_DEBUG__
783
784 #ifdef __DETAIL_DEBUG__
785                                                 ErrorF("[GroupPinchRotation] PINCHROTATION Update ! cx=%d, cy=%d, state=%d\n", cx, cy, state);
786 #endif//__DETAIL_DEBUG__
787                                                 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);
788                                                 prev_distance = cur_distance;
789                                                 prev_angle = cur_angle;
790                                                 break;
791
792                                         case GestureDone:
793                                         default:
794                                                 break;
795                                 }
796                         }
797                         break;
798
799                 case ET_ButtonRelease:
800                         if( state != GestureEnd && num_pressed >= 2)
801                         {
802 #ifdef __DETAIL_DEBUG__
803                                 ErrorF("[GroupPinchRotation][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
804 #endif//__DETAIL_DEBUG__
805                                 goto cleanup_pinchrotation;
806                         }
807
808                         if( g_pGesture->num_pressed )
809                                 break;
810
811                         goto cleanup_pinchrotation;
812                         break;
813         }
814
815         return;
816
817 cleanup_pinchrotation:
818
819         if(  has_event_mask  && (state == GestureBegin || state == GestureUpdate) )
820         {
821                 state = GestureEnd;
822 #ifdef __DETAIL_DEBUG__
823                 ErrorF("[GroupPinchRotation] PINCHROTATION End ! cx=%d, cy=%d, state=%d\n", cx, cy, state);
824 #endif//__DETAIL_DEBUG__
825                 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);
826         }
827         else
828         {
829                 g_pGesture->recognized_gesture &= ~PinchRotationFilterMask;
830         }
831
832         g_pGesture->filter_mask |= PinchRotationFilterMask;
833
834         if( g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL )
835         {
836 #if 1//def __DETAIL_DEBUG__
837                 ErrorF("[GroupPinchRotation][cleanup] GestureFlushOrDrop() !\n");
838 #endif//__DETAIL_DEBUG__
839
840                 if( ERROR_INVALPTR == GestureFlushOrDrop() )
841                 {
842                         GestureControl(g_pGesture->this_device, DEVICE_OFF);
843                 }
844         }
845
846         prev_distance = base_distance = 0.0f;
847         prev_angle = base_angle = 0.0f;
848         has_event_mask = num_pressed = 0;
849         state = GestureEnd;
850         cx = cy = 0;
851         TimerCancel(pinchrotation_event_timer);
852         return;
853 }
854
855 void
856 GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
857 {
858         static int num_pressed = 0;
859         static int mbits = 0;
860         static int base_area_size = 0;
861         static Time base_time = 0;
862         static int base_x, base_y;
863         Time current_time;
864         Time duration;
865         int distx, disty;
866         int distance, direction;
867         int area_size;
868         int flicked = 0;
869
870         switch( type )
871         {
872                 case ET_ButtonPress:
873                         g_pGesture->fingers[idx].flags |= PressFlagFlick;
874
875                         if( g_pGesture->num_pressed < 2 )
876                                 return;
877
878                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
879                         {
880                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
881                                 base_x = g_pGesture->area.extents.x1;
882                                 base_y = g_pGesture->area.extents.y1;
883                                 base_time = GetTimeInMillis();
884                         }
885                         num_pressed = g_pGesture->num_pressed;
886
887 #ifdef __DETAIL_DEBUG__
888                         ErrorF("[GroupFlick][P]][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, base_area_size);
889 #endif//__DETAIL_DEBUG__
890                         break;
891
892                 case ET_Motion:
893                         if( !(g_pGesture->fingers[idx].flags & PressFlagFlick ) )
894                                 break;
895
896 #ifdef __DETAIL_DEBUG__
897                         if( num_pressed > g_pGesture->num_pressed )
898                         {
899                                 ErrorF("[GroupFlick][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
900                                 //goto cleanup_flick;
901                         }
902 #endif//__DETAIL_DEBUG__
903
904                         if( num_pressed < 2 )
905                                 return;
906
907                         mbits |= (1 << idx);
908                         if( mbits == (pow(2, num_pressed)-1) )
909                         {
910                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
911 #ifdef __DETAIL_DEBUG__
912                                 ErrorF("[M][num_pressed=%d] AREA_SIZE(area.extents)=%d\n", num_pressed, area_size);
913 #endif//__DETAIL_DEBUG__
914                                 if( ABS(base_area_size - area_size) >= FLICK_AREA_THRESHOLD )
915                                 {
916 #ifdef __DETAIL_DEBUG__
917                                         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);
918 #endif//__DETAIL_DEBUG__
919                                         goto cleanup_flick;
920                                 }
921
922                                 current_time = GetTimeInMillis();
923                                 if( (current_time - base_time) >= FLICK_AREA_TIMEOUT )
924                                 {
925 #ifdef __DETAIL_DEBUG__
926                                         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);
927 #endif//__DETAIL_DEBUG__
928                                         goto cleanup_flick;
929                                 }
930                                 mbits = 0;
931                         }
932                         break;
933
934                 case ET_ButtonRelease:
935                         if( g_pGesture->num_pressed )
936                                 break;
937
938                         duration = GetTimeInMillis() - base_time;
939                         distx = g_pGesture->area.extents.x1 - base_x;
940                         disty = g_pGesture->area.extents.y1 - base_y;
941
942 #ifdef __DETAIL_DEBUG__
943                         ErrorF("[GroupFlick] duration=%d, distx=%d, disty=%d\n", duration, distx, disty);
944 #endif//__DETAIL_DEBUG__
945
946                         if( duration <= 0 || duration >= FLICK_AREA_TIMEOUT )
947                                 goto cleanup_flick;
948
949                         if( ABS(distx) >= FLICK_MOVE_THRESHOLD )
950                         {
951                                 direction = (distx > 0) ? FLICK_EASTWARD : FLICK_WESTWARD;
952                                 distance = ABS(distx);
953                                 flicked++;
954                         }
955                         else if( ABS(disty) >= FLICK_MOVE_THRESHOLD )
956                         {
957                                 direction = (disty > 0) ? FLICK_SOUTHWARD : FLICK_NORTHWARD;
958                                 distance = ABS(disty);
959                                 flicked++;
960                         }
961
962                         if( !flicked )
963                                 goto cleanup_flick;
964
965                         if( GestureHasFingerEventMask(GestureNotifyFlick, num_pressed) )
966                                 GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
967                         goto cleanup_flick_recognized;
968                         break;
969         }
970
971         return;
972
973 cleanup_flick:
974
975         g_pGesture->recognized_gesture &= ~FlickFilterMask;
976
977 cleanup_flick_recognized:
978
979         g_pGesture->filter_mask |= FlickFilterMask;
980         num_pressed = 0;
981         base_area_size = 0;
982         base_time = 0;
983         mbits = 0;
984         return;
985 }
986
987 void
988 GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
989 {
990         static int num_pressed = 0;
991         static int mbits = 0;
992         static int base_area_size = 0;
993         static Time base_time = 0;
994         static pixman_box16_t base_box_ext;
995         static int base_cx;
996         static int base_cy;
997         static int prev_cx;
998         static int prev_cy;
999         static int cx = 0;
1000         static int cy = 0;
1001         int dx, dy;
1002         static Time prev_time = 0;
1003         Time current_time = 0;
1004         int distance = 0;
1005         int direction = 0;
1006         int area_size;
1007         static int time_checked = 0;
1008         static int state = GestureEnd;
1009
1010         static OsTimerPtr pan_event_timer = NULL;
1011         static int event_type = GestureNotifyPan;
1012
1013         if( timer_expired )
1014         {
1015                 if( !time_checked )
1016                 {
1017                         current_time = GetTimeInMillis();
1018                         if( (current_time - base_time) >= PAN_TIME_THRESHOLD )
1019                         {
1020                                 if( (!cx && !cy) || INBOX(&base_box_ext, cx, cy) )
1021                                 {
1022 #ifdef __DETAIL_DEBUG__
1023                                         ErrorF("[GroupPan][Timer] You must move farther than move threshold(=%d) within time threshold(=%d) !\n", PAN_MOVE_THRESHOLD*2, PAN_TIME_THRESHOLD);
1024 #endif//__DETAIL_DEBUG__
1025                                         goto cleanup_pan;
1026                                 }
1027                                 time_checked = 1;
1028                         }
1029                 }
1030                 return;
1031         }
1032
1033         switch( type )
1034         {
1035                 case ET_ButtonPress:
1036                         g_pGesture->fingers[idx].flags |= PressFlagPan;
1037
1038                         if( g_pGesture->num_pressed < 2 )
1039                                 return;
1040
1041                         if( !base_area_size || g_pGesture->num_pressed > num_pressed )
1042                         {
1043                                 if( state != GestureEnd )
1044                                 {
1045 #ifdef __DETAIL_DEBUG__
1046                                         ErrorF("[GroupPan][P][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1047 #endif//__DETAIL_DEBUG__
1048                                         goto cleanup_pan;
1049                                 }
1050                                 base_area_size = AREA_SIZE(&g_pGesture->area.extents);
1051                                 prev_cx = base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
1052                                 prev_cy = base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1053                                 prev_time = base_time = GetTimeInMillis();
1054                                 base_box_ext.x1 = base_cx-PAN_MOVE_THRESHOLD;
1055                                 base_box_ext.y1 = base_cy-PAN_MOVE_THRESHOLD;
1056                                 base_box_ext.x2 = base_cx+PAN_MOVE_THRESHOLD;
1057                                 base_box_ext.y2 = base_cy+PAN_MOVE_THRESHOLD;
1058                                 event_type = GestureNotifyPan;
1059                                 pan_event_timer = TimerSet(pan_event_timer, 0, PAN_TIME_THRESHOLD, GestureEventTimerHandler, (int *)&event_type);
1060                         }
1061                         num_pressed = g_pGesture->num_pressed;
1062
1063 #ifdef __DETAIL_DEBUG__
1064                         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);
1065 #endif//__DETAIL_DEBUG__
1066                         break;
1067
1068                 case ET_Motion:
1069                         if( !(g_pGesture->fingers[idx].flags & PressFlagPan ) )
1070                                 break;
1071
1072                         if( num_pressed != g_pGesture->num_pressed )
1073                         {
1074                                 if( state != GestureEnd )
1075                                 {
1076 #ifdef __DETAIL_DEBUG__
1077                                 ErrorF("[GroupPan][M][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1078 #endif//__DETAIL_DEBUG__
1079                                         goto cleanup_pan;
1080                                 }
1081                         }
1082
1083                         if( num_pressed < 2 )
1084                                 return;
1085
1086                         mbits |= (1 << idx);
1087                         if( mbits == (pow(2, num_pressed)-1) )
1088                         {
1089                                 area_size = AREA_SIZE(&g_pGesture->area.extents);
1090 #ifdef __DETAIL_DEBUG__
1091                                 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));
1092 #endif//__DETAIL_DEBUG__
1093
1094                                 if( (state != GestureUpdate) && (ABS(base_area_size - area_size) >= PAN_AREA_THRESHOLD) )
1095                                 {
1096 #ifdef __DETAIL_DEBUG__
1097                                         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);
1098 #endif//__DETAIL_DEBUG__
1099                                         goto cleanup_pan;
1100                                 }
1101
1102                                 cx = AREA_CENTER_X(&g_pGesture->area.extents);
1103                                 cy = AREA_CENTER_Y(&g_pGesture->area.extents);
1104 #ifdef __DETAIL_DEBUG__
1105                                 ErrorF("[GroupPan][M] cx=%d, prev_cx=%d, diff=%d\n", cx, prev_cx, ABS(cx-prev_cx));
1106                                 ErrorF("[GroupPan][M] cy=%d, prev_cy=%d, diff=%d\n", cy, prev_cy, ABS(cy-prev_cy));
1107 #endif//__DETAIL_DEBUG__
1108
1109                                 if( state <= GestureBegin )
1110                                 {
1111                                         if( !INBOX(&base_box_ext, cx, cy) )
1112                                         {
1113                                                 TimerCancel(pan_event_timer);
1114                                                 pan_event_timer = NULL;
1115                                                 
1116                                                 if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
1117                                                 {
1118                                                         GestureHandleGesture_Pan(num_pressed, prev_cx, prev_cy, direction, distance, current_time-prev_time, GestureBegin);
1119                                                         state = GestureUpdate;
1120                                                 }
1121                                                 else
1122                                                         goto cleanup_pan;
1123                                         }
1124                                 }
1125                                 else
1126                                 {
1127                                         dx = cx-prev_cx;
1128                                         dy = cy-prev_cy;
1129
1130                                         //if( ABS(dx) >= PAN_UPDATE_MOVE_THRESHOLD || ABS(dy) >= PAN_UPDATE_MOVE_THRESHOLD )
1131                                         {
1132 #ifdef __DETAIL_DEBUG__
1133                                                 ErrorF("[GroupPan] PAN Update !dx=%d, dy=%d, state=%d\n", dx, dy, state);
1134 #endif//__DETAIL_DEBUG__
1135
1136                                                 GestureHandleGesture_Pan(num_pressed, dx, dy, direction, distance, current_time-prev_time, GestureUpdate);
1137                                         }
1138                                 }
1139
1140                                 prev_cx = cx;
1141                                 prev_cy = cy;
1142                                 mbits = 0;
1143                         }
1144                         break;
1145
1146                 case ET_ButtonRelease:
1147                         if( state != GestureEnd && num_pressed >= 2)
1148                         {
1149 #ifdef __DETAIL_DEBUG__
1150                                 ErrorF("[GroupPan][R][cleanup] num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
1151 #endif//__DETAIL_DEBUG__
1152                                 goto cleanup_pan;
1153                         }
1154
1155                         if( g_pGesture->num_pressed )
1156                                 break;
1157
1158                         goto cleanup_pan;
1159                         break;
1160         }
1161
1162         return;
1163
1164 cleanup_pan:
1165
1166         if( state == GestureBegin || state == GestureUpdate )
1167         {
1168                 state = GestureEnd;
1169                 if( GestureHasFingerEventMask(GestureNotifyPan, num_pressed) )
1170                 {
1171                         GestureHandleGesture_Pan(num_pressed, (short int)(cx-prev_cx), (short int)(cy-prev_cy), direction, distance, GetTimeInMillis()-prev_time, GestureEnd);
1172                 }
1173         }
1174         else
1175         {
1176                 g_pGesture->recognized_gesture &= ~PanFilterMask;
1177         }
1178
1179         g_pGesture->filter_mask |= PanFilterMask;
1180         num_pressed = 0;
1181         base_area_size = 0;
1182         base_time = 0;
1183         mbits = 0;
1184         time_checked = 0;
1185         state = GestureEnd;
1186         cx = cy = 0;
1187         prev_time = 0;
1188         base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
1189         if( pan_event_timer )
1190         {
1191                 TimerCancel(pan_event_timer);
1192                 pan_event_timer = NULL;
1193         }
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, 5000, 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         return ERROR_NONE;
2404
2405 failed:
2406         GestureUninstallResourceStateHooks();
2407         GestureUnsetMaxNumberOfFingers();
2408
2409         return ERROR_ABNORMAL;
2410 }
2411
2412 static ErrorStatus
2413 GestureDisableEventHandler(void)
2414 {
2415         ErrorStatus err = ERROR_NONE;
2416
2417         mieqSetHandler(ET_ButtonPress, NULL);
2418         mieqSetHandler(ET_ButtonRelease, NULL);
2419         mieqSetHandler(ET_Motion, NULL);
2420         mieqSetHandler(ET_MTSync, NULL);
2421
2422         err = GestureFiniEQ();
2423
2424         if( ERROR_INVALPTR == err )
2425         {
2426                 ErrorF("[X11][GestureDisableEventHandler] EQ is invalid or was freed already !\n");
2427         }
2428
2429         GestureUninstallResourceStateHooks();
2430
2431         return err;
2432 }
2433
2434 static CARD32
2435 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
2436 {
2437         InputInfoPtr pInfo = (InputInfoPtr)arg;
2438         GestureDevicePtr pGesture = pInfo->private;
2439
2440         int idx = 0;
2441         DeviceIntPtr dev;
2442         for( dev = inputInfo.pointer ; dev; dev = dev->next )
2443         {
2444                 if(IsMaster(dev) && IsPointerDevice(dev))
2445                 {
2446                         pGesture->master_pointer = dev;
2447                         ErrorF("[X11][GestureTimerHandler][id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name);
2448                         continue;
2449                 }
2450
2451                 if(IsXTestDevice(dev, NULL) && IsPointerDevice(dev))
2452                 {
2453                         pGesture->xtest_pointer = dev;
2454                         ErrorF("[X11][GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name);
2455                         continue;
2456                 }
2457
2458                 if(IsPointerDevice(dev))
2459                 {
2460                         if( idx >= MAX_MT_DEVICES )
2461                         {
2462                                 ErrorF("[X11][GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n",
2463                                         MAX_MT_DEVICES);
2464                                 continue;
2465                         }
2466                         pGesture->mt_devices[idx] = dev;
2467                         ErrorF("[X11][GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
2468                         idx++;
2469                 }
2470         }
2471
2472         if( !pGesture->master_pointer || !pGesture->xtest_pointer )
2473         {
2474                 ErrorF("[X11][GestureTimerHandler] Failed to get info of master pointer or XTest pointer !\n");
2475                 pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2476                 pGesture->num_mt_devices = 0;
2477
2478                 return 0;
2479         }
2480
2481         pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2482         pGesture->num_mt_devices = idx;
2483
2484         if( !pGesture->num_mt_devices )
2485         {
2486                 ErrorF("[X11][GestureTimerHandler] Failed to mt device information !\n");
2487                 pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
2488                 pGesture->num_mt_devices = 0;
2489         pGesture->first_fingerid = -1;
2490                 return 0;
2491         }
2492
2493         pGesture->first_fingerid = pGesture->mt_devices[0]->id;
2494         memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
2495         pGesture->pRootWin = RootWindow(pGesture->master_pointer);
2496         g_pGesture->grabMask = g_pGesture->eventMask = 0;
2497         g_pGesture->pTempWin = NULL;
2498         g_pGesture->inc_num_pressed = 0;
2499
2500         if( ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ() )
2501         {
2502                 goto failed;
2503         }
2504
2505         mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
2506         mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
2507         mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
2508
2509         if( pGesture->is_active )
2510                 mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
2511
2512         return 0;
2513
2514 failed:
2515
2516         GestureUninstallResourceStateHooks();
2517         GestureUnsetMaxNumberOfFingers();
2518
2519         return 0;
2520 }
2521
2522 BOOL
2523 IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
2524 {
2525         if (IsMaster(dev))
2526                 return FALSE;
2527
2528         if (master)
2529                 return (dev->xtest_master_id == master->id);
2530
2531         return (dev->xtest_master_id != 0);
2532 }
2533
2534 void
2535 GestureSetDisable(InputInfoPtr pInfo, int enable)
2536 {
2537         if( !enable )
2538         {
2539                 g_pGesture->ehtype = PROPAGATE_EVENTS;
2540                 mieqSetHandler(ET_MTSync, NULL);
2541                 g_pGesture->is_active = 0;
2542                 ErrorF("[X11][GestureSetDisable] Disabled !\n");
2543         }
2544         else
2545         {
2546                 g_pGesture->ehtype = KEEP_EVENTS;
2547                 mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
2548                 g_pGesture->is_active = 1;
2549                 ErrorF("[X11][GestureSetDisable] Enabled !\n");
2550         }
2551 }
2552
2553 ErrorStatus
2554 GestureRegionsInit(void)
2555 {
2556         int i;
2557
2558         if( !g_pGesture )
2559                 return ERROR_INVALPTR;
2560
2561         pixman_region_init(&g_pGesture->area);
2562
2563         for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
2564         {
2565                 pixman_region_init_rect (&g_pGesture->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T);
2566         }
2567
2568         return ERROR_NONE;
2569 }
2570
2571 ErrorStatus
2572 GestureRegionsReinit(void)
2573 {
2574         if( !g_pGesture )
2575         {
2576                 ErrorF("[X11][GestureRegionsReinit] Invalid pointer access !\n");
2577                 return ERROR_INVALPTR;
2578         }
2579
2580         pixman_region_init(&g_pGesture->area);
2581
2582         return ERROR_NONE;
2583 }
2584
2585 ErrorStatus
2586 GestureInitEQ(void)
2587 {
2588         int i;
2589         IEventPtr tmpEQ;
2590
2591         tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec));
2592
2593         if( !tmpEQ )
2594         {
2595                 ErrorF("[X11][GestureInitEQ] Failed to allocate memory for EQ !\n");
2596                 return ERROR_ALLOCFAIL;
2597         }
2598
2599         for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
2600         {
2601                 tmpEQ[i].event = (InternalEvent *)malloc(sizeof(InternalEvent));
2602                 if( !tmpEQ[i].event )
2603                 {
2604                         ErrorF("[X11][GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n");
2605                         i--;
2606                         while(i >= 0 && tmpEQ[i].event)
2607                         {
2608                                 free(tmpEQ[i].event);
2609                                 tmpEQ[i].event = NULL;
2610                         }
2611                         free (tmpEQ);
2612                         tmpEQ = NULL;
2613                         return ERROR_ALLOCFAIL;
2614                 }
2615         }
2616
2617         g_pGesture->EQ = tmpEQ;
2618         g_pGesture->headEQ = g_pGesture->tailEQ = 0;
2619
2620         return ERROR_NONE;
2621 }
2622
2623 ErrorStatus
2624 GestureFiniEQ(void)
2625 {
2626         int i;
2627
2628         if( !g_pGesture || !g_pGesture->EQ )
2629                 return ERROR_INVALPTR;
2630
2631         for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
2632         {
2633                 if( g_pGesture->EQ[i].event )
2634                 {
2635                         free(g_pGesture->EQ[i].event);
2636                         g_pGesture->EQ[i].event = NULL;
2637                 }
2638         }
2639
2640         free(g_pGesture->EQ);
2641         g_pGesture->EQ = NULL;
2642
2643         return ERROR_NONE;
2644 }
2645
2646 ErrorStatus
2647 GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
2648 {
2649         int tail;
2650
2651         if( !g_pGesture || !g_pGesture->EQ )
2652         {
2653                 ErrorF("[X11][GestureEnqueueEvent] Invalid pointer access !\n");
2654                 return ERROR_INVALPTR;
2655         }
2656
2657         tail = g_pGesture->tailEQ;
2658
2659         if( tail >= GESTURE_EQ_SIZE )
2660         {
2661                 ErrorF("[X11][GestureEnqueueEvent] Gesture EQ is full !\n");
2662                 printk("[X11][GestureEnqueueEvent] Gesture EQ is full...Force Gesture Flush !\n");
2663                 GestureEventsFlush();
2664                 return ERROR_EQFULL;
2665         }
2666
2667 #ifdef __DETAIL_DEBUG__
2668         switch( ev->any.type )
2669         {
2670                 case ET_ButtonPress:
2671                         ErrorF("[X11][GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id);
2672                         break;
2673
2674                 case ET_ButtonRelease:
2675                         ErrorF("[X11][GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id);
2676                         break;
2677
2678                 case ET_Motion:
2679                         ErrorF("[X11][GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id);
2680                         break;
2681         }
2682 #endif//__DETAIL_DEBUG__
2683
2684         g_pGesture->EQ[tail].device = device;
2685         g_pGesture->EQ[tail].screen_num = screen_num;
2686         memcpy(g_pGesture->EQ[tail].event, ev, sizeof(InternalEvent));//need to be optimized
2687         g_pGesture->tailEQ++;
2688
2689         return ERROR_NONE;
2690 }
2691
2692 ErrorStatus
2693 GestureEventsFlush(void)
2694 {
2695         int i;
2696         DeviceIntPtr device;
2697
2698         if( !g_pGesture->EQ )
2699         {
2700                 ErrorF("[X11][GestureEventsFlush] Invalid pointer access !\n");
2701                 return ERROR_INVALPTR;
2702         }
2703
2704 #ifdef __DETAIL_DEBUG__
2705         ErrorF("[X11][GestureEventsFlush]\n");
2706 #endif//__DETAIL_DEBUG__
2707
2708         for( i = g_pGesture->headEQ ; i < g_pGesture->tailEQ ; i++)
2709         {
2710                 device = g_pGesture->EQ[i].device;
2711                 device->public.processInputProc(g_pGesture->EQ[i].event, device);
2712         }
2713
2714         for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
2715                 g_pGesture->event_sum[i] = 0;
2716
2717         g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
2718
2719         return ERROR_NONE;
2720 }
2721
2722 void
2723 GestureEventsDrop(void)
2724 {
2725         g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
2726 }
2727
2728 #ifdef HAVE_PROPERTIES
2729 static void
2730 GestureInitProperty(DeviceIntPtr dev)
2731 {
2732         int rc;
2733
2734         prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
2735         rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
2736
2737         if (rc != Success)
2738                 return;
2739
2740         XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
2741 }
2742
2743 static int
2744 GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
2745                  BOOL checkonly)
2746 {
2747         InputInfoPtr pInfo  = dev->public.devicePrivate;
2748
2749         if( prop_gesture_recognizer_onoff == atom )
2750         {
2751                 int data;
2752                 if( val->format != 32 || val->type != XA_INTEGER || val->size != 1 )
2753                         return BadMatch;
2754
2755                 if( !checkonly )
2756                 {
2757                         data = *((int *)val->data);
2758                         GestureSetDisable(pInfo, data);
2759                 }
2760         }
2761
2762         return Success;
2763 }
2764 #endif//HAVE_PROPERTIES
2765
2766 static int
2767 GestureInit(DeviceIntPtr device)
2768 {
2769         InputInfoPtr pInfo;
2770         pInfo = device->public.devicePrivate;
2771
2772 #ifdef HAVE_PROPERTIES
2773         GestureInitProperty(device);
2774         XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
2775 #endif
2776
2777         return Success;
2778 }
2779
2780 static void
2781 GestureFini(DeviceIntPtr device)
2782 {
2783         XIRegisterPropertyHandler(device, NULL, NULL, NULL);
2784 }
2785
2786 static pointer
2787 GesturePlug(pointer module, pointer options, int *errmaj, int *errmin)
2788 {
2789         xf86AddInputDriver(&GESTURE, module, 0);
2790         return module;
2791 }
2792
2793 static void
2794 GestureUnplug(pointer p)
2795 {
2796 }
2797
2798 static InputInfoPtr
2799 GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2800 {
2801     int rc = BadAlloc;
2802     GestureDevicePtr    pGesture;
2803
2804     pGesture = calloc(1, sizeof(GestureDeviceRec));
2805
2806     if (!pGesture) {
2807         pInfo->private = NULL;
2808         //xf86DeleteInput(pInfo, 0);
2809         goto error;
2810     }
2811
2812     g_pGesture = pGesture;
2813     pInfo->private = pGesture;
2814     pInfo->flags = 0;
2815     pInfo->read_input = GestureReadInput; /* new data avl */
2816     pInfo->switch_mode = NULL; /* toggle absolute/relative mode */
2817     pInfo->device_control = GestureControl; /* enable/disable dev */
2818     /* process driver specific options */
2819     pGesture->device = xf86SetStrOption(pInfo->options, "Device", "/dev/null");
2820     pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0);
2821     pGesture->gestureWin = None;
2822
2823     xf86Msg(X_INFO, "%s: Using device %s.\n", pInfo->name, pGesture->device);
2824
2825     /* process generic options */
2826     xf86CollectInputOptions(pInfo, NULL);
2827     xf86ProcessCommonOptions(pInfo, pInfo->options);
2828
2829     pInfo->fd = -1;
2830
2831     return Success;
2832
2833 error:
2834     if (pInfo->fd >= 0)
2835         close(pInfo->fd);
2836     return rc;
2837 }
2838
2839 static void
2840 GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
2841 {
2842         GestureDevicePtr pGesture = pInfo->private;
2843
2844         g_pGesture = pGesture = NULL;
2845         pInfo->private = NULL;
2846
2847         xf86DeleteInput(pInfo, 0);
2848 }
2849
2850 static int
2851 GestureControl(DeviceIntPtr device, int what)
2852 {
2853     InputInfoPtr  pInfo = device->public.devicePrivate;
2854     GestureDevicePtr pGesture = pInfo->private;
2855
2856     switch(what)
2857     {
2858         case DEVICE_INIT:
2859              GestureInit(device);
2860             break;
2861
2862         /* Switch device on.  Establish socket, start event delivery.  */
2863         case DEVICE_ON:
2864             xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
2865
2866             if (device->public.on)
2867                     break;
2868
2869             device->public.on = TRUE;
2870              pGesture->this_device = device;
2871              pGesture->num_mt_devices = 0;
2872              if( ERROR_ABNORMAL == GestureEnableEventHandler(pInfo) )
2873                 goto device_off;
2874             break;
2875
2876        case DEVICE_OFF:
2877 device_off:
2878              GestureDisableEventHandler();
2879              GestureFini(device);
2880              pGesture->this_device = NULL;
2881              xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
2882
2883             if (!device->public.on)
2884                 break;
2885
2886             pInfo->fd = -1;
2887             device->public.on = FALSE;
2888             break;
2889
2890       case DEVICE_CLOSE:
2891             /* free what we have to free */
2892             break;
2893     }
2894     return Success;
2895 }
2896
2897 static void
2898 GestureReadInput(InputInfoPtr pInfo)
2899 {
2900 }
2901