Added support for tablet wheel and layout switching

This commit is contained in:
cyber-sushi 2024-05-29 06:06:52 +02:00
parent 7c3da30404
commit 955eac92e9

View file

@ -1,13 +1,13 @@
use std::{collections::HashMap, sync::Arc, option::Option, process::{Command, Stdio}};
use std::{sync::Arc, option::Option, str::FromStr, process::{Command, Stdio}};
use tokio::sync::Mutex;
use tokio_stream::StreamExt;
use fork::{fork, Fork, setsid};
use evdev::{EventStream, Key, RelativeAxisType, AbsoluteAxisType, EventType, InputEvent};
use crate::virtual_devices::VirtualDevices;
use crate::Config;
use crate::config::{Event, Axis, parse_modifiers};
use crate::config::{Event, Axis, Associations, parse_modifiers};
use crate::active_client::*;
use crate::udev_monitor::{Environment, Client};
use crate::udev_monitor::Environment;
struct Stick {
function: String,
@ -23,10 +23,12 @@ struct Settings {
invert_scroll_axis: bool,
axis_16_bit: bool,
chain_only: bool,
layout_switcher: Key,
notify_layout_switch: bool,
}
pub struct EventReader {
config: HashMap<Client, Config>,
config: Vec<Config>,
stream: Arc<Mutex<EventStream>>,
virt_dev: Arc<Mutex<VirtualDevices>>,
lstick_position: Arc<Mutex<Vec<i32>>>,
@ -34,13 +36,14 @@ pub struct EventReader {
modifiers: Arc<Mutex<Vec<Event>>>,
modifier_was_activated: Arc<Mutex<bool>>,
device_is_connected: Arc<Mutex<bool>>,
active_layout: Arc<Mutex<u16>>,
environment: Environment,
settings: Settings,
}
impl EventReader {
pub fn new (
config: HashMap<Client, Config>,
config: Vec<Config>,
stream: Arc<Mutex<EventStream>>,
modifiers: Arc<Mutex<Vec<Event>>>,
modifier_was_activated: Arc<Mutex<bool>>,
@ -51,14 +54,15 @@ impl EventReader {
let lstick_position = Arc::new(Mutex::new(position_vector.clone()));
let rstick_position = Arc::new(Mutex::new(position_vector.clone()));
let device_is_connected: Arc<Mutex<bool>> = Arc::new(Mutex::new(true));
let active_layout: Arc<Mutex<u16>> = Arc::new(Mutex::new(0));
let virt_dev = Arc::new(Mutex::new(VirtualDevices::new()));
let lstick_function = config.get(&Client::Default).unwrap()
let lstick_function = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("LSTICK").unwrap_or(&"cursor".to_string()).to_string();
let lstick_sensitivity: u64 = config.get(&Client::Default).unwrap()
let lstick_sensitivity: u64 = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("LSTICK_SENSITIVITY").unwrap_or(&"0".to_string()).parse::<u64>().expect("Invalid value for LSTICK_SENSITIVITY, please use an integer value >= 0");
let lstick_deadzone: i32 = config.get(&Client::Default).unwrap()
let lstick_deadzone: i32 = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("LSTICK_DEADZONE").unwrap_or(&"5".to_string()).parse::<i32>().expect("Invalid value for LSTICK_DEADZONE, please use an integer between 0 and 128.");
let lstick_activation_modifiers: Vec<Event> = parse_modifiers(&config.get(&Client::Default).unwrap().settings, "LSTICK_ACTIVATION_MODIFIERS");
let lstick_activation_modifiers: Vec<Event> = parse_modifiers(&config.iter().find(|&x| x.associations == Associations::default()).unwrap().settings, "LSTICK_ACTIVATION_MODIFIERS");
let lstick = Stick {
function: lstick_function,
sensitivity: lstick_sensitivity,
@ -66,13 +70,13 @@ impl EventReader {
activation_modifiers: lstick_activation_modifiers,
};
let rstick_function: String = config.get(&Client::Default).unwrap()
let rstick_function: String = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("RSTICK").unwrap_or(&"scroll".to_string()).to_string();
let rstick_sensitivity: u64 = config.get(&Client::Default).unwrap()
let rstick_sensitivity: u64 = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("RSTICK_SENSITIVITY").unwrap_or(&"0".to_string()).parse::<u64>().expect("Invalid value for RSTICK_SENSITIVITY, please use an integer value >= 0");
let rstick_deadzone: i32 = config.get(&Client::Default).unwrap()
let rstick_deadzone: i32 = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("RSTICK_DEADZONE").unwrap_or(&"5".to_string()).parse::<i32>().expect("Invalid value for RSTICK_DEADZONE, please use an integer between 0 and 128.");
let rstick_activation_modifiers: Vec<Event> = parse_modifiers(&config.get(&Client::Default).unwrap().settings, "RSTICK_ACTIVATION_MODIFIERS");
let rstick_activation_modifiers: Vec<Event> = parse_modifiers(&config.iter().find(|&x| x.associations == Associations::default()).unwrap().settings, "RSTICK_ACTIVATION_MODIFIERS");
let rstick = Stick {
function: rstick_function,
sensitivity: rstick_sensitivity,
@ -80,18 +84,24 @@ impl EventReader {
activation_modifiers: rstick_activation_modifiers,
};
let axis_16_bit: bool = config.get(&Client::Default).unwrap()
let axis_16_bit: bool = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("16_BIT_AXIS").unwrap_or(&"false".to_string()).parse().expect("16_BIT_AXIS can only be true or false.");
let chain_only: bool = config.get(&Client::Default).unwrap()
let chain_only: bool = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("CHAIN_ONLY").unwrap_or(&"true".to_string()).parse().expect("CHAIN_ONLY can only be true or false.");
let invert_cursor_axis: bool = config.get(&Client::Default).unwrap()
let invert_cursor_axis: bool = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("INVERT_CURSOR_AXIS").unwrap_or(&"false".to_string()).parse().expect("INVERT_CURSOR_AXIS can only be true or false.");
let invert_scroll_axis: bool = config.get(&Client::Default).unwrap()
let invert_scroll_axis: bool = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("INVERT_SCROLL_AXIS").unwrap_or(&"false".to_string()).parse().expect("INVERT_SCROLL_AXIS can only be true or false.");
let layout_switcher: Key = Key::from_str(config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("LAYOUT_SWITCHER").unwrap_or(&"BTN_0".to_string())).expect("LAYOUT_SWITCHER is not a valid Key.");
let notify_layout_switch: bool = config.iter().find(|&x| x.associations == Associations::default()).unwrap()
.settings.get("NOTIFY_LAYOUT_SWITCH").unwrap_or(&"false".to_string()).parse().expect("NOTIFY_LAYOUT_SWITCH can only be true or false.");
let settings = Settings {
lstick,
rstick,
@ -99,6 +109,8 @@ impl EventReader {
invert_scroll_axis,
axis_16_bit,
chain_only,
layout_switcher,
notify_layout_switch,
};
Self {
config,
@ -109,13 +121,14 @@ impl EventReader {
modifiers,
modifier_was_activated,
device_is_connected,
active_layout,
environment,
settings,
}
}
pub async fn start(&self) {
println!("{:?} detected, reading events.\n", self.config.get(&get_active_window(&self.environment.server, &self.config).await).unwrap().name);
println!("{:?} detected, reading events.\n", self.config.iter().find(|&x| x.associations == Associations::default()).unwrap().name);
tokio::join!(
self.event_loop(),
self.cursor_loop(),
@ -125,6 +138,7 @@ impl EventReader {
pub async fn event_loop(&self) {
let (mut dpad_values, mut lstick_values, mut rstick_values, mut triggers_values, mut abs_wheel_position) = ((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 max_abs_wheel = 0;
if let Ok(abs_state) = stream.device().get_abs_state() {
@ -137,8 +151,9 @@ impl EventReader {
while let Some(Ok(event)) = stream.next().await {
match (event.event_type(), RelativeAxisType(event.code()), AbsoluteAxisType(event.code())) {
(EventType::KEY, _, _) => {
match event.code() {
312 | 313 => {},
match Key(event.code()) {
Key::BTN_TL2 | Key::BTN_TR2 => {},
key if key == switcher && event.value() == 1 => { self.change_active_layout().await },
_ => self.convert_event(event, Event::Key(Key(event.code())), event.value(), false).await,
}
},
@ -368,13 +383,14 @@ impl EventReader {
}
let mut device_is_connected = self.device_is_connected.lock().await;
*device_is_connected = false;
println!("Disconnected device \"{}\".\n", self.config.get(&get_active_window(&self.environment.server, &self.config).await).unwrap().name);
println!("Disconnected device \"{}\".\n", self.get_config().await.name);
}
async fn convert_event(&self, default_event: InputEvent, event: Event, value: i32, send_zero: bool) {
let path = self.config.get(&get_active_window(&self.environment.server, &self.config).await).unwrap();
let config = self.get_config().await;
let modifiers = self.modifiers.lock().await.clone();
if let Some(map) = path.bindings.remap.get(&event) {
if let Some(map) = config.bindings.remap.get(&event) {
if let Some(event_list) = map.get(&modifiers) {
self.emit_event(event_list, value, &modifiers, modifiers.is_empty(), !modifiers.is_empty(), send_zero).await;
return
@ -385,7 +401,7 @@ impl EventReader {
return
}
}
if let Some(map) = path.bindings.commands.get(&event) {
if let Some(map) = config.bindings.commands.get(&event) {
if let Some(command_list) = map.get(&modifiers) {
if value == 1 { self.spawn_subprocess(command_list).await };
return
@ -396,7 +412,7 @@ impl EventReader {
return
}
}
if let Some(map) = path.bindings.commands.get(&event) {
if let Some(map) = config.bindings.commands.get(&event) {
if let Some(command_list) = map.get(&modifiers) {
if value == 1 { self.spawn_subprocess(command_list).await };
return
@ -406,7 +422,7 @@ impl EventReader {
}
async fn emit_event(&self, event_list: &Vec<Key>, value: i32, modifiers: &Vec<Event>, release_keys: bool, ignore_modifiers: bool, send_zero: bool) {
let path = self.config.get(&get_active_window(&self.environment.server, &self.config).await).unwrap();
let config = self.get_config().await;
let mut virt_dev = self.virt_dev.lock().await;
let mut modifier_was_activated = self.modifier_was_activated.lock().await;
if release_keys {
@ -425,11 +441,10 @@ impl EventReader {
}
}
for key in event_list {
println!("{:?}", key);
if release_keys {
self.toggle_modifiers(Event::Key(*key), value).await;
}
if path.mapped_modifiers.custom.contains(&Event::Key(*key)) {
if config.mapped_modifiers.custom.contains(&Event::Key(*key)) {
if value == 0 && !*modifier_was_activated {
let virtual_event: InputEvent = InputEvent::new_now(EventType::KEY, key.code(), 1);
virt_dev.keys.emit(&[virtual_event]).unwrap();
@ -452,7 +467,7 @@ impl EventReader {
}
async fn emit_nonmapped_event(&self, default_event: InputEvent, event: Event, value: i32, modifiers: &Vec<Event>) {
let path = self.config.get(&get_active_window(&self.environment.server, &self.config).await).unwrap();
let config = self.get_config().await;
let mut virt_dev = self.virt_dev.lock().await;
let mut modifier_was_activated = self.modifier_was_activated.lock().await;
let released_keys: Vec<Key> = self.released_keys(&modifiers).await;
@ -462,7 +477,7 @@ impl EventReader {
virt_dev.keys.emit(&[virtual_event]).unwrap()
}
self.toggle_modifiers(event, value).await;
if path.mapped_modifiers.custom.contains(&event) {
if config.mapped_modifiers.custom.contains(&event) {
if value == 0 && !*modifier_was_activated {
let virtual_event: InputEvent = InputEvent::new_now(default_event.event_type(), default_event.code(), 1);
virt_dev.keys.emit(&[virtual_event]).unwrap();
@ -521,9 +536,8 @@ impl EventReader {
match fork() {
Ok(Fork::Child) => {
setsid().unwrap();
Command::new("sh")
.arg("-c")
.arg(format!("runuser {} -c '{}'", user, command))
Command::new("runuser")
.args([user, "-c", command])
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
@ -565,9 +579,9 @@ impl EventReader {
}
async fn toggle_modifiers(&self, modifier: Event, value: i32) {
let path = self.config.get(&get_active_window(&self.environment.server, &self.config).await).unwrap();
let config = self.get_config().await;
let mut modifiers = self.modifiers.lock().await;
if path.mapped_modifiers.all.contains(&modifier) {
if config.mapped_modifiers.all.contains(&modifier) {
match value {
1 => {
modifiers.push(modifier);
@ -581,9 +595,9 @@ impl EventReader {
}
async fn released_keys(&self, modifiers: &Vec<Event>) -> Vec<Key> {
let path = self.config.get(&get_active_window(&self.environment.server, &self.config).await).unwrap();
let config = self.get_config().await;
let mut released_keys: Vec<Key> = Vec::new();
for (_key, hashmap) in path.bindings.remap.iter() {
for (_key, hashmap) in config.bindings.remap.iter() {
if let Some(event_list) = hashmap.get(modifiers) {
released_keys.extend(event_list);
}
@ -591,6 +605,33 @@ impl EventReader {
released_keys
}
async fn change_active_layout(&self) {
let mut active_layout = self.active_layout.lock().await;
loop {
if *active_layout == 3 { *active_layout = 0 }
else { *active_layout += 1 };
if let Some(_) = self.config.iter().find(|&x| x.associations.layout == *active_layout) {
break
};
}
if self.settings.notify_layout_switch {
let notify = vec![String::from(format!("notify-send -t 500 'Makima' 'Switching to layout {}'", *active_layout))];
self.spawn_subprocess(&notify).await;
}
}
async fn get_config(&self) -> &Config {
let active_layout = self.active_layout.lock().await;
let active_window = get_active_window(&self.environment.server, &self.config).await;
let associations = Associations {
client: active_window,
layout: *active_layout,
};
let config = self.config.iter()
.find(|&x| x.associations == associations).unwrap();
config
}
pub async fn cursor_loop(&self) {
let (cursor, sensitivity, activation_modifiers) = if self.settings.lstick.function.as_str() == "cursor" {
("left", self.settings.lstick.sensitivity, self.settings.lstick.activation_modifiers.clone())