[PATCH 2/2 v3 libinput] touchpad: add wobbling detection
Konstantin Kharlamov
Hi-Angel at yandex.ru
Wed Feb 21 17:16:41 UTC 2018
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
v2: rename the function, change comment style, and add calculation of
x_diff (the one that was used is an absolute coordinate).
FWIW, the algorithm don't care that now added "prev_x" is unintialized,
because that happening means the time threshold won't get satisfied
either. It's not like I can't default-init it — it's just that asking
oneself a question "what default value should it have" results in "none".
v3:
* style fixes (empty line after a block, declaration at top)
* s/x_diff/dx
* s/x_motion_in_threashold/x_motion_history
* compare with r_l_r instead of &
* store whole point instead of just x
* move x_motion_history and prev_coords into tp_touch
* move everything around tp_detect_wobbling() call into the function,
use goto for that purpose.
* per request: add a comparison for when previous coordinates don't
actually have the prev. coordinates yet.
* increased timeout from 20ms to 40ms just in case — it's still out of
human ability anyway, and in fact can be increased even further
* ignore Y-only changes, again just in case — it could happen that Y and
X events would be sent separately, and break the heuristic.
Signed-off-by: Konstantin Kharlamov <Hi-Angel at yandex.ru>
---
src/evdev-mt-touchpad.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
src/evdev-mt-touchpad.h | 2 ++
2 files changed, 50 insertions(+), 1 deletion(-)
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index ead76456..e32597d4 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -131,6 +131,52 @@ tp_motion_history_push(struct tp_touch *t)
t->history.index = motion_index;
}
+static inline void
+tp_detect_wobbling(struct tp_dispatch *tp,
+ struct tp_touch *t,
+ uint64_t time)
+{
+ int dx = (!t->prev_coords.x)? 0 /* first invocation */
+ : t->prev_coords.x - t->point.x;
+
+ if (!(tp->queued & TOUCHPAD_EVENT_MOTION) || tp->hysteresis.enabled)
+ return;
+
+ /* 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 supposed to be able to move like that within thresholds
+ *
+ * Algo: 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.
+ */
+ if (!dx && t->prev_coords.y != t->point.y) { /* ignore Y-only changes */
+ t->prev_coords.y = t->point.y;
+ return;
+ }
+
+ if (time - tp->hysteresis.last_motion_time > ms2us(40) || dx == 0) {
+ t->x_motion_history = 0;
+ goto out;
+ }
+
+ t->x_motion_history <<= 1;
+ if (dx > 0) { /* right move */
+ static const char r_l_r = 5; /* {Right, Left, Right} */
+
+ t->x_motion_history |= 1;
+ if (t->x_motion_history == r_l_r) {
+ tp->hysteresis.enabled = true;
+ evdev_log_debug(tp->device, "hysteresis enabled\n");
+ }
+ }
+
+out:
+ tp->hysteresis.last_motion_time = time;
+ t->prev_coords = t->point;
+}
+
static inline void
tp_motion_hysteresis(struct tp_dispatch *tp,
struct tp_touch *t)
@@ -260,6 +306,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->x_motion_history = 0;
tp->queued |= TOUCHPAD_EVENT_MOTION;
}
@@ -1404,7 +1451,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 442f34a3..48161efb 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -151,6 +151,8 @@ struct tp_touch {
int pressure;
bool is_tool_palm; /* MT_TOOL_PALM */
int major, minor;
+ char x_motion_history;
+ struct device_coords prev_coords;
bool was_down; /* if distance == 0, false for pure hovering
touches */
--
2.15.1
More information about the wayland-devel
mailing list