[PATCH libinput 4/4] touchpad: reset the motion history during/after a slots->nfake crossover

Peter Hutterer peter.hutterer at who-t.net
Mon Jul 20 22:51:04 PDT 2015


Whenever we cross from N slots to at least one fake finger, reset the motion
history and skip the next event too. Especially on serial Synaptics touchpads,
the first touch update after a two-slot → TRIPLETAP is garbage, as is the one
from TRIPLETAP → two slots.

Example sequence reproduce on a T440s:

E: 4.488757 0003 003a 0084      # EV_ABS / ABS_MT_PRESSURE      84
E: 4.488757 0003 002f 0001      # EV_ABS / ABS_MT_SLOT          1
E: 4.488757 0003 0039 0433      # EV_ABS / ABS_MT_TRACKING_ID   433
E: 4.488757 0003 0035 2500      # EV_ABS / ABS_MT_POSITION_X    2500
E: 4.488757 0003 0036 3064      # EV_ABS / ABS_MT_POSITION_Y    3064
E: 4.488757 0003 003a 0060      # EV_ABS / ABS_MT_PRESSURE      60
E: 4.488757 0003 0018 0084      # EV_ABS / ABS_PRESSURE         84
E: 4.488757 0001 0145 0000      # EV_KEY / BTN_TOOL_FINGER      0
E: 4.488757 0001 014e 0001      # EV_KEY / BTN_TOOL_TRIPLETAP   1
E: 4.488757 0000 0000 0000      # ------------ SYN_REPORT (0) ----------
E: 4.508506 0003 002f 0000      # EV_ABS / ABS_MT_SLOT          0
E: 4.508506 0003 0036 2982      # EV_ABS / ABS_MT_POSITION_Y    2982
E: 4.508506 0003 003a 0086      # EV_ABS / ABS_MT_PRESSURE      86
E: 4.508506 0003 002f 0001      # EV_ABS / ABS_MT_SLOT          1
E: 4.508506 0003 0035 3464      # EV_ABS / ABS_MT_POSITION_X    3464
E: 4.508506 0003 0036 2716      # EV_ABS / ABS_MT_POSITION_Y    2716
E: 4.508506 0003 0001 2982      # EV_ABS / ABS_Y                2982
E: 4.508506 0003 0018 0086      # EV_ABS / ABS_PRESSURE         86
E: 4.508506 0000 0000 0000      # ------------ SYN_REPORT (0) ----------

subsequent events then hover around the 3464 mark, but that initial jump is
enough to cause a massive cursor jump.

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

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad.c | 29 +++++++++++++++++++++++++++--
 src/evdev-mt-touchpad.h |  9 +++++++++
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 1bf206d..05a9b0f 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -760,6 +760,24 @@ tp_unhover_touches(struct tp_dispatch *tp, uint64_t time)
 
 }
 
+static inline bool
+tp_need_motion_history_reset(struct tp_dispatch *tp)
+{
+	/* semi-mt finger postions may "jump" when nfingers changes */
+	if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
+		return true;
+
+	/* if we're transitioning between slots and fake touches in either
+	 * direction, we may get a coordinate jump
+	 */
+	if (tp->nfingers_down != tp->old_nfingers_down &&
+		 (tp->nfingers_down > tp->num_slots ||
+		 tp->old_nfingers_down > tp->num_slots))
+		return true;
+
+	return false;
+}
+
 static void
 tp_process_state(struct tp_dispatch *tp, uint64_t time)
 {
@@ -767,16 +785,23 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time)
 	struct tp_touch *first = tp_get_touch(tp, 0);
 	unsigned int i;
 	bool restart_filter = false;
+	bool want_motion_reset;
 
 	tp_process_fake_touches(tp, time);
 	tp_unhover_touches(tp, time);
 
+	want_motion_reset = tp_need_motion_history_reset(tp);
+
 	for (i = 0; i < tp->ntouches; i++) {
 		t = tp_get_touch(tp, i);
 
-		/* semi-mt finger postions may "jump" when nfingers changes */
-		if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down)
+		if (want_motion_reset) {
 			tp_motion_history_reset(t);
+			t->quirks.reset_motion_history = true;
+		} else if (t->quirks.reset_motion_history) {
+			tp_motion_history_reset(t);
+			t->quirks.reset_motion_history = false;
+		}
 
 		if (i >= tp->num_slots && t->state != TOUCH_NONE) {
 			t->point = first->point;
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 61c4166..fc6d38e 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -148,6 +148,15 @@ struct tp_touch {
 	int pressure;
 
 	struct {
+		/* A quirk mostly used on Synaptics touchpads. In a
+		   transition to/from fake touches > num_slots, the current
+		   event data is likely garbage and the subsequent event
+		   is likely too. This marker tells us to reset the motion
+		   history again -> this effectively swallows any motion */
+		bool reset_motion_history;
+	} quirks;
+
+	struct {
 		struct device_coords samples[TOUCHPAD_HISTORY_LENGTH];
 		unsigned int index;
 		unsigned int count;
-- 
2.4.3



More information about the wayland-devel mailing list