+ 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);