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". Signed-off-by: Konstantin Kharlamov <hi-an...@yandex.ru> --- src/evdev-mt-touchpad.c | 33 +++++++++++++++++++++++++++++++++ src/evdev-mt-touchpad.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c index ead76456..80f56072 100644 --- a/src/evdev-mt-touchpad.c +++ b/src/evdev-mt-touchpad.c @@ -131,6 +131,36 @@ tp_motion_history_push(struct tp_touch *t) t->history.index = motion_index; } +static inline void +tp_detect_wobbling(struct tp_dispatch *tp, int x_diff, uint64_t time) +{ + if (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 (time - tp->hysteresis.last_motion_time > ms2us(20) || x_diff == 0) { + tp->hysteresis.x_motion_in_threshold = 0; + return; + } + tp->hysteresis.x_motion_in_threshold <<= 1; + if (x_diff > 0) { /* right move */ + tp->hysteresis.x_motion_in_threshold |= 1; + static const char r_l_r = 5; /* {Right, Left, Right} */ + if (tp->hysteresis.x_motion_in_threshold & 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) @@ -1405,6 +1435,8 @@ 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, tp->hysteresis.prev_x - t->point.x, time); + tp->hysteresis.prev_x = t->point.x; tp_motion_hysteresis(tp, t); tp_motion_history_push(t); @@ -2918,6 +2950,7 @@ tp_init_hysteresis(struct tp_dispatch *tp) tp->hysteresis.margin.x = res_x/2; tp->hysteresis.margin.y = res_y/2; tp->hysteresis.enabled = false; + tp->hysteresis.x_motion_in_threshold = 0; } static void diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h index 442f34a3..398a18ed 100644 --- a/src/evdev-mt-touchpad.h +++ b/src/evdev-mt-touchpad.h @@ -276,6 +276,8 @@ struct tp_dispatch { struct device_coords margin; unsigned int other_event_count; uint64_t last_motion_time; + char x_motion_in_threshold; + int prev_x; } hysteresis; struct { -- 2.15.1 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel