[PATCH libinput] tablet: add a fuzz-filter to avoid spamming callers with subpixel updates

Peter Hutterer peter.hutterer at who-t.net
Tue Apr 12 00:17:48 UTC 2016


This is especially a problem for the cursor tool which can be legitimately
left on the tablet. It wobbles by a couple of device units, resulting in
continuous axis updates to the caller. Pre-filter any of these events by the
axis' fuzz value so we don't even process them.

For ABS_DISTANCE which doesn't have a fuzz we hard-code a minimum fuzz of 2.
This should eventually land in the udev hwdb though.

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

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 src/evdev-tablet.c | 35 +++++++++++++++++++++++++++++++++++
 src/evdev-tablet.h |  2 ++
 2 files changed, 37 insertions(+)

diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c
index 84563a8..be828d9 100644
--- a/src/evdev-tablet.c
+++ b/src/evdev-tablet.c
@@ -112,6 +112,36 @@ tablet_device_has_axis(struct tablet_dispatch *tablet,
 	return has_axis;
 }
 
+static inline bool
+tablet_filter_axis_fuzz(const struct tablet_dispatch *tablet,
+			const struct evdev_device *device,
+			const struct input_event *e,
+			enum libinput_tablet_tool_axis axis)
+{
+	int delta, fuzz;
+	int current, previous;
+
+	previous = tablet->prev_value[axis];
+	current = e->value;
+	delta = previous - current;
+
+	fuzz = libevdev_get_abs_fuzz(device->evdev, e->code);
+
+	/* ABS_DISTANCE doesn't have have fuzz set and causes continuous
+	 * updates for the cursor/lens tools. Add a minimum fuzz of 2, same
+	 * as the xf86-input-wacom driver
+	 */
+	switch (e->code) {
+	case ABS_DISTANCE:
+		fuzz = max(2, fuzz);
+		break;
+	default:
+		break;
+	}
+
+	return abs(delta) <= fuzz;
+}
+
 static void
 tablet_process_absolute(struct tablet_dispatch *tablet,
 			struct evdev_device *device,
@@ -137,6 +167,11 @@ tablet_process_absolute(struct tablet_dispatch *tablet,
 			break;
 		}
 
+		tablet->prev_value[axis] = tablet->current_value[axis];
+		if (tablet_filter_axis_fuzz(tablet, device, e, axis))
+			break;
+
+		tablet->current_value[axis] = e->value;
 		set_bit(tablet->changed_axes, axis);
 		tablet_set_status(tablet, TABLET_AXES_UPDATED);
 		break;
diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h
index 880d523..d12c675 100644
--- a/src/evdev-tablet.h
+++ b/src/evdev-tablet.h
@@ -55,6 +55,8 @@ struct tablet_dispatch {
 	unsigned char changed_axes[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)];
 	struct tablet_axes axes;
 	unsigned char axis_caps[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)];
+	int current_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1];
+	int prev_value[LIBINPUT_TABLET_TOOL_AXIS_MAX + 1];
 
 	/* Only used for tablets that don't report serial numbers */
 	struct list tool_list;
-- 
2.5.5



More information about the wayland-devel mailing list