diff --git a/src/evdev.h b/src/evdev.h index 766df563..9263fb6a 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -36,6 +36,7 @@ #include "evdev-frame.h" #include "filter.h" +#include "libinput-feature.h" #include "libinput-private.h" #include "linux/input.h" #include "quirks.h" @@ -352,6 +353,9 @@ struct evdev_dispatch_interface { void (*left_handed_toggle)(struct evdev_dispatch *dispatch, struct evdev_device *device, bool left_handed_enabled); + + void (*disable_feature)(struct evdev_dispatch *dispatch, + enum libinput_feature feature); }; enum evdev_dispatch_type { @@ -389,6 +393,14 @@ evdev_libinput_context(const struct evdev_device *device) return device->base.seat->libinput; } +static inline void +evdev_device_disable_feature(struct evdev_device *device, enum libinput_feature feature) +{ + if (device->dispatch && device->dispatch->interface && + device->dispatch->interface->disable_feature) + device->dispatch->interface->disable_feature(device->dispatch, feature); +} + static inline bool evdev_device_has_model_quirk(struct evdev_device *device, enum quirk model_quirk) { diff --git a/src/libinput-feature.h b/src/libinput-feature.h new file mode 100644 index 00000000..bc802868 --- /dev/null +++ b/src/libinput-feature.h @@ -0,0 +1,26 @@ +/* + * 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 + +enum libinput_feature { LIBINPUT_FEATURE_BUTTON_DEBOUNCING = 1, _LIBINPUT_N_FEATURES }; diff --git a/src/libinput-plugin-system.h b/src/libinput-plugin-system.h index 7a2906f2..5dafa8c7 100644 --- a/src/libinput-plugin-system.h +++ b/src/libinput-plugin-system.h @@ -34,6 +34,7 @@ #include "evdev-frame.h" #include "libinput.h" +enum libinput_feature; struct libinput; struct libinput_plugin; @@ -95,3 +96,9 @@ void libinput_plugin_system_notify_evdev_frame(struct libinput_plugin_system *system, struct libinput_device *device, struct evdev_frame *frame); + +void +libinput_plugin_system_notify_device_feature_disabled( + struct libinput_plugin_system *system, + struct libinput_device *device, + enum libinput_feature feature); diff --git a/src/libinput-plugin.c b/src/libinput-plugin.c index 72d969fe..de60a647 100644 --- a/src/libinput-plugin.c +++ b/src/libinput-plugin.c @@ -30,12 +30,14 @@ #include "evdev-frame.h" #include "evdev-plugin.h" +#include "libinput-feature.h" #include "libinput-plugin-button-debounce.h" #include "libinput-plugin-lua.h" #include "libinput-plugin-mouse-wheel-lowres.h" #include "libinput-plugin-mouse-wheel.h" #include "libinput-plugin-mtdev.h" #include "libinput-plugin-private.h" +#include "libinput-plugin-system.h" #include "libinput-plugin-tablet-double-tool.h" #include "libinput-plugin-tablet-eraser-button.h" #include "libinput-plugin-tablet-forced-tool.h" @@ -208,6 +210,22 @@ libinput_plugin_enable_evdev_usage(struct libinput_plugin *plugin, evdev_mask_set_usage(plugin->mask, evdev_usage_from(usage)); } +void +libinput_plugin_disable_device_feature(struct libinput_plugin *plugin, + struct libinput_device *device, + enum libinput_feature feature) +{ + struct libinput *libinput = plugin->libinput; + + /* During device-added, only some plugins are loaded so this notifies + * some of the plugins. All plugins are notified once device-added is + * complete. */ + libinput_plugin_system_notify_device_feature_disabled(&libinput->plugin_system, + device, + feature); + bitmask_set_bit(&device->disabled_features, feature); +} + struct plugin_queued_event { struct list link; struct evdev_frame *frame; /* owns a ref */ @@ -501,6 +519,21 @@ libinput_plugin_system_notify_device_added(struct libinput_plugin_system *system libinput_plugin_notify_device_added(plugin, device); } libinput_plugin_system_drop_unregistered_plugins(system); + + /* Now that we added all our devices in all our plugins, notify + * all plugins about disabled features. Some plugins may get + * this notification twice but they should be able to handle that + * case. + */ + enum libinput_feature feature = _LIBINPUT_N_FEATURES; + + while (--feature > 0) { + if (bitmask_bit_is_set(device->disabled_features, feature)) { + libinput_plugin_system_notify_device_feature_disabled(system, + device, + feature); + } + } } void @@ -538,6 +571,22 @@ libinput_plugin_system_notify_tablet_tool_configured( libinput_plugin_system_drop_unregistered_plugins(system); } +void +libinput_plugin_system_notify_device_feature_disabled( + struct libinput_plugin_system *system, + struct libinput_device *device, + enum libinput_feature feature) +{ + libinput_device_disable_feature(device, feature); + + struct libinput_plugin *plugin; + list_for_each_safe(plugin, &system->plugins, link) { + if (plugin->interface->feature_disabled) + plugin->interface->feature_disabled(plugin, device, feature); + } + libinput_plugin_system_drop_unregistered_plugins(system); +} + static void libinput_plugin_process_frame(struct libinput_plugin *plugin, struct libinput_device *device, diff --git a/src/libinput-plugin.h b/src/libinput-plugin.h index 3639b792..d96f7878 100644 --- a/src/libinput-plugin.h +++ b/src/libinput-plugin.h @@ -39,6 +39,7 @@ struct libinput_device; struct libinput_tablet_tool; struct libinput_plugin; enum libinput_log_priority; +enum libinput_feature; #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__) @@ -107,6 +108,14 @@ struct libinput_plugin_interface { */ void (*tool_configured)(struct libinput_plugin *plugin, struct libinput_tablet_tool *tool); + + /** + * Notification that the given feature was disabled on + * the given device. + */ + void (*feature_disabled)(struct libinput_plugin *plugin, + struct libinput_device *device, + enum libinput_feature feature); }; /** @@ -159,6 +168,11 @@ libinput_plugin_enable_device_event_frame(struct libinput_plugin *plugin, struct libinput_device *device, bool enable); +void +libinput_plugin_disable_device_feature(struct libinput_plugin *plugin, + struct libinput_device *device, + enum libinput_feature feature); + /** * Mask this plugin's evdev_frame function to be called only * if the frame **contains** the given evdev usage. Plugins diff --git a/src/libinput-private.h b/src/libinput-private.h index 30ee5650..a4b6f5e9 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -35,6 +35,7 @@ #include #endif +#include "util-bits.h" #include "util-newtype.h" #include "libinput-log.h" @@ -528,6 +529,11 @@ struct libinput_device { struct libinput_device_config config; bitmask_t plugin_frame_callbacks; + /** + * Lua plugins see the device before our internal + * plugins do any calls need to be cached. + */ + bitmask_t disabled_features; void (*inject_evdev_frame)(struct libinput_device *device, struct evdev_frame *frame); @@ -724,6 +730,10 @@ libinput_device_init(struct libinput_device *device, struct libinput_seat *seat) bool libinput_device_has_model_quirk(struct libinput_device *device, enum quirk model_quirk); +void +libinput_device_disable_feature(struct libinput_device *device, + enum libinput_feature feature); + struct libinput_device_group * libinput_device_group_create(struct libinput *libinput, const char *identifier); diff --git a/src/libinput.c b/src/libinput.c index 949780e8..95b82eab 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -38,6 +38,7 @@ #include "util-libinput.h" #include "evdev.h" +#include "libinput-feature.h" #include "libinput-private.h" #include "libinput.h" #include "quirks.h" @@ -2166,6 +2167,13 @@ libinput_device_unref(struct libinput_device *device) return device; } +void +libinput_device_disable_feature(struct libinput_device *device, + enum libinput_feature feature) +{ + evdev_device_disable_feature((struct evdev_device *)device, feature); +} + LIBINPUT_EXPORT int libinput_get_fd(struct libinput *libinput) {