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 <[email protected]>
---
 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

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to