Implemented cursor and scroll movements through keys
This commit is contained in:
parent
07d5a8768d
commit
77d8a5d6ad
2 changed files with 305 additions and 2 deletions
123
src/config.rs
123
src/config.rs
|
@ -60,6 +60,47 @@ impl FromStr for Axis {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||
pub enum Relative {
|
||||
Cursor(Cursor),
|
||||
Scroll(Scroll),
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||
pub enum Cursor {
|
||||
CURSOR_UP,
|
||||
CURSOR_DOWN,
|
||||
CURSOR_LEFT,
|
||||
CURSOR_RIGHT,
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||
pub enum Scroll {
|
||||
SCROLL_UP,
|
||||
SCROLL_DOWN,
|
||||
SCROLL_LEFT,
|
||||
SCROLL_RIGHT,
|
||||
}
|
||||
|
||||
impl FromStr for Relative {
|
||||
type Err = String;
|
||||
fn from_str(s: &str) -> Result<Relative, Self::Err> {
|
||||
match s {
|
||||
"CURSOR_UP" => Ok(Relative::Cursor(Cursor::CURSOR_UP)),
|
||||
"CURSOR_DOWN" => Ok(Relative::Cursor(Cursor::CURSOR_DOWN)),
|
||||
"CURSOR_LEFT" => Ok(Relative::Cursor(Cursor::CURSOR_LEFT)),
|
||||
"CURSOR_RIGHT" => Ok(Relative::Cursor(Cursor::CURSOR_RIGHT)),
|
||||
"SCROLL_UP" => Ok(Relative::Scroll(Scroll::SCROLL_UP)),
|
||||
"SCROLL_DOWN" => Ok(Relative::Scroll(Scroll::SCROLL_DOWN)),
|
||||
"SCROLL_LEFT" => Ok(Relative::Scroll(Scroll::SCROLL_LEFT)),
|
||||
"SCROLL_RIGHT" => Ok(Relative::Scroll(Scroll::SCROLL_RIGHT)),
|
||||
_ => Err(s.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Default, Clone)]
|
||||
pub struct Associations {
|
||||
pub client: Client,
|
||||
|
@ -70,6 +111,7 @@ pub struct Associations {
|
|||
pub struct Bindings {
|
||||
pub remap: HashMap<Event, HashMap<Vec<Event>, Vec<Key>>>,
|
||||
pub commands: HashMap<Event, HashMap<Vec<Event>, Vec<String>>>,
|
||||
pub movements: HashMap<Event, HashMap<Vec<Event>, Relative>>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
|
@ -86,6 +128,8 @@ pub struct RawConfig {
|
|||
#[serde(default)]
|
||||
pub commands: HashMap<String, Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub movements: HashMap<String, String>,
|
||||
#[serde(default)]
|
||||
pub settings: HashMap<String, String>,
|
||||
}
|
||||
|
||||
|
@ -100,10 +144,12 @@ impl RawConfig {
|
|||
toml::from_str(&file_content).expect("Couldn't parse config file.");
|
||||
let remap = raw_config.remap;
|
||||
let commands = raw_config.commands;
|
||||
let movements = raw_config.movements;
|
||||
let settings = raw_config.settings;
|
||||
Self {
|
||||
remap,
|
||||
commands,
|
||||
movements,
|
||||
settings,
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +193,7 @@ impl Config {
|
|||
fn parse_raw_config(raw_config: RawConfig) -> (Bindings, HashMap<String, String>, MappedModifiers) {
|
||||
let remap: HashMap<String, Vec<Key>> = raw_config.remap;
|
||||
let commands: HashMap<String, Vec<String>> = raw_config.commands;
|
||||
let movements: HashMap<String, String> = raw_config.movements;
|
||||
let settings: HashMap<String, String> = raw_config.settings;
|
||||
let mut bindings: Bindings = Default::default();
|
||||
let default_modifiers = vec![
|
||||
|
@ -322,6 +369,82 @@ fn parse_raw_config(raw_config: RawConfig) -> (Bindings, HashMap<String, String>
|
|||
}
|
||||
}
|
||||
|
||||
for (input, output) in movements.clone() {
|
||||
if let Some((mods, event)) = input.rsplit_once("-") {
|
||||
let str_modifiers = mods.split("-").collect::<Vec<&str>>();
|
||||
let mut modifiers: Vec<Event> = Vec::new();
|
||||
for event in str_modifiers.clone() {
|
||||
if let Ok(axis) = Axis::from_str(event) {
|
||||
modifiers.push(Event::Axis(axis));
|
||||
} else if let Ok(key) = Key::from_str(event) {
|
||||
modifiers.push(Event::Key(key));
|
||||
}
|
||||
}
|
||||
modifiers.sort();
|
||||
modifiers.dedup();
|
||||
for modifier in &modifiers {
|
||||
if !mapped_modifiers.default.contains(&modifier) {
|
||||
mapped_modifiers.custom.push(modifier.clone());
|
||||
}
|
||||
}
|
||||
if str_modifiers[0] == "" {
|
||||
modifiers.push(Event::Hold);
|
||||
}
|
||||
if let Ok(event) = Axis::from_str(event) {
|
||||
if !bindings.movements.contains_key(&Event::Axis(event)) {
|
||||
bindings
|
||||
.movements
|
||||
.insert(Event::Axis(event), HashMap::from([(modifiers, Relative::from_str(output.as_str()).expect("Invalid movement in [movements]."))]));
|
||||
} else {
|
||||
bindings
|
||||
.movements
|
||||
.get_mut(&Event::Axis(event))
|
||||
.unwrap()
|
||||
.insert(modifiers, Relative::from_str(output.as_str()).expect("Invalid movement in [movements]."));
|
||||
}
|
||||
} else if let Ok(event) = Key::from_str(event) {
|
||||
if !bindings.movements.contains_key(&Event::Key(event)) {
|
||||
bindings
|
||||
.movements
|
||||
.insert(Event::Key(event), HashMap::from([(modifiers, Relative::from_str(output.as_str()).expect("Invalid movement in [movements]."))]));
|
||||
} else {
|
||||
bindings
|
||||
.movements
|
||||
.get_mut(&Event::Key(event))
|
||||
.unwrap()
|
||||
.insert(modifiers, Relative::from_str(output.as_str()).expect("Invalid movement in [movements]."));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let modifiers: Vec<Event> = Vec::new();
|
||||
if let Ok(event) = Axis::from_str(input.as_str()) {
|
||||
if !bindings.movements.contains_key(&Event::Axis(event)) {
|
||||
bindings
|
||||
.movements
|
||||
.insert(Event::Axis(event), HashMap::from([(modifiers, Relative::from_str(output.as_str()).expect("Invalid movement in [movements]."))]));
|
||||
} else {
|
||||
bindings
|
||||
.movements
|
||||
.get_mut(&Event::Axis(event))
|
||||
.unwrap()
|
||||
.insert(modifiers, Relative::from_str(output.as_str()).expect("Invalid movement in [movements]."));
|
||||
}
|
||||
} else if let Ok(event) = Key::from_str(input.as_str()) {
|
||||
if !bindings.movements.contains_key(&Event::Key(event)) {
|
||||
bindings
|
||||
.movements
|
||||
.insert(Event::Key(event), HashMap::from([(modifiers, Relative::from_str(output.as_str()).expect("Invalid movement in [movements]."))]));
|
||||
} else {
|
||||
bindings
|
||||
.movements
|
||||
.get_mut(&Event::Key(event))
|
||||
.unwrap()
|
||||
.insert(modifiers, Relative::from_str(output.as_str()).expect("Invalid movement in [movements]."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mapped_modifiers.custom.sort();
|
||||
mapped_modifiers.custom.dedup();
|
||||
mapped_modifiers
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::active_client::*;
|
||||
use crate::config::{parse_modifiers, Associations, Axis, Event};
|
||||
use crate::config::{parse_modifiers, Associations, Axis, Event, Relative, Cursor, Scroll};
|
||||
use crate::udev_monitor::Environment;
|
||||
use crate::virtual_devices::VirtualDevices;
|
||||
use crate::Config;
|
||||
|
@ -23,6 +23,11 @@ struct Stick {
|
|||
activation_modifiers: Vec<Event>,
|
||||
}
|
||||
|
||||
struct Movement {
|
||||
speed: i32,
|
||||
acceleration: f32,
|
||||
}
|
||||
|
||||
struct Settings {
|
||||
lstick: Stick,
|
||||
rstick: Stick,
|
||||
|
@ -30,6 +35,8 @@ struct Settings {
|
|||
invert_scroll_axis: bool,
|
||||
axis_16_bit: bool,
|
||||
stadia: bool,
|
||||
cursor: Movement,
|
||||
scroll: Movement,
|
||||
chain_only: bool,
|
||||
layout_switcher: Key,
|
||||
notify_layout_switch: bool,
|
||||
|
@ -41,6 +48,8 @@ pub struct EventReader {
|
|||
virt_dev: Arc<Mutex<VirtualDevices>>,
|
||||
lstick_position: Arc<Mutex<Vec<i32>>>,
|
||||
rstick_position: Arc<Mutex<Vec<i32>>>,
|
||||
cursor_movement: Arc<Mutex<(i32, i32)>>,
|
||||
scroll_movement: Arc<Mutex<(i32, i32)>>,
|
||||
modifiers: Arc<Mutex<Vec<Event>>>,
|
||||
modifier_was_activated: Arc<Mutex<bool>>,
|
||||
device_is_connected: Arc<Mutex<bool>>,
|
||||
|
@ -65,6 +74,8 @@ impl EventReader {
|
|||
}
|
||||
let lstick_position = Arc::new(Mutex::new(position_vector.clone()));
|
||||
let rstick_position = Arc::new(Mutex::new(position_vector.clone()));
|
||||
let cursor_movement = Arc::new(Mutex::new((0, 0)));
|
||||
let scroll_movement = Arc::new(Mutex::new((0, 0)));
|
||||
let device_is_connected: Arc<Mutex<bool>> = Arc::new(Mutex::new(true));
|
||||
let active_layout: Arc<Mutex<u16>> = Arc::new(Mutex::new(0));
|
||||
let current_config: Arc<Mutex<Config>> = Arc::new(Mutex::new(
|
||||
|
@ -206,6 +217,56 @@ impl EventReader {
|
|||
.parse()
|
||||
.expect("INVERT_SCROLL_AXIS can only be true or false.");
|
||||
|
||||
let cursor_speed: i32 = config
|
||||
.iter()
|
||||
.find(|&x| x.associations == Associations::default())
|
||||
.unwrap()
|
||||
.settings
|
||||
.get("CURSOR_SPEED")
|
||||
.unwrap_or(&"0".to_string())
|
||||
.parse()
|
||||
.expect("Invalid value for CURSOR_SPEED, please use an integer value.");
|
||||
|
||||
let cursor_acceleration: f32 = config
|
||||
.iter()
|
||||
.find(|&x| x.associations == Associations::default())
|
||||
.unwrap()
|
||||
.settings
|
||||
.get("CURSOR_ACCEL")
|
||||
.unwrap_or(&"0".to_string())
|
||||
.parse()
|
||||
.expect("Invalid value for CURSOR_ACCEL, please use an float value between 0 and 1.");
|
||||
|
||||
let scroll_speed: i32 = config
|
||||
.iter()
|
||||
.find(|&x| x.associations == Associations::default())
|
||||
.unwrap()
|
||||
.settings
|
||||
.get("SCROLL_SPEED")
|
||||
.unwrap_or(&"0".to_string())
|
||||
.parse()
|
||||
.expect("Invalid value for SCROLL_SPEED, please use an integer value.");
|
||||
|
||||
let scroll_acceleration: f32 = config
|
||||
.iter()
|
||||
.find(|&x| x.associations == Associations::default())
|
||||
.unwrap()
|
||||
.settings
|
||||
.get("SCROLL_ACCEL")
|
||||
.unwrap_or(&"0".to_string())
|
||||
.parse()
|
||||
.expect("Invalid value for SCROLL_ACCEL, please use a float value between 0 and 1.");
|
||||
|
||||
let cursor = Movement {
|
||||
speed: cursor_speed,
|
||||
acceleration: cursor_acceleration,
|
||||
};
|
||||
|
||||
let scroll = Movement {
|
||||
speed: scroll_speed,
|
||||
acceleration: scroll_acceleration,
|
||||
};
|
||||
|
||||
let layout_switcher: Key = Key::from_str(
|
||||
config
|
||||
.iter()
|
||||
|
@ -234,6 +295,8 @@ impl EventReader {
|
|||
invert_scroll_axis,
|
||||
axis_16_bit,
|
||||
stadia,
|
||||
cursor,
|
||||
scroll,
|
||||
chain_only,
|
||||
layout_switcher,
|
||||
notify_layout_switch,
|
||||
|
@ -244,6 +307,8 @@ impl EventReader {
|
|||
virt_dev,
|
||||
lstick_position,
|
||||
rstick_position,
|
||||
cursor_movement,
|
||||
scroll_movement,
|
||||
modifiers,
|
||||
modifier_was_activated,
|
||||
device_is_connected,
|
||||
|
@ -263,7 +328,7 @@ impl EventReader {
|
|||
.unwrap()
|
||||
.name
|
||||
);
|
||||
tokio::join!(self.event_loop(), self.cursor_loop(), self.scroll_loop(),);
|
||||
tokio::join!(self.event_loop(), self.cursor_loop(), self.scroll_loop(), self.key_cursor_loop(), self.key_scroll_loop());
|
||||
}
|
||||
|
||||
pub async fn event_loop(&self) {
|
||||
|
@ -964,6 +1029,14 @@ impl EventReader {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if let Some(map) = config.bindings.movements.get(&event) {
|
||||
if let Some(movement) = map.get(&modifiers) {
|
||||
if value <= 1 {
|
||||
self.emit_movement(movement, value).await;
|
||||
}
|
||||
};
|
||||
return;
|
||||
}
|
||||
if let Some(event_list) = map.get(&Vec::new()) {
|
||||
self.emit_event(event_list, value, &modifiers, &config, true, false)
|
||||
.await;
|
||||
|
@ -983,6 +1056,14 @@ impl EventReader {
|
|||
return;
|
||||
}
|
||||
}
|
||||
if let Some(map) = config.bindings.movements.get(&event) {
|
||||
if let Some(movement) = map.get(&modifiers) {
|
||||
if value <= 1 {
|
||||
self.emit_movement(movement, value).await;
|
||||
}
|
||||
};
|
||||
return;
|
||||
}
|
||||
self.emit_nonmapped_event(default_event, event, value, &modifiers, &config)
|
||||
.await;
|
||||
}
|
||||
|
@ -1117,6 +1198,21 @@ impl EventReader {
|
|||
}
|
||||
}
|
||||
|
||||
async fn emit_movement(&self, movement: &Relative, value: i32) {
|
||||
let mut cursor_movement = self.cursor_movement.lock().await;
|
||||
let mut scroll_movement = self.scroll_movement.lock().await;
|
||||
match movement {
|
||||
Relative::Cursor(Cursor::CURSOR_UP) => cursor_movement.1 = -value,
|
||||
Relative::Cursor(Cursor::CURSOR_DOWN) => cursor_movement.1 = value,
|
||||
Relative::Cursor(Cursor::CURSOR_LEFT) => cursor_movement.0 = -value,
|
||||
Relative::Cursor(Cursor::CURSOR_RIGHT) => cursor_movement.0 = value,
|
||||
Relative::Scroll(Scroll::SCROLL_UP) => scroll_movement.1 = -value,
|
||||
Relative::Scroll(Scroll::SCROLL_DOWN) => scroll_movement.1 = value,
|
||||
Relative::Scroll(Scroll::SCROLL_LEFT) => scroll_movement.0 = -value,
|
||||
Relative::Scroll(Scroll::SCROLL_RIGHT) => scroll_movement.0 = value,
|
||||
};
|
||||
}
|
||||
|
||||
async fn spawn_subprocess(&self, command_list: &Vec<String>) {
|
||||
let mut modifier_was_activated = self.modifier_was_activated.lock().await;
|
||||
*modifier_was_activated = true;
|
||||
|
@ -1348,4 +1444,88 @@ impl EventReader {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn key_cursor_loop(&self) {
|
||||
let (speed, acceleration, mut current_speed) = (
|
||||
if self.settings.cursor.speed == 0 {
|
||||
return
|
||||
} else {
|
||||
self.settings.cursor.speed
|
||||
},
|
||||
if self.settings.cursor.acceleration.abs() > 1.0 {
|
||||
1.0
|
||||
} else {
|
||||
self.settings.cursor.acceleration.abs()
|
||||
},
|
||||
self.settings.cursor.speed as f32
|
||||
);
|
||||
while *self.device_is_connected.lock().await {
|
||||
{
|
||||
let cursor_movement = self.cursor_movement.lock().await;
|
||||
if *cursor_movement == (0, 0) {
|
||||
current_speed = 0.0
|
||||
} else {
|
||||
current_speed += speed as f32 * acceleration / 10.0;
|
||||
if current_speed > speed as f32 {
|
||||
current_speed = speed as f32
|
||||
}
|
||||
if cursor_movement.0 != 0 {
|
||||
let mut virt_dev = self.virt_dev.lock().await;
|
||||
let virtual_event_x: InputEvent =
|
||||
InputEvent::new_now(EventType::RELATIVE, 0, cursor_movement.0 * current_speed as i32);
|
||||
virt_dev.axis.emit(&[virtual_event_x]).unwrap();
|
||||
}
|
||||
if cursor_movement.1 != 0 {
|
||||
let mut virt_dev = self.virt_dev.lock().await;
|
||||
let virtual_event_y: InputEvent =
|
||||
InputEvent::new_now(EventType::RELATIVE, 1, cursor_movement.1 * current_speed as i32);
|
||||
virt_dev.axis.emit(&[virtual_event_y]).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn key_scroll_loop(&self) {
|
||||
let (speed, acceleration, mut current_speed) = (
|
||||
if self.settings.scroll.speed == 0 {
|
||||
return
|
||||
} else {
|
||||
self.settings.scroll.speed
|
||||
},
|
||||
if self.settings.scroll.acceleration.abs() > 1.0 {
|
||||
1.0
|
||||
} else {
|
||||
self.settings.scroll.acceleration.abs()
|
||||
},
|
||||
self.settings.scroll.speed as f32
|
||||
);
|
||||
while *self.device_is_connected.lock().await {
|
||||
{
|
||||
let scroll_movement = self.scroll_movement.lock().await;
|
||||
if *scroll_movement == (0, 0) {
|
||||
current_speed = 0.0
|
||||
} else {
|
||||
current_speed += speed as f32 * acceleration / 10.0;
|
||||
if current_speed > speed as f32 {
|
||||
current_speed = speed as f32
|
||||
}
|
||||
if scroll_movement.0 != 0 {
|
||||
let mut virt_dev = self.virt_dev.lock().await;
|
||||
let virtual_event_x: InputEvent =
|
||||
InputEvent::new_now(EventType::RELATIVE, 12, scroll_movement.0 * current_speed as i32);
|
||||
virt_dev.axis.emit(&[virtual_event_x]).unwrap();
|
||||
}
|
||||
if scroll_movement.1 != 0 {
|
||||
let mut virt_dev = self.virt_dev.lock().await;
|
||||
let virtual_event_y: InputEvent =
|
||||
InputEvent::new_now(EventType::RELATIVE, 11, scroll_movement.1 * current_speed as i32);
|
||||
virt_dev.axis.emit(&[virtual_event_y]).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
tokio::time::sleep(std::time::Duration::from_millis(10)).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue