From caa05d6bffce0b082daaa2bf4de0bd3df3ec62a9 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Mon, 7 Mar 2016 16:05:25 +1000 Subject: [PATCH libinput] touchpad: add quirk for the T450 generation hardware v2: - fix an issue with the reset - use a 500ms timeout before we kick in - only count nonmotion for true nonmotion events Signed-off-by: Peter Hutterer --- src/evdev-mt-touchpad.c | 34 ++++++++++++++++++++++++++++++---- src/evdev-mt-touchpad.h | 13 +++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 00d6539..b7d64e8 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -337,7 +337,7 @@ tp_process_absolute(struct tp_dispatch *tp, case ABS_MT_PRESSURE: t->pressure = e->value; t->dirty = true; - tp->queued |= TOUCHPAD_EVENT_MOTION; + tp->queued |= TOUCHPAD_EVENT_OTHERAXIS; break; } } @@ -880,8 +880,10 @@ tp_position_fake_touches(struct tp_dispatch *tp) } static inline bool -tp_need_motion_history_reset(struct tp_dispatch *tp) +tp_need_motion_history_reset(struct tp_dispatch *tp, uint64_t time) { + bool rc = false; + /* semi-mt finger postions may "jump" when nfingers changes */ if (tp->semi_mt && tp->nfingers_down != tp->old_nfingers_down) return true; @@ -894,7 +896,31 @@ tp_need_motion_history_reset(struct tp_dispatch *tp) tp->old_nfingers_down > tp->num_slots)) return true; - return false; + /* Quirk: if we had multiple events without x/y axis + information, the next x/y event is going to be a jump. So we + reset that touch to non-dirty effectively swallowing that event + and restarting with the next event again. + */ + if (tp->queued & TOUCHPAD_EVENT_MOTION) { + if (tp->quirks.nonmotion_event_count > 10 && + time - tp->quirks.nonmotion_first_time > ms2us(500)) { + struct tp_touch *t; + + tp_for_each_touch(tp, t) + t->dirty = false; + rc = true; + } + tp->quirks.nonmotion_event_count = 0; + } + + if ((tp->queued & (TOUCHPAD_EVENT_OTHERAXIS|TOUCHPAD_EVENT_MOTION)) == + TOUCHPAD_EVENT_OTHERAXIS) { + if (tp->quirks.nonmotion_event_count == 0) + tp->quirks.nonmotion_first_time = time; + tp->quirks.nonmotion_event_count++; + } + + return rc; } static void @@ -909,7 +935,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) tp_unhover_touches(tp, time); tp_position_fake_touches(tp); - want_motion_reset = tp_need_motion_history_reset(tp); + want_motion_reset = tp_need_motion_history_reset(tp, time); for (i = 0; i < tp->ntouches; i++) { t = tp_get_touch(tp, i); diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index eae327b..a41d2f1 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -41,6 +41,7 @@ enum touchpad_event { TOUCHPAD_EVENT_MOTION = (1 << 0), TOUCHPAD_EVENT_BUTTON_PRESS = (1 << 1), TOUCHPAD_EVENT_BUTTON_RELEASE = (1 << 2), + TOUCHPAD_EVENT_OTHERAXIS = (1 << 3), }; enum touchpad_model { @@ -353,6 +354,18 @@ struct tp_dispatch { int upper_thumb_line; int lower_thumb_line; } thumb; + + struct { + /* A quirk used on the T450 series Synaptics hardware. + * Slowly moving the finger causes multiple events with only + * ABS_MT_PRESSURE but no x/y information. When the x/y + * event comes, it will be a jump of ~20 units. We use the + * below to count non-motion events to discard that first + * event with the jump. + */ + unsigned int nonmotion_event_count; + uint64_t nonmotion_first_time; + } quirks; }; #define tp_for_each_touch(_tp, _t) \ -- 2.5.0