From b83212549163283b40812b7c06a947f68ec8b628 Mon Sep 17 00:00:00 2001 From: cyber-sushi Date: Wed, 27 Mar 2024 05:32:22 +0100 Subject: [PATCH] Added 2D scrolling through analog stick --- Cargo.lock | 2 +- Cargo.toml | 2 +- README.md | 14 +++-- examples/config-playstation.toml | 6 +- examples/config-ps2.toml | 6 +- examples/config-stadia.toml | 6 +- examples/config-switch.toml | 6 +- examples/config-xbox.toml | 7 ++- src/event_reader.rs | 96 ++++++++++++++++++++++---------- 9 files changed, 99 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a29a870..f64c41c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -583,7 +583,7 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "makima" -version = "0.4.0" +version = "0.4.2" dependencies = [ "evdev", "home", diff --git a/Cargo.toml b/Cargo.toml index 29c8e46..de1091e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "makima" -version = "0.4.0" +version = "0.4.2" edition = "2021" [dependencies] diff --git a/README.md b/README.md index 9f3d30e..39c960f 100644 --- a/README.md +++ b/README.md @@ -111,10 +111,12 @@ Events that are not explicitly remapped will keep their default functionality.\ If you don't need to remap any axis event, you can just omit the entire `[bindings.axis]` and `[combinations.axis]` paragraphs. ### \[settings] -There are currently 4 available settings: +There are currently 6 available settings: - `GRAB_DEVICE` will set if Makima should have exclusivity over the device. If set to `"true"`, no other program will read the original input of the device. If set to `"false"`, both the original input and the remapped input will be read by applications. The event reader won't start if this is not set. -- `MOVE_MOUSE_WITH_STICK` will set if your mouse cursor should be moved using your controller's analog sticks, and which of the two sticks should move your cursor. Can be set to `"left"`, `"right"` or `"none"`. Defaults to `"left"` if not set. -- `ANALOG_SENSITIVITY` will change the speed of your mouse cursor when moved through an analog stick. Lower value is higher sensitivity, minimum `"1"`, suggested `"6"`. The analog stick won't be read if this is not set. +- `CURSOR_STICK` will set if your mouse cursor should be moved using your controller's analog sticks, and which of the two sticks should move your cursor. Can be set to `"left"`, `"right"` or `"none"`. Defaults to `"left"` if not set. +- `SCROLL_STICK` will set if 2D scrolling using your controller's analog sticks should be anabled, and which of the two sticks should move your cursor. Can be set to `"left"`, `"right"` or `"none"`. Defaults to `"left"` if not set. If both `CURSOR_STICK` and `SCROLL_STICK` are set to the same value, `CURSOR_STICK` will have priority. +- `CURSOR_SENSITIVITY` will change the speed of your mouse cursor when it's being moved with an analog stick. Lower value is higher sensitivity, minimum `"1"`, suggested `"6"`. If this isn't set, cursor movement will be disabled. +- `SCROLL_SENSITIVITY` will change the scroll speed when scrolling with an analog stick. Lower value is higher sensitivity, minimum `"1"`, suggested `"6"`. If this isn't set, scrolling will be disabled. - `SIGNED_AXIS_VALUE` is needed if you're using Xbox controllers and Switch Joy-Cons to properly calibrate the analog stick's sensitivity. Set to `"true"` if you're using those controllers. Can be left out otherwise. Example settings for a keyboard or mouse, notice that only the `GRAB_DEVICE` setting is needed in this case and you can leave everything else out: @@ -125,8 +127,10 @@ GRAB_DEVICE = "true" Example settings for a an Xbox 360/One controller: ``` [settings] -ANALOG_SENSITIVITY = "6" -MOVE_MOUSE_WITH_STICK = "left" +CURSOR_SENSITIVITY = "6" +SCROLL_SENSITIVITY = "6" +CURSOR_STICK = "left" +SCROLL_STICK = "right" GRAB_DEVICE = "false" SIGNED_AXIS_VALUE = "true" ``` diff --git a/examples/config-playstation.toml b/examples/config-playstation.toml index 6655098..7fec42f 100644 --- a/examples/config-playstation.toml +++ b/examples/config-playstation.toml @@ -27,6 +27,8 @@ BTN_DPAD_DOWN = ["KEY_DOWN"] #directional pad down BTN_DPAD_LEFT = ["KEY_LEFT"] #directional pad left [settings] -ANALOG_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 -MOVE_MOUSE_WITH_STICK = "left" #left, right or none +CURSOR_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +SCROLL_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +CURSOR_STICK = "left" #left, right or none +SCROLL_STICK = "right" #left, right or none GRAB_DEVICE = "false" #gain exclusivity on the device diff --git a/examples/config-ps2.toml b/examples/config-ps2.toml index d369613..4c1480d 100644 --- a/examples/config-ps2.toml +++ b/examples/config-ps2.toml @@ -26,6 +26,8 @@ BTN_DPAD_DOWN = ["KEY_DOWN"] #directional pad down BTN_DPAD_LEFT = ["KEY_LEFT"] #directional pad left [settings] -ANALOG_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 -MOVE_MOUSE_WITH_STICK = "left" #left, right or none +CURSOR_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +SCROLL_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +CURSOR_STICK = "left" #left, right or none +SCROLL_STICK = "right" #left, right or none GRAB_DEVICE = "false" #gain exclusivity on the device diff --git a/examples/config-stadia.toml b/examples/config-stadia.toml index 4cd5f84..9ba05c3 100644 --- a/examples/config-stadia.toml +++ b/examples/config-stadia.toml @@ -29,6 +29,8 @@ BTN_DPAD_DOWN = ["KEY_DOWN"] #directional pad down BTN_DPAD_LEFT = ["KEY_LEFT"] #directional pad left [settings] -ANALOG_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 -MOVE_MOUSE_WITH_STICK = "left" #left, right or none +CURSOR_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +SCROLL_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +CURSOR_STICK = "left" #left, right or none +SCROLL_STICK = "right" #left, right or none GRAB_DEVICE = "false" #gain exclusivity on the device diff --git a/examples/config-switch.toml b/examples/config-switch.toml index dcda889..a49fcff 100644 --- a/examples/config-switch.toml +++ b/examples/config-switch.toml @@ -28,7 +28,9 @@ BTN_DPAD_DOWN = ["KEY_DOWN"] #directional pad down BTN_DPAD_LEFT = ["KEY_LEFT"] #directional pad left [settings] -ANALOG_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 -MOVE_MOUSE_WITH_STICK = "left" #left, right or none +CURSOR_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +SCROLL_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +CURSOR_STICK = "left" #left, right or none +SCROLL_STICK = "right" #left, right or none GRAB_DEVICE = "false" #gain exclusivity on the device SIGNED_AXIS_VALUE = "true" #necessary for Xbox controllers and Switch joycons, use false for other controllers diff --git a/examples/config-xbox.toml b/examples/config-xbox.toml index cfb21b7..3af4b47 100644 --- a/examples/config-xbox.toml +++ b/examples/config-xbox.toml @@ -27,7 +27,8 @@ BTN_DPAD_DOWN = ["KEY_DOWN"] #directional pad down BTN_DPAD_LEFT = ["KEY_LEFT"] #directional pad left [settings] -ANALOG_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 -MOVE_MOUSE_WITH_STICK = "left" #left, right or none -GRAB_DEVICE = "false" #gain exclusivity on the device +CURSOR_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +SCROLL_SENSITIVITY = "6" #lower value is higher sensitivity, minimum 1 +CURSOR_STICK = "left" #left, right or none +SCROLL_STICK = "right" #left, right or none SIGNED_AXIS_VALUE = "true" #necessary for Xbox controllers and Switch joycons, use false for other controllers diff --git a/src/event_reader.rs b/src/event_reader.rs index 764b6b3..06920a2 100644 --- a/src/event_reader.rs +++ b/src/event_reader.rs @@ -11,7 +11,8 @@ pub struct EventReader { config: HashMap, stream: Arc>, virt_dev: Arc>, - analog_position: Arc>>, + cursor_analog_position: Arc>>, + scroll_analog_position: Arc>>, modifiers: Arc>>, device_is_connected: Arc>, current_desktop: Option, @@ -26,14 +27,16 @@ impl EventReader { ) -> Self { let mut position_vector: Vec = Vec::new(); for i in [0, 0] {position_vector.push(i)}; - let position_vector_mutex = Arc::new(Mutex::new(position_vector)); + let cursor_position_vector_mutex = Arc::new(Mutex::new(position_vector.clone())); + let scroll_position_vector_mutex = Arc::new(Mutex::new(position_vector.clone())); let device_is_connected: Arc> = Arc::new(Mutex::new(true)); let virt_dev = Arc::new(Mutex::new(VirtualDevices::new())); Self { config: config, stream: stream, virt_dev: virt_dev, - analog_position: position_vector_mutex, + cursor_analog_position: cursor_position_vector_mutex, + scroll_analog_position: scroll_position_vector_mutex, modifiers: modifiers, device_is_connected: device_is_connected, current_desktop: current_desktop, @@ -45,25 +48,30 @@ impl EventReader { tokio::join!( self.event_loop(), self.cursor_loop(), + self.scroll_loop(), ); } pub async fn event_loop(&self) { let mut stream = self.stream.lock().await; - let mut analog_mode: &str = "left"; - if let Some(stick) = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap().settings.get("POINTER_STICK") { - analog_mode = stick.as_str(); + let mut cursor_analog_mode: &str = "left"; + if let Some(stick) = self.config.get(&"default".to_string()).unwrap().settings.get("CURSOR_STICK") { + cursor_analog_mode = stick.as_str(); + } + let mut scroll_analog_mode: &str = "right"; + if let Some(stick) = self.config.get(&"default".to_string()).unwrap().settings.get("SCROLL_STICK") { + scroll_analog_mode = stick.as_str(); } let mut has_signed_axis_value: &str = "false"; - if let Some(axis_value) = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap().settings.get("SIGNED_AXIS_VALUE") { + if let Some(axis_value) = self.config.get(&"default".to_string()).unwrap().settings.get("SIGNED_AXIS_VALUE") { has_signed_axis_value = axis_value.as_str(); } while let Some(Ok(event)) = stream.next().await { - match (event.event_type(), RelativeAxisType(event.code()), AbsoluteAxisType(event.code()), analog_mode) { - (EventType::KEY, _, _, _) => { + match (event.event_type(), RelativeAxisType(event.code()), AbsoluteAxisType(event.code())) { + (EventType::KEY, _, _) => { self.convert_key_events(event).await; }, - (_, RelativeAxisType::REL_WHEEL | RelativeAxisType::REL_WHEEL_HI_RES, _, _) => { + (_, RelativeAxisType::REL_WHEEL | RelativeAxisType::REL_WHEEL_HI_RES, _) => { let event_string_option: Option = match event.value() { -1 => Option::Some("SCROLL_WHEEL_DOWN".to_string()), 1 => Option::Some("SCROLL_WHEEL_UP".to_string()), @@ -75,7 +83,7 @@ impl EventReader { self.emit_default_event(event).await; } }, - (_, _, AbsoluteAxisType::ABS_HAT0X, _) => { + (_, _, AbsoluteAxisType::ABS_HAT0X) => { let event_string: String = match event.value() { -1 => "BTN_DPAD_LEFT".to_string(), 0 => "NONE_X".to_string(), @@ -84,7 +92,7 @@ impl EventReader { }; self.convert_axis_events(event, &event_string, false, false).await; }, - (_, _, AbsoluteAxisType::ABS_HAT0Y, _) => { + (_, _, AbsoluteAxisType::ABS_HAT0Y) => { let event_string: String = match event.value() { -1 => "BTN_DPAD_UP".to_string(), 0 => "NONE_Y".to_string(), @@ -93,20 +101,32 @@ impl EventReader { }; self.convert_axis_events(event, &event_string, false, false).await; }, - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_X | AbsoluteAxisType::ABS_Y, "left") => { - let axis_value = self.get_axis_value(&has_signed_axis_value, &event).await; - let mut analog_position = self.analog_position.lock().await; - analog_position[event.code() as usize] = axis_value; + (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_X | AbsoluteAxisType::ABS_Y) => { + if cursor_analog_mode == "left" { + let axis_value = self.get_axis_value(&has_signed_axis_value, &event).await; + let mut cursor_analog_position = self.cursor_analog_position.lock().await; + cursor_analog_position[event.code() as usize] = axis_value; + } else if scroll_analog_mode == "left" { + let axis_value = self.get_axis_value(&has_signed_axis_value, &event).await; + let mut scroll_analog_position = self.scroll_analog_position.lock().await; + scroll_analog_position[event.code() as usize] = axis_value; + } }, - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RX | AbsoluteAxisType::ABS_RY, "right") => { - let axis_value = self.get_axis_value(&has_signed_axis_value, &event).await; - let mut analog_position = self.analog_position.lock().await; - analog_position[(event.code() as usize) -3] = axis_value; + (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RX | AbsoluteAxisType::ABS_RY) => { + if cursor_analog_mode == "right" { + let axis_value = self.get_axis_value(&has_signed_axis_value, &event).await; + let mut cursor_analog_position = self.cursor_analog_position.lock().await; + cursor_analog_position[event.code() as usize -3] = axis_value; + } else if scroll_analog_mode == "right" { + let axis_value = self.get_axis_value(&has_signed_axis_value, &event).await; + let mut scroll_analog_position = self.scroll_analog_position.lock().await; + scroll_analog_position[event.code() as usize -3] = axis_value; + } }, - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_Z, _) => { + (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_Z) => { self.convert_axis_events(event, &"BTN_TL2".to_string(), false, true).await; }, - (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RZ, _) => { + (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RZ) => { self.convert_axis_events(event, &"BTN_TR2".to_string(), false, true).await; }, _ => {self.emit_default_event(event).await;} @@ -247,14 +267,34 @@ impl EventReader { } pub async fn cursor_loop(&self) { - if let Some(sensitivity) = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap().settings.get("ANALOG_SENSITIVITY") { - let polling_rate: u64 = sensitivity.parse::().expect("Invalid analog sensitivity."); + if let Some(sensitivity) = self.config.get(&"default".to_string()).unwrap().settings.get("CURSOR_SENSITIVITY") { + let polling_rate: u64 = sensitivity.parse::().expect("Invalid cursor sensitivity."); while *self.device_is_connected.lock().await { { - let analog_position = self.analog_position.lock().await; - if analog_position[0] != 0 || analog_position[1] != 0 { - let virtual_event_x: InputEvent = InputEvent::new_now(EventType::RELATIVE, 0, analog_position[0]); - let virtual_event_y: InputEvent = InputEvent::new_now(EventType::RELATIVE, 1, analog_position[1]); + let cursor_analog_position = self.cursor_analog_position.lock().await; + if cursor_analog_position[0] != 0 || cursor_analog_position[1] != 0 { + let virtual_event_x: InputEvent = InputEvent::new_now(EventType::RELATIVE, 0, cursor_analog_position[0]); + let virtual_event_y: InputEvent = InputEvent::new_now(EventType::RELATIVE, 1, cursor_analog_position[1]); + let mut virt_dev = self.virt_dev.lock().await; + virt_dev.axis.emit(&[virtual_event_x]).unwrap(); + virt_dev.axis.emit(&[virtual_event_y]).unwrap(); + } + } + tokio::time::sleep(std::time::Duration::from_millis(polling_rate)).await; + } + } else { + return + } + } + pub async fn scroll_loop(&self) { + if let Some(sensitivity) = self.config.get(&"default".to_string()).unwrap().settings.get("SCROLL_SENSITIVITY") { + let polling_rate: u64 = sensitivity.parse::().expect("Invalid scroll sensitivity."); + while *self.device_is_connected.lock().await { + { + let scroll_analog_position = self.scroll_analog_position.lock().await; + if scroll_analog_position[0] != 0 || scroll_analog_position[1] != 0 { + let virtual_event_x: InputEvent = InputEvent::new_now(EventType::RELATIVE, 12, scroll_analog_position[0]); + let virtual_event_y: InputEvent = InputEvent::new_now(EventType::RELATIVE, 11, scroll_analog_position[1]); let mut virt_dev = self.virt_dev.lock().await; virt_dev.axis.emit(&[virtual_event_x]).unwrap(); virt_dev.axis.emit(&[virtual_event_y]).unwrap();