New Hotkey struct; compiling

main
Tait Hoyem 2 years ago
parent 4b80557af0
commit 56a94b2dee

@ -50,16 +50,16 @@ impl fmt::Display for Error {
} }
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Hotkey { pub struct Hotkey {
pub mode: String, pub mode: Option<String>,
pub keysym: evdev::Key, pub keysym: rdev::Key,
pub modifiers: Vec<Modifier>, pub modifiers: Vec<Modifier>,
pub command: String, pub command: String,
pub consume: bool, pub consume: bool,
} }
#[derive(Debug, PartialEq, Copy, Clone)] #[derive(Debug, PartialEq, Copy, Clone, Hash, Eq)]
// TODO: make the commented-out modifiers available // TODO: make the commented-out modifiers available
pub enum Modifier { pub enum Modifier {
Super, Super,
@ -78,7 +78,7 @@ pub enum Modifier {
} }
impl Hotkey { impl Hotkey {
pub fn new(mode: String, keysym: evdev::Key, modifiers: Vec<Modifier>, command: String, consume: bool) -> Self { pub fn new(mode: Option<String>, keysym: rdev::Key, modifiers: Vec<Modifier>, command: String, consume: bool) -> Self {
Hotkey { mode, keysym, modifiers, command, consume } Hotkey { mode, keysym, modifiers, command, consume }
} }
} }
@ -96,108 +96,113 @@ fn load_file_contents(path: path::PathBuf) -> Result<String, Error> {
} }
fn parse_contents(contents: String) -> Result<Vec<Hotkey>, Error> { fn parse_contents(contents: String) -> Result<Vec<Hotkey>, Error> {
let key_to_evdev_key: HashMap<&str, evdev::Key> = HashMap::from([ let key_to_evdev_key: HashMap<&str, rdev::Key> = HashMap::from([
("q", evdev::Key::KEY_Q), ("q", rdev::Key::KeyQ),
("w", evdev::Key::KEY_W), ("w", rdev::Key::KeyW),
("e", evdev::Key::KEY_E), ("e", rdev::Key::KeyE),
("r", evdev::Key::KEY_R), ("r", rdev::Key::KeyR),
("t", evdev::Key::KEY_T), ("t", rdev::Key::KeyT),
("y", evdev::Key::KEY_Y), ("y", rdev::Key::KeyY),
("u", evdev::Key::KEY_U), ("u", rdev::Key::KeyU),
("i", evdev::Key::KEY_I), ("i", rdev::Key::KeyI),
("o", evdev::Key::KEY_O), ("o", rdev::Key::KeyO),
("p", evdev::Key::KEY_P), ("p", rdev::Key::KeyP),
("a", evdev::Key::KEY_A), ("a", rdev::Key::KeyA),
("s", evdev::Key::KEY_S), ("s", rdev::Key::KeyS),
("d", evdev::Key::KEY_D), ("d", rdev::Key::KeyD),
("f", evdev::Key::KEY_F), ("f", rdev::Key::KeyF),
("g", evdev::Key::KEY_G), ("g", rdev::Key::KeyG),
("h", evdev::Key::KEY_H), ("h", rdev::Key::KeyH),
("j", evdev::Key::KEY_J), ("j", rdev::Key::KeyJ),
("k", evdev::Key::KEY_K), ("k", rdev::Key::KeyK),
("l", evdev::Key::KEY_L), ("l", rdev::Key::KeyL),
("z", evdev::Key::KEY_Z), ("z", rdev::Key::KeyZ),
("x", evdev::Key::KEY_X), ("x", rdev::Key::KeyX),
("c", evdev::Key::KEY_C), ("c", rdev::Key::KeyC),
("v", evdev::Key::KEY_V), ("v", rdev::Key::KeyV),
("b", evdev::Key::KEY_B), ("b", rdev::Key::KeyB),
("n", evdev::Key::KEY_N), ("n", rdev::Key::KeyN),
("m", evdev::Key::KEY_M), ("m", rdev::Key::KeyM),
("1", evdev::Key::KEY_1), ("1", rdev::Key::Num1),
("2", evdev::Key::KEY_2), ("2", rdev::Key::Num2),
("3", evdev::Key::KEY_3), ("3", rdev::Key::Num3),
("4", evdev::Key::KEY_4), ("4", rdev::Key::Num4),
("5", evdev::Key::KEY_5), ("5", rdev::Key::Num5),
("6", evdev::Key::KEY_6), ("6", rdev::Key::Num6),
("7", evdev::Key::KEY_7), ("7", rdev::Key::Num7),
("8", evdev::Key::KEY_8), ("8", rdev::Key::Num8),
("9", evdev::Key::KEY_9), ("9", rdev::Key::Num9),
("0", evdev::Key::KEY_0), ("0", rdev::Key::Num0),
("escape", evdev::Key::KEY_ESC), ("escape", rdev::Key::Escape),
("delete", evdev::Key::KEY_DELETE), ("delete", rdev::Key::Delete),
("backspace", evdev::Key::KEY_BACKSPACE), ("backspace", rdev::Key::Backspace),
("return", evdev::Key::KEY_ENTER), ("return", rdev::Key::Return),
("enter", evdev::Key::KEY_ENTER), ("enter", rdev::Key::Return),
("tab", evdev::Key::KEY_TAB), ("tab", rdev::Key::Tab),
("space", evdev::Key::KEY_SPACE), ("space", rdev::Key::Space),
("minus", evdev::Key::KEY_MINUS), ("minus", rdev::Key::Minus),
("-", evdev::Key::KEY_MINUS), ("-", rdev::Key::Minus),
("equal", evdev::Key::KEY_EQUAL), ("equal", rdev::Key::Equal),
("=", evdev::Key::KEY_EQUAL), ("=", rdev::Key::Equal),
("grave", evdev::Key::KEY_GRAVE), ("grave", rdev::Key::BackQuote),
("`", evdev::Key::KEY_GRAVE), ("`", rdev::Key::BackQuote),
("print", evdev::Key::KEY_SYSRQ), ("print", rdev::Key::PrintScreen),
("volumeup", evdev::Key::KEY_VOLUMEUP), /*
("xf86audioraisevolume", evdev::Key::KEY_VOLUMEUP), ("volumeup", rdev::Key::KEY_VOLUMEUP),
("volumedown", evdev::Key::KEY_VOLUMEDOWN), ("xf86audioraisevolume", rdev::Key::KEY_VOLUMEUP),
("xf86audiolowervolume", evdev::Key::KEY_VOLUMEDOWN), ("volumedown", rdev::Key::KEY_VOLUMEDOWN),
("mute", evdev::Key::KEY_MUTE), ("xf86audiolowervolume", rdev::Key::KEY_VOLUMEDOWN),
("xf86audiomute", evdev::Key::KEY_MUTE), ("mute", rdev::Key::KEY_MUTE),
("brightnessup", evdev::Key::KEY_BRIGHTNESSUP), ("xf86audiomute", rdev::Key::KEY_MUTE),
("brightnessdown", evdev::Key::KEY_BRIGHTNESSDOWN), ("brightnessup", rdev::Key::KEY_BRIGHTNESSUP),
(",", evdev::Key::KEY_COMMA), ("brightnessdown", rdev::Key::KEY_BRIGHTNESSDOWN),
("comma", evdev::Key::KEY_COMMA), TODO: find ways to accept xf86 keys
(".", evdev::Key::KEY_DOT), */
("dot", evdev::Key::KEY_DOT), (",", rdev::Key::Comma),
("/", evdev::Key::KEY_SLASH), ("comma", rdev::Key::Comma),
("slash", evdev::Key::KEY_SLASH), (".", rdev::Key::Dot),
("backslash", evdev::Key::KEY_BACKSLASH), ("dot", rdev::Key::Dot),
("leftbrace", evdev::Key::KEY_LEFTBRACE), ("/", rdev::Key::Slash),
("[", evdev::Key::KEY_LEFTBRACE), ("slash", rdev::Key::Slash),
("rightbrace", evdev::Key::KEY_RIGHTBRACE), ("backslash", rdev::Key::IntlBackslash),
("]", evdev::Key::KEY_RIGHTBRACE), ("leftbrace", rdev::Key::LeftBracket),
(";", evdev::Key::KEY_SEMICOLON), ("[", rdev::Key::LeftBracket),
("semicolon", evdev::Key::KEY_SEMICOLON), ("rightbrace", rdev::Key::RightBracket),
("'", evdev::Key::KEY_APOSTROPHE), ("]", rdev::Key::RightBracket),
("apostrophe", evdev::Key::KEY_APOSTROPHE), (";", rdev::Key::SemiColon),
("left", evdev::Key::KEY_LEFT), ("semicolon", rdev::Key::SemiColon),
("right", evdev::Key::KEY_RIGHT), ("'", rdev::Key::Quote),
("up", evdev::Key::KEY_UP), ("apostrophe", rdev::Key::Quote),
("down", evdev::Key::KEY_DOWN), ("left", rdev::Key::LeftArrow),
("f1", evdev::Key::KEY_F1), ("right", rdev::Key::RightArrow),
("f2", evdev::Key::KEY_F2), ("up", rdev::Key::UpArrow),
("f3", evdev::Key::KEY_F3), ("down", rdev::Key::DownArrow),
("f4", evdev::Key::KEY_F4), ("f1", rdev::Key::F1),
("f5", evdev::Key::KEY_F5), ("f2", rdev::Key::F2),
("f6", evdev::Key::KEY_F6), ("f3", rdev::Key::F3),
("f7", evdev::Key::KEY_F7), ("f4", rdev::Key::F4),
("f8", evdev::Key::KEY_F8), ("f5", rdev::Key::F5),
("f9", evdev::Key::KEY_F9), ("f6", rdev::Key::F6),
("f10", evdev::Key::KEY_F10), ("f7", rdev::Key::F7),
("f11", evdev::Key::KEY_F11), ("f8", rdev::Key::F8),
("f12", evdev::Key::KEY_F12), ("f9", rdev::Key::F9),
("f13", evdev::Key::KEY_F13), ("f10", rdev::Key::F10),
("f14", evdev::Key::KEY_F14), ("f11", rdev::Key::F11),
("f15", evdev::Key::KEY_F15), ("f12", rdev::Key::F12),
("f16", evdev::Key::KEY_F16), /*
("f17", evdev::Key::KEY_F17), ("f13", rdev::Key::F13),
("f18", evdev::Key::KEY_F18), ("f14", rdev::Key::F14),
("f19", evdev::Key::KEY_F19), ("f15", rdev::Key::F15),
("f20", evdev::Key::KEY_F20), ("f16", rdev::Key::F16),
("f21", evdev::Key::KEY_F21), ("f17", rdev::Key::F17),
("f22", evdev::Key::KEY_F22), ("f18", rdev::Key::F18),
("f23", evdev::Key::KEY_F23), ("f19", rdev::Key::F19),
("f24", evdev::Key::KEY_F24), ("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([ let mod_to_mod_enum: HashMap<&str, Modifier> = HashMap::from([
@ -306,9 +311,9 @@ fn parse_contents(contents: String) -> Result<Vec<Hotkey>, Error> {
fn parse_keybind( fn parse_keybind(
line: &str, line: &str,
line_nr: u32, 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>, mod_to_mod_enum: &HashMap<&str, Modifier>,
) -> Result<(String, evdev::Key, Vec<Modifier>, bool), Error> { ) -> Result<(Option<String>, rdev::Key, Vec<Modifier>, bool), Error> {
let line = line.split('#').next().unwrap(); let line = line.split('#').next().unwrap();
let tokens: Vec<String> = let tokens: Vec<String> =
line.split('+').map(|s| s.trim().to_lowercase()).filter(|s| s != "_").collect(); line.split('+').map(|s| s.trim().to_lowercase()).filter(|s| s != "_").collect();
@ -343,15 +348,19 @@ fn parse_keybind(
.map(|s| s.to_string()) .map(|s| s.to_string())
.collect::<Vec<String>>() .collect::<Vec<String>>()
.len() == 1 { true } else { false }; .len() == 1 { true } else { false };
let mode = tokens let mode = match tokens
.iter() .iter()
.filter(|s| s.starts_with("[") && s.ends_with("]")) .filter(|s| s.starts_with("[") && s.ends_with("]"))
.map(|s| s.replace(&['[', ']'][..], "")) .map(|s| s.replace(&['[', ']'][..], ""))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.get(0) .get(0) {
.unwrap_or(&"".to_string()) Some(z) => Some(z.to_string()),
.to_string(); None => {
let mod_index = if mode.is_empty() { 0 } else { 1 }; log::trace!("No mode specified");
None
}
};
let mod_index = if mode.is_some() { 1 } else { 0 };
let modifiers: Vec<Modifier> = tokens[mod_index..(tokens.len() - 1)] let modifiers: Vec<Modifier> = tokens[mod_index..(tokens.len() - 1)]
.iter() .iter()

@ -1,10 +1,24 @@
use clap::{arg, App}; use clap::{arg, App};
use evdev::{AttributeSet, Device, Key}; use rdev::{
Event,
EventType::{
KeyPress,
KeyRelease,
},
Key,
};
use nix::unistd::{Group, Uid}; use nix::unistd::{Group, Uid};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use std::{ use std::{
thread, thread,
sync::Mutex, sync::{
Mutex,
mpsc::{
sync_channel,
SyncSender,
Receiver
},
},
collections::HashMap, collections::HashMap,
env, fs, env, fs,
io::prelude::*, io::prelude::*,
@ -26,8 +40,8 @@ pub struct LastHotkey {
ran_at: SystemTime, ran_at: SystemTime,
} }
static MODE_SOCK: &str = "/tmp/odilia-mode.sock";
static STATE_MODE: OnceCell<Mutex<String>> = OnceCell::new(); static STATE_MODE: OnceCell<Mutex<String>> = OnceCell::new();
static MODE_SOCK: &str = "/tmp/odilia-mode.sock";
fn listen_for_mode_change() -> std::io::Result<()> { fn listen_for_mode_change() -> std::io::Result<()> {
log::trace!("Mode change listener started!"); log::trace!("Mode change listener started!");
@ -118,20 +132,6 @@ pub fn key_listener() {
exit(1); exit(1);
} }
log::trace!("Attempting to find all keyboard file descriptors.");
let mut keyboard_devices: Vec<Device> = 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) { let hotkeys = match config::load(config_file_path) {
Err(e) => { Err(e) => {
log::error!("Config Error: {}", e); log::error!("Config Error: {}", e);
@ -145,34 +145,24 @@ pub fn key_listener() {
} }
let modifiers_map: HashMap<Key, config::Modifier> = HashMap::from([ let modifiers_map: HashMap<Key, config::Modifier> = HashMap::from([
(Key::KEY_LEFTMETA, config::Modifier::Super), (Key::MetaLeft, config::Modifier::Super),
(Key::KEY_RIGHTMETA, config::Modifier::Super), (Key::MetaRight, config::Modifier::Super),
(Key::KEY_LEFTMETA, config::Modifier::Super), (Key::Alt, config::Modifier::Alt),
(Key::KEY_RIGHTMETA, config::Modifier::Super), (Key::AltGr, config::Modifier::Alt),
(Key::KEY_LEFTALT, config::Modifier::Alt), (Key::ControlLeft, config::Modifier::Control),
(Key::KEY_RIGHTALT, config::Modifier::Alt), (Key::ControlRight, config::Modifier::Control),
(Key::KEY_LEFTCTRL, config::Modifier::Control), (Key::ShiftLeft, config::Modifier::Shift),
(Key::KEY_RIGHTCTRL, config::Modifier::Control), (Key::ShiftRight, config::Modifier::Shift),
(Key::KEY_LEFTSHIFT, config::Modifier::Shift),
(Key::KEY_RIGHTSHIFT, config::Modifier::Shift),
]); ]);
let repeat_cooldown_duration: u128;
if args.is_present("cooldown") {
repeat_cooldown_duration = args.value_of("cooldown").unwrap().parse::<u128>().unwrap();
} else {
repeat_cooldown_duration = 250;
}
let mut key_states: Vec<AttributeSet<Key>> = Vec::new();
let mut possible_hotkeys: Vec<config::Hotkey> = Vec::new(); let mut possible_hotkeys: Vec<config::Hotkey> = Vec::new();
let default_test_modifier: Vec<config::Modifier> = vec![config::Modifier::Super]; let default_test_modifier: Vec<config::Modifier> = vec![config::Modifier::Super];
let mut last_hotkey = LastHotkey { let mut last_hotkey = LastHotkey {
// just a dummy last_hotkey so I don't need to mess with Option<T>. TODO: Change this to Option<T> // just a dummy last_hotkey so I don't need to mess with Option<T>. TODO: Change this to Option<T>
hotkey: config::Hotkey::new( hotkey: config::Hotkey::new(
"".to_string(), Some("".to_string()),
evdev::Key::KEY_A, Key::KeyA,
default_test_modifier, default_test_modifier,
String::from("notify-send \"it works\""), String::from("notify-send \"it works\""),
false, false,
@ -181,97 +171,9 @@ pub fn key_listener() {
}; };
loop { loop {
for device in &keyboard_devices { // TODO
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<config::Modifier> = Vec::new();
let mut state_keysyms: Vec<evdev::Key> = 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.
} }
} }
pub fn main() { pub fn main() {
@ -279,6 +181,7 @@ pub fn main() {
let key_handler = thread::spawn(|| { let key_handler = thread::spawn(|| {
key_listener(); key_listener();
}); });
/*
let mode_updater = thread::spawn(|| { let mode_updater = thread::spawn(|| {
let res = listen_for_mode_change(); let res = listen_for_mode_change();
match res { match res {
@ -286,8 +189,9 @@ pub fn main() {
Err(e) => log::error!("Error setting up mode socket: {}", e), Err(e) => log::error!("Error setting up mode socket: {}", e),
} }
}); });
*/
log::trace!("Threads set up"); log::trace!("Threads set up");
mode_updater.join().unwrap(); //mode_updater.join().unwrap();
key_handler.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> { pub fn set_flags() -> App<'static> {
let app = App::new("swhkd") let app = App::new("swhkd")
.version(env!("CARGO_PKG_VERSION")) .version(env!("CARGO_PKG_VERSION"))

Loading…
Cancel
Save