1//! XKB keymap.
2
3use std::ffi::c_char;
4use std::ops::Deref;
5use std::ptr::{self, NonNull};
6
7#[cfg(x11_platform)]
8use x11_dl::xlib_xcb::xcb_connection_t;
9#[cfg(wayland_platform)]
10use {memmap2::MmapOptions, std::os::unix::io::OwnedFd};
11
12use xkb::XKB_MOD_INVALID;
13use xkbcommon_dl::{
14 self as xkb, xkb_keycode_t, xkb_keymap, xkb_keymap_compile_flags, xkb_keysym_t,
15 xkb_layout_index_t, xkb_mod_index_t,
16};
17
18use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey};
19#[cfg(x11_platform)]
20use crate::platform_impl::common::xkb::XKBXH;
21use crate::platform_impl::common::xkb::{XkbContext, XKBH};
22
23/// Map the raw X11-style keycode to the `KeyCode` enum.
24///
25/// X11-style keycodes are offset by 8 from the keycodes the Linux kernel uses.
26pub fn raw_keycode_to_physicalkey(keycode: u32) -> PhysicalKey {
27 scancode_to_keycode(scancode:keycode.saturating_sub(8))
28}
29
30/// Map the linux scancode to Keycode.
31///
32/// Both X11 and Wayland use keys with `+ 8` offset to linux scancode.
33pub fn scancode_to_keycode(scancode: u32) -> PhysicalKey {
34 // The keycode values are taken from linux/include/uapi/linux/input-event-codes.h, as
35 // libxkbcommon's documentation seems to suggest that the keycode values we're interested in
36 // are defined by the Linux kernel. If Winit programs end up being run on other Unix-likes,
37 // I can only hope they agree on what the keycodes mean.
38 //
39 // Some of the keycodes are likely superfluous for our purposes, and some are ones which are
40 // difficult to test the correctness of, or discover the purpose of. Because of this, they've
41 // either been commented out here, or not included at all.
42 PhysicalKey::Code(match scancode {
43 0 => return PhysicalKey::Unidentified(NativeKeyCode::Xkb(0)),
44 1 => KeyCode::Escape,
45 2 => KeyCode::Digit1,
46 3 => KeyCode::Digit2,
47 4 => KeyCode::Digit3,
48 5 => KeyCode::Digit4,
49 6 => KeyCode::Digit5,
50 7 => KeyCode::Digit6,
51 8 => KeyCode::Digit7,
52 9 => KeyCode::Digit8,
53 10 => KeyCode::Digit9,
54 11 => KeyCode::Digit0,
55 12 => KeyCode::Minus,
56 13 => KeyCode::Equal,
57 14 => KeyCode::Backspace,
58 15 => KeyCode::Tab,
59 16 => KeyCode::KeyQ,
60 17 => KeyCode::KeyW,
61 18 => KeyCode::KeyE,
62 19 => KeyCode::KeyR,
63 20 => KeyCode::KeyT,
64 21 => KeyCode::KeyY,
65 22 => KeyCode::KeyU,
66 23 => KeyCode::KeyI,
67 24 => KeyCode::KeyO,
68 25 => KeyCode::KeyP,
69 26 => KeyCode::BracketLeft,
70 27 => KeyCode::BracketRight,
71 28 => KeyCode::Enter,
72 29 => KeyCode::ControlLeft,
73 30 => KeyCode::KeyA,
74 31 => KeyCode::KeyS,
75 32 => KeyCode::KeyD,
76 33 => KeyCode::KeyF,
77 34 => KeyCode::KeyG,
78 35 => KeyCode::KeyH,
79 36 => KeyCode::KeyJ,
80 37 => KeyCode::KeyK,
81 38 => KeyCode::KeyL,
82 39 => KeyCode::Semicolon,
83 40 => KeyCode::Quote,
84 41 => KeyCode::Backquote,
85 42 => KeyCode::ShiftLeft,
86 43 => KeyCode::Backslash,
87 44 => KeyCode::KeyZ,
88 45 => KeyCode::KeyX,
89 46 => KeyCode::KeyC,
90 47 => KeyCode::KeyV,
91 48 => KeyCode::KeyB,
92 49 => KeyCode::KeyN,
93 50 => KeyCode::KeyM,
94 51 => KeyCode::Comma,
95 52 => KeyCode::Period,
96 53 => KeyCode::Slash,
97 54 => KeyCode::ShiftRight,
98 55 => KeyCode::NumpadMultiply,
99 56 => KeyCode::AltLeft,
100 57 => KeyCode::Space,
101 58 => KeyCode::CapsLock,
102 59 => KeyCode::F1,
103 60 => KeyCode::F2,
104 61 => KeyCode::F3,
105 62 => KeyCode::F4,
106 63 => KeyCode::F5,
107 64 => KeyCode::F6,
108 65 => KeyCode::F7,
109 66 => KeyCode::F8,
110 67 => KeyCode::F9,
111 68 => KeyCode::F10,
112 69 => KeyCode::NumLock,
113 70 => KeyCode::ScrollLock,
114 71 => KeyCode::Numpad7,
115 72 => KeyCode::Numpad8,
116 73 => KeyCode::Numpad9,
117 74 => KeyCode::NumpadSubtract,
118 75 => KeyCode::Numpad4,
119 76 => KeyCode::Numpad5,
120 77 => KeyCode::Numpad6,
121 78 => KeyCode::NumpadAdd,
122 79 => KeyCode::Numpad1,
123 80 => KeyCode::Numpad2,
124 81 => KeyCode::Numpad3,
125 82 => KeyCode::Numpad0,
126 83 => KeyCode::NumpadDecimal,
127 85 => KeyCode::Lang5,
128 86 => KeyCode::IntlBackslash,
129 87 => KeyCode::F11,
130 88 => KeyCode::F12,
131 89 => KeyCode::IntlRo,
132 90 => KeyCode::Lang3,
133 91 => KeyCode::Lang4,
134 92 => KeyCode::Convert,
135 93 => KeyCode::KanaMode,
136 94 => KeyCode::NonConvert,
137 // 95 => KeyCode::KPJPCOMMA,
138 96 => KeyCode::NumpadEnter,
139 97 => KeyCode::ControlRight,
140 98 => KeyCode::NumpadDivide,
141 99 => KeyCode::PrintScreen,
142 100 => KeyCode::AltRight,
143 // 101 => KeyCode::LINEFEED,
144 102 => KeyCode::Home,
145 103 => KeyCode::ArrowUp,
146 104 => KeyCode::PageUp,
147 105 => KeyCode::ArrowLeft,
148 106 => KeyCode::ArrowRight,
149 107 => KeyCode::End,
150 108 => KeyCode::ArrowDown,
151 109 => KeyCode::PageDown,
152 110 => KeyCode::Insert,
153 111 => KeyCode::Delete,
154 // 112 => KeyCode::MACRO,
155 113 => KeyCode::AudioVolumeMute,
156 114 => KeyCode::AudioVolumeDown,
157 115 => KeyCode::AudioVolumeUp,
158 // 116 => KeyCode::POWER,
159 117 => KeyCode::NumpadEqual,
160 // 118 => KeyCode::KPPLUSMINUS,
161 119 => KeyCode::Pause,
162 // 120 => KeyCode::SCALE,
163 121 => KeyCode::NumpadComma,
164 122 => KeyCode::Lang1,
165 123 => KeyCode::Lang2,
166 124 => KeyCode::IntlYen,
167 125 => KeyCode::SuperLeft,
168 126 => KeyCode::SuperRight,
169 127 => KeyCode::ContextMenu,
170 // 128 => KeyCode::STOP,
171 // 129 => KeyCode::AGAIN,
172 // 130 => KeyCode::PROPS,
173 // 131 => KeyCode::UNDO,
174 // 132 => KeyCode::FRONT,
175 // 133 => KeyCode::COPY,
176 // 134 => KeyCode::OPEN,
177 // 135 => KeyCode::PASTE,
178 // 136 => KeyCode::FIND,
179 // 137 => KeyCode::CUT,
180 // 138 => KeyCode::HELP,
181 // 139 => KeyCode::MENU,
182 // 140 => KeyCode::CALC,
183 // 141 => KeyCode::SETUP,
184 // 142 => KeyCode::SLEEP,
185 // 143 => KeyCode::WAKEUP,
186 // 144 => KeyCode::FILE,
187 // 145 => KeyCode::SENDFILE,
188 // 146 => KeyCode::DELETEFILE,
189 // 147 => KeyCode::XFER,
190 // 148 => KeyCode::PROG1,
191 // 149 => KeyCode::PROG2,
192 // 150 => KeyCode::WWW,
193 // 151 => KeyCode::MSDOS,
194 // 152 => KeyCode::COFFEE,
195 // 153 => KeyCode::ROTATE_DISPLAY,
196 // 154 => KeyCode::CYCLEWINDOWS,
197 // 155 => KeyCode::MAIL,
198 // 156 => KeyCode::BOOKMARKS,
199 // 157 => KeyCode::COMPUTER,
200 // 158 => KeyCode::BACK,
201 // 159 => KeyCode::FORWARD,
202 // 160 => KeyCode::CLOSECD,
203 // 161 => KeyCode::EJECTCD,
204 // 162 => KeyCode::EJECTCLOSECD,
205 163 => KeyCode::MediaTrackNext,
206 164 => KeyCode::MediaPlayPause,
207 165 => KeyCode::MediaTrackPrevious,
208 166 => KeyCode::MediaStop,
209 // 167 => KeyCode::RECORD,
210 // 168 => KeyCode::REWIND,
211 // 169 => KeyCode::PHONE,
212 // 170 => KeyCode::ISO,
213 // 171 => KeyCode::CONFIG,
214 // 172 => KeyCode::HOMEPAGE,
215 // 173 => KeyCode::REFRESH,
216 // 174 => KeyCode::EXIT,
217 // 175 => KeyCode::MOVE,
218 // 176 => KeyCode::EDIT,
219 // 177 => KeyCode::SCROLLUP,
220 // 178 => KeyCode::SCROLLDOWN,
221 // 179 => KeyCode::KPLEFTPAREN,
222 // 180 => KeyCode::KPRIGHTPAREN,
223 // 181 => KeyCode::NEW,
224 // 182 => KeyCode::REDO,
225 183 => KeyCode::F13,
226 184 => KeyCode::F14,
227 185 => KeyCode::F15,
228 186 => KeyCode::F16,
229 187 => KeyCode::F17,
230 188 => KeyCode::F18,
231 189 => KeyCode::F19,
232 190 => KeyCode::F20,
233 191 => KeyCode::F21,
234 192 => KeyCode::F22,
235 193 => KeyCode::F23,
236 194 => KeyCode::F24,
237 // 200 => KeyCode::PLAYCD,
238 // 201 => KeyCode::PAUSECD,
239 // 202 => KeyCode::PROG3,
240 // 203 => KeyCode::PROG4,
241 // 204 => KeyCode::DASHBOARD,
242 // 205 => KeyCode::SUSPEND,
243 // 206 => KeyCode::CLOSE,
244 // 207 => KeyCode::PLAY,
245 // 208 => KeyCode::FASTFORWARD,
246 // 209 => KeyCode::BASSBOOST,
247 // 210 => KeyCode::PRINT,
248 // 211 => KeyCode::HP,
249 // 212 => KeyCode::CAMERA,
250 // 213 => KeyCode::SOUND,
251 // 214 => KeyCode::QUESTION,
252 // 215 => KeyCode::EMAIL,
253 // 216 => KeyCode::CHAT,
254 // 217 => KeyCode::SEARCH,
255 // 218 => KeyCode::CONNECT,
256 // 219 => KeyCode::FINANCE,
257 // 220 => KeyCode::SPORT,
258 // 221 => KeyCode::SHOP,
259 // 222 => KeyCode::ALTERASE,
260 // 223 => KeyCode::CANCEL,
261 // 224 => KeyCode::BRIGHTNESSDOW,
262 // 225 => KeyCode::BRIGHTNESSU,
263 // 226 => KeyCode::MEDIA,
264 // 227 => KeyCode::SWITCHVIDEOMODE,
265 // 228 => KeyCode::KBDILLUMTOGGLE,
266 // 229 => KeyCode::KBDILLUMDOWN,
267 // 230 => KeyCode::KBDILLUMUP,
268 // 231 => KeyCode::SEND,
269 // 232 => KeyCode::REPLY,
270 // 233 => KeyCode::FORWARDMAIL,
271 // 234 => KeyCode::SAVE,
272 // 235 => KeyCode::DOCUMENTS,
273 // 236 => KeyCode::BATTERY,
274 // 237 => KeyCode::BLUETOOTH,
275 // 238 => KeyCode::WLAN,
276 // 239 => KeyCode::UWB,
277 240 => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified),
278 // 241 => KeyCode::VIDEO_NEXT,
279 // 242 => KeyCode::VIDEO_PREV,
280 // 243 => KeyCode::BRIGHTNESS_CYCLE,
281 // 244 => KeyCode::BRIGHTNESS_AUTO,
282 // 245 => KeyCode::DISPLAY_OFF,
283 // 246 => KeyCode::WWAN,
284 // 247 => KeyCode::RFKILL,
285 // 248 => KeyCode::KEY_MICMUTE,
286 _ => return PhysicalKey::Unidentified(NativeKeyCode::Xkb(scancode)),
287 })
288}
289
290pub fn physicalkey_to_scancode(key: PhysicalKey) -> Option<u32> {
291 let code = match key {
292 PhysicalKey::Code(code) => code,
293 PhysicalKey::Unidentified(code) => {
294 return match code {
295 NativeKeyCode::Unidentified => Some(240),
296 NativeKeyCode::Xkb(raw) => Some(raw),
297 _ => None,
298 };
299 }
300 };
301
302 match code {
303 KeyCode::Escape => Some(1),
304 KeyCode::Digit1 => Some(2),
305 KeyCode::Digit2 => Some(3),
306 KeyCode::Digit3 => Some(4),
307 KeyCode::Digit4 => Some(5),
308 KeyCode::Digit5 => Some(6),
309 KeyCode::Digit6 => Some(7),
310 KeyCode::Digit7 => Some(8),
311 KeyCode::Digit8 => Some(9),
312 KeyCode::Digit9 => Some(10),
313 KeyCode::Digit0 => Some(11),
314 KeyCode::Minus => Some(12),
315 KeyCode::Equal => Some(13),
316 KeyCode::Backspace => Some(14),
317 KeyCode::Tab => Some(15),
318 KeyCode::KeyQ => Some(16),
319 KeyCode::KeyW => Some(17),
320 KeyCode::KeyE => Some(18),
321 KeyCode::KeyR => Some(19),
322 KeyCode::KeyT => Some(20),
323 KeyCode::KeyY => Some(21),
324 KeyCode::KeyU => Some(22),
325 KeyCode::KeyI => Some(23),
326 KeyCode::KeyO => Some(24),
327 KeyCode::KeyP => Some(25),
328 KeyCode::BracketLeft => Some(26),
329 KeyCode::BracketRight => Some(27),
330 KeyCode::Enter => Some(28),
331 KeyCode::ControlLeft => Some(29),
332 KeyCode::KeyA => Some(30),
333 KeyCode::KeyS => Some(31),
334 KeyCode::KeyD => Some(32),
335 KeyCode::KeyF => Some(33),
336 KeyCode::KeyG => Some(34),
337 KeyCode::KeyH => Some(35),
338 KeyCode::KeyJ => Some(36),
339 KeyCode::KeyK => Some(37),
340 KeyCode::KeyL => Some(38),
341 KeyCode::Semicolon => Some(39),
342 KeyCode::Quote => Some(40),
343 KeyCode::Backquote => Some(41),
344 KeyCode::ShiftLeft => Some(42),
345 KeyCode::Backslash => Some(43),
346 KeyCode::KeyZ => Some(44),
347 KeyCode::KeyX => Some(45),
348 KeyCode::KeyC => Some(46),
349 KeyCode::KeyV => Some(47),
350 KeyCode::KeyB => Some(48),
351 KeyCode::KeyN => Some(49),
352 KeyCode::KeyM => Some(50),
353 KeyCode::Comma => Some(51),
354 KeyCode::Period => Some(52),
355 KeyCode::Slash => Some(53),
356 KeyCode::ShiftRight => Some(54),
357 KeyCode::NumpadMultiply => Some(55),
358 KeyCode::AltLeft => Some(56),
359 KeyCode::Space => Some(57),
360 KeyCode::CapsLock => Some(58),
361 KeyCode::F1 => Some(59),
362 KeyCode::F2 => Some(60),
363 KeyCode::F3 => Some(61),
364 KeyCode::F4 => Some(62),
365 KeyCode::F5 => Some(63),
366 KeyCode::F6 => Some(64),
367 KeyCode::F7 => Some(65),
368 KeyCode::F8 => Some(66),
369 KeyCode::F9 => Some(67),
370 KeyCode::F10 => Some(68),
371 KeyCode::NumLock => Some(69),
372 KeyCode::ScrollLock => Some(70),
373 KeyCode::Numpad7 => Some(71),
374 KeyCode::Numpad8 => Some(72),
375 KeyCode::Numpad9 => Some(73),
376 KeyCode::NumpadSubtract => Some(74),
377 KeyCode::Numpad4 => Some(75),
378 KeyCode::Numpad5 => Some(76),
379 KeyCode::Numpad6 => Some(77),
380 KeyCode::NumpadAdd => Some(78),
381 KeyCode::Numpad1 => Some(79),
382 KeyCode::Numpad2 => Some(80),
383 KeyCode::Numpad3 => Some(81),
384 KeyCode::Numpad0 => Some(82),
385 KeyCode::NumpadDecimal => Some(83),
386 KeyCode::Lang5 => Some(85),
387 KeyCode::IntlBackslash => Some(86),
388 KeyCode::F11 => Some(87),
389 KeyCode::F12 => Some(88),
390 KeyCode::IntlRo => Some(89),
391 KeyCode::Lang3 => Some(90),
392 KeyCode::Lang4 => Some(91),
393 KeyCode::Convert => Some(92),
394 KeyCode::KanaMode => Some(93),
395 KeyCode::NonConvert => Some(94),
396 KeyCode::NumpadEnter => Some(96),
397 KeyCode::ControlRight => Some(97),
398 KeyCode::NumpadDivide => Some(98),
399 KeyCode::PrintScreen => Some(99),
400 KeyCode::AltRight => Some(100),
401 KeyCode::Home => Some(102),
402 KeyCode::ArrowUp => Some(103),
403 KeyCode::PageUp => Some(104),
404 KeyCode::ArrowLeft => Some(105),
405 KeyCode::ArrowRight => Some(106),
406 KeyCode::End => Some(107),
407 KeyCode::ArrowDown => Some(108),
408 KeyCode::PageDown => Some(109),
409 KeyCode::Insert => Some(110),
410 KeyCode::Delete => Some(111),
411 KeyCode::AudioVolumeMute => Some(113),
412 KeyCode::AudioVolumeDown => Some(114),
413 KeyCode::AudioVolumeUp => Some(115),
414 KeyCode::NumpadEqual => Some(117),
415 KeyCode::Pause => Some(119),
416 KeyCode::NumpadComma => Some(121),
417 KeyCode::Lang1 => Some(122),
418 KeyCode::Lang2 => Some(123),
419 KeyCode::IntlYen => Some(124),
420 KeyCode::SuperLeft => Some(125),
421 KeyCode::SuperRight => Some(126),
422 KeyCode::ContextMenu => Some(127),
423 KeyCode::MediaTrackNext => Some(163),
424 KeyCode::MediaPlayPause => Some(164),
425 KeyCode::MediaTrackPrevious => Some(165),
426 KeyCode::MediaStop => Some(166),
427 KeyCode::F13 => Some(183),
428 KeyCode::F14 => Some(184),
429 KeyCode::F15 => Some(185),
430 KeyCode::F16 => Some(186),
431 KeyCode::F17 => Some(187),
432 KeyCode::F18 => Some(188),
433 KeyCode::F19 => Some(189),
434 KeyCode::F20 => Some(190),
435 KeyCode::F21 => Some(191),
436 KeyCode::F22 => Some(192),
437 KeyCode::F23 => Some(193),
438 KeyCode::F24 => Some(194),
439 _ => None,
440 }
441}
442
443pub fn keysym_to_key(keysym: u32) -> Key {
444 use xkbcommon_dl::keysyms;
445 Key::Named(match keysym {
446 // TTY function keys
447 keysyms::BackSpace => NamedKey::Backspace,
448 keysyms::Tab => NamedKey::Tab,
449 // keysyms::Linefeed => NamedKey::Linefeed,
450 keysyms::Clear => NamedKey::Clear,
451 keysyms::Return => NamedKey::Enter,
452 keysyms::Pause => NamedKey::Pause,
453 keysyms::Scroll_Lock => NamedKey::ScrollLock,
454 keysyms::Sys_Req => NamedKey::PrintScreen,
455 keysyms::Escape => NamedKey::Escape,
456 keysyms::Delete => NamedKey::Delete,
457
458 // IME keys
459 keysyms::Multi_key => NamedKey::Compose,
460 keysyms::Codeinput => NamedKey::CodeInput,
461 keysyms::SingleCandidate => NamedKey::SingleCandidate,
462 keysyms::MultipleCandidate => NamedKey::AllCandidates,
463 keysyms::PreviousCandidate => NamedKey::PreviousCandidate,
464
465 // Japanese keys
466 keysyms::Kanji => NamedKey::KanjiMode,
467 keysyms::Muhenkan => NamedKey::NonConvert,
468 keysyms::Henkan_Mode => NamedKey::Convert,
469 keysyms::Romaji => NamedKey::Romaji,
470 keysyms::Hiragana => NamedKey::Hiragana,
471 keysyms::Hiragana_Katakana => NamedKey::HiraganaKatakana,
472 keysyms::Zenkaku => NamedKey::Zenkaku,
473 keysyms::Hankaku => NamedKey::Hankaku,
474 keysyms::Zenkaku_Hankaku => NamedKey::ZenkakuHankaku,
475 // keysyms::Touroku => NamedKey::Touroku,
476 // keysyms::Massyo => NamedKey::Massyo,
477 keysyms::Kana_Lock => NamedKey::KanaMode,
478 keysyms::Kana_Shift => NamedKey::KanaMode,
479 keysyms::Eisu_Shift => NamedKey::Alphanumeric,
480 keysyms::Eisu_toggle => NamedKey::Alphanumeric,
481 // NOTE: The next three items are aliases for values we've already mapped.
482 // keysyms::Kanji_Bangou => NamedKey::CodeInput,
483 // keysyms::Zen_Koho => NamedKey::AllCandidates,
484 // keysyms::Mae_Koho => NamedKey::PreviousCandidate,
485
486 // Cursor control & motion
487 keysyms::Home => NamedKey::Home,
488 keysyms::Left => NamedKey::ArrowLeft,
489 keysyms::Up => NamedKey::ArrowUp,
490 keysyms::Right => NamedKey::ArrowRight,
491 keysyms::Down => NamedKey::ArrowDown,
492 // keysyms::Prior => NamedKey::PageUp,
493 keysyms::Page_Up => NamedKey::PageUp,
494 // keysyms::Next => NamedKey::PageDown,
495 keysyms::Page_Down => NamedKey::PageDown,
496 keysyms::End => NamedKey::End,
497 // keysyms::Begin => NamedKey::Begin,
498
499 // Misc. functions
500 keysyms::Select => NamedKey::Select,
501 keysyms::Print => NamedKey::PrintScreen,
502 keysyms::Execute => NamedKey::Execute,
503 keysyms::Insert => NamedKey::Insert,
504 keysyms::Undo => NamedKey::Undo,
505 keysyms::Redo => NamedKey::Redo,
506 keysyms::Menu => NamedKey::ContextMenu,
507 keysyms::Find => NamedKey::Find,
508 keysyms::Cancel => NamedKey::Cancel,
509 keysyms::Help => NamedKey::Help,
510 keysyms::Break => NamedKey::Pause,
511 keysyms::Mode_switch => NamedKey::ModeChange,
512 // keysyms::script_switch => NamedKey::ModeChange,
513 keysyms::Num_Lock => NamedKey::NumLock,
514
515 // Keypad keys
516 // keysyms::KP_Space => return Key::Character(" "),
517 keysyms::KP_Tab => NamedKey::Tab,
518 keysyms::KP_Enter => NamedKey::Enter,
519 keysyms::KP_F1 => NamedKey::F1,
520 keysyms::KP_F2 => NamedKey::F2,
521 keysyms::KP_F3 => NamedKey::F3,
522 keysyms::KP_F4 => NamedKey::F4,
523 keysyms::KP_Home => NamedKey::Home,
524 keysyms::KP_Left => NamedKey::ArrowLeft,
525 keysyms::KP_Up => NamedKey::ArrowUp,
526 keysyms::KP_Right => NamedKey::ArrowRight,
527 keysyms::KP_Down => NamedKey::ArrowDown,
528 // keysyms::KP_Prior => NamedKey::PageUp,
529 keysyms::KP_Page_Up => NamedKey::PageUp,
530 // keysyms::KP_Next => NamedKey::PageDown,
531 keysyms::KP_Page_Down => NamedKey::PageDown,
532 keysyms::KP_End => NamedKey::End,
533 // This is the key labeled "5" on the numpad when NumLock is off.
534 // keysyms::KP_Begin => NamedKey::Begin,
535 keysyms::KP_Insert => NamedKey::Insert,
536 keysyms::KP_Delete => NamedKey::Delete,
537 // keysyms::KP_Equal => NamedKey::Equal,
538 // keysyms::KP_Multiply => NamedKey::Multiply,
539 // keysyms::KP_Add => NamedKey::Add,
540 // keysyms::KP_Separator => NamedKey::Separator,
541 // keysyms::KP_Subtract => NamedKey::Subtract,
542 // keysyms::KP_Decimal => NamedKey::Decimal,
543 // keysyms::KP_Divide => NamedKey::Divide,
544
545 // keysyms::KP_0 => return Key::Character("0"),
546 // keysyms::KP_1 => return Key::Character("1"),
547 // keysyms::KP_2 => return Key::Character("2"),
548 // keysyms::KP_3 => return Key::Character("3"),
549 // keysyms::KP_4 => return Key::Character("4"),
550 // keysyms::KP_5 => return Key::Character("5"),
551 // keysyms::KP_6 => return Key::Character("6"),
552 // keysyms::KP_7 => return Key::Character("7"),
553 // keysyms::KP_8 => return Key::Character("8"),
554 // keysyms::KP_9 => return Key::Character("9"),
555
556 // Function keys
557 keysyms::F1 => NamedKey::F1,
558 keysyms::F2 => NamedKey::F2,
559 keysyms::F3 => NamedKey::F3,
560 keysyms::F4 => NamedKey::F4,
561 keysyms::F5 => NamedKey::F5,
562 keysyms::F6 => NamedKey::F6,
563 keysyms::F7 => NamedKey::F7,
564 keysyms::F8 => NamedKey::F8,
565 keysyms::F9 => NamedKey::F9,
566 keysyms::F10 => NamedKey::F10,
567 keysyms::F11 => NamedKey::F11,
568 keysyms::F12 => NamedKey::F12,
569 keysyms::F13 => NamedKey::F13,
570 keysyms::F14 => NamedKey::F14,
571 keysyms::F15 => NamedKey::F15,
572 keysyms::F16 => NamedKey::F16,
573 keysyms::F17 => NamedKey::F17,
574 keysyms::F18 => NamedKey::F18,
575 keysyms::F19 => NamedKey::F19,
576 keysyms::F20 => NamedKey::F20,
577 keysyms::F21 => NamedKey::F21,
578 keysyms::F22 => NamedKey::F22,
579 keysyms::F23 => NamedKey::F23,
580 keysyms::F24 => NamedKey::F24,
581 keysyms::F25 => NamedKey::F25,
582 keysyms::F26 => NamedKey::F26,
583 keysyms::F27 => NamedKey::F27,
584 keysyms::F28 => NamedKey::F28,
585 keysyms::F29 => NamedKey::F29,
586 keysyms::F30 => NamedKey::F30,
587 keysyms::F31 => NamedKey::F31,
588 keysyms::F32 => NamedKey::F32,
589 keysyms::F33 => NamedKey::F33,
590 keysyms::F34 => NamedKey::F34,
591 keysyms::F35 => NamedKey::F35,
592
593 // Modifiers
594 keysyms::Shift_L => NamedKey::Shift,
595 keysyms::Shift_R => NamedKey::Shift,
596 keysyms::Control_L => NamedKey::Control,
597 keysyms::Control_R => NamedKey::Control,
598 keysyms::Caps_Lock => NamedKey::CapsLock,
599 // keysyms::Shift_Lock => NamedKey::ShiftLock,
600
601 // keysyms::Meta_L => NamedKey::Meta,
602 // keysyms::Meta_R => NamedKey::Meta,
603 keysyms::Alt_L => NamedKey::Alt,
604 keysyms::Alt_R => NamedKey::Alt,
605 keysyms::Super_L => NamedKey::Super,
606 keysyms::Super_R => NamedKey::Super,
607 keysyms::Hyper_L => NamedKey::Hyper,
608 keysyms::Hyper_R => NamedKey::Hyper,
609
610 // XKB function and modifier keys
611 // keysyms::ISO_Lock => NamedKey::IsoLock,
612 // keysyms::ISO_Level2_Latch => NamedKey::IsoLevel2Latch,
613 keysyms::ISO_Level3_Shift => NamedKey::AltGraph,
614 keysyms::ISO_Level3_Latch => NamedKey::AltGraph,
615 keysyms::ISO_Level3_Lock => NamedKey::AltGraph,
616 // keysyms::ISO_Level5_Shift => NamedKey::IsoLevel5Shift,
617 // keysyms::ISO_Level5_Latch => NamedKey::IsoLevel5Latch,
618 // keysyms::ISO_Level5_Lock => NamedKey::IsoLevel5Lock,
619 // keysyms::ISO_Group_Shift => NamedKey::IsoGroupShift,
620 // keysyms::ISO_Group_Latch => NamedKey::IsoGroupLatch,
621 // keysyms::ISO_Group_Lock => NamedKey::IsoGroupLock,
622 keysyms::ISO_Next_Group => NamedKey::GroupNext,
623 // keysyms::ISO_Next_Group_Lock => NamedKey::GroupNextLock,
624 keysyms::ISO_Prev_Group => NamedKey::GroupPrevious,
625 // keysyms::ISO_Prev_Group_Lock => NamedKey::GroupPreviousLock,
626 keysyms::ISO_First_Group => NamedKey::GroupFirst,
627 // keysyms::ISO_First_Group_Lock => NamedKey::GroupFirstLock,
628 keysyms::ISO_Last_Group => NamedKey::GroupLast,
629 // keysyms::ISO_Last_Group_Lock => NamedKey::GroupLastLock,
630 //
631 keysyms::ISO_Left_Tab => NamedKey::Tab,
632 // keysyms::ISO_Move_Line_Up => NamedKey::IsoMoveLineUp,
633 // keysyms::ISO_Move_Line_Down => NamedKey::IsoMoveLineDown,
634 // keysyms::ISO_Partial_Line_Up => NamedKey::IsoPartialLineUp,
635 // keysyms::ISO_Partial_Line_Down => NamedKey::IsoPartialLineDown,
636 // keysyms::ISO_Partial_Space_Left => NamedKey::IsoPartialSpaceLeft,
637 // keysyms::ISO_Partial_Space_Right => NamedKey::IsoPartialSpaceRight,
638 // keysyms::ISO_Set_Margin_Left => NamedKey::IsoSetMarginLeft,
639 // keysyms::ISO_Set_Margin_Right => NamedKey::IsoSetMarginRight,
640 // keysyms::ISO_Release_Margin_Left => NamedKey::IsoReleaseMarginLeft,
641 // keysyms::ISO_Release_Margin_Right => NamedKey::IsoReleaseMarginRight,
642 // keysyms::ISO_Release_Both_Margins => NamedKey::IsoReleaseBothMargins,
643 // keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastCursorLeft,
644 // keysyms::ISO_Fast_Cursor_Right => NamedKey::IsoFastCursorRight,
645 // keysyms::ISO_Fast_Cursor_Up => NamedKey::IsoFastCursorUp,
646 // keysyms::ISO_Fast_Cursor_Down => NamedKey::IsoFastCursorDown,
647 // keysyms::ISO_Continuous_Underline => NamedKey::IsoContinuousUnderline,
648 // keysyms::ISO_Discontinuous_Underline => NamedKey::IsoDiscontinuousUnderline,
649 // keysyms::ISO_Emphasize => NamedKey::IsoEmphasize,
650 // keysyms::ISO_Center_Object => NamedKey::IsoCenterObject,
651 keysyms::ISO_Enter => NamedKey::Enter,
652
653 // dead_grave..dead_currency
654
655 // dead_lowline..dead_longsolidusoverlay
656
657 // dead_a..dead_capital_schwa
658
659 // dead_greek
660
661 // First_Virtual_Screen..Terminate_Server
662
663 // AccessX_Enable..AudibleBell_Enable
664
665 // Pointer_Left..Pointer_Drag5
666
667 // Pointer_EnableKeys..Pointer_DfltBtnPrev
668
669 // ch..C_H
670
671 // 3270 terminal keys
672 // keysyms::3270_Duplicate => NamedKey::Duplicate,
673 // keysyms::3270_FieldMark => NamedKey::FieldMark,
674 // keysyms::3270_Right2 => NamedKey::Right2,
675 // keysyms::3270_Left2 => NamedKey::Left2,
676 // keysyms::3270_BackTab => NamedKey::BackTab,
677 keysyms::_3270_EraseEOF => NamedKey::EraseEof,
678 // keysyms::3270_EraseInput => NamedKey::EraseInput,
679 // keysyms::3270_Reset => NamedKey::Reset,
680 // keysyms::3270_Quit => NamedKey::Quit,
681 // keysyms::3270_PA1 => NamedKey::Pa1,
682 // keysyms::3270_PA2 => NamedKey::Pa2,
683 // keysyms::3270_PA3 => NamedKey::Pa3,
684 // keysyms::3270_Test => NamedKey::Test,
685 keysyms::_3270_Attn => NamedKey::Attn,
686 // keysyms::3270_CursorBlink => NamedKey::CursorBlink,
687 // keysyms::3270_AltCursor => NamedKey::AltCursor,
688 // keysyms::3270_KeyClick => NamedKey::KeyClick,
689 // keysyms::3270_Jump => NamedKey::Jump,
690 // keysyms::3270_Ident => NamedKey::Ident,
691 // keysyms::3270_Rule => NamedKey::Rule,
692 // keysyms::3270_Copy => NamedKey::Copy,
693 keysyms::_3270_Play => NamedKey::Play,
694 // keysyms::3270_Setup => NamedKey::Setup,
695 // keysyms::3270_Record => NamedKey::Record,
696 // keysyms::3270_ChangeScreen => NamedKey::ChangeScreen,
697 // keysyms::3270_DeleteWord => NamedKey::DeleteWord,
698 keysyms::_3270_ExSelect => NamedKey::ExSel,
699 keysyms::_3270_CursorSelect => NamedKey::CrSel,
700 keysyms::_3270_PrintScreen => NamedKey::PrintScreen,
701 keysyms::_3270_Enter => NamedKey::Enter,
702
703 keysyms::space => NamedKey::Space,
704 // exclam..Sinh_kunddaliya
705
706 // XFree86
707 // keysyms::XF86_ModeLock => NamedKey::ModeLock,
708
709 // XFree86 - Backlight controls
710 keysyms::XF86_MonBrightnessUp => NamedKey::BrightnessUp,
711 keysyms::XF86_MonBrightnessDown => NamedKey::BrightnessDown,
712 // keysyms::XF86_KbdLightOnOff => NamedKey::LightOnOff,
713 // keysyms::XF86_KbdBrightnessUp => NamedKey::KeyboardBrightnessUp,
714 // keysyms::XF86_KbdBrightnessDown => NamedKey::KeyboardBrightnessDown,
715
716 // XFree86 - "Internet"
717 keysyms::XF86_Standby => NamedKey::Standby,
718 keysyms::XF86_AudioLowerVolume => NamedKey::AudioVolumeDown,
719 keysyms::XF86_AudioRaiseVolume => NamedKey::AudioVolumeUp,
720 keysyms::XF86_AudioPlay => NamedKey::MediaPlay,
721 keysyms::XF86_AudioStop => NamedKey::MediaStop,
722 keysyms::XF86_AudioPrev => NamedKey::MediaTrackPrevious,
723 keysyms::XF86_AudioNext => NamedKey::MediaTrackNext,
724 keysyms::XF86_HomePage => NamedKey::BrowserHome,
725 keysyms::XF86_Mail => NamedKey::LaunchMail,
726 // keysyms::XF86_Start => NamedKey::Start,
727 keysyms::XF86_Search => NamedKey::BrowserSearch,
728 keysyms::XF86_AudioRecord => NamedKey::MediaRecord,
729
730 // XFree86 - PDA
731 keysyms::XF86_Calculator => NamedKey::LaunchApplication2,
732 // keysyms::XF86_Memo => NamedKey::Memo,
733 // keysyms::XF86_ToDoList => NamedKey::ToDoList,
734 keysyms::XF86_Calendar => NamedKey::LaunchCalendar,
735 keysyms::XF86_PowerDown => NamedKey::Power,
736 // keysyms::XF86_ContrastAdjust => NamedKey::AdjustContrast,
737 // keysyms::XF86_RockerUp => NamedKey::RockerUp,
738 // keysyms::XF86_RockerDown => NamedKey::RockerDown,
739 // keysyms::XF86_RockerEnter => NamedKey::RockerEnter,
740
741 // XFree86 - More "Internet"
742 keysyms::XF86_Back => NamedKey::BrowserBack,
743 keysyms::XF86_Forward => NamedKey::BrowserForward,
744 // keysyms::XF86_Stop => NamedKey::Stop,
745 keysyms::XF86_Refresh => NamedKey::BrowserRefresh,
746 keysyms::XF86_PowerOff => NamedKey::Power,
747 keysyms::XF86_WakeUp => NamedKey::WakeUp,
748 keysyms::XF86_Eject => NamedKey::Eject,
749 keysyms::XF86_ScreenSaver => NamedKey::LaunchScreenSaver,
750 keysyms::XF86_WWW => NamedKey::LaunchWebBrowser,
751 keysyms::XF86_Sleep => NamedKey::Standby,
752 keysyms::XF86_Favorites => NamedKey::BrowserFavorites,
753 keysyms::XF86_AudioPause => NamedKey::MediaPause,
754 // keysyms::XF86_AudioMedia => NamedKey::AudioMedia,
755 keysyms::XF86_MyComputer => NamedKey::LaunchApplication1,
756 // keysyms::XF86_VendorHome => NamedKey::VendorHome,
757 // keysyms::XF86_LightBulb => NamedKey::LightBulb,
758 // keysyms::XF86_Shop => NamedKey::BrowserShop,
759 // keysyms::XF86_History => NamedKey::BrowserHistory,
760 // keysyms::XF86_OpenURL => NamedKey::OpenUrl,
761 // keysyms::XF86_AddFavorite => NamedKey::AddFavorite,
762 // keysyms::XF86_HotLinks => NamedKey::HotLinks,
763 // keysyms::XF86_BrightnessAdjust => NamedKey::BrightnessAdjust,
764 // keysyms::XF86_Finance => NamedKey::BrowserFinance,
765 // keysyms::XF86_Community => NamedKey::BrowserCommunity,
766 keysyms::XF86_AudioRewind => NamedKey::MediaRewind,
767 // keysyms::XF86_BackForward => Key::???,
768 // XF86_Launch0..XF86_LaunchF
769
770 // XF86_ApplicationLeft..XF86_CD
771 keysyms::XF86_Calculater => NamedKey::LaunchApplication2, // Nice typo, libxkbcommon :)
772 // XF86_Clear
773 keysyms::XF86_Close => NamedKey::Close,
774 keysyms::XF86_Copy => NamedKey::Copy,
775 keysyms::XF86_Cut => NamedKey::Cut,
776 // XF86_Display..XF86_Documents
777 keysyms::XF86_Excel => NamedKey::LaunchSpreadsheet,
778 // XF86_Explorer..XF86iTouch
779 keysyms::XF86_LogOff => NamedKey::LogOff,
780 // XF86_Market..XF86_MenuPB
781 keysyms::XF86_MySites => NamedKey::BrowserFavorites,
782 keysyms::XF86_New => NamedKey::New,
783 // XF86_News..XF86_OfficeHome
784 keysyms::XF86_Open => NamedKey::Open,
785 // XF86_Option
786 keysyms::XF86_Paste => NamedKey::Paste,
787 keysyms::XF86_Phone => NamedKey::LaunchPhone,
788 // XF86_Q
789 keysyms::XF86_Reply => NamedKey::MailReply,
790 keysyms::XF86_Reload => NamedKey::BrowserRefresh,
791 // XF86_RotateWindows..XF86_RotationKB
792 keysyms::XF86_Save => NamedKey::Save,
793 // XF86_ScrollUp..XF86_ScrollClick
794 keysyms::XF86_Send => NamedKey::MailSend,
795 keysyms::XF86_Spell => NamedKey::SpellCheck,
796 keysyms::XF86_SplitScreen => NamedKey::SplitScreenToggle,
797 // XF86_Support..XF86_User2KB
798 keysyms::XF86_Video => NamedKey::LaunchMediaPlayer,
799 // XF86_WheelButton
800 keysyms::XF86_Word => NamedKey::LaunchWordProcessor,
801 // XF86_Xfer
802 keysyms::XF86_ZoomIn => NamedKey::ZoomIn,
803 keysyms::XF86_ZoomOut => NamedKey::ZoomOut,
804
805 // XF86_Away..XF86_Messenger
806 keysyms::XF86_WebCam => NamedKey::LaunchWebCam,
807 keysyms::XF86_MailForward => NamedKey::MailForward,
808 // XF86_Pictures
809 keysyms::XF86_Music => NamedKey::LaunchMusicPlayer,
810
811 // XF86_Battery..XF86_UWB
812 //
813 keysyms::XF86_AudioForward => NamedKey::MediaFastForward,
814 // XF86_AudioRepeat
815 keysyms::XF86_AudioRandomPlay => NamedKey::RandomToggle,
816 keysyms::XF86_Subtitle => NamedKey::Subtitle,
817 keysyms::XF86_AudioCycleTrack => NamedKey::MediaAudioTrack,
818 // XF86_CycleAngle..XF86_Blue
819 //
820 keysyms::XF86_Suspend => NamedKey::Standby,
821 keysyms::XF86_Hibernate => NamedKey::Hibernate,
822 // XF86_TouchpadToggle..XF86_TouchpadOff
823 //
824 keysyms::XF86_AudioMute => NamedKey::AudioVolumeMute,
825
826 // XF86_Switch_VT_1..XF86_Switch_VT_12
827
828 // XF86_Ungrab..XF86_ClearGrab
829 keysyms::XF86_Next_VMode => NamedKey::VideoModeNext,
830 // keysyms::XF86_Prev_VMode => NamedKey::VideoModePrevious,
831 // XF86_LogWindowTree..XF86_LogGrabInfo
832
833 // SunFA_Grave..SunFA_Cedilla
834
835 // keysyms::SunF36 => NamedKey::F36 | NamedKey::F11,
836 // keysyms::SunF37 => NamedKey::F37 | NamedKey::F12,
837
838 // keysyms::SunSys_Req => NamedKey::PrintScreen,
839 // The next couple of xkb (until SunStop) are already handled.
840 // SunPrint_Screen..SunPageDown
841
842 // SunUndo..SunFront
843 keysyms::SUN_Copy => NamedKey::Copy,
844 keysyms::SUN_Open => NamedKey::Open,
845 keysyms::SUN_Paste => NamedKey::Paste,
846 keysyms::SUN_Cut => NamedKey::Cut,
847
848 // SunPowerSwitch
849 keysyms::SUN_AudioLowerVolume => NamedKey::AudioVolumeDown,
850 keysyms::SUN_AudioMute => NamedKey::AudioVolumeMute,
851 keysyms::SUN_AudioRaiseVolume => NamedKey::AudioVolumeUp,
852 // SUN_VideoDegauss
853 keysyms::SUN_VideoLowerBrightness => NamedKey::BrightnessDown,
854 keysyms::SUN_VideoRaiseBrightness => NamedKey::BrightnessUp,
855 // SunPowerSwitchShift
856 //
857 0 => return Key::Unidentified(NativeKey::Unidentified),
858 _ => return Key::Unidentified(NativeKey::Xkb(keysym)),
859 })
860}
861
862pub fn keysym_location(keysym: u32) -> KeyLocation {
863 use xkbcommon_dl::keysyms;
864 match keysym {
865 keysyms::Shift_L
866 | keysyms::Control_L
867 | keysyms::Meta_L
868 | keysyms::Alt_L
869 | keysyms::Super_L
870 | keysyms::Hyper_L => KeyLocation::Left,
871 keysyms::Shift_R
872 | keysyms::Control_R
873 | keysyms::Meta_R
874 | keysyms::Alt_R
875 | keysyms::Super_R
876 | keysyms::Hyper_R => KeyLocation::Right,
877 keysyms::KP_0
878 | keysyms::KP_1
879 | keysyms::KP_2
880 | keysyms::KP_3
881 | keysyms::KP_4
882 | keysyms::KP_5
883 | keysyms::KP_6
884 | keysyms::KP_7
885 | keysyms::KP_8
886 | keysyms::KP_9
887 | keysyms::KP_Space
888 | keysyms::KP_Tab
889 | keysyms::KP_Enter
890 | keysyms::KP_F1
891 | keysyms::KP_F2
892 | keysyms::KP_F3
893 | keysyms::KP_F4
894 | keysyms::KP_Home
895 | keysyms::KP_Left
896 | keysyms::KP_Up
897 | keysyms::KP_Right
898 | keysyms::KP_Down
899 | keysyms::KP_Page_Up
900 | keysyms::KP_Page_Down
901 | keysyms::KP_End
902 | keysyms::KP_Begin
903 | keysyms::KP_Insert
904 | keysyms::KP_Delete
905 | keysyms::KP_Equal
906 | keysyms::KP_Multiply
907 | keysyms::KP_Add
908 | keysyms::KP_Separator
909 | keysyms::KP_Subtract
910 | keysyms::KP_Decimal
911 | keysyms::KP_Divide => KeyLocation::Numpad,
912 _ => KeyLocation::Standard,
913 }
914}
915
916#[derive(Debug)]
917pub struct XkbKeymap {
918 keymap: NonNull<xkb_keymap>,
919 _mods_indices: ModsIndices,
920 pub _core_keyboard_id: i32,
921}
922
923impl XkbKeymap {
924 #[cfg(wayland_platform)]
925 pub fn from_fd(context: &XkbContext, fd: OwnedFd, size: usize) -> Option<Self> {
926 let map = unsafe { MmapOptions::new().len(size).map_copy_read_only(&fd).ok()? };
927
928 let keymap = unsafe {
929 let keymap = (XKBH.xkb_keymap_new_from_string)(
930 (*context).as_ptr(),
931 map.as_ptr() as *const _,
932 xkb::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1,
933 xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS,
934 );
935 NonNull::new(keymap)?
936 };
937
938 Some(Self::new_inner(keymap, 0))
939 }
940
941 #[cfg(x11_platform)]
942 pub fn from_x11_keymap(
943 context: &XkbContext,
944 xcb: *mut xcb_connection_t,
945 core_keyboard_id: i32,
946 ) -> Option<Self> {
947 let keymap = unsafe {
948 (XKBXH.xkb_x11_keymap_new_from_device)(
949 context.as_ptr(),
950 xcb,
951 core_keyboard_id,
952 xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS,
953 )
954 };
955 let keymap = NonNull::new(keymap)?;
956 Some(Self::new_inner(keymap, core_keyboard_id))
957 }
958
959 fn new_inner(keymap: NonNull<xkb_keymap>, _core_keyboard_id: i32) -> Self {
960 let mods_indices = ModsIndices {
961 shift: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_SHIFT),
962 caps: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_CAPS),
963 ctrl: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_CTRL),
964 alt: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_ALT),
965 num: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_NUM),
966 mod3: mod_index_for_name(keymap, b"Mod3\0"),
967 logo: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_LOGO),
968 mod5: mod_index_for_name(keymap, b"Mod5\0"),
969 };
970
971 Self {
972 keymap,
973 _mods_indices: mods_indices,
974 _core_keyboard_id,
975 }
976 }
977
978 #[cfg(x11_platform)]
979 pub fn mods_indices(&self) -> ModsIndices {
980 self._mods_indices
981 }
982
983 pub fn first_keysym_by_level(
984 &mut self,
985 layout: xkb_layout_index_t,
986 keycode: xkb_keycode_t,
987 ) -> xkb_keysym_t {
988 unsafe {
989 let mut keysyms = ptr::null();
990 let count = (XKBH.xkb_keymap_key_get_syms_by_level)(
991 self.keymap.as_ptr(),
992 keycode,
993 layout,
994 // NOTE: The level should be zero to ignore modifiers.
995 0,
996 &mut keysyms,
997 );
998
999 if count == 1 {
1000 *keysyms
1001 } else {
1002 0
1003 }
1004 }
1005 }
1006
1007 /// Check whether the given key repeats.
1008 pub fn key_repeats(&mut self, keycode: xkb_keycode_t) -> bool {
1009 unsafe { (XKBH.xkb_keymap_key_repeats)(self.keymap.as_ptr(), keycode) == 1 }
1010 }
1011}
1012
1013impl Drop for XkbKeymap {
1014 fn drop(&mut self) {
1015 unsafe {
1016 (XKBH.xkb_keymap_unref)(self.keymap.as_ptr());
1017 };
1018 }
1019}
1020
1021impl Deref for XkbKeymap {
1022 type Target = NonNull<xkb_keymap>;
1023 fn deref(&self) -> &Self::Target {
1024 &self.keymap
1025 }
1026}
1027
1028/// Modifier index in the keymap.
1029#[derive(Default, Debug, Clone, Copy)]
1030pub struct ModsIndices {
1031 pub shift: Option<xkb_mod_index_t>,
1032 pub caps: Option<xkb_mod_index_t>,
1033 pub ctrl: Option<xkb_mod_index_t>,
1034 pub alt: Option<xkb_mod_index_t>,
1035 pub num: Option<xkb_mod_index_t>,
1036 pub mod3: Option<xkb_mod_index_t>,
1037 pub logo: Option<xkb_mod_index_t>,
1038 pub mod5: Option<xkb_mod_index_t>,
1039}
1040
1041fn mod_index_for_name(keymap: NonNull<xkb_keymap>, name: &[u8]) -> Option<xkb_mod_index_t> {
1042 unsafe {
1043 let mod_index: u32 =
1044 (XKBH.xkb_keymap_mod_get_index)(keymap.as_ptr(), name.as_ptr() as *const c_char);
1045 if mod_index == XKB_MOD_INVALID {
1046 None
1047 } else {
1048 Some(mod_index)
1049 }
1050 }
1051}
1052