From 3efd7c82aa4758a012e0bac7a148f270060f0e54 Mon Sep 17 00:00:00 2001 From: Konstantin Kharlamov Date: Wed, 21 Feb 2018 20:16:41 +0300 Subject: [PATCH libinput 3/3] touchpad: add wobbling detection The details are explained in comment in the code. That aside, I shall mention the check is so light, that it shouldn't influence CPU performance even a bit, and can blindly be kept always enabled. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104828 Signed-off-by: Konstantin Kharlamov Signed-off-by: Peter Hutterer Reviewed-by: Konstantin Kharlamov (cherry picked from commit 400aadd53ac00ca773533d14e231ba192f4141a9) --- src/evdev-mt-touchpad.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++- src/evdev-mt-touchpad.h | 2 ++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index 9f36fcbe..d9ed8ab3 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -135,6 +135,61 @@ tp_motion_history_push(struct tp_touch *t) t->history.index = motion_index; } +/* Idea: if we got a tuple of *very* quick moves like {Left, Right, + * Left}, or {Right, Left, Right}, it means touchpad jitters since no + * human can move like that within thresholds. + * + * We encode left moves as zeroes, and right as ones. We also drop + * the array to all zeroes when contraints are not satisfied. Then we + * search for the pattern {1,0,1}. It can't match {Left, Right, Left}, + * but it does match {Left, Right, Left, Right}, so it's okay. + * + * This only looks at x changes, y changes are ignored. + */ +static inline void +tp_detect_wobbling(struct tp_dispatch *tp, + struct tp_touch *t, + uint64_t time) +{ + int dx, dy; + uint64_t dtime; + + if (!(tp->queued & TOUCHPAD_EVENT_MOTION) || tp->hysteresis.enabled) + return; + + if (t->last_point.x == 0) { /* first invocation */ + dx = 0; + dy = 0; + } else { + dx = t->last_point.x - t->point.x; + dy = t->last_point.y - t->point.y; + } + + dtime = time - tp->hysteresis.last_motion_time; + + tp->hysteresis.last_motion_time = time; + t->last_point = t->point; + + if (dx == 0 && dy != 0) /* ignore y-only changes */ + return; + + if (dtime > ms2us(40)) { + t->hysteresis.x_motion_history = 0; + return; + } + + t->hysteresis.x_motion_history <<= 1; + if (dx > 0) { /* right move */ + static const char r_l_r = 0x5; /* {Right, Left, Right} */ + + t->hysteresis.x_motion_history |= 0x1; + if (t->hysteresis.x_motion_history == r_l_r) { + tp->hysteresis.enabled = true; + evdev_log_debug(tp->device, "hysteresis enabled\n"); + } + } +} + static inline void tp_motion_hysteresis(struct tp_dispatch *tp, struct tp_touch *t) @@ -264,6 +319,7 @@ tp_new_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time) t->time = time; t->speed.last_speed = 0; t->speed.exceeded_count = 0; + t->hysteresis.x_motion_history = 0; tp->queued |= TOUCHPAD_EVENT_MOTION; } @@ -1410,7 +1466,7 @@ tp_process_state(struct tp_dispatch *tp, uint64_t time) tp_thumb_detect(tp, t, time); tp_palm_detect(tp, t, time); - + tp_detect_wobbling(tp, t, time); tp_motion_hysteresis(tp, t); tp_motion_history_push(t); diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 4c2f156b..467aca57 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -147,6 +147,7 @@ struct tp_touch { bool has_ended; /* TRACKING_ID == -1 */ bool dirty; struct device_coords point; + struct device_coords last_point; uint64_t time; int pressure; bool is_tool_palm; /* MT_TOOL_PALM */ @@ -175,6 +176,7 @@ struct tp_touch { struct { struct device_coords center; + uint8_t x_motion_history; } hysteresis; /* A pinned touchpoint is the one that pressed the physical button -- 2.14.3