1use 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
23pub fn raw_keycode_to_physicalkey(keycode: u32) -> PhysicalKey {
27 scancode_to_physicalkey(keycode.saturating_sub(8))
28}
29
30pub fn scancode_to_physicalkey(scancode: u32) -> PhysicalKey {
34 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 96 => KeyCode::NumpadEnter,
139 97 => KeyCode::ControlRight,
140 98 => KeyCode::NumpadDivide,
141 99 => KeyCode::PrintScreen,
142 100 => KeyCode::AltRight,
143 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 113 => KeyCode::AudioVolumeMute,
156 114 => KeyCode::AudioVolumeDown,
157 115 => KeyCode::AudioVolumeUp,
158 117 => KeyCode::NumpadEqual,
160 119 => KeyCode::Pause,
162 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 163 => KeyCode::MediaTrackNext,
206 164 => KeyCode::MediaPlayPause,
207 165 => KeyCode::MediaTrackPrevious,
208 166 => KeyCode::MediaStop,
209 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 240 => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified),
278 _ => 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 keysyms::BackSpace => NamedKey::Backspace,
448 keysyms::Tab => NamedKey::Tab,
449 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 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 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::Kana_Lock => NamedKey::KanaMode,
478 keysyms::Kana_Shift => NamedKey::KanaMode,
479 keysyms::Eisu_Shift => NamedKey::Alphanumeric,
480 keysyms::Eisu_toggle => NamedKey::Alphanumeric,
481 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::Page_Up => NamedKey::PageUp,
494 keysyms::Page_Down => NamedKey::PageDown,
496 keysyms::End => NamedKey::End,
497 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::Num_Lock => NamedKey::NumLock,
514
515 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_Page_Up => NamedKey::PageUp,
530 keysyms::KP_Page_Down => NamedKey::PageDown,
532 keysyms::KP_End => NamedKey::End,
533 keysyms::KP_Insert => NamedKey::Insert,
536 keysyms::KP_Delete => NamedKey::Delete,
537 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 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::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 keysyms::ISO_Level3_Shift => NamedKey::AltGraph,
614 keysyms::ISO_Level3_Latch => NamedKey::AltGraph,
615 keysyms::ISO_Level3_Lock => NamedKey::AltGraph,
616 keysyms::ISO_Next_Group => NamedKey::GroupNext,
623 keysyms::ISO_Prev_Group => NamedKey::GroupPrevious,
625 keysyms::ISO_First_Group => NamedKey::GroupFirst,
627 keysyms::ISO_Last_Group => NamedKey::GroupLast,
629 keysyms::ISO_Left_Tab => NamedKey::Tab,
631 keysyms::ISO_Enter => NamedKey::Enter,
651
652 keysyms::_3270_EraseEOF => NamedKey::EraseEof,
677 keysyms::_3270_Attn => NamedKey::Attn,
685 keysyms::_3270_Play => NamedKey::Play,
693 keysyms::_3270_ExSelect => NamedKey::ExSel,
698 keysyms::_3270_CursorSelect => NamedKey::CrSel,
699 keysyms::_3270_PrintScreen => NamedKey::PrintScreen,
700 keysyms::_3270_Enter => NamedKey::Enter,
701
702 keysyms::space => NamedKey::Space,
703 keysyms::XF86_MonBrightnessUp => NamedKey::BrightnessUp,
710 keysyms::XF86_MonBrightnessDown => NamedKey::BrightnessDown,
711 keysyms::XF86_Standby => NamedKey::Standby,
717 keysyms::XF86_AudioLowerVolume => NamedKey::AudioVolumeDown,
718 keysyms::XF86_AudioRaiseVolume => NamedKey::AudioVolumeUp,
719 keysyms::XF86_AudioPlay => NamedKey::MediaPlay,
720 keysyms::XF86_AudioStop => NamedKey::MediaStop,
721 keysyms::XF86_AudioPrev => NamedKey::MediaTrackPrevious,
722 keysyms::XF86_AudioNext => NamedKey::MediaTrackNext,
723 keysyms::XF86_HomePage => NamedKey::BrowserHome,
724 keysyms::XF86_Mail => NamedKey::LaunchMail,
725 keysyms::XF86_Search => NamedKey::BrowserSearch,
727 keysyms::XF86_AudioRecord => NamedKey::MediaRecord,
728
729 keysyms::XF86_Calculator => NamedKey::LaunchApplication2,
731 keysyms::XF86_Calendar => NamedKey::LaunchCalendar,
734 keysyms::XF86_PowerDown => NamedKey::Power,
735 keysyms::XF86_Back => NamedKey::BrowserBack,
742 keysyms::XF86_Forward => NamedKey::BrowserForward,
743 keysyms::XF86_Refresh => NamedKey::BrowserRefresh,
745 keysyms::XF86_PowerOff => NamedKey::Power,
746 keysyms::XF86_WakeUp => NamedKey::WakeUp,
747 keysyms::XF86_Eject => NamedKey::Eject,
748 keysyms::XF86_ScreenSaver => NamedKey::LaunchScreenSaver,
749 keysyms::XF86_WWW => NamedKey::LaunchWebBrowser,
750 keysyms::XF86_Sleep => NamedKey::Standby,
751 keysyms::XF86_Favorites => NamedKey::BrowserFavorites,
752 keysyms::XF86_AudioPause => NamedKey::MediaPause,
753 keysyms::XF86_MyComputer => NamedKey::LaunchApplication1,
755 keysyms::XF86_AudioRewind => NamedKey::MediaRewind,
766 keysyms::XF86_Calculater => NamedKey::LaunchApplication2, keysyms::XF86_Close => NamedKey::Close,
773 keysyms::XF86_Copy => NamedKey::Copy,
774 keysyms::XF86_Cut => NamedKey::Cut,
775 keysyms::XF86_Excel => NamedKey::LaunchSpreadsheet,
777 keysyms::XF86_LogOff => NamedKey::LogOff,
779 keysyms::XF86_MySites => NamedKey::BrowserFavorites,
781 keysyms::XF86_New => NamedKey::New,
782 keysyms::XF86_Open => NamedKey::Open,
784 keysyms::XF86_Paste => NamedKey::Paste,
786 keysyms::XF86_Phone => NamedKey::LaunchPhone,
787 keysyms::XF86_Reply => NamedKey::MailReply,
789 keysyms::XF86_Reload => NamedKey::BrowserRefresh,
790 keysyms::XF86_Save => NamedKey::Save,
792 keysyms::XF86_Send => NamedKey::MailSend,
794 keysyms::XF86_Spell => NamedKey::SpellCheck,
795 keysyms::XF86_SplitScreen => NamedKey::SplitScreenToggle,
796 keysyms::XF86_Video => NamedKey::LaunchMediaPlayer,
798 keysyms::XF86_Word => NamedKey::LaunchWordProcessor,
800 keysyms::XF86_ZoomIn => NamedKey::ZoomIn,
802 keysyms::XF86_ZoomOut => NamedKey::ZoomOut,
803
804 keysyms::XF86_WebCam => NamedKey::LaunchWebCam,
806 keysyms::XF86_MailForward => NamedKey::MailForward,
807 keysyms::XF86_Music => NamedKey::LaunchMusicPlayer,
809
810 keysyms::XF86_AudioForward => NamedKey::MediaFastForward,
812 keysyms::XF86_AudioRandomPlay => NamedKey::RandomToggle,
814 keysyms::XF86_Subtitle => NamedKey::Subtitle,
815 keysyms::XF86_AudioCycleTrack => NamedKey::MediaAudioTrack,
816 keysyms::XF86_Suspend => NamedKey::Standby,
818 keysyms::XF86_Hibernate => NamedKey::Hibernate,
819 keysyms::XF86_AudioMute => NamedKey::AudioVolumeMute,
821
822 keysyms::XF86_Next_VMode => NamedKey::VideoModeNext,
826 keysyms::SUN_Copy => NamedKey::Copy,
840 keysyms::SUN_Open => NamedKey::Open,
841 keysyms::SUN_Paste => NamedKey::Paste,
842 keysyms::SUN_Cut => NamedKey::Cut,
843
844 keysyms::SUN_AudioLowerVolume => NamedKey::AudioVolumeDown,
846 keysyms::SUN_AudioMute => NamedKey::AudioVolumeMute,
847 keysyms::SUN_AudioRaiseVolume => NamedKey::AudioVolumeUp,
848 keysyms::SUN_VideoLowerBrightness => NamedKey::BrightnessDown,
850 keysyms::SUN_VideoRaiseBrightness => NamedKey::BrightnessUp,
851 0 => return Key::Unidentified(NativeKey::Unidentified),
853 _ => return Key::Unidentified(NativeKey::Xkb(keysym)),
854 })
855}
856
857pub fn keysym_location(keysym: u32) -> KeyLocation {
858 use xkbcommon_dl::keysyms;
859 match keysym {
860 keysyms::Shift_L
861 | keysyms::Control_L
862 | keysyms::Meta_L
863 | keysyms::Alt_L
864 | keysyms::Super_L
865 | keysyms::Hyper_L => KeyLocation::Left,
866 keysyms::Shift_R
867 | keysyms::Control_R
868 | keysyms::Meta_R
869 | keysyms::Alt_R
870 | keysyms::Super_R
871 | keysyms::Hyper_R => KeyLocation::Right,
872 keysyms::KP_0
873 | keysyms::KP_1
874 | keysyms::KP_2
875 | keysyms::KP_3
876 | keysyms::KP_4
877 | keysyms::KP_5
878 | keysyms::KP_6
879 | keysyms::KP_7
880 | keysyms::KP_8
881 | keysyms::KP_9
882 | keysyms::KP_Space
883 | keysyms::KP_Tab
884 | keysyms::KP_Enter
885 | keysyms::KP_F1
886 | keysyms::KP_F2
887 | keysyms::KP_F3
888 | keysyms::KP_F4
889 | keysyms::KP_Home
890 | keysyms::KP_Left
891 | keysyms::KP_Up
892 | keysyms::KP_Right
893 | keysyms::KP_Down
894 | keysyms::KP_Page_Up
895 | keysyms::KP_Page_Down
896 | keysyms::KP_End
897 | keysyms::KP_Begin
898 | keysyms::KP_Insert
899 | keysyms::KP_Delete
900 | keysyms::KP_Equal
901 | keysyms::KP_Multiply
902 | keysyms::KP_Add
903 | keysyms::KP_Separator
904 | keysyms::KP_Subtract
905 | keysyms::KP_Decimal
906 | keysyms::KP_Divide => KeyLocation::Numpad,
907 _ => KeyLocation::Standard,
908 }
909}
910
911#[derive(Debug)]
912pub struct XkbKeymap {
913 keymap: NonNull<xkb_keymap>,
914 _mods_indices: ModsIndices,
915 pub _core_keyboard_id: i32,
916}
917
918impl XkbKeymap {
919 #[cfg(wayland_platform)]
920 pub fn from_fd(context: &XkbContext, fd: OwnedFd, size: usize) -> Option<Self> {
921 let map = unsafe { MmapOptions::new().len(size).map_copy_read_only(&fd).ok()? };
922
923 let keymap = unsafe {
924 let keymap = (XKBH.xkb_keymap_new_from_string)(
925 (*context).as_ptr(),
926 map.as_ptr() as *const _,
927 xkb::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1,
928 xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS,
929 );
930 NonNull::new(keymap)?
931 };
932
933 Some(Self::new_inner(keymap, 0))
934 }
935
936 #[cfg(x11_platform)]
937 pub fn from_x11_keymap(
938 context: &XkbContext,
939 xcb: *mut xcb_connection_t,
940 core_keyboard_id: i32,
941 ) -> Option<Self> {
942 let keymap = unsafe {
943 (XKBXH.xkb_x11_keymap_new_from_device)(
944 context.as_ptr(),
945 xcb,
946 core_keyboard_id,
947 xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS,
948 )
949 };
950 let keymap = NonNull::new(keymap)?;
951 Some(Self::new_inner(keymap, core_keyboard_id))
952 }
953
954 fn new_inner(keymap: NonNull<xkb_keymap>, _core_keyboard_id: i32) -> Self {
955 let mods_indices = ModsIndices {
956 shift: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_SHIFT),
957 caps: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_CAPS),
958 ctrl: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_CTRL),
959 alt: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_ALT),
960 num: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_NUM),
961 mod3: mod_index_for_name(keymap, b"Mod3\0"),
962 logo: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_LOGO),
963 mod5: mod_index_for_name(keymap, b"Mod5\0"),
964 };
965
966 Self { keymap, _mods_indices: mods_indices, _core_keyboard_id }
967 }
968
969 #[cfg(x11_platform)]
970 pub fn mods_indices(&self) -> ModsIndices {
971 self._mods_indices
972 }
973
974 pub fn first_keysym_by_level(
975 &mut self,
976 layout: xkb_layout_index_t,
977 keycode: xkb_keycode_t,
978 ) -> xkb_keysym_t {
979 unsafe {
980 let mut keysyms = ptr::null();
981 let count = (XKBH.xkb_keymap_key_get_syms_by_level)(
982 self.keymap.as_ptr(),
983 keycode,
984 layout,
985 0,
987 &mut keysyms,
988 );
989
990 if count == 1 {
991 *keysyms
992 } else {
993 0
994 }
995 }
996 }
997
998 pub fn key_repeats(&mut self, keycode: xkb_keycode_t) -> bool {
1000 unsafe { (XKBH.xkb_keymap_key_repeats)(self.keymap.as_ptr(), keycode) == 1 }
1001 }
1002}
1003
1004impl Drop for XkbKeymap {
1005 fn drop(&mut self) {
1006 unsafe {
1007 (XKBH.xkb_keymap_unref)(self.keymap.as_ptr());
1008 };
1009 }
1010}
1011
1012impl Deref for XkbKeymap {
1013 type Target = NonNull<xkb_keymap>;
1014
1015 fn deref(&self) -> &Self::Target {
1016 &self.keymap
1017 }
1018}
1019
1020#[cfg_attr(not(x11_platform), allow(dead_code))]
1022#[derive(Default, Debug, Clone, Copy)]
1023pub struct ModsIndices {
1024 pub shift: Option<xkb_mod_index_t>,
1025 pub caps: Option<xkb_mod_index_t>,
1026 pub ctrl: Option<xkb_mod_index_t>,
1027 pub alt: Option<xkb_mod_index_t>,
1028 pub num: Option<xkb_mod_index_t>,
1029 pub mod3: Option<xkb_mod_index_t>,
1030 pub logo: Option<xkb_mod_index_t>,
1031 pub mod5: Option<xkb_mod_index_t>,
1032}
1033
1034fn mod_index_for_name(keymap: NonNull<xkb_keymap>, name: &[u8]) -> Option<xkb_mod_index_t> {
1035 unsafe {
1036 let mod_index =
1037 (XKBH.xkb_keymap_mod_get_index)(keymap.as_ptr(), name.as_ptr() as *const c_char);
1038 if mod_index == XKB_MOD_INVALID {
1039 None
1040 } else {
1041 Some(mod_index)
1042 }
1043 }
1044}