[PATCH libinput 4/4] touchpad: automatically disable the hysteresis where not required

Peter Hutterer peter.hutterer at who-t.net
Mon Oct 30 23:52:32 UTC 2017


Touchpads that require the hysteresis do not have filtering in the firmware
and holding a finger still causes continuous cursor movements. This implies
that we get a continuous stream of events with motion data.

If the finger is on the touchpad but we don't see any motion, the finger is
stationary and the touchpad firmware does filtering. In that case, we don't
need to add a hysteresis on top.

https://bugs.freedesktop.org/show_bug.cgi?id=98839

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-mt-touchpad.c | 19 +++++++++++++++++++
 src/evdev-mt-touchpad.h |  2 ++
 test/litest.c           |  6 ++++++
 test/litest.h           |  3 +++
 4 files changed, 30 insertions(+)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index a3e243b3..44bc9780 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -132,6 +132,21 @@ tp_motion_history_push(struct tp_touch *t)
 }
 
 static inline void
+tp_maybe_disable_hysteresis(struct tp_dispatch *tp, uint64_t time)
+{
+	/* If the finger is down for 80ms without seeing motion events,
+	   the firmware filters and we don't need a software hysteresis */
+	if (time - tp->hysteresis.last_motion_time > ms2us(80)) {
+		tp->hysteresis.enabled = false;
+		evdev_log_debug(tp->device, "hysteresis disabled\n");
+		return;
+	}
+
+	if (tp->queued & TOUCHPAD_EVENT_MOTION)
+		tp->hysteresis.last_motion_time = time;
+}
+
+static inline void
 tp_motion_hysteresis(struct tp_dispatch *tp,
 		     struct tp_touch *t)
 {
@@ -276,6 +291,7 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t, uint64_t time)
 	t->thumb.first_touch_time = time;
 	t->tap.is_thumb = false;
 	assert(tp->nfingers_down >= 1);
+	tp->hysteresis.last_motion_time = time;
 }
 
 /**
@@ -1529,6 +1545,9 @@ static void
 tp_handle_state(struct tp_dispatch *tp,
 		uint64_t time)
 {
+	if (tp->hysteresis.enabled)
+		tp_maybe_disable_hysteresis(tp, time);
+
 	tp_process_state(tp, time);
 	tp_post_events(tp, time);
 	tp_post_process_state(tp, time);
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index ab4bcde1..cb87b3ff 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -272,6 +272,8 @@ struct tp_dispatch {
 	struct {
 		bool enabled;
 		struct device_coords margin;
+		unsigned int other_event_count;
+		uint64_t last_motion_time;
 	} hysteresis;
 
 	struct {
diff --git a/test/litest.c b/test/litest.c
index d34bd3c5..1fd5a6e9 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -3224,6 +3224,12 @@ litest_timeout_tablet_proxout(void)
 }
 
 void
+litest_timeout_hysteresis(void)
+{
+	msleep(90);
+}
+
+void
 litest_push_event_frame(struct litest_device *dev)
 {
 	litest_assert(dev->skip_ev_syn >= 0);
diff --git a/test/litest.h b/test/litest.h
index 53d8153d..d6d5c82c 100644
--- a/test/litest.h
+++ b/test/litest.h
@@ -767,6 +767,9 @@ void
 litest_timeout_tablet_proxout(void);
 
 void
+litest_timeout_hysteresis(void);
+
+void
 litest_push_event_frame(struct litest_device *dev);
 
 void
-- 
2.13.6



More information about the wayland-devel mailing list