libinput/0003-touchpad-add-wobbling-detection.patch

127 lines
3.8 KiB
Diff

From 3efd7c82aa4758a012e0bac7a148f270060f0e54 Mon Sep 17 00:00:00 2001
From: Konstantin Kharlamov <Hi-Angel@yandex.ru>
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 <Hi-Angel@yandex.ru>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Konstantin Kharlamov <Hi-Angel@yandex.ru>
(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