mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 06:50:05 +01:00
Add an internal plugin system to libinput
This adds the scaffolding for an internal plugin architecture. No such plugin currently exists and any plugin implemented against this architecture merely is plugin-like in the event flow, not actually external to libinput. The goal of this architecture is to have more segmented processing of the event stream from devices to modify that stream before libinput ever sees it. Right now libinput looks at e.g. a tablet packet and then determines whether the tool was correctly in proximity, etc. With this architecture we can have a plugin that modifies the event stream that the tool is *always* correctly in proximity and the tablet backend itself merely needs to handle the correct case. The event flow will thus logically change from: evdev device -> backend dispatch to evdev device -> plugin1 -> plugin2 -> backend dispatch The plugin API is more expansive than we will use immediately, it is the result of several different implementation branches that all require different functionality. Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1217>
This commit is contained in:
parent
7e6a9f322f
commit
3958ba44c2
8 changed files with 643 additions and 11 deletions
|
|
@ -335,7 +335,7 @@ src_libfilter = [
|
|||
'src/filter-trackpoint-flat.c',
|
||||
]
|
||||
libfilter = static_library('filter', src_libfilter,
|
||||
dependencies : [dep_udev, dep_libwacom],
|
||||
dependencies : [dep_udev, dep_libwacom, dep_libevdev],
|
||||
include_directories : includes_include)
|
||||
dep_libfilter = declare_dependency(link_with : libfilter)
|
||||
|
||||
|
|
@ -374,6 +374,7 @@ config_h.set10('EVENT_DEBUGGING', get_option('internal-event-debugging'))
|
|||
install_headers('src/libinput.h')
|
||||
src_libinput = src_libfilter + [
|
||||
'src/libinput.c',
|
||||
'src/libinput-plugin.c',
|
||||
'src/libinput-private-config.c',
|
||||
'src/evdev.c',
|
||||
'src/evdev-debounce.c',
|
||||
|
|
|
|||
35
src/evdev.c
35
src/evdev.c
|
|
@ -1120,19 +1120,25 @@ evdev_device_dispatch_one(struct evdev_device *device,
|
|||
}
|
||||
|
||||
static inline void
|
||||
evdev_device_dispatch_frame(struct evdev_device *device,
|
||||
evdev_device_dispatch_frame(struct libinput *libinput,
|
||||
struct evdev_device *device,
|
||||
struct evdev_frame *frame)
|
||||
{
|
||||
size_t nevents;
|
||||
struct evdev_event *events = evdev_frame_get_events(frame, &nevents);
|
||||
|
||||
libinput_plugin_system_notify_evdev_frame(&libinput->plugin_system,
|
||||
&device->base,
|
||||
frame);
|
||||
|
||||
for (size_t i = 0; i < nevents; i++) {
|
||||
evdev_device_dispatch_one(device, &events[i], evdev_frame_get_time(frame));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
evdev_sync_device(struct evdev_device *device)
|
||||
evdev_sync_device(struct libinput *libinput,
|
||||
struct evdev_device *device)
|
||||
{
|
||||
struct input_event ev;
|
||||
int rc;
|
||||
|
|
@ -1149,7 +1155,7 @@ evdev_sync_device(struct evdev_device *device)
|
|||
evdev_frame_append_input_event(frame, &ev);
|
||||
} while (rc == LIBEVDEV_READ_STATUS_SYNC);
|
||||
|
||||
evdev_device_dispatch_frame(device, frame);
|
||||
evdev_device_dispatch_frame(libinput, device, frame);
|
||||
|
||||
return rc == -EAGAIN ? 0 : rc;
|
||||
}
|
||||
|
|
@ -1211,10 +1217,10 @@ evdev_device_dispatch(void *data)
|
|||
evdev_log_bug_libinput(device,
|
||||
"event frame overflow, discarding events.\n");
|
||||
}
|
||||
evdev_device_dispatch_frame(device, frame);
|
||||
evdev_device_dispatch_frame(libinput, device, frame);
|
||||
evdev_frame_reset(frame);
|
||||
|
||||
rc = evdev_sync_device(device);
|
||||
rc = evdev_sync_device(libinput, device);
|
||||
if (rc == 0)
|
||||
rc = LIBEVDEV_READ_STATUS_SUCCESS;
|
||||
} else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
|
||||
|
|
@ -1228,7 +1234,7 @@ evdev_device_dispatch(void *data)
|
|||
"event frame overflow, discarding events.\n");
|
||||
}
|
||||
if (ev.type == EV_SYN && ev.code == SYN_REPORT) {
|
||||
evdev_device_dispatch_frame(device, frame);
|
||||
evdev_device_dispatch_frame(libinput, device, frame);
|
||||
evdev_frame_reset(frame);
|
||||
}
|
||||
} else if (rc == -ENODEV) {
|
||||
|
|
@ -1240,7 +1246,7 @@ evdev_device_dispatch(void *data)
|
|||
/* This should never happen, the kernel flushes only on SYN_REPORT */
|
||||
if (evdev_frame_get_count(frame) > 1) {
|
||||
evdev_log_bug_kernel(device, "event frame missing SYN_REPORT, forcing frame.\n");
|
||||
evdev_device_dispatch_frame(device, frame);
|
||||
evdev_device_dispatch_frame(libinput, device, frame);
|
||||
}
|
||||
|
||||
if (rc != -EAGAIN && rc != -EINTR) {
|
||||
|
|
@ -2538,17 +2544,22 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
|
||||
evdev_pre_configure_model_quirks(device);
|
||||
|
||||
libinput_plugin_system_notify_device_new(&libinput->plugin_system,
|
||||
&device->base,
|
||||
device->evdev,
|
||||
device->udev_device);
|
||||
|
||||
device->dispatch = evdev_configure_device(device);
|
||||
if (device->dispatch == NULL || device->seat_caps == EVDEV_DEVICE_NO_CAPABILITIES)
|
||||
goto err;
|
||||
goto err_notify;
|
||||
|
||||
device->source =
|
||||
libinput_add_fd(libinput, fd, evdev_device_dispatch, device);
|
||||
if (!device->source)
|
||||
goto err;
|
||||
goto err_notify;
|
||||
|
||||
if (!evdev_set_device_group(device, udev_device))
|
||||
goto err;
|
||||
goto err_notify;
|
||||
|
||||
list_insert(seat->devices_list.prev, &device->base.link);
|
||||
|
||||
|
|
@ -2556,6 +2567,10 @@ evdev_device_create(struct libinput_seat *seat,
|
|||
|
||||
return device;
|
||||
|
||||
err_notify:
|
||||
libinput_plugin_system_notify_device_ignored(&libinput->plugin_system,
|
||||
&device->base);
|
||||
|
||||
err:
|
||||
if (fd >= 0) {
|
||||
close_restricted(libinput, fd);
|
||||
|
|
|
|||
54
src/libinput-plugin-private.h
Normal file
54
src/libinput-plugin-private.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright © 2025 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libinput-plugin.h"
|
||||
|
||||
void
|
||||
libinput_plugin_run(struct libinput_plugin *plugin);
|
||||
|
||||
void
|
||||
libinput_plugin_notify_device_new(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device,
|
||||
struct libevdev *evdev,
|
||||
struct udev_device *udev_device);
|
||||
|
||||
void
|
||||
libinput_plugin_notify_device_added(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device);
|
||||
|
||||
void
|
||||
libinput_plugin_notify_device_ignored(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device);
|
||||
|
||||
void
|
||||
libinput_plugin_notify_device_removed(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device);
|
||||
|
||||
void
|
||||
libinput_plugin_notify_evdev_frame(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device,
|
||||
struct evdev_frame *frame);
|
||||
84
src/libinput-plugin-system.h
Normal file
84
src/libinput-plugin-system.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright © 2025 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <libudev.h>
|
||||
#include <libevdev/libevdev.h>
|
||||
|
||||
#include "evdev-frame.h"
|
||||
#include "util-list.h"
|
||||
|
||||
#include "libinput.h"
|
||||
|
||||
struct libinput;
|
||||
struct libinput_plugin;
|
||||
|
||||
struct libinput_plugin_system {
|
||||
char **directories; /* NULL once loaded == true */
|
||||
|
||||
struct list plugins;
|
||||
struct list removed_plugins;
|
||||
};
|
||||
|
||||
void
|
||||
libinput_plugin_system_init(struct libinput_plugin_system *system);
|
||||
|
||||
void
|
||||
libinput_plugin_system_destroy(struct libinput_plugin_system *system);
|
||||
|
||||
void
|
||||
libinput_plugin_system_run(struct libinput_plugin_system *system);
|
||||
|
||||
void
|
||||
libinput_plugin_system_register_plugin(struct libinput_plugin_system *system,
|
||||
struct libinput_plugin *plugin);
|
||||
void
|
||||
libinput_plugin_system_unregister_plugin(struct libinput_plugin_system *system,
|
||||
struct libinput_plugin *plugin);
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_device_new(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device,
|
||||
struct libevdev *evdev,
|
||||
struct udev_device *udev);
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_device_added(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device);
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_device_removed(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device);
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_device_ignored(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device);
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_evdev_frame(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device,
|
||||
struct evdev_frame *frame);
|
||||
319
src/libinput-plugin.c
Normal file
319
src/libinput-plugin.c
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* Copyright © 2025 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "util-files.h"
|
||||
#include "util-list.h"
|
||||
|
||||
#include "libinput-plugin.h"
|
||||
#include "libinput-plugin-private.h"
|
||||
#include "libinput-plugin-system.h"
|
||||
#include "libinput-util.h"
|
||||
#include "libinput-private.h"
|
||||
|
||||
struct libinput_plugin {
|
||||
struct libinput *libinput;
|
||||
char *name;
|
||||
int refcount;
|
||||
struct list link;
|
||||
void *user_data;
|
||||
|
||||
bool registered;
|
||||
|
||||
const struct libinput_plugin_interface *interface;
|
||||
};
|
||||
|
||||
LIBINPUT_ATTRIBUTE_PRINTF(3, 4)
|
||||
void
|
||||
plugin_log_msg(struct libinput_plugin *plugin,
|
||||
enum libinput_log_priority priority,
|
||||
const char *format,
|
||||
...)
|
||||
{
|
||||
|
||||
if (!log_is_logged(plugin->libinput, priority))
|
||||
return;
|
||||
|
||||
_autofree_ char *prefix = strdup_printf("Plugin:%-15s - ", plugin->name);
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
_autofree_ char *message = strdup_vprintf(format, args);
|
||||
va_end(args);
|
||||
|
||||
log_msg(plugin->libinput, priority, "%s%s", prefix, message);
|
||||
}
|
||||
|
||||
struct libinput_plugin *
|
||||
libinput_plugin_new(struct libinput *libinput,
|
||||
const char *name,
|
||||
const struct libinput_plugin_interface *interface,
|
||||
void *user_data)
|
||||
{
|
||||
struct libinput_plugin *plugin = zalloc(sizeof(*plugin));
|
||||
|
||||
plugin->registered = true;
|
||||
plugin->libinput = libinput;
|
||||
plugin->refcount = 1;
|
||||
plugin->interface = interface;
|
||||
plugin->user_data = user_data;
|
||||
plugin->name = strdup(name);
|
||||
|
||||
libinput_plugin_system_register_plugin(&libinput->plugin_system, plugin);
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_unregister(struct libinput_plugin *plugin)
|
||||
{
|
||||
struct libinput *libinput = plugin->libinput;
|
||||
if (!plugin->registered)
|
||||
return;
|
||||
|
||||
plugin->registered = false;
|
||||
|
||||
libinput_plugin_system_unregister_plugin(&libinput->plugin_system,
|
||||
plugin);
|
||||
}
|
||||
|
||||
struct libinput_plugin *
|
||||
libinput_plugin_ref(struct libinput_plugin *plugin)
|
||||
{
|
||||
assert(plugin->refcount > 0);
|
||||
++plugin->refcount;
|
||||
return plugin;
|
||||
}
|
||||
|
||||
struct libinput_plugin *
|
||||
libinput_plugin_unref(struct libinput_plugin *plugin)
|
||||
{
|
||||
assert(plugin->refcount > 0);
|
||||
if (--plugin->refcount == 0) {
|
||||
list_remove(&plugin->link);
|
||||
if (plugin->interface->destroy)
|
||||
plugin->interface->destroy(plugin);
|
||||
free(plugin->name);
|
||||
free(plugin);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_set_user_data(struct libinput_plugin *plugin,
|
||||
void *user_data)
|
||||
{
|
||||
plugin->user_data = user_data;
|
||||
}
|
||||
|
||||
void *
|
||||
libinput_plugin_get_user_data(struct libinput_plugin *plugin)
|
||||
{
|
||||
return plugin->user_data;
|
||||
}
|
||||
|
||||
const char *
|
||||
libinput_plugin_get_name(struct libinput_plugin *plugin)
|
||||
{
|
||||
return plugin->name;
|
||||
}
|
||||
|
||||
struct libinput *
|
||||
libinput_plugin_get_context(struct libinput_plugin *plugin)
|
||||
{
|
||||
return plugin->libinput;
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_run(struct libinput_plugin *plugin)
|
||||
{
|
||||
if (plugin->interface->run)
|
||||
plugin->interface->run(plugin);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_notify_device_new(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device,
|
||||
struct libevdev *evdev,
|
||||
struct udev_device *udev_device)
|
||||
{
|
||||
if (plugin->interface->device_new)
|
||||
plugin->interface->device_new(plugin, device, evdev, udev_device);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_notify_device_added(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
if (plugin->interface->device_added)
|
||||
plugin->interface->device_added(plugin, device);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_notify_device_ignored(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
if (plugin->interface->device_ignored)
|
||||
plugin->interface->device_ignored(plugin, device);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_notify_device_removed(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
if (plugin->interface->device_removed)
|
||||
plugin->interface->device_removed(plugin, device);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_notify_evdev_frame(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device,
|
||||
struct evdev_frame *frame)
|
||||
{
|
||||
if (plugin->interface->evdev_frame)
|
||||
plugin->interface->evdev_frame(plugin, device, frame);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_run(struct libinput_plugin_system *system)
|
||||
{
|
||||
struct libinput_plugin *plugin;
|
||||
list_for_each_safe(plugin,
|
||||
&system->plugins,
|
||||
link) {
|
||||
libinput_plugin_run(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_register_plugin(struct libinput_plugin_system *system,
|
||||
struct libinput_plugin *plugin)
|
||||
{
|
||||
libinput_plugin_ref(plugin);
|
||||
list_append(&system->plugins, &plugin->link);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_unregister_plugin(struct libinput_plugin_system *system,
|
||||
struct libinput_plugin *plugin)
|
||||
{
|
||||
struct libinput_plugin *p;
|
||||
list_for_each(p, &system->plugins, link) {
|
||||
if (p == plugin) {
|
||||
list_remove(&plugin->link);
|
||||
list_append(&system->removed_plugins, &plugin->link);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
libinput_plugin_system_drop_unregistered_plugins(struct libinput_plugin_system *system)
|
||||
{
|
||||
struct libinput_plugin *plugin;
|
||||
list_for_each_safe(plugin, &system->removed_plugins, link) {
|
||||
list_remove(&plugin->link);
|
||||
list_init(&plugin->link); /* allow list_remove in unref */
|
||||
libinput_plugin_unref(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_init(struct libinput_plugin_system *system)
|
||||
{
|
||||
list_init(&system->plugins);
|
||||
list_init(&system->removed_plugins);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_destroy(struct libinput_plugin_system *system)
|
||||
{
|
||||
struct libinput_plugin *plugin;
|
||||
list_for_each_safe(plugin, &system->plugins, link) {
|
||||
libinput_plugin_unregister(plugin);
|
||||
}
|
||||
|
||||
libinput_plugin_system_drop_unregistered_plugins(system);
|
||||
|
||||
strv_free(system->directories);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_device_new(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device,
|
||||
struct libevdev *evdev,
|
||||
struct udev_device *udev_device)
|
||||
{
|
||||
struct libinput_plugin *plugin;
|
||||
list_for_each_safe(plugin, &system->plugins, link) {
|
||||
libinput_plugin_notify_device_new(plugin, device, evdev, udev_device);
|
||||
}
|
||||
libinput_plugin_system_drop_unregistered_plugins(system);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_device_added(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
struct libinput_plugin *plugin;
|
||||
list_for_each_safe(plugin, &system->plugins, link) {
|
||||
libinput_plugin_notify_device_added(plugin, device);
|
||||
}
|
||||
libinput_plugin_system_drop_unregistered_plugins(system);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_device_removed(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
struct libinput_plugin *plugin;
|
||||
list_for_each_safe(plugin, &system->plugins, link) {
|
||||
libinput_plugin_notify_device_removed(plugin, device);
|
||||
}
|
||||
libinput_plugin_system_drop_unregistered_plugins(system);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_device_ignored(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device)
|
||||
{
|
||||
struct libinput_plugin *plugin;
|
||||
list_for_each_safe(plugin, &system->plugins, link) {
|
||||
libinput_plugin_notify_device_ignored(plugin, device);
|
||||
}
|
||||
libinput_plugin_system_drop_unregistered_plugins(system);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_notify_evdev_frame(struct libinput_plugin_system *system,
|
||||
struct libinput_device *device,
|
||||
struct evdev_frame *frame)
|
||||
{
|
||||
struct libinput_plugin *plugin;
|
||||
list_for_each_safe(plugin, &system->plugins, link) {
|
||||
libinput_plugin_notify_evdev_frame(plugin, device, frame);
|
||||
}
|
||||
libinput_plugin_system_drop_unregistered_plugins(system);
|
||||
}
|
||||
146
src/libinput-plugin.h
Normal file
146
src/libinput-plugin.h
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
/*
|
||||
* Copyright © 2025 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <libudev.h>
|
||||
#include <libevdev/libevdev.h>
|
||||
|
||||
/* Forward declarations instead of #includes to make
|
||||
* this header self-contained (bindgen, etc.) */
|
||||
struct evdev_frame;
|
||||
struct libinput;
|
||||
struct libinput_device;
|
||||
struct libinput_plugin;
|
||||
enum libinput_log_priority;
|
||||
|
||||
#define plugin_log_debug(p_, ...) plugin_log_msg((p_), LIBINPUT_LOG_PRIORITY_DEBUG, __VA_ARGS__)
|
||||
#define plugin_log_info(p_, ...) plugin_log_msg((p_), LIBINPUT_LOG_PRIORITY_INFO, __VA_ARGS__)
|
||||
#define plugin_log_error(p_, ...) plugin_log_msg((p_), LIBINPUT_LOG_PRIORITY_ERROR, __VA_ARGS__)
|
||||
#define plugin_log_bug_kernel(p_, ...) plugin_log_msg((p_), LIBINPUT_LOG_PRIORITY_ERROR, "kernel bug: " __VA_ARGS__)
|
||||
#define plugin_log_bug_libinput(p_, ...) plugin_log_msg((p_), LIBINPUT_LOG_PRIORITY_ERROR, "libinput bug: " __VA_ARGS__)
|
||||
#define plugin_log_bug_client(p_, ...) plugin_log_msg((p_), LIBINPUT_LOG_PRIORITY_ERROR, "client bug: " __VA_ARGS__)
|
||||
#define plugin_log_bug(p_, ...) plugin_log_msg((p_), LIBINPUT_LOG_PRIORITY_ERROR, "plugin bug: " __VA_ARGS__)
|
||||
|
||||
void
|
||||
plugin_log_msg(struct libinput_plugin *plugin,
|
||||
enum libinput_log_priority priority,
|
||||
const char *format,
|
||||
...);
|
||||
|
||||
struct libinput_plugin_interface {
|
||||
void (*run)(struct libinput_plugin *plugin);
|
||||
/**
|
||||
* Notification that the plugin is about to be destroyed.
|
||||
* When this function is called, the plugin has already
|
||||
* been unregistered. The plugin should free any
|
||||
* resources allocated but not the struct libinput_plugin
|
||||
* itself.
|
||||
*/
|
||||
void (*destroy)(struct libinput_plugin *plugin);
|
||||
/**
|
||||
* Notification about a newly added device that has **not** yet
|
||||
* been added by libinput as struct libinput_device.
|
||||
*/
|
||||
void (*device_new)(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device,
|
||||
struct libevdev *evdev,
|
||||
struct udev_device *udev_device);
|
||||
/**
|
||||
* Notification that a device (previously announced with device_new)
|
||||
* was ignored by libinput and was **never** added as struct
|
||||
* libinput_device.
|
||||
*
|
||||
* If a device was added (device_added) then this callback will
|
||||
* not be called for that device.
|
||||
*/
|
||||
void (*device_ignored)(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device);
|
||||
/**
|
||||
* Notification that a device was added to libinput. Called
|
||||
* after the device_new callback if the device matches libinput's
|
||||
* expectations.
|
||||
*/
|
||||
void (*device_added)(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device);
|
||||
/**
|
||||
* Notification that a previously added device was removed.
|
||||
*/
|
||||
void (*device_removed)(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device);
|
||||
/**
|
||||
* Notification that a device submitted a frame event.
|
||||
*/
|
||||
void (*evdev_frame)(struct libinput_plugin *plugin,
|
||||
struct libinput_device *device,
|
||||
struct evdev_frame *frame);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a new plugin with the given interface and, optionally,
|
||||
* the user data. The returned plugin has a refcount of at least 1
|
||||
* and must be unref'd by the caller.
|
||||
* Should an error occur, the plugin must be unregistered by
|
||||
* the caller:
|
||||
*
|
||||
* ```
|
||||
* struct libinput_plugin *plugin = libinput_plugin_new(libinput, ...);
|
||||
* if (some_error_condition) {
|
||||
* libinput_plugin_unregister(plugin);
|
||||
* }
|
||||
* libinput_plugin_unref(plugin);
|
||||
* ```
|
||||
*/
|
||||
struct libinput_plugin *
|
||||
libinput_plugin_new(struct libinput *libinput,
|
||||
const char *name,
|
||||
const struct libinput_plugin_interface *interface,
|
||||
void *user_data);
|
||||
|
||||
const char *
|
||||
libinput_plugin_get_name(struct libinput_plugin *plugin);
|
||||
|
||||
struct libinput *
|
||||
libinput_plugin_get_context(struct libinput_plugin *plugin);
|
||||
|
||||
void
|
||||
libinput_plugin_unregister(struct libinput_plugin *plugin);
|
||||
|
||||
void
|
||||
libinput_plugin_set_user_data(struct libinput_plugin *plugin,
|
||||
void *user_data);
|
||||
void *
|
||||
libinput_plugin_get_user_data(struct libinput_plugin *plugin);
|
||||
|
||||
struct libinput_plugin *
|
||||
libinput_plugin_ref(struct libinput_plugin *plugin);
|
||||
|
||||
struct libinput_plugin *
|
||||
libinput_plugin_unref(struct libinput_plugin *plugin);
|
||||
|
||||
#ifdef DEFINE_UNREF_CLEANUP_FUNC
|
||||
DEFINE_UNREF_CLEANUP_FUNC(libinput_plugin);
|
||||
#endif
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "libinput.h"
|
||||
#include "libinput-log.h"
|
||||
#include "libinput-plugin-system.h"
|
||||
#include "libinput-private-config.h"
|
||||
#include "libinput-util.h"
|
||||
#include "libinput-version.h"
|
||||
|
|
@ -221,6 +222,8 @@ struct libinput {
|
|||
bool quirks_initialized;
|
||||
struct quirks_context *quirks;
|
||||
|
||||
struct libinput_plugin_system plugin_system;
|
||||
|
||||
#if HAVE_LIBWACOM
|
||||
struct {
|
||||
WacomDeviceDatabase *db;
|
||||
|
|
|
|||
|
|
@ -1879,6 +1879,8 @@ libinput_init(struct libinput *libinput,
|
|||
list_init(&libinput->device_group_list);
|
||||
list_init(&libinput->tool_list);
|
||||
|
||||
libinput_plugin_system_init(&libinput->plugin_system);
|
||||
|
||||
if (libinput_timer_subsys_init(libinput) != 0) {
|
||||
free(libinput->events);
|
||||
close(libinput->epoll_fd);
|
||||
|
|
@ -1977,6 +1979,8 @@ libinput_unref(struct libinput *libinput)
|
|||
|
||||
free(libinput->events);
|
||||
|
||||
libinput_plugin_system_destroy(&libinput->plugin_system);
|
||||
|
||||
list_for_each_safe(seat, &libinput->seat_list, link) {
|
||||
list_for_each_safe(device,
|
||||
&seat->devices_list,
|
||||
|
|
@ -2345,6 +2349,9 @@ post_device_event(struct libinput_device *device,
|
|||
void
|
||||
notify_added_device(struct libinput_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->seat->libinput;
|
||||
libinput_plugin_system_notify_device_added(&libinput->plugin_system, device);
|
||||
|
||||
struct libinput_event_device_notify *added_device_event;
|
||||
|
||||
added_device_event = zalloc(sizeof *added_device_event);
|
||||
|
|
@ -2363,6 +2370,9 @@ notify_added_device(struct libinput_device *device)
|
|||
void
|
||||
notify_removed_device(struct libinput_device *device)
|
||||
{
|
||||
struct libinput *libinput = device->seat->libinput;
|
||||
libinput_plugin_system_notify_device_removed(&libinput->plugin_system, device);
|
||||
|
||||
struct libinput_event_device_notify *removed_device_event;
|
||||
|
||||
removed_device_event = zalloc(sizeof *removed_device_event);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue