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];