tizen 2.3 release tizen_2.3 submit/tizen_2.3/20150202.052948 tizen_2.3_release
authorjk7744.park <jk7744.park@samsung.com>
Sun, 1 Feb 2015 04:00:28 +0000 (13:00 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sun, 1 Feb 2015 04:00:28 +0000 (13:00 +0900)
mobile/src/gesture.c
mobile/src/gesture.h
packaging/xorg-x11-drv-gesture.spec
wearable/configure.ac
wearable/src/gesture.c
wearable/src/gesture.h

index 1dddb27..af7fd87 100755 (executable)
@@ -58,6 +58,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #endif
 
+#include <X11/Xatom.h>
+
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
@@ -75,9 +77,34 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define MGEST  XDBG_M('G','E','S','T')
 
+static const void(*PalmRecognize)(int, InternalEvent*, DeviceIntPtr);
+
+#define _GESTUREPALMRECOGNIZE_(function, type, ev, device)     \
+       if(function)    \
+       {       \
+               XDBG_WARNING(MGEST, "[_GESTUREPALMRECOGNIZE_] Enable GesturePalmRecognize. type=%d\n", type);   \
+               function(type, ev, device);     \
+       }       \
+       else    \
+       {       \
+               XDBG_WARNING(MGEST, "[_GESTUREPALMRECOGNIZE_] Disable GesturePalmRecognize \n");        \
+       }       \
+
 static void printk(const char* fmt, ...) __attribute__((format(printf, 1, 0)));
 extern char *strcasestr(const char *s, const char *find);
 extern ScreenPtr miPointerCurrentScreen(void);
+extern EventQueuePtr mieqGetEventQueuePtr();
+
+static Bool GestureIsEventInMIEQ(int finger_index, enum EventType type);
+static int GestureGetFingerIndexFromDevice(DeviceIntPtr device);
+static int GestureGetDeviceIdFromFingerIndex(int finger_index);
+static Bool GestureIsPalmEventInMIEQ(void);
+static Bool GestureIsPalmEvent(InternalEvent *event);
+static int GestureGetMTToolValuator(InternalEvent *ev, DeviceIntPtr device);
+static void GestureRegisterTouchInfo(InternalEvent *ev, DeviceIntPtr device);
+static void GestureSetToolData(InternalEvent *ev, double val_tool);
+static void GestureCleanupTouch(int screen_num, InternalEvent *ev, DeviceIntPtr device);
+static void GestureChangeEventToFirstFingerEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
 
 //Basic functions
 static int GesturePreInit(InputDriverPtr  drv, InputInfoPtr pInfo, int flags);
@@ -111,17 +138,20 @@ static Bool GestureHasFingersEvents(int eventType);
 //Enqueued event handlers and enabler/disabler
 static ErrorStatus GestureEnableEventHandler(InputInfoPtr pInfo);
 static ErrorStatus GestureDisableEventHandler(void);
-static CARD32 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
 static CARD32 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
-static CARD32 GesturePalmEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg);
 void GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
 void GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
 void GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
 void GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
 void GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
+void GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device);
+
+static void GestureRegisterDeviceInfo(DeviceIntPtr device);
 
 //Gesture recognizer helper
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21
 static Bool PointInBorderSize(WindowPtr pWin, int x, int y);
+#endif
 static WindowPtr GestureWindowOnXY(int x, int y);
 Bool GestureHasFingerEventMask(int eventType, int num_finger);
 #ifdef _F_SUPPORT_BEZEL_FLICK_
@@ -151,7 +181,6 @@ ErrorStatus GestureFlushOrDrop(void);
 
 static int GesturePalmGetHorizIndexWithX(int x, int type);
 static int GesturePalmGetVertiIndexWithY(int y, int type);
-static void GesturePalmRecognize_Hold(int type, int idx, int timer_expired);
 static void GesturePalmRecognize_FlickHorizen(int type, int idx);
 static void GesturePalmRecognize_FlickVertical(int type,int idx);
 static int GesturePalmGetScreenInfo();
@@ -173,6 +202,13 @@ static int GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr va
 #endif
 
 static Atom prop_gesture_recognizer_onoff = None;
+static Atom prop_gesture_palm_rejection_mode = None;
+
+#ifdef SUPPORT_ANR_WITH_INPUT_EVENT
+static Atom prop_anr_in_input_event = None;
+static Atom prop_anr_event_window = None;
+static Window prop_anr_event_window_xid = None;
+#endif
 
 GestureDevicePtr g_pGesture = NULL;
 _X_EXPORT InputDriverRec GESTURE = {
@@ -228,15 +264,54 @@ printk(const char* fmt, ...)
        va_end(argptr);
 }
 
+#ifdef SUPPORT_ANR_WITH_INPUT_EVENT
+static WindowPtr
+_GestureFindANRWindow(DeviceIntPtr device)
+{
+    WindowPtr root=NULL;
+    WindowPtr anr_window=NULL;
+    Window anr_xid=0;
+    PropertyPtr pProp;
+    int rc=0;
+
+    root = RootWindow(device);
+
+    if( prop_anr_event_window == None )
+        prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE);
+
+    rc = dixLookupProperty (&pProp, root, prop_anr_event_window, serverClient, DixReadAccess);
+    if (rc == Success && pProp->data){
+        anr_xid = *(int*)pProp->data;
+    }
+
+    if( anr_xid != 0 )
+    {
+        rc = dixLookupWindow(&anr_window, anr_xid, serverClient, DixSetPropAccess);
+        if( rc == BadWindow )
+        {
+            XDBG_ERROR(MGEST, "Can't find ANR window !!\n");
+            anr_window = NULL;
+        }
+        prop_anr_event_window_xid = anr_xid;
+    }
+
+    XDBG_DEBUG(MGEST, "ANR Window is %#x. Ptr is %#x\n", anr_xid, anr_window);
+    return anr_window;
+}
+#endif
+
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21
 static Bool
 PointInBorderSize(WindowPtr pWin, int x, int y)
 {
     BoxRec box;
-    if( pixman_region_contains_point (&pWin->borderSize, x, y, &box) )
-       return TRUE;
-
+    if (pixman_region_contains_point (&pWin->borderSize, x, y, &box))
+    {
+        return TRUE;
+    }
     return FALSE;
 }
+#endif
 
 static WindowPtr
 GestureWindowOnXY(int x, int y)
@@ -424,14 +499,13 @@ GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int
                if(direction == FLICK_NORTHWARD || direction == FLICK_SOUTHWARD)
                        g_pGesture->recognized_palm |= PalmFlickVertiFilterMask;
        }
-
 #ifdef _F_SUPPORT_BEZEL_FLICK_
        else if(num_of_fingers == 1)
        {
                g_pGesture->bezel_recognized_mask |= BezelFlickFilterMask;
        }
-       else
 #endif
+       else
                g_pGesture->recognized_gesture |= FlickFilterMask;
 
        memset(&fev, 0, sizeof(xGestureNotifyFlickEvent));
@@ -583,7 +657,7 @@ void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, i
 #endif//__DETAIL_DEBUG__
 
        if(num_fingers == 0)
-               g_pGesture->recognized_palm |= PalmHoldFilterMask;
+               g_pGesture->hold_detected = TRUE;
        else
                g_pGesture->recognized_gesture |= HoldFilterMask;
        memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
@@ -917,7 +991,7 @@ GestureRecognize_GroupPinchRotation(int type, InternalEvent *ev, DeviceIntPtr de
        static Time base_time = 0;
        Time current_time;
 
-       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1
+       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected
 #ifdef _F_SUPPORT_BEZEL_FLICK_
                        || g_pGesture->bezel_recognized_mask)
 #else
@@ -1184,7 +1258,7 @@ GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, in
        int area_size;
        int flicked = 0;
 
-       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1
+       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected
 #ifdef _F_SUPPORT_BEZEL_FLICK_
                || g_pGesture->bezel_recognized_mask)
 #else
@@ -1334,7 +1408,7 @@ GestureRecognize_GroupPan(int type, InternalEvent *ev, DeviceIntPtr device, int
        static OsTimerPtr pan_event_timer = NULL;
        static int event_type = GestureNotifyPan;
 
-       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1
+       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected
 #ifdef _F_SUPPORT_BEZEL_FLICK_
                || g_pGesture->bezel_recognized_mask)
 #else
@@ -1545,7 +1619,6 @@ GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int
        static int base_area_size = 0;
 
        static Time base_time = 0;
-       Time current_time;
 
        int cx, cy;
        int area_size;
@@ -1557,13 +1630,12 @@ GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int
        static pixman_box16_t base_box_ext;
 
        static int tap_repeat = 0;
-       static int prev_tap_repeat = 0;
        static int prev_num_pressed = 0;
 
        static OsTimerPtr tap_event_timer = NULL;
        static int event_type = GestureNotifyTap;
 
-       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1
+       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected
 #ifdef _F_SUPPORT_BEZEL_FLICK_
                || g_pGesture->bezel_recognized_mask)
 #else
@@ -1583,7 +1655,7 @@ GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int
                                if( num_pressed )
                                {
 #ifdef __DETAIL_DEBUG__
-                                       XDBG_DEBUG(MGEST, "[Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", tap_repeat, num_pressed, tap_repeat);
+                                       XDBG_DEBUG(MGEST, "[Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", num_pressed, tap_repeat);
 #endif//__DETAIL_DEBUG__
                                        state = GestureEnd;
                                        goto cleanup_tap;
@@ -1601,7 +1673,7 @@ GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int
                                }
 
 #ifdef __DETAIL_DEBUG__
-                               XDBG_DEBUG(MGEST, "[Timer][state=2]  tap_repeat=%d, prev_tap_repeat=%d, num_pressed=%d\n", tap_repeat, prev_tap_repeat, num_pressed);
+                               XDBG_DEBUG(MGEST, "[Timer][state=2]  tap_repeat=%d, num_pressed=%d\n", tap_repeat, num_pressed);
 #endif//__DETAIL_DEBUG__
                                if( GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed) )
                                {
@@ -1647,10 +1719,8 @@ GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int
 
                        num_pressed = g_pGesture->num_pressed;
 
-                       current_time = GetTimeInMillis();
-
 #ifdef __DETAIL_DEBUG__
-                       XDBG_DEBUG(MGEST, "[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);
+                       XDBG_DEBUG(MGEST, "[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, GetTimeInMillis());
 #endif//__DETAIL_DEBUG__
                        break;
 
@@ -1715,12 +1785,11 @@ GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int
                                prev_num_pressed = num_pressed;
                        }
 
-                       prev_tap_repeat = tap_repeat;
                        tap_repeat++;
                        g_pGesture->tap_repeated = tap_repeat;
 
 #ifdef __DETAIL_DEBUG__
-                       XDBG_DEBUG(MGEST, "[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);
+                       XDBG_DEBUG(MGEST, "[R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed);
 #endif//__DETAIL_DEBUG__
 
                        if( num_pressed != prev_num_pressed || !GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
@@ -1812,7 +1881,7 @@ GestureRecognize_GroupTapNHold(int type, InternalEvent *ev, DeviceIntPtr device,
        Time interval = 0;
        Time holdtime = 0;
 
-       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1
+       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected
 #ifdef _F_SUPPORT_BEZEL_FLICK_
                || g_pGesture->bezel_recognized_mask)
 #else
@@ -2081,7 +2150,7 @@ void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device
        static OsTimerPtr hold_event_timer = NULL;
        static int event_type = GestureNotifyHold;
 
-       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1
+       if(g_pGesture->recognized_palm || g_pGesture->enqueue_fulled == 1 || g_pGesture->hold_detected
 #ifdef _F_SUPPORT_BEZEL_FLICK_
                || g_pGesture->bezel_recognized_mask)
 #else
@@ -2390,8 +2459,6 @@ nonempty_eventmask:
 #endif
 #endif//__DETAIL_DEBUG__
        g_pGesture->palm_filter_mask = 0;
-       if(mask & HoldFilterMask)
-               g_pGesture->palm_filter_mask |= PalmHoldFilterMask;
        if(mask & FlickFilterMask)
        {
                g_pGesture->palm_filter_mask |= PalmFlickHorizFilterMask;
@@ -2506,30 +2573,6 @@ GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
        return 0;
 }
 
-static CARD32
-GesturePalmEventTimerHandler(OsTimerPtr timer,CARD32 time,pointer arg)
-{
-       int event_type = *(int *)arg;
-
-       switch( event_type )
-       {
-               case GestureNotifyHold:
-#ifdef __PALM_DETAIL_LOG__
-                       XDBG_DEBUG(MGEST, "GestureNotifyHold (event_type = %d)\n", event_type);
-#endif//__PALM_DETAIL_LOG__
-                       GesturePalmRecognize_Hold(event_type, 0, 1);
-                       break;
-
-               default:
-#ifdef __PALM_DETAIL_LOG__
-                       XDBG_DEBUG(MGEST, "unknown event_type (=%d)\n", event_type);
-#endif//__PALM_DETAIL_LOG__
-                       break;
-       }
-
-       return 0;
-}
-
 #ifdef _F_SUPPORT_BEZEL_FLICK_
 static CARD32
 GestureBezelSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
@@ -2583,17 +2626,6 @@ GesturePalmSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
        return 0;
 }
 
-static CARD32
-GesturePalmHoldRapidHandler(OsTimerPtr timer, CARD32 time, pointer arg)
-{
-#ifdef __PALM_DETAIL_LOG__
-       XDBG_DEBUG(MGEST, "[%d] rapid timer in.....\n", __LINE__);
-#endif
-       GesturePalmRecognize_Hold(0, 0, 0);
-       return 0;
-}
-
-
 static int
 GesturePalmGetHorizIndexWithX(int x, int type)
 {
@@ -2668,7 +2700,7 @@ GesturePalmGetVertiIndexWithY(int y, int type)
        for(i = 0 ; i < PALM_VERTI_ARRAY_COUNT ; i++)
        {
 #ifdef __PALM_DETAIL_LOG__
-               XDBG_DEBUG(MGEST, "pPalmMisc->horiz_coord[%d]=%d, x=%d\n", i, pPalmMisc->horiz_coord[i], y);
+               XDBG_DEBUG(MGEST, "pPalmMisc->verti_coord[%d]=%d, x=%d\n", i, pPalmMisc->verti_coord[i], y);
 #endif//__PALM_DETAIL_LOG__
                if(y <= pPalmMisc->verti_coord[i])
                {
@@ -2735,54 +2767,61 @@ index_check:
 }
 
 static void
-GesturePalmRecognize_Hold(int type, int idx, int timer_expired)
+GesturePalmRecognize_FlickHorizen(int type, int idx)
 {
-       static int is_holding = 1;
+       static int curTouched = 0;
        static int num_pressed = 0;
-       static Time base_time = 0;
-       static int cx, cy;
        static int base_width_size = 0;
+       static Time base_time = 0;
+       static int base_x;
+       static pixman_box16_t base_box_ext;
+#ifdef __PALM_GESTURE_LOG__
+       int i;
+#endif
 
-       static int state = GestureEnd;
-       static int false_base_width_size_count = 0;
-       static int max_num_finger = 0;
+       int line_idx;
+       static int prev_line_idx;
+       static int horiz_line[PALM_HORIZ_ARRAY_COUNT];
 
-       static OsTimerPtr palm_hold_event_timer = NULL;
-       static int event_type = GestureNotifyHold;
-       PalmStatusPtr pPalm = &g_pGesture->palm;
-       static int hold_occured = 0;
-       static int rapid_hold = 0;
-       static OsTimerPtr palm_hold_rapid_timer = NULL;
+       Time duration;
+       int distx=0, disty=0;
+       int distance, direction;
+
+       int width_size;
+       static int is_flicking = 1;
+       //static int is_surface = 0;
+       static int pass_count = 0;
+       static int base_cx=0, base_cy=0;
+       static int release_flag = 0;
 
+       PalmStatusPtr pPalm = &g_pGesture->palm;
 #ifdef __PALM_GESTURE_LOG__
        XDBG_DEBUG(MGEST, "recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask);
-       XDBG_DEBUG(MGEST, "num_pressed: %d, cur_touched: %d, palm_flag: %d, is_holding: %d hold_occured %.f\n", num_pressed, pPalm->cur_touched, pPalm->palmflag, is_holding, hold_occured);
-       XDBG_DEBUG(MGEST, "pPalm->biggest_wmajor: %.f, pPalm->bigger_wmajor: %.f, pPalm->biggest_tmajor: %.f\n", pPalm->biggest_wmajor, pPalm->bigger_wmajor, pPalm->biggest_tmajor);
+       XDBG_DEBUG(MGEST, "num_pressed: %d, cur_touched: %d palmflag: %d\n", num_pressed, pPalm->cur_touched, pPalm->palmflag);
+       XDBG_DEBUG(MGEST, "idx: %d, cx: %d, cy: %d, type: %d, touch_status: %d\n", idx, pPalm->cx, pPalm->cy, type, pPalm->pti[idx].touch_status);
 #endif
+
+       if( idx < 0 )
+               goto flick_failed;
+
        if(g_pGesture->enqueue_fulled == 1)
        {
 #ifdef __PALM_GESTURE_LOG__
-               XDBG_DEBUG(MGEST, "EQ Event is full.... palm recognize drop..\n");
-#endif
-               goto hold_failed;
-       }
-       if(rapid_hold && type==0 && idx==0 && timer_expired == 0)
-       {
-#ifdef __PALM_GESTURE_LOG__
-               XDBG_DEBUG(MGEST, "rapid timer is released .....\n");
+                       XDBG_DEBUG(MGEST, "EQ Event is full.... palm recognize drop..\n");
 #endif
-               rapid_hold = 0;
-               goto release_hold;
+                       goto flick_failed;
        }
-       if(pPalm->single_timer_expired && (pPalm->biggest_tmajor < PALM_HOLD_FINGER_MIN_TOUCH_MAJOR) && (max_num_finger < (PALM_HOLD_MIN_FINGER - 1)))
+
+       if(pPalm->single_timer_expired)
        {
 #ifdef __PALM_GESTURE_LOG__
-               XDBG_DEBUG(MGEST, "No Hold single finger...expired, biggest_tmajor: %.f\n", pPalm->biggest_tmajor);
+               XDBG_DEBUG(MGEST, "No flick single finger...expired\n");
 #endif
-               goto hold_failed;
+               goto flick_failed;
        }
 
-       if(g_pGesture->recognized_gesture || (g_pGesture->recognized_palm && !(g_pGesture->recognized_palm & PalmHoldFilterMask)) || (g_pGesture->palm_filter_mask & PalmHoldFilterMask)
+       if(g_pGesture->recognized_gesture || g_pGesture->hold_detected ||
+               (g_pGesture->recognized_palm && !(g_pGesture->recognized_palm & PalmFlickHorizFilterMask)) || (g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask)
 #ifdef _F_SUPPORT_BEZEL_FLICK_
                || g_pGesture->bezel_recognized_mask)
 #else
@@ -2794,452 +2833,130 @@ GesturePalmRecognize_Hold(int type, int idx, int timer_expired)
                XDBG_DEBUG(MGEST, "type(%d) recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", type, g_pGesture->recognized_palm, g_pGesture->palm_filter_mask);
                XDBG_DEBUG(MGEST, "type(%d) recognized_gesture= 0x%x, filter_mask= 0x%x\n", type, g_pGesture->recognized_gesture, g_pGesture->filter_mask);
 #endif
-               goto hold_failed;
+               goto flick_failed;
        }
-       if( timer_expired && !pPalm->palmflag)
+       switch( type )
        {
+               case ET_ButtonPress:
+                       if(!is_flicking)
+                               break;
+                       if(!base_width_size || pPalm->cur_touched > curTouched)
+                       {
+                               if(!base_time)
+                               {
+                                       base_time = GetTimeInMillis();
+                                       base_x = AREA_CENTER_X(&pPalm->area.extents);
+                                       line_idx = GesturePalmGetHorizIndexWithX(base_x, type);
 #ifdef __PALM_GESTURE_LOG__
-               XDBG_DEBUG(MGEST, "No Palm is comming \n");
-#endif
-               if( (pPalm->biggest_wmajor > PALM_HOLD_FINGER_MIN_WIDTH_MAJOR) && (max_num_finger >= PALM_HOLD_MIN_FINGER) )
-               {
-#ifdef __PALM_GESTURE_LOG__
-                       XDBG_DEBUG(MGEST, "It seemed palm hold (biggest_wmajor: %.f max_num_finger: %d) \n", pPalm->biggest_wmajor, max_num_finger);
+                                       XDBG_DEBUG(MGEST, "[P] cx: %d, cy: %d, x1: %d, x2: %d, y1: %d, y2: %d, line_idx: %d\n", pPalm->cx, pPalm->cy, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2, line_idx);
 #endif
-                       pPalm->palmflag = 1;
-               }
-               else
-               {
+                                       if(line_idx < 0)
+                                       {
 #ifdef __PALM_GESTURE_LOG__
-                       XDBG_DEBUG(MGEST, "No Palm and No Hold \n");
+                                               XDBG_DEBUG(MGEST, "[P] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x, line_idx);
 #endif
-                       goto hold_failed;
-               }
-       }
+                                               goto flick_failed;
+                                       }
 
-       if( timer_expired && pPalm->palmflag)
-       {
+                                       horiz_line[line_idx]++;
+                                       pass_count++;
+                                       prev_line_idx = line_idx;
+                                       release_flag = 0;
 #ifdef __PALM_GESTURE_LOG__
-               XDBG_DEBUG(MGEST, "state: %d\n", state);
+                                       XDBG_DEBUG(MGEST, "[P] Base_width=%d, base_x=%d, line_idx=%d\n", base_width_size, base_x, line_idx);
 #endif
-               if(max_num_finger < PALM_HOLD_MIN_FINGER)
-               {
+                               }
+
+                               base_width_size = AREA_WIDTH(&pPalm->area.extents);
+                               if(base_width_size > PALM_FLICK_HORIZ_MAX_BASE_WIDTH)
+                               {
 #ifdef __PALM_GESTURE_LOG__
-                       XDBG_DEBUG(MGEST, "palm hold false : max_num_finger(%d) < %d\n", max_num_finger, PALM_HOLD_MIN_FINGER);
+                                       XDBG_DEBUG(MGEST, "[P] No flickBase_width=%d > %d: MAX_WIDTH\n", base_width_size, PALM_FLICK_HORIZ_MAX_BASE_WIDTH);
 #endif
-                       goto hold_failed;
-               }
-               if( state <= GestureBegin )
-                       state++;
-
-               switch( state )
-               {
-                       case GestureBegin:
+                                       goto flick_failed;
+                               }
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "HOLD Begin !(state=%d)\n", state);
+                               XDBG_DEBUG(MGEST, "[P] Base_width=%d, cur_touched=%d\n", base_width_size, pPalm->cur_touched);
 #endif
-                               break;
+                               if(pPalm->max_touched == 1)
+                               {
+                                       base_cx = AREA_CENTER_X(&pPalm->area.extents);
+                                       base_cy = AREA_CENTER_Y(&pPalm->area.extents);
+                                       base_box_ext.x1 = base_cx-HOLD_MOVE_THRESHOLD;
+                                       base_box_ext.y1 = base_cy-HOLD_MOVE_THRESHOLD;
+                                       base_box_ext.x2 = base_cx+HOLD_MOVE_THRESHOLD;
+                                       base_box_ext.y2 = base_cy+HOLD_MOVE_THRESHOLD;
+                               }
+                       }
+                       curTouched = pPalm->cur_touched;
+                       num_pressed++;
+                       break;
 
-                       case GestureUpdate:
+               case ET_Motion:
+                       if(!num_pressed || !is_flicking)
+                       {
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "HOLD Update !(state=%d)\n", state);
+                               XDBG_DEBUG(MGEST, "[M] num_pressed: %d, is_flicking: %d\n", num_pressed, is_flicking);
 #endif
                                break;
-               }
+                       }
 
-               if(base_width_size < PALM_HOLD_MIN_BASE_WIDTH)
-               {
+                       distx = AREA_CENTER_X(&pPalm->area.extents);
+                       disty = AREA_CENTER_Y(&pPalm->area.extents);
+                       line_idx = GesturePalmGetHorizIndexWithX(distx, type);
 #ifdef __PALM_GESTURE_LOG__
-                       XDBG_DEBUG(MGEST, "[P] No Hold base_width_size: %d < %d\n", base_width_size, PALM_HOLD_MIN_BASE_WIDTH);
-#endif
-                       goto hold_failed;
-               }
-
-               if( GestureHasFingerEventMask(GestureNotifyHold, 0) )
-               {
-                       if(state == GestureBegin)
+                       for(i=0; i<PALM_HORIZ_ARRAY_COUNT; i++)
                        {
-                               hold_occured = 1;
+                               XDBG_DEBUG(MGEST, "M] %d: %d\n", i, horiz_line[i]);
                        }
-                       GestureHandleGesture_Hold(0, cx, cy, GetTimeInMillis()-base_time, state);
-#ifdef __PALM_GESTURE_LOG__
-                       XDBG_DEBUG(MGEST, "[T] create hold timer @ timer expired\n");
+                       XDBG_DEBUG(MGEST, "[M] distx: %d, line_idx: %d, prev_line_idx: %d! pass_count: %d\n", distx, line_idx, prev_line_idx, pass_count);
 #endif
-                       palm_hold_event_timer = TimerSet(palm_hold_event_timer, 0, PALM_HOLD_UPDATE_THRESHOLD, GesturePalmEventTimerHandler, (int *)&event_type);
-               }
-               return;
-       }
 
-       switch( type )
-       {
-               case ET_ButtonPress:
-                       if(!is_holding)
-                               break;
-                       if(!base_time)
+                       if(line_idx < 0)
                        {
-                               if(!base_time)
-                                       base_time = GetTimeInMillis();
-                               event_type = GestureNotifyHold;
-                               TimerCancel(palm_hold_event_timer);
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[P] create hold timer @ initial time\n");
+                               XDBG_DEBUG(MGEST, "[M] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x, line_idx);
 #endif
-                               max_num_finger=0;
-                               palm_hold_event_timer = TimerSet(palm_hold_event_timer, 0, PALM_HOLD_TIME_THRESHOLD, GesturePalmEventTimerHandler, (int *)&event_type);
+                               goto flick_failed;
                        }
-                       base_width_size = AREA_WIDTH(&pPalm->area.extents);
-#ifdef __PALM_GESTURE_LOG__
-                       XDBG_DEBUG(MGEST, "[P] Hold base_width_size: %d\n", base_width_size);
-#endif
-                       false_base_width_size_count = 0;
-                       num_pressed++;
-                       if(max_num_finger < num_pressed)
-                               max_num_finger = num_pressed;
-                       break;
-
-               case ET_Motion:
-                       if(!num_pressed || !is_holding)
-                               return;
 
-                       if(state < GestureBegin)
+                       if(pPalm->max_touched == 1)
                        {
-                               if( !(pPalm->palmflag) && pPalm->max_palm >= PALM_FLICK_MIN_PALM)
-                                       pPalm->palmflag = 1;
-                               if(base_width_size < PALM_HOLD_MIN_BASE_WIDTH)
+                               if(ABS(disty - base_cy) > PALM_FLICK_HORIZ_MAX_MOVE_Y)
                                {
-                                       false_base_width_size_count++;
-#ifdef __PALM_GESTURE_LOG__
-                                       XDBG_DEBUG(MGEST, "[M] increase false_base_width_size_count: %d!, width: %.f\n", false_base_width_size_count, base_width_size);
-#endif
-                                       if(false_base_width_size_count > PALM_HOLD_FALSE_WIDTH)
-                                       {
 #ifdef __PALM_GESTURE_LOG__
-                                               XDBG_DEBUG(MGEST, "[M] No hold width!\n");
+                                       XDBG_DEBUG(MGEST, "[M] No flick ! (move too long toward y coordination %d(%d - %d) > %d\n", ABS(disty - base_cy), disty, base_cy, PALM_FLICK_HORIZ_MAX_MOVE_Y);
 #endif
-                                               goto hold_failed;
-                                       }
+                                       goto flick_failed;
                                }
                        }
 
-                       cx = AREA_CENTER_X(&pPalm->area.extents);
-                       cy = AREA_CENTER_Y(&pPalm->area.extents);
-                       break;
-
-               case ET_ButtonRelease:
-                       if(--num_pressed < 0)
-                               num_pressed = 0;
-
-                       if(pPalm->cur_touched || num_pressed)
-                               break;
-#ifdef __PALM_GESTURE_LOG__
-                       XDBG_DEBUG(MGEST, "[R] All fingers were released ! state=%d, is_holding=%d, cur_touched=%d, num_pressed=%d\n",
-                               state, is_holding, pPalm->cur_touched, num_pressed);
-#endif
-                       if(!is_holding)
-                               goto cleanup_hold;
-
-                       if (hold_occured == 0 && state == GestureEnd)
+                       if(prev_line_idx != line_idx)
                        {
-#ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[R] Fast Release..\n");
-#endif
-                               if( (pPalm->palmflag) && (base_width_size > PALM_HOLD_MIN_BASE_WIDTH))
-                               {
-#ifdef __PALM_GESTURE_LOG__
-                                       XDBG_DEBUG(MGEST, "[R] seemed hold palm is came, base_width_size: %d..\n", base_width_size);
-#endif
-                                       if( GestureHasFingerEventMask(GestureNotifyHold, 0) )
-                                       {
-                                               hold_occured = 1;
-                                               state = GestureBegin;
-                                               GestureHandleGesture_Hold(0, cx, cy, GetTimeInMillis()-base_time, state);
-                                               rapid_hold = 1;
-                                               palm_hold_rapid_timer = TimerSet(palm_hold_rapid_timer, 0, PALM_HOLD_TIME_THRESHOLD, GesturePalmHoldRapidHandler,  NULL);
-#ifdef __PALM_GESTURE_LOG__
-                                               XDBG_DEBUG(MGEST, "[R] rapid hold begin !!\n");
-#endif
-                                               goto hold_failed;
-                                       }
-                               }
-                               else if( (pPalm->biggest_wmajor > PALM_HOLD_FINGER_MIN_WIDTH_MAJOR) && (max_num_finger >= PALM_HOLD_MIN_FINGER) )
+                               horiz_line[line_idx]++;
+                               if(horiz_line[line_idx] > 2)
                                {
 #ifdef __PALM_GESTURE_LOG__
-                                       XDBG_DEBUG(MGEST, "[R] seemed hold.. biggest_wmajor: %.f, max_num_finger: %d", pPalm->biggest_wmajor, max_num_finger);
+                                       XDBG_DEBUG(MGEST, "[M] No flick ! horiz_line[%d]: %d > 2\n", line_idx, horiz_line[line_idx]);
 #endif
-                                       if( GestureHasFingerEventMask(GestureNotifyHold, 0) )
-                                       {
-                                               hold_occured = 1;
-                                               state = GestureBegin;
-                                               GestureHandleGesture_Hold(0, cx, cy, GetTimeInMillis()-base_time, state);
-                                               rapid_hold = 1;
-                                               palm_hold_rapid_timer = TimerSet(palm_hold_rapid_timer, 0, PALM_HOLD_TIME_THRESHOLD, GesturePalmHoldRapidHandler,  NULL);
-#ifdef __PALM_GESTURE_LOG__
-                                               XDBG_DEBUG(MGEST, "[R] rapid hold begin !!\n");
-#endif
-                                               goto hold_failed;
-                                       }
+                                       goto flick_failed;
                                }
+                               pass_count++;
                        }
-release_hold:
-                       if(hold_occured == 0 && num_pressed == 0)
+                       if(pass_count > 6)
                        {
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[R] release all finger and No hold base_width_size: %d, biggest_wmajor: %.f, max_num_finger: %d\n", base_width_size, pPalm->biggest_wmajor, max_num_finger);
+                               XDBG_DEBUG(MGEST, "[M] No flick !(visit same place twice !)\n");
 #endif
-                               goto hold_failed;
+                               goto flick_failed;
                        }
-
-                       if( state == GestureBegin || state == GestureUpdate )
+#if 0
+                       if((prev_line_idx != line_idx) && horiz_line[line_idx] && !release_flag)
                        {
-                               state = GestureEnd;
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[R] HOLD End !(state=%d)\n", state);
+                               XDBG_DEBUG(MGEST, "[M] No flick !(visit same place twice !)\n");
 #endif
-                               hold_occured = 0;
-                               //g_pGesture->recognized_palm = GESTURE_PALM_FILTER_MASK_ALL;
-                               if( GestureHasFingerEventMask(GestureNotifyHold, 0) )
-                               {
-                                       GestureHandleGesture_Hold(0, cx, cy, GetTimeInMillis()-base_time, state);
-                               }
-                               //else
-                                       //XDBG_DEBUG(MGEST, "[END] \n");
-                       }
-                       else
-                       {
-#ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[R] Gesture Hold End is already occured\n");
-#endif
-                               goto hold_failed;
-                       }
-                       goto cleanup_hold;
-       }
-       return;
-
-hold_failed:
-       is_holding = 0;
-       TimerCancel(palm_hold_event_timer);
-       g_pGesture->palm_filter_mask |= PalmHoldFilterMask;
-       if( g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL )
-       {
-               if( ERROR_INVALPTR == GestureFlushOrDrop() )
-               {
-                       GestureControl(g_pGesture->this_device, DEVICE_OFF);
-               }
-       }
-#ifdef __PALM_GESTURE_LOG__
-       XDBG_DEBUG(MGEST, "[F] recognized_palm= 0x%x, palm_filter_mask: 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask);
-#endif
-       goto cleanup_hold;
-       return;
-
-cleanup_hold:
-#ifdef __PALM_GESTURE_LOG__
-       XDBG_DEBUG(MGEST, "[F] HOLD Cleanup (state: %d)\n", state);
-#endif
-       TimerCancel(palm_hold_event_timer);
-       if(state == GestureBegin || state == GestureUpdate)
-       {
-               if( GestureHasFingerEventMask(GestureNotifyHold, 0) )
-               {
-                       GestureHandleGesture_Hold(0, cx, cy, GetTimeInMillis()-base_time, GestureEnd);
-               }
-       }
-       is_holding = 1;
-       num_pressed = 0;
-       false_base_width_size_count = 0;
-       base_time = 0;
-       cx = cy = 0;
-       max_num_finger = 0;
-       state = GestureEnd;
-       base_width_size = 0;
-       hold_occured = 0;
-       rapid_hold = 0;
-       return;
-}
-
-static void
-GesturePalmRecognize_FlickHorizen(int type, int idx)
-{
-       static int curTouched = 0;
-       static int num_pressed = 0;
-       static int base_width_size = 0;
-       static Time base_time = 0;
-       static int base_x;
-       static pixman_box16_t base_box_ext;
-#ifdef __PALM_GESTURE_LOG__
-       int i;
-#endif
-
-       int line_idx;
-       static int press_idx;
-       static int prev_line_idx;
-       static int horiz_line[PALM_HORIZ_ARRAY_COUNT];
-
-       Time duration;
-       int distx=0, disty=0;
-       int distance, direction;
-
-       int width_size;
-       static int is_flicking = 1;
-       //static int is_surface = 0;
-       static int pass_count = 0;
-       static int base_cx=0, base_cy=0;
-       static int release_flag = 0;
-
-       PalmStatusPtr pPalm = &g_pGesture->palm;
-#ifdef __PALM_GESTURE_LOG__
-       XDBG_DEBUG(MGEST, "recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask);
-       XDBG_DEBUG(MGEST, "num_pressed: %d, cur_touched: %d palmflag: %d\n", num_pressed, pPalm->cur_touched, pPalm->palmflag);
-       XDBG_DEBUG(MGEST, "idx: %d, cx: %d, cy: %d\n", idx, pPalm->cx, pPalm->cy);
-#endif
-
-       if(g_pGesture->enqueue_fulled == 1)
-       {
-#ifdef __PALM_GESTURE_LOG__
-                       XDBG_DEBUG(MGEST, "EQ Event is full.... palm recognize drop..\n");
-#endif
-                       goto flick_failed;
-       }
-
-       if(pPalm->single_timer_expired)
-       {
-#ifdef __PALM_GESTURE_LOG__
-               XDBG_DEBUG(MGEST, "No flick single finger...expired\n");
-#endif
-               goto flick_failed;
-       }
-
-       if(g_pGesture->recognized_gesture || (g_pGesture->recognized_palm && !(g_pGesture->recognized_palm & PalmFlickHorizFilterMask)) || (g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask)
-#ifdef _F_SUPPORT_BEZEL_FLICK_
-               || g_pGesture->bezel_recognized_mask)
-#else
-               )
-#endif
-       {
-#ifdef __PALM_GESTURE_LOG__
-               XDBG_DEBUG(MGEST, "zoom_enabled: %d\n", g_pGesture->zoom_enabled);
-               XDBG_DEBUG(MGEST, "type(%d) recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", type, g_pGesture->recognized_palm, g_pGesture->palm_filter_mask);
-               XDBG_DEBUG(MGEST, "type(%d) recognized_gesture= 0x%x, filter_mask= 0x%x\n", type, g_pGesture->recognized_gesture, g_pGesture->filter_mask);
-#endif
-               goto flick_failed;
-       }
-       switch( type )
-       {
-               case ET_ButtonPress:
-                       if(!is_flicking)
-                               break;
-                       if(!base_width_size || pPalm->cur_touched > curTouched)
-                       {
-                               if(!base_time)
-                               {
-                                       base_time = GetTimeInMillis();
-                                       base_x = AREA_CENTER_X(&pPalm->area.extents);
-                                       line_idx = GesturePalmGetHorizIndexWithX(base_x, type);
-#ifdef __PALM_GESTURE_LOG__
-                                       XDBG_DEBUG(MGEST, "[P] cx: %d, cy: %d, x1: %d, x2: %d, y1: %d, y2: %d, line_idx: %d\n", pPalm->cx, pPalm->cy, pPalm->area.extents.x1, pPalm->area.extents.x2, pPalm->area.extents.y1, pPalm->area.extents.y2, line_idx);
-#endif
-                                       if(line_idx < 0)
-                                       {
-#ifdef __PALM_GESTURE_LOG__
-                                               XDBG_DEBUG(MGEST, "[P] line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x, line_idx);
-#endif
-                                               goto flick_failed;
-                                       }
-
-                                       horiz_line[line_idx]++;
-                                       pass_count++;
-                                       press_idx = prev_line_idx = line_idx;
-                                       release_flag = 0;
-#ifdef __PALM_GESTURE_LOG__
-                                       XDBG_DEBUG(MGEST, "[P] Base_width=%d, base_x=%d, line_idx=%d\n", base_width_size, base_x, line_idx);
-#endif
-                               }
-
-                               base_width_size = AREA_WIDTH(&pPalm->area.extents);
-                               if(base_width_size > PALM_FLICK_HORIZ_MAX_BASE_WIDTH)
-                               {
-#ifdef __PALM_GESTURE_LOG__
-                                       XDBG_DEBUG(MGEST, "[P] No flickBase_width=%d > MAX_WIDTH\n", base_width_size, PALM_FLICK_HORIZ_MAX_BASE_WIDTH);
-#endif
-                                       goto flick_failed;
-                               }
-#ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[P] Base_width=%d, cur_touched=%d\n", base_width_size, pPalm->cur_touched);
-#endif
-                               if(pPalm->max_touched == 1)
-                               {
-                                       base_cx = AREA_CENTER_X(&pPalm->area.extents);
-                                       base_cy = AREA_CENTER_Y(&pPalm->area.extents);
-                                       base_box_ext.x1 = base_cx-HOLD_MOVE_THRESHOLD;
-                                       base_box_ext.y1 = base_cy-HOLD_MOVE_THRESHOLD;
-                                       base_box_ext.x2 = base_cx+HOLD_MOVE_THRESHOLD;
-                                       base_box_ext.y2 = base_cy+HOLD_MOVE_THRESHOLD;
-                               }
-                       }
-                       curTouched = pPalm->cur_touched;
-                       num_pressed++;
-                       break;
-
-               case ET_Motion:
-                       if(!num_pressed || !is_flicking)
-                       {
-#ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[M] num_pressed: %d, is_flicking: %d\n", num_pressed, is_flicking);
-#endif
-                               break;
-                       }
-
-                       distx = AREA_CENTER_X(&pPalm->area.extents);
-                       disty = AREA_CENTER_Y(&pPalm->area.extents);
-                       line_idx = GesturePalmGetHorizIndexWithX(distx, type);
-#ifdef __PALM_GESTURE_LOG__
-                       for(i=0; i<PALM_HORIZ_ARRAY_COUNT; i++)
-                       {
-                               XDBG_DEBUG(MGEST, "M] %d: %d\n", i, horiz_line[i]);
-                       }
-                       XDBG_DEBUG(MGEST, "[M] distx: %d, line_idx: %d, prev_line_idx: %d! pass_count: %d\n", distx, line_idx, prev_line_idx, pass_count);
-#endif
-
-                       if(line_idx < 0)
-                       {
-#ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[M] line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x, line_idx);
-#endif
-                               goto flick_failed;
-                       }
-
-                       if(pPalm->max_touched == 1)
-                       {
-                               if(ABS(disty - base_cy) > PALM_FLICK_HORIZ_MAX_MOVE_Y)
-                               {
-#ifdef __PALM_GESTURE_LOG__
-                                       XDBG_DEBUG(MGEST, "[M] No flick ! (move too long toward y coordination %d(%d - %d) > %d\n", ABS(disty - base_cy), disty, base_cy, PALM_FLICK_HORIZ_MAX_MOVE_Y);
-#endif
-                                       goto flick_failed;
-                               }
-                       }
-
-                       if(prev_line_idx != line_idx)
-                       {
-                               horiz_line[line_idx]++;
-                               if(horiz_line[line_idx] > 2)
-                                       goto flick_failed;
-                               pass_count++;
-                       }
-                       if(pass_count > 6)
-                       {
-#ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[M] No flick !(visit same place twice !)\n");
-#endif
-                               goto flick_failed;
-                       }
-#if 0
-                       if((prev_line_idx != line_idx) && horiz_line[line_idx] && !release_flag)
-                       {
-#ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[M] No flick !(visit same place twice !)\n");
-#endif
-                               goto flick_failed;
+                               goto flick_failed;
                        }
 #endif
                        prev_line_idx = line_idx;
@@ -3252,7 +2969,8 @@ GesturePalmRecognize_FlickHorizen(int type, int idx)
 #ifdef __PALM_GESTURE_LOG__
                        XDBG_DEBUG(MGEST, "[M] duration =%d !\n", duration);
 #endif
-                       if(!pPalm->palmflag && (duration >= PALM_FLICK_INITIAL_TIMEOUT))
+                       if(((!pPalm->palmflag) && (pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR-20) && (pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR-20)) &&
+                       (duration >= PALM_FLICK_INITIAL_TIMEOUT))
                        {
 #ifdef __PALM_GESTURE_LOG__
                                XDBG_DEBUG(MGEST, "[M] No flick !(initial flick timeout : duration=%d)\n", duration);
@@ -3266,10 +2984,10 @@ GesturePalmRecognize_FlickHorizen(int type, int idx)
 #endif
                                goto flick_failed;
                        }
-                       if( (duration >= PALM_FLICK_FALSE_TIMEOUT) && (pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR) )
+                       if( (duration >= PALM_FLICK_FALSE_TIMEOUT) && (pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR) && (pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR))
                        {
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[M] No flick !(press touch major(%.f < %.f) is little in duration(%d))\n", pPalm->biggest_tmajor, PALM_FLICK_TOUCH_MAJOR, duration);
+                               XDBG_DEBUG(MGEST, "[M] No flick !(press touch major(%.f) width major (%.f) < (%.f) is little in duration(%d))\n", pPalm->biggest_tmajor, pPalm->biggest_wmajor, PALM_FLICK_TOUCH_MAJOR, duration);
 #endif
                                goto flick_failed;
                        }
@@ -3290,7 +3008,8 @@ GesturePalmRecognize_FlickHorizen(int type, int idx)
                        base_width_size = AREA_WIDTH(&pPalm->area.extents);
                        if(num_pressed)
                                break;
-                       if(!pPalm->palmflag)
+
+                       if((!pPalm->palmflag) && (pPalm->biggest_tmajor < 100) && (pPalm->bigger_wmajor < 100))
                        {
 #ifdef __PALM_GESTURE_LOG__
                                XDBG_DEBUG(MGEST, "[R] No flick (No palm comming and all finger release))\n");
@@ -3329,10 +3048,10 @@ GesturePalmRecognize_FlickHorizen(int type, int idx)
 #endif
                                goto flick_failed;
                        }
-                       if(pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR)
+                       if((pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR) && (pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR))
                        {
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[R] No flick !(touch major(%.f < %d) is small...)\n", pPalm->biggest_tmajor, PALM_FLICK_TOUCH_MAJOR);
+                               XDBG_DEBUG(MGEST, "[R] No flick !(touch major(%.f) width major(%.f) < %d) is small...)\n", pPalm->biggest_tmajor, pPalm->biggest_wmajor, PALM_FLICK_TOUCH_MAJOR);
 #endif
                                goto flick_failed;
                        }
@@ -3393,7 +3112,6 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
        static pixman_box16_t base_box_ext;
 
        int line_idx;
-       static int press_idx;
        static int prev_line_idx;
        static int verti_line[PALM_VERTI_ARRAY_COUNT];
 
@@ -3411,16 +3129,20 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
        XDBG_DEBUG(MGEST, "recognized_palm= 0x%x, palm_filter_mask= 0x%x\n", g_pGesture->recognized_palm, g_pGesture->palm_filter_mask);
        XDBG_DEBUG(MGEST, "num_pressed: %d, cur_touched: %d, palm_flag: %d, single_timer_expired: %d\n", num_pressed, pPalm->cur_touched, pPalm->palmflag, pPalm->single_timer_expired);
 #endif
+
+       if( idx < 0 )
+               goto flick_failed;
+
        if(g_pGesture->enqueue_fulled == 1)
        {
 #ifdef __PALM_GESTURE_LOG__
-               XDBG_DEBUG(MGEST, "EQ Event is full.... palm recognize drop..\n");
+               XDBG_DEBUG(MGEST, "EQ Event is full.... No palm recognize drop..\n");
 #endif
                goto flick_failed;
        }
 
-
-       if(g_pGesture->recognized_gesture || (g_pGesture->recognized_palm && !(g_pGesture->recognized_palm & PalmFlickVertiFilterMask)) || (g_pGesture->palm_filter_mask & PalmFlickVertiFilterMask)
+       if(g_pGesture->recognized_gesture || g_pGesture->hold_detected ||
+               (g_pGesture->recognized_palm && !(g_pGesture->recognized_palm & PalmFlickVertiFilterMask)) || (g_pGesture->palm_filter_mask & PalmFlickVertiFilterMask)
 #ifdef _F_SUPPORT_BEZEL_FLICK_
                || g_pGesture->bezel_recognized_mask)
 #else
@@ -3460,11 +3182,16 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
                                        XDBG_DEBUG(MGEST, "[P] Base_height=%d, base_y=%d, line_idx=%d\n", base_height_size, base_y, line_idx);
 #endif
                                        if(line_idx < 0)
+                                       {
+#ifdef __PALM_GESTURE_LOG__
+                                               XDBG_DEBUG(MGEST, "[P] No Base_height=%d, base_y=%d, line_idx=%d\n", base_height_size, base_y, line_idx);
+#endif
                                                goto flick_failed;
+                                       }
 
                                        verti_line[line_idx] = 1;
                                        pass_count++;
-                                       press_idx = prev_line_idx = line_idx;
+                                       prev_line_idx = line_idx;
                                        release_flag = 0;
 #ifdef __PALM_GESTURE_LOG__
                                        XDBG_DEBUG(MGEST, "[P] Base_height=%d, base_y=%d, line_idx=%d\n", base_height_size, base_y, line_idx);
@@ -3510,7 +3237,12 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
 #endif
 
                        if(line_idx < 0)
+                       {
+#ifdef __PALM_GESTURE_LOG__
+                               XDBG_DEBUG(MGEST, "[M] No line_idx: %d\n", line_idx);
+#endif
                                goto flick_failed;
+                       }
                        if((prev_line_idx != line_idx) && verti_line[line_idx] && !release_flag)
                        {
 #ifdef __PALM_GESTURE_LOG__
@@ -3518,7 +3250,7 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
 #endif
                                goto flick_failed;
                        }
-
+#if 0
                        if(pPalm->max_touched == 1)
                        {
                                if(ABS(AREA_CENTER_X(&pPalm->area.extents) - base_cx) > PALM_FLICK_VERTI_MAX_MOVE_X)
@@ -3529,7 +3261,7 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
                                        goto flick_failed;
                                }
                        }
-
+#endif
                        verti_line[line_idx] = 1;
                        if(prev_line_idx != line_idx)
                                pass_count++;
@@ -3545,7 +3277,8 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
                        XDBG_DEBUG(MGEST, "[M] duration =%d !\n", duration);
 #endif
 
-                       if(!pPalm->palmflag && (duration >= PALM_FLICK_INITIAL_TIMEOUT))
+                       if(!pPalm->palmflag && (pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR-20) && (pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR-20)
+                                && (duration >= PALM_FLICK_INITIAL_TIMEOUT))
                        {
 #ifdef __PALM_GESTURE_LOG__
                                XDBG_DEBUG(MGEST, "[M] No flick !(initial flick timeout : duration=%d)\n", duration);
@@ -3571,17 +3304,16 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
 
                case ET_ButtonRelease:
                        release_flag = 1;
-                       if(pPalm->cur_touched)
-                               break;
 
                        if(--num_pressed < 0)
                                num_pressed = 0;
                        if(num_pressed)
                                break;
-                       if(!pPalm->palmflag)
+
+                       if(!pPalm->palmflag && (pPalm->biggest_tmajor < 100) && (pPalm->bigger_wmajor < 100))
                        {
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[R] num_pressed is 0\n");
+                               XDBG_DEBUG(MGEST, "[R] No flick (No palm comming and all finger release))\n");
 #endif
                                goto flick_failed;
                        }
@@ -3597,7 +3329,12 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
 #endif
 
                        if(line_idx < 0)
+                       {
+#ifdef __PALM_GESTURE_LOG__
+                               XDBG_DEBUG(MGEST, "[R] No line_idx: %d\n", line_idx);
+#endif
                                goto flick_failed;
+                       }
 #ifdef __PALM_GESTURE_LOG__
                        XDBG_DEBUG(MGEST, "[R] duration=%d, disty=%d\n", duration, disty);
 #endif
@@ -3616,10 +3353,10 @@ GesturePalmRecognize_FlickVertical(int type,int idx)
 #endif
                                goto flick_failed;
                        }
-                       if(pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR)
+                       if(pPalm->biggest_tmajor < PALM_FLICK_TOUCH_MAJOR && pPalm->biggest_wmajor < PALM_FLICK_TOUCH_MAJOR)
                        {
 #ifdef __PALM_GESTURE_LOG__
-                               XDBG_DEBUG(MGEST, "[R] No flick !(flick touch major(%.f < %d) is small!)\n", pPalm->biggest_tmajor, PALM_FLICK_TOUCH_MAJOR);
+                               XDBG_DEBUG(MGEST, "[R] No flick !(flick touch major(%.f) width major(%.f) < %d) is small!)\n", pPalm->biggest_tmajor, pPalm->biggest_wmajor, PALM_FLICK_TOUCH_MAJOR);
 #endif
                                goto flick_failed;
                        }
@@ -3691,7 +3428,7 @@ GesturePalmGetScreenInfo()
        pixman_region_init(&tarea);
        pixman_region_init_rect(&tarea, 0, 0, pPalmMisc->scrn_width, pPalmMisc->scrn_height);
        pPalmMisc->half_scrn_area_size = AREA_SIZE(&tarea.extents);
-       pPalmMisc->half_scrn_area_size = (unsigned int)((double)pPalmMisc->half_scrn_area_size / 2);
+       pPalmMisc->half_scrn_area_size = (unsigned int)((double)pPalmMisc->half_scrn_area_size / 2.4f);
 #ifdef __HOLD_DETECTOR_DEBUG__
        XDBG_DEBUG(MGEST, "pPalmMisc->half_scrn_area_size = %d\n", pPalmMisc->half_scrn_area_size);
 #endif//__HOLD_DETECTOR_DEBUG__
@@ -3734,6 +3471,7 @@ GesturePalmGetAbsAxisInfo(DeviceIntPtr dev)
        Atom atom_mt_slot;
        Atom atom_tracking_id;
        Atom atom_distance;
+       Atom atom_mt_tool;
 
        g_pGesture->wmajor_idx = -1;
        g_pGesture->tmajor_idx = -1;
@@ -3742,6 +3480,7 @@ GesturePalmGetAbsAxisInfo(DeviceIntPtr dev)
        g_pGesture->tpalm_idx = -1;
        g_pGesture->mt_px_idx = -1;
        g_pGesture->mt_py_idx = -1;
+       g_pGesture->mt_tool_idx = -1;
 
        memset(&g_pGesture->palm, 0, sizeof(PalmStatus));
 
@@ -3762,12 +3501,17 @@ GesturePalmGetAbsAxisInfo(DeviceIntPtr dev)
        atom_mt_slot = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_SLOT);
        atom_tracking_id = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TRACKING_ID);
        atom_distance = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_DISTANCE);
+       atom_mt_tool = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE);
 
        if (!numAxes || !atom_mt_px || !atom_mt_py || !atom_tmajor || !atom_tminor  || !atom_tangle || !atom_tpalm)
        {
                XDBG_WARNING(MGEST, "one or more axes is/are not supported!\n");
                goto out;
        }
+       if (!atom_mt_tool)
+       {
+               XDBG_WARNING(MGEST, "multitouch various type was not supported\n");
+       }
 
        for( i = 0 ; i < numAxes ; i++ )
        {
@@ -3811,12 +3555,21 @@ GesturePalmGetAbsAxisInfo(DeviceIntPtr dev)
                        g_pGesture->tpalm_idx = i;
                        found += 7;
                }
+               else if ( atom_mt_tool && axes->label == atom_mt_tool )
+               {
+                       g_pGesture->mt_tool_idx = i;
+                       found += 8;
+               }
        }
 
-       if (found != 28)
+       if (found != 36)
        {
-               XDBG_WARNING(MGEST, "Axes for palm recognization are not supported !\n");
-               goto out;
+               XDBG_WARNING(MGEST, "Various multitouch devices are not supported !\n");
+               if (found != 28)
+               {
+                       XDBG_WARNING(MGEST, "Axes for palm recognization are not supported !\n");
+                       goto out;
+               }
        }
 
        pPalm = &g_pGesture->palm;
@@ -4140,18 +3893,12 @@ GesturePalmRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
        int idx = -1;
        PalmStatusPtr pPalm = &g_pGesture->palm;
        static int calc_touched = 0;
+       static int event_sum_palm_first_finger = 0, event_sum_palm_second_finger=0;
 
        if( device->id < g_pGesture->first_fingerid )
                return;
 
-       for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ )
-       {
-               if( device->id == g_pGesture->mt_devices[i]->id )
-               {
-                       idx = i;
-                       break;
-               }
-       }
+       idx = GestureGetFingerIndexFromDevice(device);
        if( idx < 0 )
                return;
 
@@ -4161,22 +3908,39 @@ GesturePalmRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
        if(!g_pGesture->pTempPalmWin)
        {
                g_pGesture->pTempPalmWin = GestureGetEventsWindow();
-               if(!g_pGesture->pTempPalmWin)
+               if(!g_pGesture->pTempPalmWin || g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)
                {
 #ifdef __PALM_DETAIL_LOG__
                        XDBG_DEBUG(MGEST, "No events are grabbed/selected !\n");
 #endif//__PALM_DETAIL_LOG__
-                       g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL;
-                       goto flush_or_drop;
-               }
-       }
-       GesturePalmDataUpdate(idx, type, ev, device);
-       GesturePalmUpdateAreaInfo(type, idx);
-
+                       g_pGesture->no_palm_events = TRUE;
+                       if (g_pGesture->palm_rejection_mode == 0)
+                       {
+                               g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL;
+                               goto flush_or_drop;
+                       }
+                       else
+                       {
+                               g_pGesture->palm_filter_mask = 0;
+                       }
+               }
+       }
+       GesturePalmDataUpdate(idx, type, ev, device);
+       GesturePalmUpdateAreaInfo(type, idx);
+#ifdef __PALM_DETAIL_LOG__
+       XDBG_DEBUG(MGEST, "[idx: %d: %d](%d, %d)max_tmajor: %lf, palmflag: %d, max_wmajor: %lf\n", idx, type, pPalm->pti[idx].x, pPalm->pti[idx].y, pPalm->max_tmajor, pPalm->palmflag, pPalm->max_wmajor);
+       XDBG_DEBUG(MGEST, "bigger_wmajor: %lf, biggest_tmajor: %lf, biggest_wmajor: %lf\n", pPalm->bigger_wmajor, pPalm->biggest_tmajor, pPalm->biggest_wmajor);
+       XDBG_DEBUG(MGEST, "area: %d, deviationX: %lf, deviationY: %lf, dispersionX: %lf, dispersion: %lf\n", pPalm->area, pPalm->deviationX, pPalm->deviationY, pPalm->dispersionX, pPalm->dispersionY);
+#endif
        switch(type)
        {
                case ET_ButtonPress:
+                       if( idx == 0 )
+                               event_sum_palm_first_finger = BTN_PRESSED;
+                       else if( idx == 1)
+                               event_sum_palm_second_finger = BTN_PRESSED;
                        pPalm->max_touched++;
+
                        if( g_pGesture->num_pressed == 1 )
                        {
                                pPalm->palm_single_finger_timer = TimerSet(pPalm->palm_single_finger_timer, 0, 50, GesturePalmSingleFingerTimerHandler, NULL);
@@ -4187,9 +3951,83 @@ GesturePalmRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
                        }
                        break;
                case ET_Motion:
-                       if(pPalm->cur_touched == 0)
+                       if(pPalm->cur_touched == 0 || pPalm->pti[idx].touch_status != 1)
                        {
-                               break;
+                               return;
+                       }
+                       if((pPalm->cur_touched == 1 && idx == 0 && event_sum_palm_first_finger == BTN_PRESSED) ||
+                               (pPalm->cur_touched == 2 && idx == 1 && event_sum_palm_second_finger == BTN_PRESSED))
+                       {
+                               if(idx == 0)
+                               {
+                                       event_sum_palm_first_finger = BTN_MOVING;
+#ifdef __PALM_DETAIL_LOG__
+                                       XDBG_DEBUG(MGEST, "First move detected!\n");
+#endif//__PALM_DETAIL_LOG__
+                               }
+                               else // idx == 1
+                               {
+                                       event_sum_palm_second_finger = BTN_MOVING;
+#ifdef __PALM_DETAIL_LOG__
+                                       XDBG_DEBUG(MGEST, "Second finger First move detected!\n");
+#endif//__PALM_DETAIL_LOG__
+                               }
+                               if (pPalm->palmflag < 1 && pPalm->biggest_tmajor < g_pGesture->palm_min_touch_major && pPalm->biggest_wmajor < g_pGesture->palm_min_width_major)
+                               {
+#ifdef __PALM_DETAIL_LOG__
+                                       XDBG_DEBUG(MGEST, "No palm coming.\n");
+#endif//__PALM_DETAIL_LOG__
+                                       Bool exist;
+                                       exist = GestureIsPalmEventInMIEQ();
+#ifdef __PALM_DETAIL_LOG__
+                                       XDBG_DEBUG(MGEST, "palm event exist: %d\n", exist);
+#endif//__PALM_DETAIL_LOG__
+
+                                       if (exist)
+                                       {
+                                               pPalm->palmflag = 1;
+                                               g_pGesture->palm_detected = TRUE;
+                                       }
+                                       else
+                                       {
+                                               /*
+                                                * The following is the bezel condition for palm
+                                                * -- palm touch area can be smaller than that of non-bezel regions, so the threshold value is reduced.
+                                                */
+                                               if(!(g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask) &&
+                                                       (pPalm->cx >= g_pGesture->screen_width - g_pGesture->palm_bezel || pPalm->cx < g_pGesture->palm_bezel) &&
+                                                       (pPalm->biggest_tmajor >= g_pGesture->palm_min_touch_major_bezel || pPalm->biggest_wmajor >= g_pGesture->palm_min_width_major_bezel))
+                                               {
+                                                       g_pGesture->palm_detected = TRUE;
+                                                       break;
+                                               }
+                                               if(!(g_pGesture->palm_filter_mask & PalmFlickVertiFilterMask) &&
+                                                       (pPalm->cy >= g_pGesture->screen_height - g_pGesture->palm_bezel || pPalm->cy < g_pGesture->palm_bezel) &&
+                                                       (pPalm->biggest_tmajor >= g_pGesture->palm_min_touch_major_bezel || pPalm->biggest_wmajor >= g_pGesture->palm_min_width_major_bezel))
+                                               {
+                                                       g_pGesture->palm_detected = TRUE;
+                                                       break;
+                                               }
+
+                                               if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->no_palm_events == TRUE)
+                                                       g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL;
+                                               g_pGesture->recognized_palm = 0;
+                                               if(!(g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask))
+                                               {
+                                                       GesturePalmRecognize_FlickHorizen(type, -1);
+                                               }
+                                               if(!(g_pGesture->palm_filter_mask & PalmFlickVertiFilterMask))
+                                               {
+                                                       GesturePalmRecognize_FlickVertical(type, -1);
+                                               }
+                                               if (g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)
+                                                       goto flush_or_drop;
+                                       }
+                               }
+                               else
+                               {
+                                       g_pGesture->palm_detected = TRUE;
+                               }
                        }
                        calc_touched++;
                        if(calc_touched == pPalm->cur_touched)
@@ -4198,12 +4036,22 @@ GesturePalmRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
                        }
                        break;
                case ET_ButtonRelease:
+                       if( idx == 0 )
+                               event_sum_palm_first_finger = BTN_RELEASED;
+                       else if( idx == 1)
+                               event_sum_palm_second_finger = BTN_RELEASED;
                        if(calc_touched)
                        {
                                calc_touched--;
                        }
                        break;
        }
+       if( g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE && g_pGesture->no_palm_events == TRUE)
+       {
+               g_pGesture->recognized_palm = 0;
+               g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL;
+               goto flush_or_drop;
+       }
 
        if( GestureHasFingerEventMask(GestureNotifyFlick, 0) )
        {
@@ -4216,13 +4064,6 @@ GesturePalmRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
                        GesturePalmRecognize_FlickVertical(type, idx);
                }
        }
-       if( GestureHasFingerEventMask(GestureNotifyHold, 0) )
-       {
-               if(!(g_pGesture->palm_filter_mask & PalmHoldFilterMask))
-               {
-                       GesturePalmRecognize_Hold(type, idx, 0);
-               }
-       }
 
        if(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL)
        {
@@ -4485,6 +4326,188 @@ bezel_cleanup:
 }
 #endif
 
+static EventQueuePtr
+GestureGetMIEQ(void)
+{
+       if (*checkForInput[0] == *checkForInput[1])
+       {
+#ifdef __DETAIL_DEBUG__
+               XDBG_DEBUG(MGEST, "mieq is empty !\n");
+#endif//__DETAIL_DEBUG__
+               return NULL;
+       }
+
+       EventQueuePtr mieqEQPtr = NULL;
+       mieqEQPtr = mieqGetEventQueuePtr();
+
+       if (!mieqEQPtr)
+       {
+#ifdef __DETAIL_DEBUG__
+               XDBG_DEBUG(MGEST, "mieqEQPtr is NULL !\n");
+#endif//__DETAIL_DEBUG__
+
+               return NULL;
+       }
+
+       int num = mieqNumEnqueued(mieqEQPtr);
+#ifdef __DETAIL_DEBUG__
+       XDBG_DEBUG(MGEST, " num of event in mieq = %d\n", num);
+#endif//__DETAIL_DEBUG__
+       if (num <= 0)
+               return NULL;
+
+       return mieqEQPtr;
+}
+
+static Bool
+GestureIsEventInMIEQ(int finger_index, enum EventType type)
+{
+       EventQueuePtr mieqEQPtr = NULL;
+       mieqEQPtr = GestureGetMIEQ();
+       if (!mieqEQPtr)
+       {
+#ifdef __DETAIL_DEBUG__
+               XDBG_DEBUG(MGEST, "failed to get mieq\n");
+#endif//__DETAIL_DEBUG__
+               return FALSE;
+       }
+
+       int deviceid = GestureGetDeviceIdFromFingerIndex(finger_index);
+       if (deviceid < 0)
+       {
+               XDBG_ERROR(MGEST, "Failed to get deviceid from finger index !\n");
+               return FALSE;
+       }
+
+       EventRec *e = NULL;
+       static InternalEvent event;
+       HWEventQueueType head, tail;
+       head = mieqEQPtr->head;
+       tail = mieqEQPtr->tail;
+
+       while (head != tail)
+       {
+               e = &mieqEQPtr->events[head];
+               if (e)
+               {
+                       event = *e->events;
+
+                       if (e->pDev && (deviceid == e->pDev->id) && (event.any.type == type))
+                       {
+                               return TRUE;
+                       }
+               }
+
+               head = (head + 1) % mieqEQPtr->nevents;
+       }
+
+       return FALSE;
+}
+
+static Bool
+GestureIsPalmEventInMIEQ(void)
+{
+       EventQueuePtr mieqEQPtr = NULL;
+       mieqEQPtr = GestureGetMIEQ();
+       if (!mieqEQPtr)
+       {
+#ifdef __PALM_DETAIL_LOG__
+               XDBG_DEBUG(MGEST, "failed to get mieq\n");
+#endif//__PALM_DETAIL_LOG__
+               return FALSE;
+       }
+
+       EventRec *e = NULL;
+       static InternalEvent event;
+       HWEventQueueType head, tail;
+       head = mieqEQPtr->head;
+       tail = mieqEQPtr->tail;
+
+       while (head != tail)
+       {
+               e = &mieqEQPtr->events[head];
+               if (e)
+               {
+                       event = *e->events;
+
+                       if (GestureIsPalmEvent(&event))
+                       {
+                               return TRUE;
+                       }
+               }
+
+               head = (head + 1) % mieqEQPtr->nevents;
+       }
+
+       return FALSE;
+}
+
+static Bool
+GestureIsPalmEvent(InternalEvent *event)
+{
+       int wmajor_idx = g_pGesture->wmajor_idx;
+       int tmajor_idx = g_pGesture->tmajor_idx;
+       int tpalm_idx = g_pGesture->tpalm_idx;
+
+       double width_major = 0.0f;
+       double touch_major = 0.0f;
+       double touch_palm = 0.0f;
+
+       if (event->any.type != ET_ButtonPress && event->any.type != ET_Motion && event->any.type != ET_ButtonRelease)
+               return FALSE;
+
+       DeviceEvent *de = &event->device_event;
+
+       if (!de || !de->valuators.data)
+       {
+               XDBG_WARNING(MGEST, "de or de->valuators.data are NULL !\n");
+               return FALSE;
+       }
+
+       if ((wmajor_idx < 0) || (tmajor_idx < 0) || (tpalm_idx < 0))
+       {
+               XDBG_WARNING(MGEST, "One or more of axes are not supported !\n");
+               return FALSE;
+       }
+
+       width_major = de->valuators.data[wmajor_idx];
+       touch_major = de->valuators.data[tmajor_idx];
+       touch_palm = de->valuators.data[tpalm_idx];
+#ifdef __PALM_DETAIL_LOG__
+       XDBG_DEBUG(MGEST, "width_major: %.f, touch_major: %.f, touch_palm: %.f\n", width_major, touch_major, touch_palm);
+#endif//__PALM_DETAIL_LOG__
+
+       if (touch_palm >= 1 || touch_major >= g_pGesture->palm_min_touch_major || width_major >= g_pGesture->palm_min_width_major)
+               return TRUE;
+       return FALSE;
+}
+
+static int
+GestureGetFingerIndexFromDevice(DeviceIntPtr device)
+{
+       int i;
+
+       for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ )
+       {
+               if( device->id == g_pGesture->mt_devices[i]->id )
+               {
+                       return i;
+               }
+       }
+
+       return -1;
+}
+
+static int
+GestureGetDeviceIdFromFingerIndex(int finger_index)
+{
+       if (g_pGesture->num_mt_devices <= finger_index)
+               return -1;
+
+       return g_pGesture->mt_devices[finger_index]->id;
+}
+
+
 void
 GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
 {
@@ -4496,14 +4519,7 @@ GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
                device->id < g_pGesture->first_fingerid )
                return;
 
-       for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ )
-       {
-               if( device->id == g_pGesture->mt_devices[i]->id )
-               {
-                       idx = i;
-                       break;
-               }
-       }
+       idx = GestureGetFingerIndexFromDevice(device);
 
        if( idx < 0 )
                return;
@@ -4531,7 +4547,7 @@ GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
 
                        if( g_pGesture->num_pressed == 1 )
                        {
-                               single_finger_timer = TimerSet(single_finger_timer, 0, g_pGesture->singlefinger_threshold, GestureSingleFingerTimerHandler, NULL);
+                               single_finger_timer = TimerSet(single_finger_timer, 0, g_pGesture->tap_repeated ? 80 : g_pGesture->singlefinger_threshold, GestureSingleFingerTimerHandler, NULL);
                        }
                        else
                        {
@@ -4545,7 +4561,7 @@ GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
                        {
                                g_pGesture->pTempWin = GestureGetEventsWindow();
 
-                               if( NULL == g_pGesture->pTempWin )
+                               if( NULL == g_pGesture->pTempWin || g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL)
                                {
 #ifdef __DETAIL_DEBUG__
                                        XDBG_DEBUG(MGEST, "[g_pGesture->num_pressed=%d] No events were selected !\n", g_pGesture->num_pressed);
@@ -4562,82 +4578,96 @@ GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
                        g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
                        g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
 
-                       if( g_pGesture->inc_num_pressed == 1 )
+                       pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+                       for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
                        {
-                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
-#ifdef __DETAIL_DEBUG__
-                               XDBG_DEBUG(MGEST, "[P][g_pGesture->inc_num_pressed=1] AREA_SIZE(area.extents)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
-#endif//__DETAIL_DEBUG__
+                               pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
                        }
-                       else
-                       {
-                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
-                               for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
-                               {
-                                       pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
-                               }
 #ifdef __DETAIL_DEBUG__
-                               XDBG_DEBUG(MGEST, "[P][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area.extents)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
+                       XDBG_DEBUG(MGEST, "[M][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
 #endif//__DETAIL_DEBUG__
-                       }
 
                        break;
 
                case ET_Motion:
                        if( !g_pGesture->fingers[idx].ptime )
                                return;
+
+                       g_pGesture->fingers[idx].mx = ev->device_event.root_x;
+                       g_pGesture->fingers[idx].my = ev->device_event.root_y;
+
                        if( (g_pGesture->inc_num_pressed < 2) && (idx == 0))
                        {
                                g_pGesture->event_sum[0] += BTN_MOVING;
 #ifdef __DETAIL_DEBUG__
                                XDBG_DEBUG(MGEST, "no seconds finger comming\n");
 #endif//__DETAIL_DEBUG__
-
-                               // tolerate false motion events only when second double-finger press is applied
                                if(!g_pGesture->tap_repeated)
                                {
+                                       if(g_pGesture->event_sum[0] >= 3)
+                                       {
 #ifdef __DETAIL_DEBUG__
-                                       XDBG_DEBUG(MGEST, "single finger!\n");
+                                               XDBG_DEBUG(MGEST, "single finger!\n");
 #endif//__DETAIL_DEBUG__
-                                       g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
-                                       goto flush_or_drop;
+                                               Bool exist;
+                                               exist = GestureIsEventInMIEQ(1, ET_ButtonPress);
+#ifdef __DETAIL_DEBUG__
+                                               XDBG_DEBUG(MGEST, "two finger touch in queue, exist: %d\n", exist);
+#endif//__DETAIL_DEBUG__
+                                               if (exist)
+                                                       g_pGesture->event_sum[0] -= BTN_MOVING;
+                                               else
+                                               {
+                                                       g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
+                                                       goto flush_or_drop;
+                                               }
+                                       }
                                }
-                               else if(g_pGesture->event_sum[0] >= 7)
+                               else
                                {
+                                       if(ABS(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) > FINGER_WIDTH
+                                       || ABS(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) > FINGER_HEIGHT)
+                                       {
 #ifdef __DETAIL_DEBUG__
-                                       XDBG_DEBUG(MGEST, "tap repeat Moving Limit Exceeded.\n");
+                                               XDBG_DEBUG(MGEST, "tap repeat Moving Limit Exceeded.\n");
 #endif//__DETAIL_DEBUG__
-                                       g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
-                                       goto flush_or_drop;
+                                               g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
+                                               goto flush_or_drop;
+                                       }
+                                       else if(g_pGesture->event_sum[0] >= 15)
+                                       {
+#ifdef __DETAIL_DEBUG__
+                                               XDBG_DEBUG(MGEST, "tap repeat Moving Limit Exceeded.\n");
+#endif//__DETAIL_DEBUG__
+                                               Bool exist;
+                                               exist = GestureIsEventInMIEQ(1, ET_ButtonPress);
+#ifdef __DETAIL_DEBUG__
+                                               XDBG_DEBUG(MGEST, "two finger touch in queue, exist: %d\n", exist);
+#endif//__DETAIL_DEBUG__
+                                               if (exist)
+                                                       g_pGesture->event_sum[0] -= BTN_MOVING;
+                                               else
+                                               {
+                                                       g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
+                                                       goto flush_or_drop;
+                                               }
+                                       }
                                }
                        }
 
-                       g_pGesture->fingers[idx].mx = ev->device_event.root_x;
-                       g_pGesture->fingers[idx].my = ev->device_event.root_y;
-
                        g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
                        g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
                        g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
                        g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
 
-                       if( g_pGesture->inc_num_pressed == 1 )
+                       pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+                       for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
                        {
-                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
-#ifdef __DETAIL_DEBUG__
-                               XDBG_DEBUG(MGEST, "[M][g_pGesture->inc_num_pressed=1] AREA_SIZE(area)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
-#endif//__DETAIL_DEBUG__
+                               pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
                        }
-                       else
-                       {
-                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
-                               for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
-                               {
-                                       pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
-                               }
 #ifdef __DETAIL_DEBUG__
-                               XDBG_DEBUG(MGEST, "[M][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
+                       XDBG_DEBUG(MGEST, "[M][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
 #endif//__DETAIL_DEBUG__
-                       }
                        break;
 
                case ET_ButtonRelease:
@@ -4712,7 +4742,7 @@ GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
        return;
 
 flush_or_drop:
-
+       TimerCancel(single_finger_timer);
 #ifdef __DETAIL_DEBUG__
        XDBG_DEBUG(MGEST, "GestureFlushOrDrop() !\n");
 #endif//__DETAIL_DEBUG__
@@ -4768,10 +4798,16 @@ ErrorStatus GestureFlushOrDrop(void)
 #endif
        {
                g_pGesture->ehtype = PROPAGATE_EVENTS;
-               err = GestureEventsFlush();
-               if( ERROR_NONE != err )
-                       return err;
-
+               if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE)
+               {
+                       GestureEventsDrop();
+               }
+               else
+               {
+                       err = GestureEventsFlush();
+                       if( ERROR_NONE != err )
+                               return err;
+               }
                err = GestureRegionsReinit();
                for(i=0; i<MAX_MT_DEVICES; i++)
                {
@@ -4837,42 +4873,266 @@ GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
                        for( i=0 ; i < g_pGesture->num_mt_devices ; i++ )
                                g_pGesture->fingers[i].ptime = 0;
                }
+               g_pGesture->stylusInfo.stylus_id = 0;
+               g_pGesture->stylusInfo.pen_detected = FALSE;
+               g_pGesture->no_palm_events = FALSE;
+               g_pGesture->stylusInfo.fake_events = FALSE;
+               g_pGesture->palm_detected = FALSE;
+       }
+       else if( MTOUCH_FRAME_SYNC_END == ev->any_event.sync )
+       {
+#ifdef __DEBUG_EVENT_HANDLER__
+               XDBG_DEBUG(MGEST, "SYNC_END\n");
+#endif//__DEBUG_EVENT_HANDLER
+               g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_END;
+
+               if(g_pGesture->is_active)
+               {
+                       g_pGesture->ehtype = PROPAGATE_EVENTS;
+                       g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL;
+                       pPalm->cur_touched = 0;
+                       pPalm->palmflag = 0;
+                       pPalm->max_palm = 0;
+                       g_pGesture->pTempPalmWin = NULL;
+                       if(pPalm->palm_single_finger_timer)
+                               TimerCancel(pPalm->palm_single_finger_timer);
+                       g_pGesture->pTempWin = NULL;
+                       g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
+                       g_pGesture->event_sum[0] = 0;
+                       pPalm->max_touched = 0;
+                       g_pGesture->hold_detected = FALSE;
+#ifdef _F_SUPPORT_BEZEL_FLICK_
+                       pBezel->is_active = BEZEL_END;
+                       g_pGesture->bezel_filter_mask = BezelFlickFilterMask;
+#endif
+               }
+               for(i=0; i<MAX_MT_DEVICES; i++)
+               {
+                       g_pGesture->stylusInfo.t_status[i].status = BTN_RELEASED;
+               }
+       }
+}
+
+static int
+GestureGetMTToolValuator(InternalEvent *ev, DeviceIntPtr device)
+{
+       int mt_tool_idx = g_pGesture->mt_tool_idx;
+       double mt_tool = 0.0f;
+
+       DeviceEvent *de = &ev->device_event;
+
+       if (!de || !de->valuators.data)
+       {
+               XDBG_WARNING(MGEST, "de or de->valuators.data are NULL !\n");
+               return -1;
+       }
+
+       if (mt_tool_idx < 0)
+       {
+               XDBG_WARNING(MGEST, "One or more of axes are not supported !\n");
+               return -1;
+       }
+
+       if (ev->any.type == ET_ButtonPress || ev->any.type == ET_ButtonRelease)
+       {
+               if (device->id == g_pGesture->master_pointer->id && g_pGesture->stylusInfo.stylus_id == g_pGesture->first_fingerid)
+                       de->valuators.data[mt_tool_idx] = 1;
+
+               if (g_pGesture->stylusInfo.stylus_id == device->id)
+                       de->valuators.data[mt_tool_idx] = 1;
+       }
+
+       mt_tool = de->valuators.data[mt_tool_idx];
+
+       return (int)mt_tool;
+}
+
+static void
+GestureRegisterTouchInfo(InternalEvent *ev, DeviceIntPtr device)
+{
+       int idx;
+
+       idx = GestureGetFingerIndexFromDevice(device);
+       if (idx < 0)
+       {
+               if (device->id != g_pGesture->master_pointer->id)
+                       XDBG_WARNING(MGEST, "Failed to get correct idx(%d) device->id: %d, master_pointer: %d\n", idx, device->id, g_pGesture->master_pointer->id);
+               return;
+       }
+       switch(ev->any.type)
+       {
+               case ET_ButtonPress:
+                       g_pGesture->stylusInfo.t_status[idx].status = BTN_PRESSED;
+                       break;
+               case ET_Motion:
+                       if (g_pGesture->stylusInfo.t_status[idx].status == BTN_PRESSED)
+                               g_pGesture->stylusInfo.t_status[idx].status = BTN_MOVING;
+                       break;
+               case ET_ButtonRelease:
+                       g_pGesture->stylusInfo.t_status[idx].status = BTN_RELEASED;
+                       break;
+               default:
+                       XDBG_WARNING(MGEST, "unhandled event type(%d)\n", ev->any.type);
+                       break;
+       }
+       g_pGesture->stylusInfo.t_status[idx].cx = ev->device_event.root_x;
+       g_pGesture->stylusInfo.t_status[idx].cy = ev->device_event.root_y;
+}
+
+static void
+GestureSetToolData(InternalEvent *ev, double val_tool)
+{
+       int mt_tool_idx = g_pGesture->mt_tool_idx;
+       double mt_tool = 0.0f;
+
+       DeviceEvent *de = &ev->device_event;
+
+       if (!de || !de->valuators.data)
+       {
+               XDBG_WARNING(MGEST, "de or de->valuators.data are NULL !\n");
+               return;
+       }
+
+       if (mt_tool_idx < 0)
+       {
+               XDBG_WARNING(MGEST, "One or more of axes are not supported !\n");
+               return;
+       }
+       de->valuators.data[mt_tool_idx] = val_tool;
+}
+
+static void
+GestureCleanupTouch(int screen_num, InternalEvent *ev, DeviceIntPtr device)
+{
+       ErrorStatus err;
+       int i;
+       if (g_pGesture->stylusInfo.stylus_id == 0 && g_pGesture->stylusInfo.pen_detected == FALSE)
+               g_pGesture->stylusInfo.stylus_id = device->id;
+
+       if (g_pGesture->ehtype == KEEP_EVENTS)
+       {
+               GestureEventsDrop();
+               g_pGesture->ehtype = PROPAGATE_EVENTS;
        }
-       else if( MTOUCH_FRAME_SYNC_END == ev->any_event.sync )
+       else if (g_pGesture->stylusInfo.pen_detected == FALSE && g_pGesture->ehtype == PROPAGATE_EVENTS)
        {
-#ifdef __DEBUG_EVENT_HANDLER__
-               XDBG_DEBUG(MGEST, "SYNC_END\n");
-#endif//__DEBUG_EVENT_HANDLER
-               g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_END;
-
-               if(g_pGesture->is_active)
+               g_pGesture->stylusInfo.pen_detected = TRUE;
+               g_pGesture->stylusInfo.fake_events = TRUE;
+               for(i=0; i<MAX_MT_DEVICES; i++)
                {
-                       g_pGesture->ehtype = PROPAGATE_EVENTS;
-                       g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL;
-                       pPalm->cur_touched = 0;
-                       pPalm->palmflag = 0;
-                       pPalm->max_palm = 0;
-                       g_pGesture->pTempPalmWin = NULL;
-                       if(pPalm->palm_single_finger_timer)
-                               TimerCancel(pPalm->palm_single_finger_timer);
-                       g_pGesture->pTempWin = NULL;
-                       g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
-                       g_pGesture->event_sum[0] = 0;
-                       pPalm->max_touched = 0;
-#ifdef _F_SUPPORT_BEZEL_FLICK_
-                       pBezel->is_active = BEZEL_END;
-                       g_pGesture->bezel_filter_mask = BezelFlickFilterMask;
-#endif
+                       if (g_pGesture->stylusInfo.t_status[i].status == BTN_PRESSED || g_pGesture->stylusInfo.t_status[i].status == BTN_MOVING)
+                       {
+                               InternalEvent release_ev;
+                               memcpy(&release_ev, ev, sizeof(InternalEvent));
+                               release_ev.any.time = ev->any.time;
+                               release_ev.any.type = ET_ButtonRelease;
+
+                               release_ev.device_event.detail.button = 1;
+                               release_ev.device_event.type = ET_ButtonRelease;
+                               release_ev.device_event.root_x = g_pGesture->stylusInfo.t_status[i].cx;
+                               release_ev.device_event.root_y = g_pGesture->stylusInfo.t_status[i].cy;
+                               release_ev.device_event.deviceid = g_pGesture->mt_devices[i]->id;
+                               g_pGesture->stylusInfo.t_status[i].status = BTN_RELEASED;
+                               GestureSetToolData(&release_ev, (double)0);
+
+                               GestureHandleButtonReleaseEvent(screen_num, &release_ev, g_pGesture->mt_devices[i]);
+                               if (g_pGesture->mt_devices[i]->id == g_pGesture->first_fingerid)
+                               {
+                                       InternalEvent release_mev;
+                                       memcpy(&release_mev, ev, sizeof(InternalEvent));
+                                       release_mev.any.time = ev->any.time;
+                                       release_mev.any.type = ET_ButtonRelease;
+
+                                       release_mev.device_event.detail.button = 1;
+                                       release_mev.device_event.type = ET_ButtonRelease;
+                                       release_mev.device_event.root_x = g_pGesture->stylusInfo.t_status[i].cx;
+                                       release_mev.device_event.root_y = g_pGesture->stylusInfo.t_status[i].cy;
+                                       release_mev.device_event.deviceid = g_pGesture->master_pointer->id;
+                                       GestureSetToolData(&release_mev, (double)0);
+
+                                       GestureHandleButtonReleaseEvent(screen_num, &release_mev, g_pGesture->master_pointer);
+                               }
+                       }
                }
+               g_pGesture->stylusInfo.fake_events = FALSE;
+       }
+       g_pGesture->stylusInfo.pen_detected = TRUE;
+       g_pGesture->filter_mask = GESTURE_FILTER_MASK_ALL;
+       g_pGesture->recognized_gesture = 0;
+       g_pGesture->palm_filter_mask = GESTURE_PALM_FILTER_MASK_ALL;
+       g_pGesture->recognized_palm = 0;
+}
+
+static void
+GestureChangeEventToFirstFingerEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
+{
+       InternalEvent master_ev;
+       ev->device_event.deviceid = g_pGesture->first_fingerid;
+
+       switch(ev->any.type)
+       {
+               case ET_ButtonPress:
+                       if(!(device->id < g_pGesture->first_fingerid))
+                               g_pGesture->num_pressed++;
+                       break;
+               case ET_ButtonRelease:
+                       if(!(device->id < g_pGesture->first_fingerid))
+                               g_pGesture->num_pressed--;
+                       break;
+               default:
+                       break;
        }
+       memcpy(&master_ev, ev, sizeof(InternalEvent));
+       g_pGesture->mt_devices[0]->public.processInputProc(ev, g_pGesture->mt_devices[0]);
+
+       master_ev.device_event.deviceid = g_pGesture->master_pointer->id;
+       g_pGesture->master_pointer->public.processInputProc(&master_ev, g_pGesture->master_pointer);
 }
 
 void
 GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
 #ifdef __DEBUG_EVENT_HANDLER__
-       XDBG_DEBUG(MGEST, "mode: %d devid=%d time:%d cur: %d\n", g_pGesture->ehtype, device->id, ev->any.time, GetTimeInMillis());
+       XDBG_DEBUG(MGEST, "mode: %d devid=%d time:%d cur: %d (%d, %d)\n",
+               g_pGesture->ehtype, device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
+#endif//__DEBUG_EVENT_HANDLER__
+
+       if (g_pGesture->stylus_able)
+       {
+               int isStylus = GestureGetMTToolValuator(ev, device);
+
+#ifdef __DEBUG_EVENT_HANDLER__
+                       XDBG_DEBUG(MGEST, "isSytlus: %d, pen_detected: %d, stylus_id: %d\n", isStylus, g_pGesture->stylusInfo.pen_detected, g_pGesture->stylusInfo.stylus_id);
 #endif//__DEBUG_EVENT_HANDLER__
+
+               if (g_pGesture->stylusInfo.pen_detected == FALSE)
+               {
+                       if (!isStylus)
+                       {
+                               GestureRegisterTouchInfo(ev, device);
+                       }
+                       else
+                       {
+                               GestureCleanupTouch(screen_num, ev, device);
+                       }
+               }
+               if (g_pGesture->stylusInfo.pen_detected == TRUE)
+               {
+                       if (!isStylus || (device->id != g_pGesture->stylusInfo.stylus_id ))
+                       {
+                               if (!(g_pGesture->stylusInfo.stylus_id == g_pGesture->first_fingerid && device->id == g_pGesture->master_pointer->id))
+                               {
+                                       return;
+                               }
+                       }
+                       else if (device->id != g_pGesture->first_fingerid)
+                       {
+                               GestureChangeEventToFirstFingerEvent(screen_num, ev, device);
+                               return;
+                       }
+               }
+       }
+
        switch( g_pGesture->ehtype )
        {
                case KEEP_EVENTS:
@@ -4892,7 +5152,12 @@ GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr de
                                if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL))
                                        GestureRecognize(ET_ButtonPress, ev, device);
                                if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL))
-                                       GesturePalmRecognize(ET_ButtonPress, ev, device);
+                               {
+                                       if (PalmRecognize)
+                                               _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_ButtonPress, ev, device)
+                                       else
+                                               g_pGesture->ehtype = PROPAGATE_EVENTS;
+                               }
                        }
                        else
                                device->public.processInputProc(ev, device);
@@ -4902,7 +5167,14 @@ GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr de
                case PROPAGATE_EVENTS:
                        if(!(device->id < g_pGesture->first_fingerid))
                                g_pGesture->num_pressed++;
-                       device->public.processInputProc(ev, device);
+                       if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->stylusInfo.pen_detected == TRUE)
+                       {
+                               device->public.processInputProc(ev, device);
+                       }
+                       else if (!(g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE))
+                       {
+                               device->public.processInputProc(ev, device);
+                       }
                        GestureHoldDetector(ET_ButtonPress, ev, device);
                        break;
 
@@ -4916,7 +5188,10 @@ GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr de
                        if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL))
                                GestureRecognize(ET_ButtonPress, ev, device);
                        if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL))
-                               GesturePalmRecognize(ET_ButtonPress, ev, device);
+                       {
+                               if (PalmRecognize)
+                                       _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_ButtonPress, ev, device);
+                       }
                        break;
 
                default:
@@ -4928,9 +5203,46 @@ void
 GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
 #ifdef __DEBUG_EVENT_HANDLER__
-       XDBG_DEBUG(MGEST, "devid=%d time:%d cur: %d\n", device->id, ev->any.time, GetTimeInMillis());
+       XDBG_DEBUG(MGEST, "mode: %d devid=%d time:%d cur: %d (%d, %d)\n",
+               g_pGesture->ehtype, device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
+#endif//__DEBUG_EVENT_HANDLER__
+
+       if (g_pGesture->stylus_able)
+       {
+               int isStylus = GestureGetMTToolValuator(ev, device);
+
+#ifdef __DEBUG_EVENT_HANDLER__
+                       XDBG_DEBUG(MGEST, "isSytlus: %d, pen_detected: %d, stylus_id: %d\n", isStylus, g_pGesture->stylusInfo.pen_detected, g_pGesture->stylusInfo.stylus_id);
 #endif//__DEBUG_EVENT_HANDLER__
 
+               if (g_pGesture->stylusInfo.pen_detected == FALSE)
+               {
+                       if (!isStylus)
+                       {
+                               GestureRegisterTouchInfo(ev, device);
+                       }
+                       else
+                       {
+                               GestureCleanupTouch(screen_num, ev, device);
+                       }
+               }
+               if (g_pGesture->stylusInfo.pen_detected == TRUE)
+               {
+                       if (!isStylus || (device->id != g_pGesture->stylusInfo.stylus_id ))
+                       {
+                               if (!(g_pGesture->stylusInfo.stylus_id == g_pGesture->first_fingerid && device->id == g_pGesture->master_pointer->id))
+                               {
+                                       return;
+                               }
+                       }
+                       else if (device->id != g_pGesture->first_fingerid)
+                       {
+                               GestureChangeEventToFirstFingerEvent(screen_num, ev, device);
+                               return;
+                       }
+               }
+       }
+
        switch( g_pGesture->ehtype )
        {
                case KEEP_EVENTS:
@@ -4948,7 +5260,12 @@ GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
                                if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL))
                                        GestureRecognize(ET_Motion, ev, device);
                                if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL))
-                                       GesturePalmRecognize(ET_Motion, ev, device);
+                               {
+                                       if (PalmRecognize)
+                                               _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_Motion, ev, device)
+                                       else
+                                               g_pGesture->ehtype = PROPAGATE_EVENTS;
+                               }
                        }
                        else
                                device->public.processInputProc(ev, device);
@@ -4956,7 +5273,14 @@ GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
                        break;
 
                case PROPAGATE_EVENTS:
-                       device->public.processInputProc(ev, device);
+                       if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->stylusInfo.pen_detected == TRUE)
+                       {
+                               device->public.processInputProc(ev, device);
+                       }
+                       else if (!(g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE))
+                       {
+                               device->public.processInputProc(ev, device);
+                       }
                        GestureHoldDetector(ET_Motion, ev, device);
                        break;
 
@@ -4968,7 +5292,10 @@ GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
                        if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL))
                                GestureRecognize(ET_Motion, ev, device);
                        if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL))
-                               GesturePalmRecognize(ET_Motion, ev, device);
+                       {
+                               if (PalmRecognize)
+                                       _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_Motion, ev, device);
+                       }
                        break;
 
                default:
@@ -4981,8 +5308,50 @@ void
 GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
 #ifdef __DEBUG_EVENT_HANDLER__
-       XDBG_DEBUG(MGEST, "devid=%d time:%d cur: %d\n", device->id, ev->any.time, GetTimeInMillis());
+       XDBG_DEBUG(MGEST, "mode: %d devid=%d time:%d cur: %d (%d, %d)\n",
+               g_pGesture->ehtype, device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
+#endif//__DEBUG_EVENT_HANDLER__
+
+       if (g_pGesture->stylus_able)
+       {
+               int isStylus = GestureGetMTToolValuator(ev, device);
+
+#ifdef __DEBUG_EVENT_HANDLER__
+       XDBG_DEBUG(MGEST, "isSytlus: %d, pen_detected: %d, stylus_id: %d\n", isStylus, g_pGesture->stylusInfo.pen_detected, g_pGesture->stylusInfo.stylus_id);
 #endif//__DEBUG_EVENT_HANDLER__
+
+               if (g_pGesture->stylusInfo.pen_detected == FALSE)
+               {
+                       if (!isStylus)
+                       {
+                               GestureRegisterTouchInfo(ev, device);
+                       }
+                       else
+                       {
+                               GestureCleanupTouch(screen_num, ev, device);
+                       }
+               }
+               if (g_pGesture->stylusInfo.pen_detected == TRUE)
+               {
+                       if (g_pGesture->stylusInfo.fake_events == TRUE)
+                       {
+                               goto deliver_event;
+                       }
+                       if (!isStylus || (device->id != g_pGesture->stylusInfo.stylus_id ))
+                       {
+                               if (!(g_pGesture->stylusInfo.stylus_id == g_pGesture->first_fingerid && device->id == g_pGesture->master_pointer->id))
+                               {
+                                       return;
+                               }
+                       }
+                       else if (device->id != g_pGesture->first_fingerid)
+                       {
+                               GestureChangeEventToFirstFingerEvent(screen_num, ev, device);
+                               return;
+                       }
+               }
+       }
+deliver_event:
        switch( g_pGesture->ehtype )
        {
                case KEEP_EVENTS:
@@ -5002,7 +5371,12 @@ GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr
                                if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL))
                                        GestureRecognize(ET_ButtonRelease, ev, device);
                                if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL))
-                                       GesturePalmRecognize(ET_ButtonRelease, ev, device);
+                               {
+                                       if (PalmRecognize)
+                                               _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_ButtonRelease, ev, device)
+                                       else
+                                               g_pGesture->num_mt_devices = PROPAGATE_EVENTS;
+                               }
                        }
                        else
                                device->public.processInputProc(ev, device);
@@ -5010,9 +5384,45 @@ GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr
                        break;
 
                case PROPAGATE_EVENTS:
+#ifdef SUPPORT_ANR_WITH_INPUT_EVENT
+                     if( IsMaster(device) && ev->any.type == ET_ButtonRelease )
+                     {
+                         if( g_pGesture->anr_window == NULL )
+                         {
+                             g_pGesture->anr_window = _GestureFindANRWindow(device);
+                         }
+                         Time current_time;
+
+                         // Send event to the e17 process.
+                         current_time = GetTimeInMillis();
+                         if( g_pGesture->anr_window != NULL )
+                         {
+                             // Check anr_window validation.
+                             if( dixLookupWindow(&g_pGesture->anr_window, prop_anr_event_window_xid, serverClient, DixSetPropAccess) != BadWindow )
+                             {
+                                 if( serverClient->devPrivates != NULL )
+                                     dixChangeWindowProperty (serverClient, g_pGesture->anr_window, prop_anr_in_input_event,
+                                                                               XA_CARDINAL, 32, PropModeReplace, 1, &current_time, TRUE);
+                             }
+                             else
+                             {
+                                 prop_anr_event_window_xid = 0;
+                                 g_pGesture->anr_window = NULL;
+                             }
+                             XDBG_DEBUG(MGEST, "Release TOUCH!!   devid=%d time:%d cur: %d\n", device->id, ev->any.time, GetTimeInMillis());
+                         }
+                     }
+#endif
                        if(!(device->id < g_pGesture->first_fingerid))
                                g_pGesture->num_pressed--;
-                       device->public.processInputProc(ev, device);
+                       if (g_pGesture->palm_rejection_mode == 1 && g_pGesture->stylusInfo.pen_detected == TRUE)
+                       {
+                               device->public.processInputProc(ev, device);
+                       }
+                       else if (!(g_pGesture->palm_rejection_mode == 1 && g_pGesture->palm_detected == TRUE))
+                       {
+                               device->public.processInputProc(ev, device);
+                       }
                        GestureHoldDetector(ET_ButtonRelease, ev, device);
                        break;
 
@@ -5026,7 +5436,10 @@ GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr
                        if(!(g_pGesture->filter_mask == GESTURE_FILTER_MASK_ALL))
                                GestureRecognize(ET_ButtonRelease, ev, device);
                        if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL))
-                               GesturePalmRecognize(ET_ButtonRelease, ev, device);
+                       {
+                               if (PalmRecognize)
+                                       _GESTUREPALMRECOGNIZE_(PalmRecognize, ET_ButtonRelease, ev, device);
+                       }
                        break;
 
                default:
@@ -5040,6 +5453,7 @@ GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr devic
 #ifdef __DEBUG_EVENT_HANDLER__
        XDBG_DEBUG(MGEST, "devid=%d time:%d cur:%d\n", device->id, ev->any.time, GetTimeInMillis());
 #endif//__DEBUG_EVENT_HANDLER__
+       static int find_dev_false_count = 0;
 
        if(DPMSPowerLevel == DPMSModeOff)
        {
@@ -5065,16 +5479,46 @@ GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr devic
        }
 
 handle_keypress:
+       if (g_pGesture->touchkey_id <= 0 && find_dev_false_count < 10)
+       {
+               DeviceIntPtr dev;
+               find_dev_false_count++;
+
+               for( dev = inputInfo.keyboard ; dev; dev = dev->next )
+               {
+                       if(strcasestr(dev->name, "touchkey"))
+                       {
+                               g_pGesture->touchkey_id = dev->id;
+                               find_dev_false_count = 0;
+                               break;
+                       }
+               }
+       }
 
        if((g_pGesture->mtsync_status != MTOUCH_FRAME_SYNC_END) && (device->id == g_pGesture->touchkey_id))
        {
-               XDBG_SECURE(MGEST, "Ignore TouchKey KeyPress (devid:%d, keycode:%d)\n", device->id, ev->device_event.detail.key);
+               if(ev->device_event.detail.key == 177)
+                       XDBG_INFO(MGEST, "Ignore TouchKey KEY_MENU (devid:%d)\n", device->id);
+               else if (ev->device_event.detail.key == 166)
+                       XDBG_INFO(MGEST, "Ignore TouchKey KEY_BACK (devid:%d)\n", device->id);
+               else
+                       XDBG_SECURE(MGEST, "Ignore TouchKey KeyPress (devid:%d, keycode:%d)\n", device->id, ev->device_event.detail.key);
                return;
        }
 
        device->public.processInputProc(ev, device);
 }
 
+void
+GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
+{
+       if (g_pGesture->pass_keycodes[3] == ev->device_event.detail.key)
+       {
+               XDBG_SECURE(MGEST, "TIME = %d, keycode = %d\n", ev->any.time, ev->device_event.detail.key);
+       }
+    device->public.processInputProc(ev, device);
+}
+
 static ErrorStatus
 GestureEnableEventHandler(InputInfoPtr pInfo)
  {
@@ -5105,14 +5549,6 @@ GestureEnableEventHandler(InputInfoPtr pInfo)
                goto failed;
        }
 
-       pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 5000, GestureTimerHandler, pInfo);
-
-       if( !pGesture->device_setting_timer )
-       {
-               XDBG_ERROR(MGEST, "Failed to allocate memory for timer !\n");
-               goto failed;
-       }
-
        return ERROR_NONE;
 
 failed:
@@ -5128,6 +5564,7 @@ GestureDisableEventHandler(void)
        ErrorStatus err = ERROR_NONE;
 
        mieqSetHandler(ET_KeyPress, NULL);
+       mieqSetHandler(ET_KeyRelease, NULL);
        mieqSetHandler(ET_ButtonPress, NULL);
        mieqSetHandler(ET_ButtonRelease, NULL);
        mieqSetHandler(ET_Motion, NULL);
@@ -5146,14 +5583,24 @@ GestureDisableEventHandler(void)
        return err;
 }
 
-static CARD32
-GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
+static void
+GestureRegisterDeviceInfo(DeviceIntPtr device)
 {
-       InputInfoPtr pInfo = (InputInfoPtr)arg;
+       InputInfoPtr  pInfo = device->public.devicePrivate;
        GestureDevicePtr pGesture = pInfo->private;
-
-       int idx = 0;
        DeviceIntPtr dev;
+       ScreenPtr pScreen = miPointerCurrentScreen();
+       int width = 0, height = 0;
+       int idx = 0;
+       int i;
+
+       XDBG_INFO(MGEST, "Get devices information\n");
+
+       for (i=0; i<MAX_MT_DEVICES; i++)
+       {
+               pGesture->mt_devices[i] = NULL;
+       }
+
        for( dev = inputInfo.pointer ; dev; dev = dev->next )
        {
                if(IsMaster(dev) && IsPointerDevice(dev))
@@ -5178,45 +5625,38 @@ GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
                                        MAX_MT_DEVICES);
                                continue;
                        }
-                       pGesture->mt_devices[idx] = dev;
-                       XDBG_INFO(MGEST, "[id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
-                       GesturePalmGetAbsAxisInfo(dev);
-                       idx++;
-               }
-       }
-
-       for( dev = inputInfo.keyboard ; dev; dev = dev->next )
-       {
-               if(strcasestr(dev->name, "touchkey"))
-               {
-                       g_pGesture->touchkey_id = dev->id;
-                       break;
+                       if (strcasestr(dev->name, "Touchscreen"))
+                       {
+                               pGesture->mt_devices[idx] = dev;
+                               XDBG_INFO(MGEST, "[id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
+                               ErrorF("[id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
+                               GesturePalmGetAbsAxisInfo(dev);
+                               idx++;
+                       }
                }
        }
 
        if( !pGesture->master_pointer || !pGesture->xtest_pointer )
        {
                XDBG_ERROR(MGEST, "Failed to get info of master pointer or XTest pointer !\n");
-               pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
                pGesture->num_mt_devices = 0;
 
-               return 0;
+               return;
        }
 
-       pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
        pGesture->num_mt_devices = idx;
 
        if( !pGesture->num_mt_devices )
        {
                XDBG_ERROR(MGEST, "Failed to mt device information !\n");
-               pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
                pGesture->num_mt_devices = 0;
        pGesture->first_fingerid = -1;
-               return 0;
+               return;
        }
 
        pGesture->first_fingerid = pGesture->mt_devices[0]->id;
        memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
+
        pGesture->pRootWin = RootWindow(pGesture->master_pointer);
 
        if(g_pGesture->palm_misc.enabled)
@@ -5231,20 +5671,30 @@ GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
                goto failed;
        }
 
+       if (pScreen)
+       {
+               pGesture->screen_width = pScreen->width;
+               pGesture->screen_height = pScreen->height;
+               XDBG_ERROR(MGEST, "screen_width = %d, screen_height = %d\n", pGesture->screen_width, pGesture->screen_height);
+       }
+       else
+       {
+               XDBG_ERROR(MGEST, "Fail to get current screen size\n");
+       }
+
        mieqSetHandler(ET_KeyPress, GestureHandleKeyPressEvent);
+       mieqSetHandler(ET_KeyRelease, GestureHandleKeyReleaseEvent);
        mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
        mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
        mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
        mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
 
-       return 0;
+       return;
 
 failed:
 
        GestureUninstallResourceStateHooks();
        GestureUnsetMaxNumberOfFingers();
-
-       return 0;
 }
 
 BOOL
@@ -5428,10 +5878,6 @@ GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
                }
                if(!(g_pGesture->palm_filter_mask == GESTURE_PALM_FILTER_MASK_ALL))
                {
-                       if(!(g_pGesture->palm_filter_mask & PalmHoldFilterMask))
-                       {
-                               GesturePalmRecognize_Hold(ev->any.type, 0, 0);
-                       }
                        if(!(g_pGesture->palm_filter_mask & PalmFlickHorizFilterMask))
                        {
                                GesturePalmRecognize_FlickHorizen(ev->any.type, 0);
@@ -5510,6 +5956,7 @@ GestureEventsFlush(void)
                if(g_pGesture->EQ[i].event->any.type != ET_Motion)
                        XDBG_DEBUG(MGEST, "[%d] type: %d\n", device->id, g_pGesture->EQ[i].event->any.type);
 #endif//__DETAIL_DEBUG__
+
                for(j = 0 ; j < MAX_MT_DEVICES+1 ; j++)
                {
                        if(g_pGesture->palm.qti[j].devid == device->id)
@@ -5575,6 +6022,11 @@ GestureInitProperty(DeviceIntPtr dev)
 {
        int rc;
 
+#ifdef SUPPORT_ANR_WITH_INPUT_EVENT
+       prop_anr_in_input_event = MakeAtom(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT, strlen(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT),  TRUE);
+       prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE);
+#endif
+
        prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
        rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
 
@@ -5582,6 +6034,14 @@ GestureInitProperty(DeviceIntPtr dev)
                return;
 
        XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
+
+       prop_gesture_palm_rejection_mode = MakeAtom(GESTURE_PALM_REJECTION_MODE, strlen(GESTURE_PALM_REJECTION_MODE), TRUE);
+       rc = XIChangeDeviceProperty(dev, prop_gesture_palm_rejection_mode, XA_INTEGER, 8, PropModeReplace, 1, &g_pGesture->palm_rejection_mode, FALSE);
+
+       if (rc != Success)
+               return;
+
+       XISetDevicePropertyDeletable(dev, prop_gesture_palm_rejection_mode, FALSE);
 }
 
 static int
@@ -5600,6 +6060,60 @@ GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
                        GestureEnable(data, TRUE, dev);
                }
        }
+       else if( prop_gesture_palm_rejection_mode == atom)
+       {
+               int data;
+               if( val->format != 8 || val->type != XA_INTEGER || val->size != 1 )
+                       return BadMatch;
+
+               if( !checkonly )
+               {
+                       int ret;
+                       data = *((BOOL*)val->data);
+                       int fd, fd_result;
+                       char buf[128];
+
+                       g_pGesture->palm_rejection_mode = (int)data;
+
+                       fd = open("/sys/class/sec/tsp/cmd", O_WRONLY);
+                       if (fd < 0)
+                       {
+                               XDBG_ERROR(MGEST, "failed to open tsp node(%d)\n", fd);
+                               return Success;
+                       }
+
+                       sprintf(buf, "stylus_enable,%d", !!(g_pGesture->palm_rejection_mode));
+                       XDBG_DEBUG(MGEST, "stylus_changed: %d!\n", !!(g_pGesture->palm_rejection_mode));
+
+                       ret = write(fd, buf, strlen(buf));
+                       if (ret <= 0)
+                       {
+                               XDBG_WARNING(MGEST, "failed to stylus_changed: %d\n", !!(g_pGesture->palm_rejection_mode));
+                       }
+
+                       close(fd);
+
+                       fd_result = open("/sys/class/sec/tsp/cmd_result", O_RDONLY);
+                       if (fd_result < 0)
+                       {
+                               XDBG_ERROR(MGEST, "failed to open tsp node(%d)\n", fd_result);
+                               return Success;
+                       }
+
+                       memset(buf, 0L, sizeof(buf));
+
+                       ret = read(fd_result, buf, sizeof(buf));
+                       if (ret <= 0)
+                       {
+                               XDBG_WARNING(MGEST, "failed to read cmd_result\n");
+                       }
+                       else
+                       {
+                               ErrorF("stylus mode result: %s\n", buf);
+                       }
+                       close(fd_result);
+               }
+       }
 
        return Success;
 }
@@ -5608,9 +6122,6 @@ GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
 static int
 GestureInit(DeviceIntPtr device)
 {
-       InputInfoPtr pInfo;
-       pInfo = device->public.devicePrivate;
-
 #ifdef HAVE_PROPERTIES
        GestureInitProperty(device);
        XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
@@ -5663,6 +6174,19 @@ GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
     /* process driver specific options */
     pGesture->device = xf86SetStrOption(pInfo->options, "Device", "/dev/null");
     pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0);
+       pGesture->stylus_able = xf86SetIntOption(pInfo->options, "Stylus", 0);
+       pGesture->support_palm = xf86SetIntOption(pInfo->options, "SupportPalm", 0);
+
+       if (pGesture->support_palm)
+       {
+               PalmRecognize = GesturePalmRecognize;
+               XDBG_DEBUG(MGEST, "Palm Support !!\n");
+       }
+       else
+       {
+               PalmRecognize = NULL;
+               XDBG_DEBUG(MGEST, "No Palm Support !!\n");
+       }
 
     {
        int i;
@@ -5679,6 +6203,7 @@ GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
     }
 
     pGesture->gestureWin = None;
+
 #ifdef _F_SUPPORT_BEZEL_FLICK_
     pBezel = &pGesture->bezel;
     pBezel->is_active = xf86SetIntOption(pInfo->options, "Bezel_Activate", 0);
@@ -5709,6 +6234,12 @@ GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
        pGesture->singletap_threshold = xf86SetIntOption(pInfo->options, "SingleTapThresHold", SGL_TAP_TIME_THRESHOLD);
        pGesture->doubletap_threshold = xf86SetIntOption(pInfo->options, "DoubleTapThresHold", DBL_TAP_TIME_THRESHOLD);
 
+       pGesture->palm_min_touch_major = xf86SetIntOption(pInfo->options, "PalmMinTouchMajor", PALM_MIN_TOUCH_MAJOR);
+       pGesture->palm_min_width_major = xf86SetIntOption(pInfo->options, "PalmMinWidthMajor", PALM_MIN_WIDTH_MAJOR);
+       pGesture->palm_min_touch_major_bezel = xf86SetIntOption(pInfo->options, "PalmMinTouchMajorBezel", PALM_MIN_TOUCH_MAJOR_BEZEL);
+       pGesture->palm_min_width_major_bezel = xf86SetIntOption(pInfo->options, "PalmMinWidthMajorBezel", PALM_MIN_WIDTH_MAJOR_BEZEL);
+       pGesture->palm_bezel = xf86SetIntOption(pInfo->options, "PalmBezel", PALM_BEZEL);
+
        if (pGesture->is_active)
                pGesture->ehtype = KEEP_EVENTS;
        else
@@ -5750,6 +6281,13 @@ GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
        g_pGesture->zoom_enabled = 0;
        memset(g_pGesture->palm.qti, 0, sizeof(g_pGesture->palm.qti[MAX_MT_DEVICES+1]));
 
+       g_pGesture->palm_rejection_mode = 0;
+       g_pGesture->palm_detected = FALSE;
+
+       memset(g_pGesture->stylusInfo.t_status, 0, sizeof(g_pGesture->stylusInfo.t_status[MAX_MT_DEVICES]));
+       g_pGesture->stylusInfo.stylus_id = 0;
+       g_pGesture->stylusInfo.pen_detected = FALSE;
+
     return Success;
 
 error:
@@ -5812,6 +6350,9 @@ device_off:
       case DEVICE_CLOSE:
             /* free what we have to free */
             break;
+      case DEVICE_READY:
+            GestureRegisterDeviceInfo(device);
+            break;
     }
     return Success;
 }
index 1e737c4..1c8b83c 100755 (executable)
@@ -45,6 +45,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define ABS_CNT (ABS_MAX+1)
 #endif
 
+/**
+ * If there's touch event in pointed window and there's no reponse, we just assume that client looks like deadlock.
+ * In this case, we will make a popup window and terminate application.
+ * To support this feature, we use SUPPORT_ANR_WITH_INPUT_EVENT flag.
+ */
+#define SUPPORT_ANR_WITH_INPUT_EVENT
+
 #define NUM_PASSKEYS   20
 
 #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
@@ -56,6 +63,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define GESTURE_EQ_SIZE        256
 
 #define GESTURE_RECOGNIZER_ONOFF       "GESTURE_RECOGNIZER_ONOFF"
+#define GESTURE_PALM_REJECTION_MODE    "GESTURE_PALM_REJECTION_MODE"
+#define CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT "_CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT_"
+#define ANR_EVENT_WINDOW "_ANR_EVENT_WINDOW_"
 
 #define FINGER_WIDTH           10
 #define FINGER_HEIGHT          10
@@ -99,6 +109,13 @@ enum
        FLICK_NORTHWESTWARD
 };
 
+/* Gesture query devices infomation and register handlers
+  * if a device_control function is called using DEVICE_READY */
+#define DEVICE_READY 11
+
+#define SCREEN_WIDTH                           720
+#define SCREEN_HEIGHT                          1280
+
 #define PAN_AREA_THRESHOLD                     10000//=100pixel * 100pixel
 #define PAN_MOVE_THRESHOLD                     5//pixel
 #define PAN_UPDATE_MOVE_THRESHOLD      3//pixel
@@ -114,12 +131,12 @@ enum
 #define HOLD_MOVE_THRESHOLD                    10//pixel
 #define HOLD_TIME_THRESHOLD                    500//ms
 
-#define TAP_AREA_THRESHOLD                     10000//= 100pixel * 100pixel
-#define TAP_MOVE_THRESHOLD                     200//pixel
+#define TAP_AREA_THRESHOLD                     30000//= 300pixel * 100pixel
+#define TAP_MOVE_THRESHOLD                     300//pixel
 #define SGL_FINGER_TIME_THRESHOLD      50//ms
 #define SGL_TAP_TIME_THRESHOLD         200//ms
 #define DBL_TAP_TIME_THRESHOLD         400//ms
-#define MAX_TAP_REPEATS                                3
+#define MAX_TAP_REPEATS                                2
 
 #define TAPNHOLD_AREA_THRESHOLD                        4900//= 70pixel * 70pixel
 #define TAPNHOLD_MOVE_THRESHOLD                        50//pixel
@@ -409,11 +426,10 @@ enum
 
 #define GESTURE_FILTER_MASK_ALL        0x3f//(FlickFilterMask | PanFilterMask | PinchRotationFilterMask | TapFilterMask |TapNHoldFilterMask | HoldFilterMask)
 
-#define PalmHoldFilterMask                             0x01//(1 << 0)
-#define PalmFlickHorizFilterMask               0x02//(1 << 1)
-#define PalmFlickVertiFilterMask               0x04//(1 << 2)
+#define PalmFlickHorizFilterMask               0x01//(1 << 0)
+#define PalmFlickVertiFilterMask               0x02//(1 << 1)
 
-#define GESTURE_PALM_FILTER_MASK_ALL   0x07//(PalmHoldFilterMask | PalmFlickHorizFilterMask | PalmFlickVertiFilterMask)
+#define GESTURE_PALM_FILTER_MASK_ALL   0x03//(PalmFlickHorizFilterMask | PalmFlickVertiFilterMask)
 
 #ifdef _F_SUPPORT_BEZEL_FLICK_
 #define BezelFlickFilterMask           0x01//(1 << 0)
@@ -443,6 +459,13 @@ typedef struct _tagCurrentTouchStatus
        int cy;         //current y
 } CurTouchStatus;
 
+//palm global
+#define PALM_MIN_TOUCH_MAJOR                           30
+#define PALM_MIN_WIDTH_MAJOR                           40
+#define PALM_MIN_TOUCH_MAJOR_BEZEL                     16
+#define PALM_MIN_WIDTH_MAJOR_BEZEL                     24
+#define PALM_BEZEL                                                     33
+
 //palm flick
 #define PALM_FLICK_INITIAL_TIMEOUT                     300//ms
 #define PALM_FLICK_FALSE_TIMEOUT                       900//ms
@@ -456,7 +479,7 @@ typedef struct _tagCurrentTouchStatus
 #define PALM_FALSE_FLICK_BASE_WIDTH                    8
 #define PALM_FLICK_TOUCH_MAJOR                         80
 #define PALM_FLICK_FINGER_MIN_TOUCH_MAJOR      15
-#define PALM_FLICK_HORIZ_MAX_MOVE_Y                    300
+#define PALM_FLICK_HORIZ_MAX_MOVE_Y                    400
 #define PALM_FLICK_VERTI_MAX_MOVE_X                    300
 
 //palm tap
@@ -469,13 +492,6 @@ typedef struct _tagCurrentTouchStatus
 
 //palm hold
 #define PALM_HOLD_TIME_THRESHOLD                       150
-#define PALM_HOLD_UPDATE_THRESHOLD                     500
-#define PALM_HOLD_MIN_DEVIATION                                120
-#define PALM_HOLD_MIN_FINGER                           4
-#define PALM_HOLD_MIN_BASE_WIDTH                       400
-#define PALM_HOLD_FALSE_WIDTH                          10
-#define PALM_HOLD_FINGER_MIN_TOUCH_MAJOR       10
-#define PALM_HOLD_FINGER_MIN_WIDTH_MAJOR       15
 
 typedef struct _tagPalmTouchInfo
 {
@@ -537,6 +553,14 @@ typedef struct _tagPalmDrvStatus
        int verti_coord[PALM_VERTI_ARRAY_COUNT];
 } PalmMiscInfo, *PalmMiscInfoPtr;
 
+typedef struct _tagStylusStatus
+{
+       CurTouchStatus t_status[MAX_MT_DEVICES];
+       int stylus_id;
+       Bool pen_detected;
+       Bool fake_events;
+} StylusInfo, *StylusInfoPtr;
+
 #ifdef _F_SUPPORT_BEZEL_FLICK_
 typedef struct _tagBezelStatus
 {
@@ -569,6 +593,9 @@ typedef struct _GestureDeviceRec
 
        int is_active;
 
+       int screen_width;
+       int screen_height;
+
        int pinchrotation_time_threshold;
        double pinchrotation_dist_threshold;
        double pinchrotation_angle_threshold;
@@ -577,8 +604,18 @@ typedef struct _GestureDeviceRec
        int singletap_threshold;
        int doubletap_threshold;
 
+       int palm_min_touch_major;
+       int palm_min_width_major;
+       int palm_min_touch_major_bezel;
+       int palm_min_width_major_bezel;
+       int palm_bezel;
+
        int touchkey_id;
        MTSyncType mtsync_status;
+       StylusInfo stylusInfo;
+       int palm_rejection_mode;
+       Bool palm_detected;
+       Bool no_palm_events;
 
        int pass_keycodes[NUM_PASSKEYS];
 
@@ -601,6 +638,7 @@ typedef struct _GestureDeviceRec
        int has_hold_grabmask;
        pixman_region16_t chold_area;
        CurTouchStatus cts[MAX_MT_DEVICES];
+       Bool hold_detected;
 
        PalmStatus palm;
        PalmMiscInfo palm_misc;
@@ -611,6 +649,7 @@ typedef struct _GestureDeviceRec
        int tpalm_idx;
        int mt_px_idx;
        int mt_py_idx;
+       int mt_tool_idx;
 
        pixman_region16_t area;
        pixman_region16_t finger_rects[MAX_MT_DEVICES];
@@ -643,6 +682,10 @@ typedef struct _GestureDeviceRec
 #ifdef _F_SUPPORT_BEZEL_FLICK_
        BezelFlickStatus bezel;
 #endif
+    WindowPtr anr_window;
+
+    int stylus_able;
+    int support_palm;
 } GestureDeviceRec, *GestureDevicePtr ;
 
 #endif//_GESTURE_H_
index 9cae527..52f87ab 100644 (file)
@@ -1,8 +1,8 @@
 #sbs-git:slp/pkgs/xorg/driver/xserver-xorg-input-gesture xorg-x11-drv-gesture 0.1.0 fb1092a8ea453d658b38d5c28e67a58462d7c931
 Name:  xorg-x11-drv-gesture
 Summary:    X.Org X server -- Xserver gesture driver
-Version: 0.1.29
-Release:    7
+Version: 0.1.55
+Release:    1
 VCS:        adaptation/xorg/driver/xserver-xorg-input-gesture#xorg-x11-drv-gesture-0.1.2-8-6-g7c67de9af10190753599a01144e865bf0a341604
 Group:      System/X Hardware Support
 License:    MIT
@@ -13,7 +13,8 @@ BuildRequires:  pkgconfig(xproto)
 BuildRequires:  pkgconfig(inputproto)
 BuildRequires:  pkgconfig(resourceproto)
 BuildRequires:  pkgconfig(xorg-macros)
-%if "%{_repository}" == "mobile"
+BuildRequires:  pkgconfig(dlog)
+%if "%{?tizen_profile_name}" == "mobile"
 BuildRequires:  pkgconfig(xdbg)
 %endif
 
@@ -35,7 +36,7 @@ xorg-x11-drv-gesture development files
 
 %build
 
-%if "%{_repository}" == "wearable"
+%if "%{?tizen_profile_name}" == "wearable"
 cd wearable
 %else
 cd mobile
@@ -48,7 +49,7 @@ make %{?jobs:-j%jobs}
 
 %install
 
-%if "%{_repository}" == "wearable"
+%if "%{?tizen_profile_name}" == "wearable"
 cd wearable
 %else
 cd mobile
index c36e7f8..109646d 100644 (file)
@@ -54,7 +54,7 @@ AC_SUBST(inputdir)
 
 # Checks for pkg-config packages. We need to be able to override sdkdir
 # to satisfy silly distcheck requirements.
-PKG_CHECK_MODULES(XORG, xorg-server xproto $REQUIRED_MODULES)
+PKG_CHECK_MODULES(XORG, xorg-server xproto dlog $REQUIRED_MODULES)
 XORG_CFLAGS="$CWARNFLAGS $XORG_CFLAGS"
 AC_ARG_WITH([sdkdir], [],
     [sdkdir="$withval"],
index eab747f..31cef63 100755 (executable)
@@ -58,6 +58,30 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #endif
 
+//#define __DETAIL_DEBUG__
+//#define __DEBUG_EVENT_HANDLER__
+//#define __PalmFlick_DEBUG__
+//#define __HOLD_DETECTOR_DEBUG__
+
+#ifdef __PalmFlick_DEBUG__
+#define PalmFlickDebugPrint ErrorF
+#else
+#define PalmFlickDebugPrint(...)
+#endif
+
+#ifdef __HOLD_DETECTOR_DEBUG__
+#define HoldDetectorDebugPrint ErrorF
+#else
+#define HoldDetectorDebugPrint(...)
+#endif
+
+
+#ifdef __DETAIL_DEBUG__
+#define DetailDebugPrint ErrorF
+#else
+#define DetailDebugPrint(...)
+#endif
+
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
@@ -72,7 +96,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "gesture.h"
 #include <xorg/mi.h>
 
+#define LOG_TAG        "GESTURE"
+#include "dlog.h"
+
+
+
 char *strcasestr(const char *s, const char *find);
+extern ScreenPtr miPointerCurrentScreen(void);
 static void printk(const char* fmt, ...) __attribute__((format(printf, 1, 0)));
 
 //Basic functions
@@ -117,7 +147,9 @@ void GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPt
 void GestureEmulateHWKey(DeviceIntPtr dev, int keycode);
 
 //Gesture recognizer helper
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21
 static Bool PointInBorderSize(WindowPtr pWin, int x, int y);
+#endif
 static WindowPtr GestureWindowOnXY(int x, int y);
 Bool GestureHasFingerEventMask(int eventType, int num_finger);
 
@@ -126,11 +158,18 @@ void GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device);
 void GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
 void GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int start_point, int direction);
 void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired);
+void GestureRecognize_PalmFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx);
 void GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction);
 void GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy);
 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds);
 ErrorStatus GestureFlushOrDrop(void);
 
+static int GestureGetPalmValuator(InternalEvent *ev, DeviceIntPtr device);
+static int GesturePalmGetAbsAxisInfo(DeviceIntPtr dev);
+static void GestureHoldDetector(int type, InternalEvent *ev, DeviceIntPtr device);
+static int GesturePalmGetScreenInfo();
+static int GesturePalmGetHorizIndexWithX(int current_x, int idx, int type);
+
 #ifdef HAVE_PROPERTIES
 //function related property handling
 static void GestureInitProperty(DeviceIntPtr dev);
@@ -139,6 +178,13 @@ static int GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr va
 
 static Atom prop_gesture_recognizer_onoff = None;
 
+#ifdef SUPPORT_ANR_WITH_INPUT_EVENT
+static Atom prop_anr_in_input_event = None;
+static Atom prop_anr_event_window = None;
+static Window prop_anr_event_window_xid = None;
+#endif
+
+
 GestureDevicePtr g_pGesture = NULL;
 _X_EXPORT InputDriverRec GESTURE = {
     1,
@@ -175,33 +221,72 @@ _X_EXPORT XF86ModuleData gestureModuleData =
 static void
 printk(const char* fmt, ...)
 {
-       static FILE* fp = NULL;
-       static char init = 0;
-       va_list argptr;
-
-       if(!init && !fp)
-       {
-               fp = fopen("/dev/kmsg", "wt");
-               init = 1;
-       }
-
-       if(!fp) return;
-
-       va_start(argptr, fmt);
-       vfprintf(fp, fmt, argptr);
-       fflush(fp);
-       va_end(argptr);
+    static FILE* fp = NULL;
+    static char init = 0;
+    va_list argptr;
+
+    if (!init && !fp)
+    {
+        fp = fopen("/dev/kmsg", "wt");
+        init = 1;
+    }
+
+    if (!fp) return;
+
+    va_start(argptr, fmt);
+    vfprintf(fp, fmt, argptr);
+    fflush(fp);
+    va_end(argptr);
+}
+
+#ifdef SUPPORT_ANR_WITH_INPUT_EVENT
+static WindowPtr
+_GestureFindANRWindow(DeviceIntPtr device)
+{
+    WindowPtr root=NULL;
+    WindowPtr anr_window=NULL;
+    Window anr_xid=0;
+    PropertyPtr pProp;
+    int rc=0;
+
+    root = RootWindow(device);
+
+    if( prop_anr_event_window == None )
+        prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE);
+
+    rc = dixLookupProperty (&pProp, root, prop_anr_event_window, serverClient, DixReadAccess);
+    if (rc == Success && pProp->data){
+        anr_xid = *(int*)pProp->data;
+    }
+
+    if( anr_xid != 0 )
+    {
+        rc = dixLookupWindow(&anr_window, anr_xid, serverClient, DixSetPropAccess);
+        if( rc == BadWindow )
+        {
+            ErrorF("Can't find ANR window !!\n");
+            anr_window = NULL;
+        }
+        prop_anr_event_window_xid = anr_xid;
+    }
+
+    ErrorF("ANR Window is %#x. Ptr is %#x\n", anr_xid, anr_window);
+    return anr_window;
 }
+#endif
 
+#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 21
 static Bool
 PointInBorderSize(WindowPtr pWin, int x, int y)
 {
     BoxRec box;
-    if( pixman_region_contains_point (&pWin->borderSize, x, y, &box) )
-       return TRUE;
-
+    if (pixman_region_contains_point (&pWin->borderSize, x, y, &box))
+    {
+        return TRUE;
+    }
     return FALSE;
 }
+#endif
 
 static WindowPtr
 GestureWindowOnXY(int x, int y)
@@ -217,1416 +302,2467 @@ GestureWindowOnXY(int x, int y)
 
     while (pWin)
     {
-       if ((pWin->mapped) &&
-           (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
-           (x < pWin->drawable.x + (int)pWin->drawable.width +
-            wBorderWidth(pWin)) &&
-           (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
-           (y < pWin->drawable.y + (int)pWin->drawable.height +
-            wBorderWidth (pWin))
-           /* When a window is shaped, a further check
-            * is made to see if the point is inside
-            * borderSize
-            */
-           && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
-           && (!wInputShape(pWin) ||
-               RegionContainsPoint(wInputShape(pWin),
-                                   x - pWin->drawable.x,
-                                   y - pWin->drawable.y, &box))
+        if ((pWin->mapped) &&
+                (x >= pWin->drawable.x - wBorderWidth (pWin)) &&
+                (x < pWin->drawable.x + (int)pWin->drawable.width +
+                 wBorderWidth(pWin)) &&
+                (y >= pWin->drawable.y - wBorderWidth (pWin)) &&
+                (y < pWin->drawable.y + (int)pWin->drawable.height +
+                 wBorderWidth (pWin))
+                /* When a window is shaped, a further check
+                 * is made to see if the point is inside
+                 * borderSize
+                 */
+                && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
+                && (!wInputShape(pWin) ||
+                    RegionContainsPoint(wInputShape(pWin),
+                        x - pWin->drawable.x,
+                        y - pWin->drawable.y, &box))
 #ifdef ROOTLESS
-    /* In rootless mode windows may be offscreen, even when
-     * they're in X's stack. (E.g. if the native window system
-     * implements some form of virtual desktop system).
-     */
-               && !pWin->rootlessUnhittable
+                /* In rootless mode windows may be offscreen, even when
+                 * they're in X's stack. (E.g. if the native window system
+                 * implements some form of virtual desktop system).
+                 */
+                    && !pWin->rootlessUnhittable
 #endif
-           )
-       {
-           if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
-           {
-               pSprite->spriteTraceSize += 10;
-               pSprite->spriteTrace = realloc(pSprite->spriteTrace,
-                                   pSprite->spriteTraceSize*sizeof(WindowPtr));
-           }
-           pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
-           pWin = pWin->firstChild;
-       }
-       else
-           pWin = pWin->nextSib;
+                    )
+                    {
+                        if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
+                        {
+                            pSprite->spriteTraceSize += 10;
+                            pSprite->spriteTrace = realloc(pSprite->spriteTrace,
+                                    pSprite->spriteTraceSize*sizeof(WindowPtr));
+                        }
+                        pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
+                        pWin = pWin->firstChild;
+                    }
+        else
+            pWin = pWin->nextSib;
     }
     return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
 }
 
-Bool
+    Bool
 GestureHasFingerEventMask(int eventType, int num_finger)
 {
-       Bool ret = FALSE;
-       Mask eventmask = (1L << eventType);
+    Bool ret = FALSE;
+    Mask eventmask = (1L << eventType);
 
-       if( (g_pGesture->grabMask & eventmask) &&
-               (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[num_finger].window != None) )
-       {
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has grabMask\n");
-#endif//__DETAIL_DEBUG__
-               return TRUE;
-       }
+    if ((g_pGesture->grabMask & eventmask) &&
+            (g_pGesture->GrabEvents[eventType].pGestureGrabWinInfo[num_finger].window != None))
+    {
+        DetailDebugPrint("[GestureHasFingerEventMask] TRUE !! Has grabMask\n");
+        return TRUE;
+    }
 
-       if( g_pGesture->eventMask & eventmask )
-       {
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[X11][GestureHasFingerEventMask] TRUE !! Has eventMask\n");
-#endif//__DETAIL_DEBUG__
-               return TRUE;
-       }
+    if (g_pGesture->eventMask & eventmask)
+    {
+        DetailDebugPrint("[GestureHasFingerEventMask] TRUE !! Has eventMask\n");
+        return TRUE;
+    }
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger);
-#endif//__DETAIL_DEBUG__
+    DetailDebugPrint("[GestureHasFingerEventMask] FALSE !! eventType=%d, num_finger=%d\n", eventType, num_finger);
 
-       return ret;
+    return ret;
 }
 
 static CARD32
 GestureEventTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
 {
-       int event_type = *(int *)arg;
+    int event_type = *(int *)arg;
 
-       switch( event_type )
-       {
-               case GestureNotifyHold:
-#ifdef __DETAIL_DEBUG__
-                       ErrorF("[GestureEventTimerHandler] GestureNotifyHold (event_type = %d)\n", event_type);
-#endif//__DETAIL_DEBUG__
-                       GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1);
-                       break;
-               case GestureNotifyTap:
-#ifdef __DETAIL_DEBUG__
-                       ErrorF("[GestureEventTimerHandler] GestureNotifyTap (event_type = %d)\n", event_type);
-#endif//__DETAIL_DEBUG__
-                       GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1);
-                       break;
-               default:
-#ifdef __DETAIL_DEBUG__
-                       ErrorF("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type);
-#endif//__DETAIL_DEBUG__
-                       if(timer)
-                               ErrorF("[GestureEventTimerHandler] timer=%x\n", (unsigned int)timer);
-       }
+    switch (event_type)
+    {
+        case GestureNotifyHold:
+            DetailDebugPrint("[GestureEventTimerHandler] GestureNotifyHold (event_type = %d)\n", event_type);
+            GestureRecognize_GroupHold(event_type, NULL, NULL, 0, 1);
+            break;
+        case GestureNotifyTap:
+            DetailDebugPrint("[GestureEventTimerHandler] GestureNotifyTap (event_type = %d)\n", event_type);
+            GestureRecognize_GroupTap(event_type, NULL, NULL, 0, 1);
+            break;
+        default:
+            DetailDebugPrint("[GestureEventTimerHandler] unknown event_type (=%d)\n", event_type);
+            if (timer)
+            {
+                DetailDebugPrint("[GestureEventTimerHandler] timer=%x\n", (unsigned int)timer);
+            }
+    }
 
-       return 0;
+    return 0;
 }
 
 void
 GestureHandleGesture_Tap(int num_finger, int tap_repeat, int cx, int cy)
 {
-       Window target_win;
-       WindowPtr target_pWin;
-       xGestureNotifyTapEvent tev;
+    Window target_win;
+    WindowPtr target_pWin;
+    xGestureNotifyTapEvent tev;
 
-       //skip non-tap events and single finger tap
-       if( !tap_repeat || num_finger <= 1 )
-               return;
+    //skip non-tap events and single finger tap
+    if (!tap_repeat || num_finger <= 1)
+    {
+        return;
+    }
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n",
-               num_finger, tap_repeat, cx, cy);
-#endif//__DETAIL_DEBUG__
-
-       g_pGesture->recognized_gesture |= WTapFilterMask;
-       memset(&tev, 0, sizeof(xGestureNotifyTapEvent));
-       tev.type = GestureNotifyTap;
-       tev.kind = GestureDone;
-       tev.num_finger = num_finger;
-       tev.tap_repeat = tap_repeat;
-       tev.interval = 0;
-       tev.cx = cx;
-       tev.cy = cy;
-
-       target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window;
-       target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin;
-
-       if( g_pGesture->grabMask && (target_win != None) )
-       {
-               tev.window = target_win;
-       }
-       else
-       {
-               tev.window = g_pGesture->gestureWin;
-       }
-
-       ErrorF("[X11][GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)tev.window, (unsigned int)g_pGesture->grabMask);
-
-       GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev);
+    DetailDebugPrint("[GestureHandleGesture_Tap] num_finger=%d, tap_repeat=%d, cx=%d, cy=%d\n", num_finger, tap_repeat, cx, cy);
+
+    g_pGesture->recognized_gesture |= WTapFilterMask;
+    memset(&tev, 0, sizeof(xGestureNotifyTapEvent));
+    tev.type = GestureNotifyTap;
+    tev.kind = GestureDone;
+    tev.num_finger = num_finger;
+    tev.tap_repeat = tap_repeat;
+    tev.interval = 0;
+    tev.cx = cx;
+    tev.cy = cy;
+
+    target_win = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].window;
+    target_pWin = g_pGesture->GrabEvents[GestureNotifyTap].pGestureGrabWinInfo[num_finger].pWin;
+
+    if (g_pGesture->grabMask && (target_win != None))
+    {
+        tev.window = target_win;
+    }
+    else
+    {
+        tev.window = g_pGesture->gestureWin;
+    }
+
+    DetailDebugPrint("[GestureHandleGesture_Tap] tev.window=0x%x, g_pGesture->grabMask=0x%x\n", (unsigned int)tev.window, (unsigned int)g_pGesture->grabMask);
+
+    GestureSendEvent(target_pWin, GestureNotifyTap, GestureTapMask, (xGestureCommonEvent *)&tev);
+    LOGI("GroupTap Event done. 2 fingers %d tap!", tap_repeat);
 }
 
 void
 GestureHandleGesture_Flick(int num_of_fingers, int distance, Time duration, int direction)
 {
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n",
-               num_of_fingers, distance, duration, direction);
-#endif//__DETAIL_DEBUG__
-       switch(direction)
-       {
-               case FLICK_NORTHWARD:
-                       ErrorF("[X11][GestureHandleGesture_Flick] Flick Down \n");
-                       GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_down);
-                       break;
-
-               case FLICK_SOUTHWARD:
-                       ErrorF("[X11][GestureHandleGesture_Flick] Flick Up \n");
-                       GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_up);
-                       break;
-               case FLICK_WESTWARD:
-                       if(g_pGesture->power_pressed == 2)
-                       {
-                               ErrorF("[X11][GestureHandleGesture_Flick] Flick Right & power_pressed\n");
-                               GestureEmulateHWKey(g_pGesture->hwkey_dev, 122);
-                       }
-                       break;
-               default:
-                       break;
-       }
-       g_pGesture->recognized_gesture |= WFlickFilterMask;
+    if (num_of_fingers == 0)
+    {
+        Window target_win;
+        WindowPtr target_pWin;
+        xGestureNotifyFlickEvent fev;
+
+        DetailDebugPrint("[GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n", num_of_fingers, distance, duration, direction);
+
+        g_pGesture->recognized_gesture |= WPalmFlickFilterMask;
+
+        memset(&fev, 0, sizeof(xGestureNotifyFlickEvent));
+        fev.type = GestureNotifyFlick;
+        fev.kind = GestureDone;
+        fev.num_finger = num_of_fingers;
+        fev.distance = distance;
+        fev.duration = duration;
+        fev.direction = direction;
+
+        if (g_pGesture->GrabEvents)
+        {
+            target_win = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].window;
+            target_pWin = g_pGesture->GrabEvents[GestureNotifyFlick].pGestureGrabWinInfo[num_of_fingers].pWin;
+        }
+        else
+        {
+            target_win = None;
+            target_pWin = None;
+        }
+
+        if (g_pGesture->grabMask && (target_win != None))
+        {
+            fev.window = target_win;
+        }
+        else
+        {
+            fev.window = g_pGesture->gestureWin;
+        }
+
+        DetailDebugPrint("[GestureHandleGesture_Flick] fev.window=0x%x, g_pGesture->grabMask=0x%x\n", fev.window, g_pGesture->grabMask);
+
+        GestureSendEvent(target_pWin, GestureNotifyFlick, GestureFlickMask, (xGestureCommonEvent *)&fev);
+    }
+    else
+    {
+        DetailDebugPrint("[GestureHandleGesture_Flick] num_fingers=%d, distance=%d, duration=%d, direction=%d\n", num_of_fingers, distance, duration, direction);
+
+        switch (direction)
+        {
+            case FLICK_NORTHWARD:
+                DetailDebugPrint("[GestureHandleGesture_Flick] Flick Down \n");
+                GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_down);
+                break;
+
+            case FLICK_SOUTHWARD:
+                DetailDebugPrint("[GestureHandleGesture_Flick] Flick Up \n");
+                GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_up);
+                break;
+            case FLICK_WESTWARD:
+                if (g_pGesture->power_pressed == 2)
+                {
+                    DetailDebugPrint("[GestureHandleGesture_Flick] Flick Right & power_pressed\n");
+                    GestureEmulateHWKey(g_pGesture->hwkey_dev, 122);
+                }
+                break;
+            default:
+                break;
+        }
+        g_pGesture->recognized_gesture |= WFlickFilterMask;
+    }
 }
 
 void GestureHandleGesture_Hold(int num_fingers, int cx, int cy, Time holdtime, int kinds)
 {
-       Window target_win;
-       WindowPtr target_pWin;
-       xGestureNotifyHoldEvent hev;
+    Window target_win;
+    WindowPtr target_pWin;
+    xGestureNotifyHoldEvent hev;
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n",
-                               num_fingers, cx, cy, holdtime, kinds);
-#endif//__DETAIL_DEBUG__
-
-       g_pGesture->recognized_gesture |= WHoldFilterMask;
-       memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
-       hev.type = GestureNotifyHold;
-       hev.kind = kinds;
-       hev.num_finger = num_fingers;
-       hev.holdtime = holdtime;
-       hev.cx = cx;
-       hev.cy = cy;
-
-       if(g_pGesture->GrabEvents)
-       {
-               target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window;
-               target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin;
-       }
-       else
-       {
-               target_win = None;
-               target_pWin = None;
-       }
-
-       if( g_pGesture->grabMask && (target_win != None) )
-       {
-               hev.window = target_win;
-       }
-       else
-       {
-               hev.window = g_pGesture->gestureWin;
-       }
+    DetailDebugPrint("[GestureHandleGesture_Hold] num_fingers=%d, cx=%d, cy=%d, holdtime=%d, kinds=%d\n", num_fingers, cx, cy, holdtime, kinds);
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask);
-#endif//__DETAIL_DEBUG__
+    if (num_fingers == 0)
+    {
+        g_pGesture->hold_detected = TRUE;
+        LOGI("[PalmHold] PalmHold success !\n");
+    }
+    else
+    {
+        g_pGesture->recognized_gesture |= WHoldFilterMask;
+    }
+
+    memset(&hev, 0, sizeof(xGestureNotifyHoldEvent));
+    hev.type = GestureNotifyHold;
+    hev.kind = kinds;
+    hev.num_finger = num_fingers;
+    hev.holdtime = holdtime;
+    hev.cx = cx;
+    hev.cy = cy;
 
-       GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev);
+    if (g_pGesture->GrabEvents)
+    {
+        target_win = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].window;
+        target_pWin = g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[num_fingers].pWin;
+    }
+    else
+    {
+        target_win = None;
+        target_pWin = None;
+    }
+
+    if (g_pGesture->grabMask && (target_win != None))
+    {
+        hev.window = target_win;
+    }
+    else
+    {
+        hev.window = g_pGesture->gestureWin;
+    }
+
+    DetailDebugPrint("[GestureHandleGesture_Hold] hev.window=0x%x, g_pGesture->grabMask=0x%x\n", hev.window, g_pGesture->grabMask);
+
+    GestureSendEvent(target_pWin, GestureNotifyHold, GestureHoldMask, (xGestureCommonEvent *)&hev);
+    LOGI("[GroupHold] GestureHold success !\n");
 }
 
 
 void
 GestureRecognize_GroupTap(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
 {
-       static int num_pressed = 0;
-       static int base_area_size = 0;
+    static int num_pressed = 0;
+    static int base_area_size = 0;
 
-       int cx, cy;
-       int area_size;
+    int cx, cy;
+    int area_size;
 
-       static int state = 0;
-       static int mbits = 0;
-       static int base_cx;
-       static int base_cy;
-       static pixman_box16_t base_box_ext;
+    static int state = 0;
+    static int mbits = 0;
+    static int base_cx;
+    static int base_cy;
+    static pixman_box16_t base_box_ext;
 
-       static int tap_repeat = 0;
-       static int prev_num_pressed = 0;
+    static int tap_repeat = 0;
+    static int prev_num_pressed = 0;
 
-       static OsTimerPtr tap_event_timer = NULL;
-       static int event_type = GestureNotifyTap;
+    static OsTimerPtr tap_event_timer = NULL;
+    static int event_type = GestureNotifyTap;
 
-       if( timer_expired )
-       {
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[GroupTap][Timer] state=%d\n", state);
-#endif//__DETAIL_DEBUG__
-
-               switch( state )
-               {
-                       case 1://first tap initiation check
-                               if( num_pressed )
-                               {
-#ifdef __DETAIL_DEBUG__
-                                       ErrorF("[GroupTap][Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", tap_repeat, num_pressed, tap_repeat);
-#endif//__DETAIL_DEBUG__
-                                       state = 0;
-                                       goto cleanup_tap;
-                               }
-                               break;
-
-                       case 2:
-                               if( tap_repeat <= 1 )
-                               {
-#ifdef __DETAIL_DEBUG__
-                                       ErrorF("[GroupTap][Timer][state=2] %d finger SINGLE TAP !(ignored)\n", prev_num_pressed);
-#endif//__DETAIL_DEBUG__
-                                       state = 0;
-                                       goto cleanup_tap;
-                               }
+    if (timer_expired)
+    {
+        DetailDebugPrint("[GroupTap][Timer] state=%d, num_pressed=%d, tap_repeat=%d\n", state, num_pressed, tap_repeat);
+
+        switch (state)
+        {
+            case 1://first tap initiation check
+                if (num_pressed)
+                {
+                    DetailDebugPrint("[GroupTap][Timer][state=1] Tap time expired !(num_pressed=%d, tap_repeat=%d)\n", num_pressed, tap_repeat);
+                    DetailDebugPrint("[GroupTap][F] 1\n");
+
+                    state = 0;
+                    goto cleanup_tap;
+                }
+                break;
 
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[GroupTap][Timer][state=2]  tap_repeat=%d, num_pressed=%d\n", tap_repeat, num_pressed);
-#endif//__DETAIL_DEBUG__
-                               if( GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed) )
-                               {
-                                       GestureHandleGesture_Tap(prev_num_pressed, tap_repeat, base_cx, base_cy);
-                               }
-                               goto cleanup_tap;
-                               break;
-               }
-
-               return;
-       }
-
-       switch( type )
-       {
-               case ET_ButtonPress:
-                       g_pGesture->fingers[idx].flags |= PressFlagTap;
-
-                       if( g_pGesture->num_pressed < 2 )
-                               return;
-
-                       if( (!base_area_size || g_pGesture->num_pressed > num_pressed) )
-                       {
-                               base_area_size = AREA_SIZE(&g_pGesture->area.extents);
-                               base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
-                               base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
-                               base_box_ext.x1 = base_cx-TAP_MOVE_THRESHOLD;
-                               base_box_ext.y1 = base_cy-TAP_MOVE_THRESHOLD;
-                               base_box_ext.x2 = base_cx+TAP_MOVE_THRESHOLD;
-                               base_box_ext.y2 = base_cy+TAP_MOVE_THRESHOLD;
-                               state = 1;
-                               TimerCancel(tap_event_timer);
-                               tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->singletap_threshold, GestureEventTimerHandler, (int *)&event_type);
-                       }
-                       num_pressed = g_pGesture->num_pressed;
+            case 2:
+                if (tap_repeat <= 1)
+                {
+                    state = 0;
+                    DetailDebugPrint("[GroupTap][Timer][state=2] 2 finger %d tap\n", tap_repeat);
+                    LOGI("[GroupTap][F] Second tap doesn't come up in 400ms after first tap.\n");
+                    goto cleanup_tap;
+                }
+
+                if (GestureHasFingerEventMask(GestureNotifyTap, prev_num_pressed))
+                {
+                    DetailDebugPrint("[GroupTap] Success 1!! 2 finger %d tap\n", tap_repeat);
+                    GestureHandleGesture_Tap(prev_num_pressed, tap_repeat, base_cx, base_cy);
+                    goto cleanup_tap;
+                }
+                break;
+        }
+        return;
+    }
 
-#ifdef __DETAIL_DEBUG__
-                       ErrorF("[GroupTap][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);
-#endif//__DETAIL_DEBUG__
-                       break;
+    switch (type)
+    {
+        case ET_ButtonPress:
+            g_pGesture->fingers[idx].flags |= PressFlagTap;
+
+            if (g_pGesture->num_pressed < 2)
+            {
+                DetailDebugPrint("[GroupTap][P] num_pressed=%d, base_px=%d, base_py=%d. return \n", g_pGesture->num_pressed, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
+                return;
+            }
+
+            if ((!base_area_size || g_pGesture->num_pressed > num_pressed))
+            {
+                base_area_size = AREA_SIZE(&g_pGesture->area.extents);
+                base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+                base_box_ext.x1 = base_cx-TAP_MOVE_THRESHOLD;
+                base_box_ext.y1 = base_cy-TAP_MOVE_THRESHOLD;
+                base_box_ext.x2 = base_cx+TAP_MOVE_THRESHOLD;
+                base_box_ext.y2 = base_cy+TAP_MOVE_THRESHOLD;
+                state = 1;
+                TimerCancel(tap_event_timer);
+                tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->singletap_threshold, GestureEventTimerHandler, (int *)&event_type);
+            }
+            num_pressed = g_pGesture->num_pressed;
+
+            DetailDebugPrint("[GroupTap][P] num_pressed=%d, area_size=%d, base_mx=%d, base_my=%d\n", num_pressed, base_area_size, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
+            break;
+
+        case ET_Motion:
+            if (!(g_pGesture->fingers[idx].flags & PressFlagTap))
+            {
+                break;
+            }
+
+            if (num_pressed < 2)
+            {
+                DetailDebugPrint("[GroupTap][M] num_pressed=%d, return \n", num_pressed);
+                return;
+            }
+
+            if (num_pressed != g_pGesture->num_pressed)
+            {
+                DetailDebugPrint("[GroupTap][M] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+            }
+
+            mbits |= (1 << idx);
+            if (mbits == (pow(2, num_pressed)-1))
+            {
+                area_size = AREA_SIZE(&g_pGesture->area.extents);
+                cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+
+                DetailDebugPrint("[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));
+                DetailDebugPrint("[GroupTap][M] cx=%d, base_cx=%d, diff=%d\n", cx, g_pGesture->fingers[idx].mx, ABS(cx-base_cx));
+                DetailDebugPrint("[GroupTap][M] cy=%d, base_cy=%d, diff=%d\n", cy, g_pGesture->fingers[idx].my, ABS(cy-base_cy));
+
+                if (ABS(base_area_size-area_size) >= TAP_AREA_THRESHOLD)
+                {
+                    DetailDebugPrint("[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));
+                    DetailDebugPrint("[GroupTap][F] 3\n");
+                    LOGI("[GroupTap][F] 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));
+
+                    goto cleanup_tap;
+                }
+
+                if (!INBOX(&base_box_ext, cx, cy))
+                {
+                    DetailDebugPrint("[GroupTap][M] current center coordinates is not in base coordinates box !\n");
+                    DetailDebugPrint("[GroupTap][F] 4\n");
+                    LOGI("[GroupTap][F] current center coordinates is not in base coordinates box !\n");
+
+                    goto cleanup_tap;
+                }
+            }
+            break;
+
+        case ET_ButtonRelease:
+            if (g_pGesture->num_pressed)
+            {
+                DetailDebugPrint("[GroupTap][R] Second finger doesn't come up. g_pGesture->num_pressed=%d\n", g_pGesture->num_pressed);
+                break;
+            }
+
+            if (!tap_repeat)
+            {
+                prev_num_pressed = num_pressed;
+            }
+
+            tap_repeat++;
+            g_pGesture->num_tap_repeated = tap_repeat;
+
+            DetailDebugPrint("[GroupTap][R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed);
+            DetailDebugPrint("[GroupTap][R] base_rx=%d, base_ry=%d,\n", g_pGesture->fingers[idx].rx, g_pGesture->fingers[idx].ry);
+
+            if ((num_pressed != prev_num_pressed) || (!GestureHasFingerEventMask(GestureNotifyTap, num_pressed)))
+            {
+                DetailDebugPrint("[GroupTap][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
+                        num_pressed, prev_num_pressed, num_pressed);
+                DetailDebugPrint("[GroupTap][F] 5\n");
+                LOGI("[GroupTap][F] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
+                        num_pressed, prev_num_pressed, num_pressed);
+                goto cleanup_tap;
+            }
+
+            if (tap_repeat == 1)
+            {
+                DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat);
+                TimerCancel(tap_event_timer);
+                tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->doubletap_threshold, GestureEventTimerHandler, (int *)&event_type);
+                state = 2;
+                prev_num_pressed = num_pressed;
+                num_pressed = 0;
+                break;
+            }
+
+            else if (tap_repeat == 2)
+            {
+                DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat);
+                TimerCancel(tap_event_timer);
+                tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->tripletap_threshold, GestureEventTimerHandler, (int *)&event_type);
+                state = 2;
+                base_area_size = num_pressed = 0;
+                break;
+            }
+
+            DetailDebugPrint("[GroupTap][R] %d finger %d tap\n", num_pressed, tap_repeat);
+
+            if (tap_repeat == MAX_TAP_REPEATS)
+            {
+                if (GestureHasFingerEventMask(GestureNotifyTap, num_pressed))
+                {
+                    DetailDebugPrint("[GroupTap] Sucess 2!\n");
+                    GestureHandleGesture_Tap(num_pressed, tap_repeat, base_cx, base_cy);
+                }
+                goto cleanup_tap;
+            }
+
+            if (tap_repeat >= MAX_TAP_REPEATS)
+            {
+                LOGI("[GroupTap][F] More than 3 taps. Ignore. \n");
+                goto cleanup_tap;
+            }
+
+            prev_num_pressed = num_pressed;
+            num_pressed = 0;
+            break;
+    }
 
-               case ET_Motion:
-                       if( !(g_pGesture->fingers[idx].flags & PressFlagTap ) )
-                               break;
+    return;
 
-                       if( num_pressed < 2 )
-                               return;
+cleanup_tap:
 
-                       if( num_pressed != g_pGesture->num_pressed )
-                       {
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[GroupTap][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
-#endif//__DETAIL_DEBUG__
-                               //goto cleanup_tap;
-                       }
-
-                       mbits |= (1 << idx);
-                       if( mbits == (pow(2, num_pressed)-1) )
-                       {
-                               area_size = AREA_SIZE(&g_pGesture->area.extents);
-                               cx = AREA_CENTER_X(&g_pGesture->area.extents);
-                               cy = AREA_CENTER_Y(&g_pGesture->area.extents);
-#ifdef __DETAIL_DEBUG__
-                               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));
-                               ErrorF("[GroupTap][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
-                               ErrorF("[GroupTap][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
-#endif//__DETAIL_DEBUG__
+    DetailDebugPrint("[GroupTap][cleanup_tap]\n");
 
-                               if( ABS(base_area_size-area_size) >= TAP_AREA_THRESHOLD )
-                               {
-#ifdef __DETAIL_DEBUG__
-                                       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));
-#endif//__DETAIL_DEBUG__
-                                       goto cleanup_tap;
-                               }
+    if (0 == state)
+    {
+        g_pGesture->recognized_gesture &= ~WTapFilterMask;
+    }
 
-                               if( !INBOX(&base_box_ext, cx, cy) )
-                               {
-#ifdef __DETAIL_DEBUG__
-                                       ErrorF("[GroupTap][M] current center coordinates is not in base coordinates box !\n");
-#endif//__DETAIL_DEBUG__
-                                       goto cleanup_tap;
-                               }
-                       }
-                       break;
+    g_pGesture->filter_mask |= WTapFilterMask;
 
-               case ET_ButtonRelease:
-                       if( g_pGesture->num_pressed )
-                               break;
+    if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
+    {
+        DetailDebugPrint("[GroupTap][cleanup] GestureFlushOrDrop() !\n");
 
-                       if( !tap_repeat )
-                       {
-                               prev_num_pressed = num_pressed;
-                       }
+        if (ERROR_INVALPTR == GestureFlushOrDrop())
+        {
+            GestureControl(g_pGesture->this_device, DEVICE_OFF);
+        }
+    }
 
-                       tap_repeat++;
+    num_pressed = 0;
+    g_pGesture->num_tap_repeated = tap_repeat = 0;
+    prev_num_pressed = 0;
+    mbits = 0;
+    state = 0;
+    TimerCancel(tap_event_timer);
+    return;
+}
 
-#ifdef __DETAIL_DEBUG__
-                       ErrorF("[GroupTap][R] tap_repeat=%d, num_pressed=%d, prev_num_pressed=%d\n", tap_repeat, num_pressed, prev_num_pressed);
-#endif//__DETAIL_DEBUG__
+void
+GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int start_point, int direction)
+{
+    static int num_pressed = 0;
+    static Time base_time = 0;
+    Time duration;
+    int distance;
+    static int diff_base_coord = 0;
+    static int diff_base_minor_coord = 0;
+    static int diff_current_coord = 0;
+    static int false_diff_count = 0;
+    static int false_minor_diff_count = 0;
+    static float angle = 0.0f;
+    static int angle_base_x = 0, angle_base_y = 0;
+    static int motion_count = 0;
+
+    if (g_pGesture->num_pressed > 1)
+    {
+        DetailDebugPrint("[GroupFlick][F] 1\n");
+        goto cleanup_flick;
+    }
 
-                       if(( num_pressed != prev_num_pressed ) || (!GestureHasFingerEventMask(GestureNotifyTap, num_pressed)) )
-                       {
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[GroupTap][R] num_pressed(=%d) != prev_num_pressed(=%d) OR %d finger tap event was not grabbed/selected !\n",
-                                       num_pressed, prev_num_pressed, num_pressed);
-#endif//__DETAIL_DEBUG__
-                               goto cleanup_tap;
-                       }
-
-                       if( tap_repeat < MAX_TAP_REPEATS )
-                       {
-                               state = 2;
-                               TimerCancel(tap_event_timer);
-                               tap_event_timer = TimerSet(tap_event_timer, 0, g_pGesture->doubletap_threshold, GestureEventTimerHandler, (int *)&event_type);
-                               base_area_size = num_pressed = 0;
-                               break;
-                       }
+    if ((start_point <= FLICK_POINT_NONE) || (FLICK_POINT_MAX <= start_point))
+    {
+        DetailDebugPrint("[GroupFlick][F] 2\n");
+        goto cleanup_flick;
+    }
 
-#ifdef __DETAIL_DEBUG__
-                       ErrorF("[GroupTap][R] %d finger %s\n", num_pressed, (tap_repeat==2) ? "DBL_TAP" : "TRIPLE_TAP");
-#endif//__DETAIL_DEBUG__
+    switch (type)
+    {
+        case ET_ButtonPress:
+            g_pGesture->fingers[idx].flags = PressFlagFlick;
+            base_time = GetTimeInMillis();
+            num_pressed = g_pGesture->num_pressed;
+            switch (start_point)
+            {
+                case FLICK_POINT_UP:
+                    if (g_pGesture->fingers[idx].py > g_pGesture->flick_press_area)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickDown][P] press coord is out of bound. (%d, %d)\n",
+                                g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
+                        DetailDebugPrint("[GroupFlick][F] 3\n");
+                        LOGI("[BackKey][F] press coord is out of bound (40 pixel from upper vezel). press y=%d\n", g_pGesture->fingers[idx].py);
+                        goto cleanup_flick;
+                    }
+
+                    angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
+                    angle_base_x = g_pGesture->fingers[idx].px;
+                    DetailDebugPrint("[GroupFlick][FlickDown][P] px=%d, py=%d\n", g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
+                    break;
 
-                       if( GestureHasFingerEventMask(GestureNotifyTap, num_pressed) )
-                               GestureHandleGesture_Tap(num_pressed, tap_repeat, base_cx, base_cy);
+                case FLICK_POINT_DOWN:
+                    if (g_pGesture->fingers[idx].py < g_pGesture->screen_height - g_pGesture->flick_press_area)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickUp][P] press coord is out of bound. (%d, %d)\n",
+                                g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
+                        DetailDebugPrint("[GroupFlick][F] 4\n");
+                        goto cleanup_flick;
+                    }
+                    angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
+                    angle_base_x = g_pGesture->fingers[idx].px;
+                    break;
 
-                       if( tap_repeat >= MAX_TAP_REPEATS )
-                       {
-                               goto cleanup_tap;
-                       }
+                case FLICK_POINT_LEFT:
+                    if (g_pGesture->fingers[idx].px > g_pGesture->flick_press_area)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickLeft][P] press coord is out of bound. (%d, %d)\n",
+                                g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
+                        DetailDebugPrint("[GroupFlick][F] 5\n");
+                        goto cleanup_flick;
+                    }
+                    angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
+                    angle_base_x = g_pGesture->fingers[idx].px;
+                    break;
 
-                       prev_num_pressed = num_pressed;
-                       num_pressed = 0;
-                       break;
-       }
+                default:
+                    DetailDebugPrint("[GroupFlick][F] 6\n");
+                    goto cleanup_flick;
+                    break;
+            }
 
-       return;
+            break;
 
-cleanup_tap:
+        case ET_Motion:
 
-       if( 0 == state )
-               g_pGesture->recognized_gesture &= ~WTapFilterMask;
-       g_pGesture->filter_mask |= WTapFilterMask;
+            motion_count++;
+
+            if (motion_count > 15)
+            {
+                DetailDebugPrint("[GroupFlick][F] 6-1 motion_count=%d\n", motion_count);
+                LOGI("[BackKey][F] More than 15 motion.\n");
+                goto cleanup_flick;
+            }
+
+            if (!(g_pGesture->fingers[idx].flags & PressFlagFlick))
+            {
+                break;
+            }
+
+            switch (start_point)
+            {
+                case FLICK_POINT_UP:
+                    diff_base_coord = diff_current_coord;
+                    diff_current_coord = g_pGesture->fingers[idx].my;
+
+                    if ((diff_current_coord - diff_base_coord) < 0)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickDown][M] false_diff\n");
+                        false_diff_count++;
+                    }
+
+                    if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickDown][M] false_diff_count: %d > %d\n",
+                                false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
+                        DetailDebugPrint("[GroupFlick][F] 7\n");
+                        LOGI("[BackKey][F] Direction is wrong for 7 times.\n");
+                        goto cleanup_flick;
+                    }
+
+                    if ((g_pGesture->fingers[idx].my < g_pGesture->flick_press_area) &&
+                            (abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) >(int)( g_pGesture->screen_width/2)))
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickDown][M] move x: %d - %d, y coord: %d\n",
+                                g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].my);
+                        DetailDebugPrint("[GroupFlick][F] 8\n");
+                        LOGI("[BackKey][F] From press point, moving x axis is more than half screen size.\n");
+                        goto cleanup_flick;
+                    }
+
+                    if ((g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) > g_pGesture->flick_minimum_height)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickDown][M] %d - %d < %d(min_size), angle_base_coord (%d, %d)\n",
+                                g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py, g_pGesture->flick_minimum_height, angle_base_x, angle_base_y);
+
+                        if (abs(g_pGesture->fingers[idx].mx - angle_base_x) == 0)
+                        {
+                            DetailDebugPrint("[GroupFlick][FlickDown][M] abs(%d - %d) = 0\n",
+                                    g_pGesture->fingers[idx].mx, angle_base_x);
+                            angle = 1.0f;
+                        }
+                        else
+                        {
+                            DetailDebugPrint("[GroupFlick][FlickDown][M] angle_base_x: %d, angle_base_y: %d\n",
+                                    angle_base_x, angle_base_y);
+                            int y_diff = abs(g_pGesture->fingers[idx].my - angle_base_y);
+                            int x_diff = abs(g_pGesture->fingers[idx].mx - angle_base_x);
+                            angle = (float)y_diff / (float)x_diff;
+                        }
+
+                        if (angle < 0.23f)
+                        {
+                            DetailDebugPrint("[GroupFlick][FlickDown][M][F] %d / %d = %f (angle)\n",
+                                    abs(g_pGesture->fingers[idx].my - angle_base_y), abs(g_pGesture->fingers[idx].mx - angle_base_x), angle);
+                            DetailDebugPrint("[GroupFlick][F] 9\n");
+                            LOGI("[BackKey][F] angle is improper. %d < 0.23\n", angle);
+                            goto cleanup_flick;
+                        }
+
+                        distance = g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py;
+                        duration = GetTimeInMillis() - base_time;
+
+                        GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
+                        DetailDebugPrint("[GroupFlick][FlickDown][M] FlickDown Done!!\n");
+                        goto cleanup_flick_recognized;
+                    }
+                    else
+                    {
+                        if ((g_pGesture->fingers[idx].mx - diff_base_minor_coord) < 0)
+                        {
+                            false_minor_diff_count++;
+                        }
+
+                        if (false_minor_diff_count> FLICK_FALSE_X_DIFF_COUNT)
+                        {
+                            DetailDebugPrint("[GroupFlick][FlickDown][M] false_minor_diff_count: %d > %d\n",
+                                    false_minor_diff_count, FLICK_FALSE_X_DIFF_COUNT);
+                            DetailDebugPrint("[GroupFlick][F] 10\n");
+                            goto cleanup_flick;
+                        }
+                    }
+
+                    if (g_pGesture->fingers[idx].my < g_pGesture->flick_press_area)
+                    {
+                        angle_base_x = g_pGesture->fingers[idx].px;
+                        angle_base_y = g_pGesture->fingers[idx].py;
+                    }
+                    DetailDebugPrint("[GroupFlick][FlickDown][M] mx=%d, my=%d, diff_x=%d, diff_y=%d\n",
+                            g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].my, abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py));
+
+                    break;
+
+                case FLICK_POINT_DOWN:
+                    diff_base_coord = diff_current_coord;
+                    diff_current_coord = g_pGesture->fingers[idx].my;
+
+                    if ((diff_base_coord - diff_current_coord) < 0)
+                    {
+                        false_diff_count++;
+                    }
+
+                    if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickUp][M] false_diff_count: %d > %d\n",
+                                false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
+                        DetailDebugPrint("[GroupFlick][F] 11\n");
+                        goto cleanup_flick;
+                    }
+
+                    if ((g_pGesture->fingers[idx].py - g_pGesture->fingers[idx].my) > g_pGesture->flick_minimum_height)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickUp][R] %d - %d < %d(min_size)\n",
+                                g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py, g_pGesture->flick_minimum_height);
+                        if (abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) == 0)
+                        {
+                            DetailDebugPrint("[GroupFlick][FlickUp][R] abs(%d - %d) = 0\n",
+                                    g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px);
+                            angle = 1.0f;
+                        }
+                        else
+                        {
+                            int y_diff = abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py);
+                            int x_diff = abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px);
+                            angle = (float)y_diff / (float)x_diff;
+                        }
+
+                        if (angle <0.5f)
+                        {
+                            DetailDebugPrint("[GroupFlick][FlickUp][R] %d / %d = %f (angle)\n",
+                                    abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py), abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), angle);
+                            DetailDebugPrint("[GroupFlick][F] 12\n");
+                            goto cleanup_flick;
+                        }
+
+                        distance = g_pGesture->fingers[idx].py - g_pGesture->fingers[idx].my;
+                        duration = GetTimeInMillis() - base_time;
+
+                        GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
+                        goto cleanup_flick_recognized;
+                    }
+                    break;
+
+                case FLICK_POINT_LEFT:
+                    diff_base_coord = diff_current_coord;
+                    diff_current_coord = g_pGesture->fingers[idx].mx;
+
+                    if ((diff_current_coord - diff_base_coord) < 0)
+                    {
+                        false_diff_count++;
+                    }
+
+                    if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickLeft][M] false_diff_count: %d > %d\n",
+                                false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
+                        DetailDebugPrint("[GroupFlick][F] 13\n");
+                        goto cleanup_flick;
+                    }
+
+                    if ((g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) > g_pGesture->flick_minimum_height)
+                    {
+                        DetailDebugPrint("[GroupFlick][FlickLeft][M] %d - %d < %d(min_size)\n",
+                                g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px, g_pGesture->flick_minimum_height);
+
+                        if (abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) == 0)
+                        {
+                            DetailDebugPrint("[GroupFlick][FlickLeft][M] abs(%d - %d) = 0\n",
+                                    g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py);
+                            angle = 1.0f;
+                        }
+                        else
+                        {
+                            int y_diff = abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py);
+                            int x_diff = abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px);
+                            angle = (float)x_diff / (float)y_diff;
+                        }
+
+                        if ( angle < 0.5f)
+                        {
+                            DetailDebugPrint("[GroupFlick][FlickLeft][M] %d / %d = %f (angle)\n",
+                                    abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py), angle);
+                            DetailDebugPrint("[GroupFlick][F] 14\n");
+                            goto cleanup_flick;
+                        }
+
+                        distance = g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px;
+                        duration = GetTimeInMillis() - base_time;
+
+                        GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
+                        goto cleanup_flick_recognized;
+                    }
+
+                    break;
+                default:
+                    DetailDebugPrint("[GroupFlick][F] 15\n");
+                    goto cleanup_flick;
+                    break;
+            }
+            break;
+
+        case ET_ButtonRelease:
+            DetailDebugPrint("[GroupFlick][R][F] 16\n");
+            goto cleanup_flick;
+            break;
+    }
+
+    return;
+
+cleanup_flick:
+    DetailDebugPrint("[GroupFlick] cleanup_flick \n");
+    g_pGesture->recognized_gesture &= ~WFlickFilterMask;
+    motion_count = 0;
+
+cleanup_flick_recognized:
+    DetailDebugPrint("[GroupFlick] Flick recognized !\n");
+    g_pGesture->filter_mask |= WFlickFilterMask;
+    num_pressed = 0;
+    base_time = 0;
+    false_diff_count = 0;
+    diff_base_coord = 0;
+    diff_current_coord = 0;
+    angle = 0.0f;
+    angle_base_x = angle_base_y = 0;
+    motion_count = 0;
+    return;
+}
+
+void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
+{
+    static int num_pressed = 0;
+    static int base_area_size = 0;
+    static Time base_time = 0;
+    static int base_cx;
+    static int base_cy;
+    int cx, cy;
+    static pixman_box16_t base_box_ext;
+    int area_size;
+    static int state = GestureEnd;
+
+    static OsTimerPtr hold_event_timer = NULL;
+    static int event_type = GestureNotifyHold;
+
+    if (timer_expired)
+    {
+        if (state <= GestureBegin)
+        {
+            state++;
+        }
+
+        switch (state)
+        {
+            case GestureBegin:
+                DetailDebugPrint("[GroupHold] HOLD Begin !\n");
+                break;
+
+            case GestureUpdate:
+                DetailDebugPrint("[GroupHold] HOLD Update !\n");
+                break;
+        }
+
+        if (GestureHasFingerEventMask(GestureNotifyHold, num_pressed))
+        {
+            DetailDebugPrint("[GroupHold] Success 1! \n");
+            GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
+
+            // one more time
+            hold_event_timer = TimerSet(hold_event_timer, 0, g_pGesture->hold_time_threshold, GestureEventTimerHandler, (int *)&event_type);
+        }
+        return;
+    }
+
+    switch (type)
+    {
+        case ET_ButtonPress:
+            g_pGesture->fingers[idx].flags |= PressFlagHold;
+
+            if (g_pGesture->num_pressed < 2)
+            {
+                DetailDebugPrint("[GroupHold][P] No num_finger changed ! num_pressed=%d\n", num_pressed);
+                DetailDebugPrint("[GroupHold][F] 0\n");
+                return;
+            }
+
+            if (!base_area_size || g_pGesture->num_pressed > num_pressed)
+            {
+                if (state != GestureEnd)
+                {
+                    DetailDebugPrint("[GroupHold][P][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+                    DetailDebugPrint("[GroupHold][F] 1\n");
+
+                    goto cleanup_hold;
+                }
+
+                base_area_size = AREA_SIZE(&g_pGesture->area.extents);
+                base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
+                base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+                base_time = GetTimeInMillis();
+
+                base_box_ext.x1 = base_cx-g_pGesture->hold_move_threshold;
+                base_box_ext.y1 = base_cy-g_pGesture->hold_move_threshold;
+                base_box_ext.x2 = base_cx+g_pGesture->hold_move_threshold;
+                base_box_ext.y2 = base_cy+g_pGesture->hold_move_threshold;
+
+                event_type = GestureNotifyHold;
+
+                hold_event_timer = TimerSet(hold_event_timer, 0, g_pGesture->hold_time_threshold, GestureEventTimerHandler, (int *)&event_type);
+            }
+            num_pressed = g_pGesture->num_pressed;
+
+            DetailDebugPrint("[GroupHold][P] num_pressed=%d area_size=%d, base_cx=%d, base_cy=%d\n", num_pressed, base_area_size, base_cx, base_cy);
+
+            break;
+
+        case ET_Motion:
+            if (!(g_pGesture->fingers[idx].flags & PressFlagHold))
+            {
+                DetailDebugPrint("[GroupHold][M] No PressFlagHold\n");
+                break;
+            }
+
+            if (num_pressed < 2)
+            {
+                DetailDebugPrint("[GroupHold][M] No num_finger changed ! num_pressed=%d\n", num_pressed);
+                DetailDebugPrint("[GroupHold][F] 2\n");
+                return;
+            }
+
+            if (num_pressed != g_pGesture->num_pressed)
+            {
+                if (state != GestureEnd)
+                {
+                    DetailDebugPrint("[GroupHold][M][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+                    DetailDebugPrint("[GroupHold][F] 3\n");
+                    goto cleanup_hold;
+                }
+
+                DetailDebugPrint("[GroupHold][M] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+            }
+
+            area_size = AREA_SIZE(&g_pGesture->area.extents);
+            cx = AREA_CENTER_X(&g_pGesture->area.extents);
+            cy = AREA_CENTER_Y(&g_pGesture->area.extents);
+
+            DetailDebugPrint("[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));
+            DetailDebugPrint("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
+            DetailDebugPrint("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
+
+            if (area_size > 0 && base_area_size > 0)
+            {
+                if (((area_size > base_area_size) ? (double)area_size / (double)base_area_size : (double)base_area_size / (double) area_size) >= g_pGesture->hold_area_threshold)
+                {
+                    DetailDebugPrint("[GroupHold][M] No diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%lf)!\n", area_size, base_area_size, ((area_size > base_area_size) ? (double)area_size / (double)base_area_size : (double)base_area_size / (double) area_size));
+                    DetailDebugPrint("[GroupHold][F] 4\n");
+                    goto cleanup_hold;
+                }
+            }
+
+            if (!INBOX(&base_box_ext, cx, cy))
+            {
+                DetailDebugPrint("[GroupHold][M] No current center coordinates is not in base coordinates box !\n");
+                DetailDebugPrint("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
+                DetailDebugPrint("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
+                DetailDebugPrint("[GroupHold][F] 5\n");
+                goto cleanup_hold;
+            }
+            break;
+
+        case ET_ButtonRelease:
+            if (state != GestureEnd && num_pressed >= 2)
+            {
+                DetailDebugPrint("[GroupHold][R] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
+                DetailDebugPrint("[GroupHold][F] 6\n");
+                goto cleanup_hold;
+            }
+
+            if (g_pGesture->num_pressed)
+            {
+                DetailDebugPrint("[GroupHold][R] num_pressed=%d\n", num_pressed);
+                DetailDebugPrint("[GroupHold][F] 7\n");
+                break;
+            }
+
+            goto cleanup_hold;
+            break;
+    }
+
+    return;
+
+cleanup_hold:
+
+    DetailDebugPrint("[GroupHold][cleanup_hold] enter!\n");
+
+    if (state == GestureBegin || state == GestureUpdate)
+    {
+        state = GestureEnd;
+        if (GestureHasFingerEventMask(GestureNotifyHold, num_pressed))
+        {
+            DetailDebugPrint("[GroupHold] Success 2!\n");
+            GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
+        }
+    }
+    else
+    {
+        g_pGesture->recognized_gesture &= ~WHoldFilterMask;
+    }
+
+    g_pGesture->filter_mask |= WHoldFilterMask;
+    num_pressed = 0;
+    base_area_size = 0;
+    base_time = 0;
+    base_cx = base_cy = 0;
+    state = GestureEnd;
+    base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
+    TimerCancel(hold_event_timer);
+    return;
+}
+
+int
+GestureGetMaxTmajor(InternalEvent *ev, int max_tmajor)
+{
+    int mt_tmajor_idx = g_pGesture->tmajor_idx;
+    int mt_tmajor = 0;
+
+    DeviceEvent *de = &ev->device_event;
+
+    if (!de)
+    {
+        DetailDebugPrint("[GestureGetMaxTmajor] de is NULL !\n");
+        return -1;
+    }
+
+    if (mt_tmajor_idx < 0)
+    {
+        DetailDebugPrint("[GestureGetMaxTmajor] One or more of axes are not supported !\n");
+        return -1;
+    }
+
+    mt_tmajor = de->valuators.data[mt_tmajor_idx];
+
+    DetailDebugPrint("[GestureGetMaxTmajor]mt_tmajor_idx=%d, mt_tmajor=%d, max_tmajor=%d\n", mt_tmajor_idx, mt_tmajor, max_tmajor);
+
+    return ((mt_tmajor > max_tmajor) ? mt_tmajor : max_tmajor);
 
-       if( g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL )
-       {
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[GroupTap][cleanup] GestureFlushOrDrop() !\n");
-#endif//__DETAIL_DEBUG__
-
-               if( ERROR_INVALPTR == GestureFlushOrDrop() )
-               {
-                       GestureControl(g_pGesture->this_device, DEVICE_OFF);
-               }
-       }
-
-       num_pressed = 0;
-       tap_repeat = 0;
-       prev_num_pressed = 0;
-       mbits = 0;
-       state = 0;
-       TimerCancel(tap_event_timer);
-       return;
 }
 
 void
-GestureRecognize_GroupFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int start_point, int direction)
+GestureRecognize_PalmFlick(int type, InternalEvent *ev, DeviceIntPtr device, int idx)
 {
-       static int num_pressed = 0;
-       static Time base_time = 0;
-       Time duration;
-       int distance;
-       static int diff_base_coord = 0;
-       static int diff_base_minor_coord = 0;
-       static int diff_current_coord = 0;
-       static int false_diff_count = 0;
-       static int false_minor_diff_count = 0;
-       static float angle = 0.0f;
-       static int angle_base_x=0, angle_base_y=0;
-
-       if( g_pGesture->num_pressed > 1 )
-               goto cleanup_flick;
-       if( (start_point <= FLICK_POINT_NONE) || (FLICK_POINT_MAX <= start_point) )
-               goto cleanup_flick;
-
-       switch( type )
-       {
-               case ET_ButtonPress:
-                       g_pGesture->fingers[idx].flags = PressFlagFlick;
-                       base_time = GetTimeInMillis();
-                       num_pressed = g_pGesture->num_pressed;
-                       switch(start_point)
-                       {
-                               case FLICK_POINT_UP:
-                                       if( g_pGesture->fingers[idx].py > g_pGesture->flick_press_area)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickDown] press coord is out of bound. (%d, %d)\n", g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
-#endif//__DETAIL_DEBUG__
-                                               goto cleanup_flick;
-                                       }
-
-                                       angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
-                                       angle_base_x = g_pGesture->fingers[idx].px;
-                                       break;
-
-                               case FLICK_POINT_DOWN:
-                                       if( g_pGesture->fingers[idx].py < g_pGesture->screen_height - g_pGesture->flick_press_area)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickUp] press coord is out of bound. (%d, %d)\n", g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
-#endif//__DETAIL_DEBUG__
-                                               goto cleanup_flick;
-                                       }
-                                       angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
-                                       angle_base_x = g_pGesture->fingers[idx].px;
-                                       break;
-
-                               case FLICK_POINT_LEFT:
-                                       if( g_pGesture->fingers[idx].px > g_pGesture->flick_press_area)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickLeft] press coord is out of bound. (%d, %d)\n", g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
-#endif//__DETAIL_DEBUG__
-                                               goto cleanup_flick;
-                                       }
-                                       angle_base_y = diff_base_coord = diff_current_coord = g_pGesture->fingers[idx].py;
-                                       angle_base_x = g_pGesture->fingers[idx].px;
-                                       break;
-
-                               default:
-                                       goto cleanup_flick;
-                                       break;
-                       }
-
-                       break;
-
-               case ET_Motion:
-                       if( !(g_pGesture->fingers[idx].flags & PressFlagFlick ) )
-                               break;
-
-                       switch(start_point)
-                       {
-                               case FLICK_POINT_UP:
-                                       diff_base_coord = diff_current_coord;
-                                       diff_current_coord = g_pGesture->fingers[idx].my;
-
-                                       if( (diff_current_coord - diff_base_coord) < 0 )
-                                               false_diff_count++;
-                                       if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickDown][M][F] false_diff_count: %d > %d\n", false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
-#endif//__DETAIL_DEBUG__
-                                               goto cleanup_flick;
-                                       }
-
-                                       if ((g_pGesture->fingers[idx].my < g_pGesture->flick_press_area) &&
-                                               (abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) >(int)( g_pGesture->screen_width/2)) )
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickDown][M][F] move x: %d - %d, y coord: %d\n", g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].my);
-#endif//__DETAIL_DEBUG__
-                                               goto cleanup_flick;
-                                       }
+    // static int num_pressed = 0;
+    static int base_time = 0, current_time = 0;
+    static int base_x[MAX_MT_DEVICES] = {0}, base_y[MAX_MT_DEVICES] = {0};
+    static int update_x[MAX_MT_DEVICES] = {0}, update_y[MAX_MT_DEVICES] = {0};
 
-                                       if( (g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) > g_pGesture->flick_minimum_height)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickDown][M] %d - %d < %d(min_size), angle_base_coord (%d, %d)\n", g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py, g_pGesture->flick_minimum_height, angle_base_x, angle_base_y);
-#endif//__DETAIL_DEBUG__
-                                               if(abs(g_pGesture->fingers[idx].mx - angle_base_x) == 0)
-                                               {
-#ifdef __DETAIL_DEBUG__
-                                                       ErrorF("[FlickDown][M] abs(%d - %d) = 0\n", g_pGesture->fingers[idx].mx, angle_base_x);
-#endif//__DETAIL_DEBUG__
-                                                       angle = 1.0f;
-                                               }
-                                               else
-                                               {
-#ifdef __DETAIL_DEBUG__
-                                                       ErrorF("[FlickDown][M] angle_base_x: %d, angle_base_y: %d\n", angle_base_x, angle_base_y);
-#endif//__DETAIL_DEBUG__
 
-                                                       int y_diff = abs(g_pGesture->fingers[idx].my - angle_base_y);
-                                                       int x_diff = abs(g_pGesture->fingers[idx].mx - angle_base_x);
-                                                       angle = (float)y_diff / (float)x_diff;
-                                               }
+    static int current_x[MAX_MT_DEVICES] = {0}, current_y[MAX_MT_DEVICES] = {0};
+    static Bool press_status[MAX_MT_DEVICES] = {FALSE, FALSE};
+    static Bool release_status[MAX_MT_DEVICES] = {FALSE, FALSE};
 
-                                               if ( angle < 0.27f)
-                                               {
-#ifdef __DETAIL_DEBUG__
-                                                       ErrorF("[FlickDown][M][F] %d / %d = %f (angle)\n", abs(g_pGesture->fingers[idx].my - angle_base_y), abs(g_pGesture->fingers[idx].mx - angle_base_x), angle);
-#endif//__DETAIL_DEBUG__
-                                                       goto cleanup_flick;
-                                               }
-
-                                               distance = g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py;
-                                               duration = GetTimeInMillis() - base_time;
-
-                                               GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
-                                               goto cleanup_flick_recognized;
-                                       }
-                                       else
-                                       {
-                                               if( (g_pGesture->fingers[idx].mx - diff_base_minor_coord) < 0 )
-                                                       false_minor_diff_count++;
-                                               if (false_minor_diff_count> FLICK_FALSE_X_DIFF_COUNT)
-                                               {
-#ifdef __DETAIL_DEBUG__
-                                                       ErrorF("[FlickDown][M][F] false_minor_diff_count: %d > %d\n", false_minor_diff_count, FLICK_FALSE_X_DIFF_COUNT);
-#endif//__DETAIL_DEBUG__
-                                                       goto cleanup_flick;
-                                               }
-                                       }
-
-                                       if (g_pGesture->fingers[idx].my < g_pGesture->flick_press_area)
-                                       {
-                                               angle_base_x = g_pGesture->fingers[idx].px;
-                                               angle_base_y = g_pGesture->fingers[idx].py;
-                                       }
-
-                                       break;
-                               case FLICK_POINT_DOWN:
-                                       diff_base_coord = diff_current_coord;
-                                       diff_current_coord = g_pGesture->fingers[idx].my;
-
-                                       if( (diff_base_coord - diff_current_coord) < 0 )
-                                               false_diff_count++;
-                                       if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickUp][M] false_diff_count: %d > %d\n", false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
-#endif//__DETAIL_DEBUG__
-                                               goto cleanup_flick;
-                                       }
+    static int line_idx[MAX_MT_DEVICES] = {0}, prev_line_idx[MAX_MT_DEVICES] = {0}, press_idx[MAX_MT_DEVICES] = {0};
+    static Bool is_line_invalid[MAX_MT_DEVICES] = {TRUE, TRUE};
 
-                                       if( (g_pGesture->fingers[idx].py - g_pGesture->fingers[idx].my) > g_pGesture->flick_minimum_height)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickUp][R] %d - %d < %d(min_size)\n", g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py, g_pGesture->flick_minimum_height);
-#endif//__DETAIL_DEBUG__
-                                               if(abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) == 0)
-                                               {
-#ifdef __DETAIL_DEBUG__
-                                                       ErrorF("[FlickUp][R] abs(%d - %d) = 0\n", g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px);
-#endif//__DETAIL_DEBUG__
-                                                       angle = 1.0f;
-                                               }
-                                               else
-                                               {
-                                                       int y_diff = abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py);
-                                                       int x_diff = abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px);
-                                                       angle = (float)y_diff / (float)x_diff;
-                                               }
-
-                                               if ( angle <0.5f)
-                                               {
-#ifdef __DETAIL_DEBUG__
-                                                       ErrorF("[FlickUp][R] %d / %d = %f (angle)\n", abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py), abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), angle);
-#endif//__DETAIL_DEBUG__
-                                                       goto cleanup_flick;
-                                               }
-
-                                               distance = g_pGesture->fingers[idx].py - g_pGesture->fingers[idx].my;
-                                               duration = GetTimeInMillis() - base_time;
-
-                                               GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
-                                               goto cleanup_flick_recognized;
-                                       }
-                                       break;
-                               case FLICK_POINT_LEFT:
-                                       diff_base_coord = diff_current_coord;
-                                       diff_current_coord = g_pGesture->fingers[idx].mx;
-
-                                       if( (diff_current_coord - diff_base_coord) < 0 )
-                                               false_diff_count++;
-                                       if (false_diff_count > FLICK_FALSE_Y_DIFF_COUNT)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickLeft][M] false_diff_count: %d > %d\n", false_diff_count, FLICK_FALSE_Y_DIFF_COUNT);
-#endif//__DETAIL_DEBUG__
-                                               goto cleanup_flick;
-                                       }
+    static int max_tmajor[MAX_MT_DEVICES] = {0};
+    static int total_max_tmajor = 0;
+    static Bool is_tmajor_invalid[MAX_MT_DEVICES] = {TRUE, TRUE};
 
-                                       if( (g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px) > g_pGesture->flick_minimum_height)
-                                       {
-#ifdef __DETAIL_DEBUG__
-                                               ErrorF("[FlickLeft][M] %d - %d < %d(min_size)\n", g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].px, g_pGesture->flick_minimum_height);
-#endif//__DETAIL_DEBUG__
-                                               if(abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py) == 0)
-                                               {
-#ifdef __DETAIL_DEBUG__
-                                                       ErrorF("[FlickLeft][M] abs(%d - %d) = 0\n", g_pGesture->fingers[idx].my, g_pGesture->fingers[idx].py);
-#endif//__DETAIL_DEBUG__
-                                                       angle = 1.0f;
-                                               }
-                                               else
-                                               {
-                                                       int y_diff = abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py);
-                                                       int x_diff = abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px);
-                                                       angle = (float)x_diff / (float)y_diff;
-                                               }
-
-                                               if ( angle < 0.5f)
-                                               {
-#ifdef __DETAIL_DEBUG__
-                                                       ErrorF("[FlickLeft][M] %d / %d = %f (angle)\n", abs(g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px), abs(g_pGesture->fingers[idx].my - g_pGesture->fingers[idx].py), angle);
-#endif//__DETAIL_DEBUG__
-                                                       goto cleanup_flick;
-                                               }
+    static int mt_sync_count[MAX_MT_DEVICES] = {0};
 
-                                               distance = g_pGesture->fingers[idx].mx - g_pGesture->fingers[idx].px;
-                                               duration = GetTimeInMillis() - base_time;
+    static Bool is_palm = FALSE;
+    PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc;
+
+    static Bool is_retry = FALSE;
+
+    int distance, direction, duration;
+
+    if (g_pGesture->recognized_gesture && !(g_pGesture->recognized_gesture & WPalmFlickFilterMask))
+    {
+        PalmFlickDebugPrint("[PalmFlick] recognize other gesture already( g_pGesture->recognized_gesture: %d)\n", g_pGesture->recognized_gesture);
+        PalmFlickDebugPrint("[PalmFlick][F] 1\n");
+        goto flick_failed;
+    }
+
+    // only first finger recognize
+    if (!(idx == 0 || idx == 1))
+    {
+        PalmFlickDebugPrint("[PalmFlick] idx=%d, least two fingers come on\n", idx);
+        return;
+    }
+
+    switch (type)
+    {
+        case ET_ButtonPress:
+
+            if (!is_palm)
+            {
+                if (idx == 0)
+                {
+                    base_time = GetTimeInMillis();
+                }
+
+                // press (x,y), touch major
+                update_x[idx] = base_x[idx] = g_pGesture->fingers[idx].px;
+                update_y[idx] = base_y[idx] = g_pGesture->fingers[idx].py;
+                max_tmajor[idx] = g_pGesture->max_mt_tmajor[idx];
+                press_status[idx] = TRUE;
+                is_tmajor_invalid[idx] = FALSE;
+                is_line_invalid[idx] = FALSE;
+
+                total_max_tmajor = (total_max_tmajor > max_tmajor[idx]) ? total_max_tmajor : max_tmajor[idx];
+
+                // press region
+                press_idx[idx] = prev_line_idx[idx] = line_idx[idx] = GesturePalmGetHorizIndexWithX(base_x[idx], idx, type);
+
+                PalmFlickDebugPrint("[PalmFlick][P] idx: %d, num_pressed: %d\n", idx, g_pGesture->num_pressed);
+                PalmFlickDebugPrint("[PalmFlick][P] base_time: %d, base_x: %d, base_y: %d, line_idx: %d, touch_major=%d\n",
+                        base_time, base_x[idx], base_y[idx], line_idx[idx], max_tmajor[idx]);
+
+                // invalid region
+                if (line_idx[idx] < 0 || line_idx[idx] >= PALM_HORIZ_ARRAY_COUNT)
+                {
+                    PalmFlickDebugPrint("[PalmFlick][P][F] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x[idx], line_idx[idx]);
+                    PalmFlickDebugPrint("[PalmFlick][F] 2\n");
+                    goto flick_failed;
+                }
+
+                // check press point when there are two fingers
+                if (idx == 1)
+                {
+                    if (press_idx[0] != press_idx[1])
+                    {
+                        PalmFlickDebugPrint("[PalmFlick] Press line_idx is the different between two fingers. 1st finger_line_idx=%d, 2nd finger_line_idx=%d\n",
+                                press_idx[0], press_idx[1]);
+                        PalmFlickDebugPrint("[PalmFlick][F] 2-1\n");
+                        goto flick_failed;
+                    }
+                }
+            }
+            else
+            {
+                update_x[idx] = g_pGesture->fingers[idx].px;
+                update_y[idx] = g_pGesture->fingers[idx].py;
+
+                PalmFlickDebugPrint("[PalmFlick][P] Already palm flick success. base_x=%d, base_y=%d, update_x=%d, update_y=%d\n",
+                        base_x[idx], base_y[idx], update_x[idx], update_y[idx]);
+            }
+
+            break;
+
+        case ET_Motion:
+
+            if (total_max_tmajor > g_pGesture->palm_flick_max_tmajor_threshold)
+            {
+                mt_sync_count[idx]++;
+                is_palm = TRUE;
+                DetailDebugPrint("[PalmFlick][M] Sufficient touch enough ! max_tmajor=%d\n", total_max_tmajor);
+                break;
+            }
+
+            // motion information (touch major, x, y)
+            current_x[idx] = g_pGesture->fingers[idx].mx;
+            current_y[idx] = g_pGesture->fingers[idx].my;
+            max_tmajor[idx] = g_pGesture->max_mt_tmajor[idx];
+            mt_sync_count[idx]++;
+
+            //int temp_total_max_tmajor = (idx == 0 ? max_tmajor[0] : max_tmajor[0] + max_tmajor[1]);
+            int temp_total_max_tmajor = max_tmajor[idx];
+            total_max_tmajor = (total_max_tmajor > temp_total_max_tmajor ? total_max_tmajor : temp_total_max_tmajor);
+
+            PalmFlickDebugPrint("[PalmFlick][M] idx=%d, total_max_tmajor=%d, max_tmajor[0]=%d, max_tmajor[1]=%d, current current=(%d, %d)\n",
+                    idx, total_max_tmajor, max_tmajor[0], max_tmajor[1], current_x[idx], current_y[idx]);
+
+            // exception vezel end line motion
+            if (current_x[idx] < 5 || current_x[idx] > 355)
+            {
+                if (total_max_tmajor >= g_pGesture->palm_flick_max_tmajor_threshold)
+                {
+                    PalmFlickDebugPrint("[PalmFlick][M][Vezel] Sufficient touch major was came(%d)\n", total_max_tmajor);
+                    is_palm = TRUE;
+                }
+                else
+                {
+                    mt_sync_count[idx]--;
+                    PalmFlickDebugPrint("[PalmFlick][M] Except vezel end line condition. x=%d, sync_count=%d \n",
+                            current_x[idx], mt_sync_count[idx]);
+                }
+                break;
+            }
+
+            // get current position
+            line_idx[idx] = GesturePalmGetHorizIndexWithX(current_x[idx], idx, type);
+
+            PalmFlickDebugPrint("[PalmFlick][M] line_idx: %d, prev_line_idx: %d, sync_count: %d\n",
+                    line_idx[idx], prev_line_idx[idx], mt_sync_count[idx]);
+
+            //error check
+            if (line_idx[idx] < 0 || line_idx[idx] >= PALM_HORIZ_ARRAY_COUNT)
+            {
+                PalmFlickDebugPrint("[PalmFlick][M][F] No line_idx is invalid.. base_x: %d, line_idx: %d\n", base_x[idx], line_idx[idx]);
+                PalmFlickDebugPrint("[PalmFlick][F] 3\n");
+                goto flick_failed;
+            }
+
+            // screen capture motion validation
+            if (line_idx[idx] != prev_line_idx[idx])
+            {
+                if (base_x[idx] <= pPalmMisc->horiz_coord[0])
+                {
+                    if (line_idx[idx] < prev_line_idx[idx])
+                    {
+                        PalmFlickDebugPrint("[PalmFlick][M][F] Invalid line_idx.. line_idx: %d, prev_line_idx: %d, pPalmMisc->horiz_coord[0]: %d\n",
+                                line_idx[idx], prev_line_idx[idx], pPalmMisc->horiz_coord[0]);
+
+                        is_line_invalid[idx] = TRUE;
+
+                        if (is_line_invalid[0] && is_line_invalid[1])
+                        {
+                            PalmFlickDebugPrint("[PalmFlick][F] 4\n");
+                            goto flick_failed;
+                        }
+                    }
+                }
+                else if (base_x[idx] >= pPalmMisc->horiz_coord[PALM_HORIZ_ARRAY_COUNT-1])
+                {
+                    if (line_idx[idx] > prev_line_idx[idx])
+                    {
+                        PalmFlickDebugPrint("[PalmFlick][M][F] Invalid line_idx.. line_idx: %d, prev_line_idx: %d, pPalmMisc->horiz_coord[%d]: %d\n",
+                                line_idx[idx], prev_line_idx[idx], PALM_HORIZ_ARRAY_COUNT-1, pPalmMisc->horiz_coord[PALM_HORIZ_ARRAY_COUNT-1]);
+
+                        is_line_invalid[idx] = TRUE;
+
+                        if (is_line_invalid[0] && is_line_invalid[1])
+                        {
+                            PalmFlickDebugPrint("[PalmFlick][F] 5\n");
+                            goto flick_failed;
+                        }
+                    }
+                }
+                prev_line_idx[idx] = line_idx[idx];
+            }
+
+            if (is_palm == FALSE)
+            {
+                switch (mt_sync_count[idx])
+                {
+                    case 1:
+                        if (total_max_tmajor <= g_pGesture->palm_flick_min_tmajor_threshold)
+                        {
+                            PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n",
+                                    mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_min_tmajor_threshold, line_idx[idx]);
+                            PalmFlickDebugPrint("[PalmFlick][F] 6\n");
+                            is_tmajor_invalid[idx] = TRUE;
+                            //goto flick_failed;
+                        }
+                        break;
+                    case 2:
+                        if (total_max_tmajor <= (g_pGesture->palm_flick_max_tmajor_threshold - 10))
+                        {
+                            PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n",
+                                    mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_max_tmajor_threshold-10, line_idx[idx]);
+                            PalmFlickDebugPrint("[PalmFlick][F] 7\n");
+                            is_tmajor_invalid[idx] = TRUE;
+                            //goto flick_failed;
+                        }
+                        break;
+                    case 3:
+                        if (total_max_tmajor < g_pGesture->palm_flick_max_tmajor_threshold)
+                        {
+                            PalmFlickDebugPrint("[PalmFlick][M][F] mtsync_count: %d, max_tmajor: %d(%d) line_idx: %d\n",
+                                    mt_sync_count[idx], total_max_tmajor, g_pGesture->palm_flick_max_tmajor_threshold, line_idx[idx]);
+                            PalmFlickDebugPrint("[PalmFlick][F] 8\n");
+                            is_tmajor_invalid[idx] = TRUE;
+                            //goto flick_failed;
+                        }
+                        break;
+                    default:
+                        PalmFlickDebugPrint("[PalmFlick][M] See more next motion...\n");
+                        break;
+                }
+            }
+
+            if (is_tmajor_invalid[0] && is_tmajor_invalid[1])
+            {
+                PalmFlickDebugPrint("[PalmFlick][M][F] max_tmajor=%d\n", total_max_tmajor);
+                goto flick_failed;
+            }
+
+            current_time = GetTimeInMillis();
+
+            if (current_time - base_time > g_pGesture->palm_flick_time_threshold)
+            {
+                PalmFlickDebugPrint("[PalmFlick][M][F] Release event were not came too long time (%d - %d > %d)\n", current_time, base_time, g_pGesture->palm_flick_time_threshold);
+                PalmFlickDebugPrint("[PalmFlick][F] 10\n");
+                goto flick_failed;
+            }
+
+            break;
+
+        case ET_ButtonRelease:
+            current_x[idx] = g_pGesture->fingers[idx].mx;
+            current_y[idx] = g_pGesture->fingers[idx].my;
+            release_status[idx] = TRUE;
+
+            if ((update_x[idx] == current_x[idx]) && (update_y[idx] == current_y[idx]))
+            {
+                PalmFlickDebugPrint("[PalmFlick][R][F] Press point and release point are the same. base_x=%d, base_y=%d, current_x=%d, current_y=%d\n",
+                        update_x[idx], update_y[idx], current_x[idx], current_y[idx]);
+                PalmFlickDebugPrint("[PalmFlick][F] 10-1\n");
+                break;
+                //goto flick_failed;
+            }
+
+            if (!is_palm)
+            {
+                is_tmajor_invalid[idx] = TRUE;
+
+                if (is_tmajor_invalid[0] && is_tmajor_invalid[1])
+                {
+                    PalmFlickDebugPrint("[PalmFlick][R][F] Insufficient touch major was came(%d)\n", total_max_tmajor);
+                    PalmFlickDebugPrint("[PalmFlick][F] 11\n");
+                    goto flick_failed;
+                }
+            }
+
+            line_idx[idx] = GesturePalmGetHorizIndexWithX(current_x[idx], idx, type);
+
+            if (is_palm && line_idx[idx] == 1)
+            {
+                PalmFlickDebugPrint("[PalmFlick][R] Enough major, but release. base_x=%d, base_y=%d, current_x=%d, current_y=%d\n",
+                        base_x[idx], base_y[idx], current_x[idx], current_y[idx]);
+                is_retry = TRUE;
+                mt_sync_count[idx] = 0;
+                break;
+            }
+
+            if (line_idx[idx] < 0 || line_idx[idx] > PALM_HORIZ_ARRAY_COUNT - 1)
+            {
+                is_line_invalid[idx] = TRUE;
+
+                if (is_line_invalid[0] && is_line_invalid[1])
+                {
+                    PalmFlickDebugPrint("[PalmFlick][R][F] No line_idx is invalid.. base_x: %d, current_x: %d\n", base_x[idx], current_x[idx]);
+                    PalmFlickDebugPrint("[PalmFlick][F] 12\n");
+                    goto flick_failed;
+                }
+            }
+
+            current_time = GetTimeInMillis();
+
+            if (current_time - base_time > g_pGesture->palm_flick_time_threshold)
+            {
+                PalmFlickDebugPrint("[PalmFlick][R][F] Release event were came to have long delay (%d - %d > %d)\n",
+                        current_time, base_time, g_pGesture->palm_flick_time_threshold);
+                PalmFlickDebugPrint("[PalmFlick][F] 13\n");
+                goto flick_failed;
+            }
+
+            direction = (line_idx[idx] <= 1) ? FLICK_EASTWARD : FLICK_WESTWARD;
+            distance = ABS(current_x[idx] - base_x[idx]);
+            duration = current_time - base_time;
+
+            if (!is_retry)
+            {
+                if (GestureHasFingerEventMask(GestureNotifyFlick, 0))
+                {
+                    PalmFlickDebugPrint("[PalmFlick][R] Palm Flick1 !!!, direction=%d, distance=%d\n", direction, distance);
+                    is_palm = FALSE;
+                    GestureHandleGesture_Flick(0, distance, duration, direction);
+                }
+            }
+            else
+            {
+                if (mt_sync_count[idx] < 25)
+                {
+                    PalmFlickDebugPrint("[PalmFlick][R][F] No enough motion=%d\n", mt_sync_count[idx]);
+                    PalmFlickDebugPrint("[PalmFlick][F] 14\n");
+                    goto flick_failed;
+                }
+                else
+                {
+                    if (GestureHasFingerEventMask(GestureNotifyFlick, 0))
+                    {
+                        PalmFlickDebugPrint("[PalmFlick][R] Palm Flick2 !!!, direction=%d, distance=%d\n", direction, distance);
+                        is_palm = FALSE;
+                        GestureHandleGesture_Flick(0, distance, duration, direction);
+                    }
+                }
+            }
+
+            g_pGesture->recognized_gesture |= WPalmFlickFilterMask;
+
+            goto cleanup_flick;
+            break;
+    }
 
-                                               GestureHandleGesture_Flick(num_pressed, distance, duration, direction);
-                                               goto cleanup_flick_recognized;
-                                       }
+    return;
 
-                                       break;
-                               default:
-                                       goto cleanup_flick;
-                                       break;
-                       }
-                       break;
+flick_failed:
 
-               case ET_ButtonRelease:
-                       goto cleanup_flick;
-                       break;
-       }
+    DetailDebugPrint("[PalmFlick][R] flick failed\n");
 
-       return;
+    g_pGesture->recognized_gesture &= ~WPalmFlickFilterMask;
+    g_pGesture->filter_mask |= WPalmFlickFilterMask;
+    goto cleanup_flick;
 
 cleanup_flick:
-       ErrorF("[Flick][R] clenup_flick\n");
-       g_pGesture->recognized_gesture &= ~WFlickFilterMask;
 
-cleanup_flick_recognized:
-       ErrorF("[Flick][R] cleanup_flick_recognized\n");
-       g_pGesture->filter_mask |= WFlickFilterMask;
-       num_pressed = 0;
-       base_time = 0;
-       false_diff_count = 0;
-       diff_base_coord = 0;
-       diff_current_coord = 0;
-       angle = 0.0f;
-       angle_base_x = angle_base_y = 0;
-       return;
+    DetailDebugPrint("[PalmFlick][R] cleanup_flick\n");
+
+    for (int i = 0; i < MAX_MT_DEVICES; i++)
+    {
+        base_x[i] = 0;
+        base_y[i] = 0;
+        update_x[i] = 0;
+        update_y[i] = 0;
+        current_x[i] = 0;
+        current_y[i] = 0;
+        line_idx[i] = 0;
+        press_idx[i] = 0;
+        prev_line_idx[i] = 0;
+        max_tmajor[i] = 0;
+        mt_sync_count[i] = 0;
+        press_status[i] = FALSE;
+        release_status[i] = FALSE;
+        is_tmajor_invalid[i] = TRUE;
+        is_line_invalid[i] = TRUE;
+    }
+
+    total_max_tmajor = 0;
+    is_palm = FALSE;
+    is_retry = FALSE;
+
+    return;
 }
 
-void GestureRecognize_GroupHold(int type, InternalEvent *ev, DeviceIntPtr device, int idx, int timer_expired)
+static int
+GesturePalmGetHorizIndexWithX(int current_x, int idx, int type)
 {
-       static int num_pressed = 0;
-       static int base_area_size = 0;
-       static Time base_time = 0;
-       static int base_cx;
-       static int base_cy;
-       int cx, cy;
-       static pixman_box16_t base_box_ext;
-       int area_size;
-       static int state = GestureEnd;
-
-       static OsTimerPtr hold_event_timer = NULL;
-       static int event_type = GestureNotifyHold;
-
-       if( timer_expired )
-       {
-               if( state <= GestureBegin )
-                       state++;
+    int i;
+    int ret_idx = -1;
+    static int pressed_idx[MAX_MT_DEVICES] = {-1, -1};
+    PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc;
 
-#ifdef __DETAIL_DEBUG__
-               switch( state )
-               {
-                       case GestureBegin:
-                               ErrorF("[GroupHold] HOLD Begin !\n");
-                               break;
-
-                       case GestureUpdate:
-                               ErrorF("[GroupHold] HOLD Update !\n");
-                               break;
-               }
-#endif//__DETAIL_DEBUG__
-
-               if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
-               {
-                       GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
-                       hold_event_timer = TimerSet(hold_event_timer, 0, g_pGesture->hold_time_threshold, GestureEventTimerHandler, (int *)&event_type);
-               }
-               return;
-       }
-
-       switch( type )
-       {
-               case ET_ButtonPress:
-                       g_pGesture->fingers[idx].flags |= PressFlagHold;
-
-                       if( g_pGesture->num_pressed < 2 )
-                               return;
-
-                       if( !base_area_size || g_pGesture->num_pressed > num_pressed )
-                       {
-                               if( state != GestureEnd )
-                               {
-#ifdef __DETAIL_DEBUG__
-                                       ErrorF("[GroupHold][P][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
-#endif//__DETAIL_DEBUG__
-                                       goto cleanup_hold;
-                               }
-
-                               base_area_size = AREA_SIZE(&g_pGesture->area.extents);
-                               base_cx = AREA_CENTER_X(&g_pGesture->area.extents);
-                               base_cy = AREA_CENTER_Y(&g_pGesture->area.extents);
-                               base_time = GetTimeInMillis();
-                               base_box_ext.x1 = base_cx-g_pGesture->hold_move_threshold;
-                               base_box_ext.y1 = base_cy-g_pGesture->hold_move_threshold;
-                               base_box_ext.x2 = base_cx+g_pGesture->hold_move_threshold;
-                               base_box_ext.y2 = base_cy+g_pGesture->hold_move_threshold;
-                               event_type = GestureNotifyHold;
-                               hold_event_timer = TimerSet(hold_event_timer, 0, g_pGesture->hold_time_threshold, GestureEventTimerHandler, (int *)&event_type);
-                       }
-                       num_pressed = g_pGesture->num_pressed;
+    for (i = 0; i < PALM_HORIZ_ARRAY_COUNT; i++)
+    {
+        if (current_x <= pPalmMisc->horiz_coord[i])
+        {
+            DetailDebugPrint("[GesturePalmGetHorizIndexWithX] index=%d, pPalmMisc->horiz_coord[%d]=%d\n", i, i, pPalmMisc->horiz_coord[i]);
 
-#ifdef __DETAIL_DEBUG__
-                       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);
-#endif//__DETAIL_DEBUG__
-                       break;
+            ret_idx = i;
+            goto index_check;
+        }
+    }
 
-               case ET_Motion:
-                       if( !(g_pGesture->fingers[idx].flags & PressFlagHold ) )
-                               break;
+    DetailDebugPrint("[GesturePalmGetHorizIndexWithX]Error ! Failed to get horiz coordinate index !\n");
+    return ret_idx;
 
-                       if( num_pressed < 2 )
-                               return;
+index_check:
 
-                       if( num_pressed != g_pGesture->num_pressed )
-                       {
-                               if( state != GestureEnd )
-                               {
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[GroupHold][M][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
-#endif//__DETAIL_DEBUG__
-                                       goto cleanup_hold;
-                               }
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[GroupHold][M][cleanup] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
-#endif//__DETAIL_DEBUG__
-                               //goto cleanup_hold;
-                       }
-
-                       area_size = AREA_SIZE(&g_pGesture->area.extents);
-                       cx = AREA_CENTER_X(&g_pGesture->area.extents);
-                       cy = AREA_CENTER_Y(&g_pGesture->area.extents);
-#ifdef __DETAIL_DEBUG__
-                       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));
-                       ErrorF("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
-                       ErrorF("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
-#endif//__DETAIL_DEBUG__
-
-                       if(area_size > 0 && base_area_size > 0)
-                       {
-                               if( ((area_size > base_area_size) ? (double)area_size / (double)base_area_size : (double)base_area_size / (double) area_size) >= g_pGesture->hold_area_threshold)
-                               {
-#ifdef __DETAIL_DEBUG__
-                                       ErrorF("[GroupHold][M] No diff between area size(=%d) and base area size(=%d) is bigger than threshold(=%lf)!\n", area_size, base_area_size, ((area_size > base_area_size) ? (double)area_size / (double)base_area_size : (double)base_area_size / (double) area_size));
-#endif//__DETAIL_DEBUG__
-                                       goto cleanup_hold;
-                               }
-                       }
-
-                       if( !INBOX(&base_box_ext, cx, cy) )
-                       {
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[GroupHold][M] No current center coordinates is not in base coordinates box !\n");
-                               ErrorF("[GroupHold][M] cx=%d, base_cx=%d, diff=%d\n", cx, base_cx, ABS(cx-base_cx));
-                               ErrorF("[GroupHold][M] cy=%d, base_cy=%d, diff=%d\n", cy, base_cy, ABS(cy-base_cy));
-#endif//__DETAIL_DEBUG__
-                               goto cleanup_hold;
-                       }
-                       break;
-
-               case ET_ButtonRelease:
-                       if( state != GestureEnd && num_pressed >= 2)
-                       {
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[GroupHold][R][cleanup] No num_finger changed ! num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
-#endif//__DETAIL_DEBUG__
-                               goto cleanup_hold;
-                       }
+    if (type == ET_ButtonPress)
+    {
+        pressed_idx[idx] = ret_idx;
 
-                       //ErrorF("[GroupHold][R] num_pressed=%d, g_pGesture->num_pressed=%d\n", num_pressed, g_pGesture->num_pressed);
-                       if( g_pGesture->num_pressed )
-                               break;
+        // first press is center
+        if (pressed_idx[idx] == PALM_HORIZ_ARRAY_COUNT -2)
+        {
+            DetailDebugPrint("[GesturePalmGetHorizIndexWithX][P] Invalid press area x=%d, idx=%d, pressed_idx=%d\n", current_x, idx, pressed_idx[idx]);
+            ret_idx = -1;
+        }
 
-                       goto cleanup_hold;
-                       break;
-       }
+        DetailDebugPrint("[GesturePalmGetHorizIndexWithX][P] pressed_idx=%d\n", pressed_idx[idx]);
+    }
 
-       return;
+    else if (type == ET_Motion)
+    {
+        DetailDebugPrint("[GesturePalmGetHorizIndexWithX][M] moving x=%d, idx=%d, pressed_idx=%d\n", current_x, idx, pressed_idx[idx]);
+    }
 
-cleanup_hold:
+    else if (type == ET_ButtonRelease)
+    {
+        if ((pressed_idx[idx] == 0) && (ret_idx == (PALM_HORIZ_ARRAY_COUNT - 1)))
+        {
+            DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] From the left to the right ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx);
+        }
+        else if ((pressed_idx[idx] == (PALM_HORIZ_ARRAY_COUNT - 1)) && (ret_idx == 0))
+        {
+            DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] From the right to the left ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx);
+        }
+        else if ((pressed_idx[idx] == ret_idx) && ret_idx != 1)
+        {
+            DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] Relased the same region ! pressed_idx=%d, ret_idx=%d\n", pressed_idx[idx], ret_idx);
+            return 1;
+        }
+        else
+        {
+            DetailDebugPrint("[GesturePalmGetHorizIndexWithX][R] Invalid ! pressed_idx=%d, released_idx=%d\n", pressed_idx[idx], ret_idx);
+            ret_idx = -1;
+        }
+
+        pressed_idx[idx] = -1;
+    }
 
-       if( state == GestureBegin || state == GestureUpdate )
-       {
-               state = GestureEnd;
-               if( GestureHasFingerEventMask(GestureNotifyHold, num_pressed) )
-               {
-                       GestureHandleGesture_Hold(num_pressed, base_cx, base_cy, GetTimeInMillis()-base_time, state);
-               }
-       }
-       else
-       {
-               g_pGesture->recognized_gesture &= ~WHoldFilterMask;
-       }
-
-       g_pGesture->filter_mask |= WHoldFilterMask;
-       num_pressed = 0;
-       base_area_size = 0;
-       base_time = 0;
-       base_cx = base_cy = 0;
-       state = GestureEnd;
-       base_box_ext.x1 = base_box_ext.x2 = base_box_ext.y1 = base_box_ext.y2 = 0;
-       TimerCancel(hold_event_timer);
-       return;
+    return ret_idx;
 }
 
+static int
+GesturePalmGetAbsAxisInfo(DeviceIntPtr dev)
+{
+    int i, found = 0;
+    int numAxes;
+
+    Atom atom_tpalm;
+    Atom atom_mt_slot;
+    Atom atom_tracking_id;
+    Atom atom_tmajor;
+    Atom atom_tminor;
+
+    g_pGesture->tpalm_idx = -1;
+    g_pGesture->tmajor_idx = -1;
+    g_pGesture->tminor_idx = -1;
+
+    if (!dev || !dev->valuator)
+        goto out;
+
+    numAxes = dev->valuator->numAxes;
+
+    atom_tpalm = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_PALM);
+    atom_mt_slot = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_SLOT);
+    atom_tracking_id = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TRACKING_ID);
+    atom_tmajor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR);
+    atom_tminor = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR);
+
+    if (!numAxes || !atom_tpalm || !atom_tmajor || !atom_tminor)
+    {
+        ErrorF("one or more axes is/are not supported!\n");
+        goto out;
+    }
+
+    for (i = 0; i < numAxes; i++)
+    {
+        AxisInfoPtr axes = &dev->valuator->axes[i];
+
+        if (!axes || (axes->mode != Absolute))
+            continue;
+
+        if (axes->label == atom_tpalm)
+        {
+            g_pGesture->tpalm_idx = i;
+            found += 1;
+        }
+        else if (axes->label == atom_tmajor)
+        {
+            g_pGesture->tmajor_idx = i;
+            found += 2;
+        }
+        else if (axes->label == atom_tminor)
+        {
+            g_pGesture->tminor_idx = i;
+            found += 4;
+        }
+    }
+
+    if (found != 7)
+    {
+        ErrorF("Axes for palm recognization are not supported !\n");
+        goto out;
+    }
+
+    g_pGesture->palm_misc.enabled = 1;
+    ErrorF("Axes for palm recognization are supported !\n");
+    return 1;
+
+out:
+    g_pGesture->palm_misc.enabled = 0;
+    ErrorF("Palm recognization is not supported !\n");
+    return 0;
+}
+
+static int
+GestureGetPalmValuator(InternalEvent *ev, DeviceIntPtr device)
+{
+    int mt_palm_idx = g_pGesture->tpalm_idx;
+    int mt_palm = 0;
+
+    DeviceEvent *de = &ev->device_event;
+
+    if (!de)
+    {
+        ErrorF("[GestureGetPalmValuator] de is NULL !\n");
+        return -1;
+    }
+
+    if (mt_palm_idx < 0)
+    {
+        ErrorF("[GestureGetPalmValuator] One or more of axes are not supported !\n");
+        return -1;
+    }
+
+    mt_palm = de->valuators.data[mt_palm_idx];
+
+    HoldDetectorDebugPrint("[GestureGetPalmValuator] mt_palm:%d\n", mt_palm);
+
+    return mt_palm;
+}
+
+static void GestureHoldDetector(int type, InternalEvent *ev, DeviceIntPtr device)
+{
+    int i;
+    int idx = -1;
+    pixman_region16_t tarea1;
+    static int num_pressed = 0;
+    unsigned int hold_area_size;
+    PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc;
+    int palm_flag = 0;
+
+    if (!g_pGesture->has_hold_grabmask)
+    {
+        HoldDetectorDebugPrint("[GestureHoldDetector] g_pGesture->has_hold_grabmask=%d\n", g_pGesture->has_hold_grabmask);
+
+        Mask eventmask = (1L << GestureNotifyHold);
+
+        if ((g_pGesture->grabMask & eventmask) &&
+                (g_pGesture->GrabEvents[GestureNotifyHold].pGestureGrabWinInfo[0].window != None))
+        {
+            g_pGesture->has_hold_grabmask = 1;
+
+            //Initialize a set of variables
+            num_pressed = 0;
+            memset(&g_pGesture->cts, 0, sizeof(g_pGesture->cts));
+            pixman_region_init(&g_pGesture->chold_area);
+
+            HoldDetectorDebugPrint("[GestureHoldDetector] Initialize...\n");
+        }
+        else
+        {
+            //reset local hold_grab_mask variable
+            g_pGesture->has_hold_grabmask = 0;
+
+            g_pGesture->hold_detector_activate = 0;
+            HoldDetectorDebugPrint("[GestureHoldDetector] has_hold_grabmask=0 and g_pGesture->hold_detector_activate=0\n");
+            return;
+        }
+    }
+
+    if (IGNORE_EVENTS == g_pGesture->ehtype ||
+            device->id < g_pGesture->first_fingerid)
+    {
+        HoldDetectorDebugPrint("[GestureHoldDetector] Return (IGNORE_EVENTS or device->id:%d < first_fingerid:%d)\n", device->id, g_pGesture->first_fingerid);
+        return;
+    }
+
+    palm_flag = GestureGetPalmValuator(ev, device);
+
+    if (palm_flag)
+    {
+        GestureHandleGesture_Hold(0, 0, 0, PALM_HOLD_TIME_THRESHOLD, GestureBegin);
+        GestureHandleGesture_Hold(0, 0, 0, PALM_HOLD_TIME_THRESHOLD, GestureEnd);
+
+        g_pGesture->hold_detector_activate = 0;
+        g_pGesture->has_hold_grabmask = 0;
+        HoldDetectorDebugPrint("[GestureHoldDetector] palm_flag:%d enable\n", palm_flag);
+        return;
+    }
+    else
+    {
+        HoldDetectorDebugPrint("[GestureHoldDetector] palm_flag:%d disable\n", palm_flag);
+        return;
+    }
+
+    HoldDetectorDebugPrint("[GestureHoldDetector] g_pGesture->num_mt_devices:%d\n", g_pGesture->num_mt_devices);
+
+    for (i = 0; i < g_pGesture->num_mt_devices; i++)
+    {
+        if ( device->id == g_pGesture->mt_devices[i]->id)
+        {
+            idx = i;
+            HoldDetectorDebugPrint("[GestureHoldDetector] idx:%d\n", idx);
+            break;
+        }
+    }
+    if ((idx < 0) || ((MAX_MT_DEVICES-1) < idx)) return;
+
+    switch (type)
+    {
+        case ET_ButtonPress:
+            g_pGesture->cts[idx].status = BTN_PRESSED;
+            g_pGesture->cts[idx].cx = ev->device_event.root_x;
+            g_pGesture->cts[idx].cy = ev->device_event.root_y;
+            num_pressed++;
+            HoldDetectorDebugPrint("[GestureHoldDetector][P] cx:%d, cy:%d, num_pressed:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy, num_pressed);
+
+            if (num_pressed < 2)
+            {
+                HoldDetectorDebugPrint("[GestureHoldDetector][P] num_pressed:%d\n", num_pressed);
+                break;
+            }
+
+            if (num_pressed > g_pGesture->num_mt_devices)
+                num_pressed = g_pGesture->num_mt_devices;
+
+            pixman_region_init(&tarea1);
+            pixman_region_init(&g_pGesture->chold_area);
+            pixman_region_init_rect(&tarea1, g_pGesture->cts[0].cx, g_pGesture->cts[0].cy, g_pGesture->cts[0].cx+1, g_pGesture->cts[0].cy+1);
+
+            tarea1.extents.x1 = g_pGesture->cts[0].cx;
+            tarea1.extents.x2 = g_pGesture->cts[0].cx+1;
+            tarea1.extents.y1 = g_pGesture->cts[0].cy;
+            tarea1.extents.y2 = g_pGesture->cts[0].cy+1;
+
+            pixman_region_union(&g_pGesture->chold_area, &tarea1, &tarea1);
+
+            for (i = 1; i < num_pressed; i++)
+            {
+                pixman_region_init_rect(&tarea1, g_pGesture->cts[i].cx, g_pGesture->cts[i].cy, g_pGesture->cts[i].cx + 1, g_pGesture->cts[i].cy + 1);
+
+                tarea1.extents.x1 = g_pGesture->cts[i].cx;
+                tarea1.extents.x2 = g_pGesture->cts[i].cx + 1;
+                tarea1.extents.y1 = g_pGesture->cts[i].cy;
+                tarea1.extents.y2 = g_pGesture->cts[i].cy + 1;
+
+                pixman_region_union(&g_pGesture->chold_area, &g_pGesture->chold_area, &tarea1);
+            }
+            break;
+
+        case ET_Motion:
+            if (BTN_RELEASED == g_pGesture->cts[idx].status)
+                return;
+
+            g_pGesture->cts[idx].status = BTN_MOVING;
+            g_pGesture->cts[idx].cx = ev->device_event.root_x;
+            g_pGesture->cts[idx].cy = ev->device_event.root_y;
+
+            HoldDetectorDebugPrint("[GestureHoldDetector][M] cx:%d, cy:%d, num_pressed:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy, num_pressed);
+
+            if (num_pressed < 2)
+            {
+                HoldDetectorDebugPrint("[GestureHoldDetector][M] num_pressed:%d\n", num_pressed);
+                break;
+            }
+
+            pixman_region_init(&tarea1);
+            pixman_region_init(&g_pGesture->chold_area);
+            pixman_region_init_rect(&tarea1, g_pGesture->cts[0].cx, g_pGesture->cts[0].cy, g_pGesture->cts[0].cx+1, g_pGesture->cts[0].cy+1);
+
+            tarea1.extents.x1 = g_pGesture->cts[0].cx;
+            tarea1.extents.x2 = g_pGesture->cts[0].cx+1;
+            tarea1.extents.y1 = g_pGesture->cts[0].cy;
+            tarea1.extents.y2 = g_pGesture->cts[0].cy+1;
+
+            pixman_region_union(&g_pGesture->chold_area, &tarea1, &tarea1);
+
+            for (i = 1; i < num_pressed; i++)
+            {
+                pixman_region_init_rect(&tarea1, g_pGesture->cts[i].cx, g_pGesture->cts[i].cy, g_pGesture->cts[i].cx + 1, g_pGesture->cts[i].cy + 1);
+
+                tarea1.extents.x1 = g_pGesture->cts[i].cx;
+                tarea1.extents.x2 = g_pGesture->cts[i].cx + 1;
+                tarea1.extents.y1 = g_pGesture->cts[i].cy;
+                tarea1.extents.y2 = g_pGesture->cts[i].cy + 1;
+
+                pixman_region_union(&g_pGesture->chold_area, &g_pGesture->chold_area, &tarea1);
+            }
+            break;
+
+        case ET_ButtonRelease:
+            g_pGesture->cts[idx].status = BTN_RELEASED;
+            g_pGesture->cts[idx].cx = ev->device_event.root_x;
+            g_pGesture->cts[idx].cy = ev->device_event.root_y;
+
+            HoldDetectorDebugPrint("[GestureHoldDetector][R] cx:%d, cy:%d\n", g_pGesture->cts[idx].cx, g_pGesture->cts[idx].cy);
+
+            num_pressed--;
+            if (num_pressed <3)
+            {
+                pixman_region_init(&g_pGesture->chold_area);
+            }
+            break;
+    }
+
+    if (num_pressed >= 2)
+    {
+        hold_area_size = AREA_SIZE(&g_pGesture->chold_area.extents);
+
+        HoldDetectorDebugPrint("[GestureHoldDetector] hold_area_size=%d, pPalmMisc->half_scrn_area_size=%d\n", hold_area_size, pPalmMisc->half_scrn_area_size);
+
+        if (pPalmMisc->half_scrn_area_size <= hold_area_size)
+        {
+            GestureHandleGesture_Hold(0, AREA_CENTER_X(&g_pGesture->chold_area.extents), AREA_CENTER_Y(&g_pGesture->chold_area.extents), PALM_HOLD_TIME_THRESHOLD, GestureBegin);
+            GestureHandleGesture_Hold(0, AREA_CENTER_X(&g_pGesture->chold_area.extents), AREA_CENTER_Y(&g_pGesture->chold_area.extents), PALM_HOLD_TIME_THRESHOLD, GestureEnd);
+
+            g_pGesture->hold_detector_activate = 0;
+            g_pGesture->has_hold_grabmask = 0;
+        }
+    }
+    else
+    {
+        hold_area_size = AREA_SIZE(&g_pGesture->chold_area.extents);
+        HoldDetectorDebugPrint("[GestureHoldDetector] num_pressed is under 2, hold_area_size=%d\n", hold_area_size);
+    }
+}
+
+
+static int
+GesturePalmGetScreenInfo()
+{
+    int i;
+    pixman_region16_t tarea;
+    PalmMiscInfoPtr pPalmMisc = &g_pGesture->palm_misc;
+    ScreenPtr pScreen = miPointerCurrentScreen();
+
+    if (!pScreen)
+    {
+        DetailDebugPrint("[X11][GesturePalmGetScreenInfo]Failed to get screen information !\n");
+
+        pPalmMisc->scrn_width = pPalmMisc->scrn_height = 0;
+        return 0;
+    }
+
+    pPalmMisc->scrn_width = pScreen->width;
+    pPalmMisc->scrn_height = pScreen->height;
+    pixman_region_init(&tarea);
+    pixman_region_init_rect(&tarea, 0, 0, pPalmMisc->scrn_width, pPalmMisc->scrn_height);
+
+    DetailDebugPrint("[X11][GesturePalmGetScreenInfo] x2:%d, x2:%d, y2:%d, y1:%d \n", tarea.extents.x2, tarea.extents.x1, tarea.extents.y2, tarea.extents.y1);
+    pPalmMisc->half_scrn_area_size = AREA_SIZE(&tarea.extents);
+    pPalmMisc->half_scrn_area_size = (unsigned int)((double)pPalmMisc->half_scrn_area_size / 4);
+
+    DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->half_scrn_area_size = %d\n", pPalmMisc->half_scrn_area_size);
+
+    for (i = 0; i < PALM_HORIZ_ARRAY_COUNT; i++)
+    {
+        pPalmMisc->horiz_coord[i] = pPalmMisc->scrn_width * ((i+1)/(double)PALM_HORIZ_ARRAY_COUNT);
+        DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->horiz_coord[%d]=%d, pPalmMisc->scrn_width=%d\n", i, pPalmMisc->horiz_coord[i], pPalmMisc->scrn_width);
+    }
+    for (i = 0; i < PALM_VERTI_ARRAY_COUNT; i++)
+    {
+        pPalmMisc->verti_coord[i] = pPalmMisc->scrn_height * ((i+1)/(double)PALM_VERTI_ARRAY_COUNT);
+        DetailDebugPrint("[X11][GesturePalmGetScreenInfo] pPalmMisc->verti_coord[%d]=%d, pPalmMisc->scrn_height=%d\n", i, pPalmMisc->verti_coord[i], pPalmMisc->scrn_height);
+    }
+
+    return 1;
+}
+
+
 static inline void
 GestureEnableDisable()
 {
-       GestureEnable(1, FALSE, g_pGesture->this_device);
+    GestureEnable(1, FALSE, g_pGesture->this_device);
 #if 0
-       if((g_pGesture->grabMask) || (g_pGesture->lastSelectedWin != None))
-       {
-               GestureEnable(1, FALSE, g_pGesture->this_device);
-       }
-       else
-       {
-               GestureEnable(0, FALSE, g_pGesture->this_device);
-       }
+    if ((g_pGesture->grabMask) || (g_pGesture->lastSelectedWin != None))
+    {
+        GestureEnable(1, FALSE, g_pGesture->this_device);
+    }
+    else
+    {
+        GestureEnable(0, FALSE, g_pGesture->this_device);
+    }
 #endif
 }
 
 void
 GestureCbEventsGrabbed(Mask *pGrabMask, GestureGrabEventPtr *pGrabEvent)
 {
-       g_pGesture->grabMask = *pGrabMask;
-       g_pGesture->GrabEvents = (GestureGrabEventPtr)pGrabEvent;
-       GestureEnableDisable();
+    g_pGesture->grabMask = *pGrabMask;
+    g_pGesture->GrabEvents = (GestureGrabEventPtr)pGrabEvent;
+    GestureEnableDisable();
 }
 
 void
 GestureCbEventsSelected(Window win, Mask *pEventMask)
 {
-       g_pGesture->lastSelectedWin = win;
-       g_pGesture->lastSelectedMask = (pEventMask) ? *pEventMask : 0;
-       GestureEnableDisable();
+    g_pGesture->lastSelectedWin = win;
+    g_pGesture->lastSelectedMask = (pEventMask) ? *pEventMask : 0;
+    GestureEnableDisable();
 }
 
 WindowPtr
 GestureGetEventsWindow(void)
 {
-       Mask mask;
-       WindowPtr pWin;
+    Mask mask;
+    WindowPtr pWin;
 
-       pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py);
+    pWin = GestureWindowOnXY(g_pGesture->fingers[0].px, g_pGesture->fingers[0].py);
 
-       if( pWin )
-       {
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[X11][GestureGetEventsWindow] pWin->drawable.id=0x%x\n", pWin->drawable.id);
-#endif//__DETAIL_DEBUG__
-               g_pGesture->gestureWin = pWin->drawable.id;
-       }
-       else
-       {
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[X11][GestureGetEventsWindow] GestureWindowOnXY returns NULL !\n");
-#endif//__DETAIL_DEBUG__
-               return NULL;
-       }
-
-       if(g_pGesture->gestureWin == g_pGesture->lastSelectedWin)
-       {
-               g_pGesture->eventMask = g_pGesture->lastSelectedMask;
-               goto nonempty_eventmask;
-       }
-
-       //check selected event(s)
-       if( !GestureHasSelectedEvents(pWin, &g_pGesture->eventMask) )
-       {
-               g_pGesture->eventMask = 0;
-       }
-       else
-       {
-               g_pGesture->lastSelectedWin = g_pGesture->gestureWin;
-               g_pGesture->lastSelectedMask = g_pGesture->eventMask;
-       }
-
-       if( !g_pGesture->eventMask && !g_pGesture->grabMask)
-       {
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[X11][GestureGetEventsWindow] No grabbed events or no events were selected for window(0x%x) !\n", pWin->drawable.id);
-#endif//__DETAIL_DEBUG__
-               return NULL;
-       }
+    if (pWin)
+    {
+        DetailDebugPrint("[GestureGetEventsWindow] pWin->drawable.id=0x%x\n", pWin->drawable.id);
+        g_pGesture->gestureWin = pWin->drawable.id;
+    }
+    else
+    {
+        DetailDebugPrint("[GestureGetEventsWindow] GestureWindowOnXY returns NULL !\n");
+        return NULL;
+    }
+
+    if (g_pGesture->gestureWin == g_pGesture->lastSelectedWin)
+    {
+        g_pGesture->eventMask = g_pGesture->lastSelectedMask;
+        goto nonempty_eventmask;
+    }
+
+    //check selected event(s)
+    if (!GestureHasSelectedEvents(pWin, &g_pGesture->eventMask))
+    {
+        g_pGesture->eventMask = 0;
+    }
+    else
+    {
+        g_pGesture->lastSelectedWin = g_pGesture->gestureWin;
+        g_pGesture->lastSelectedMask = g_pGesture->eventMask;
+    }
+
+    if (!g_pGesture->eventMask && !g_pGesture->grabMask)
+    {
+        DetailDebugPrint("[X11][GestureGetEventsWindow] No grabbed events or no events were selected for window(0x%x) !\n", pWin->drawable.id);
+        return NULL;
+    }
 
 nonempty_eventmask:
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureGetEventsWindow] g_pGesture->eventMask=0x%x\n", g_pGesture->eventMask);
-#endif//__DETAIL_DEBUG__
+    DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->eventMask=0x%x\n", g_pGesture->eventMask);
+
+    mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask));
+
+    DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x, mask=0x%x\n", g_pGesture->filter_mask, mask);
+
+    g_pGesture->filter_mask = mask;
+
+    DetailDebugPrint("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x\n", g_pGesture->filter_mask);
+
+    return pWin;
+}
+
+static CARD32
+GestureSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+    g_pGesture->filter_mask |= WTapFilterMask;
+    g_pGesture->filter_mask |= WHoldFilterMask;
+    LOGI("[GroupTap][GroupHold] 50ms after 1st finger.\n");
+
+    DetailDebugPrint("[GestureSingleFingerTimerHandler] TapFilterMask, HoldFilterMask \n");
+
+    if ((g_pGesture->event_sum[0] == BTN_PRESSED) && ((g_pGesture->flick_pressed_point <= FLICK_POINT_NONE) && (FLICK_POINT_MAX <= g_pGesture->flick_pressed_point)))
+    {
+        DetailDebugPrint("[GestureSingleFingerTimerHandler] press_point: %d\n", g_pGesture->flick_pressed_point);
+        DetailDebugPrint("[GestureSingleFingerTimerHandler] FlickFilterMask\n");
+        g_pGesture->filter_mask |= WFlickFilterMask;
+    }
+
+    if (g_pGesture->flick_pressed_point == FLICK_POINT_DOWN && abs(g_pGesture->fingers[0].py - g_pGesture->fingers[0].my) < 3)
+    {
+        DetailDebugPrint("[GestureSingleFingerTimerHandler] py: %d, my: %d\n", g_pGesture->fingers[0].py, g_pGesture->fingers[0].my);
+        DetailDebugPrint("[GestureSingleFingerTimerHandler] FlickFilterMask\n");
+        g_pGesture->filter_mask |= WFlickFilterMask;
+    }
+
+    DetailDebugPrint("[GestureSingleFingerTimerHandler] expired !\n");
+
+    if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
+    {
+        if ( ERROR_INVALPTR == GestureFlushOrDrop())
+        {
+            DetailDebugPrint("[GestureSingleFingerTimerHandler] AllFilterMask, Flush!\n");
+            GestureControl(g_pGesture->this_device, DEVICE_OFF);
+        }
+    }
+
+    return 0;
+}
+
+void
+GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
+{
+    int i;
+    static OsTimerPtr single_finger_timer = NULL;
+    int idx = -1;
+
+    if (PROPAGATE_EVENTS == g_pGesture->ehtype || device->id < g_pGesture->first_fingerid)
+    {
+        return;
+    }
+
+    for (i = 0; i < g_pGesture->num_mt_devices; i++)
+    {
+        if (device->id == g_pGesture->mt_devices[i]->id)
+        {
+            idx = i;
+            break;
+        }
+    }
+
+    if (idx < 0)
+        return;
+
+    switch (type)
+    {
+        case ET_ButtonPress:
+            if (idx == 0)
+            {
+                g_pGesture->event_sum[0] = BTN_PRESSED;
+            }
+
+            g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]);
+
+            g_pGesture->fingers[idx].ptime = ev->any.time;
+            g_pGesture->fingers[idx].px = ev->device_event.root_x;
+            g_pGesture->fingers[idx].py = ev->device_event.root_y;
+
+            g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
+            g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
+            g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
+            g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
+
+            g_pGesture->num_pressed++;
+            g_pGesture->inc_num_pressed = g_pGesture->num_pressed;
+
+            if (g_pGesture->inc_num_pressed == 1)
+            {
+                pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+            }
+            else
+            {
+                pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+
+                for (i = 1; i < g_pGesture->inc_num_pressed; i++)
+                {
+                    pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
+                }
+            }
+
+            DetailDebugPrint("[GestureRecognize][P] num_pressed=%d, area_size=%d, px=%d, py=%d\n",
+                    g_pGesture->num_pressed, AREA_SIZE(&g_pGesture->area.extents), g_pGesture->fingers[idx].px, g_pGesture->fingers[idx].py);
+
+            if (g_pGesture->num_pressed == 1)
+            {
+                single_finger_timer = TimerSet(single_finger_timer, 0, 50, GestureSingleFingerTimerHandler, NULL);
+
+                if (g_pGesture->fingers[idx].py <= g_pGesture->flick_press_area)
+                {
+                    if ((!g_pGesture->activate_flick_down)
+                            || (g_pGesture->fingers[idx].px <= (g_pGesture->flick_press_area_left_right))
+                            || (g_pGesture->fingers[idx].px >= (g_pGesture->screen_width - g_pGesture->flick_press_area_left_right)))
+                    {
+                        DetailDebugPrint("[GestureRecognize][P] px=%d, flick_press_area_left_right=%d\n",
+                            g_pGesture->fingers[idx].px, g_pGesture->flick_press_area_left_right);
+                        g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
+                        LOGI("[BackKey][F] Press touch within 40 pixel area from left or right vezel\n");
+                    }
+                    else
+                    {
+                        DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_UP\n");
+                        g_pGesture->flick_pressed_point = FLICK_POINT_UP;
+                    }
+                }
+                else
+                {
+                    LOGI("[BackKey][F] Press touch outside 40 pixel area from upper vezel. \n");
+                }
+
+                if (g_pGesture->fingers[idx].py >= (g_pGesture->screen_height - g_pGesture->flick_press_area))
+                {
+                    if (!g_pGesture->activate_flick_up)
+                    {
+                        g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
+                    }
+                    else
+                    {
+                        DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_DOWN\n");
+                        g_pGesture->flick_pressed_point = FLICK_POINT_DOWN;
+                    }
+                }
+                else if ( g_pGesture->fingers[idx].px <= g_pGesture->flick_press_area_left)
+                {
+                    if (!g_pGesture->activate_flick_right)
+                    {
+                        g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
+                    }
+                    else
+                    {
+                        DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_LEFT\n");
+                        g_pGesture->flick_pressed_point = FLICK_POINT_LEFT;
+                    }
+                }
+
+                DetailDebugPrint("[GestureRecognize][P] flick_press_point: %d\n", g_pGesture->flick_pressed_point);
+
+                if ((g_pGesture->flick_pressed_point <= FLICK_POINT_NONE) || (FLICK_POINT_MAX <= g_pGesture->flick_pressed_point))
+                {
+                    DetailDebugPrint("[GestureRecognize][P] FLICK_POINT_NONE\n");
+                    g_pGesture->filter_mask |= WFlickFilterMask;
+                    g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
+                }
+                else
+                {
+                    g_pGesture->flick_direction = (g_pGesture->flick_pressed_point - 1) * 2;
+                    if ((g_pGesture->flick_direction == FLICK_WESTWARD) && (g_pGesture->power_pressed != 2))
+                    {
+                        DetailDebugPrint("[GestureRecognize][P] Flick WesWard is disable when power is not pressed\n");
+                        g_pGesture->filter_mask |= WFlickFilterMask;
+                        g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
+                    }
+                    if ((g_pGesture->flick_direction < FLICK_NORTHWARD) || (FLICK_NORTHWESTWARD < g_pGesture->flick_direction))
+                    {
+                        DetailDebugPrint("[GestureRecognize][P] Invalid flick direction\n");
+                        g_pGesture->filter_mask |= WFlickFilterMask;
+                        g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
+                    }
+
+                    DetailDebugPrint("[GestureRecognize][P] flick_direction: %d\n", g_pGesture->flick_direction);
+                }
+            }
+            else
+            {
+                DetailDebugPrint("[GestureRecognize][P] Two more fingers come on!\n");
+                TimerCancel(single_finger_timer);
+                single_finger_timer = NULL;
+            }
+            break;
 
-       mask = (GESTURE_FILTER_MASK_ALL & ~(g_pGesture->grabMask | g_pGesture->eventMask));
+        case ET_Motion:
+
+            if (!g_pGesture->fingers[idx].ptime)
+            {
+                DetailDebugPrint("[GestureRecognize][M] Start motion. idx=%d\n", idx);
+                g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]);
+                return;
+            }
+
+            g_pGesture->fingers[idx].mx = ev->device_event.root_x;
+            g_pGesture->fingers[idx].my = ev->device_event.root_y;
+            g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]);
+
+            if (idx == 0)
+            {
+                g_pGesture->event_sum[0] += BTN_MOVING;
+            }
+
+            g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
+            g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
+            g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
+            g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
+
+            if (g_pGesture->inc_num_pressed == 1)
+            {
+                pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+            }
+            else
+            {
+                pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
+
+                for (i = 1; i < g_pGesture->inc_num_pressed; i++)
+                {
+                    pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
+                }
+            }
+
+            DetailDebugPrint("[GestureRecognize][M] num_pressed=%d, area_size=%d, mx=%d, my=%d\n",
+                    g_pGesture->num_pressed, AREA_SIZE(&g_pGesture->area.extents), g_pGesture->fingers[idx].mx, g_pGesture->fingers[idx].my);
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x, mask=0x%x\n", g_pGesture->filter_mask, mask);
-#endif//__DETAIL_DEBUG__
+            break;
 
-       g_pGesture->filter_mask = mask;
+        case ET_ButtonRelease:
+            g_pGesture->fingers[idx].rtime = ev->any.time;
+            g_pGesture->fingers[idx].rx = ev->device_event.root_x;
+            g_pGesture->fingers[idx].ry = ev->device_event.root_y;
+            g_pGesture->max_mt_tmajor[idx] = GestureGetMaxTmajor(ev, g_pGesture->max_mt_tmajor[idx]);
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureGetEventsWindow] g_pGesture->filter_mask=0x%x\n", g_pGesture->filter_mask);
-#endif//__DETAIL_DEBUG__
+            g_pGesture->num_pressed--;
 
-       return pWin;
-}
+            if (g_pGesture->num_pressed == 0)
+            {
+                DetailDebugPrint("[GestureRecognize] All fingers were released !\n");
+            }
+            else if (g_pGesture->num_pressed < 0)
+            {
+                DetailDebugPrint("[GestureRecognize] All fingers were released. But, num_pressed is under 0 !\n");
+            }
 
-static CARD32
-GestureSingleFingerTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
-{
-       g_pGesture->filter_mask |= WTapFilterMask;
-       g_pGesture->filter_mask |= WHoldFilterMask;
+            DetailDebugPrint("[GestureRecognize][R] num_pressed=%d, rx=%d, ry=%d\n",
+                    g_pGesture->num_pressed, g_pGesture->fingers[idx].rx, g_pGesture->fingers[idx].ry);
 
-       if( (g_pGesture->event_sum[0] == BTN_PRESSED) && ( (g_pGesture->flick_pressed_point <= FLICK_POINT_NONE) && (FLICK_POINT_MAX <= g_pGesture->flick_pressed_point) ) )
-       {
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[SingleFingerTimer] press_point: %d\n", g_pGesture->flick_pressed_point);
-#endif//__DETAIL_DEBUG_
-               g_pGesture->filter_mask |= WFlickFilterMask;
-       }
+            break;
+    }
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][Single] expired !\n");
-#endif//__DETAIL_DEBUG__
-
-       if(g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
-       {
-               if( ERROR_INVALPTR == GestureFlushOrDrop() )
-               {
-                       GestureControl(g_pGesture->this_device, DEVICE_OFF);
-               }
-       }
-
-       return 0;
-}
+    if (!(g_pGesture->filter_mask & WFlickFilterMask))
+    {
+        DetailDebugPrint("[GestureRecognize] GestureRecognize_groupFlick !\n");
+        GestureRecognize_GroupFlick(type, ev, device, idx, g_pGesture->flick_pressed_point, g_pGesture->flick_direction);
+    }
+    if (!(g_pGesture->filter_mask & WTapFilterMask))
+    {
+        DetailDebugPrint("[GestureRecognize] GestureRecognize_groupTap !\n");
+        GestureRecognize_GroupTap(type, ev, device, idx, 0);
+    }
+    if (!(g_pGesture->filter_mask & WHoldFilterMask))
+    {
+        DetailDebugPrint("[GestureRecognize] GestureRecognize_groupHold !\n");
+        GestureRecognize_GroupHold(type, ev, device, idx, 0);
+    }
+/*
+    if (!(g_pGesture->filter_mask & WPalmFlickFilterMask))
+    {
+        DetailDebugPrint("[GestureRecognize] GestureRecognize_palmFlick !\n");
+        GestureRecognize_PalmFlick(type, ev, device, idx);
+    }
+*/
+    DetailDebugPrint("[GestureRecognize][N] g_pGesture->filter_mask = 0x%x, g_pGesture->GESTURE_WATCH_FILTER_MASK_ALL = 0x%x, g_pGesture->recognized_gesture=0x%x\n",
+            g_pGesture->filter_mask, GESTURE_WATCH_FILTER_MASK_ALL, g_pGesture->recognized_gesture);
 
-void
-GestureRecognize(int type, InternalEvent *ev, DeviceIntPtr device)
-{
-       int i;
-       static OsTimerPtr single_finger_timer = NULL;
-       int idx = -1;
-
-       if( PROPAGATE_EVENTS == g_pGesture->ehtype ||
-               device->id < g_pGesture->first_fingerid )
-               return;
-
-       for( i = 0 ; i < g_pGesture->num_mt_devices ; i++ )
-       {
-               if( device->id == g_pGesture->mt_devices[i]->id )
-               {
-                       idx = i;
-                       break;
-               }
-       }
-
-       if( idx < 0 )
-               return;
-
-       switch( type )
-       {
-               case ET_ButtonPress:
-                       if( idx == 0 )
-                               g_pGesture->event_sum[0] = BTN_PRESSED;
-                       g_pGesture->fingers[idx].ptime = ev->any.time;
-                       g_pGesture->fingers[idx].px = ev->device_event.root_x;
-                       g_pGesture->fingers[idx].py = ev->device_event.root_y;
-
-                       g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
-                       g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
-                       g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
-                       g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
-
-                       g_pGesture->num_pressed++;
-                       g_pGesture->inc_num_pressed = g_pGesture->num_pressed;
-
-                       if( g_pGesture->inc_num_pressed == 1 )
-                       {
-                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[P][g_pGesture->inc_num_pressed=1] AREA_SIZE(area.extents)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
-#endif//__DETAIL_DEBUG__
-                       }
-                       else
-                       {
-                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
-                               for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
-                               {
-                                       pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
-                               }
-#ifdef __DETAIL_DEBUG__
-                               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));
-#endif//__DETAIL_DEBUG__
-                       }
-#ifdef __DETAIL_DEBUG__
-                       ErrorF("[X11][GestureRecognize][P] g_pGesture->finger_rects\n");
-#endif//__DETAIL_DEBUG__
-                       if(g_pGesture->num_pressed == 1)
-                       {
-                               single_finger_timer = TimerSet(single_finger_timer, 0, 50, GestureSingleFingerTimerHandler, NULL);
-
-                               if( g_pGesture->fingers[idx].py <= g_pGesture->flick_press_area)
-                               {
-                                       if((!g_pGesture->activate_flick_down)
-                                               || (g_pGesture->fingers[idx].px <= (g_pGesture->flick_press_area_left_right))
-                                               || (g_pGesture->fingers[idx].px >= (g_pGesture->screen_width - g_pGesture->flick_press_area_left_right)) )
-                                               g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
-                                       else
-                                               g_pGesture->flick_pressed_point = FLICK_POINT_UP;
-                               }
-                               else if(g_pGesture->fingers[idx].py >= (g_pGesture->screen_height - g_pGesture->flick_press_area))
-                               {
-                                       if(!g_pGesture->activate_flick_up)
-                                               g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
-                                       else
-                                               g_pGesture->flick_pressed_point = FLICK_POINT_DOWN;
-                               }
-                               else if( g_pGesture->fingers[idx].px <= g_pGesture->flick_press_area_left)
-                               {
-                                       if(!g_pGesture->activate_flick_right)
-                                               g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
-                                       else
-                                               g_pGesture->flick_pressed_point = FLICK_POINT_LEFT;
-                               }
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[GestureRecognize] flick_press_point: %d\n", g_pGesture->flick_pressed_point);
-#endif//__DETAIL_DEBUG__
-
-                               if( (g_pGesture->flick_pressed_point <= FLICK_POINT_NONE) || (FLICK_POINT_MAX <= g_pGesture->flick_pressed_point) )
-                               {
-                                       g_pGesture->filter_mask |= WFlickFilterMask;
-                                       g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
-                               }
-                               else
-                               {
-                                       g_pGesture->flick_direction = ( g_pGesture->flick_pressed_point - 1 ) * 2;
-                                       if( (g_pGesture->flick_direction == FLICK_WESTWARD) && (g_pGesture->power_pressed != 2) )
-                                       {
-                                               ErrorF("[GestureRecognize] Flick WesWard is disable when power is not pressed\n");
-                                               g_pGesture->filter_mask |= WFlickFilterMask;
-                                               g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
-                                       }
-                                       if( (g_pGesture->flick_direction < FLICK_NORTHWARD) || (FLICK_NORTHWESTWARD < g_pGesture->flick_direction) )
-                                       {
-                                               ErrorF("[GestureRecognize] Invalid flick direction\n");
-                                               g_pGesture->filter_mask |= WFlickFilterMask;
-                                               g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
-                                       }
-#ifdef __DETAIL_DEBUG__
-                                       ErrorF("[GestureRecognize] flick_direction: %d\n", g_pGesture->flick_direction);
-#endif//__DETAIL_DEBUG__
-                               }
-                       }
-                       else
-                       {
-                               TimerCancel(single_finger_timer);
-                               single_finger_timer = NULL;
-                       }
-                       break;
-
-               case ET_Motion:
-                       if( !g_pGesture->fingers[idx].ptime )
-                               return;
-
-                       g_pGesture->fingers[idx].mx = ev->device_event.root_x;
-                       g_pGesture->fingers[idx].my = ev->device_event.root_y;
-
-                       if( (g_pGesture->inc_num_pressed < 2) && (idx == 0) && (g_pGesture->event_sum[0] == BTN_PRESSED) )
-                       {
-                               g_pGesture->event_sum[0] += BTN_MOVING;
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("no seconds finger comming\n");
-#endif//__DETAIL_DEBUG__
-                               if(g_pGesture->event_sum[0] >= 7)
-                               {
-#ifdef __DETAIL_DEBUG__
-                                       ErrorF("Moving Limit\n");
-#endif//__DETAIL_DEBUG__
-                                       g_pGesture->filter_mask |= WTapFilterMask;
-                                       g_pGesture->filter_mask |= WHoldFilterMask;
-                               }
-                               if(g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
-                                       goto flush_or_drop;
-                       }
-
-                       g_pGesture->finger_rects[idx].extents.x1 = ev->device_event.root_x - FINGER_WIDTH;
-                       g_pGesture->finger_rects[idx].extents.x2 = ev->device_event.root_x + FINGER_WIDTH;
-                       g_pGesture->finger_rects[idx].extents.y1 =  ev->device_event.root_y - FINGER_HEIGHT;
-                       g_pGesture->finger_rects[idx].extents.y2 =  ev->device_event.root_y + FINGER_HEIGHT;
-
-                       if( g_pGesture->inc_num_pressed == 1 )
-                       {
-                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[M][g_pGesture->inc_num_pressed=1] AREA_SIZE(area)=%d\n", AREA_SIZE(&g_pGesture->area.extents));
-#endif//__DETAIL_DEBUG__
-                       }
-                       else
-                       {
-                               pixman_region_union(&g_pGesture->area, &g_pGesture->finger_rects[0], &g_pGesture->finger_rects[0]);
-                               for( i = 1 ; i < g_pGesture->inc_num_pressed ; i++ )
-                               {
-                                       pixman_region_union(&g_pGesture->area, &g_pGesture->area, &g_pGesture->finger_rects[i]);
-                               }
-#ifdef __DETAIL_DEBUG__
-                               ErrorF("[M][g_pGesture->inc_num_pressed=%d] AREA_SIZE(area)=%d\n", g_pGesture->inc_num_pressed, AREA_SIZE(&g_pGesture->area.extents));
-#endif//__DETAIL_DEBUG__
-                       }
-                       break;
-
-               case ET_ButtonRelease:
-                       g_pGesture->fingers[idx].rtime = ev->any.time;
-                       g_pGesture->fingers[idx].rx = ev->device_event.root_x;
-                       g_pGesture->fingers[idx].ry = ev->device_event.root_y;
-
-                       g_pGesture->num_pressed--;
-                       if( g_pGesture->num_pressed <= 0 )
-                       {
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureRecognize] All fingers were released !\n");
-#endif//__DETAIL_DEBUG__
-                       }
-                       break;
-       }
-       if( g_pGesture->filter_mask != GESTURE_WATCH_FILTER_MASK_ALL )
-       {
-               if( !(g_pGesture->filter_mask & WFlickFilterMask) )
-               {
-                       GestureRecognize_GroupFlick(type, ev, device, idx, g_pGesture->flick_pressed_point, g_pGesture->flick_direction);
-               }
-               if( !(g_pGesture->filter_mask & WTapFilterMask) )
-               {
-                       GestureRecognize_GroupTap(type, ev, device, idx, 0);
-               }
-               if( !(g_pGesture->filter_mask & WHoldFilterMask) )
-               {
-                       GestureRecognize_GroupHold(type, ev, device, idx, 0);
-               }
-       }
+    if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
+    {
+        if (!g_pGesture->recognized_gesture)
+        {
+            DetailDebugPrint("[GestureRecognize][F] 1 !\n");
+            goto flush_or_drop;
+        }
+        else if (!g_pGesture->num_pressed)
+        {
+            DetailDebugPrint("[GestureRecognize][F] 2 !\n");
+            goto flush_or_drop;
+        }
+    }
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureRecognize][N] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
-       ErrorF("[X11][GestureRecognize][N] g_pGesture->GESTURE_WATCH_FILTER_MASK_ALL = 0x%x\n", GESTURE_WATCH_FILTER_MASK_ALL);
-       ErrorF("[X11][GestureRecognize][N] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
-#endif//__DETAIL_DEBUG__
-
-       if( g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL )
-       {
-               if( !g_pGesture->recognized_gesture )
-                       goto flush_or_drop;
-               else if( !g_pGesture->num_pressed )
-                       goto flush_or_drop;
-       }
-
-       if( g_pGesture->recognized_gesture )
-       {
-               if( g_pGesture->ehtype == KEEP_EVENTS )
-                       GestureEventsDrop();
-               g_pGesture->ehtype = IGNORE_EVENTS;
-       }
-       return;
+    if (g_pGesture->recognized_gesture)
+    {
+        if (g_pGesture->ehtype == KEEP_EVENTS)
+        {
+            DetailDebugPrint("[GestureRecognize] Keep Event !\n");
+            GestureEventsDrop();
+        }
+        g_pGesture->ehtype = IGNORE_EVENTS;
+    }
+    return;
 
 flush_or_drop:
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[GestureRecognize] GestureFlushOrDrop() !\n");
-#endif//__DETAIL_DEBUG__
-       if( ERROR_INVALPTR == GestureFlushOrDrop() )
-       {
-               GestureControl(g_pGesture->this_device, DEVICE_OFF);
-       }
-}
 
+    DetailDebugPrint("[GestureRecognize] GestureFlushOrDrop() !\n");
+
+    if (ERROR_INVALPTR == GestureFlushOrDrop())
+    {
+        GestureControl(g_pGesture->this_device, DEVICE_OFF);
+    }
+}
 
 ErrorStatus GestureFlushOrDrop(void)
 {
-       ErrorStatus err;
+    ErrorStatus err;
 
-       if( g_pGesture->recognized_gesture )
-       {
-               g_pGesture->ehtype = IGNORE_EVENTS;
-               GestureEventsDrop();
-       }
-       else
-       {
-               g_pGesture->ehtype = PROPAGATE_EVENTS;
+    if (g_pGesture->recognized_gesture)
+    {
+        g_pGesture->ehtype = IGNORE_EVENTS;
+        GestureEventsDrop();
+        DetailDebugPrint("[GestureFlushOrDrop][Drop] IGNORE_EVENTS\n");
+    }
+    else
+    {
+        g_pGesture->ehtype = PROPAGATE_EVENTS;
 
-               err = GestureEventsFlush();
-               if( ERROR_NONE != err )
-                       return err;
+        err = GestureEventsFlush();
 
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
-               ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->GESTURE_WATCH_FILTER_MASK_ALL = 0x%x\n", GESTURE_WATCH_FILTER_MASK_ALL);
-               ErrorF("[X11][GestureFlushOrDrop][F] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
-#endif//__DETAIL_DEBUG__
-       }
+        if (ERROR_NONE != err)
+        {
+            return err;
+        }
 
-       err = GestureRegionsReinit();
-       if( ERROR_NONE != err )
-               return err;
+        DetailDebugPrint("[GestureFlushOrDrop][Flush] PROPAGATE_EVENTS\n");
+        DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->filter_mask = 0x%x\n", g_pGesture->filter_mask);
+        DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->GESTURE_WATCH_FILTER_MASK_ALL = 0x%x\n", GESTURE_WATCH_FILTER_MASK_ALL);
+        DetailDebugPrint("[GestureFlushOrDrop][Flush] g_pGesture->recognized_gesture=0x%x\n", g_pGesture->recognized_gesture);
+    }
+
+    err = GestureRegionsReinit();
+
+    if (ERROR_NONE != err)
+    {
+        return err;
+    }
 
-       g_pGesture->pTempWin = NULL;
-       g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
-       g_pGesture->event_sum[0] = 0;
+    g_pGesture->pTempWin = NULL;
+    g_pGesture->inc_num_pressed = g_pGesture->num_pressed = 0;
+    g_pGesture->event_sum[0] = 0;
 
-       return ERROR_NONE;
+    return ERROR_NONE;
 }
 
 void
 GestureHandleMTSyncEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
-       int i;
+    int i;
+    int idx;
 
 #ifdef __DEBUG_EVENT_HANDLER__
-       ErrorF("\n[X11][GestureHandleMTSyncEvent] (%d:%d) time:%d cur:%d\n",
-                       ev->any_event.deviceid, ev->any_event.sync, (int)ev->any.time, (int)GetTimeInMillis());
-#endif//__DEBUG_EVENT_HANDLER__
+    DetailDebugPrint("[GestureHandleMTSyncEvent] (%d:%d) time:%d cur:%d\n",
+            ev->any_event.deviceid, ev->any_event.sync, (int)ev->any.time, (int)GetTimeInMillis());
+#endif
+
+    if (!g_pGesture->is_active)
+    {
+        g_pGesture->ehtype = PROPAGATE_EVENTS;
+        DetailDebugPrint("[GestureHandleMTSyncEvent] PROPAGATE_EVENT\n");
+        return;
+    }
 
-       if(!g_pGesture->is_active)
-       {
-               g_pGesture->ehtype = PROPAGATE_EVENTS;
-               return;
-       }
-
-       if( MTOUCH_FRAME_SYNC_BEGIN == ev->any_event.sync )
-       {
-               g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_BEGIN;
-               g_pGesture->ehtype = KEEP_EVENTS;
-               g_pGesture->filter_mask = 0;
-               g_pGesture->recognized_gesture = 0;
-               g_pGesture->num_pressed = 0;
-
-               for( i=0 ; i < g_pGesture->num_mt_devices ; i++ )
-                       g_pGesture->fingers[i].ptime = 0;
-       }
-       else if( MTOUCH_FRAME_SYNC_END == ev->any_event.sync )
-       {
-               g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_END;
-               g_pGesture->ehtype = PROPAGATE_EVENTS;
-               g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
-       }
+    if (MTOUCH_FRAME_SYNC_BEGIN == ev->any_event.sync)
+    {
+        DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_BEGIN\n");
+        g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_BEGIN;
+        g_pGesture->ehtype = KEEP_EVENTS;
+        g_pGesture->filter_mask = 0;
+        g_pGesture->recognized_gesture = 0;
+        g_pGesture->hold_detector_activate = 1;
+        g_pGesture->num_pressed = 0;
+        g_pGesture->has_hold_grabmask = 0;
+        g_pGesture->mtsync_total_count = 0;
+
+        for (i=0; i < g_pGesture->num_mt_devices; i++)
+        {
+            g_pGesture->fingers[i].ptime = 0;
+            g_pGesture->max_mt_tmajor[i] = 0;
+        }
+    }
+    else if (MTOUCH_FRAME_SYNC_END == ev->any_event.sync)
+    {
+        DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_END\n");
+        g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_END;
+        g_pGesture->ehtype = PROPAGATE_EVENTS;
+        g_pGesture->flick_pressed_point = FLICK_POINT_NONE;
+        g_pGesture->pTempWin = NULL;
+        g_pGesture->num_pressed = 0;
+        g_pGesture->hold_detected = FALSE;
+    }
+    else if (MTOUCH_FRAME_SYNC_UPDATE == ev->any_event.sync)
+    {
+        g_pGesture->mtsync_status = MTOUCH_FRAME_SYNC_UPDATE;
+        g_pGesture->mtsync_total_count++;
+
+        DetailDebugPrint("[GestureHandleMTSyncEvent] SYNC_Update. mt_total_sync=%d\n", g_pGesture->mtsync_total_count);
+
+        if ((g_pGesture->inc_num_pressed < 2) && (g_pGesture->filter_mask != GESTURE_WATCH_FILTER_MASK_ALL))
+        {
+            if (g_pGesture->num_tap_repeated == 1 || g_pGesture->num_tap_repeated == 2)
+            {
+                if (g_pGesture->mtsync_total_count >= 6)
+                {
+                    DetailDebugPrint("[GestureHandleMTSyncEvent] Moving Limit first tap repeated. tap_repeated: %d, mtsync_total_count: %d\n",
+                            g_pGesture->num_tap_repeated, g_pGesture->mtsync_total_count);
+                    g_pGesture->filter_mask |= WTapFilterMask;
+                    g_pGesture->filter_mask |= WHoldFilterMask;
+                                       LOGI("[GroupTap][GroupHold] Motions are more than 6 between 1st finger and 2nd finger.\n");
+                }
+            }
+
+            if (g_pGesture->filter_mask == GESTURE_WATCH_FILTER_MASK_ALL)
+            {
+                DetailDebugPrint("[GestureHandleMTSyncEvent] Gesture filter mask all. GestureFlushOrDrop() !\n");
+
+                if (ERROR_INVALPTR == GestureFlushOrDrop())
+                {
+                    GestureControl(g_pGesture->this_device, DEVICE_OFF);
+                }
+            }
+        }
+    }
 }
 
+
 void GestureEmulateHWKey(DeviceIntPtr dev, int keycode)
 {
-       if(dev)
-       {
-               xf86PostKeyboardEvent(dev, keycode, 1);
-               xf86PostKeyboardEvent(dev, keycode, 0);
-       }
+    if (dev)
+    {
+        DetailDebugPrint("[GestureEmulateHWKey] keycode=%d\n", keycode);
+        xf86PostKeyboardEvent(dev, keycode, 1);
+        xf86PostKeyboardEvent(dev, keycode, 0);
+    }
 }
 
 void
 GestureHandleButtonPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
 #ifdef __DEBUG_EVENT_HANDLER__
-       ErrorF("[X11][GestureHandleButtonPEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
+    DetailDebugPrint("[GestureHandleButtonPressEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
 #endif//__DEBUG_EVENT_HANDLER__
-       switch( g_pGesture->ehtype )
-       {
-               case KEEP_EVENTS:
-                       if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
-                       {
-                               GestureControl(g_pGesture->this_device, DEVICE_OFF);
-                               return;
-                       }
-
-                       if( g_pGesture->num_mt_devices )
-                               GestureRecognize(ET_ButtonPress, ev, device);
-                       else
-                               device->public.processInputProc(ev, device);
-                       break;
-
-               case PROPAGATE_EVENTS:
-                       device->public.processInputProc(ev, device);
-                       break;
-
-               case IGNORE_EVENTS:
-                       GestureRecognize(ET_ButtonPress, ev, device);
-                       break;
-
-               default:
-                       break;
-       }
+
+    switch (g_pGesture->ehtype)
+    {
+        case KEEP_EVENTS:
+            DetailDebugPrint("[GestureHandleButtonPressEvent] KEEP_EVENT\n");
+
+            if (ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev, device))
+            {
+                GestureControl(g_pGesture->this_device, DEVICE_OFF);
+                return;
+            }
+
+            if (g_pGesture->num_mt_devices)
+            {
+                GestureRecognize(ET_ButtonPress, ev, device);
+            }
+            else
+            {
+                device->public.processInputProc(ev, device);
+            }
+
+            GestureHoldDetector(ET_ButtonPress, ev, device);
+            break;
+
+        case PROPAGATE_EVENTS:
+            DetailDebugPrint("[GestureHandleButtonPressEvent] PROPAGATE_EVENT\n");
+
+            device->public.processInputProc(ev, device);
+            GestureHoldDetector(ET_ButtonPress, ev, device);
+            break;
+
+        case IGNORE_EVENTS:
+            DetailDebugPrint("[GestureHandleButtonPressEvent] IGNORE_EVENTS\n");
+
+            GestureRecognize(ET_ButtonPress, ev, device);
+            break;
+
+        default:
+            break;
+    }
 }
 
 void
 GestureHandleMotionEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
-#ifdef __DEBUG_EVENT_HANDLER__
-       ErrorF("[X11][GestureHandleMotionEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
-#endif//__DEBUG_EVENT_HANDLER__
-       switch( g_pGesture->ehtype )
-       {
-               case KEEP_EVENTS:
-                       if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
-                       {
-                               GestureControl(g_pGesture->this_device, DEVICE_OFF);
-                               return;
-                       }
-
-                       if( g_pGesture->num_mt_devices )
-                               GestureRecognize(ET_Motion, ev, device);
-                       else
-                               device->public.processInputProc(ev, device);
-                       break;
-
-               case PROPAGATE_EVENTS:
-                       device->public.processInputProc(ev, device);
-                       break;
-
-               case IGNORE_EVENTS:
-                       GestureRecognize(ET_Motion, ev, device);
-                       break;
-
-               default:
-                       break;
-       }
+#ifdef __DEBUG_EVENT_MOTION_HANDLER__
+    DetailDebugPrint("[GestureHandleMotionEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
+#endif
+
+    switch (g_pGesture->ehtype)
+    {
+        case KEEP_EVENTS:
+            if (ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev, device))
+            {
+                GestureControl(g_pGesture->this_device, DEVICE_OFF);
+                return;
+            }
+
+            if (g_pGesture->num_mt_devices)
+            {
+                GestureRecognize(ET_Motion, ev, device);
+            }
+            else
+            {
+                device->public.processInputProc(ev, device);
+            }
+
+            GestureHoldDetector(ET_Motion, ev, device);
+            break;
+
+        case PROPAGATE_EVENTS:
+            device->public.processInputProc(ev, device);
+            GestureHoldDetector(ET_Motion, ev, device);
+            break;
+
+        case IGNORE_EVENTS:
+            GestureRecognize(ET_Motion, ev, device);
+            break;
+
+        default:
+            break;
+    }
 
 }
 
@@ -1634,508 +2770,618 @@ void
 GestureHandleButtonReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
 #ifdef __DEBUG_EVENT_HANDLER__
-       ErrorF("[X11][GestureHandleButtonREvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
-#endif//__DEBUG_EVENT_HANDLER__
-       switch( g_pGesture->ehtype )
-       {
-               case KEEP_EVENTS:
-                       if( ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device) )
-                       {
-                               GestureControl(g_pGesture->this_device, DEVICE_OFF);
-                               return;
-                       }
-
-                       if( g_pGesture->num_mt_devices )
-                               GestureRecognize(ET_ButtonRelease, ev, device);
-                       else
-                               device->public.processInputProc(ev, device);
-                       break;
-
-               case PROPAGATE_EVENTS:
-                       device->public.processInputProc(ev, device);
+    DetailDebugPrint("[GestureHandleButtonReleaseEvent] devid=%d time:%d cur:%d (%d, %d)\n", device->id, ev->any.time, GetTimeInMillis(), ev->device_event.root_x, ev->device_event.root_y);
+#endif
+
+    switch (g_pGesture->ehtype)
+    {
+        case KEEP_EVENTS:
+            DetailDebugPrint("[GestureHandleButtonPressEvent] KEEP_EVENT\n");
+
+            if (ERROR_INVALPTR == GestureEnqueueEvent(screen_num, ev,  device))
+            {
+                GestureControl(g_pGesture->this_device, DEVICE_OFF);
+                return;
+            }
+
+            if (g_pGesture->num_mt_devices)
+            {
+                GestureRecognize(ET_ButtonRelease, ev, device);
+            }
+            else
+            {
+                device->public.processInputProc(ev, device);
+            }
+
+            GestureHoldDetector(ET_ButtonRelease, ev, device);
+            break;
+
+        case PROPAGATE_EVENTS:
+            DetailDebugPrint("[GestureHandleButtonPressEvent] PROPAGATE_EVENTS\n");
+#ifdef SUPPORT_ANR_WITH_INPUT_EVENT
+                     if( IsMaster(device) && ev->any.type == ET_ButtonRelease )
+                     {
+                         if( g_pGesture->anr_window == NULL )
+                         {
+                             g_pGesture->anr_window = _GestureFindANRWindow(device);
+                         }
+                         Time current_time;
+
+                         // Send event to the e17 process.
+                         current_time = GetTimeInMillis();
+                         if( g_pGesture->anr_window != NULL )
+                         {
+                             // Check anr_window validation.
+                             if( dixLookupWindow(&g_pGesture->anr_window, prop_anr_event_window_xid, serverClient, DixSetPropAccess) != BadWindow )
+                             {
+                                 if( serverClient->devPrivates != NULL )
+                                     dixChangeWindowProperty (serverClient, g_pGesture->anr_window, prop_anr_in_input_event,
+                                                                               XA_CARDINAL, 32, PropModeReplace, 1, &current_time, TRUE);
+                             }
+                             else
+                             {
+                                 prop_anr_event_window_xid = 0;
+                                 g_pGesture->anr_window = NULL;
+                             }
+                             DetailDebugPrint("Release TOUCH!! devid=%d time:%d cur: %d\n", device->id, ev->any.time, GetTimeInMillis());
+                         }
+                     }
+#endif
+            device->public.processInputProc(ev, device);
+            GestureHoldDetector(ET_ButtonRelease, ev, device);
 #if 0
-                       GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_down);
-                       GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_up);
+            GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_down);
+            GestureEmulateHWKey(g_pGesture->hwkey_dev, g_pGesture->hwkeycode_flick_up);
 #endif
-                       break;
+            break;
 
-               case IGNORE_EVENTS:
-                       GestureRecognize(ET_ButtonRelease, ev, device);
-                       break;
+        case IGNORE_EVENTS:
+            DetailDebugPrint("[GestureHandleButtonPressEvent] IGNORE_EVENTS\n");
+            GestureRecognize(ET_ButtonRelease, ev, device);
+            break;
 
-               default:
-                       break;
-       }
- }
+        default:
+            break;
+    }
+}
 
 void
 GestureHandleKeyPressEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
-       if( (ev->device_event.detail.key == 124) && (g_pGesture->power_pressed != 0) )
-       {
-               g_pGesture->power_pressed = 2;
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[GestureHandleKeyPressEvent] power key pressed devid: %d, hwkey_id: %d\n", device->id, g_pGesture->hwkey_id);
-               ErrorF("[GestureHandleKeyPressEvent] power_pressed: %d\n", g_pGesture->power_pressed);
-#endif//__DETAIL_DEBUG__
-               g_pGesture->power_device = device;
-       }
-       device->public.processInputProc(ev, device);
+    if ((ev->device_event.detail.key == 124) && (g_pGesture->power_pressed != 0))
+    {
+        g_pGesture->power_pressed = 2;
+        g_pGesture->power_device = device;
+
+        DetailDebugPrint("[GestureHandleKeyPressEvent] power key pressed devid: %d, hwkey_id: %d\n", device->id, g_pGesture->hwkey_id);
+        DetailDebugPrint("[GestureHandleKeyPressEvent] power_pressed: %d\n", g_pGesture->power_pressed);
+    }
+    device->public.processInputProc(ev, device);
 }
 
 void
 GestureHandleKeyReleaseEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
-       if( (ev->device_event.detail.key == 124) && (g_pGesture->power_pressed != 0) )
-       {
-               g_pGesture->power_pressed = 1;
-#ifdef __DETAIL_DEBUG__
-               ErrorF("[GestureHandleKeyReleaseEvent] power key released devid: %d, hwkey_id: %d\n", device->id, g_pGesture->hwkey_id);
-               ErrorF("[GestureHandleKeyReleaseEvent] power_pressed: %d\n", g_pGesture->power_pressed);
-#endif//__DETAIL_DEBUG__
-               g_pGesture->power_device = device;
-       }
-       device->public.processInputProc(ev, device);
+    if ((ev->device_event.detail.key == 124) && (g_pGesture->power_pressed != 0))
+    {
+        g_pGesture->power_pressed = 1;
+        g_pGesture->power_device = device;
+
+        DetailDebugPrint("[GestureHandleKeyReleaseEvent] power key released devid: %d, hwkey_id: %d\n", device->id, g_pGesture->hwkey_id);
+        DetailDebugPrint("[GestureHandleKeyReleaseEvent] power_pressed: %d\n", g_pGesture->power_pressed);
+    }
+    device->public.processInputProc(ev, device);
+}
+
+static void
+GestureHandleClientState (CallbackListPtr *list, pointer closure, pointer calldata)
+{
+    NewClientInfoRec *clientinfo = (NewClientInfoRec*)calldata;
+    ClientPtr client = clientinfo->client;
+
+    if (client->clientState != ClientStateGone)
+    {
+        return;
+    }
+
+    if (!g_pGesture->factory_cmdname)
+    {
+        return;
+    }
+
+    if (strncmp(client->clientIds->cmdname, g_pGesture->factory_cmdname, strlen(g_pGesture->factory_cmdname)))
+    {
+        return;
+    }
+
+    if (g_pGesture->is_active == 0)
+    {
+        int prop_val = 1;
+        int rc = XIChangeDeviceProperty(g_pGesture->this_device, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &prop_val, FALSE);
+
+        ErrorF("[GestureHandleClientState] %s is exited unintentionally\n", g_pGesture->factory_cmdname);
+
+        if (rc != Success)
+        {
+            ErrorF("[GestureHandleClientState] Failed to Gesture Enable\n");
+            return;
+        }
+    }
 }
 
 static ErrorStatus
 GestureEnableEventHandler(InputInfoPtr pInfo)
- {
-       Bool res;
-       GestureDevicePtr pGesture = pInfo->private;
+{
+    Bool res;
+    GestureDevicePtr pGesture = pInfo->private;
 
-       res = GestureInstallResourceStateHooks();
+    res = GestureInstallResourceStateHooks();
 
-       if( !res )
-       {
-               ErrorF("[X11][GestureEnableEventHandler] Failed on GestureInstallResourceStateHooks() !\n");
-               return ERROR_ABNORMAL;
-       }
+    if (!res)
+    {
+        ErrorF("[GestureEnableEventHandler] Failed on GestureInstallResourceStateHooks() !\n");
+        return ERROR_ABNORMAL;
+    }
 
-       res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES);
+    res = GestureSetMaxNumberOfFingers((int)MAX_MT_DEVICES);
 
-       if( !res )
-       {
-               ErrorF("[X11][GestureEnableEventHandler] Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES);
-               goto failed;
-       }
+    if (!res)
+    {
+        ErrorF("[GestureEnableEventHandler] Failed on GestureSetMaxNumberOfFingers(%d) !\n", (int)MAX_MT_DEVICES);
+        goto failed;
+    }
 
-       res = GestureRegisterCallbacks(GestureCbEventsGrabbed, GestureCbEventsSelected);
+    res = GestureRegisterCallbacks(GestureCbEventsGrabbed, GestureCbEventsSelected);
 
-       if( !res )
-       {
-               ErrorF("[X11][GestureEnableEventHandler] Failed to register callbacks for GestureEventsGrabbed(), GestureEventsSelected() !\n");
-               goto failed;
-       }
+    if (!res)
+    {
+        ErrorF("[GestureEnableEventHandler] Failed to register callbacks for GestureEventsGrabbed(), GestureEventsSelected() !\n");
+        goto failed;
+    }
 
-       pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 5000, GestureTimerHandler, pInfo);
+    pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 5000, GestureTimerHandler, pInfo);
 
-       if( !pGesture->device_setting_timer )
-       {
-               ErrorF("[X11][GestureEnableEventHandler] Failed to set time for detecting devices !\n");
-               goto failed;
-       }
+    if (!pGesture->device_setting_timer)
+    {
+        ErrorF("[GestureEnableEventHandler] Failed to set time for detecting devices !\n");
+        goto failed;
+    }
 
-       return ERROR_NONE;
+    return ERROR_NONE;
 
 failed:
-       GestureUninstallResourceStateHooks();
-       GestureUnsetMaxNumberOfFingers();
+    GestureUninstallResourceStateHooks();
+    GestureUnsetMaxNumberOfFingers();
 
-       return ERROR_ABNORMAL;
+    return ERROR_ABNORMAL;
 }
 
 static ErrorStatus
 GestureDisableEventHandler(void)
 {
-       ErrorStatus err = ERROR_NONE;
+    ErrorStatus err = ERROR_NONE;
 
-       mieqSetHandler(ET_ButtonPress, NULL);
-       mieqSetHandler(ET_ButtonRelease, NULL);
-       mieqSetHandler(ET_Motion, NULL);
-       mieqSetHandler(ET_KeyPress, NULL);
-       mieqSetHandler(ET_KeyRelease, NULL);
-       mieqSetHandler(ET_MTSync, NULL);
+    mieqSetHandler(ET_ButtonPress, NULL);
+    mieqSetHandler(ET_ButtonRelease, NULL);
+    mieqSetHandler(ET_Motion, NULL);
+    mieqSetHandler(ET_KeyPress, NULL);
+    mieqSetHandler(ET_KeyRelease, NULL);
+    mieqSetHandler(ET_MTSync, NULL);
 
-       err = GestureFiniEQ();
+    err = GestureFiniEQ();
 
-       if( ERROR_INVALPTR == err )
-       {
-               ErrorF("[X11][GestureDisableEventHandler] EQ is invalid or was freed already !\n");
-       }
+    if (ERROR_INVALPTR == err)
+    {
+        ErrorF("[GestureDisableEventHandler] EQ is invalid or was freed already !\n");
+    }
 
-       GestureRegisterCallbacks(NULL, NULL);
-       GestureUninstallResourceStateHooks();
+    GestureRegisterCallbacks(NULL, NULL);
+    GestureUninstallResourceStateHooks();
 
-       return err;
+    return err;
 }
 
 static CARD32
 GestureTimerHandler(OsTimerPtr timer, CARD32 time, pointer arg)
 {
-       InputInfoPtr pInfo = (InputInfoPtr)arg;
-       GestureDevicePtr pGesture;
-       int idx;
-       DeviceIntPtr dev;
-
-       if(!pInfo)
-       {
-               ErrorF("[X11][%s] pInfo is NULL !\n", __FUNCTION__);
-               goto failed;
-       }
-
-       pGesture = pInfo->private;
-
-       idx = 0;
-       for( dev = inputInfo.pointer ; dev; dev = dev->next )
-       {
-               if(IsMaster(dev) && IsPointerDevice(dev))
-               {
-                       pGesture->master_pointer = dev;
-                       ErrorF("[X11][GestureTimerHandler][id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name);
-                       continue;
-               }
-
-               if(IsXTestDevice(dev, NULL) && IsPointerDevice(dev))
-               {
-                       pGesture->xtest_pointer = dev;
-                       ErrorF("[X11][GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name);
-                       continue;
-               }
-
-               if(IsPointerDevice(dev))
-               {
-                       if( idx >= MAX_MT_DEVICES )
-                       {
-                               ErrorF("[X11][GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n",
-                                       MAX_MT_DEVICES);
-                               continue;
-                       }
-                       pGesture->mt_devices[idx] = dev;
-                       ErrorF("[X11][GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
-                       idx++;
-               }
-       }
-
-       for( dev = inputInfo.keyboard ; dev; dev = dev->next )
-       {
-               if(g_pGesture->hwkey_name && !strncmp(dev->name, g_pGesture->hwkey_name, strlen(dev->name)))
-               {
-                       g_pGesture->hwkey_id = dev->id;
-                       g_pGesture->hwkey_dev = dev;
-
-                       ErrorF("[X11][%s] hwkey_name has been found. hwkey_id=%d (hwkey_dev->name:%s)\n", __FUNCTION__, g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
-                       break;
-               }
-               else if(!strcasestr(dev->name, "keyboard") && strcasestr(dev->name, "key") && !IsXTestDevice(dev, NULL) && !IsMaster(dev))
-               {
-                       g_pGesture->hwkey_id = dev->id;
-                       g_pGesture->hwkey_dev = dev;
-
-                       ErrorF("[X11][%s] hwkey has been found. hwkey_id=%d (hwkey_dev->name:%s)\n", __FUNCTION__, g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
-                       break;
-               }
-       }
-
-       if(!g_pGesture->hwkey_id)
-       {
-               g_pGesture->hwkey_id = inputInfo.keyboard->id;
-               g_pGesture->hwkey_dev = inputInfo.keyboard;
-
-               ErrorF("[X11][%s] No hwkey has been found. Back key will go through VCK. hwkey_id=%d (hwkey_dev->name:%s)\n",
-                       __FUNCTION__, g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
-       }
-
-       if( !pGesture->master_pointer || !pGesture->xtest_pointer )
-       {
-               ErrorF("[X11][GestureTimerHandler] Failed to get info of master pointer or XTest pointer !\n");
-               pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
-               pGesture->num_mt_devices = 0;
-
-               return 0;
-       }
-
-       TimerCancel(pGesture->device_setting_timer);
-       pGesture->device_setting_timer = NULL;
-       pGesture->num_mt_devices = idx;
-
-       if( !pGesture->num_mt_devices )
-       {
-               ErrorF("[X11][GestureTimerHandler] Failed to mt device information !\n");
-               TimerCancel(pGesture->device_setting_timer);
-               pGesture->device_setting_timer = NULL;
-               pGesture->num_mt_devices = 0;
-               pGesture->first_fingerid = -1;
-               return 0;
-       }
-
-       pGesture->first_fingerid = pGesture->mt_devices[0]->id;
-       memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
-       g_pGesture->pTempWin = NULL;
-       g_pGesture->inc_num_pressed = 0;
-
-       if( ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ() )
-       {
-               goto failed;
-       }
-
-       mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
-       mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
-       mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
-       mieqSetHandler(ET_KeyPress, GestureHandleKeyPressEvent);
-       mieqSetHandler(ET_KeyRelease, GestureHandleKeyReleaseEvent);
-
-       //if( pGesture->is_active )
-               mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
-
-       return 0;
+    InputInfoPtr pInfo = (InputInfoPtr)arg;
+    GestureDevicePtr pGesture;
+    int idx;
+    DeviceIntPtr dev;
 
-failed:
+    if (!pInfo)
+    {
+        ErrorF("[GestureTimerHandler][%s] pInfo is NULL !\n");
+        goto failed;
+    }
+
+    pGesture = pInfo->private;
+
+    idx = 0;
+    for (dev = inputInfo.pointer; dev; dev = dev->next)
+    {
+        if (IsMaster(dev) && IsPointerDevice(dev))
+        {
+            pGesture->master_pointer = dev;
+            ErrorF("[GestureTimerHandler][id:%d] Master Pointer=%s\n", dev->id, pGesture->master_pointer->name);
+            continue;
+        }
+
+        if (IsXTestDevice(dev, NULL) && IsPointerDevice(dev))
+        {
+            pGesture->xtest_pointer = dev;
+            ErrorF("[GestureTimerHandler][id:%d] XTest Pointer=%s\n", dev->id, pGesture->xtest_pointer->name);
+            continue;
+        }
+
+        if (IsPointerDevice(dev))
+        {
+            if (idx >= MAX_MT_DEVICES)
+            {
+                ErrorF("[GestureTimerHandler] Number of mt device is over MAX_MT_DEVICES(%d) !\n", MAX_MT_DEVICES);
+                continue;
+            }
+            pGesture->mt_devices[idx] = dev;
+            ErrorF("[GestureTimerHandler][id:%d] MT device[%d] name=%s\n", dev->id, idx, pGesture->mt_devices[idx]->name);
+            GesturePalmGetAbsAxisInfo(dev);
+            idx++;
+        }
+    }
+
+    for (dev = inputInfo.keyboard ; dev; dev = dev->next)
+    {
+        if (g_pGesture->hwkey_name && !strncmp(dev->name, g_pGesture->hwkey_name, strlen(dev->name)))
+        {
+            g_pGesture->hwkey_id = dev->id;
+            g_pGesture->hwkey_dev = dev;
+
+            ErrorF("[GestureTimerHandler] hwkey_name has been found. hwkey_id=%d (hwkey_dev->name:%s)\n", g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
+            break;
+        }
+        else if (!strcasestr(dev->name, "keyboard") && strcasestr(dev->name, "key") && !IsXTestDevice(dev, NULL) && !IsMaster(dev))
+        {
+            g_pGesture->hwkey_id = dev->id;
+            g_pGesture->hwkey_dev = dev;
+
+            ErrorF("[GestureTimerHandler] hwkey has been found. hwkey_id=%d (hwkey_dev->name:%s)\n", g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
+            break;
+        }
+    }
+
+    if (!g_pGesture->hwkey_id)
+    {
+        g_pGesture->hwkey_id = inputInfo.keyboard->id;
+        g_pGesture->hwkey_dev = inputInfo.keyboard;
+
+        ErrorF("[GestureTimerHandler] No hwkey has been found. Back key will go through VCK. hwkey_id=%d (hwkey_dev->name:%s)\n",
+                g_pGesture->hwkey_id, g_pGesture->hwkey_dev->name);
+    }
 
-       GestureUninstallResourceStateHooks();
-       GestureUnsetMaxNumberOfFingers();
+    if (!pGesture->master_pointer || !pGesture->xtest_pointer)
+    {
+        ErrorF("[GestureTimerHandler] Failed to get info of master pointer or XTest pointer !\n");
+        pGesture->device_setting_timer = TimerSet(pGesture->device_setting_timer, 0, 0, NULL, NULL);
+        pGesture->num_mt_devices = 0;
+
+        return 0;
+    }
+
+    TimerCancel(pGesture->device_setting_timer);
+    pGesture->device_setting_timer = NULL;
+    pGesture->num_mt_devices = idx;
+
+    if (!pGesture->num_mt_devices)
+    {
+        ErrorF("[GestureTimerHandler] Failed to mt device information !\n");
+        TimerCancel(pGesture->device_setting_timer);
+        pGesture->device_setting_timer = NULL;
+        pGesture->num_mt_devices = 0;
+        pGesture->first_fingerid = -1;
+        return 0;
+    }
+
+    pGesture->first_fingerid = pGesture->mt_devices[0]->id;
+    memset(pGesture->fingers, 0, sizeof(TouchStatus)*pGesture->num_mt_devices);
+    pGesture->pRootWin = RootWindow(pGesture->master_pointer);
+
+    if (g_pGesture->palm_misc.enabled)
+    {
+        GesturePalmGetScreenInfo();
+    }
+
+    g_pGesture->pTempWin = NULL;
+    g_pGesture->inc_num_pressed = 0;
+
+    if (ERROR_NONE != GestureRegionsInit() || ERROR_NONE != GestureInitEQ())
+    {
+        goto failed;
+    }
+
+    mieqSetHandler(ET_ButtonPress, GestureHandleButtonPressEvent);
+    mieqSetHandler(ET_ButtonRelease, GestureHandleButtonReleaseEvent);
+    mieqSetHandler(ET_Motion, GestureHandleMotionEvent);
+    mieqSetHandler(ET_KeyPress, GestureHandleKeyPressEvent);
+    mieqSetHandler(ET_KeyRelease, GestureHandleKeyReleaseEvent);
 
-       return 0;
+    //if ( pGesture->is_active)
+    mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
+
+    return 0;
+
+failed:
+    GestureUninstallResourceStateHooks();
+    GestureUnsetMaxNumberOfFingers();
+
+    return 0;
 }
 
 BOOL
 IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
 {
-       if (IsMaster(dev))
-               return FALSE;
+    if (IsMaster(dev))
+    {
+        return FALSE;
+    }
 
-       if (master)
-               return (dev->xtest_master_id == master->id);
+    if (master)
+    {
+        return (dev->xtest_master_id == master->id);
+    }
 
-       return (dev->xtest_master_id != 0);
+    return (dev->xtest_master_id != 0);
 }
 
 void
 GestureEnable(int enable, Bool prop, DeviceIntPtr dev)
 {
-       if((!enable) && (g_pGesture->is_active))
-       {
-               g_pGesture->ehtype = PROPAGATE_EVENTS;
-               mieqSetHandler(ET_MTSync, NULL);
-               g_pGesture->is_active = 0;
-               ErrorF("[X11][GestureEnable] Disabled !\n");
-       }
-       else if((enable) && (!g_pGesture->is_active))
-       {
-               g_pGesture->ehtype = KEEP_EVENTS;
-               mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
-               g_pGesture->is_active = 1;
-               ErrorF("[X11][GestureEnable] Enabled !\n");
-       }
-
-       if(!prop)
-                XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
+    if ((!enable) && (g_pGesture->is_active))
+    {
+        g_pGesture->ehtype = PROPAGATE_EVENTS;
+        mieqSetHandler(ET_MTSync, NULL);
+        g_pGesture->is_active = 0;
+        ErrorF("[GestureEnable] Disabled !\n");
+        int res = AddCallback (&ClientStateCallback, GestureHandleClientState, NULL);
+
+        if (!res)
+        {
+            ErrorF("[GestureEnable] Failed to add callback for client state\n");
+            return;
+        }
+    }
+
+    else if ((enable) && (!g_pGesture->is_active))
+    {
+        g_pGesture->ehtype = KEEP_EVENTS;
+        mieqSetHandler(ET_MTSync, GestureHandleMTSyncEvent);
+        g_pGesture->is_active = 1;
+        ErrorF("[GestureEnable] Enabled !\n");
+
+        DeleteCallback (&ClientStateCallback, GestureHandleClientState, NULL);
+    }
+
+    if (!prop)
+    {
+        XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
+    }
 }
 
 ErrorStatus
 GestureRegionsInit(void)
 {
-       int i;
+    int i;
 
-       if( !g_pGesture )
-               return ERROR_INVALPTR;
+    if (!g_pGesture)
+    {
+        return ERROR_INVALPTR;
+    }
 
-       pixman_region_init(&g_pGesture->area);
+    pixman_region_init(&g_pGesture->area);
 
-       for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
-       {
-               pixman_region_init_rect (&g_pGesture->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T);
-       }
+    for (i = 0; i < MAX_MT_DEVICES; i++)
+    {
+        pixman_region_init_rect(&g_pGesture->finger_rects[i], 0, 0, FINGER_WIDTH_2T, FINGER_HEIGHT_2T);
+    }
 
-       return ERROR_NONE;
+    return ERROR_NONE;
 }
 
 ErrorStatus
 GestureRegionsReinit(void)
 {
-       if( !g_pGesture )
-       {
-               ErrorF("[X11][GestureRegionsReinit] Invalid pointer access !\n");
-               return ERROR_INVALPTR;
-       }
+    if (!g_pGesture)
+    {
+        ErrorF("[GestureRegionsReinit] Invalid pointer access !\n");
+        return ERROR_INVALPTR;
+    }
 
-       pixman_region_init(&g_pGesture->area);
+    pixman_region_init(&g_pGesture->area);
 
-       return ERROR_NONE;
+    return ERROR_NONE;
 }
 
 ErrorStatus
 GestureInitEQ(void)
 {
-       int i;
-       IEventPtr tmpEQ;
-
-       tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec));
-
-       if( !tmpEQ )
-       {
-               ErrorF("[X11][GestureInitEQ] Failed to allocate memory for EQ !\n");
-               return ERROR_ALLOCFAIL;
-       }
-
-       for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
-       {
-               tmpEQ[i].event = (InternalEvent *)malloc(sizeof(InternalEvent));
-               if( !tmpEQ[i].event )
-               {
-                       ErrorF("[X11][GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n");
-                       i--;
-                       while(i >= 0 && tmpEQ[i].event)
-                       {
-                               free(tmpEQ[i].event);
-                               tmpEQ[i].event = NULL;
-                       }
-                       free (tmpEQ);
-                       tmpEQ = NULL;
-                       return ERROR_ALLOCFAIL;
-               }
-       }
-
-       g_pGesture->EQ = tmpEQ;
-       g_pGesture->headEQ = g_pGesture->tailEQ = 0;
-
-       return ERROR_NONE;
+    int i;
+    IEventPtr tmpEQ;
+
+    tmpEQ = (IEventRec *)calloc(GESTURE_EQ_SIZE, sizeof(IEventRec));
+
+    if (!tmpEQ)
+    {
+        ErrorF("[GestureInitEQ] Failed to allocate memory for EQ !\n");
+        return ERROR_ALLOCFAIL;
+    }
+
+    for (i = 0; i < GESTURE_EQ_SIZE; i++)
+    {
+        tmpEQ[i].event = (InternalEvent *)malloc(sizeof(InternalEvent));
+        if (!tmpEQ[i].event)
+        {
+            ErrorF("[GestureInitEQ] Failed to allocation memory for each event buffer in EQ !\n");
+            i--;
+            while(i >= 0 && tmpEQ[i].event)
+            {
+                free(tmpEQ[i].event);
+                tmpEQ[i].event = NULL;
+            }
+            free (tmpEQ);
+            tmpEQ = NULL;
+            return ERROR_ALLOCFAIL;
+        }
+    }
+
+    g_pGesture->EQ = tmpEQ;
+    g_pGesture->headEQ = g_pGesture->tailEQ = 0;
+
+    return ERROR_NONE;
 }
 
 ErrorStatus
 GestureFiniEQ(void)
 {
-       int i;
+    int i;
 
-       if( !g_pGesture || !g_pGesture->EQ )
-               return ERROR_INVALPTR;
+    if (!g_pGesture || !g_pGesture->EQ)
+    {
+        return ERROR_INVALPTR;
+    }
 
-       for( i = 0 ; i < GESTURE_EQ_SIZE ; i++ )
-       {
-               if( g_pGesture->EQ[i].event )
-               {
-                       free(g_pGesture->EQ[i].event);
-                       g_pGesture->EQ[i].event = NULL;
-               }
-       }
+    for (i = 0; i < GESTURE_EQ_SIZE; i++)
+    {
+        if (g_pGesture->EQ[i].event)
+        {
+            free(g_pGesture->EQ[i].event);
+            g_pGesture->EQ[i].event = NULL;
+        }
+    }
 
-       free(g_pGesture->EQ);
-       g_pGesture->EQ = NULL;
+    free(g_pGesture->EQ);
+    g_pGesture->EQ = NULL;
 
-       return ERROR_NONE;
+    return ERROR_NONE;
 }
 
 ErrorStatus
 GestureEnqueueEvent(int screen_num, InternalEvent *ev, DeviceIntPtr device)
 {
-       int tail;
+    int tail;
+
+    if (!g_pGesture || !g_pGesture->EQ)
+    {
+        ErrorF("[GestureEnqueueEvent] Invalid pointer access !\n");
+        return ERROR_INVALPTR;
+    }
+
+    tail = g_pGesture->tailEQ;
 
-       if( !g_pGesture || !g_pGesture->EQ )
-       {
-               ErrorF("[X11][GestureEnqueueEvent] Invalid pointer access !\n");
-               return ERROR_INVALPTR;
-       }
+    if (tail >= GESTURE_EQ_SIZE)
+    {
+        ErrorF("[GestureEnqueueEvent] Gesture EQ is full !\n");
+        printk("[GestureEnqueueEvent] Gesture EQ is full...Force Gesture Flush !\n");
+        GestureEventsFlush();
+        return ERROR_EQFULL;
+    }
 
-       tail = g_pGesture->tailEQ;
+    switch (ev->any.type)
+    {
+        case ET_ButtonPress:
+            DetailDebugPrint("[GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id);
+            break;
 
-       if( tail >= GESTURE_EQ_SIZE )
-       {
-               ErrorF("[X11][GestureEnqueueEvent] Gesture EQ is full !\n");
-               printk("[X11][GestureEnqueueEvent] Gesture EQ is full...Force Gesture Flush !\n");
-               GestureEventsFlush();
-               return ERROR_EQFULL;
-       }
+        case ET_ButtonRelease:
+            DetailDebugPrint("[GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id);
+            break;
 
-#ifdef __DETAIL_DEBUG__
-       switch( ev->any.type )
-       {
-               case ET_ButtonPress:
-                       ErrorF("[X11][GestureEnqueueEvent] ET_ButtonPress (id:%d)\n", device->id);
-                       break;
-
-               case ET_ButtonRelease:
-                       ErrorF("[X11][GestureEnqueueEvent] ET_ButtonRelease (id:%d)\n", device->id);
-                       break;
-
-               case ET_Motion:
-                       ErrorF("[X11][GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id);
-                       break;
-       }
-#endif//__DETAIL_DEBUG__
-
-       g_pGesture->EQ[tail].device = device;
-       g_pGesture->EQ[tail].screen_num = screen_num;
-       memcpy(g_pGesture->EQ[tail].event, ev, sizeof(InternalEvent));//need to be optimized
-       g_pGesture->tailEQ++;
-
-       return ERROR_NONE;
+        case ET_Motion:
+            DetailDebugPrint("[GestureEnqueueEvent] ET_Motion (id:%d)\n", device->id);
+            break;
+    }
+
+    g_pGesture->EQ[tail].device = device;
+    g_pGesture->EQ[tail].screen_num = screen_num;
+    memcpy(g_pGesture->EQ[tail].event, ev, sizeof(InternalEvent));//need to be optimized
+    g_pGesture->tailEQ++;
+
+    return ERROR_NONE;
 }
 
 ErrorStatus
 GestureEventsFlush(void)
 {
-       int i;
-       DeviceIntPtr device;
+    int i;
+    DeviceIntPtr device;
+
+    if (!g_pGesture->EQ)
+    {
+        ErrorF("[GestureEventsFlush] Invalid pointer access !\n");
+        return ERROR_INVALPTR;
+    }
 
-       if( !g_pGesture->EQ )
-       {
-               ErrorF("[X11][GestureEventsFlush] Invalid pointer access !\n");
-               return ERROR_INVALPTR;
-       }
+    DetailDebugPrint("[GestureEventsFlush]\n");
 
-#ifdef __DETAIL_DEBUG__
-       ErrorF("[X11][GestureEventsFlush]\n");
-#endif//__DETAIL_DEBUG__
-       for( i = g_pGesture->headEQ ; i < g_pGesture->tailEQ ; i++)
-       {
-               device = g_pGesture->EQ[i].device;
-               device->public.processInputProc(g_pGesture->EQ[i].event, device);
-       }
-       for( i = 0 ; i < MAX_MT_DEVICES ; i++ )
-               g_pGesture->event_sum[i] = 0;
-       g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
-
-       return ERROR_NONE;
+    for (i = g_pGesture->headEQ; i < g_pGesture->tailEQ; i++)
+    {
+        device = g_pGesture->EQ[i].device;
+        device->public.processInputProc(g_pGesture->EQ[i].event, device);
+    }
+
+    for (i = 0; i < MAX_MT_DEVICES; i++)
+    {
+        g_pGesture->event_sum[i] = 0;
+    }
+
+    g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
+
+    return ERROR_NONE;
 }
 
 void
 GestureEventsDrop(void)
 {
-       g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
+    DetailDebugPrint("[GestureEventsDrop]\n");
+    g_pGesture->headEQ = g_pGesture->tailEQ = 0;//Free EQ
 }
 
 #ifdef HAVE_PROPERTIES
 static void
 GestureInitProperty(DeviceIntPtr dev)
 {
-       int rc;
+    int rc;
+
+#ifdef SUPPORT_ANR_WITH_INPUT_EVENT
+    prop_anr_in_input_event = MakeAtom(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT, strlen(CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT),  TRUE);
+    prop_anr_event_window = MakeAtom(ANR_EVENT_WINDOW, strlen(ANR_EVENT_WINDOW), TRUE);
+#endif
 
-       prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
-       rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
+    prop_gesture_recognizer_onoff = MakeAtom(GESTURE_RECOGNIZER_ONOFF, strlen(GESTURE_RECOGNIZER_ONOFF),  TRUE);
+    rc = XIChangeDeviceProperty(dev, prop_gesture_recognizer_onoff, XA_INTEGER, 32, PropModeReplace, 1, &g_pGesture->is_active, FALSE);
 
-       if (rc != Success)
-               return;
+    if (rc != Success)
+    {
+        return;
+    }
 
-       XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
+    XISetDevicePropertyDeletable(dev, prop_gesture_recognizer_onoff, FALSE);
 }
 
 static int
 GestureSetProperty(DeviceIntPtr dev, Atom atom, XIPropertyValuePtr val,
-                 BOOL checkonly)
+        BOOL checkonly)
 {
-       if( prop_gesture_recognizer_onoff == atom )
-       {
-               int data;
-               if( val->format != 32 || val->type != XA_INTEGER || val->size != 1 )
-                       return BadMatch;
-
-               if( !checkonly )
-               {
-                       data = *((int *)val->data);
-                       GestureEnable(data, TRUE, dev);
-               }
-       }
-       return Success;
+    if (prop_gesture_recognizer_onoff == atom)
+    {
+        int data;
+        if (val->format != 32 || val->type != XA_INTEGER || val->size != 1)
+            return BadMatch;
+
+        if (!checkonly)
+        {
+            data = *((int *)val->data);
+            GestureEnable(data, TRUE, dev);
+        }
+    }
+    return Success;
 }
 #endif//HAVE_PROPERTIES
 
@@ -2143,24 +3389,24 @@ static int
 GestureInit(DeviceIntPtr device)
 {
 #ifdef HAVE_PROPERTIES
-       GestureInitProperty(device);
-       XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
+    GestureInitProperty(device);
+    XIRegisterPropertyHandler(device, GestureSetProperty, NULL, NULL);
 #endif
-       //GestureEnable(1, FALSE, g_pGesture->this_device);
-       return Success;
+    //GestureEnable(1, FALSE, g_pGesture->this_device);
+    return Success;
 }
 
 static void
 GestureFini(DeviceIntPtr device)
 {
-       XIRegisterPropertyHandler(device, NULL, NULL, NULL);
+    XIRegisterPropertyHandler(device, NULL, NULL, NULL);
 }
 
 static pointer
 GesturePlug(pointer module, pointer options, int *errmaj, int *errmin)
 {
-       xf86AddInputDriver(&GESTURE, module, 0);
-       return module;
+    xf86AddInputDriver(&GESTURE, module, 0);
+    return module;
 }
 
 static void
@@ -2172,22 +3418,25 @@ static int
 GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
 {
     int rc = BadAlloc;
-    GestureDevicePtr    pGesture;
+    GestureDevicePtr pGesture;
 
     pGesture = calloc(1, sizeof(GestureDeviceRec));
 
-    if (!pGesture) {
+    if (!pGesture)
+    {
         pInfo->private = NULL;
         //xf86DeleteInput(pInfo, 0);
         goto error;
     }
 
     g_pGesture = pGesture;
+
     pInfo->private = pGesture;
     pInfo->flags = 0;
     pInfo->read_input = GestureReadInput; /* new data avl */
     pInfo->switch_mode = NULL; /* toggle absolute/relative mode */
     pInfo->device_control = GestureControl; /* enable/disable dev */
+
     /* process driver specific options */
     pGesture->device = xf86SetStrOption(pInfo->options, "Device", "/dev/null");
     pGesture->is_active = xf86SetIntOption(pInfo->options, "Activate", 0);
@@ -2196,6 +3445,8 @@ GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
     pGesture->power_pressed = 1;
     pGesture->hwkey_id = 0;
     pGesture->hwkey_dev = NULL;
+    pGesture->num_tap_repeated = 0;
+    pGesture->mtsync_total_count = 0;
     pGesture->hwkey_name = xf86SetStrOption(pInfo->options, "BackHWKeyName", NULL);
     pGesture->screen_width = xf86SetIntOption(pInfo->options,"ScreenWidth", 0);
     pGesture->screen_height = xf86SetIntOption(pInfo->options,"ScreenHeight", 0);
@@ -2208,30 +3459,40 @@ GesturePreInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
     pGesture->shutdown_keycode = xf86SetIntOption(pInfo->options, "ShutdownKeycode", 0);
     pGesture->singletap_threshold= xf86SetIntOption(pInfo->options, "SingleTapThresHold", 0);
     pGesture->doubletap_threshold= xf86SetIntOption(pInfo->options, "DoubleTapThresHold", 0);
+    pGesture->tripletap_threshold= xf86SetIntOption(pInfo->options, "TripleTapThresHold", 0);
     pGesture->hold_area_threshold = xf86SetRealOption(pInfo->options, "HoldAreaThresHold", 0);
     pGesture->hold_move_threshold = xf86SetIntOption(pInfo->options, "HoldMoveThresHold", 0);
     pGesture->hold_time_threshold = xf86SetIntOption(pInfo->options, "HoldTimeThresHold", 0);
+    pGesture->palm_flick_time_threshold = xf86SetIntOption(pInfo->options, "PalmFlickTimeThresHold", 0);
+    pGesture->palm_flick_max_tmajor_threshold = xf86SetIntOption(pInfo->options, "PalmFlickMaxTouchMajorThresHold", 0);
+    pGesture->palm_flick_min_tmajor_threshold = xf86SetIntOption(pInfo->options, "PalmFlickMinTouchMajorThresHold", 0);
     pGesture->activate_flick_down = xf86SetIntOption(pInfo->options, "ActivateFlickDown", 0);
     pGesture->activate_flick_up = xf86SetIntOption(pInfo->options, "ActivateFlickUp", 0);
     pGesture->activate_flick_right = xf86SetIntOption(pInfo->options, "ActivateFlickRight", 0);
+    pGesture->factory_cmdname = xf86SetStrOption(pInfo->options, "FactoryCmdName", NULL);
 
-       ErrorF("[X11][%s] ###############################################################\n", __FUNCTION__);
+    ErrorF("[X11][%s] ###############################################################\n", __FUNCTION__);
     ErrorF("[X11][%s] screen_width=%d, screen_height=%d\n", __FUNCTION__,
-        pGesture->screen_width, pGesture->screen_height);
+            pGesture->screen_width, pGesture->screen_height);
     ErrorF("[X11][%s] FlickDownKeycode=%d, FlickUpKeycode=%d\n", __FUNCTION__,
-        pGesture->hwkeycode_flick_down, pGesture->hwkeycode_flick_up);
+            pGesture->hwkeycode_flick_down, pGesture->hwkeycode_flick_up);
     ErrorF("[X11][%s] flick_press_area=%d, flick_press_area_left: %d, flick_press_area_left_right: %d, flick_minimum_height=%d\n", __FUNCTION__,
-        pGesture->flick_press_area, pGesture->flick_press_area_left, pGesture->flick_press_area_left_right, pGesture->flick_minimum_height);
+            pGesture->flick_press_area, pGesture->flick_press_area_left, pGesture->flick_press_area_left_right, pGesture->flick_minimum_height);
     ErrorF("[X11][%s] ShutdownKeycode=%d\n", __FUNCTION__, pGesture->shutdown_keycode);
     ErrorF("[X11][%s] singletap_threshold=%d, doubletap_threshold=%d\n", __FUNCTION__, pGesture->singletap_threshold, pGesture->doubletap_threshold);
     ErrorF("[X11][%s] hold_area_threshold: %f, hold_move_threshold: %d, hold_time_threshold: %d\n", __FUNCTION__,
-        pGesture->hold_area_threshold, pGesture->hold_move_threshold, pGesture->hold_time_threshold);
+            pGesture->hold_area_threshold, pGesture->hold_move_threshold, pGesture->hold_time_threshold);
+    ErrorF("[X11][%s] palm_flick_time_threshold: %d, palm_flick_max_tmajor_threshold: %d, palm_flick_min_tmajor_threshold: %d\n", __FUNCTION__,
+            pGesture->palm_flick_time_threshold, pGesture->palm_flick_max_tmajor_threshold, pGesture->palm_flick_min_tmajor_threshold);
     ErrorF("[X11][%s] activate_flick_down=%d, activate_flick_up=%d, activate_flick_right=%d\n", __FUNCTION__,
-               pGesture->activate_flick_down, pGesture->activate_flick_up, pGesture->activate_flick_right);
+            pGesture->activate_flick_down, pGesture->activate_flick_up, pGesture->activate_flick_right);
+    ErrorF("[X11][%s] factory cmd name: %s\n", __FUNCTION__, pGesture->factory_cmdname);
     ErrorF("[X11][%s] ###############################################################\n", __FUNCTION__);
 
-    if(pGesture->hwkey_name)
-               ErrorF("[X11][%s] hwkey_name=%s\n", __FUNCTION__, pGesture->hwkey_name);
+    if (pGesture->hwkey_name)
+    {
+        ErrorF("[X11][%s] hwkey_name=%s\n", __FUNCTION__, pGesture->hwkey_name);
+    }
 
     pGesture->mtsync_status = MTOUCH_FRAME_SYNC_END;
     g_pGesture->grabMask = g_pGesture->eventMask = 0;
@@ -2255,12 +3516,12 @@ error:
 static void
 GestureUnInit(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
 {
-       GestureDevicePtr pGesture = pInfo->private;
+    GestureDevicePtr pGesture = pInfo->private;
 
-       g_pGesture = pGesture = NULL;
-       pInfo->private = NULL;
+    g_pGesture = pGesture = NULL;
+    pInfo->private = NULL;
 
-       xf86DeleteInput(pInfo, 0);
+    xf86DeleteInput(pInfo, 0);
 }
 
 static int
@@ -2269,32 +3530,32 @@ GestureControl(DeviceIntPtr device, int what)
     InputInfoPtr  pInfo = device->public.devicePrivate;
     GestureDevicePtr pGesture = pInfo->private;
 
-    switch(what)
+    switch (what)
     {
         case DEVICE_INIT:
-            GestureInit(device);
+            GestureInit(device);
             break;
 
-        /* Switch device on.  Establish socket, start event delivery.  */
+            /* Switch device on.  Establish socket, start event delivery.  */
         case DEVICE_ON:
             xf86Msg(X_INFO, "%s: On.\n", pInfo->name);
 
             if (device->public.on)
-                    break;
+                break;
 
             device->public.on = TRUE;
-            pGesture->this_device = device;
-            pGesture->num_mt_devices = 0;
-            if( ERROR_ABNORMAL == GestureEnableEventHandler(pInfo) )
-               goto device_off;
+            pGesture->this_device = device;
+            pGesture->num_mt_devices = 0;
+            if (ERROR_ABNORMAL == GestureEnableEventHandler(pInfo))
+                goto device_off;
             break;
 
-       case DEVICE_OFF:
+        case DEVICE_OFF:
 device_off:
-            GestureDisableEventHandler();
-            GestureFini(device);
-            pGesture->this_device = NULL;
-             xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
+            GestureDisableEventHandler();
+            GestureFini(device);
+            pGesture->this_device = NULL;
+            xf86Msg(X_INFO, "%s: Off.\n", pInfo->name);
 
             if (!device->public.on)
                 break;
@@ -2303,7 +3564,7 @@ device_off:
             device->public.on = FALSE;
             break;
 
-      case DEVICE_CLOSE:
+        case DEVICE_CLOSE:
             /* free what we have to free */
             break;
     }
@@ -2315,3 +3576,5 @@ GestureReadInput(InputInfoPtr pInfo)
 {
 }
 
+
+
index f61d5a8..e2256db 100755 (executable)
@@ -41,12 +41,25 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define HAVE_PROPERTIES 1
 #endif
 
+/**
+ * If there's touch event in pointed window and there's no reponse, we just assume that client looks like deadlock.
+ * In this case, we will make a popup window and terminate application.
+ * To support this feature, we use SUPPORT_ANR_WITH_INPUT_EVENT flag.
+ */
+#define SUPPORT_ANR_WITH_INPUT_EVENT
+
+#define GESTURE_RECOGNIZER_ONOFF       "GESTURE_RECOGNIZER_ONOFF"
+#define GESTURE_PALM_REJECTION_MODE    "GESTURE_PALM_REJECTION_MODE"
+#define CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT "_CHECK_APPLICATION_NOT_RESPONSE_IN_INPUT_EVENT_"
+#define ANR_EVENT_WINDOW "_ANR_EVENT_WINDOW_"
+
+
 #define SYSCALL(call) while (((call) == -1) && (errno == EINTR))
 #define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
 #define CLIENT_BITS(id) ((id) & RESOURCE_CLIENT_MASK)
 #define CLIENT_ID(id) ((int)(CLIENT_BITS(id) >> CLIENTOFFSET))
 
-#define MAX_MT_DEVICES         10
+#define MAX_MT_DEVICES         2
 #define GESTURE_EQ_SIZE        256
 
 #define GESTURE_RECOGNIZER_ONOFF       "GESTURE_RECOGNIZER_ONOFF"
@@ -68,6 +81,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define SINGLE_TAP_TIMEOUT             100//in msec
 #define DOUBLE_TAP_TIMEOUT     250//in msec
 
+//palm
+#define PALM_HORIZ_ARRAY_COUNT 3
+#define PALM_VERTI_ARRAY_COUNT 4
+
 typedef int XFixed;
 typedef double XDouble;
 #define XDoubleToFixed(f)    ((XFixed) ((f) * 65536))
@@ -100,10 +117,10 @@ enum
 };
 
 #define TAP_AREA_THRESHOLD                     10000//= 100pixel * 100pixel
-#define TAP_MOVE_THRESHOLD                     70//pixel
+#define TAP_MOVE_THRESHOLD                     35//pixel
 #define SGL_TAP_TIME_THRESHOLD         300//ms
 #define DBL_TAP_TIME_THRESHOLD         200//ms
-#define MAX_TAP_REPEATS             2
+#define MAX_TAP_REPEATS             3
 
 #define FLICK_AREA_THRESHOLD                   22500//=150pixel * 150pixel
 #define FLICK_AREA_TIMEOUT                             700//ms
@@ -112,11 +129,20 @@ enum
 #define FLICK_FALSE_Y_DIFF_COUNT               7
 #define FLICK_FALSE_X_DIFF_COUNT               5
 
+#define PALM_FLICK_DETECT_TIMEOUT                      1000//ms
+#define PALM_FLICK_MAX_TOUCH_MAJOR             130
+
+#define AXIS_LABEL_PROP_ABS_MT_TRACKING_ID "Abs MT Tracking ID"
+#define AXIS_LABEL_PROP_ABS_MT_SLOT     "Abs MT Slot"
+#define AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR "Abs MT Touch Major"
+#define AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR "Abs MT Touch Minor"
+#define AXIS_LABEL_PROP_ABS_MT_PALM        "Abs MT Palm/MT Sumsize"
 
 typedef enum _MTSyncType
 {
        MTOUCH_FRAME_SYNC_END,
-       MTOUCH_FRAME_SYNC_BEGIN
+       MTOUCH_FRAME_SYNC_BEGIN,
+       MTOUCH_FRAME_SYNC_UPDATE
 } MTSyncType;
 
 typedef enum _EventHandleType
@@ -319,8 +345,11 @@ enum
 #define WFlickFilterMask                               0x01//(1 << 0)
 #define WTapFilterMask                         0x02//(1 << 1)
 #define WHoldFilterMask                                0x04//(1 << 2)
+#define WPalmFlickFilterMask                   0x08//(1 << 3)
 
-#define GESTURE_WATCH_FILTER_MASK_ALL  0x07//(WFlickFilterMask | WTapFilterMask | WHoldFilterMask)
+#define GESTURE_WATCH_FILTER_MASK_ALL  0x07//(WFlickFilterMask | WTapFilterMask | WHoldFilterMask )
+
+#define PALM_HOLD_TIME_THRESHOLD 150
 
 typedef struct _tagTouchStatus
 {
@@ -338,6 +367,24 @@ typedef struct _tagTouchStatus
        Time rtime;     //current/previous release time
 } TouchStatus;
 
+typedef struct _tagCurrentTouchStatus
+{
+       int status;//One of BTN_RELEASED, BTN_PRESSED and BTN_MOVING
+       int cx;         //current x
+       int cy;         //current y
+} CurTouchStatus;
+
+typedef struct _tagPalmDrvStatus
+{
+       int enabled;
+       int scrn_width;
+       int scrn_height;
+       unsigned int half_scrn_area_size;
+       int horiz_coord[PALM_HORIZ_ARRAY_COUNT];
+       int verti_coord[PALM_VERTI_ARRAY_COUNT];
+} PalmMiscInfo, *PalmMiscInfoPtr;
+
+
 typedef struct _GestureDeviceRec
 {
        char *device;
@@ -361,16 +408,29 @@ typedef struct _GestureDeviceRec
        int activate_flick_right;//left to right
        int screen_width;
        int screen_height;
+
        int singletap_threshold;
        int doubletap_threshold;
+       int tripletap_threshold;
+
+       int num_tap_repeated;
+
        double hold_area_threshold;
        int hold_move_threshold;
        int hold_time_threshold;
 
+       int palm_flick_time_threshold;
+       int palm_flick_max_tmajor_threshold;
+       int palm_flick_min_tmajor_threshold;
+       char *factory_cmdname;
+
+       int max_mt_tmajor[MAX_MT_DEVICES];
+
        int hwkey_id;
        char *hwkey_name;
        DeviceIntPtr hwkey_dev;
        MTSyncType mtsync_status;
+       int mtsync_total_count;
 
        DeviceIntPtr power_device;
 
@@ -389,6 +449,19 @@ typedef struct _GestureDeviceRec
        int headEQ;
        int tailEQ;
 
+       int hold_detector_activate;
+       int has_hold_grabmask;
+       pixman_region16_t chold_area;
+       CurTouchStatus cts[MAX_MT_DEVICES];
+       Bool hold_detected;
+
+       PalmMiscInfo palm_misc;
+       int tmajor_idx;
+       int tminor_idx;
+       int tpalm_idx;
+       int mt_px_idx;
+       int mt_py_idx;
+
        pixman_region16_t area;
        pixman_region16_t finger_rects[MAX_MT_DEVICES];
 
@@ -407,6 +480,8 @@ typedef struct _GestureDeviceRec
        DeviceIntPtr mt_devices[MAX_MT_DEVICES];
        DeviceIntPtr master_pointer;
        DeviceIntPtr xtest_pointer;
+
+       WindowPtr anr_window;
 } GestureDeviceRec, *GestureDevicePtr ;
 
 #endif//_GESTURE_H_