1use super::{WHEEL_DOWN_CODE, WHEEL_UP_CODE};
2
3pub fn key_name_to_evdev(name: &str) -> Option<u32> {
4 match name.trim().to_ascii_lowercase().as_str() {
5 "none" => Some(0),
6
7 "escape" | "esc" => Some(1),
8 "1" => Some(2),
9 "2" => Some(3),
10 "3" => Some(4),
11 "4" => Some(5),
12 "5" => Some(6),
13 "6" => Some(7),
14 "7" => Some(8),
15 "8" => Some(9),
16 "9" => Some(10),
17 "0" => Some(11),
18 "minus" | "-" => Some(12),
19 "equal" | "=" => Some(13),
20 "backspace" => Some(14),
21 "tab" => Some(15),
22
23 "q" => Some(16),
24 "w" => Some(17),
25 "e" => Some(18),
26 "r" => Some(19),
27 "t" => Some(20),
28 "y" => Some(21),
29 "u" => Some(22),
30 "i" => Some(23),
31 "o" => Some(24),
32 "p" => Some(25),
33 "leftbrace" | "[" => Some(26),
34 "rightbrace" | "]" => Some(27),
35 "enter" | "return" => Some(28),
36
37 "a" => Some(30),
38 "s" => Some(31),
39 "d" => Some(32),
40 "f" => Some(33),
41 "g" => Some(34),
42 "h" => Some(35),
43 "j" => Some(36),
44 "k" => Some(37),
45 "l" => Some(38),
46 "semicolon" | ";" => Some(39),
47 "apostrophe" | "'" => Some(40),
48 "grave" | "`" => Some(41),
49 "backslash" | "\\" => Some(43),
50
51 "z" => Some(44),
52 "x" => Some(45),
53 "c" => Some(46),
54 "v" => Some(47),
55 "b" => Some(48),
56 "n" => Some(49),
57 "m" => Some(50),
58 "comma" | "," => Some(51),
59 "dot" | "period" | "." => Some(52),
60 "slash" | "/" => Some(53),
61
62 "space" => Some(57),
63
64 "f1" => Some(59),
65 "f2" => Some(60),
66 "f3" => Some(61),
67 "f4" => Some(62),
68 "f5" => Some(63),
69 "f6" => Some(64),
70 "f7" => Some(65),
71 "f8" => Some(66),
72 "f9" => Some(67),
73 "f10" => Some(68),
74 "f11" => Some(87),
75 "f12" => Some(88),
76
77 "home" => Some(102),
78 "up" => Some(103),
79 "pageup" => Some(104),
80 "left" => Some(105),
81 "right" => Some(106),
82 "end" => Some(107),
83 "down" => Some(108),
84 "pagedown" => Some(109),
85 "insert" => Some(110),
86 "delete" => Some(111),
87
88 "mouseleft" | "leftmouse" | "leftbutton" | "btnleft" | "btn_left" => Some(272),
89 "mouseright" | "rightmouse" | "rightbutton" | "btnright" | "btn_right" => Some(273),
90 "mousemiddle" | "middlemouse" | "middlebutton" | "btnmiddle" | "btn_middle" => Some(274),
91 "mouse4" | "mouseback" | "sidebutton" | "btnside" | "btn_side" => Some(275),
92 "mouse5" | "mouseforward" | "extrabutton" | "btnextra" | "btn_extra" => Some(276),
93 "mousewheelup" | "wheelup" | "scrollup" => Some(WHEEL_UP_CODE),
94 "mousewheeldown" | "wheeldown" | "scrolldown" => Some(WHEEL_DOWN_CODE),
95
96 "xf86audiomute" | "audiomute" | "mute" => Some(113),
97 "xf86audiolowervolume" | "audiolowervolume" | "volumedown" => Some(114),
98 "xf86audioraisevolume" | "audioraisevolume" | "volumeup" => Some(115),
99 "xf86audiostop" | "audiostop" | "stopmedia" => Some(166),
100 "xf86audioplay" | "audioplay" | "playpause" => Some(164),
101 "xf86audioprev" | "audioprev" | "previoussong" => Some(165),
102 "xf86audionext" | "audionext" | "nextsong" => Some(163),
103 "xf86audiorecord" | "audiorecord" => Some(167),
104 "xf86audiorewind" | "audiorewind" | "rewind" => Some(168),
105 "xf86homepage" | "homepage" => Some(172),
106 "xf86search" | "search" => Some(217),
107 "xf86monbrightnessdown" | "brightnessdown" => Some(224),
108 "xf86monbrightnessup" | "brightnessup" => Some(225),
109 "xf86mail" | "mail" => Some(155),
110 "xf86calculator" | "calculator" => Some(140),
111 "xf86sleep" | "sleep" => Some(142),
112 "xf86audiopause" | "audiopause" => Some(201),
113 "xf86audiomicmute" | "audiomicmute" | "micmute" => Some(248),
114
115 _ => None,
116 }
117}
118
119#[inline]
120pub fn is_pointer_button_code(code: u32) -> bool {
121 matches!(code, 272..=276)
122}
123
124#[inline]
125pub fn is_wheel_code(code: u32) -> bool {
126 matches!(code, WHEEL_UP_CODE | WHEEL_DOWN_CODE)
127}
128
129pub fn evdev_to_key_name(code: u32) -> &'static str {
130 match code {
131 0 => "None",
132 1 => "Escape",
133 2 => "1",
134 3 => "2",
135 4 => "3",
136 5 => "4",
137 6 => "5",
138 7 => "6",
139 8 => "7",
140 9 => "8",
141 10 => "9",
142 11 => "0",
143 12 => "Minus",
144 13 => "Equal",
145 14 => "Backspace",
146 15 => "Tab",
147 16 => "Q",
148 17 => "W",
149 18 => "E",
150 19 => "R",
151 20 => "T",
152 21 => "Y",
153 22 => "U",
154 23 => "I",
155 24 => "O",
156 25 => "P",
157 26 => "[",
158 27 => "]",
159 28 => "Return",
160 30 => "A",
161 31 => "S",
162 32 => "D",
163 33 => "F",
164 34 => "G",
165 35 => "H",
166 36 => "J",
167 37 => "K",
168 38 => "L",
169 39 => ";",
170 40 => "'",
171 41 => "`",
172 43 => "\\",
173 44 => "Z",
174 45 => "X",
175 46 => "C",
176 47 => "V",
177 48 => "B",
178 49 => "N",
179 50 => "M",
180 51 => "Comma",
181 52 => "Period",
182 53 => "Slash",
183 57 => "Space",
184 59 => "F1",
185 60 => "F2",
186 61 => "F3",
187 62 => "F4",
188 63 => "F5",
189 64 => "F6",
190 65 => "F7",
191 66 => "F8",
192 67 => "F9",
193 68 => "F10",
194 87 => "F11",
195 88 => "F12",
196 102 => "Home",
197 103 => "Up",
198 104 => "PageUp",
199 105 => "Left",
200 106 => "Right",
201 107 => "End",
202 108 => "Down",
203 109 => "PageDown",
204 110 => "Insert",
205 111 => "Delete",
206 140 => "XF86Calculator",
207 142 => "XF86Sleep",
208 155 => "XF86Mail",
209 113 => "XF86AudioMute",
210 114 => "XF86AudioLowerVolume",
211 115 => "XF86AudioRaiseVolume",
212 163 => "XF86AudioNext",
213 164 => "XF86AudioPlay",
214 165 => "XF86AudioPrev",
215 166 => "XF86AudioStop",
216 167 => "XF86AudioRecord",
217 168 => "XF86AudioRewind",
218 172 => "XF86HomePage",
219 201 => "XF86AudioPause",
220 217 => "XF86Search",
221 224 => "XF86MonBrightnessDown",
222 225 => "XF86MonBrightnessUp",
223 248 => "XF86AudioMicMute",
224 272 => "MouseLeft",
225 273 => "MouseRight",
226 274 => "MouseMiddle",
227 275 => "MouseBack",
228 276 => "MouseForward",
229 WHEEL_UP_CODE => "MouseWheelUp",
230 WHEEL_DOWN_CODE => "MouseWheelDown",
231 _ => "?",
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::{WHEEL_DOWN_CODE, WHEEL_UP_CODE, evdev_to_key_name, key_name_to_evdev};
238 use crate::keybinds::{parse_chord, parse_modifiers};
239
240 #[test]
241 fn generic_alt_modifier_matches_either_side_in_config() {
242 let mods = parse_modifiers("alt").expect("alt should parse");
243 assert!(mods.alt);
244 assert!(!mods.left_alt);
245 assert!(!mods.right_alt);
246
247 let (chord_mods, key) = parse_chord("alt+r").expect("alt+r should parse");
248 assert!(chord_mods.alt);
249 assert_eq!(key, 19);
250 }
251
252 #[test]
253 fn mouse_button_aliases_resolve_to_pointer_button_codes() {
254 assert_eq!(key_name_to_evdev("mouseleft"), Some(272));
255 assert_eq!(key_name_to_evdev("btn_right"), Some(273));
256 assert_eq!(key_name_to_evdev("middlemouse"), Some(274));
257 assert_eq!(key_name_to_evdev("mouseback"), Some(275));
258 assert_eq!(key_name_to_evdev("mouseforward"), Some(276));
259 assert_eq!(key_name_to_evdev("mousewheelup"), Some(WHEEL_UP_CODE));
260 assert_eq!(key_name_to_evdev("mousewheeldown"), Some(WHEEL_DOWN_CODE));
261 }
262
263 #[test]
264 fn xf86_media_aliases_resolve_to_expected_codes() {
265 assert_eq!(key_name_to_evdev("XF86AudioMute"), Some(113));
266 assert_eq!(key_name_to_evdev("XF86AudioStop"), Some(166));
267 assert_eq!(key_name_to_evdev("XF86AudioPause"), Some(201));
268 assert_eq!(key_name_to_evdev("XF86AudioMicMute"), Some(248));
269 assert_eq!(key_name_to_evdev("XF86MonBrightnessUp"), Some(225));
270 }
271
272 #[test]
273 fn reverse_lookup_uses_canonical_names_for_new_codes() {
274 assert_eq!(evdev_to_key_name(272), "MouseLeft");
275 assert_eq!(evdev_to_key_name(275), "MouseBack");
276 assert_eq!(evdev_to_key_name(WHEEL_UP_CODE), "MouseWheelUp");
277 assert_eq!(evdev_to_key_name(WHEEL_DOWN_CODE), "MouseWheelDown");
278 assert_eq!(evdev_to_key_name(166), "XF86AudioStop");
279 assert_eq!(evdev_to_key_name(248), "XF86AudioMicMute");
280 }
281}