[PATCH libinput] touchpad: only keep low-pressure fingers alive for 2+-slot touchpads

Peter Hutterer peter.hutterer at who-t.net
Wed Mar 21 03:56:43 UTC 2018


Regression introduced by 3979b9e16a5ed141506d95f80ddfd7b94651dcfa, bug 105258.
With that commit, we only ended real touches when we had less than nslots fake
fingers down. i.e. tripletap on a 2 slot touchpad would not end the
first/second touch even if the pressure goes below the threshold. e.g. Lenovo
x270 needs this, see https://bugs.freedesktop.org/attachment.cgi?id=137672, it
dips below the pressure threshold for the first slot and ends the second slot
in the same frame as the third finger is detected. Fun times.

Anyway, this breaks semi-mt touchpads, another fine category of devices,
because some of those can detect hovering fingers at low pressure, see bug
105535. Because semi-mt devices are generally garbage, we treat them as
single-touch devices instead. So whenever two fingers are down, we treat both
as above the pressure threshold, even when they're physicall hovering.

Fix this by making the x270 fix conditional on at least 2 slots.

https://bugs.freedesktop.org/show_bug.cgi?id=105535

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad.c  |  8 ++++++--
 test/test-touchpad-tap.c |  5 ++++-
 test/test-touchpad.c     | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+), 3 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 1da85c17..99cbcc56 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -1178,8 +1178,12 @@ tp_unhover_pressure(struct tp_dispatch *tp, uint64_t time)
 					tp_begin_touch(tp, t, time);
 				}
 			/* don't unhover for pressure if we have too many
-			 * fake fingers down, see comment below */
-			} else if (nfake_touches <= tp->num_slots) {
+			 * fake fingers down, see comment below. Except
+			 * for single-finger touches where the real touch
+			 * decides for the rest.
+			 */
+			} else if (nfake_touches <= tp->num_slots ||
+				   tp->num_slots == 1) {
 				if (t->pressure < tp->pressure.low) {
 					evdev_log_debug(tp->device,
 							"pressure: end touch %d\n",
diff --git a/test/test-touchpad-tap.c b/test/test-touchpad-tap.c
index 2e1c556d..68b4dc06 100644
--- a/test/test-touchpad-tap.c
+++ b/test/test-touchpad-tap.c
@@ -1620,7 +1620,10 @@ START_TEST(touchpad_3fg_tap_pressure_btntool)
 	litest_drain_events(li);
 
 	/* drop below the pressure threshold in the same frame as starting a
-	 * third touch  */
+	 * third touch, see
+	 *   E: 8713.954784 0001 014e 0001 # EV_KEY / BTN_TOOL_TRIPLETAP   1
+	 * in https://bugs.freedesktop.org/attachment.cgi?id=137672
+	 */
 	litest_event(dev, EV_ABS, ABS_MT_PRESSURE, 3);
 	litest_event(dev, EV_ABS, ABS_PRESSURE, 3);
 	litest_event(dev, EV_KEY, BTN_TOOL_DOUBLETAP, 0);
diff --git a/test/test-touchpad.c b/test/test-touchpad.c
index e2edc32e..4759bfb6 100644
--- a/test/test-touchpad.c
+++ b/test/test-touchpad.c
@@ -5503,6 +5503,45 @@ START_TEST(touchpad_pressure_btntool)
 }
 END_TEST
 
+START_TEST(touchpad_pressure_semi_mt_2fg_goes_light)
+{
+	struct litest_device *dev = litest_current_device();
+	struct libinput *li = dev->libinput;
+	struct axis_replacement axes[] = {
+		{ ABS_PRESSURE, 2 },
+		{ -1, 0 }
+	};
+
+	litest_enable_2fg_scroll(dev);
+	litest_drain_events(li);
+
+	litest_touch_down(dev, 0, 40, 50);
+	litest_touch_down(dev, 1, 60, 50);
+	litest_touch_move_two_touches(dev, 40, 50, 60, 50, 0, -20, 10, 0);
+
+	/* This should trigger a scroll end event */
+	litest_push_event_frame(dev);
+	litest_touch_move_extended(dev, 0, 40, 31, axes);
+	litest_touch_move_extended(dev, 1, 60, 31, axes);
+	litest_pop_event_frame(dev);
+	libinput_dispatch(li);
+
+	litest_assert_scroll(li, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, 0);
+
+	litest_push_event_frame(dev);
+	litest_touch_move_extended(dev, 0, 40, 35, axes);
+	litest_touch_move_extended(dev, 1, 60, 35, axes);
+	litest_pop_event_frame(dev);
+
+	litest_push_event_frame(dev);
+	litest_touch_move_extended(dev, 0, 40, 40, axes);
+	litest_touch_move_extended(dev, 1, 60, 40, axes);
+	litest_pop_event_frame(dev);
+	libinput_dispatch(li);
+	litest_assert_empty_queue(li);
+}
+END_TEST
+
 static inline bool
 touchpad_has_touch_size(struct litest_device *dev)
 {
@@ -5887,6 +5926,7 @@ litest_setup_tests_touchpad(void)
 	litest_add("touchpad:pressure", touchpad_pressure_tap_2fg, LITEST_TOUCHPAD, LITEST_ANY);
 	litest_add("touchpad:pressure", touchpad_pressure_tap_2fg_1fg_light, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
 	litest_add("touchpad:pressure", touchpad_pressure_btntool, LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
+	litest_add("touchpad:pressure", touchpad_pressure_semi_mt_2fg_goes_light, LITEST_SEMI_MT, LITEST_ANY);
 
 	litest_add("touchpad:touch-size", touchpad_touch_size, LITEST_APPLE_CLICKPAD, LITEST_ANY);
 	litest_add("touchpad:touch-size", touchpad_touch_size_2fg, LITEST_APPLE_CLICKPAD, LITEST_ANY);
-- 
2.14.3



More information about the wayland-devel mailing list