From 56a94b2dee8193d2b9d52130631460f4a2834d1b Mon Sep 17 00:00:00 2001 From: Tait Hoyem Date: Wed, 23 Feb 2022 13:05:49 -0700 Subject: [PATCH] New Hotkey struct; compiling --- src/config.rs | 237 ++++++++++++++++++++++++++------------------------ src/daemon.rs | 170 +++++++----------------------------- 2 files changed, 155 insertions(+), 252 deletions(-) diff --git a/src/config.rs b/src/config.rs index 3ad0d98..a95cd9e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -50,16 +50,16 @@ impl fmt::Display for Error { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Hotkey { - pub mode: String, - pub keysym: evdev::Key, + pub mode: Option, + pub keysym: rdev::Key, pub modifiers: Vec, pub command: String, pub consume: bool, } -#[derive(Debug, PartialEq, Copy, Clone)] +#[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)] // TODO: make the commented-out modifiers available pub enum Modifier { Super, @@ -78,7 +78,7 @@ pub enum Modifier { } impl Hotkey { - pub fn new(mode: String, keysym: evdev::Key, modifiers: Vec, command: String, consume: bool) -> Self { + pub fn new(mode: Option, keysym: rdev::Key, modifiers: Vec, command: String, consume: bool) -> Self { Hotkey { mode, keysym, modifiers, command, consume } } } @@ -96,108 +96,113 @@ fn load_file_contents(path: path::PathBuf) -> Result { } fn parse_contents(contents: String) -> Result, Error> { - let key_to_evdev_key: HashMap<&str, evdev::Key> = HashMap::from([ - ("q", evdev::Key::KEY_Q), - ("w", evdev::Key::KEY_W), - ("e", evdev::Key::KEY_E), - ("r", evdev::Key::KEY_R), - ("t", evdev::Key::KEY_T), - ("y", evdev::Key::KEY_Y), - ("u", evdev::Key::KEY_U), - ("i", evdev::Key::KEY_I), - ("o", evdev::Key::KEY_O), - ("p", evdev::Key::KEY_P), - ("a", evdev::Key::KEY_A), - ("s", evdev::Key::KEY_S), - ("d", evdev::Key::KEY_D), - ("f", evdev::Key::KEY_F), - ("g", evdev::Key::KEY_G), - ("h", evdev::Key::KEY_H), - ("j", evdev::Key::KEY_J), - ("k", evdev::Key::KEY_K), - ("l", evdev::Key::KEY_L), - ("z", evdev::Key::KEY_Z), - ("x", evdev::Key::KEY_X), - ("c", evdev::Key::KEY_C), - ("v", evdev::Key::KEY_V), - ("b", evdev::Key::KEY_B), - ("n", evdev::Key::KEY_N), - ("m", evdev::Key::KEY_M), - ("1", evdev::Key::KEY_1), - ("2", evdev::Key::KEY_2), - ("3", evdev::Key::KEY_3), - ("4", evdev::Key::KEY_4), - ("5", evdev::Key::KEY_5), - ("6", evdev::Key::KEY_6), - ("7", evdev::Key::KEY_7), - ("8", evdev::Key::KEY_8), - ("9", evdev::Key::KEY_9), - ("0", evdev::Key::KEY_0), - ("escape", evdev::Key::KEY_ESC), - ("delete", evdev::Key::KEY_DELETE), - ("backspace", evdev::Key::KEY_BACKSPACE), - ("return", evdev::Key::KEY_ENTER), - ("enter", evdev::Key::KEY_ENTER), - ("tab", evdev::Key::KEY_TAB), - ("space", evdev::Key::KEY_SPACE), - ("minus", evdev::Key::KEY_MINUS), - ("-", evdev::Key::KEY_MINUS), - ("equal", evdev::Key::KEY_EQUAL), - ("=", evdev::Key::KEY_EQUAL), - ("grave", evdev::Key::KEY_GRAVE), - ("`", evdev::Key::KEY_GRAVE), - ("print", evdev::Key::KEY_SYSRQ), - ("volumeup", evdev::Key::KEY_VOLUMEUP), - ("xf86audioraisevolume", evdev::Key::KEY_VOLUMEUP), - ("volumedown", evdev::Key::KEY_VOLUMEDOWN), - ("xf86audiolowervolume", evdev::Key::KEY_VOLUMEDOWN), - ("mute", evdev::Key::KEY_MUTE), - ("xf86audiomute", evdev::Key::KEY_MUTE), - ("brightnessup", evdev::Key::KEY_BRIGHTNESSUP), - ("brightnessdown", evdev::Key::KEY_BRIGHTNESSDOWN), - (",", evdev::Key::KEY_COMMA), - ("comma", evdev::Key::KEY_COMMA), - (".", evdev::Key::KEY_DOT), - ("dot", evdev::Key::KEY_DOT), - ("/", evdev::Key::KEY_SLASH), - ("slash", evdev::Key::KEY_SLASH), - ("backslash", evdev::Key::KEY_BACKSLASH), - ("leftbrace", evdev::Key::KEY_LEFTBRACE), - ("[", evdev::Key::KEY_LEFTBRACE), - ("rightbrace", evdev::Key::KEY_RIGHTBRACE), - ("]", evdev::Key::KEY_RIGHTBRACE), - (";", evdev::Key::KEY_SEMICOLON), - ("semicolon", evdev::Key::KEY_SEMICOLON), - ("'", evdev::Key::KEY_APOSTROPHE), - ("apostrophe", evdev::Key::KEY_APOSTROPHE), - ("left", evdev::Key::KEY_LEFT), - ("right", evdev::Key::KEY_RIGHT), - ("up", evdev::Key::KEY_UP), - ("down", evdev::Key::KEY_DOWN), - ("f1", evdev::Key::KEY_F1), - ("f2", evdev::Key::KEY_F2), - ("f3", evdev::Key::KEY_F3), - ("f4", evdev::Key::KEY_F4), - ("f5", evdev::Key::KEY_F5), - ("f6", evdev::Key::KEY_F6), - ("f7", evdev::Key::KEY_F7), - ("f8", evdev::Key::KEY_F8), - ("f9", evdev::Key::KEY_F9), - ("f10", evdev::Key::KEY_F10), - ("f11", evdev::Key::KEY_F11), - ("f12", evdev::Key::KEY_F12), - ("f13", evdev::Key::KEY_F13), - ("f14", evdev::Key::KEY_F14), - ("f15", evdev::Key::KEY_F15), - ("f16", evdev::Key::KEY_F16), - ("f17", evdev::Key::KEY_F17), - ("f18", evdev::Key::KEY_F18), - ("f19", evdev::Key::KEY_F19), - ("f20", evdev::Key::KEY_F20), - ("f21", evdev::Key::KEY_F21), - ("f22", evdev::Key::KEY_F22), - ("f23", evdev::Key::KEY_F23), - ("f24", evdev::Key::KEY_F24), + let key_to_evdev_key: HashMap<&str, rdev::Key> = HashMap::from([ + ("q", rdev::Key::KeyQ), + ("w", rdev::Key::KeyW), + ("e", rdev::Key::KeyE), + ("r", rdev::Key::KeyR), + ("t", rdev::Key::KeyT), + ("y", rdev::Key::KeyY), + ("u", rdev::Key::KeyU), + ("i", rdev::Key::KeyI), + ("o", rdev::Key::KeyO), + ("p", rdev::Key::KeyP), + ("a", rdev::Key::KeyA), + ("s", rdev::Key::KeyS), + ("d", rdev::Key::KeyD), + ("f", rdev::Key::KeyF), + ("g", rdev::Key::KeyG), + ("h", rdev::Key::KeyH), + ("j", rdev::Key::KeyJ), + ("k", rdev::Key::KeyK), + ("l", rdev::Key::KeyL), + ("z", rdev::Key::KeyZ), + ("x", rdev::Key::KeyX), + ("c", rdev::Key::KeyC), + ("v", rdev::Key::KeyV), + ("b", rdev::Key::KeyB), + ("n", rdev::Key::KeyN), + ("m", rdev::Key::KeyM), + ("1", rdev::Key::Num1), + ("2", rdev::Key::Num2), + ("3", rdev::Key::Num3), + ("4", rdev::Key::Num4), + ("5", rdev::Key::Num5), + ("6", rdev::Key::Num6), + ("7", rdev::Key::Num7), + ("8", rdev::Key::Num8), + ("9", rdev::Key::Num9), + ("0", rdev::Key::Num0), + ("escape", rdev::Key::Escape), + ("delete", rdev::Key::Delete), + ("backspace", rdev::Key::Backspace), + ("return", rdev::Key::Return), + ("enter", rdev::Key::Return), + ("tab", rdev::Key::Tab), + ("space", rdev::Key::Space), + ("minus", rdev::Key::Minus), + ("-", rdev::Key::Minus), + ("equal", rdev::Key::Equal), + ("=", rdev::Key::Equal), + ("grave", rdev::Key::BackQuote), + ("`", rdev::Key::BackQuote), + ("print", rdev::Key::PrintScreen), + /* + ("volumeup", rdev::Key::KEY_VOLUMEUP), + ("xf86audioraisevolume", rdev::Key::KEY_VOLUMEUP), + ("volumedown", rdev::Key::KEY_VOLUMEDOWN), + ("xf86audiolowervolume", rdev::Key::KEY_VOLUMEDOWN), + ("mute", rdev::Key::KEY_MUTE), + ("xf86audiomute", rdev::Key::KEY_MUTE), + ("brightnessup", rdev::Key::KEY_BRIGHTNESSUP), + ("brightnessdown", rdev::Key::KEY_BRIGHTNESSDOWN), + TODO: find ways to accept xf86 keys + */ + (",", rdev::Key::Comma), + ("comma", rdev::Key::Comma), + (".", rdev::Key::Dot), + ("dot", rdev::Key::Dot), + ("/", rdev::Key::Slash), + ("slash", rdev::Key::Slash), + ("backslash", rdev::Key::IntlBackslash), + ("leftbrace", rdev::Key::LeftBracket), + ("[", rdev::Key::LeftBracket), + ("rightbrace", rdev::Key::RightBracket), + ("]", rdev::Key::RightBracket), + (";", rdev::Key::SemiColon), + ("semicolon", rdev::Key::SemiColon), + ("'", rdev::Key::Quote), + ("apostrophe", rdev::Key::Quote), + ("left", rdev::Key::LeftArrow), + ("right", rdev::Key::RightArrow), + ("up", rdev::Key::UpArrow), + ("down", rdev::Key::DownArrow), + ("f1", rdev::Key::F1), + ("f2", rdev::Key::F2), + ("f3", rdev::Key::F3), + ("f4", rdev::Key::F4), + ("f5", rdev::Key::F5), + ("f6", rdev::Key::F6), + ("f7", rdev::Key::F7), + ("f8", rdev::Key::F8), + ("f9", rdev::Key::F9), + ("f10", rdev::Key::F10), + ("f11", rdev::Key::F11), + ("f12", rdev::Key::F12), +/* + ("f13", rdev::Key::F13), + ("f14", rdev::Key::F14), + ("f15", rdev::Key::F15), + ("f16", rdev::Key::F16), + ("f17", rdev::Key::F17), + ("f18", rdev::Key::F18), + ("f19", rdev::Key::F19), + ("f20", rdev::Key::F20), + ("f21", rdev::Key::F21), + ("f22", rdev::Key::F22), + ("f23", rdev::Key::F23), + ("f24", rdev::Key::F24), +*/ ]); let mod_to_mod_enum: HashMap<&str, Modifier> = HashMap::from([ @@ -306,9 +311,9 @@ fn parse_contents(contents: String) -> Result, Error> { fn parse_keybind( line: &str, line_nr: u32, - key_to_evdev_key: &HashMap<&str, evdev::Key>, + key_to_evdev_key: &HashMap<&str, rdev::Key>, mod_to_mod_enum: &HashMap<&str, Modifier>, -) -> Result<(String, evdev::Key, Vec, bool), Error> { +) -> Result<(Option, rdev::Key, Vec, bool), Error> { let line = line.split('#').next().unwrap(); let tokens: Vec = line.split('+').map(|s| s.trim().to_lowercase()).filter(|s| s != "_").collect(); @@ -343,15 +348,19 @@ fn parse_keybind( .map(|s| s.to_string()) .collect::>() .len() == 1 { true } else { false }; - let mode = tokens + let mode = match tokens .iter() .filter(|s| s.starts_with("[") && s.ends_with("]")) .map(|s| s.replace(&['[', ']'][..], "")) .collect::>() - .get(0) - .unwrap_or(&"".to_string()) - .to_string(); - let mod_index = if mode.is_empty() { 0 } else { 1 }; + .get(0) { + Some(z) => Some(z.to_string()), + None => { + log::trace!("No mode specified"); + None + } + }; + let mod_index = if mode.is_some() { 1 } else { 0 }; let modifiers: Vec = tokens[mod_index..(tokens.len() - 1)] .iter() diff --git a/src/daemon.rs b/src/daemon.rs index f893ca9..42a08ab 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -1,10 +1,24 @@ use clap::{arg, App}; -use evdev::{AttributeSet, Device, Key}; +use rdev::{ + Event, + EventType::{ + KeyPress, + KeyRelease, + }, + Key, +}; use nix::unistd::{Group, Uid}; use once_cell::sync::OnceCell; use std::{ thread, - sync::Mutex, + sync::{ + Mutex, + mpsc::{ + sync_channel, + SyncSender, + Receiver + }, + }, collections::HashMap, env, fs, io::prelude::*, @@ -26,8 +40,8 @@ pub struct LastHotkey { ran_at: SystemTime, } -static MODE_SOCK: &str = "/tmp/odilia-mode.sock"; static STATE_MODE: OnceCell> = OnceCell::new(); +static MODE_SOCK: &str = "/tmp/odilia-mode.sock"; fn listen_for_mode_change() -> std::io::Result<()> { log::trace!("Mode change listener started!"); @@ -118,20 +132,6 @@ pub fn key_listener() { exit(1); } - log::trace!("Attempting to find all keyboard file descriptors."); - let mut keyboard_devices: Vec = Vec::new(); - for (_, device) in evdev::enumerate().enumerate() { - if check_keyboard(&device) { - keyboard_devices.push(device); - } - } - - if keyboard_devices.is_empty() { - log::error!("No valid keyboard device was detected!"); - exit(1); - } - log::debug!("{} Keyboard device(s) detected.", keyboard_devices.len()); - let hotkeys = match config::load(config_file_path) { Err(e) => { log::error!("Config Error: {}", e); @@ -145,34 +145,24 @@ pub fn key_listener() { } let modifiers_map: HashMap = HashMap::from([ - (Key::KEY_LEFTMETA, config::Modifier::Super), - (Key::KEY_RIGHTMETA, config::Modifier::Super), - (Key::KEY_LEFTMETA, config::Modifier::Super), - (Key::KEY_RIGHTMETA, config::Modifier::Super), - (Key::KEY_LEFTALT, config::Modifier::Alt), - (Key::KEY_RIGHTALT, config::Modifier::Alt), - (Key::KEY_LEFTCTRL, config::Modifier::Control), - (Key::KEY_RIGHTCTRL, config::Modifier::Control), - (Key::KEY_LEFTSHIFT, config::Modifier::Shift), - (Key::KEY_RIGHTSHIFT, config::Modifier::Shift), + (Key::MetaLeft, config::Modifier::Super), + (Key::MetaRight, config::Modifier::Super), + (Key::Alt, config::Modifier::Alt), + (Key::AltGr, config::Modifier::Alt), + (Key::ControlLeft, config::Modifier::Control), + (Key::ControlRight, config::Modifier::Control), + (Key::ShiftLeft, config::Modifier::Shift), + (Key::ShiftRight, config::Modifier::Shift), ]); - let repeat_cooldown_duration: u128; - if args.is_present("cooldown") { - repeat_cooldown_duration = args.value_of("cooldown").unwrap().parse::().unwrap(); - } else { - repeat_cooldown_duration = 250; - } - - let mut key_states: Vec> = Vec::new(); let mut possible_hotkeys: Vec = Vec::new(); let default_test_modifier: Vec = vec![config::Modifier::Super]; let mut last_hotkey = LastHotkey { // just a dummy last_hotkey so I don't need to mess with Option. TODO: Change this to Option hotkey: config::Hotkey::new( - "".to_string(), - evdev::Key::KEY_A, + Some("".to_string()), + Key::KeyA, default_test_modifier, String::from("notify-send \"it works\""), false, @@ -181,97 +171,9 @@ pub fn key_listener() { }; loop { - for device in &keyboard_devices { - key_states.push(device.get_key_state().unwrap()); - } - // check if a hotkey in hotkeys is pressed - for state in &key_states { - for hotkey in &hotkeys { - if hotkey.modifiers.len() < state.iter().count() { - possible_hotkeys.push(hotkey.clone()); - } else { - continue; - } - } - - if possible_hotkeys.is_empty() { - continue; - } - - let mut state_modifiers: Vec = Vec::new(); - let mut state_keysyms: Vec = Vec::new(); - let state_mode: String = match STATE_MODE.get() { - Some(mm) => { - match mm.lock() { - Ok(m) => m.to_string(), - Err(e) => { - log::error!("Could not lock state_mode within main event loop."); - "".to_string() - }, - } - } - None => { - log::error!("Could not get STATE_MODE in main event loop."); - "".to_string() - } - }; - for key in state.iter() { - if let Some(modifier) = modifiers_map.get(&key) { - state_modifiers.push(*modifier); - } else { - state_keysyms.push(key); - } - } - log::debug!("state_modifiers: {:#?}", state_modifiers); - log::debug!("state_keysyms: {:#?}", state_keysyms); - log::debug!("state_mode: {:#?}", state_mode); - log::debug!("hotkey: {:#?}", possible_hotkeys); - for hotkey in &possible_hotkeys { - // this should check if state_modifiers and hotkey.modifiers have the same elements - if state_modifiers.iter().all(|x| hotkey.modifiers.contains(x)) - && state_modifiers.len() == hotkey.modifiers.len() - && state_keysyms.contains(&hotkey.keysym) - && state_mode == hotkey.mode - { - if last_hotkey.hotkey == hotkey.clone() { - let time_since_ran_at = - match SystemTime::now().duration_since(last_hotkey.ran_at) { - Ok(n) => n.as_millis(), - Err(e) => { - log::error!("Error: {:#?}", e); - exit(1); - } - }; - if time_since_ran_at <= repeat_cooldown_duration { - log::error!( - "In cooldown: {:#?} \nTime Remaining: {:#?}ms", - hotkey, - repeat_cooldown_duration - time_since_ran_at - ); - continue; - } else { - last_hotkey = - LastHotkey { hotkey: hotkey.clone(), ran_at: SystemTime::now() }; - } - } else { - last_hotkey = - LastHotkey { hotkey: hotkey.clone(), ran_at: SystemTime::now() }; - } - - log::info!("Hotkey pressed: {:#?}", hotkey); - if let Err(e) = sock_send(&hotkey.command) { - log::error!("Failed to send command over IPC."); - log::error!("Is swhks running?"); - log::error!("{:#?}", e) - } - } - } - } - - key_states.clear(); - possible_hotkeys.clear(); - sleep(Duration::from_millis(10)); // without this, swhkd will start to chew through your cpu. + // TODO } + } pub fn main() { @@ -279,6 +181,7 @@ pub fn main() { let key_handler = thread::spawn(|| { key_listener(); }); + /* let mode_updater = thread::spawn(|| { let res = listen_for_mode_change(); match res { @@ -286,8 +189,9 @@ pub fn main() { Err(e) => log::error!("Error setting up mode socket: {}", e), } }); + */ log::trace!("Threads set up"); - mode_updater.join().unwrap(); + //mode_updater.join().unwrap(); key_handler.join().unwrap(); } @@ -309,16 +213,6 @@ pub fn permission_check() { } } -pub fn check_keyboard(device: &Device) -> bool { - if device.supported_keys().map_or(false, |keys| keys.contains(Key::KEY_ENTER)) { - log::debug!("{} is a keyboard.", device.name().unwrap(),); - true - } else { - log::trace!("{} is not a keyboard.", device.name().unwrap(),); - false - } -} - pub fn set_flags() -> App<'static> { let app = App::new("swhkd") .version(env!("CARGO_PKG_VERSION"))