mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2025-12-20 09:10:04 +01:00
Add a public plugin system to libinput
This patch adds a new API for enabling public "plugins" in libinput, in
addition to the exisitng internal ones. The API is currently limited to
specifying which paths should be loaded and whether to load them.
Public plugins are static, they are loaded before the context is initialized
and do not update after that.
If plugins are to be loaded, libinput will then run through those paths,
look up files and pass them to (future) plugins to load the actual
files.
Our debugging tools have an --enable-plugins and
--disable-plugins option that load from the default data paths
(/etc/libinput/plugins and /usr/lib{64}/libinput/plugins) and from
the $builddir/plugins directory.
Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1192>
This commit is contained in:
parent
d1dbbb7328
commit
d557a649fd
13 changed files with 272 additions and 13 deletions
|
|
@ -93,6 +93,9 @@ __all_seats()
|
|||
+ '(natural-scrolling)' \
|
||||
'--enable-natural-scrolling[Enable natural scrolling]' \
|
||||
'--disable-natural-scrolling[Disable natural scrolling]' \
|
||||
+ '(plugins)' \
|
||||
'--enable-plugins[Enable plugins]' \
|
||||
'--disable-plugins[Disable plugins]' \
|
||||
+ '(tap-to-click)' \
|
||||
'--enable-tap[Enable tap-to-click]' \
|
||||
'--disable-tap[Disable tap-to-click]'
|
||||
|
|
|
|||
|
|
@ -168,6 +168,8 @@ dep_libevdev = dependency('libevdev', version: '>= 1.10.0')
|
|||
dep_lm = cc.find_library('m', required : false)
|
||||
dep_rt = cc.find_library('rt', required : false)
|
||||
|
||||
config_h.set10('HAVE_PLUGINS', true)
|
||||
|
||||
# Include directories
|
||||
includes_include = include_directories('include')
|
||||
includes_src = include_directories('src')
|
||||
|
|
@ -381,6 +383,9 @@ if get_option('internal-event-debugging')
|
|||
config_h.set('EVENT_DEBUGGING', 1)
|
||||
endif
|
||||
|
||||
config_h.set_quoted('LIBINPUT_PLUGIN_LIBDIR', dir_lib / 'libinput' / 'plugins')
|
||||
config_h.set_quoted('LIBINPUT_PLUGIN_ETCDIR', dir_etc / 'libinput' / 'plugins')
|
||||
|
||||
install_headers('src/libinput.h')
|
||||
src_libinput = src_libfilter + [
|
||||
'src/libinput.c',
|
||||
|
|
|
|||
|
|
@ -327,6 +327,55 @@ libinput_plugin_notify_device_removed(struct libinput_plugin *plugin,
|
|||
plugin->interface->device_removed(plugin, device);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void
|
||||
libinput_plugin_system_append_path(struct libinput *libinput, const char *path)
|
||||
{
|
||||
if (libinput->plugin_system.loaded) {
|
||||
log_bug_client(libinput, "plugin system already initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strv_find(libinput->plugin_system.directories, path, NULL))
|
||||
return;
|
||||
|
||||
libinput->plugin_system.directories =
|
||||
strv_append_strdup(libinput->plugin_system.directories, path);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT void
|
||||
libinput_plugin_system_append_default_paths(struct libinput *libinput)
|
||||
{
|
||||
if (libinput->plugin_system.loaded) {
|
||||
log_bug_client(libinput, "plugin system already initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
libinput_plugin_system_append_path(libinput, LIBINPUT_PLUGIN_ETCDIR);
|
||||
libinput_plugin_system_append_path(libinput, LIBINPUT_PLUGIN_LIBDIR);
|
||||
}
|
||||
|
||||
LIBINPUT_EXPORT int
|
||||
libinput_plugin_system_load_plugins(struct libinput *libinput,
|
||||
enum libinput_plugins_flags flags)
|
||||
{
|
||||
if (libinput->plugin_system.loaded) {
|
||||
log_bug_client(libinput, "%s() called twice\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
libinput_plugin_system_load_internal_plugins(libinput,
|
||||
&libinput->plugin_system);
|
||||
libinput->plugin_system.loaded = true;
|
||||
|
||||
libinput_plugin_system_run(&libinput->plugin_system);
|
||||
|
||||
#if !HAVE_PLUGINS
|
||||
return -ENOSYS;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_run(struct libinput_plugin_system *system)
|
||||
{
|
||||
|
|
@ -403,6 +452,7 @@ libinput_plugin_system_load_internal_plugins(struct libinput *libinput,
|
|||
* actually connected to anything yet */
|
||||
libinput_evdev_dispatch_plugin(libinput);
|
||||
}
|
||||
|
||||
void
|
||||
libinput_plugin_system_destroy(struct libinput_plugin_system *system)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3690,6 +3690,89 @@ libinput_path_add_device(struct libinput *libinput, const char *path);
|
|||
void
|
||||
libinput_path_remove_device(struct libinput_device *device);
|
||||
|
||||
/**
|
||||
* @ingroup base
|
||||
*
|
||||
* Appends the given directory path to the libinput plugin lookup path.
|
||||
* If the path is already in the lookup paths, it is ignored.
|
||||
*
|
||||
* A path's priority is determined by its position in the list; the first
|
||||
* path in the list has the highest priority.
|
||||
*
|
||||
* Plugin lookup is performed across all paths in lexical order. If
|
||||
* a plugin exists in multiple paths, the one in the highest priority
|
||||
* path (i.e. front of the list) is used.
|
||||
*
|
||||
* Paths are not traversed recursively.
|
||||
*
|
||||
* Plugins that have a 0 byte size shadow any plugins with the same name
|
||||
* but do not provide any fuctionality. This allows disabling a plugin
|
||||
* by simply dropping an empty file in a higher-priority directory.
|
||||
*
|
||||
* This function must be called before i
|
||||
* libinput_plugin_system_load_plugins().
|
||||
*
|
||||
* @see libinput_plugin_system_append_default_paths
|
||||
*
|
||||
* @since 1.29
|
||||
*/
|
||||
void
|
||||
libinput_plugin_system_append_path(struct libinput *libinput, const char *path);
|
||||
|
||||
/**
|
||||
* @ingroup base
|
||||
*
|
||||
* Add the default plugin lookup paths, typically:
|
||||
* - /etc/libinput/plugins/
|
||||
* - /usr/lib{64}/libinput/plugins/
|
||||
*
|
||||
* These paths are inserted at the current priority - to add
|
||||
* paths with a higher priority than these, call
|
||||
* libinput_plugin_system_append_path() prior to this function.
|
||||
*
|
||||
* See libinput_plugin_system_append_path() for more details.
|
||||
*
|
||||
* This function must be called before
|
||||
* libinput_plugin_system_load_plugins().
|
||||
*
|
||||
* @see libinput_plugin_system_append_paths
|
||||
*
|
||||
* @since 1.29
|
||||
*/
|
||||
void
|
||||
libinput_plugin_system_append_default_paths(struct libinput *libinput);
|
||||
|
||||
enum libinput_plugins_flags {
|
||||
LIBINPUT_PLUGIN_FLAG_NONE = 0,
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup base
|
||||
*
|
||||
* Load the plugins from the set of lookup paths. This function does nothing
|
||||
* if no plugin paths have been configured, see
|
||||
* libinput_plugin_system_append_default_paths() and
|
||||
* libinput_plugin_system_append_path().
|
||||
*
|
||||
* The typical use of this function is:
|
||||
* ```
|
||||
* struct libinput *li = libinput_udev_create_context(...);
|
||||
* libinput_plugin_system_append_default_paths(li);
|
||||
* libinput_plugin_system_load(li, flags);
|
||||
* ```
|
||||
*
|
||||
* This function must be called before libinput iterates through the
|
||||
* devices, i.e. before libinput_udev_assign_seat() or libinput_path_add_device().
|
||||
*
|
||||
* @return 0 or a negative errno on failure
|
||||
* @retval -ENOSYS libinput was compiled without plugin support
|
||||
*
|
||||
* @since 1.29
|
||||
*/
|
||||
int
|
||||
libinput_plugin_system_load_plugins(struct libinput *libinput,
|
||||
enum libinput_plugins_flags flags);
|
||||
|
||||
/**
|
||||
* @ingroup base
|
||||
*
|
||||
|
|
|
|||
|
|
@ -374,3 +374,9 @@ LIBINPUT_1.29 {
|
|||
libinput_tablet_tool_config_eraser_button_set_button;
|
||||
libinput_tablet_tool_config_eraser_button_set_mode;
|
||||
} LIBINPUT_1.28;
|
||||
|
||||
LIBINPUT_1.30 {
|
||||
libinput_plugin_system_append_default_paths;
|
||||
libinput_plugin_system_append_path;
|
||||
libinput_plugin_system_load_plugins;
|
||||
} LIBINPUT_1.29;
|
||||
|
|
|
|||
|
|
@ -2144,6 +2144,8 @@ litest_create_context(void)
|
|||
if (verbose)
|
||||
libinput_log_set_priority(libinput, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
|
||||
libinput_plugin_system_load_plugins(libinput, LIBINPUT_PLUGIN_FLAG_NONE);
|
||||
|
||||
return libinput;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -319,7 +319,13 @@ main(int argc, char **argv)
|
|||
if (verbose)
|
||||
printf("libinput version: %s\n", LIBINPUT_VERSION);
|
||||
|
||||
li = tools_open_backend(backend, seat_or_devices, verbose, &grab);
|
||||
bool with_plugins = (options.plugins == 1);
|
||||
li = tools_open_backend(backend,
|
||||
seat_or_devices,
|
||||
verbose,
|
||||
&grab,
|
||||
with_plugins,
|
||||
steal(&options.plugin_paths));
|
||||
if (!li)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
|
|||
|
|
@ -2007,7 +2007,13 @@ main(int argc, char **argv)
|
|||
backend = BACKEND_UDEV;
|
||||
}
|
||||
|
||||
li = tools_open_backend(backend, seat_or_device, verbose, &w.grab);
|
||||
bool with_plugins = (options.plugins == 1);
|
||||
li = tools_open_backend(backend,
|
||||
seat_or_device,
|
||||
verbose,
|
||||
&w.grab,
|
||||
with_plugins,
|
||||
steal(&options.plugin_paths));
|
||||
if (!li)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
|
|||
|
|
@ -528,7 +528,14 @@ main(int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
li = tools_open_backend(backend, seat_or_device, false, &grab);
|
||||
bool with_plugins = (options.plugins == 1);
|
||||
li = tools_open_backend(backend,
|
||||
seat_or_device,
|
||||
false,
|
||||
&grab,
|
||||
with_plugins,
|
||||
steal(&options.plugin_paths));
|
||||
|
||||
if (!li)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
|
|||
|
|
@ -602,7 +602,13 @@ main(int argc, char **argv)
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
li = tools_open_backend(backend, seat_or_device, false, &grab);
|
||||
bool with_plugins = (options.plugins == 1);
|
||||
li = tools_open_backend(backend,
|
||||
seat_or_device,
|
||||
false,
|
||||
&grab,
|
||||
with_plugins,
|
||||
steal(&options.plugin_paths));
|
||||
if (!li)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
|
|
|
|||
|
|
@ -606,10 +606,15 @@ main(int argc, char **argv)
|
|||
}
|
||||
devices[ndevices++] = argv[optind];
|
||||
} while (++optind < argc);
|
||||
li = tools_open_backend(BACKEND_DEVICE, devices, false, &grab);
|
||||
li = tools_open_backend(BACKEND_DEVICE,
|
||||
devices,
|
||||
false,
|
||||
&grab,
|
||||
false,
|
||||
NULL);
|
||||
} else {
|
||||
const char *seat[2] = { "seat0", NULL };
|
||||
li = tools_open_backend(BACKEND_UDEV, seat, false, &grab);
|
||||
li = tools_open_backend(BACKEND_UDEV, seat, false, &grab, false, NULL);
|
||||
}
|
||||
if (!li)
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ void
|
|||
tools_init_options(struct tools_options *options)
|
||||
{
|
||||
memset(options, 0, sizeof(*options));
|
||||
options->plugins = -1;
|
||||
options->plugin_paths = NULL;
|
||||
options->tapping = -1;
|
||||
options->tap_map = -1;
|
||||
options->drag = -1;
|
||||
|
|
@ -146,6 +148,15 @@ int
|
|||
tools_parse_option(int option, const char *optarg, struct tools_options *options)
|
||||
{
|
||||
switch (option) {
|
||||
case OPT_PLUGINS_ENABLE:
|
||||
options->plugins = 1;
|
||||
break;
|
||||
case OPT_PLUGINS_DISABLE:
|
||||
options->plugins = 0;
|
||||
break;
|
||||
case OPT_PLUGIN_PATH:
|
||||
options->plugin_paths = strv_from_string(optarg, ":", NULL);
|
||||
break;
|
||||
case OPT_TAP_ENABLE:
|
||||
options->tapping = 1;
|
||||
break;
|
||||
|
|
@ -494,8 +505,46 @@ static const struct libinput_interface interface = {
|
|||
.close_restricted = close_restricted,
|
||||
};
|
||||
|
||||
static int
|
||||
add_path(const char *str, size_t index, void *data)
|
||||
{
|
||||
struct libinput *libinput = data;
|
||||
libinput_plugin_system_append_default_paths(libinput);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
tools_load_plugins(struct libinput *libinput, char **plugin_paths)
|
||||
{
|
||||
_autofree_ char *builddir = NULL;
|
||||
|
||||
if (plugin_paths) {
|
||||
strv_for_each((const char **)plugin_paths, add_path, libinput);
|
||||
strv_free(plugin_paths);
|
||||
} else {
|
||||
if (builddir_lookup(&builddir)) {
|
||||
_autofree_ char *plugindir =
|
||||
strdup_printf("%s/plugins", builddir);
|
||||
libinput_plugin_system_append_path(libinput, plugindir);
|
||||
}
|
||||
libinput_plugin_system_append_default_paths(libinput);
|
||||
}
|
||||
switch (libinput_plugin_system_load_plugins(libinput,
|
||||
LIBINPUT_PLUGIN_FLAG_NONE)) {
|
||||
case -ENOSYS:
|
||||
fprintf(stderr, "Warning: plugins were disabled at compile time");
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct libinput *
|
||||
tools_open_udev(const char *seat, bool verbose, bool *grab)
|
||||
tools_open_udev(const char *seat,
|
||||
bool verbose,
|
||||
bool *grab,
|
||||
bool with_plugins,
|
||||
char **plugin_paths)
|
||||
{
|
||||
_unref_(udev) *udev = udev_new();
|
||||
if (!udev) {
|
||||
|
|
@ -513,6 +562,9 @@ tools_open_udev(const char *seat, bool verbose, bool *grab)
|
|||
if (verbose)
|
||||
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
|
||||
if (with_plugins)
|
||||
tools_load_plugins(li, plugin_paths);
|
||||
|
||||
if (libinput_udev_assign_seat(li, seat)) {
|
||||
fprintf(stderr, "Failed to set seat\n");
|
||||
return NULL;
|
||||
|
|
@ -522,7 +574,11 @@ tools_open_udev(const char *seat, bool verbose, bool *grab)
|
|||
}
|
||||
|
||||
static struct libinput *
|
||||
tools_open_device(const char **paths, bool verbose, bool *grab)
|
||||
tools_open_device(const char **paths,
|
||||
bool verbose,
|
||||
bool *grab,
|
||||
bool with_plugins,
|
||||
char **plugin_paths)
|
||||
{
|
||||
_unref_(libinput) *li = libinput_path_create_context(&interface, grab);
|
||||
if (!li) {
|
||||
|
|
@ -535,6 +591,9 @@ tools_open_device(const char **paths, bool verbose, bool *grab)
|
|||
libinput_log_set_priority(li, LIBINPUT_LOG_PRIORITY_DEBUG);
|
||||
}
|
||||
|
||||
if (with_plugins)
|
||||
tools_load_plugins(li, plugin_paths);
|
||||
|
||||
const char **p = paths;
|
||||
while (*p) {
|
||||
struct libinput_device *device = libinput_path_add_device(li, *p);
|
||||
|
|
@ -559,7 +618,9 @@ struct libinput *
|
|||
tools_open_backend(enum tools_backend which,
|
||||
const char **seat_or_device,
|
||||
bool verbose,
|
||||
bool *grab)
|
||||
bool *grab,
|
||||
bool with_plugins,
|
||||
char **plugin_paths)
|
||||
{
|
||||
struct libinput *li;
|
||||
|
||||
|
|
@ -567,10 +628,18 @@ tools_open_backend(enum tools_backend which,
|
|||
|
||||
switch (which) {
|
||||
case BACKEND_UDEV:
|
||||
li = tools_open_udev(seat_or_device[0], verbose, grab);
|
||||
li = tools_open_udev(seat_or_device[0],
|
||||
verbose,
|
||||
grab,
|
||||
with_plugins,
|
||||
plugin_paths);
|
||||
break;
|
||||
case BACKEND_DEVICE:
|
||||
li = tools_open_device(seat_or_device, verbose, grab);
|
||||
li = tools_open_device(seat_or_device,
|
||||
verbose,
|
||||
grab,
|
||||
with_plugins,
|
||||
plugin_paths);
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
|
|
|
|||
|
|
@ -77,10 +77,15 @@ enum configuration_options {
|
|||
OPT_SENDEVENTS,
|
||||
OPT_ERASER_BUTTON_MODE,
|
||||
OPT_ERASER_BUTTON_BUTTON,
|
||||
OPT_PLUGINS_DISABLE,
|
||||
OPT_PLUGINS_ENABLE,
|
||||
OPT_PLUGIN_PATH,
|
||||
};
|
||||
|
||||
#define CONFIGURATION_OPTIONS \
|
||||
{ "disable-sendevents", required_argument, 0, OPT_DISABLE_SENDEVENTS }, \
|
||||
{ "enable-plugins", no_argument, 0, OPT_PLUGINS_ENABLE }, \
|
||||
{ "disable-plugins", no_argument, 0, OPT_PLUGINS_DISABLE }, \
|
||||
{ "enable-tap", no_argument, 0, OPT_TAP_ENABLE }, \
|
||||
{ "disable-tap", no_argument, 0, OPT_TAP_DISABLE }, \
|
||||
{ "enable-drag", no_argument, 0, OPT_DRAG_ENABLE }, \
|
||||
|
|
@ -117,7 +122,8 @@ enum configuration_options {
|
|||
{ "set-calibration", required_argument, 0, OPT_CALIBRATION }, \
|
||||
{ "set-area", required_argument, 0, OPT_AREA }, \
|
||||
{ "set-eraser-button-mode", required_argument, 0, OPT_ERASER_BUTTON_MODE }, \
|
||||
{ "set-eraser-button-button", required_argument, 0, OPT_ERASER_BUTTON_BUTTON }
|
||||
{ "set-eraser-button-button", required_argument, 0, OPT_ERASER_BUTTON_BUTTON },\
|
||||
{ "set-plugin-path", required_argument, 0, OPT_PLUGIN_PATH }
|
||||
|
||||
/* Note: New arguments should be added to shell completions */
|
||||
|
||||
|
|
@ -144,6 +150,9 @@ enum tools_backend { BACKEND_NONE, BACKEND_DEVICE, BACKEND_UDEV };
|
|||
struct tools_options {
|
||||
char match[256];
|
||||
|
||||
int plugins;
|
||||
char **plugin_paths;
|
||||
|
||||
int tapping;
|
||||
int drag;
|
||||
int drag_lock;
|
||||
|
|
@ -183,7 +192,9 @@ struct libinput *
|
|||
tools_open_backend(enum tools_backend which,
|
||||
const char **seat_or_devices,
|
||||
bool verbose,
|
||||
bool *grab);
|
||||
bool *grab,
|
||||
bool with_plugins,
|
||||
char **plugin_paths);
|
||||
void
|
||||
tools_device_apply_config(struct libinput_device *device,
|
||||
struct tools_options *options);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue