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: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1218>
This commit is contained in:
Peter Hutterer 2025-03-14 14:06:07 +10:00
parent 28e50024ab
commit e7ebb1bca6
3 changed files with 38 additions and 5 deletions

View file

@ -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,

View file

@ -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

View file

@ -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);