From 158f15a216de1e99034c3179010bfd48365698a1 Mon Sep 17 00:00:00 2001 From: Sawyer McLane Date: Tue, 24 Sep 2024 09:10:48 -0600 Subject: [PATCH] Move rdev key, button to unified "InputKey" --- src/app.rs | 4 +- src/listener.rs | 336 ++++++++++++++++++++++++------------------------ 2 files changed, 169 insertions(+), 171 deletions(-) diff --git a/src/app.rs b/src/app.rs index 707e550..82c789b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -407,9 +407,9 @@ impl MantleApp { ui.separator(); ui.label("Shortcut"); }); - for shortcut in self.input_listener.get_active_items() { + for shortcut in self.input_listener.get_active_shortcuts() { ui.horizontal(|ui| { - ui.label(format!("{:?}", shortcut.name)); + ui.label(format!("{:?}", shortcut.shortcut)); ui.separator(); ui.label(format!("{:?}", shortcut.callback_name)); }); diff --git a/src/listener.rs b/src/listener.rs index d7e5b47..90d55bf 100644 --- a/src/listener.rs +++ b/src/listener.rs @@ -1,14 +1,71 @@ use log::error; use rdev::{listen, Button, Event, EventType, Key}; -use std::collections::HashSet; -use std::fmt::{Debug, Display, Formatter, Result}; +use std::cmp::Ordering; +use std::collections::BTreeSet; +use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; use std::hash::{Hash, Hasher}; use std::sync::{Arc, Mutex}; use std::thread::{spawn, JoinHandle}; use std::time::Instant; type BackgroundCallback = Box; -type ShortcutCallback = Arc) + Send + Sync>; +type ShortcutCallback = Arc) + Send + Sync>; + +#[derive(Clone, Copy, Debug)] +pub enum InputKey { + Key(Key), + Button(Button), +} + +impl PartialEq for InputKey { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (InputKey::Key(k1), InputKey::Key(k2)) => k1 == k2, + (InputKey::Button(b1), InputKey::Button(b2)) => b1 == b2, + _ => false, + } + } +} + +impl Eq for InputKey {} + +impl Hash for InputKey { + fn hash(&self, state: &mut H) { + std::mem::discriminant(self).hash(state); + match self { + InputKey::Key(k) => k.hash(state), + InputKey::Button(b) => b.hash(state), + } + } +} + +impl Ord for InputKey { + fn cmp(&self, other: &Self) -> Ordering { + match (self, other) { + (InputKey::Key(k1), InputKey::Key(k2)) => format!("{:?}", k1).cmp(&format!("{:?}", k2)), + (InputKey::Button(b1), InputKey::Button(b2)) => { + format!("{:?}", b1).cmp(&format!("{:?}", b2)) + } + (InputKey::Key(_), InputKey::Button(_)) => Ordering::Less, + (InputKey::Button(_), InputKey::Key(_)) => Ordering::Greater, + } + } +} + +impl PartialOrd for InputKey { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Display for InputKey { + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + match self { + InputKey::Key(k) => write!(f, "{:?}", k), + InputKey::Button(b) => write!(f, "{:?}", b), + } + } +} #[derive(Clone, Copy)] pub struct MousePosition { @@ -16,42 +73,34 @@ pub struct MousePosition { pub y: i32, } -#[derive(Clone, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct KeyboardShortcut { - pub keys: HashSet, + pub keys: BTreeSet, } #[derive(Clone)] pub struct KeyboardShortcutCallback { pub shortcut: KeyboardShortcut, pub callback: ShortcutCallback, - pub name: String, pub callback_name: String, } -impl Hash for KeyboardShortcut { - fn hash(&self, state: &mut H) { - for key in &self.keys { - key.hash(state); - } - } -} - impl Debug for KeyboardShortcut { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - write!(f, "KeyboardShortcut({:?})", self.keys) + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + let keys: Vec = self.keys.iter().map(|k| format!("{}", k)).collect(); + write!(f, "KeyboardShortcut({})", keys.join(" + ")) } } impl Display for KeyboardShortcut { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - let keys: Vec = self.keys.iter().map(|k| format!("{:?}", k)).collect(); + fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { + let keys: Vec = self.keys.iter().map(|k| format!("{}", k)).collect(); write!(f, "{}", keys.join(" + ")) } } impl KeyboardShortcut { - fn is_matched(&self, keys_pressed: &HashSet) -> bool { + fn is_matched(&self, keys_pressed: &BTreeSet) -> bool { self.keys.is_subset(keys_pressed) } } @@ -59,13 +108,10 @@ impl KeyboardShortcut { pub struct SharedInputState { last_mouse_position: Mutex>, last_click_time: Mutex>, - button_pressed: Mutex>, - last_button_pressed: Mutex>, - keys_pressed: Mutex>, - last_keys_pressed: Mutex>, + keys_pressed: Mutex>, callbacks: Mutex>, shortcuts: Mutex>, - active_shortcuts: Mutex>, + active_shortcuts: Mutex>, } impl SharedInputState { @@ -73,130 +119,94 @@ impl SharedInputState { SharedInputState { last_mouse_position: Mutex::new(None), last_click_time: Mutex::new(None), - button_pressed: Mutex::new(None), - last_button_pressed: Mutex::new(None), - keys_pressed: Mutex::new(HashSet::new()), - last_keys_pressed: Mutex::new(HashSet::new()), + keys_pressed: Mutex::new(BTreeSet::new()), callbacks: Mutex::new(Vec::new()), shortcuts: Mutex::new(Vec::new()), - active_shortcuts: Mutex::new(HashSet::new()), + active_shortcuts: Mutex::new(BTreeSet::new()), + } + } + + fn update_input_key_press(&self, input_key: InputKey) { + if let Ok(mut keys) = self.keys_pressed.lock() { + keys.insert(input_key); + } else { + error!("Failed to lock keys_pressed mutex"); + } + } + + fn update_input_key_release(&self, input_key: InputKey) { + if let Ok(mut keys) = self.keys_pressed.lock() { + keys.remove(&input_key); + } else { + error!("Failed to lock keys_pressed mutex"); } } fn update_mouse_position(&self, x: i32, y: i32) { - match self.last_mouse_position.lock() { - Ok(mut pos) => { - *pos = Some(MousePosition { x, y }); - } - Err(e) => { - error!("Failed to lock last_mouse_position mutex: {}", e); - } + if let Ok(mut pos) = self.last_mouse_position.lock() { + *pos = Some(MousePosition { x, y }); + } else { + error!("Failed to lock last_mouse_position mutex"); } } fn update_button_press(&self, button: Button) { - if let Err(e) = self.button_pressed.lock().map(|mut pressed| { - *pressed = Some(button); - }) { - error!("Failed to lock button_pressed mutex: {}", e); - } + self.update_input_key_press(InputKey::Button(button)); - if let Err(e) = self.last_click_time.lock().map(|mut time| { + if let Ok(mut time) = self.last_click_time.lock() { *time = Some(Instant::now()); - }) { - error!("Failed to lock last_click_time mutex: {}", e); + } else { + error!("Failed to lock last_click_time mutex"); } + } - if let Err(e) = self.last_button_pressed.lock().map(|mut last| { - *last = Some(button); - }) { - error!("Failed to lock last_button_pressed mutex: {}", e); - } + fn update_button_release(&self, button: Button) { + self.update_input_key_release(InputKey::Button(button)); } fn update_key_press(&self, key: Key) { - match self.keys_pressed.lock() { - Ok(mut keys) => { - keys.insert(key); - - if let Ok(mut last) = self.last_keys_pressed.lock() { - *last = keys.clone(); - } else { - error!("Failed to lock last_keys_pressed mutex"); - } - } - Err(e) => { - error!("Failed to lock keys_pressed mutex: {}", e); - } - } + self.update_input_key_press(InputKey::Key(key)); } fn update_key_release(&self, key: Key) { - match self.keys_pressed.lock() { - Ok(mut keys) => { - keys.remove(&key); - } - Err(e) => { - error!("Failed to lock keys_pressed mutex: {}", e); - } - } - } - - fn update_button_release(&self) { - if let Err(e) = self.button_pressed.lock().map(|mut pressed| { - *pressed = None; - }) { - error!("Failed to lock button_pressed mutex: {}", e); - } + self.update_input_key_release(InputKey::Key(key)); } fn execute_callbacks(&self, event: &Event) { - match self.callbacks.lock() { - Ok(callbacks) => { - for callback in callbacks.iter() { - callback(event.clone()); - } - } - Err(e) => { - error!("Failed to lock callbacks mutex: {}", e); + if let Ok(callbacks) = self.callbacks.lock() { + for callback in callbacks.iter() { + callback(event.clone()); } + } else { + error!("Failed to lock callbacks mutex"); } } fn add_callback(&self, callback: BackgroundCallback) { - match self.callbacks.lock() { - Ok(mut callbacks) => { - callbacks.push(callback); - } - Err(e) => { - error!("Failed to lock callbacks mutex: {}", e); - } + if let Ok(mut callbacks) = self.callbacks.lock() { + callbacks.push(callback); + } else { + error!("Failed to lock callbacks mutex"); } } - fn add_shortcut_callback(&self, shortcut: KeyboardShortcut, callback: F) - where - F: Fn(HashSet) + Send + Sync + 'static, + fn add_shortcut_callback( + &self, + shortcut: KeyboardShortcut, + callback: F, + callback_name: String, + ) where + F: Fn(BTreeSet) + Send + Sync + 'static, { let callback = Arc::new(callback); - match self.shortcuts.lock() { - Ok(mut shortcuts) => { - let keys = shortcut - .keys - .iter() - .map(|k| format!("{:?}", k)) - .collect::>(); - let name = format!("{}", shortcut); - shortcuts.push(KeyboardShortcutCallback { - shortcut, - callback, - name, - callback_name: format!("{:?}", keys), - }); - } - Err(e) => { - error!("Failed to lock shortcuts mutex: {}", e); - } + if let Ok(mut shortcuts) = self.shortcuts.lock() { + shortcuts.push(KeyboardShortcutCallback { + shortcut, + callback, + callback_name, + }); + } else { + error!("Failed to lock shortcuts mutex"); } } @@ -205,7 +215,7 @@ impl SharedInputState { Ok(guard) => guard.clone(), Err(e) => { error!("Failed to lock keys_pressed mutex: {}", e); - HashSet::new() + BTreeSet::new() } }; @@ -217,11 +227,11 @@ impl SharedInputState { } }; - let active_shortcuts = match self.active_shortcuts.lock() { + let mut active_shortcuts = match self.active_shortcuts.lock() { Ok(guard) => guard.clone(), Err(e) => { error!("Failed to lock active_shortcuts mutex: {}", e); - HashSet::new() + BTreeSet::new() } }; @@ -231,22 +241,18 @@ impl SharedInputState { // Shortcut is newly activated (shortcut.callback)(keys_pressed.clone()); - // Add to active_shortcuts - if let Ok(mut guard) = self.active_shortcuts.lock() { - guard.insert(shortcut.shortcut.clone()); - } else { - error!("Failed to lock active_shortcuts mutex"); - } + active_shortcuts.insert(shortcut.shortcut.clone()); } } else { - // Remove from active_shortcuts if present - if let Ok(mut guard) = self.active_shortcuts.lock() { - guard.remove(&shortcut.shortcut); - } else { - error!("Failed to lock active_shortcuts mutex"); - } + active_shortcuts.remove(&shortcut.shortcut); } } + + if let Ok(mut guard) = self.active_shortcuts.lock() { + *guard = active_shortcuts; + } else { + error!("Failed to lock active_shortcuts mutex"); + } } } @@ -281,42 +287,30 @@ impl InputListener { } } - pub fn get_last_button_pressed(&self) -> Option