From eea9c6331f01729d5feb8f86a4c0bbb53012d292 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 8 Feb 2021 19:24:20 +0100 Subject: Automatically map built-in touchscreens/tablets to built-in panels Detect whether an output is built-in via its type. Detect whether a touchscreen or tablet tool is built-in via its ID_PATH property. --- include/sway/input/libinput.h | 2 ++ meson.build | 1 + sway/input/libinput.c | 23 ++++++++++++++++++++ sway/input/seat.c | 49 +++++++++++++++++++++++++++++++++++++++++++ sway/meson.build | 1 + 5 files changed, 76 insertions(+) diff --git a/include/sway/input/libinput.h b/include/sway/input/libinput.h index de019976..890d632e 100644 --- a/include/sway/input/libinput.h +++ b/include/sway/input/libinput.h @@ -6,4 +6,6 @@ void sway_input_configure_libinput_device(struct sway_input_device *device); void sway_input_reset_libinput_device(struct sway_input_device *device); +bool sway_libinput_device_is_builtin(struct sway_input_device *device); + #endif diff --git a/meson.build b/meson.build index cb4ee20e..60daf882 100644 --- a/meson.build +++ b/meson.build @@ -54,6 +54,7 @@ libinput = dependency('libinput', version: '>=1.6.0') xcb = dependency('xcb', required: get_option('xwayland')) drm_full = dependency('libdrm') # only needed for drm_fourcc.h drm = drm_full.partial_dependency(compile_args: true, includes: true) +libudev = dependency('libudev') bash_comp = dependency('bash-completion', required: false) fish_comp = dependency('fish', required: false) math = cc.find_library('m') diff --git a/sway/input/libinput.c b/sway/input/libinput.c index 54520f9e..060a584a 100644 --- a/sway/input/libinput.c +++ b/sway/input/libinput.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include "log.h" @@ -312,3 +313,25 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) { ipc_event_input("libinput_config", input_device); } } + +bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) { + if (!wlr_input_device_is_libinput(sway_device->wlr_device)) { + return false; + } + + struct libinput_device *device = + wlr_libinput_get_device_handle(sway_device->wlr_device); + struct udev_device *udev_device = + libinput_device_get_udev_device(device); + if (!udev_device) { + return false; + } + + const char *id_path = udev_device_get_property_value(udev_device, "ID_PATH"); + if (!id_path) { + return false; + } + + const char prefix[] = "platform-"; + return strncmp(id_path, prefix, strlen(prefix)) == 0; +} diff --git a/sway/input/seat.c b/sway/input/seat.c index e6e1d4fb..d23525a8 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -20,6 +20,7 @@ #include "sway/input/cursor.h" #include "sway/input/input-manager.h" #include "sway/input/keyboard.h" +#include "sway/input/libinput.h" #include "sway/input/seat.h" #include "sway/input/switch.h" #include "sway/input/tablet.h" @@ -666,6 +667,40 @@ static void seat_reset_input_config(struct sway_seat *seat, sway_device->input_device->wlr_device, NULL); } +static bool has_prefix(const char *str, const char *prefix) { + return strncmp(str, prefix, strlen(prefix)) == 0; +} + +/** + * Get the name of the built-in output, if any. Returns NULL if there isn't + * exactly one built-in output. + */ +static const char *get_builtin_output_name(void) { + const char *match = NULL; + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + const char *name = output->wlr_output->name; + if (has_prefix(name, "eDP-") || has_prefix(name, "LVDS-") || + has_prefix(name, "DSI-")) { + if (match != NULL) { + return NULL; + } + match = name; + } + } + return match; +} + +static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { + switch (seat_device->input_device->wlr_device->type) { + case WLR_INPUT_DEVICE_TOUCH: + case WLR_INPUT_DEVICE_TABLET_TOOL: + return true; + default: + return false; + } +} + static void seat_apply_input_config(struct sway_seat *seat, struct sway_seat_device *sway_device) { struct input_config *ic = @@ -681,7 +716,21 @@ static void seat_apply_input_config(struct sway_seat *seat, switch (mapped_to) { case MAPPED_TO_DEFAULT: + /* + * If the wlroots backend provides an output name, use that. + * + * Otherwise, try to map built-in touch and tablet tool devices to the + * built-in output. + */ mapped_to_output = sway_device->input_device->wlr_device->output_name; + if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) && + sway_libinput_device_is_builtin(sway_device->input_device)) { + mapped_to_output = get_builtin_output_name(); + if (mapped_to_output) { + sway_log(SWAY_DEBUG, "Auto-detected output '%s' for device '%s'", + mapped_to_output, sway_device->input_device->identifier); + } + } if (mapped_to_output == NULL) { return; } diff --git a/sway/meson.build b/sway/meson.build index f163ee90..b52fada4 100644 --- a/sway/meson.build +++ b/sway/meson.build @@ -208,6 +208,7 @@ sway_deps = [ jsonc, libevdev, libinput, + libudev, math, pango, pcre, -- cgit v1.2.3-54-g00ecf