Added analog stick remapping to keys

This commit is contained in:
cyber-sushi 2024-04-10 09:37:39 +02:00
parent c83b70a91a
commit c838c55af2
2 changed files with 186 additions and 82 deletions

View file

@ -88,23 +88,45 @@ impl Config {
modifiers.axis.insert(modmap, map.clone()); modifiers.axis.insert(modmap, map.clone());
} }
let mut pad_horizontal: Vec<Key> = bindings.axis.get("BTN_DPAD_LEFT") let mut pad_x: Vec<Key> = bindings.axis.get("BTN_DPAD_LEFT")
.unwrap_or(&Vec::new()).clone(); .unwrap_or(&Vec::new()).clone();
pad_horizontal.extend(bindings.axis.get("BTN_DPAD_RIGHT") pad_x.extend(bindings.axis.get("BTN_DPAD_RIGHT")
.unwrap_or(&Vec::new())); .unwrap_or(&Vec::new()));
let mut pad_vertical: Vec<Key> = bindings.axis.get("BTN_DPAD_UP") let mut pad_y: Vec<Key> = bindings.axis.get("BTN_DPAD_UP")
.unwrap_or(&Vec::new()).clone(); .unwrap_or(&Vec::new()).clone();
pad_vertical.extend(bindings.axis.get("BTN_DPAD_DOWN") pad_y.extend(bindings.axis.get("BTN_DPAD_DOWN")
.unwrap_or(&Vec::new())); .unwrap_or(&Vec::new()));
bindings.axis.insert("NONE_X".to_string(), pad_horizontal); bindings.axis.insert("NONE_X".to_string(), pad_x);
bindings.axis.insert("NONE_Y".to_string(), pad_vertical); bindings.axis.insert("NONE_Y".to_string(), pad_y);
let mut lstick_x: Vec<Key> = bindings.axis.get("LSTICK_LEFT")
.unwrap_or(&Vec::new()).clone();
lstick_x.extend(bindings.axis.get("LSTICK_RIGHT")
.unwrap_or(&Vec::new()));
let mut lstick_y: Vec<Key> = bindings.axis.get("LSTICK_UP")
.unwrap_or(&Vec::new()).clone();
lstick_y.extend(bindings.axis.get("LSTICK_DOWN")
.unwrap_or(&Vec::new()));
bindings.axis.insert("LSTICK_X".to_string(), lstick_x);
bindings.axis.insert("LSTICK_Y".to_string(), lstick_y);
let mut rstick_x: Vec<Key> = bindings.axis.get("RSTICK_LEFT")
.unwrap_or(&Vec::new()).clone();
rstick_x.extend(bindings.axis.get("RSTICK_RIGHT")
.unwrap_or(&Vec::new()));
let mut rstick_y: Vec<Key> = bindings.axis.get("RSTICK_UP")
.unwrap_or(&Vec::new()).clone();
rstick_y.extend(bindings.axis.get("RSTICK_DOWN")
.unwrap_or(&Vec::new()));
bindings.axis.insert("RSTICK_X".to_string(), rstick_x);
bindings.axis.insert("RSTICK_Y".to_string(), rstick_y);
Self { Self {
name: file_name, name: file_name,
bindings: bindings, bindings,
combinations: combinations, combinations,
modifiers: modifiers, modifiers,
settings: settings, settings,
} }
} }
} }

View file

