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: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1229>
This commit is contained in:
Peter Hutterer 2025-06-17 16:01:09 +10:00 committed by Marge Bot
parent b31326dd02
commit 29bb231114
9 changed files with 50 additions and 2 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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