From e7ebb1bca6850b046e266a25483d033fd3dbb4ab Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 14 Mar 2025 14:06:07 +1000 Subject: [PATCH] tablet: keep a ref to the last tablet in proximity for each tool 99.9% of the time the next tablet will be the same tablet it was used on last. Having a ref means we can modify tablet settings while the tool is out of proximity. Part-of: --- src/evdev-tablet.c | 32 +++++++++++++++++++++++++++++++- src/libinput-private.h | 1 + src/libinput.c | 10 ++++++---- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 0b5b651f..19d9af28 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -1289,6 +1289,7 @@ tablet_new_tool(struct tablet_dispatch *tablet, .serial = serial, .tool_id = tool_id, .refcount = 1, + .last_device = NULL, .pressure.range.min = 0.0, .pressure.range.max = 0.0, /* to trigger configuration */ @@ -1313,6 +1314,7 @@ tablet_get_tool(struct tablet_dispatch *tablet, uint32_t tool_id, uint32_t serial) { + struct evdev_device *device = tablet->device; struct libinput *libinput = tablet_libinput_context(tablet); struct libinput_tablet_tool *tool = NULL, *t; struct list *tool_list; @@ -1361,6 +1363,11 @@ tablet_get_tool(struct tablet_dispatch *tablet, list_insert(tool_list, &tool->link); } + struct libinput_device *last = tool->last_device; + tool->last_device = libinput_device_ref(&device->base); + if (last) + libinput_device_unref(last); + return tool; } @@ -2441,6 +2448,29 @@ tablet_suspend(struct evdev_dispatch *dispatch, } } +static void +tablet_remove(struct evdev_dispatch *dispatch) +{ + struct tablet_dispatch *tablet = tablet_dispatch(dispatch); + struct libinput_device *device = &tablet->device->base; + struct libinput *libinput = tablet_libinput_context(tablet); + struct libinput_tablet_tool *tool; + + list_for_each_safe(tool, &tablet->tool_list, link) { + if (tool->last_device == device) { + libinput_device_unref(tool->last_device); + tool->last_device = NULL; + } + } + + list_for_each_safe(tool, &libinput->tool_list, link) { + if (tool->last_device == device) { + libinput_device_unref(tool->last_device); + tool->last_device = NULL; + } + } +} + static void tablet_destroy(struct evdev_dispatch *dispatch) { @@ -2625,7 +2655,7 @@ tablet_left_handed_toggled(struct evdev_dispatch *dispatch, static struct evdev_dispatch_interface tablet_interface = { .process = tablet_process, .suspend = tablet_suspend, - .remove = NULL, + .remove = tablet_remove, .destroy = tablet_destroy, .device_added = tablet_device_added, .device_removed = tablet_device_removed, diff --git a/src/libinput-private.h b/src/libinput-private.h index ecc372ac..200d1117 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -566,6 +566,7 @@ struct libinput_tablet_tool { unsigned char buttons[NCHARS(KEY_MAX) + 1]; int refcount; void *user_data; + struct libinput_device *last_device; struct { /* We're assuming that the *configured* pressure range is per diff --git a/src/libinput.c b/src/libinput.c index 75afc544..c303185b 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -1759,6 +1759,8 @@ libinput_tablet_tool_unref(struct libinput_tablet_tool *tool) return tool; list_remove(&tool->link); + if (tool->last_device) + tool->last_device = libinput_device_unref(tool->last_device); free(tool); return NULL; } @@ -1979,6 +1981,10 @@ libinput_unref(struct libinput *libinput) free(libinput->events); + list_for_each_safe(tool, &libinput->tool_list, link) { + libinput_tablet_tool_unref(tool); + } + libinput_plugin_system_destroy(&libinput->plugin_system); list_for_each_safe(seat, &libinput->seat_list, link) { @@ -1996,10 +2002,6 @@ libinput_unref(struct libinput *libinput) libinput_device_group_destroy(group); } - list_for_each_safe(tool, &libinput->tool_list, link) { - libinput_tablet_tool_unref(tool); - } - libinput_timer_subsys_destroy(libinput); libinput_drop_destroyed_sources(libinput); quirks_context_unref(libinput->quirks);