From a8e3f4d1a5dbfa785bebcd5ac7f53443d64201ee Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 2 Oct 2018 10:40:47 +1000 Subject: [PATCH] touchpad: ignore motion speed for hovering touches tp_detect_thumb_while_moving() assumes that of the 2 fingers down, at least one must be in TOUCH_UPDATE, otherwise we wouldn't have a speed to analyze for thumb. If a touch starts in HOVERING and exceeds the speed limit, we were previously increasing the 'exceeded count'. This later leads to an assert() in tp_detect_thumb_while_moving() when the second finger comes down because although we have multiple fingers, none of them are in TOUCH_UPDATE. This only happens when fingers 2 and 3 come down in the same event frame, because then we have nfingers_down at 2 (the hovering one doesn't count) but we don't yet have a finger in TOUCH_UPDATE. Fix this twofold, first by now calculating the speed on anything but TOUCH_UPDATE. And second by force-resetting the speed count on TOUCH_BEGIN/TOUCH_END so we definitely cover all the hover transitions. Fixes #150 Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 5 +++++ test/test-touchpad.c | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index ae5fb07c..c22293c1 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -98,6 +98,9 @@ tp_calculate_motion_speed(struct tp_dispatch *tp, struct tp_touch *t) if (!tp->has_mt || tp->semi_mt) return; + if (t->state != TOUCH_UPDATE) + return; + /* This doesn't kick in until we have at least 4 events in the * motion history. As a side-effect, this automatically handles the * 2fg scroll where a finger is down and moving fast before the @@ -332,6 +335,7 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) t->thumb.first_touch_time = time; t->tap.is_thumb = false; t->tap.is_palm = false; + t->speed.exceeded_count = 0; assert(tp->nfingers_down >= 1); tp->hysteresis.last_motion_time = time; } @@ -409,6 +413,7 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) t->pinned.is_pinned = false; t->time = time; t->palm.time = 0; + t->speed.exceeded_count = 0; tp->queued |= TOUCHPAD_EVENT_MOTION; } diff --git a/test/test-touchpad.c b/test/test-touchpad.c index e4667a80..00794dbc 100644 --- a/test/test-touchpad.c +++ b/test/test-touchpad.c @@ -6274,6 +6274,42 @@ START_TEST(touchpad_speed_ignore_finger_edgescroll) } END_TEST +START_TEST(touchpad_speed_ignore_hovering_finger) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct axis_replacement axes[] = { + { ABS_MT_TOUCH_MAJOR, 1 }, + { ABS_MT_TOUCH_MINOR, 1 }, + { -1, 0 } + }; + + litest_drain_events(li); + + /* first finger down but below touch size. we use slot 2 because + * it's easier this way for litest */ + litest_touch_down_extended(dev, 2, 20, 20, axes); + litest_touch_move_to_extended(dev, 2, 20, 20, 60, 80, axes, 20); + litest_drain_events(li); + + /* second, third finger down withn same frame */ + litest_push_event_frame(dev); + litest_touch_down(dev, 0, 59, 70); + litest_touch_down(dev, 1, 65, 70); + litest_pop_event_frame(dev); + + litest_touch_move_two_touches(dev, 59, 70, 65, 70, 0, 30, 10); + libinput_dispatch(li); + + litest_touch_up(dev, 2); + libinput_dispatch(li); + litest_touch_up(dev, 1); + litest_touch_up(dev, 0); + + litest_assert_only_typed_events(li, LIBINPUT_EVENT_POINTER_AXIS); +} +END_TEST + enum suspend { SUSPEND_EXT_MOUSE = 1, SUSPEND_SENDEVENTS, @@ -6778,6 +6814,7 @@ TEST_COLLECTION(touchpad) litest_add("touchpad:speed", touchpad_speed_ignore_finger, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); litest_add("touchpad:speed", touchpad_speed_allow_nearby_finger, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); litest_add("touchpad:speed", touchpad_speed_ignore_finger_edgescroll, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT); + litest_add_for_device("touchpad:speed", touchpad_speed_ignore_hovering_finger, LITEST_BCM5974); litest_add_ranged("touchpad:suspend", touchpad_suspend_abba, LITEST_TOUCHPAD, LITEST_ANY, &suspends); litest_add_ranged("touchpad:suspend", touchpad_suspend_abab, LITEST_TOUCHPAD, LITEST_ANY, &suspends);