From a506d092b8fc5d05c0ef7579b58d36be20b2c2af Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 8 Oct 2020 09:47:36 +1000 Subject: [PATCH] tablet: disable smoothing for AES devices Data in https://gitlab.freedesktop.org/libinput/libinput/-/issues/225#note_379034 suggests that AES devices have lower noise than the older EMR devices, so let's try disabling it for those devices. We can't directly get the AES devices in libinput unless we want to add a whole bunch of quirks for the various vid/pid combinations. But we can get that info from libwacom, primarily because we know that libwacom will list all known AES pens for any device. So we can check for one that we know of (0x11) and if it's in the list, the tablet is an AES tablet. Setting the history size to 1 means we never do any actual smoothing. Signed-off-by: Peter Hutterer --- src/evdev-tablet.c | 52 +++++++++++++++++++++++++++++++++- src/evdev-tablet.h | 1 + test/test-tablet.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 1 deletion(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index d4e3890..02753d3 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -89,7 +89,7 @@ tablet_force_button_presses(struct tablet_dispatch *tablet) static inline size_t tablet_history_size(const struct tablet_dispatch *tablet) { - return ARRAY_LENGTH(tablet->history.samples); + return tablet->history.size; } static inline void @@ -2344,6 +2344,55 @@ tablet_init_left_handed(struct evdev_device *device) tablet_change_to_left_handed); } +static void +tablet_init_smoothing(struct evdev_device *device, + struct tablet_dispatch *tablet) +{ + size_t history_size = ARRAY_LENGTH(tablet->history.samples); +#if HAVE_LIBWACOM + const char *devnode; + WacomDeviceDatabase *db; + WacomDevice *libwacom_device = NULL; + const int *stylus_ids; + int nstyli; + bool is_aes = false; + int vid = evdev_device_get_id_vendor(device); + + /* Wacom-specific check for whether smoothing is required: + * libwacom keeps all the AES pens in a single group, so any device + * that supports AES pens will list all AES pens. 0x11 is one of the + * lenovo pens so we use that as the flag of whether the tablet + * is an AES tablet + */ + if (vid != VENDOR_ID_WACOM) + goto out; + + db = tablet_libinput_context(tablet)->libwacom.db; + if (!db) + goto out; + + devnode = udev_device_get_devnode(device->udev_device); + libwacom_device = libwacom_new_from_path(db, devnode, WFALLBACK_NONE, NULL); + if (!libwacom_device) + goto out; + + stylus_ids = libwacom_get_supported_styli(libwacom_device, &nstyli); + for (int i = 0; i < nstyli; i++) { + if (stylus_ids[i] == 0x11) { + is_aes = true; + break; + } + } + + if (is_aes) + history_size = 1; + + libwacom_destroy(libwacom_device); +out: +#endif + tablet->history.size = history_size; +} + static bool tablet_reject_device(struct evdev_device *device) { @@ -2408,6 +2457,7 @@ tablet_init(struct tablet_dispatch *tablet, evdev_init_sendevents(device, &tablet->base); tablet_init_left_handed(device); + tablet_init_smoothing(device, tablet); for (axis = LIBINPUT_TABLET_TOOL_AXIS_X; axis <= LIBINPUT_TABLET_TOOL_AXIS_MAX; diff --git a/src/evdev-tablet.h b/src/evdev-tablet.h index 34d5b99..48469a2 100644 --- a/src/evdev-tablet.h +++ b/src/evdev-tablet.h @@ -64,6 +64,7 @@ struct tablet_dispatch { unsigned int index; unsigned int count; struct tablet_axes samples[TABLET_HISTORY_LENGTH]; + size_t size; } history; unsigned char axis_caps[NCHARS(LIBINPUT_TABLET_TOOL_AXIS_MAX + 1)]; diff --git a/test/test-tablet.c b/test/test-tablet.c index 73c0074..211ccfb 100644 --- a/test/test-tablet.c +++ b/test/test-tablet.c @@ -5988,6 +5988,86 @@ START_TEST(huion_static_btn_tool_pen_disable_quirk_on_prox_out) } END_TEST +START_TEST(tablet_smoothing) +{ +#if HAVE_LIBWACOM + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + double x, y; + struct point { + double x, y; + } coordinates[100]; + size_t npoints = 0; + size_t idx = 0; + struct axis_replacement axes[] = { + { ABS_DISTANCE, 10 }, + { ABS_PRESSURE, 0 }, + { -1, -1 } + }; + + litest_drain_events(li); + + litest_tablet_proximity_in(dev, 10, 10, axes); + libinput_dispatch(li); + litest_drain_events(li); + + /* Move in a straight line, collect the resulting points */ + for (x = 11, y = 11; x < 50; x++, y++) { + struct libinput_event *event; + struct libinput_event_tablet_tool *tev; + struct point *p = &coordinates[npoints++]; + + litest_assert(npoints <= ARRAY_LENGTH(coordinates)); + + litest_tablet_motion(dev, x, y, axes); + libinput_dispatch(li); + + event = libinput_get_event(li); + tev = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_AXIS); + p->x = libinput_event_tablet_tool_get_x(tev); + p->y = libinput_event_tablet_tool_get_y(tev); + + libinput_event_destroy(event); + } + + litest_tablet_proximity_out(dev); + litest_tablet_proximity_in(dev, 10, 10, axes); + libinput_dispatch(li); + litest_drain_events(li); + + /* Move in a wobbly line, collect every second point */ + for (x = 11, y = 11; x < 50; x++, y++) { + struct libinput_event *event; + struct libinput_event_tablet_tool *tev; + double ex, ey; + struct point *p = &coordinates[idx++]; + + litest_assert(idx <= npoints); + + /* point off position */ + litest_tablet_motion(dev, x - 2, y + 1, axes); + libinput_dispatch(li); + event = libinput_get_event(li); + litest_is_tablet_event(event, LIBINPUT_EVENT_TABLET_TOOL_AXIS); + libinput_event_destroy(event); + + /* same position as before */ + litest_tablet_motion(dev, x, y, axes); + libinput_dispatch(li); + event = libinput_get_event(li); + tev = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_AXIS); + ex = libinput_event_tablet_tool_get_x(tev); + ey = libinput_event_tablet_tool_get_y(tev); + + ck_assert_double_eq(ex, p->x); + ck_assert_double_eq(ey, p->y); + } +#endif +} +END_TEST + TEST_COLLECTION(tablet) { struct range with_timeout = { 0, 2 }; @@ -6112,4 +6192,6 @@ TEST_COLLECTION(tablet) litest_add_for_device("tablet:quirks", huion_static_btn_tool_pen, LITEST_HUION_TABLET); litest_add_for_device("tablet:quirks", huion_static_btn_tool_pen_no_timeout_during_usage, LITEST_HUION_TABLET); litest_add_ranged_for_device("tablet:quirks", huion_static_btn_tool_pen_disable_quirk_on_prox_out, LITEST_HUION_TABLET, &with_timeout); + + litest_add_for_device("tablet:smoothing", tablet_smoothing, LITEST_WACOM_HID4800_PEN); } -- 2.7.4