From 2a342ee056e13a01d175d5e0f15d528440d54a81 Mon Sep 17 00:00:00 2001 From: cyber-sushi Date: Sat, 2 Nov 2024 19:43:01 +0100 Subject: [PATCH] Inject tablet/pen events into a dedicated uinput device --- src/event_reader.rs | 115 ++++++++++++++++++++++++++++++----------- src/udev_monitor.rs | 5 +- src/virtual_devices.rs | 56 +++++++++++++++++++- 3 files changed, 143 insertions(+), 33 deletions(-) diff --git a/src/event_reader.rs b/src/event_reader.rs index bf9054e..19a779e 100644 --- a/src/event_reader.rs +++ b/src/event_reader.rs @@ -52,6 +52,7 @@ pub struct EventReader { impl EventReader { pub fn new( config: Vec, + virt_dev: Arc>, stream: Arc>, modifiers: Arc>>, modifier_was_activated: Arc>, @@ -72,7 +73,6 @@ impl EventReader { .unwrap() .clone(), )); - let virt_dev = Arc::new(Mutex::new(VirtualDevices::new())); let lstick_function = config .iter() .find(|&x| x.associations == Associations::default()) @@ -264,6 +264,11 @@ impl EventReader { ) = ((0, 0), (0, 0), (0, 0), (0, 0), 0); let switcher: Key = self.settings.layout_switcher; let mut stream = self.stream.lock().await; + let mut pen_events: Vec = Vec::new(); + let is_tablet: bool = + stream.device().properties().contains(evdev::PropType::POINTER) + && stream.device().supported_keys() + .unwrap_or(&evdev::AttributeSet::new()).contains(evdev::Key::BTN_TOOL_PEN); let mut max_abs_wheel = 0; if let Ok(abs_state) = stream.device().get_abs_state() { for state in abs_state { @@ -277,9 +282,18 @@ impl EventReader { event.event_type(), RelativeAxisType(event.code()), AbsoluteAxisType(event.code()), + is_tablet, ) { - (EventType::KEY, _, _) => match Key(event.code()) { + (EventType::KEY, _, _, _) => match Key(event.code()) { Key::BTN_TL2 | Key::BTN_TR2 => {} + Key::BTN_TOOL_PEN + | Key::BTN_TOOL_RUBBER + | Key::BTN_TOOL_BRUSH + | Key::BTN_TOOL_PENCIL + | Key::BTN_TOOL_AIRBRUSH + | Key::BTN_TOOL_MOUSE + | Key::BTN_TOOL_LENS + if is_tablet => pen_events.push(event), key if key == switcher && event.value() == 1 => { self.change_active_layout().await } @@ -297,6 +311,7 @@ impl EventReader { EventType::RELATIVE, RelativeAxisType::REL_WHEEL | RelativeAxisType::REL_WHEEL_HI_RES, _, + _, ) => match event.value() { -1 => { self.convert_event(event, Event::Axis(Axis::SCROLL_WHEEL_DOWN), 1, true) @@ -308,7 +323,35 @@ impl EventReader { } _ => {} }, - (_, _, AbsoluteAxisType::ABS_HAT0X) => { + (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_WHEEL, _) => { + let value = event.value(); + if value != 0 && abs_wheel_position != 0 { + let gap = value - abs_wheel_position; + if gap < -max_abs_wheel / 2 { + self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CW), 1, true) + .await; + } else if gap > max_abs_wheel / 2 { + self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CCW), 1, true) + .await; + } else if value > abs_wheel_position { + self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CW), 1, true) + .await; + } else if value < abs_wheel_position { + self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CCW), 1, true) + .await; + } + } + abs_wheel_position = value; + } + (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_MISC, false) => { + if event.value() == 0 { + abs_wheel_position = 0 + } + } + (EventType::ABSOLUTE, _, _, true) => { + pen_events.push(event) + } + (_, _, AbsoluteAxisType::ABS_HAT0X, _) => { match event.value() { -1 => { self.convert_event(event, Event::Axis(Axis::BTN_DPAD_LEFT), 1, false) @@ -347,7 +390,7 @@ impl EventReader { _ => {} }; } - (_, _, AbsoluteAxisType::ABS_HAT0Y) => { + (_, _, AbsoluteAxisType::ABS_HAT0Y, _) => { match event.value() { -1 => { self.convert_event(event, Event::Axis(Axis::BTN_DPAD_UP), 1, false) @@ -386,7 +429,12 @@ impl EventReader { _ => {} }; } - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_X | AbsoluteAxisType::ABS_Y) => { + ( + EventType::ABSOLUTE, + _, + AbsoluteAxisType::ABS_X | AbsoluteAxisType::ABS_Y, + false + ) => { match self.settings.lstick.function.as_str() { "cursor" | "scroll" => { let axis_value = self @@ -513,7 +561,12 @@ impl EventReader { _ => {} } } - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RX | AbsoluteAxisType::ABS_RY) => { + ( + EventType::ABSOLUTE, + _, + AbsoluteAxisType::ABS_RX | AbsoluteAxisType::ABS_RY, + false + ) => { match self.settings.rstick.function.as_str() { "cursor" | "scroll" => { let axis_value = self @@ -644,7 +697,7 @@ impl EventReader { _ => {} } } - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_Z) => { + (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_Z, false) => { match (event.value(), triggers_values.0) { (0, 1) => { self.convert_event(event, Event::Axis(Axis::BTN_TL2), 0, false) @@ -659,7 +712,7 @@ impl EventReader { _ => {} } } - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RZ) => { + (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RZ, false) => { match (event.value(), triggers_values.1) { (0, 1) => { self.convert_event(event, Event::Axis(Axis::BTN_TR2), 0, false) @@ -674,30 +727,15 @@ impl EventReader { _ => {} } } - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_WHEEL) => { - let value = event.value(); - if value != 0 && abs_wheel_position != 0 { - let gap = value - abs_wheel_position; - if gap < -max_abs_wheel / 2 { - self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CW), 1, true) - .await; - } else if gap > max_abs_wheel / 2 { - self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CCW), 1, true) - .await; - } else if value > abs_wheel_position { - self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CW), 1, true) - .await; - } else if value < abs_wheel_position { - self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CCW), 1, true) - .await; - } + (EventType::MISC, _, _, true) => { + if !stream.device().properties().contains(evdev::PropType::POINTER) { + self.emit_default_event(event).await; + } else if evdev::MiscType(event.code()) == evdev::MiscType::MSC_SERIAL { + pen_events.push(event); + let mut virt_dev = self.virt_dev.lock().await; + virt_dev.abs.emit(&pen_events).unwrap(); + pen_events.clear() } - abs_wheel_position = value; - } - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_MISC) => { - if event.value() == 0 { - abs_wheel_position = 0 - }; } _ => self.emit_default_event(event).await, } @@ -877,6 +915,13 @@ impl EventReader { EventType::RELATIVE => { virt_dev.axis.emit(&[default_event]).unwrap(); } + EventType::ABSOLUTE => { + virt_dev.abs.emit(&[default_event]).unwrap(); + } + EventType::MISC => { + let mut virt_dev = self.virt_dev.lock().await; + virt_dev.abs.emit(&[default_event]).unwrap(); + } _ => {} } } @@ -892,6 +937,14 @@ impl EventReader { let mut virt_dev = self.virt_dev.lock().await; virt_dev.axis.emit(&[event]).unwrap(); } + EventType::ABSOLUTE => { + let mut virt_dev = self.virt_dev.lock().await; + virt_dev.abs.emit(&[event]).unwrap(); + } + EventType::MISC => { + let mut virt_dev = self.virt_dev.lock().await; + virt_dev.abs.emit(&[event]).unwrap(); + } _ => {} } } diff --git a/src/udev_monitor.rs b/src/udev_monitor.rs index 2ab2fb1..482ebd6 100644 --- a/src/udev_monitor.rs +++ b/src/udev_monitor.rs @@ -1,6 +1,7 @@ use crate::config::{Associations, Event}; use crate::event_reader::EventReader; use crate::Config; +use crate::virtual_devices::VirtualDevices; use evdev::{Device, EventStream}; use std::{env, path::Path, process::Command, sync::Arc}; use tokio::sync::Mutex; @@ -138,8 +139,10 @@ pub fn launch_tasks( Path::new(&event_device), config_list.clone(), ))); + let virt_dev = Arc::new(Mutex::new(VirtualDevices::new(device.1))); let reader = EventReader::new( config_list.clone(), + virt_dev, stream, modifiers.clone(), modifier_was_activated.clone(), @@ -213,7 +216,7 @@ fn set_environment() -> Environment { } (Ok(session), Ok(desktop)) if session == wayland => { println!("Warning: unsupported compositor: {}, won't be able to change bindings according to the active window.\n\ - Currently supported desktops: Hyprland, Sway, Plasma/KWin, X11.\n", desktop); + Currently supported desktops: Hyprland, Sway, Niri, Plasma/KWin, X11.\n", desktop); Server::Unsupported } (Ok(session), _) if session == x11 => { diff --git a/src/virtual_devices.rs b/src/virtual_devices.rs index d835f77..417daa7 100644 --- a/src/virtual_devices.rs +++ b/src/virtual_devices.rs @@ -6,10 +6,11 @@ use evdev::{ pub struct VirtualDevices { pub keys: VirtualDevice, pub axis: VirtualDevice, + pub abs: VirtualDevice, } impl VirtualDevices { - pub fn new() -> Self { + pub fn new(device: evdev::Device) -> Self { let mut key_capabilities = evdev::AttributeSet::new(); for i in 1..334 { key_capabilities.insert(Key(i)); @@ -18,6 +19,46 @@ impl VirtualDevices { for i in 0..13 { axis_capabilities.insert(evdev::RelativeAxisType(i)); } + let mut tablet_abs_capabilities: Vec = Vec::new(); + if let Ok(absinfo) = device.get_abs_state() { + for (axis_type, info) in absinfo.iter().enumerate() { + if [0, 1, 2, 5, 6, 8, 24, 25, 26, 27].contains(&axis_type) { + let new_absinfo = evdev::AbsInfo::new( + info.value, + info.minimum, + info.maximum, + info.fuzz, + info.flat, + info.resolution + ); + tablet_abs_capabilities.push( + evdev::UinputAbsSetup::new( + evdev::AbsoluteAxisType(axis_type.try_into().unwrap()), + new_absinfo + ) + ) + } + } + } + let mut tablet_capabilities = evdev::AttributeSet::new(); + for i in 272..277 { + tablet_capabilities.insert(evdev::Key(i)); + } + for i in 320..325 { + tablet_capabilities.insert(evdev::Key(i)); + } + for i in 326..328 { + tablet_capabilities.insert(evdev::Key(i)); + } + for i in 330..333 { + tablet_capabilities.insert(evdev::Key(i)); + } + let mut tab_rel = evdev::AttributeSet::new(); + tab_rel.insert(evdev::RelativeAxisType(8)); + let mut tab_msc = evdev::AttributeSet::new(); + tab_msc.insert(evdev::MiscType(0)); + let mut pointer_prop = evdev::AttributeSet::new(); + pointer_prop.insert(evdev::PropType::POINTER); let keys_builder = VirtualDeviceBuilder::new() .expect("Unable to create virtual device through uinput. Take a look at the Troubleshooting section for more info.") .name("Makima Virtual Keyboard/Mouse") @@ -26,11 +67,24 @@ impl VirtualDevices { .expect("Unable to create virtual device through uinput. Take a look at the Troubleshooting section for more info.") .name("Makima Virtual Pointer") .with_relative_axes(&axis_capabilities).unwrap(); + let mut abs_builder = VirtualDeviceBuilder::new() + .expect("Unable to create virtual device through uinput. Take a look at the Troubleshooting section for more info.") + .name("Makima Virtual Pen/Tablet") + .with_properties(&pointer_prop).unwrap() + .with_msc(&tab_msc).unwrap() + .with_relative_axes(&tab_rel).unwrap() + .with_keys(&tablet_capabilities).unwrap() + .input_id(device.input_id()); + for abs_setup in tablet_abs_capabilities { + abs_builder = abs_builder.with_absolute_axis(&abs_setup).unwrap(); + }; let virtual_device_keys = keys_builder.build().unwrap(); let virtual_device_axis = axis_builder.build().unwrap(); + let virtual_device_abs = abs_builder.build().unwrap(); Self { keys: virtual_device_keys, axis: virtual_device_axis, + abs: virtual_device_abs, } } }