Added support for custom key modifiers
This commit is contained in:
parent
a6dfe9dfd4
commit
f5452cac5d
3 changed files with 180 additions and 128 deletions
159
src/config.rs
159
src/config.rs
|
@ -1,4 +1,4 @@
|
|||
use std::collections::{HashMap, BTreeMap};
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use evdev::Key;
|
||||
use serde;
|
||||
|
@ -14,21 +14,12 @@ pub struct Bindings {
|
|||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct Combinations {
|
||||
pub keys: HashMap<String, HashMap<Key, Vec<Key>>>,
|
||||
pub axis: HashMap<String, HashMap<String, Vec<Key>>>,
|
||||
pub keys_sh: HashMap<String, HashMap<Key, Vec<String>>>,
|
||||
pub axis_sh: HashMap<String, HashMap<String, Vec<String>>>,
|
||||
pub keys: HashMap<Key, HashMap<Vec<Key>, Vec<Key>>>,
|
||||
pub axis: HashMap<String, HashMap<Vec<Key>, Vec<Key>>>,
|
||||
pub keys_sh: HashMap<Key, HashMap<Vec<Key>, Vec<String>>>,
|
||||
pub axis_sh: HashMap<String, HashMap<Vec<Key>, Vec<String>>>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct Modifiers {
|
||||
pub keys: HashMap<BTreeMap<Key, i32>, HashMap<Key, Vec<Key>>>,
|
||||
pub axis: HashMap<BTreeMap<Key, i32>, HashMap<String, Vec<Key>>>,
|
||||
pub keys_sh: HashMap<BTreeMap<Key, i32>, HashMap<Key, Vec<String>>>,
|
||||
pub axis_sh: HashMap<BTreeMap<Key, i32>, HashMap<String, Vec<String>>>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(serde::Deserialize, Debug, Clone)]
|
||||
pub struct RawConfig {
|
||||
#[serde(default)]
|
||||
|
@ -38,6 +29,13 @@ pub struct RawConfig {
|
|||
pub settings: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MappedModifiers {
|
||||
pub default: Vec<Key>,
|
||||
pub custom: Vec<Key>,
|
||||
pub all: Vec<Key>,
|
||||
}
|
||||
|
||||
impl RawConfig {
|
||||
fn new_from_file(file: &str) -> Self {
|
||||
println!("Parsing config file:\n{:?}\n", file.rsplit_once("/").unwrap().1);
|
||||
|
@ -59,32 +57,55 @@ impl RawConfig {
|
|||
pub struct Config {
|
||||
pub name: String,
|
||||
pub bindings: Bindings,
|
||||
pub modifiers: Modifiers,
|
||||
pub combinations: Combinations,
|
||||
pub settings: HashMap<String, String>,
|
||||
pub mapped_modifiers: MappedModifiers,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
pub fn new_from_file(file: &str, file_name: String) -> Self {
|
||||
let raw_config = RawConfig::new_from_file(file);
|
||||
let (bindings, combinations, settings) = parse_raw_config(raw_config);
|
||||
let (bindings, combinations, settings, mapped_modifiers) = parse_raw_config(raw_config);
|
||||
let bindings: Bindings = merge_axis_bindings(bindings);
|
||||
let modifiers: Modifiers = parse_modifiers(combinations);
|
||||
|
||||
Self {
|
||||
name: file_name,
|
||||
bindings,
|
||||
modifiers,
|
||||
combinations,
|
||||
settings,
|
||||
mapped_modifiers,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_raw_config(raw_config: RawConfig) -> (Bindings, Combinations, HashMap<String, String>) {
|
||||
fn parse_raw_config(raw_config: RawConfig) -> (Bindings, Combinations, HashMap<String, String>, MappedModifiers) {
|
||||
let remap: HashMap<String, Vec<Key>> = raw_config.remap;
|
||||
let commands: HashMap<String, Vec<String>> = raw_config.commands;
|
||||
let settings: HashMap<String, String> = raw_config.settings;
|
||||
let mut bindings: Bindings = Default::default();
|
||||
let mut combinations: Combinations = Default::default();
|
||||
let default_modifiers = vec![
|
||||
Key::KEY_LEFTSHIFT,
|
||||
Key::KEY_LEFTCTRL,
|
||||
Key::KEY_LEFTALT,
|
||||
Key::KEY_RIGHTSHIFT,
|
||||
Key::KEY_RIGHTCTRL,
|
||||
Key::KEY_RIGHTALT,
|
||||
Key::KEY_LEFTMETA,
|
||||
];
|
||||
let mut mapped_modifiers = MappedModifiers {
|
||||
default: default_modifiers.clone(),
|
||||
custom: Vec::new(),
|
||||
all: Vec::new(),
|
||||
};
|
||||
let custom_modifiers: Vec<Key> = match settings.get(&"CUSTOM_MODIFIERS".to_string()) {
|
||||
Some(modifiers) => {
|
||||
modifiers.split("-").collect::<Vec<&str>>().iter()
|
||||
.map(|key_str| Key::from_str(key_str).expect("Invalid KEY value used as modifier in CUSTOM_MODIFIERS.")).collect()
|
||||
},
|
||||
None => Vec::new(),
|
||||
};
|
||||
mapped_modifiers.custom.extend(custom_modifiers);
|
||||
|
||||
let abs = [
|
||||
"DPAD_UP",
|
||||
|
@ -108,24 +129,32 @@ fn parse_raw_config(raw_config: RawConfig) -> (Bindings, Combinations, HashMap<S
|
|||
for (input, output) in remap.clone().into_iter() {
|
||||
if input.contains("-") {
|
||||
let (mods, key) = input.rsplit_once("-").unwrap();
|
||||
let mut modifiers: Vec<Key> = mods.split("-").collect::<Vec<&str>>().iter().map(|key_str| Key::from_str(key_str).expect("Invalid KEY value used as modifier.")).collect();
|
||||
modifiers.sort();
|
||||
modifiers.dedup();
|
||||
for modifier in &modifiers {
|
||||
if !mapped_modifiers.default.contains(&modifier) {
|
||||
mapped_modifiers.custom.push(modifier.clone());
|
||||
}
|
||||
}
|
||||
if abs.contains(&key) {
|
||||
if !combinations.axis.contains_key(&mods.to_string()) {
|
||||
combinations.axis.insert(mods.to_string(), HashMap::from([(key.to_string(), output)]));
|
||||
if !combinations.axis.contains_key(&key.to_string()) {
|
||||
combinations.axis.insert(key.to_string(), HashMap::from([(modifiers , output)]));
|
||||
} else {
|
||||
combinations.axis.get_mut(mods).unwrap().insert(key.to_string(), output);
|
||||
combinations.axis.get_mut(key).unwrap().insert(modifiers, output);
|
||||
}
|
||||
} else {
|
||||
if !combinations.keys.contains_key(&mods.to_string()) {
|
||||
combinations.keys.insert(mods.to_string(), HashMap::from([(Key::from_str(key).expect("Invalid KEY value."), output)]));
|
||||
if !combinations.keys.contains_key(&Key::from_str(key).unwrap()) {
|
||||
combinations.keys.insert(Key::from_str(key).unwrap(), HashMap::from([(modifiers, output)]));
|
||||
} else {
|
||||
combinations.keys.get_mut(mods).unwrap().insert(Key::from_str(key).expect("Invalid KEY value."), output);
|
||||
combinations.keys.get_mut(&Key::from_str(key).unwrap()).unwrap().insert(modifiers, output);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if abs.contains(&input.as_str()) {
|
||||
bindings.axis.insert(input, output);
|
||||
} else {
|
||||
bindings.keys.insert(Key::from_str(input.as_str()).expect("Invalid KEY value."), output);
|
||||
bindings.keys.insert(Key::from_str(input.as_str()).expect("Invalid KEY value used for rebinding."), output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,74 +162,44 @@ fn parse_raw_config(raw_config: RawConfig) -> (Bindings, Combinations, HashMap<S
|
|||
for (input, output) in commands.clone().into_iter() {
|
||||
if input.contains("-") {
|
||||
let (mods, key) = input.rsplit_once("-").unwrap();
|
||||
let mut modifiers: Vec<Key> = mods.split("-").collect::<Vec<&str>>().iter().map(|key_str| Key::from_str(key_str).expect("Invalid KEY value used as modifier.")).collect();
|
||||
modifiers.sort();
|
||||
modifiers.dedup();
|
||||
for modifier in &modifiers {
|
||||
if !mapped_modifiers.default.contains(&modifier) {
|
||||
mapped_modifiers.custom.push(modifier.clone());
|
||||
}
|
||||
}
|
||||
if abs.contains(&key) {
|
||||
if !combinations.axis_sh.contains_key(&mods.to_string()) {
|
||||
combinations.axis_sh.insert(mods.to_string(), HashMap::from([(key.to_string(), output)]));
|
||||
if !combinations.axis_sh.contains_key(&key.to_string()) {
|
||||
combinations.axis_sh.insert(key.to_string(), HashMap::from([(modifiers, output)]));
|
||||
} else {
|
||||
combinations.axis_sh.get_mut(mods).unwrap().insert(key.to_string(), output);
|
||||
combinations.axis_sh.get_mut(key).unwrap().insert(modifiers, output);
|
||||
}
|
||||
} else {
|
||||
if !combinations.keys_sh.contains_key(&mods.to_string()) {
|
||||
combinations.keys_sh.insert(mods.to_string(), HashMap::from([(Key::from_str(key).expect("Invalid KEY value."), output)]));
|
||||
if !combinations.keys_sh.contains_key(&Key::from_str(key).unwrap()) {
|
||||
combinations.keys_sh.insert(Key::from_str(key).unwrap(), HashMap::from([(modifiers, output)]));
|
||||
} else {
|
||||
combinations.keys_sh.get_mut(mods).unwrap().insert(Key::from_str(key).expect("Invalid KEY value."), output);
|
||||
combinations.keys_sh.get_mut(&Key::from_str(key).unwrap()).unwrap().insert(modifiers, output);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if abs.contains(&input.as_str()) {
|
||||
bindings.axis_sh.insert(input, output);
|
||||
} else {
|
||||
bindings.keys_sh.insert(Key::from_str(input.as_str()).expect("Invalid KEY value."), output);
|
||||
bindings.keys_sh.insert(Key::from_str(input.as_str()).expect("Invalid KEY value used for rebinding."), output);
|
||||
}
|
||||
}
|
||||
}
|
||||
(bindings, combinations, settings)
|
||||
}
|
||||
|
||||
fn parse_modifiers(combinations: Combinations) -> Modifiers {
|
||||
let empty_modmap = BTreeMap::from ([
|
||||
(Key::KEY_LEFTSHIFT, 0),
|
||||
(Key::KEY_LEFTCTRL, 0),
|
||||
(Key::KEY_LEFTALT, 0),
|
||||
(Key::KEY_RIGHTSHIFT, 0),
|
||||
(Key::KEY_RIGHTCTRL, 0),
|
||||
(Key::KEY_RIGHTALT, 0),
|
||||
(Key::KEY_LEFTMETA, 0)
|
||||
]);
|
||||
let mut modifiers: Modifiers = Default::default();
|
||||
for (mods, key) in combinations.keys.iter() {
|
||||
let mods_vector = mods.split("-").map(str::to_string).collect::<Vec<String>>();
|
||||
let mut modmap = empty_modmap.clone();
|
||||
for modifier in mods_vector {
|
||||
modmap.insert(Key::from_str(&modifier).unwrap(), 1);
|
||||
}
|
||||
modifiers.keys.insert(modmap, key.clone());
|
||||
}
|
||||
for (mods, key) in combinations.axis.iter() {
|
||||
let mods_vector = mods.split("-").map(str::to_string).collect::<Vec<String>>();
|
||||
let mut modmap = empty_modmap.clone();
|
||||
for modifier in mods_vector {
|
||||
modmap.insert(Key::from_str(&modifier).unwrap(), 1);
|
||||
}
|
||||
modifiers.axis.insert(modmap, key.clone());
|
||||
}
|
||||
for (mods, key) in combinations.keys_sh.iter() {
|
||||
let mods_vector = mods.split("-").map(str::to_string).collect::<Vec<String>>();
|
||||
let mut modmap = empty_modmap.clone();
|
||||
for modifier in mods_vector {
|
||||
modmap.insert(Key::from_str(&modifier).unwrap(), 1);
|
||||
}
|
||||
modifiers.keys_sh.insert(modmap, key.clone());
|
||||
}
|
||||
for (mods, key) in combinations.axis_sh.iter() {
|
||||
let mods_vector = mods.split("-").map(str::to_string).collect::<Vec<String>>();
|
||||
let mut modmap = empty_modmap.clone();
|
||||
for modifier in mods_vector {
|
||||
modmap.insert(Key::from_str(&modifier).unwrap(), 1);
|
||||
}
|
||||
modifiers.axis_sh.insert(modmap, key.clone());
|
||||
}
|
||||
modifiers
|
||||
mapped_modifiers.custom.sort();
|
||||
mapped_modifiers.custom.dedup();
|
||||
mapped_modifiers.all.extend(mapped_modifiers.default.clone());
|
||||
mapped_modifiers.all.extend(mapped_modifiers.custom.clone());
|
||||
mapped_modifiers.all.sort();
|
||||
mapped_modifiers.all.dedup();
|
||||
|
||||
(bindings, combinations, settings, mapped_modifiers)
|
||||
}
|
||||
|
||||
fn merge_axis_bindings(mut bindings: Bindings) -> Bindings {
|
||||
|
@ -238,3 +237,5 @@ fn merge_axis_bindings(mut bindings: Bindings) -> Bindings {
|
|||
bindings.axis.insert("RSTICK_Y".to_string(), rstick_y);
|
||||
bindings
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::{HashMap, BTreeMap}, sync::Arc, option::Option, process::Command};
|
||||
use std::{collections::HashMap, sync::Arc, option::Option, process::Command};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio_stream::StreamExt;
|
||||
use evdev::{EventStream, Key, RelativeAxisType, AbsoluteAxisType, EventType, InputEvent};
|
||||
|
@ -25,7 +25,8 @@ pub struct EventReader {
|
|||
virt_dev: Arc<Mutex<VirtualDevices>>,
|
||||
lstick_position: Arc<Mutex<Vec<i32>>>,
|
||||
rstick_position: Arc<Mutex<Vec<i32>>>,
|
||||
modifiers: Arc<Mutex<BTreeMap<Key, i32>>>,
|
||||
modifiers: Arc<Mutex<Vec<Key>>>,
|
||||
modifier_was_activated: Arc<Mutex<bool>>,
|
||||
device_is_connected: Arc<Mutex<bool>>,
|
||||
current_desktop: Option<String>,
|
||||
settings: Settings,
|
||||
|
@ -35,7 +36,8 @@ impl EventReader {
|
|||
pub fn new(
|
||||
config: HashMap<String, Config>,
|
||||
stream: Arc<Mutex<EventStream>>,
|
||||
modifiers: Arc<Mutex<BTreeMap<Key, i32>>>,
|
||||
modifiers: Arc<Mutex<Vec<Key>>>,
|
||||
modifier_was_activated: Arc<Mutex<bool>>,
|
||||
current_desktop: Option<String>,
|
||||
) -> Self {
|
||||
let mut position_vector: Vec<i32> = Vec::new();
|
||||
|
@ -83,6 +85,7 @@ impl EventReader {
|
|||
lstick_position,
|
||||
rstick_position,
|
||||
modifiers,
|
||||
modifier_was_activated,
|
||||
device_is_connected,
|
||||
current_desktop,
|
||||
settings,
|
||||
|
@ -252,13 +255,13 @@ impl EventReader {
|
|||
async fn convert_key_events(&self, event: InputEvent) {
|
||||
let path = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap();
|
||||
let modifiers = self.modifiers.lock().await.clone();
|
||||
if let Some(event_hashmap) = path.modifiers.keys.get(&modifiers) {
|
||||
if let Some(event_list) = event_hashmap.get(&Key(event.code())) {
|
||||
if let Some(event_hashmap) = path.combinations.keys.get(&Key(event.code())) {
|
||||
if let Some(event_list) = event_hashmap.get(&modifiers) {
|
||||
self.emit_event_without_modifiers(event_list, &modifiers, event.value()).await;
|
||||
return
|
||||
}
|
||||
} else if let Some(command_hashmap) = path.modifiers.keys_sh.get(&modifiers) {
|
||||
if let Some(command_list) = command_hashmap.get(&Key(event.code())) {
|
||||
} else if let Some(command_hashmap) = path.combinations.keys_sh.get(&Key(event.code())) {
|
||||
if let Some(command_list) = command_hashmap.get(&modifiers) {
|
||||
spawn_subprocess(command_list).await;
|
||||
return
|
||||
}
|
||||
|
@ -275,16 +278,16 @@ impl EventReader {
|
|||
async fn convert_axis_events(&self, event: InputEvent, event_string: &String, send_zero: bool) {
|
||||
let path = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap();
|
||||
let modifiers = self.modifiers.lock().await.clone();
|
||||
if let Some(event_hashmap) = path.modifiers.axis.get(&modifiers) {
|
||||
if let Some(event_list) = event_hashmap.get(event_string) {
|
||||
if let Some(event_hashmap) = path.combinations.axis.get(event_string) {
|
||||
if let Some(event_list) = event_hashmap.get(&modifiers) {
|
||||
self.emit_event_without_modifiers(event_list, &modifiers, event.value()).await;
|
||||
if send_zero {
|
||||
self.emit_event_without_modifiers(event_list, &modifiers, 0).await;
|
||||
}
|
||||
return
|
||||
}
|
||||
} else if let Some(command_hashmap) = path.modifiers.axis_sh.get(&modifiers) {
|
||||
if let Some(command_list) = command_hashmap.get(event_string) {
|
||||
} else if let Some(command_hashmap) = path.combinations.axis_sh.get(event_string) {
|
||||
if let Some(command_list) = command_hashmap.get(&modifiers) {
|
||||
spawn_subprocess(command_list).await;
|
||||
return
|
||||
}
|
||||
|
@ -302,8 +305,10 @@ impl EventReader {
|
|||
}
|
||||
|
||||
async fn emit_event(&self, event_list: &Vec<Key>, value: i32) {
|
||||
let path = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap();
|
||||
let mut virt_dev = self.virt_dev.lock().await;
|
||||
let modifiers = self.modifiers.lock().await.clone();
|
||||
let mut modifier_was_activated = self.modifier_was_activated.lock().await;
|
||||
let released_keys: Vec<Key> = self.released_keys(&modifiers).await;
|
||||
for key in released_keys {
|
||||
self.toggle_modifiers(key, 0).await;
|
||||
|
@ -312,13 +317,28 @@ impl EventReader {
|
|||
}
|
||||
for key in event_list {
|
||||
self.toggle_modifiers(*key, value).await;
|
||||
let virtual_event: InputEvent = InputEvent::new_now(EventType::KEY, key.code(), value);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
if path.mapped_modifiers.custom.contains(&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();
|
||||
let virtual_event: InputEvent = InputEvent::new_now(EventType::KEY, key.code(), 0);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
*modifier_was_activated = true;
|
||||
} else if value == 1 {
|
||||
*modifier_was_activated = false;
|
||||
}
|
||||
} else {
|
||||
let virtual_event: InputEvent = InputEvent::new_now(EventType::KEY, key.code(), value);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
*modifier_was_activated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn emit_default_event(&self, event: InputEvent) {
|
||||
let path = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap();
|
||||
let mut virt_dev = self.virt_dev.lock().await;
|
||||
let mut modifier_was_activated = self.modifier_was_activated.lock().await;
|
||||
match event.event_type() {
|
||||
EventType::KEY => {
|
||||
let modifiers = self.modifiers.lock().await.clone();
|
||||
|
@ -329,27 +349,53 @@ impl EventReader {
|
|||
virt_dev.keys.emit(&[virtual_event]).unwrap()
|
||||
}
|
||||
self.toggle_modifiers(Key(event.code()), event.value()).await;
|
||||
virt_dev.keys.emit(&[event]).unwrap();
|
||||
if path.mapped_modifiers.custom.contains(&Key(event.code())) {
|
||||
if event.value() == 0 && !*modifier_was_activated {
|
||||
let virtual_event: InputEvent = InputEvent::new_now(event.event_type(), event.code(), 1);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
let virtual_event: InputEvent = InputEvent::new_now(event.event_type(), event.code(), 0);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
*modifier_was_activated = true;
|
||||
} else if event.value() == 1 {
|
||||
*modifier_was_activated = false;
|
||||
}
|
||||
} else {
|
||||
virt_dev.keys.emit(&[event]).unwrap();
|
||||
*modifier_was_activated = true;
|
||||
}
|
||||
},
|
||||
EventType::RELATIVE => {
|
||||
virt_dev.axis.emit(&[event]).unwrap();
|
||||
*modifier_was_activated = true;
|
||||
},
|
||||
EventType::RELATIVE => virt_dev.axis.emit(&[event]).unwrap(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
async fn emit_event_without_modifiers(&self, event_list: &Vec<Key>, modifiers: &BTreeMap<Key, i32>, value: i32) {
|
||||
let modifiers_list = modifiers.iter()
|
||||
.filter(|(_key, value)| value == &&1)
|
||||
.collect::<HashMap<&Key, &i32>>()
|
||||
.into_keys().copied()
|
||||
.collect::<Vec<Key>>();
|
||||
async fn emit_event_without_modifiers(&self, event_list: &Vec<Key>, modifiers: &Vec<Key>, value: i32) {
|
||||
let path = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap();
|
||||
let mut virt_dev = self.virt_dev.lock().await;
|
||||
for key in modifiers_list {
|
||||
let mut modifier_was_activated = self.modifier_was_activated.lock().await;
|
||||
for key in modifiers {
|
||||
let virtual_event: InputEvent = InputEvent::new_now(EventType::KEY, key.code(), 0);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
}
|
||||
for key in event_list {
|
||||
let virtual_event: InputEvent = InputEvent::new_now(EventType::KEY, key.code(), value);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
if path.mapped_modifiers.custom.contains(&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();
|
||||
let virtual_event: InputEvent = InputEvent::new_now(EventType::KEY, key.code(), 0);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
*modifier_was_activated = true;
|
||||
} else if value == 1 {
|
||||
*modifier_was_activated = false;
|
||||
}
|
||||
} else {
|
||||
let virtual_event: InputEvent = InputEvent::new_now(EventType::KEY, key.code(), value);
|
||||
virt_dev.keys.emit(&[virtual_event]).unwrap();
|
||||
*modifier_was_activated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -366,20 +412,33 @@ impl EventReader {
|
|||
}
|
||||
|
||||
async fn toggle_modifiers(&self, key: Key, value: i32) {
|
||||
let path = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap();
|
||||
let mut modifiers = self.modifiers.lock().await;
|
||||
if modifiers.contains_key(&key) && vec![0, 1].contains(&value) {
|
||||
modifiers.insert(key, value).unwrap();
|
||||
if path.mapped_modifiers.all.contains(&key) {
|
||||
match value {
|
||||
1 => {
|
||||
modifiers.push(key);
|
||||
modifiers.sort();
|
||||
modifiers.dedup();
|
||||
},
|
||||
0 => modifiers.retain(|&x| x != key),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn released_keys(&self, modifiers: &BTreeMap<Key, i32>) -> Vec<Key> {
|
||||
async fn released_keys(&self, modifiers: &Vec<Key>) -> Vec<Key> {
|
||||
let path = self.config.get(&get_active_window(&self.current_desktop, &self.config).await).unwrap();
|
||||
let mut released_keys: Vec<Key> = Vec::new();
|
||||
if let Some(event_hashmap) = path.modifiers.keys.get(&modifiers) {
|
||||
event_hashmap.iter().for_each(|(_modifiers, event_list)| released_keys.extend(event_list));
|
||||
for (_key, hashmap) in path.combinations.keys.iter() {
|
||||
if let Some(event_list) = hashmap.get(modifiers) {
|
||||
released_keys.extend(event_list);
|
||||
}
|
||||
}
|
||||
if let Some(event_hashmap) = path.modifiers.axis.get(&modifiers) {
|
||||
event_hashmap.iter().for_each(|(_modifiers, event_list)| released_keys.extend(event_list));
|
||||
for (_key, hashmap) in path.combinations.axis.iter() {
|
||||
if let Some(event_list) = hashmap.get(modifiers) {
|
||||
released_keys.extend(event_list);
|
||||
}
|
||||
}
|
||||
released_keys
|
||||
}
|
||||
|
@ -460,3 +519,6 @@ async fn spawn_subprocess(command_list: &Vec<String>) {
|
|||
.expect("Failed to run command.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use std::{collections::{HashMap, BTreeMap}, sync::Arc, path::Path, process::Command, env};
|
||||
use std::{collections::HashMap, sync::Arc, path::Path, process::Command, env};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio_stream::StreamExt;
|
||||
|
@ -16,7 +16,7 @@ pub async fn start_monitoring_udev(config_files: Vec<Config>, mut tasks: Vec<Joi
|
|||
).unwrap();
|
||||
while let Some(Ok(event)) = monitor.next().await {
|
||||
if is_mapped(&event.device(), &config_files) {
|
||||
println!("---------------------\nReinitializing...\n");
|
||||
println!("---------------------\n\nReinitializing...\n");
|
||||
for task in &tasks {
|
||||
task.abort();
|
||||
}
|
||||
|
@ -27,19 +27,8 @@ pub async fn start_monitoring_udev(config_files: Vec<Config>, mut tasks: Vec<Joi
|
|||
}
|
||||
|
||||
pub fn launch_tasks(config_files: &Vec<Config>, tasks: &mut Vec<JoinHandle<()>>) {
|
||||
let modifiers: Arc<Mutex<BTreeMap<Key, i32>>> = Arc::new (
|
||||
Mutex::new (
|
||||
BTreeMap::from ([
|
||||
(Key::KEY_LEFTSHIFT, 0),
|
||||
(Key::KEY_LEFTCTRL, 0),
|
||||
(Key::KEY_LEFTALT, 0),
|
||||
(Key::KEY_RIGHTSHIFT, 0),
|
||||
(Key::KEY_RIGHTCTRL, 0),
|
||||
(Key::KEY_RIGHTALT, 0),
|
||||
(Key::KEY_LEFTMETA, 0)
|
||||
])
|
||||
)
|
||||
);
|
||||
let modifiers: Arc<Mutex<Vec<Key>>> = Arc::new(Mutex::new(Default::default()));
|
||||
let modifier_was_activated: Arc<Mutex<bool>> = Arc::new(Mutex::new(true));
|
||||
let current_desktop: Option<String> = match (env::var("XDG_SESSION_TYPE"), env::var("XDG_CURRENT_DESKTOP")) {
|
||||
(Ok(session), Ok(desktop)) if session == "wayland".to_string() && vec!["Hyprland".to_string(), "sway".to_string()].contains(&desktop) => {
|
||||
println!(">> Running on {}, active window detection enabled.\n", desktop);
|
||||
|
@ -68,7 +57,7 @@ pub fn launch_tasks(config_files: &Vec<Config>, tasks: &mut Vec<JoinHandle<()>>)
|
|||
};
|
||||
let user_has_access = match Command::new("groups").output() {
|
||||
Ok(groups) if std::str::from_utf8(&groups.stdout.as_slice()).unwrap().contains("input") => {
|
||||
println!("Running with evdev permissions.\nScanning for event devices with a matching config file...\n"); //todo: make the config dir customizable through env variable
|
||||
println!("Running with evdev permissions.\nScanning for event devices with a matching config file...\n");
|
||||
true
|
||||
},
|
||||
Ok(groups) if std::str::from_utf8(&groups.stdout.as_slice()).unwrap().contains("root") => {
|
||||
|
@ -105,7 +94,7 @@ pub fn launch_tasks(config_files: &Vec<Config>, tasks: &mut Vec<JoinHandle<()>>)
|
|||
let event_device = device.0.as_path().to_str().unwrap().to_string();
|
||||
if !config_map.is_empty() {
|
||||
let stream = Arc::new(Mutex::new(get_event_stream(Path::new(&event_device), config_map.clone())));
|
||||
let reader = EventReader::new(config_map.clone(), stream, modifiers.clone(), current_desktop.clone());
|
||||
let reader = EventReader::new(config_map.clone(), stream, modifiers.clone(), modifier_was_activated.clone(), current_desktop.clone());
|
||||
tasks.push(tokio::spawn(start_reader(reader)));
|
||||
devices_found += 1
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue