From e8fc44117b4ecb877fe6dbb9ac271c0abdb1b9fd Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Tue, 5 Nov 2024 20:11:48 -0700 Subject: [PATCH] input-device: Check for sections matching key udev properties This patch adds additional checks for input-device sections in the config file. It checks for ID_PATH, ID_SERIAL, LIBINPUT_DEVICE_GROUP then falls back to the device name and finally the global input-device section. In addition, DEVPATH is printed to log when WF_PRINT_UDEV_DEVPATH is set and '-d' is passed to wayfire, for matching the correct device in i.e. 'udevadm info --tree'. The sections that wayfire checks for are also logged with '-d'. This makes it so users can match devices, especially identical devices lacking many of the usual differentiating properties. Fixes #2504. --- meson.build | 1 + src/core/plugin.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++--- src/meson.build | 3 +- 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/meson.build b/meson.build index c5987607f..73178d211 100644 --- a/meson.build +++ b/meson.build @@ -34,6 +34,7 @@ pixman = dependency('pixman-1') xkbcommon = dependency('xkbcommon') libdl = meson.get_compiler('cpp').find_library('dl') json = dependency('nlohmann_json', version: '>= 3.11.2') +udev = dependency('libudev') # We're not to use system wlroots: So we'll use the subproject if get_option('use_system_wlroots').disabled() diff --git a/src/core/plugin.cpp b/src/core/plugin.cpp index 6d7d8917d..afec20d2f 100644 --- a/src/core/plugin.cpp +++ b/src/core/plugin.cpp @@ -5,6 +5,7 @@ #include "wayfire/signal-definitions.hpp" #include #include +#include void wf::plugin_interface_t::fini() {} @@ -27,18 +28,76 @@ std::shared_ptr wf::config_backend_t::get_output_section( return config.get_section(name); } +static struct udev_property_and_desc +{ + char const *property_name; + char const *description; +} properties_and_descs[] = +{ + {"ID_PATH", "stable physical connection path"}, + {"ID_SERIAL", "stable vendor+pn+sn info"}, + {"LIBINPUT_DEVICE_GROUP", "stable libinput info"}, + // sometimes it contains info "by path", sometimes "by id" + {"DEVPATH", "unstable devpath"}, + // used for debugging, to find DEVPATH and match the right + // device in `udevadm info --tree` +}; + std::shared_ptr wf::config_backend_t::get_input_device_section( wlr_input_device *device) { + auto& config = wf::get_core().config; + std::shared_ptr section; + auto print_devpath = getenv("WF_PRINT_UDEV_DEVPATH"); + + if (wlr_input_device_is_libinput(device)) + { + auto libinput_dev = wlr_libinput_get_device_handle(device); + if (libinput_dev) + { + udev_device *udev_dev = libinput_device_get_udev_device(libinput_dev); + if (udev_dev) + { + for (struct property_and_desc const & pd : properties_and_descs) + { + if (!print_devpath && !strncmp(pd.property_name, "DEVPATH", strlen("DEVPATH"))) + { + continue; + } + + const char *value = udev_device_get_property_value(udev_dev, pd.property_name); + if (value == nullptr) + { + continue; + } + + std::string name = std::string("input-device:") + nonull(value); + LOGD("Checking for config section [", name, "] ", + pd.property_name, " (", pd.description, ")"); + section = config.get_section(name); + if (section) + { + LOGD("Using config section [", name, "] for ", nonull(device->name)); + return section; + } + } + } + } + } + std::string name = nonull(device->name); name = "input-device:" + name; - auto& config = wf::get_core().config; - if (!config.get_section(name)) + LOGD("Checking for config section [", name, "]"); + section = config.get_section(name); + if (section) { - config.merge_section( - config.get_section("input-device")->clone_with_name(name)); + LOGD("Using config section [", name, "]"); + return section; } + config.merge_section( + config.get_section("input-device")->clone_with_name(name)); + return config.get_section(name); } diff --git a/src/meson.build b/src/meson.build index 384533ae7..ebc7463e3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -64,7 +64,8 @@ wayfire_sources = ['geometry.cpp', wayfire_dependencies = [wayland_server, wlroots, xkbcommon, libinput, pixman, drm, egl, glesv2, glm, wf_protos, libdl, - wfconfig, libinotify, backtrace, wfutils, xcb, wftouch, json] + wfconfig, libinotify, backtrace, wfutils, xcb, + wftouch, json, udev] if conf_data.get('BUILD_WITH_IMAGEIO') wayfire_dependencies += [jpeg, png]