tty: Load libinput plugins if available

Some distros like Fedora build libinput with plugin autoloading, however
by default, the compositor needs to explicitly load them. Plus, we need
to load manually if we want to also load from
$XDG_CONFIG_HOME/libinput/plugins.

Ref. https://gitlab.gnome.org/GNOME/mutter/-/commit/c5b12fbf6313d51f3279901bb561023e56181e36
This commit is contained in:
Ivan Molodetskikh
2025-12-29 16:14:52 +03:00
parent b5640d5293
commit 1ab1737653
4 changed files with 59 additions and 0 deletions
Generated
+1
View File
@@ -2207,6 +2207,7 @@ dependencies = [
"pango",
"pangocairo",
"pipewire",
"pkg-config",
"png",
"portable-atomic",
"profiling",
+3
View File
@@ -126,6 +126,9 @@ rayon = "1.11.0"
wayland-client = "0.31.11"
xshell = "0.2.7"
[build-dependencies]
pkg-config = "0.3.32"
[features]
default = ["dbus", "systemd", "xdp-gnome-screencast"]
# Enables D-Bus support (serve various freedesktop and GNOME interfaces, accessibility tree, power button handling).
+10
View File
@@ -0,0 +1,10 @@
fn main() {
println!("cargo:rustc-check-cfg=cfg(have_libinput_plugin_system)");
if pkg_config::Config::new()
.atleast_version("1.30.0")
.probe("libinput")
.is_ok()
{
println!("cargo:rustc-cfg=have_libinput_plugin_system")
}
}
+45
View File
@@ -434,6 +434,7 @@ impl Tty {
.unwrap();
let mut libinput = Libinput::new_with_udev(LibinputSessionInterface::from(session.clone()));
unsafe { init_libinput_plugin_system(&libinput) };
{
let _span = tracy_client::span!("Libinput::udev_assign_seat");
libinput.udev_assign_seat(&seat_name)
@@ -3334,6 +3335,50 @@ fn make_output_name(
}
}
/// Initializes the libinput plugin system.
///
/// # Safety
///
/// This function must be called before libinput iterates through the devices, i.e. before
/// libinput_udev_assign_seat() or the first call to libinput_path_add_device().
unsafe fn init_libinput_plugin_system(libinput: &Libinput) {
#[cfg(have_libinput_plugin_system)]
unsafe {
use std::ffi::{c_char, c_int, CString};
use std::os::unix::ffi::OsStringExt;
use directories::BaseDirs;
use input::ffi::libinput;
use input::AsRaw as _;
extern "C" {
fn libinput_plugin_system_append_path(libinput: *const libinput, path: *const c_char);
fn libinput_plugin_system_append_default_paths(libinput: *const libinput);
fn libinput_plugin_system_load_plugins(
libinput: *const libinput,
flags: c_int,
) -> c_int;
}
const LIBINPUT_PLUGIN_SYSTEM_FLAG_NONE: c_int = 0;
let libinput = libinput.as_raw();
// Also load plugins from $XDG_CONFIG_HOME/libinput/plugins.
if let Some(dirs) = BaseDirs::new() {
let mut plugins_dir = dirs.config_dir().to_path_buf();
plugins_dir.push("libinput");
plugins_dir.push("plugins");
if let Ok(plugins_dir) = CString::new(plugins_dir.into_os_string().into_vec()) {
libinput_plugin_system_append_path(libinput, plugins_dir.as_ptr());
}
}
libinput_plugin_system_append_default_paths(libinput);
libinput_plugin_system_load_plugins(libinput, LIBINPUT_PLUGIN_SYSTEM_FLAG_NONE);
}
#[cfg(not(have_libinput_plugin_system))]
let _ = libinput;
}
#[cfg(test)]
mod tests {
use insta::assert_debug_snapshot;