If a single-touch touchpad drops below the pressure threshold in the same
frame where a fake finger is added, we begin a fake touch here. The subsequent
loop ends this fake touch because real_fingers_down is 0.

This causes the tapping code to have a mismatch of how many fingers are down
because it never sees the touch begin event for that finger.

https://bugs.freedesktop.org/show_bug.cgi?id=105160
---
 src/evdev-mt-touchpad-tap.c |  1 +
 src/evdev-mt-touchpad.c     | 16 +++++++++-------
 test/test-touchpad-tap.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+), 7 deletions(-)

diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c
index eaf3a573..fadc9535 100644
--- a/src/evdev-mt-touchpad-tap.c
+++ b/src/evdev-mt-touchpad-tap.c
@@ -1027,6 +1027,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint64_t time)
 
                } else if (t->state == TOUCH_END) {
                        if (t->was_down) {
+                               assert(tp->tap.nfingers_down >= 1);
                                tp->tap.nfingers_down--;
                                tp_tap_handle_event(tp, t, TAP_EVENT_RELEASE, 
time);
                        }
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 02ad9dd8..b3ed6d56 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1102,14 +1102,16 @@ tp_unhover_pressure(struct tp_dispatch *tp, uint64_t 
time)
         * _all_ fingers have enough pressure, even if some of the slotted
         * ones don't. Anything else gets insane quickly.
         */
-       tp_for_each_touch(tp, t) {
-               if (t->state == TOUCH_HOVERING) {
-                       /* avoid jumps when landing a finger */
-                       tp_motion_history_reset(t);
-                       tp_begin_touch(tp, t, time);
+       if (real_fingers_down > 0) {
+               tp_for_each_touch(tp, t) {
+                       if (t->state == TOUCH_HOVERING) {
+                               /* avoid jumps when landing a finger */
+                               tp_motion_history_reset(t);
+                               tp_begin_touch(tp, t, time);
 
-                       if (tp->nfingers_down >= nfake_touches)
-                               break;
+                               if (tp->nfingers_down >= nfake_touches)
+                                       break;
+                       }
                }
        }
 
diff --git a/test/test-touchpad-tap.c b/test/test-touchpad-tap.c
index 06caeb20..0616ae22 100644
--- a/test/test-touchpad-tap.c
+++ b/test/test-touchpad-tap.c
@@ -1591,6 +1591,48 @@ START_TEST(touchpad_3fg_tap_quickrelease)
 }
 END_TEST
 
+START_TEST(touchpad_3fg_tap_hover_btntool)
+{
+       struct litest_device *dev = litest_current_device();
+       struct libinput *li = dev->libinput;
+
+       if (libevdev_get_abs_maximum(dev->evdev,
+                                    ABS_MT_SLOT) >= 2)
+               return;
+
+       litest_enable_tap(dev->libinput_device);
+       litest_enable_edge_scroll(dev);
+
+       litest_drain_events(li);
+
+       litest_touch_down(dev, 0, 50, 50);
+       litest_touch_down(dev, 1, 70, 50);
+       libinput_dispatch(li);
+
+       litest_touch_move_to(dev, 0, 50, 50, 50, 70, 10, 0);
+       litest_touch_move_to(dev, 1, 70, 50, 50, 70, 10, 0);
+       litest_drain_events(li);
+
+       /* drop below the pressure threshold in the same frame as starting a */
+       litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 3);
+       litest_event(dev, EV_ABS, ABS_PRESSURE, 3);
+       litest_event(dev, EV_KEY, BTN_TOUCH, 0);
+       litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
+       litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 1);
+       litest_event(dev, EV_SYN, SYN_REPORT, 0);
+       libinput_dispatch(li);
+
+       litest_push_event_frame(dev);
+       litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 1);
+       litest_event(dev, EV_KEY, BTN_TOOL_TRIPLETAP, 0);
+       litest_pop_event_frame(dev);
+       litest_assert_empty_queue(li);
+
+       litest_touch_up(dev, 0);
+       litest_touch_up(dev, 1);
+}
+END_TEST
+
 START_TEST(touchpad_3fg_tap_btntool)
 {
        struct litest_device *dev = litest_current_device();
@@ -3273,6 +3315,7 @@ litest_setup_tests_touchpad_tap(void)
        litest_add_ranged("tap-3fg:3fg", touchpad_3fg_tap, LITEST_TOUCHPAD, 
LITEST_SINGLE_TOUCH, &tap_map_range);
        litest_add("tap-3fg:3fg", touchpad_3fg_tap_tap_again, LITEST_TOUCHPAD, 
LITEST_SINGLE_TOUCH);
        litest_add("tap-3fg:3fg", touchpad_3fg_tap_quickrelease, 
LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
+       litest_add("tap-3fg:3fg", touchpad_3fg_tap_hover_btntool, 
LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
        litest_add_for_device("tap-3fg:3fg", 
touchpad_3fg_tap_btntool_pointerjump, LITEST_SYNAPTICS_TOPBUTTONPAD);
        litest_add("tap-4fg:4fg", touchpad_4fg_tap, LITEST_TOUCHPAD, 
LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
        litest_add("tap-4fg:4fg", touchpad_4fg_tap_quickrelease, 
LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH|LITEST_SEMI_MT);
-- 
2.14.3

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to