efl/gesture: more accurately handle flick/momentum recognition with multi-touch
authorMike Blumenkrantz <zmike@samsung.com>
Wed, 22 Jan 2020 18:51:44 +0000 (13:51 -0500)
committerJongmin Lee <jm105.lee@samsung.com>
Tue, 11 Feb 2020 21:58:35 +0000 (06:58 +0900)
if we have one of these gestures where we are flicking/momentuming with multiple
touch points, we want to permit this so long as the touch points are moving vaguely
in the same direction, e.g., press -> swipe with 2 fingers

with this, we now cancel these gestures with multi-touch active if we detect motion
with subsequent touch events that doesn't match the vector of the "active" press
for which we are monitoring events

Reviewed-by: woochan lee <wc0917.lee@samsung.com>
Differential Revision: https://phab.enlightenment.org/D11165

src/lib/evas/gesture/efl_canvas_gesture_recognizer_flick.c
src/lib/evas/gesture/efl_canvas_gesture_recognizer_momentum.c

index 8045416..48ee2ec 100644 (file)
@@ -178,6 +178,7 @@ _efl_canvas_gesture_recognizer_flick_efl_canvas_gesture_recognizer_recognize(Eo
    unsigned char glayer_continues_enable;
    Efl_Canvas_Gesture_Recognizer_Result result = EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
    Eina_Bool touch_up = EINA_FALSE;
+   int points = efl_gesture_touch_points_count_get(event);
    Efl_Canvas_Gesture_Flick_Data *fd = efl_data_scope_get(gesture, EFL_CANVAS_GESTURE_FLICK_CLASS);
    Efl_Canvas_Gesture_Recognizer_Data *rd = efl_data_scope_get(obj, EFL_CANVAS_GESTURE_RECOGNIZER_CLASS);
    Eina_Bool dead = EINA_FALSE;
@@ -220,8 +221,26 @@ _efl_canvas_gesture_recognizer_flick_efl_canvas_gesture_recognizer_recognize(Eo
         if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
           return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
      }
-   if (pd->t_st && (fd->id != efl_gesture_touch_cur_data_get(event)->id))
-     return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+   if (pd->t_st && (points > 1) && (fd->id != efl_gesture_touch_cur_data_get(event)->id))
+     {
+        int xdir[2], ydir[2];
+        const Efl_Gesture_Touch_Point_Data *data = efl_gesture_touch_cur_data_get(event);
+        const Efl_Gesture_Touch_Point_Data *data2;
+
+        if (fd->id == -1) return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+        data2 = efl_gesture_touch_data_get(event, fd->id);
+        xdir[0] = _direction_get(data->prev.pos.x, data->cur.pos.x);
+        ydir[0] = _direction_get(data->prev.pos.y, data->cur.pos.y);
+        xdir[1] = _direction_get(data2->prev.pos.x, data2->cur.pos.x);
+        ydir[1] = _direction_get(data2->prev.pos.y, data2->cur.pos.y);
+        if ((xdir[0] != xdir[1]) || (ydir[0] != ydir[1]))
+          {
+             rd->continues = EINA_FALSE;
+             memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Flick_Data));
+             return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
+          }
+        return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+     }
 
    _single_line_process(obj, pd, gesture, fd, event);
    _vector_get(pd->st_line, efl_gesture_touch_cur_point_get(event),
index a23959a..41f015a 100644 (file)
@@ -77,18 +77,42 @@ _efl_canvas_gesture_recognizer_momentum_efl_canvas_gesture_recognizer_recognize(
    //It does not have any meanging of this gesture.
    if (glayer_continues_enable && !pd->touched)
      {
-        pd->touched = EINA_TRUE;
+        if (efl_gesture_touch_state_get(event) != EFL_GESTURE_TOUCH_STATE_END)
+          {
+             /* guard against successive multi-touch cancels */
+             if (efl_gesture_touch_points_count_get(event) == 1)
+               {
+                  pd->touched = EINA_TRUE;
+                  md->id = -1;
+               }
+          }
 
         return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
      }
    if (pd->touched && (efl_gesture_touch_cur_data_get(event)->action == EFL_POINTER_ACTION_DOWN))
      {
         /* a second finger was pressed at the same time-ish as the first: combine into same event */
-        if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
+        if (efl_gesture_touch_points_count_get(event) > 1)
+          {
+             if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_touch_prev_data_get(event)->cur.timestamp < TAP_TOUCH_TIME_THRESHOLD)
+               return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+          }
+        else if (efl_gesture_touch_cur_timestamp_get(event) - efl_gesture_timestamp_get(gesture) < TAP_TOUCH_TIME_THRESHOLD)
           return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
      }
-   if (pd->t_st && (md->id != efl_gesture_touch_cur_data_get(event)->id))
-     return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+   if (pd->t_st && (md->id != -1) && (md->id != efl_gesture_touch_cur_data_get(event)->id))
+     {
+        int xdir, ydir;
+        const Efl_Gesture_Touch_Point_Data *data = efl_gesture_touch_cur_data_get(event);
+        xdir = _direction_get(data->prev.pos.x, data->cur.pos.x);
+        ydir = _direction_get(data->prev.pos.y, data->cur.pos.y);
+        if ((xdir != pd->xdir) || (ydir != pd->ydir))
+          {
+             memset(pd, 0, sizeof(Efl_Canvas_Gesture_Recognizer_Momentum_Data));
+             return EFL_GESTURE_RECOGNIZER_RESULT_CANCEL;
+          }
+        return EFL_GESTURE_RECOGNIZER_RESULT_IGNORE;
+     }
 
    switch (efl_gesture_touch_state_get(event))
      {