1 //! Xlib calls related to a keyboard. 2 use super::{utils, XlibError}; 3 use crate::config::Keybind; 4 use crate::XWrap; 5 use std::os::raw::c_ulong; 6 use x11_dl::xlib; 7 8 impl XWrap { 9 /// Grabs the keysym with the modifier for a window. 10 // `XKeysymToKeycode`: https://tronche.com/gui/x/xlib/utilities/keyboard/XKeysymToKeycode.html 11 // `XGrabKey`: https://tronche.com/gui/x/xlib/input/XGrabKey.html grab_keys(&self, root: xlib::Window, keysym: u32, modifiers: u32)12 pub fn grab_keys(&self, root: xlib::Window, keysym: u32, modifiers: u32) { 13 let code = unsafe { (self.xlib.XKeysymToKeycode)(self.display, c_ulong::from(keysym)) }; 14 // Grab the keys with and without numlock (Mod2). 15 let mods: Vec<u32> = vec![ 16 modifiers, 17 modifiers | xlib::Mod2Mask, 18 modifiers | xlib::LockMask, 19 ]; 20 for m in mods { 21 unsafe { 22 (self.xlib.XGrabKey)( 23 self.display, 24 i32::from(code), 25 m, 26 root, 27 1, 28 xlib::GrabModeAsync, 29 xlib::GrabModeAsync, 30 ); 31 } 32 } 33 } 34 35 /// Resets the keybindings to a list of keybindings. 36 // `XUngrabKey`: https://tronche.com/gui/x/xlib/input/XUngrabKey.html reset_grabs(&self, keybinds: &[Keybind])37 pub fn reset_grabs(&self, keybinds: &[Keybind]) { 38 // Cleanup key grabs. 39 unsafe { 40 (self.xlib.XUngrabKey)(self.display, xlib::AnyKey, xlib::AnyModifier, self.root); 41 } 42 43 // Grab all the key combos from the config file. 44 for kb in keybinds { 45 if let Some(keysym) = utils::xkeysym_lookup::into_keysym(&kb.key) { 46 let modmask = utils::xkeysym_lookup::into_modmask(&kb.modifier); 47 self.grab_keys(self.root, keysym, modmask); 48 } 49 } 50 } 51 52 /// Updates the keyboard mapping. 53 /// # Errors 54 /// 55 /// Will error if updating the keyboard failed. 56 // `XRefreshKeyboardMapping`: https://tronche.com/gui/x/xlib/utilities/keyboard/XRefreshKeyboardMapping.html refresh_keyboard(&self, evt: &mut xlib::XMappingEvent) -> Result<(), XlibError>57 pub fn refresh_keyboard(&self, evt: &mut xlib::XMappingEvent) -> Result<(), XlibError> { 58 let status = unsafe { (self.xlib.XRefreshKeyboardMapping)(evt) }; 59 if status == 0 { 60 Err(XlibError::FailedStatus) 61 } else { 62 Ok(()) 63 } 64 } 65 66 /// Converts a keycode to a keysym. 67 // `XkbKeycodeToKeysym`: https://linux.die.net/man/3/xkbkeycodetokeysym 68 #[must_use] keycode_to_keysym(&self, keycode: u32) -> utils::xkeysym_lookup::XKeysym69 pub fn keycode_to_keysym(&self, keycode: u32) -> utils::xkeysym_lookup::XKeysym { 70 // Not using XKeysymToKeycode because deprecated. 71 let sym = unsafe { (self.xlib.XkbKeycodeToKeysym)(self.display, keycode as u8, 0, 0) }; 72 sym as u32 73 } 74 75 /// Converts a keysym to a keycode. 76 // `XKeysymToKeycode`: https://tronche.com/gui/x/xlib/utilities/keyboard/XKeysymToKeycode.html keysym_to_keycode(&self, keysym: utils::xkeysym_lookup::XKeysym) -> u3277 pub fn keysym_to_keycode(&self, keysym: utils::xkeysym_lookup::XKeysym) -> u32 { 78 let code = unsafe { (self.xlib.XKeysymToKeycode)(self.display, keysym.into()) }; 79 u32::from(code) 80 } 81 } 82