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