@ -6,21 +6,25 @@ use crate::virtual_devices::VirtualDevices;
use crate::Config; use crate::Config;
use crate::active_client::*; use crate::active_client::*;
struct Settings {
cursor_analog_mode: String, struct Stick {
scroll_analog_mode: String, function: String,
cursor_sensitivity: u64, sensitivity: u64,
scroll_sensitivity: u64,
has_signed_axis_value: bool,
deadzone: i32, deadzone: i32,
} }
struct Settings {
lstick: Stick,
rstick: Stick,
axis_16_bit: bool,
}
pub struct EventReader { pub struct EventReader {
config: HashMap<String, Config>, config: HashMap<String, Config>,
stream: Arc<Mutex<EventStream>>, stream: Arc<Mutex<EventStream>>,
virt_dev: Arc<Mutex<VirtualDevices>>, virt_dev: Arc<Mutex<VirtualDevices>>,
cursor_analog_position: Arc<Mutex<Vec<i32>>>, lstick_position: Arc<Mutex<Vec<i32>>>,
scroll_analog_position: Arc<Mutex<Vec<i32>>>, rstick_position: Arc<Mutex<Vec<i32>>>,
modifiers: Arc<Mutex<BTreeMap<Key, i32>>>, modifiers: Arc<Mutex<BTreeMap<Key, i32>>>,
device_is_connected: Arc<Mutex<bool>>, device_is_connected: Arc<Mutex<bool>>,
current_desktop: Option<String>, current_desktop: Option<String>,
@ -36,40 +40,53 @@ impl EventReader {
) -> Self { ) -> Self {
let mut position_vector: Vec<i32> = Vec::new(); let mut position_vector: Vec<i32> = Vec::new();
for i in [0, 0] {position_vector.push(i)}; for i in [0, 0] {position_vector.push(i)};
let cursor_position_vector_mutex = Arc::new(Mutex::new(position_vector.clone())); let lstick_position = Arc::new(Mutex::new(position_vector.clone()));
let scroll_position_vector_mutex = 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 device_is_connected: Arc<Mutex<bool>> = Arc::new(Mutex::new(true));
let virt_dev = Arc::new(Mutex::new(VirtualDevices::new())); let virt_dev = Arc::new(Mutex::new(VirtualDevices::new()));
let cursor_analog_mode: String = config.get(&"default".to_string()).unwrap()
.settings.get("CURSOR_STICK").unwrap_or(&"left".to_string()).to_string(); let lstick_function = config.get(&"default".to_string()).unwrap()
let scroll_analog_mode: String = config.get(&"default".to_string()).unwrap() .settings.get("LSTICK").unwrap_or(&"cursor".to_string()).to_string();
.settings.get("SCROLL_STICK").unwrap_or(&"right".to_string()).to_string(); let lstick_sensitivity: u64 = config.get(&"default".to_string()).unwrap()
let cursor_sensitivity: u64 = config.get(&"default".to_string()).unwrap() .settings.get("LSTICK_SENSITIVITY").unwrap_or(&"0".to_string()).parse::<u64>().expect("Invalid value for LSTICK_SENSITIVITY, please use an integer value >= 0");
.settings.get("CURSOR_SENSITIVITY").unwrap_or(&"0".to_string()).parse::<u64>().expect("Invalid cursor sensitivity."); let lstick_deadzone: i32 = config.get(&"default".to_string()).unwrap()
let scroll_sensitivity: u64 = config.get(&"default".to_string()).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.");
.settings.get("SCROLL_SENSITIVITY").unwrap_or(&"0".to_string()).parse::<u64>().expect("Invalid scroll sensitivity."); let lstick = Stick {
let has_signed_axis_value: bool = config.get(&"default".to_string()).unwrap() function: lstick_function,
.settings.get("SIGNED_AXIS_VALUE").unwrap_or(&"false".to_string()).parse().expect("SIGNED_AXIS_VALUE can only be true or false."); sensitivity: lstick_sensitivity,
let deadzone: i32 = config.get(&"default".to_string()).unwrap() deadzone: lstick_deadzone,
.settings.get("DEADZONE").unwrap_or(&"5".to_string()).parse::<i32>().expect("Invalid value for DEADZONE, please use an integer between 0 and 128."); };
let rstick_function: String = config.get(&"default".to_string()).unwrap()
.settings.get("RSTICK").unwrap_or(&"scroll".to_string()).to_string();
let rstick_sensitivity: u64 = config.get(&"default".to_string()).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(&"default".to_string()).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 = Stick {
function: rstick_function,
sensitivity: rstick_sensitivity,
deadzone: rstick_deadzone,
};
let axis_16_bit: bool = config.get(&"default".to_string()).unwrap()
.settings.get("16_BIT_AXIS").unwrap_or(&"false".to_string()).parse().expect("16_BIT_AXIS can only be true or false.");
let settings = Settings { let settings = Settings {
cursor_analog_mode: cursor_analog_mode, lstick,
scroll_analog_mode: scroll_analog_mode, rstick,
cursor_sensitivity: cursor_sensitivity, axis_16_bit,
scroll_sensitivity: scroll_sensitivity,
has_signed_axis_value: has_signed_axis_value,
deadzone: deadzone,
}; };
Self { Self {
config: config, config,
stream: stream, stream,
virt_dev: virt_dev, virt_dev,
cursor_analog_position: cursor_position_vector_mutex, lstick_position,
scroll_analog_position: scroll_position_vector_mutex, rstick_position,
modifiers: modifiers, modifiers,
device_is_connected: device_is_connected, device_is_connected,
current_desktop: current_desktop, current_desktop,
settings: settings, settings,
} }
} }
@ -102,41 +119,79 @@ impl EventReader {
(_, _, AbsoluteAxisType::ABS_HAT0X) => { (_, _, AbsoluteAxisType::ABS_HAT0X) => {
let event_string: String = match event.value() { let event_string: String = match event.value() {
-1 => "BTN_DPAD_LEFT".to_string(), -1 => "BTN_DPAD_LEFT".to_string(),
0 => "NONE_X".to_string(), 0 => "BTN_DPAD_X".to_string(),
1 => "BTN_DPAD_RIGHT".to_string(), 1 => "BTN_DPAD_RIGHT".to_string(),
_ => "NONE_X".to_string(), _ => "BTN_DPAD_X".to_string(),
}; };
self.convert_axis_events(event, &event_string, false, false).await; self.convert_axis_events(event, &event_string, false, false).await;
}, },
(_, _, AbsoluteAxisType::ABS_HAT0Y) => { (_, _, AbsoluteAxisType::ABS_HAT0Y) => {
let event_string: String = match event.value() { let event_string: String = match event.value() {
-1 => "BTN_DPAD_UP".to_string(), -1 => "BTN_DPAD_UP".to_string(),
0 => "NONE_Y".to_string(), 0 => "BTN_DPAD_Y".to_string(),
1 => "BTN_DPAD_DOWN".to_string(), 1 => "BTN_DPAD_DOWN".to_string(),
_ => "NONE_Y".to_string(), _ => "BTN_DPAD_Y".to_string(),
}; };
self.convert_axis_events(event, &event_string, false, false).await; self.convert_axis_events(event, &event_string, false, false).await;
}, },
(EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_X | AbsoluteAxisType::ABS_Y) => { (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_X | AbsoluteAxisType::ABS_Y) => {
if self.settings.cursor_analog_mode == "left".to_string() { if ["cursor", "scroll"].contains(&self.settings.lstick.function.as_str()) {
let axis_value = self.get_axis_value(&event).await; let axis_value = self.get_axis_value(&event, &self.settings.lstick.deadzone).await;
let mut cursor_analog_position = self.cursor_analog_position.lock().await; let mut lstick_position = self.lstick_position.lock().await;
cursor_analog_position[event.code() as usize] = axis_value; lstick_position[event.code() as usize] = axis_value;
} else if self.settings.scroll_analog_mode == "left".to_string() { } else if self.settings.lstick.function.as_str() == "bind" {
let axis_value = self.get_axis_value(&event).await; let axis_value = self.get_axis_value(&event, &self.settings.lstick.deadzone).await;
let mut scroll_analog_position = self.scroll_analog_position.lock().await; let clamped_value = if axis_value < 0 { -1 }
scroll_analog_position[event.code() as usize] = axis_value; else if axis_value > 0 { 1 }
else { 0 };
let axis = if AbsoluteAxisType(event.code()) == AbsoluteAxisType::ABS_X { "x" }
else if AbsoluteAxisType(event.code()) == AbsoluteAxisType::ABS_Y { "y" }
else { "none" };
let event_string_option: Option<String> = match clamped_value {
-1 if axis == "x" => Option::Some("LSTICK_LEFT".to_string()),
-1 if axis == "y" => Option::Some("LSTICK_UP".to_string()),
0 if axis == "x" => Option::Some("LSTICK_X".to_string()),
0 if axis == "y" => Option::Some("LSTICK_Y".to_string()),
1 if axis == "x" => Option::Some("LSTICK_RIGHT".to_string()),
1 if axis == "y" => Option::Some("LSTICK_DOWN".to_string()),
_ => Option::None,
};
if let Some(event_string) = event_string_option {
let clamped_event = InputEvent::new_now(event.event_type(), event.code(), clamped_value);
self.convert_axis_events(clamped_event, &event_string, false, false).await;
}
} else {
self.emit_default_event(event).await;
} }
}, },
(EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RX | AbsoluteAxisType::ABS_RY) => { (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_RX | AbsoluteAxisType::ABS_RY) => {
if self.settings.cursor_analog_mode == "right".to_string() { if ["cursor", "scroll"].contains(&self.settings.rstick.function.as_str()) {
let axis_value = self.get_axis_value(&event).await; let axis_value = self.get_axis_value(&event, &self.settings.rstick.deadzone).await;
let mut cursor_analog_position = self.cursor_analog_position.lock().await; let mut rstick_position = self.rstick_position.lock().await;
cursor_analog_position[event.code() as usize -3] = axis_value; rstick_position[event.code() as usize -3] = axis_value;
} else if self.settings.scroll_analog_mode == "right".to_string() { } else if self.settings.rstick.function.as_str() == "bind" {
let axis_value = self.get_axis_value(&event).await; let axis_value = self.get_axis_value(&event, &self.settings.rstick.deadzone).await;
let mut scroll_analog_position = self.scroll_analog_position.lock().await; let clamped_value = if axis_value < 0 { -1 }
scroll_analog_position[event.code() as usize -3] = axis_value; else if axis_value > 0 { 1 }
else { 0 };
let axis = if AbsoluteAxisType(event.code()) == AbsoluteAxisType::ABS_RX { "x" }
else if AbsoluteAxisType(event.code()) == AbsoluteAxisType::ABS_RY { "y" }
else { "none" };
let event_string_option: Option<String> = match clamped_value {
-1 if axis == "x" => Option::Some("RSTICK_LEFT".to_string()),
-1 if axis == "y" => Option::Some("RSTICK_UP".to_string()),
0 if axis == "x" => Option::Some("RSTICK_X".to_string()),
0 if axis == "y" => Option::Some("RSTICK_Y".to_string()),
1 if axis == "x" => Option::Some("RSTICK_RIGHT".to_string()),
1 if axis == "y" => Option::Some("RSTICK_DOWN".to_string()),
_ => Option::None,
};
if let Some(event_string) = event_string_option {
let clamped_event = InputEvent::new_now(event.event_type(), event.code(), clamped_value);
self.convert_axis_events(clamped_event, &event_string, false, false).await;
}
} else {
self.emit_default_event(event).await;
} }
}, },
(EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_Z) => { (EventType::ABSOLUTE, _, AbsoluteAxisType::ABS_Z) => {
@ -189,6 +244,7 @@ impl EventReader {
} }
} }
if let Some(event_list) = path.bindings.axis.get(event_string) { if let Some(event_list) = path.bindings.axis.get(event_string) {
println!("{:?}", event_list);
self.emit_event(event_list, value).await; self.emit_event(event_list, value).await;
if send_zero { if send_zero {
self.emit_event_without_modifiers(event_list, &modifiers, 0).await; self.emit_event_without_modifiers(event_list, &modifiers, 0).await;
@ -250,12 +306,12 @@ impl EventReader {
} }
} }
async fn get_axis_value(&self, event: &InputEvent) -> i32 { async fn get_axis_value(&self, event: &InputEvent, deadzone: &i32) -> i32 {
let distance_from_center: i32 = match self.settings.has_signed_axis_value { let distance_from_center: i32 = match self.settings.axis_16_bit {
false => (event.value() as i32 - 128) * 200, false => (event.value() as i32 - 128) * 200,
_ => event.value() as i32 _ => event.value() as i32
}; };
if distance_from_center.abs() <= self.settings.deadzone * 200 { if distance_from_center.abs() <= deadzone * 200 {
0 0
} else { } else {
(distance_from_center + 2000 - 1) / 2000 (distance_from_center + 2000 - 1) / 2000
@ -282,19 +338,32 @@ impl EventReader {
} }
pub async fn cursor_loop(&self) { pub async fn cursor_loop(&self) {
if self.settings.cursor_sensitivity != 0 { let (cursor, sensitivity) = if self.settings.lstick.function.as_str() == "cursor" {
("left", self.settings.lstick.sensitivity)
} else if self.settings.rstick.function.as_str() == "cursor" {
("right", self.settings.rstick.sensitivity)
} else {
("disabled", 0)
};
if sensitivity != 0 {
while *self.device_is_connected.lock().await { while *self.device_is_connected.lock().await {
{ {
let cursor_analog_position = self.cursor_analog_position.lock().await; let stick_position = if cursor == "left" {
if cursor_analog_position[0] != 0 || cursor_analog_position[1] != 0 { self.lstick_position.lock().await
let virtual_event_x: InputEvent = InputEvent::new_now(EventType::RELATIVE, 0, cursor_analog_position[0]); } else if cursor == "right" {
let virtual_event_y: InputEvent = InputEvent::new_now(EventType::RELATIVE, 1, cursor_analog_position[1]); self.rstick_position.lock().await
} else {
break
};
if stick_position[0] != 0 || stick_position[1] != 0 {
let virtual_event_x: InputEvent = InputEvent::new_now(EventType::RELATIVE, 0, stick_position[0]);
let virtual_event_y: InputEvent = InputEvent::new_now(EventType::RELATIVE, 1, stick_position[1]);
let mut virt_dev = self.virt_dev.lock().await; let mut virt_dev = self.virt_dev.lock().await;
virt_dev.axis.emit(&[virtual_event_x]).unwrap(); virt_dev.axis.emit(&[virtual_event_x]).unwrap();
virt_dev.axis.emit(&[virtual_event_y]).unwrap(); virt_dev.axis.emit(&[virtual_event_y]).unwrap();
} }
} }
tokio::time::sleep(std::time::Duration::from_millis(self.settings.cursor_sensitivity)).await; tokio::time::sleep(std::time::Duration::from_millis(sensitivity)).await;
} }
} else { } else {
return return
@ -302,19 +371,32 @@ impl EventReader {
} }
pub async fn scroll_loop(&self) { pub async fn scroll_loop(&self) {
if self.settings.scroll_sensitivity != 0 { let (scroll, sensitivity) = if self.settings.lstick.function.as_str() == "scroll" {
("left", self.settings.lstick.sensitivity)
} else if self.settings.rstick.function.as_str() == "scroll" {
("right", self.settings.rstick.sensitivity)
} else {
("disabled", 0)
};
if sensitivity != 0 {
while *self.device_is_connected.lock().await { while *self.device_is_connected.lock().await {
{ {
let scroll_analog_position = self.scroll_analog_position.lock().await; let stick_position = if scroll == "left" {
if scroll_analog_position[0] != 0 || scroll_analog_position[1] != 0 { self.lstick_position.lock().await
let virtual_event_x: InputEvent = InputEvent::new_now(EventType::RELATIVE, 12, scroll_analog_position[0]); } else if scroll == "right" {
let virtual_event_y: InputEvent = InputEvent::new_now(EventType::RELATIVE, 11, scroll_analog_position[1]); self.rstick_position.lock().await
} else {
break
};
if stick_position[0] != 0 || stick_position[1] != 0 {
let virtual_event_x: InputEvent = InputEvent::new_now(EventType::RELATIVE, 12, stick_position[0]);
let virtual_event_y: InputEvent = InputEvent::new_now(EventType::RELATIVE, 11, stick_position[1]);
let mut virt_dev = self.virt_dev.lock().await; let mut virt_dev = self.virt_dev.lock().await;
virt_dev.axis.emit(&[virtual_event_x]).unwrap(); virt_dev.axis.emit(&[virtual_event_x]).unwrap();
virt_dev.axis.emit(&[virtual_event_y]).unwrap(); virt_dev.axis.emit(&[virtual_event_y]).unwrap();
} }
} }
tokio::time::sleep(std::time::Duration::from_millis(self.settings.scroll_sensitivity)).await; tokio::time::sleep(std::time::Duration::from_millis(sensitivity)).await;
} }
} else { } else {
return return