tablet: add a fuzz-filter to avoid spamming callers with subpixel updates

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 60a8ba9f3e)
This commit is contained in:
Peter Hutterer 2016-04-12 08:36:48 +10:00
parent 6e8561390d
commit 4ae3d7fb49
2 changed files with 37 additions and 0 deletions

View 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;

View 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;