tablet: add a fuzz-filter to avoid spamming callers with subpixel updates
authorPeter Hutterer <peter.hutterer@who-t.net>
Mon, 11 Apr 2016 22:36:48 +0000 (08:36 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 14 Apr 2016 04:51:47 +0000 (14:51 +1000)
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 kernel though.

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

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Jason Gerecke <jason.gerecke@wacom.com>
(cherry picked from commit 60a8ba9f3e3210a2dceabc834af9a140f548c1af)

src/evdev-tablet.c
src/evdev-tablet.h

index 84563a8f05111fc023e3f538458327a010ba029c..be828d965552a7e432c83983cf8b50c5b7d85a12 100644 (file)
@@ -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;
index 880d52300a9854d27c88711e68d08a79920162f5..d12c6752332ab476f5bba7b1eb7d3c24633c0f26 100644 (file)
@@ -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;