Improve disambiguation between two-finger pinch and scroll

A pinch is defined as two fingers moving in different directions, and a
scroll as two fingers moving in the same direction.

Often enough when the user is trying to pinch, we may initially see both
fingers moving in the same direction and decide that they want to
scroll.

Add a grace period during which we may transition to a pinch in those
situations.

Test fix: touchpad_trackpoint_buttons_2fg_scroll emits movements that
change the distance between fingers, which triggers this new transition
and makes the test fail; correct this.

Signed-off-by: novenary <streetwalkermc@gmail.com>
This commit is contained in:
novenary 2021-04-04 18:30:41 +03:00 committed by Peter Hutterer
parent 3dcfae3fb6
commit 939a022cbc
2 changed files with 42 additions and 3 deletions

View file

@ -32,6 +32,8 @@
#define DEFAULT_GESTURE_SWIPE_TIMEOUT ms2us(150)
#define DEFAULT_GESTURE_PINCH_TIMEOUT ms2us(150)
#define PINCH_DISAMBIGUATION_MOVE_THRESHOLD 1.5 /* mm */
static inline const char*
gesture_state_to_str(enum tp_gesture_state state)
{
@ -546,6 +548,33 @@ tp_gesture_detect_motion_gestures(struct tp_dispatch *tp, uint64_t time)
return GESTURE_STATE_PINCH;
}
static bool
tp_gesture_is_pinch(struct tp_dispatch *tp)
{
struct tp_touch *first = tp->gesture.touches[0],
*second = tp->gesture.touches[1];
uint32_t dir1, dir2;
struct phys_coords first_moved, second_moved;
double first_mm, second_mm;
dir1 = tp_gesture_get_direction(tp, first);
dir2 = tp_gesture_get_direction(tp, second);
if (tp_gesture_same_directions(dir1, dir2))
return false;
first_moved = tp_gesture_mm_moved(tp, first);
first_mm = hypot(first_moved.x, first_moved.y);
if (first_mm < PINCH_DISAMBIGUATION_MOVE_THRESHOLD)
return false;
second_moved = tp_gesture_mm_moved(tp, second);
second_mm = hypot(second_moved.x, second_moved.y);
if (second_mm < PINCH_DISAMBIGUATION_MOVE_THRESHOLD)
return false;
return true;
}
static enum tp_gesture_state
tp_gesture_handle_state_none(struct tp_dispatch *tp, uint64_t time)
{
@ -624,6 +653,16 @@ tp_gesture_handle_state_scroll(struct tp_dispatch *tp, uint64_t time)
if (tp->scroll.method != LIBINPUT_CONFIG_SCROLL_2FG)
return GESTURE_STATE_SCROLL;
/* We may confuse a pinch for a scroll initially,
* allow ourselves to correct our guess.
*/
if (time < (tp->gesture.initial_time + DEFAULT_GESTURE_PINCH_TIMEOUT) &&
tp_gesture_is_pinch(tp)) {
tp_gesture_cancel(tp, time);
tp_gesture_init_pinch(tp);
return GESTURE_STATE_PINCH;
}
raw = tp_get_average_touches_delta(tp);
/* scroll is not accelerated */

View file

@ -3401,9 +3401,9 @@ START_TEST(touchpad_trackpoint_buttons_2fg_scroll)
litest_drain_events(li);
litest_touch_down(touchpad, 0, 49, 70);
litest_touch_down(touchpad, 1, 51, 70);
litest_touch_move_two_touches(touchpad, 49, 70, 51, 70, 0, -40, 10);
litest_touch_down(touchpad, 0, 40, 70);
litest_touch_down(touchpad, 1, 60, 70);
litest_touch_move_two_touches(touchpad, 40, 70, 60, 70, 0, -40, 10);
libinput_dispatch(li);
litest_wait_for_event(li);