mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-04 18:40:28 +01:00
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>
This commit is contained in:
parent
e8dffbd73a
commit
400aadd53a
2 changed files with 59 additions and 1 deletions
|
|
@ -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)
|
||||
|
|
@ -265,6 +320,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;
|
||||
}
|
||||
|
||||
|
|
@ -1443,7 +1499,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -149,6 +149,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 */
|
||||
|
|
@ -177,6 +178,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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue