From 29bb231114b0432bd5d13245b10e09d5fc4e5346 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 17 Jun 2025 16:01:09 +1000 Subject: [PATCH] plugin: require plugins to enable the frame callback for a device The vast majority of plugins are only interested in a single or a few devices. Require that they enable the frame callback for those devices and don't notify them for any other frames. Give each plugin a unique index and use that for a bitmask to check if the plugin wants events for a particular device. If not, skip it. Part-of: --- src/evdev-plugin.c | 10 +++++++- src/libinput-plugin-system.h | 2 ++ src/libinput-plugin-tablet-double-tool.c | 2 ++ src/libinput-plugin-tablet-eraser-button.c | 2 ++ src/libinput-plugin-tablet-forced-tool.c | 2 ++ src/libinput-plugin-tablet-proximity-timer.c | 2 ++ src/libinput-plugin.c | 25 +++++++++++++++++++- src/libinput-plugin.h | 5 ++++ src/libinput-private.h | 2 ++ 9 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/evdev-plugin.c b/src/evdev-plugin.c index a1949ee4..d4f5154a 100644 --- a/src/evdev-plugin.c +++ b/src/evdev-plugin.c @@ -128,12 +128,20 @@ evdev_device_dispatch_one(struct libinput_plugin *plugin, evdev_frame_reset(frame); } +static void +evdev_plugin_device_added(struct libinput_plugin *plugin, + struct libinput_device *device) + +{ + libinput_plugin_enable_device_event_frame(plugin, device, true); +} + static const struct libinput_plugin_interface interface = { .run = NULL, .destroy = NULL, .device_new = NULL, .device_ignored = NULL, - .device_added = NULL, + .device_added = evdev_plugin_device_added, .device_removed = NULL, .evdev_frame = evdev_device_dispatch_one, }; diff --git a/src/libinput-plugin-system.h b/src/libinput-plugin-system.h index 4734989a..9545e3c6 100644 --- a/src/libinput-plugin-system.h +++ b/src/libinput-plugin-system.h @@ -44,6 +44,8 @@ struct libinput_plugin_system { struct list plugins; struct list removed_plugins; + + size_t next_plugin_index; /* sequential index of all plugins */ }; void diff --git a/src/libinput-plugin-tablet-double-tool.c b/src/libinput-plugin-tablet-double-tool.c index 398bcd20..f0d1ab71 100644 --- a/src/libinput-plugin-tablet-double-tool.c +++ b/src/libinput-plugin-tablet-double-tool.c @@ -328,6 +328,8 @@ double_tool_plugin_device_added(struct libinput_plugin *libinput_plugin, if (!libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) return; + libinput_plugin_enable_device_event_frame(libinput_plugin, device, true); + struct plugin_data *plugin = libinput_plugin_get_user_data(libinput_plugin); struct plugin_device *pd = zalloc(sizeof(*pd)); pd->device = libinput_device_ref(device); diff --git a/src/libinput-plugin-tablet-eraser-button.c b/src/libinput-plugin-tablet-eraser-button.c index 22ba50bc..c7f3bf7a 100644 --- a/src/libinput-plugin-tablet-eraser-button.c +++ b/src/libinput-plugin-tablet-eraser-button.c @@ -533,6 +533,8 @@ eraser_button_plugin_device_added(struct libinput_plugin *libinput_plugin, if (!libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) return; + libinput_plugin_enable_device_event_frame(libinput_plugin, device, true); + struct plugin_data *plugin = libinput_plugin_get_user_data(libinput_plugin); struct plugin_device *pd = zalloc(sizeof(*pd)); pd->device = libinput_device_ref(device); diff --git a/src/libinput-plugin-tablet-forced-tool.c b/src/libinput-plugin-tablet-forced-tool.c index 0636ade3..6b7bb0d1 100644 --- a/src/libinput-plugin-tablet-forced-tool.c +++ b/src/libinput-plugin-tablet-forced-tool.c @@ -186,6 +186,8 @@ forced_tool_plugin_device_added(struct libinput_plugin *libinput_plugin, if (!libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) return; + libinput_plugin_enable_device_event_frame(libinput_plugin, device, true); + struct plugin_data *plugin = libinput_plugin_get_user_data(libinput_plugin); struct plugin_device *pd = zalloc(sizeof(*pd)); pd->device = libinput_device_ref(device); diff --git a/src/libinput-plugin-tablet-proximity-timer.c b/src/libinput-plugin-tablet-proximity-timer.c index f0f955bf..820fc2d9 100644 --- a/src/libinput-plugin-tablet-proximity-timer.c +++ b/src/libinput-plugin-tablet-proximity-timer.c @@ -251,6 +251,8 @@ proximity_timer_plugin_device_added(struct libinput_plugin *libinput_plugin, if (!libinput_device_has_capability(device, LIBINPUT_DEVICE_CAP_TABLET_TOOL)) return; + libinput_plugin_enable_device_event_frame(libinput_plugin, device, true); + struct plugin_data *plugin = libinput_plugin_get_user_data(libinput_plugin); struct plugin_device *pd = zalloc(sizeof(*pd)); pd->device = libinput_device_ref(device); diff --git a/src/libinput-plugin.c b/src/libinput-plugin.c index 5819a954..83194afc 100644 --- a/src/libinput-plugin.c +++ b/src/libinput-plugin.c @@ -45,6 +45,7 @@ struct libinput_plugin { struct libinput *libinput; + size_t index; /* sequential index of all plugins */ char *name; int refcount; struct list link; @@ -98,7 +99,7 @@ libinput_plugin_new(struct libinput *libinput, void *user_data) { struct libinput_plugin *plugin = zalloc(sizeof(*plugin)); - + plugin->index = libinput->plugin_system.next_plugin_index++; plugin->registered = true; plugin->libinput = libinput; plugin->refcount = 1; @@ -107,6 +108,10 @@ libinput_plugin_new(struct libinput *libinput, plugin->name = strdup(name); list_init(&plugin->timers); + if (plugin->index >= 32) { + log_bug_libinput(libinput, "Too many plugins, maximum is 32\n"); + } + libinput_plugin_system_register_plugin(&libinput->plugin_system, plugin); return plugin; @@ -178,6 +183,18 @@ libinput_plugin_get_context(struct libinput_plugin *plugin) return plugin->libinput; } +void +libinput_plugin_enable_device_event_frame(struct libinput_plugin *plugin, + struct libinput_device *device, + bool enable) +{ + if (enable) { + bitmask_set_bit(&device->plugin_frame_callbacks, plugin->index); + } else { + bitmask_clear_bit(&device->plugin_frame_callbacks, plugin->index); + } +} + struct plugin_queued_event { struct list link; struct evdev_frame *frame; /* owns a ref */ @@ -589,6 +606,12 @@ plugin_system_notify_evdev_frame(struct libinput_plugin_system *system, if (evdev_frame_get_time(event->frame) == 0) evdev_frame_set_time(event->frame, frame_time); + if (!bitmask_bit_is_set(device->plugin_frame_callbacks, + plugin->index)) { + list_remove(&event->link); + list_append(&next_events, &event->link); + continue; + } #ifdef EVENT_DEBUGGING _autofree_ char *prefix = strdup_printf("plugin %-25s - %s:", plugin->name, diff --git a/src/libinput-plugin.h b/src/libinput-plugin.h index c2af29ae..ddb0a5a3 100644 --- a/src/libinput-plugin.h +++ b/src/libinput-plugin.h @@ -154,6 +154,11 @@ libinput_plugin_unref(struct libinput_plugin *plugin); DEFINE_UNREF_CLEANUP_FUNC(libinput_plugin); #endif +void +libinput_plugin_enable_device_event_frame(struct libinput_plugin *plugin, + struct libinput_device *device, + bool enable); + /** * Inject a new event frame from the given plugin. This * frame is treated as if it was just sent by the kernel's diff --git a/src/libinput-private.h b/src/libinput-private.h index 8063ec15..691d9819 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -495,6 +495,8 @@ struct libinput_device { int refcount; struct libinput_device_config config; + bitmask_t plugin_frame_callbacks; + void (*inject_evdev_frame)(struct libinput_device *device, struct evdev_frame *frame); };