Inject tablet/pen events into a dedicated uinput device

This commit is contained in:
cyber-sushi 2024-11-02 19:43:01 +01:00
parent dfd1e88543
commit 2a342ee056
3 changed files with 143 additions and 33 deletions

View file

@ -52,6 +52,7 @@ pub struct EventReader {
impl EventReader { impl EventReader {
pub fn new( pub fn new(
config: Vec<Config>, config: Vec<Config>,
virt_dev: Arc<Mutex<VirtualDevices>>,
stream: Arc<Mutex<EventStream>>, stream: Arc<Mutex<EventStream>>,
modifiers: Arc<Mutex<Vec<Event>>>, modifiers: Arc<Mutex<Vec<Event>>>,
modifier_was_activated: Arc<Mutex<bool>>, modifier_was_activated: Arc<Mutex<bool>>,
@ -72,7 +73,6 @@ impl EventReader {
.unwrap() .unwrap()
.clone(), .clone(),
)); ));
let virt_dev = Arc::new(Mutex::new(VirtualDevices::new()));
let lstick_function = config let lstick_function = config
.iter() .iter()
.find(|&x| x.associations == Associations::default()) .find(|&x| x.associations == Associations::default())
@ -264,6 +264,11 @@ impl EventReader {
) = ((0, 0), (0, 0), (0, 0), (0, 0), 0); ) = ((0, 0), (0, 0), (0, 0), (0, 0), 0);
let switcher: Key = self.settings.layout_switcher; let switcher: Key = self.settings.layout_switcher;
let mut stream = self.stream.lock().await; let mut stream = self.stream.lock().await;
let mut pen_events: Vec<InputEvent> = 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; let mut max_abs_wheel = 0;
if let Ok(abs_state) = stream.device().get_abs_state() { if let Ok(abs_state) = stream.device().get_abs_state() {
for state in abs_state { for state in abs_state {
@ -277,9 +282,18 @@ impl EventReader {
event.event_type(), event.event_type(),
RelativeAxisType(event.code()), RelativeAxisType(event.code()),
AbsoluteAxisType(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_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 => { key if key == switcher && event.value() == 1 => {
self.change_active_layout().await self.change_active_layout().await
} }
@ -297,6 +311,7 @@ impl EventReader {
EventType::RELATIVE, EventType::RELATIVE,
RelativeAxisType::REL_WHEEL | RelativeAxisType::REL_WHEEL_HI_RES, RelativeAxisType::REL_WHEEL | RelativeAxisType::REL_WHEEL_HI_RES,
_, _,
_,
) => match event.value() { ) => match event.value() {
-1 => { -1 => {
self.convert_event(event, Event::Axis(Axis::SCROLL_WHEEL_DOWN), 1, true) 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() { match event.value() {
-1 => { -1 => {
self.convert_event(event, Event::Axis(Axis::BTN_DPAD_LEFT), 1, false) 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() { match event.value() {
-1 => { -1 => {
self.convert_event(event, Event::Axis(Axis::BTN_DPAD_UP), 1, false) 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() { match self.settings.lstick.function.as_str() {
"cursor" | "scroll" => { "cursor" | "scroll" => {
let axis_value = self 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() { match self.settings.rstick.function.as_str() {
"cursor" | "scroll" => { "cursor" | "scroll" => {
let axis_value = self 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) { match (event.value(), triggers_values.0) {
(0, 1) => { (0, 1) => {
self.convert_event(event, Event::Axis(Axis::BTN_TL2), 0, false) 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) { match (event.value(), triggers_values.1) {
(0, 1) => { (0, 1) => {
self.convert_event(event, Event::Axis(Axis::BTN_TR2), 0, false) self.convert_event(event, Event::Axis(Axis::BTN_TR2), 0, false)
@ -674,30 +727,15 @@ impl EventReader {
_ => {} _ => {}
} }
} }
(EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_WHEEL) => { (EventType::MISC, _, _, true) => {
let value = event.value(); if !stream.device().properties().contains(evdev::PropType::POINTER) {
if value != 0 && abs_wheel_position != 0 { self.emit_default_event(event).await;
let gap = value - abs_wheel_position; } else if evdev::MiscType(event.code()) == evdev::MiscType::MSC_SERIAL {
if gap < -max_abs_wheel / 2 { pen_events.push(event);
self.convert_event(event, Event::Axis(Axis::ABS_WHEEL_CW), 1, true) let mut virt_dev = self.virt_dev.lock().await;
.await; virt_dev.abs.emit(&pen_events).unwrap();
} else if gap > max_abs_wheel / 2 { pen_events.clear()
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) => {
if event.value() == 0 {
abs_wheel_position = 0
};
} }
_ => self.emit_default_event(event).await, _ => self.emit_default_event(event).await,
} }
@ -877,6 +915,13 @@ impl EventReader {
EventType::RELATIVE => { EventType::RELATIVE => {
virt_dev.axis.emit(&[default_event]).unwrap(); 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; let mut virt_dev = self.virt_dev.lock().await;
virt_dev.axis.emit(&[event]).unwrap(); 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();
}
_ => {} _ => {}
} }
} }

View file

@ -1,6 +1,7 @@
use crate::config::{Associations, Event}; use crate::config::{Associations, Event};
use crate::event_reader::EventReader; use crate::event_reader::EventReader;
use crate::Config; use crate::Config;
use crate::virtual_devices::VirtualDevices;
use evdev::{Device, EventStream}; use evdev::{Device, EventStream};
use std::{env, path::Path, process::Command, sync::Arc}; use std::{env, path::Path, process::Command, sync::Arc};
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -138,8 +139,10 @@ pub fn launch_tasks(
Path::new(&event_device), Path::new(&event_device),
config_list.clone(), config_list.clone(),
))); )));
let virt_dev = Arc::new(Mutex::new(VirtualDevices::new(device.1)));
let reader = EventReader::new( let reader = EventReader::new(
config_list.clone(), config_list.clone(),
virt_dev,
stream, stream,
modifiers.clone(), modifiers.clone(),
modifier_was_activated.clone(), modifier_was_activated.clone(),
@ -213,7 +216,7 @@ fn set_environment() -> Environment {
} }
(Ok(session), Ok(desktop)) if session == wayland => { (Ok(session), Ok(desktop)) if session == wayland => {
println!("Warning: unsupported compositor: {}, won't be able to change bindings according to the active window.\n\ 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 Server::Unsupported
} }
(Ok(session), _) if session == x11 => { (Ok(session), _) if session == x11 => {

View file

@ -6,10 +6,11 @@ use evdev::{
pub struct VirtualDevices { pub struct VirtualDevices {
pub keys: VirtualDevice, pub keys: VirtualDevice,
pub axis: VirtualDevice, pub axis: VirtualDevice,
pub abs: VirtualDevice,
} }
impl VirtualDevices { impl VirtualDevices {
pub fn new() -> Self { pub fn new(device: evdev::Device) -> Self {
let mut key_capabilities = evdev::AttributeSet::new(); let mut key_capabilities = evdev::AttributeSet::new();
for i in 1..334 { for i in 1..334 {
key_capabilities.insert(Key(i)); key_capabilities.insert(Key(i));
@ -18,6 +19,46 @@ impl VirtualDevices {
for i in 0..13 { for i in 0..13 {
axis_capabilities.insert(evdev::RelativeAxisType(i)); axis_capabilities.insert(evdev::RelativeAxisType(i));
} }
let mut tablet_abs_capabilities: Vec<evdev::UinputAbsSetup> = 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() let keys_builder = VirtualDeviceBuilder::new()
.expect("Unable to create virtual device through uinput. Take a look at the Troubleshooting section for more info.") .expect("Unable to create virtual device through uinput. Take a look at the Troubleshooting section for more info.")
.name("Makima Virtual Keyboard/Mouse") .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.") .expect("Unable to create virtual device through uinput. Take a look at the Troubleshooting section for more info.")
.name("Makima Virtual Pointer") .name("Makima Virtual Pointer")
.with_relative_axes(&axis_capabilities).unwrap(); .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_keys = keys_builder.build().unwrap();
let virtual_device_axis = axis_builder.build().unwrap(); let virtual_device_axis = axis_builder.build().unwrap();
let virtual_device_abs = abs_builder.build().unwrap();
Self { Self {
keys: virtual_device_keys, keys: virtual_device_keys,
axis: virtual_device_axis, axis: virtual_device_axis,
abs: virtual_device_abs,
} }
} }
} }