keyboard.rs

  1use collections::HashMap;
  2#[cfg(any(feature = "wayland", feature = "x11"))]
  3use xkbcommon::xkb::Keycode;
  4
  5use crate::{PlatformKeyboardLayout, SharedString};
  6
  7#[derive(Clone)]
  8pub(crate) struct LinuxKeyboardLayout {
  9    name: SharedString,
 10}
 11
 12impl PlatformKeyboardLayout for LinuxKeyboardLayout {
 13    fn id(&self) -> &str {
 14        &self.name
 15    }
 16
 17    fn name(&self) -> &str {
 18        &self.name
 19    }
 20}
 21
 22impl LinuxKeyboardLayout {
 23    pub(crate) fn new(name: SharedString) -> Self {
 24        Self { name }
 25    }
 26}
 27
 28#[cfg(any(feature = "wayland", feature = "x11"))]
 29pub(crate) struct LinuxKeyboardMapper {
 30    code_to_key: HashMap<Keycode, String>,
 31    code_to_shifted_key: HashMap<Keycode, String>,
 32}
 33
 34#[cfg(any(feature = "wayland", feature = "x11"))]
 35impl LinuxKeyboardMapper {
 36    pub(crate) fn new(xkb_state: &xkbcommon::xkb::State) -> Self {
 37        let mut code_to_key = HashMap::default();
 38        let mut code_to_shifted_key = HashMap::default();
 39
 40        let keymap = xkb_state.get_keymap();
 41        let mut shifted_state = xkbcommon::xkb::State::new(&keymap);
 42        let shift_mod = keymap.mod_get_index(xkbcommon::xkb::MOD_NAME_SHIFT);
 43        let shift_mask = 1 << shift_mod;
 44        shifted_state.update_mask(shift_mask, 0, 0, 0, 0, 0);
 45
 46        for &scan_code in TYPEABLE_CODES {
 47            let keycode = Keycode::new(scan_code);
 48            let key = xkb_state.key_get_utf8(keycode);
 49            code_to_key.insert(keycode, key.clone());
 50
 51            let shifted_key = shifted_state.key_get_utf8(keycode);
 52            code_to_shifted_key.insert(keycode, shifted_key);
 53        }
 54
 55        Self {
 56            code_to_key,
 57            code_to_shifted_key,
 58        }
 59    }
 60
 61    pub(crate) fn get_key(&self, keycode: Keycode, shift: bool) -> Option<String> {
 62        if shift {
 63            self.code_to_shifted_key.get(&keycode).cloned()
 64        } else {
 65            self.code_to_key.get(&keycode).cloned()
 66        }
 67    }
 68}
 69
 70// All typeable scan codes for the standard US keyboard layout, ANSI104
 71#[cfg(any(feature = "wayland", feature = "x11"))]
 72const TYPEABLE_CODES: &[u32] = &[
 73    0x0026, // a
 74    0x0038, // b
 75    0x0036, // c
 76    0x0028, // d
 77    0x001a, // e
 78    0x0029, // f
 79    0x002a, // g
 80    0x002b, // h
 81    0x001f, // i
 82    0x002c, // j
 83    0x002d, // k
 84    0x002e, // l
 85    0x003a, // m
 86    0x0039, // n
 87    0x0020, // o
 88    0x0021, // p
 89    0x0018, // q
 90    0x001b, // r
 91    0x0027, // s
 92    0x001c, // t
 93    0x001e, // u
 94    0x0037, // v
 95    0x0019, // w
 96    0x0035, // x
 97    0x001d, // y
 98    0x0034, // z
 99    0x0013, // Digit 0
100    0x000a, // Digit 1
101    0x000b, // Digit 2
102    0x000c, // Digit 3
103    0x000d, // Digit 4
104    0x000e, // Digit 5
105    0x000f, // Digit 6
106    0x0010, // Digit 7
107    0x0011, // Digit 8
108    0x0012, // Digit 9
109    0x0031, // ` Backquote
110    0x0014, // - Minus
111    0x0015, // = Equal
112    0x0022, // [ Left bracket
113    0x0023, // ] Right bracket
114    0x0033, // \ Backslash
115    0x002f, // ; Semicolon
116    0x0030, // ' Quote
117    0x003b, // , Comma
118    0x003c, // . Period
119    0x003d, // / Slash
120];