efl/gesture: more accurately handle flick/momentum recognition with multi-touch

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

Differential Revision: https://phab.enlightenment.org/D11165
This commit is contained in:
Mike Blumenkrantz 2020-01-22 13:51:44 -05:00
parent 9915b34c46
commit 981c3fbad0
2 changed files with 49 additions and 6 deletions

View 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);
@ -214,8 +215,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),

View 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))
{