diff options
author | tcmal <me@aria.rip> | 2024-06-09 17:34:45 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-06-09 17:34:45 +0100 |
commit | 124e6878b1de561f4bc3fccea768203821c88469 (patch) | |
tree | ff46ede6bc720148402841bfaad6d850ec900ab0 /src/keys.rs | |
parent | 66e3423828892a72e5e525f2dc8d5ad91e634445 (diff) |
minor cleanup
Diffstat (limited to 'src/keys.rs')
-rw-r--r-- | src/keys.rs | 99 |
1 files changed, 46 insertions, 53 deletions
diff --git a/src/keys.rs b/src/keys.rs index 07dfb40..21217b0 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,6 +1,6 @@ -use std::process::Command; +use std::ops::RangeInclusive; -use crate::{error::*, WM}; +use crate::{config::KEYBINDS, error::*, WM}; use xcb::{ x::{ GetKeyboardMapping, GetKeyboardMappingReply, GetModifierMapping, GrabKey, GrabMode, @@ -11,8 +11,8 @@ use xcb::{ use xkeysym::{KeyCode, Keysym, RawKeyCode}; impl WM<'_> { - /// Handles a key press event by dispatching according to [`self::KEYBINDS`] - pub(crate) fn handle_key_press(&mut self, e: KeyPressEvent) -> Result<()> { + /// Dispatch the given keypress event according to [`self::KEYBINDS`] + pub fn handle_key_press(&mut self, e: KeyPressEvent) -> Result<()> { let Some(sym) = self.keyboard_state.keycode_to_keysym(e.detail().into(), 0) else { return Ok(()); // probably not bound }; @@ -27,8 +27,8 @@ impl WM<'_> { Ok(()) } - /// Handles a mapping notify event by updating our keyboard setup if needed. - pub(crate) fn handle_mapping_notify(&mut self, e: MappingNotifyEvent) -> Result<()> { + /// Update our keyboard info when the mapping changes. + pub fn handle_mapping_notify(&mut self, e: MappingNotifyEvent) -> Result<()> { if e.request() == Mapping::Keyboard { self.grab_keys()?; } @@ -36,8 +36,8 @@ impl WM<'_> { Ok(()) } - /// Grab all keys specified by [`self::KEYBINDS`], ensuring we get events for them. - pub(crate) fn grab_keys(&mut self) -> Result<()> { + /// Refresh our keyboard info, and ensure that we get events for bound keys. + pub fn grab_keys(&mut self) -> Result<()> { // Refresh keyboard state self.keyboard_state = KeyboardInfo::new_with(self.conn)?; @@ -81,9 +81,14 @@ impl WM<'_> { /// Cached information about our keyboard layout. pub struct KeyboardInfo { - min_keycode: RawKeyCode, - max_keycode: RawKeyCode, + /// The range of keycodes used + keycodes: RangeInclusive<RawKeyCode>, + + /// The ModMask corresponding to NumLock. + /// This varies sometimes, and we need to know to ignore it. numlock_mask: ModMask, + + /// The mapping from keycodes to (multiple) key symbols mapping: GetKeyboardMappingReply, } @@ -99,20 +104,22 @@ impl KeyboardInfo { }))?; let mut this = Self { - min_keycode: min_keycode as u32, - max_keycode: max_keycode as u32, + keycodes: min_keycode as RawKeyCode..=max_keycode as RawKeyCode, numlock_mask: ModMask::empty(), mapping, }; - let numlock_keycode = this.keysym_to_keycode(Keysym::Num_Lock)?; + let Some(numlock_keycode) = this.keysym_to_keycode(Keysym::Num_Lock) else { + // No numlock button, so no modmask for numlock + return Ok(this); + }; let mod_map = conn.wait_for_reply(conn.send_request(&GetModifierMapping {}))?; let keypermod = mod_map.keycodes().len() / 8; for i in 0..8 { for j in 0..keypermod { if mod_map.keycodes()[i * keypermod + j] as u32 == numlock_keycode.raw() { this.numlock_mask = - ModMask::from_bits(1 << i).expect("x11 has unrecognised modifier"); + ModMask::from_bits(1 << i).expect("x11 returned unrecognised modifier"); } } } @@ -120,18 +127,16 @@ impl KeyboardInfo { Ok(this) } - /// Get the modifier mask being used for numlock, which varies. + /// Get the modifier mask being used for numlock pub fn numlock_mask(&self) -> ModMask { self.numlock_mask } /// Iterate over all keycodes and their bound keysyms. /// This is likely to contain duplicate pairs. - pub(crate) fn iter_keycodes_keysyms(&self) -> impl Iterator<Item = (KeyCode, Keysym)> + '_ { + pub fn iter_keycodes_keysyms(&self) -> impl Iterator<Item = (KeyCode, Keysym)> + '_ { (0..self.mapping.keysyms_per_keycode()) - .flat_map(|shift| { - (self.min_keycode..self.max_keycode).map(move |keycode| (shift, keycode)) - }) + .flat_map(|shift| self.keycodes.clone().map(move |keycode| (shift, keycode))) .flat_map(|(shift, keycode)| -> Option<_> { Some(( keycode.into(), @@ -140,21 +145,21 @@ impl KeyboardInfo { }) } - /// Lookup the first keycode which has the given keysym - pub(crate) fn keysym_to_keycode(&self, keysym: Keysym) -> Result<KeyCode> { + /// Lookup the first keycode which has the given keysym in any column + pub(crate) fn keysym_to_keycode(&self, keysym: Keysym) -> Option<KeyCode> { for shift in 0..self.mapping.keysyms_per_keycode() { - for keycode in self.min_keycode..self.max_keycode { - if self.mapping.keysyms()[(keycode as usize - self.min_keycode as usize) + for keycode in self.keycodes.clone() { + if self.mapping.keysyms()[(keycode as usize - *self.keycodes.start() as usize) * self.mapping.keysyms_per_keycode() as usize + shift as usize] == keysym.raw() { - return Ok(keycode.into()); + return Some(keycode.into()); } } } - Ok(KeyCode::new(0)) + None } /// Lookup the keysym in the given column for the given keycode @@ -162,43 +167,22 @@ impl KeyboardInfo { xkeysym::keysym( keycode, col, - self.min_keycode.into(), + (*self.keycodes.start()).into(), self.mapping.keysyms_per_keycode(), self.mapping.keysyms(), ) } } -/// A bound key +/// A key bound to some action pub struct Keybind { - modifiers: ModMask, - key: Keysym, - action: &'static dyn Fn(&mut WM<'_>), -} - -impl std::fmt::Debug for Keybind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("Keybind") - .field("modifiers", &self.modifiers) - .field("key", &self.key) - .finish() - } + pub modifiers: ModMask, + pub key: Keysym, + pub action: &'static dyn Fn(&mut WM<'_>), } -/// A set of keybinds. Currently, there is only one instance of this defined statically: [`self::KEYBINDS`]. -pub struct Keybinds(&'static [Keybind]); - -/// The keybinds to use. -const KEYBINDS: Keybinds = Keybinds(&[Keybind { - modifiers: ModMask::CONTROL, - key: Keysym::t, - action: &|_| { - // TODO: disown this process, probably using another way to spawn commands - if let Err(e) = Command::new("xterm").spawn() { - dbg!(e); - } - }, -}]); +/// A set of keybinds. Currently, there is only one instance of this defined statically: [`crate::config::KEYBINDS`]. +pub struct Keybinds(pub &'static [Keybind]); impl Keybinds { /// Get an iterator over all bound keys @@ -216,3 +200,12 @@ impl Keybinds { } } } + +impl std::fmt::Debug for Keybind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Keybind") + .field("modifiers", &self.modifiers) + .field("key", &self.key) + .finish() + } +} |