From a87d51f9d70413ced1405673b6c892c57ffcb6c9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 20 Jul 2015 13:10:29 +1000 Subject: [PATCH] touchpad: reset the motion history during/after a slots->nfake crossover MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Hallelujah-expressed-by: Benjamin Tissoires Reviewed-by: Hans de Goede --- 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 1bf206de..05a9b0f1 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 61c41660..fc6d38e2 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -147,6 +147,15 @@ struct tp_touch { int distance; /* distance == 0 means 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;