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;
9use xkb::XKB_MOD_INVALID;
10use xkbcommon_dl::{
11 self as xkb, xkb_keycode_t, xkb_keymap, xkb_keymap_compile_flags, xkb_keysym_t,
12 xkb_layout_index_t, xkb_mod_index_t,
13};
14#[cfg(wayland_platform)]
15use {memmap2::MmapOptions, std::os::unix::io::OwnedFd};
16
17use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey};
18#[cfg(x11_platform)]
19use crate::platform_impl::common::xkb::XKBXH;
20use crate::platform_impl::common::xkb::{XkbContext, XKBH};
21
22pub fn raw_keycode_to_physicalkey(keycode: u32) -> PhysicalKey {
26 scancode_to_physicalkey(keycode.saturating_sub(8))
27}
28
29pub fn scancode_to_physicalkey(scancode: u32) -> PhysicalKey {
33 PhysicalKey::Code(match scancode {
42 0 => return PhysicalKey::Unidentified(NativeKeyCode::Xkb(0)),
43 1 => KeyCode::Escape,
44 2 => KeyCode::Digit1,
45 3 => KeyCode::Digit2,
46 4 => KeyCode::Digit3,
47 5 => KeyCode::Digit4,
48 6 => KeyCode::Digit5,
49 7 => KeyCode::Digit6,
50 8 => KeyCode::Digit7,
51 9 => KeyCode::Digit8,
52 10 => KeyCode::Digit9,
53 11 => KeyCode::Digit0,
54 12 => KeyCode::Minus,
55 13 => KeyCode::Equal,
56 14 => KeyCode::Backspace,
57 15 => KeyCode::Tab,
58 16 => KeyCode::KeyQ,
59 17 => KeyCode::KeyW,
60 18 => KeyCode::KeyE,
61 19 => KeyCode::KeyR,
62 20 => KeyCode::KeyT,
63 21 => KeyCode::KeyY,
64 22 => KeyCode::KeyU,
65 23 => KeyCode::KeyI,
66 24 => KeyCode::KeyO,
67 25 => KeyCode::KeyP,
68 26 => KeyCode::BracketLeft,
69 27 => KeyCode::BracketRight,
70 28 => KeyCode::Enter,
71 29 => KeyCode::ControlLeft,
72 30 => KeyCode::KeyA,
73 31 => KeyCode::KeyS,
74 32 => KeyCode::KeyD,
75 33 => KeyCode::KeyF,
76 34 => KeyCode::KeyG,
77 35 => KeyCode::KeyH,
78 36 => KeyCode::KeyJ,
79 37 => KeyCode::KeyK,
80 38 => KeyCode::KeyL,
81 39 => KeyCode::Semicolon,
82 40 => KeyCode::Quote,
83 41 => KeyCode::Backquote,
84 42 => KeyCode::ShiftLeft,
85 43 => KeyCode::Backslash,
86 44 => KeyCode::KeyZ,
87 45 => KeyCode::KeyX,
88 46 => KeyCode::KeyC,
89 47 => KeyCode::KeyV,
90 48 => KeyCode::KeyB,
91 49 => KeyCode::KeyN,
92 50 => KeyCode::KeyM,
93 51 => KeyCode::Comma,
94 52 => KeyCode::Period,
95 53 => KeyCode::Slash,
96 54 => KeyCode::ShiftRight,
97 55 => KeyCode::NumpadMultiply,
98 56 => KeyCode::AltLeft,
99 57 => KeyCode::Space,
100 58 => KeyCode::CapsLock,
101 59 => KeyCode::F1,
102 60 => KeyCode::F2,
103 61 => KeyCode::F3,
104 62 => KeyCode::F4,
105 63 => KeyCode::F5,
106 64 => KeyCode::F6,
107 65 => KeyCode::F7,
108 66 => KeyCode::F8,
109 67 => KeyCode::F9,
110 68 => KeyCode::F10,
111 69 => KeyCode::NumLock,
112 70 => KeyCode::ScrollLock,
113 71 => KeyCode::Numpad7,
114 72 => KeyCode::Numpad8,
115 73 => KeyCode::Numpad9,
116 74 => KeyCode::NumpadSubtract,
117 75 => KeyCode::Numpad4,
118 76 => KeyCode::Numpad5,
119 77 => KeyCode::Numpad6,
120 78 => KeyCode::NumpadAdd,
121 79 => KeyCode::Numpad1,
122 80 => KeyCode::Numpad2,
123 81 => KeyCode::Numpad3,
124 82 => KeyCode::Numpad0,
125 83 => KeyCode::NumpadDecimal,
126 85 => KeyCode::Lang5,
127 86 => KeyCode::IntlBackslash,
128 87 => KeyCode::F11,
129 88 => KeyCode::F12,
130 89 => KeyCode::IntlRo,
131 90 => KeyCode::Lang3,
132 91 => KeyCode::Lang4,
133 92 => KeyCode::Convert,
134 93 => KeyCode::KanaMode,
135 94 => KeyCode::NonConvert,
136 96 => KeyCode::NumpadEnter,
138 97 => KeyCode::ControlRight,
139 98 => KeyCode::NumpadDivide,
140 99 => KeyCode::PrintScreen,
141 100 => KeyCode::AltRight,
142 102 => KeyCode::Home,
144 103 => KeyCode::ArrowUp,
145 104 => KeyCode::PageUp,
146 105 => KeyCode::ArrowLeft,
147 106 => KeyCode::ArrowRight,
148 107 => KeyCode::End,
149 108 => KeyCode::ArrowDown,
150 109 => KeyCode::PageDown,
151 110 => KeyCode::Insert,
152 111 => KeyCode::Delete,
153 113 => KeyCode::AudioVolumeMute,
155 114 => KeyCode::AudioVolumeDown,
156 115 => KeyCode::AudioVolumeUp,
157 117 => KeyCode::NumpadEqual,
159 119 => KeyCode::Pause,
161 121 => KeyCode::NumpadComma,
163 122 => KeyCode::Lang1,
164 123 => KeyCode::Lang2,
165 124 => KeyCode::IntlYen,
166 125 => KeyCode::SuperLeft,
167 126 => KeyCode::SuperRight,
168 127 => KeyCode::ContextMenu,
169 163 => KeyCode::MediaTrackNext,
205 164 => KeyCode::MediaPlayPause,
206 165 => KeyCode::MediaTrackPrevious,
207 166 => KeyCode::MediaStop,
208 183 => KeyCode::F13,
225 184 => KeyCode::F14,
226 185 => KeyCode::F15,
227 186 => KeyCode::F16,
228 187 => KeyCode::F17,
229 188 => KeyCode::F18,
230 189 => KeyCode::F19,
231 190 => KeyCode::F20,
232 191 => KeyCode::F21,
233 192 => KeyCode::F22,
234 193 => KeyCode::F23,
235 194 => KeyCode::F24,
236 240 => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified),
277 _ => return PhysicalKey::Unidentified(NativeKeyCode::Xkb(scancode)),
286 })
287}
288
289pub fn physicalkey_to_scancode(key: PhysicalKey) -> Option<u32> {
290 let code = match key {
291 PhysicalKey::Code(code) => code,
292 PhysicalKey::Unidentified(code) => {
293 return match code {
294 NativeKeyCode::Unidentified => Some(240),
295 NativeKeyCode::Xkb(raw) => Some(raw),
296 _ => None,
297 };
298 },
299 };
300
301 match code {
302 KeyCode::Escape => Some(1),
303 KeyCode::Digit1 => Some(2),
304 KeyCode::Digit2 => Some(3),
305 KeyCode::Digit3 => Some(4),
306 KeyCode::Digit4 => Some(5),
307 KeyCode::Digit5 => Some(6),
308 KeyCode::Digit6 => Some(7),
309 KeyCode::Digit7 => Some(8),
310 KeyCode::Digit8 => Some(9),
311 KeyCode::Digit9 => Some(10),
312 KeyCode::Digit0 => Some(11),
313 KeyCode::Minus => Some(12),
314 KeyCode::Equal => Some(13),
315 KeyCode::Backspace => Some(14),
316 KeyCode::Tab => Some(15),
317 KeyCode::KeyQ => Some(16),
318 KeyCode::KeyW => Some(17),
319 KeyCode::KeyE => Some(18),
320 KeyCode::KeyR => Some(19),
321 KeyCode::KeyT => Some(20),
322 KeyCode::KeyY => Some(21),
323 KeyCode::KeyU => Some(22),
324 KeyCode::KeyI => Some(23),
325 KeyCode::KeyO => Some(24),
326 KeyCode::KeyP => Some(25),
327 KeyCode::BracketLeft => Some(26),
328 KeyCode::BracketRight => Some(27),
329 KeyCode::Enter => Some(28),
330 KeyCode::ControlLeft => Some(29),
331 KeyCode::KeyA => Some(30),
332 KeyCode::KeyS => Some(31),
333 KeyCode::KeyD => Some(32),
334 KeyCode::KeyF => Some(33),
335 KeyCode::KeyG => Some(34),
336 KeyCode::KeyH => Some(35),
337 KeyCode::KeyJ => Some(36),
338 KeyCode::KeyK => Some(37),
339 KeyCode::KeyL => Some(38),
340 KeyCode::Semicolon => Some(39),
341 KeyCode::Quote => Some(40),
342 KeyCode::Backquote => Some(41),
343 KeyCode::ShiftLeft => Some(42),
344 KeyCode::Backslash => Some(43),
345 KeyCode::KeyZ => Some(44),
346 KeyCode::KeyX => Some(45),
347 KeyCode::KeyC => Some(46),
348 KeyCode::KeyV => Some(47),
349 KeyCode::KeyB => Some(48),
350 KeyCode::KeyN => Some(49),
351 KeyCode::KeyM => Some(50),
352 KeyCode::Comma => Some(51),
353 KeyCode::Period => Some(52),
354 KeyCode::Slash => Some(53),
355 KeyCode::ShiftRight => Some(54),
356 KeyCode::NumpadMultiply => Some(55),
357 KeyCode::AltLeft => Some(56),
358 KeyCode::Space => Some(57),
359 KeyCode::CapsLock => Some(58),
360 KeyCode::F1 => Some(59),
361 KeyCode::F2 => Some(60),
362 KeyCode::F3 => Some(61),
363 KeyCode::F4 => Some(62),
364 KeyCode::F5 => Some(63),
365 KeyCode::F6 => Some(64),
366 KeyCode::F7 => Some(65),
367 KeyCode::F8 => Some(66),
368 KeyCode::F9 => Some(67),
369 KeyCode::F10 => Some(68),
370 KeyCode::NumLock => Some(69),
371 KeyCode::ScrollLock => Some(70),
372 KeyCode::Numpad7 => Some(71),
373 KeyCode::Numpad8 => Some(72),
374 KeyCode::Numpad9 => Some(73),
375 KeyCode::NumpadSubtract => Some(74),
376 KeyCode::Numpad4 => Some(75),
377 KeyCode::Numpad5 => Some(76),
378 KeyCode::Numpad6 => Some(77),
379 KeyCode::NumpadAdd => Some(78),
380 KeyCode::Numpad1 => Some(79),
381 KeyCode::Numpad2 => Some(80),
382 KeyCode::Numpad3 => Some(81),
383 KeyCode::Numpad0 => Some(82),
384 KeyCode::NumpadDecimal => Some(83),
385 KeyCode::Lang5 => Some(85),
386 KeyCode::IntlBackslash => Some(86),
387 KeyCode::F11 => Some(87),
388 KeyCode::F12 => Some(88),
389 KeyCode::IntlRo => Some(89),
390 KeyCode::Lang3 => Some(90),
391 KeyCode::Lang4 => Some(91),
392 KeyCode::Convert => Some(92),
393 KeyCode::KanaMode => Some(93),
394 KeyCode::NonConvert => Some(94),
395 KeyCode::NumpadEnter => Some(96),
396 KeyCode::ControlRight => Some(97),
397 KeyCode::NumpadDivide => Some(98),
398 KeyCode::PrintScreen => Some(99),
399 KeyCode::AltRight => Some(100),
400 KeyCode::Home => Some(102),
401 KeyCode::ArrowUp => Some(103),
402 KeyCode::PageUp => Some(104),
403 KeyCode::ArrowLeft => Some(105),
404 KeyCode::ArrowRight => Some(106),
405 KeyCode::End => Some(107),
406 KeyCode::ArrowDown => Some(108),
407 KeyCode::PageDown => Some(109),
408 KeyCode::Insert => Some(110),
409 KeyCode::Delete => Some(111),
410 KeyCode::AudioVolumeMute => Some(113),
411 KeyCode::AudioVolumeDown => Some(114),
412 KeyCode::AudioVolumeUp => Some(115),
413 KeyCode::NumpadEqual => Some(117),
414 KeyCode::Pause => Some(119),
415 KeyCode::NumpadComma => Some(121),
416 KeyCode::Lang1 => Some(122),
417 KeyCode::Lang2 => Some(123),
418 KeyCode::IntlYen => Some(124),
419 KeyCode::SuperLeft => Some(125),
420 KeyCode::SuperRight => Some(126),
421 KeyCode::ContextMenu => Some(127),
422 KeyCode::MediaTrackNext => Some(163),
423 KeyCode::MediaPlayPause => Some(164),
424 KeyCode::MediaTrackPrevious => Some(165),
425 KeyCode::MediaStop => Some(166),
426 KeyCode::F13 => Some(183),
427 KeyCode::F14 => Some(184),
428 KeyCode::F15 => Some(185),
429 KeyCode::F16 => Some(186),
430 KeyCode::F17 => Some(187),
431 KeyCode::F18 => Some(188),
432 KeyCode::F19 => Some(189),
433 KeyCode::F20 => Some(190),
434 KeyCode::F21 => Some(191),
435 KeyCode::F22 => Some(192),
436 KeyCode::F23 => Some(193),
437 KeyCode::F24 => Some(194),
438 _ => None,
439 }
440}
441
442pub fn keysym_to_key(keysym: u32) -> Key {
443 use xkbcommon_dl::keysyms;
444 Key::Named(match keysym {
445 keysyms::BackSpace => NamedKey::Backspace,
447 keysyms::Tab => NamedKey::Tab,
448 keysyms::Clear => NamedKey::Clear,
450 keysyms::Return => NamedKey::Enter,
451 keysyms::Pause => NamedKey::Pause,
452 keysyms::Scroll_Lock => NamedKey::ScrollLock,
453 keysyms::Sys_Req => NamedKey::PrintScreen,
454 keysyms::Escape => NamedKey::Escape,
455 keysyms::Delete => NamedKey::Delete,
456
457 keysyms::Multi_key => NamedKey::Compose,
459 keysyms::Codeinput => NamedKey::CodeInput,
460 keysyms::SingleCandidate => NamedKey::SingleCandidate,
461 keysyms::MultipleCandidate => NamedKey::AllCandidates,
462 keysyms::PreviousCandidate => NamedKey::PreviousCandidate,
463
464 keysyms::Kanji => NamedKey::KanjiMode,
466 keysyms::Muhenkan => NamedKey::NonConvert,
467 keysyms::Henkan_Mode => NamedKey::Convert,
468 keysyms::Romaji => NamedKey::Romaji,
469 keysyms::Hiragana => NamedKey::Hiragana,
470 keysyms::Hiragana_Katakana => NamedKey::HiraganaKatakana,
471 keysyms::Zenkaku => NamedKey::Zenkaku,
472 keysyms::Hankaku => NamedKey::Hankaku,
473 keysyms::Zenkaku_Hankaku => NamedKey::ZenkakuHankaku,
474 keysyms::Kana_Lock => NamedKey::KanaMode,
477 keysyms::Kana_Shift => NamedKey::KanaMode,
478 keysyms::Eisu_Shift => NamedKey::Alphanumeric,
479 keysyms::Eisu_toggle => NamedKey::Alphanumeric,
480 keysyms::Home => NamedKey::Home,
487 keysyms::Left => NamedKey::ArrowLeft,
488 keysyms::Up => NamedKey::ArrowUp,
489 keysyms::Right => NamedKey::ArrowRight,
490 keysyms::Down => NamedKey::ArrowDown,
491 keysyms::Page_Up => NamedKey::PageUp,
493 keysyms::Page_Down => NamedKey::PageDown,
495 keysyms::End => NamedKey::End,
496 keysyms::Select => NamedKey::Select,
500 keysyms::Print => NamedKey::PrintScreen,
501 keysyms::Execute => NamedKey::Execute,
502 keysyms::Insert => NamedKey::Insert,
503 keysyms::Undo => NamedKey::Undo,
504 keysyms::Redo => NamedKey::Redo,
505 keysyms::Menu => NamedKey::ContextMenu,
506 keysyms::Find => NamedKey::Find,
507 keysyms::Cancel => NamedKey::Cancel,
508 keysyms::Help => NamedKey::Help,
509 keysyms::Break => NamedKey::Pause,
510 keysyms::Mode_switch => NamedKey::ModeChange,
511 keysyms::Num_Lock => NamedKey::NumLock,
513
514 keysyms::KP_Tab => NamedKey::Tab,
517 keysyms::KP_Enter => NamedKey::Enter,
518 keysyms::KP_F1 => NamedKey::F1,
519 keysyms::KP_F2 => NamedKey::F2,
520 keysyms::KP_F3 => NamedKey::F3,
521 keysyms::KP_F4 => NamedKey::F4,
522 keysyms::KP_Home => NamedKey::Home,
523 keysyms::KP_Left => NamedKey::ArrowLeft,
524 keysyms::KP_Up => NamedKey::ArrowUp,
525 keysyms::KP_Right => NamedKey::ArrowRight,
526 keysyms::KP_Down => NamedKey::ArrowDown,
527 keysyms::KP_Page_Up => NamedKey::PageUp,
529 keysyms::KP_Page_Down => NamedKey::PageDown,
531 keysyms::KP_End => NamedKey::End,
532 keysyms::KP_Insert => NamedKey::Insert,
535 keysyms::KP_Delete => NamedKey::Delete,
536 keysyms::F1 => NamedKey::F1,
557 keysyms::F2 => NamedKey::F2,
558 keysyms::F3 => NamedKey::F3,
559 keysyms::F4 => NamedKey::F4,
560 keysyms::F5 => NamedKey::F5,
561 keysyms::F6 => NamedKey::F6,
562 keysyms::F7 => NamedKey::F7,
563 keysyms::F8 => NamedKey::F8,
564 keysyms::F9 => NamedKey::F9,
565 keysyms::F10 => NamedKey::F10,
566 keysyms::F11 => NamedKey::F11,
567 keysyms::F12 => NamedKey::F12,
568 keysyms::F13 => NamedKey::F13,
569 keysyms::F14 => NamedKey::F14,
570 keysyms::F15 => NamedKey::F15,
571 keysyms::F16 => NamedKey::F16,
572 keysyms::F17 => NamedKey::F17,
573 keysyms::F18 => NamedKey::F18,
574 keysyms::F19 => NamedKey::F19,
575 keysyms::F20 => NamedKey::F20,
576 keysyms::F21 => NamedKey::F21,
577 keysyms::F22 => NamedKey::F22,
578 keysyms::F23 => NamedKey::F23,
579 keysyms::F24 => NamedKey::F24,
580 keysyms::F25 => NamedKey::F25,
581 keysyms::F26 => NamedKey::F26,
582 keysyms::F27 => NamedKey::F27,
583 keysyms::F28 => NamedKey::F28,
584 keysyms::F29 => NamedKey::F29,
585 keysyms::F30 => NamedKey::F30,
586 keysyms::F31 => NamedKey::F31,
587 keysyms::F32 => NamedKey::F32,
588 keysyms::F33 => NamedKey::F33,
589 keysyms::F34 => NamedKey::F34,
590 keysyms::F35 => NamedKey::F35,
591
592 keysyms::Shift_L => NamedKey::Shift,
594 keysyms::Shift_R => NamedKey::Shift,
595 keysyms::Control_L => NamedKey::Control,
596 keysyms::Control_R => NamedKey::Control,
597 keysyms::Caps_Lock => NamedKey::CapsLock,
598 keysyms::Alt_L => NamedKey::Alt,
603 keysyms::Alt_R => NamedKey::Alt,
604 keysyms::Super_L => NamedKey::Super,
605 keysyms::Super_R => NamedKey::Super,
606 keysyms::Hyper_L => NamedKey::Hyper,
607 keysyms::Hyper_R => NamedKey::Hyper,
608
609 keysyms::ISO_Level3_Shift => NamedKey::AltGraph,
613 keysyms::ISO_Level3_Latch => NamedKey::AltGraph,
614 keysyms::ISO_Level3_Lock => NamedKey::AltGraph,
615 keysyms::ISO_Next_Group => NamedKey::GroupNext,
622 keysyms::ISO_Prev_Group => NamedKey::GroupPrevious,
624 keysyms::ISO_First_Group => NamedKey::GroupFirst,
626 keysyms::ISO_Last_Group => NamedKey::GroupLast,
628 keysyms::ISO_Left_Tab => NamedKey::Tab,
630 keysyms::ISO_Enter => NamedKey::Enter,
650
651 keysyms::_3270_EraseEOF => NamedKey::EraseEof,
676 keysyms::_3270_Attn => NamedKey::Attn,
684 keysyms::_3270_Play => NamedKey::Play,
692 keysyms::_3270_ExSelect => NamedKey::ExSel,
697 keysyms::_3270_CursorSelect => NamedKey::CrSel,
698 keysyms::_3270_PrintScreen => NamedKey::PrintScreen,
699 keysyms::_3270_Enter => NamedKey::Enter,
700
701 keysyms::space => NamedKey::Space,
702 keysyms::XF86_MonBrightnessUp => NamedKey::BrightnessUp,
709 keysyms::XF86_MonBrightnessDown => NamedKey::BrightnessDown,
710 keysyms::XF86_Standby => NamedKey::Standby,
716 keysyms::XF86_AudioLowerVolume => NamedKey::AudioVolumeDown,
717 keysyms::XF86_AudioRaiseVolume => NamedKey::AudioVolumeUp,
718 keysyms::XF86_AudioPlay => NamedKey::MediaPlay,
719 keysyms::XF86_AudioStop => NamedKey::MediaStop,
720 keysyms::XF86_AudioPrev => NamedKey::MediaTrackPrevious,
721 keysyms::XF86_AudioNext => NamedKey::MediaTrackNext,
722 keysyms::XF86_HomePage => NamedKey::BrowserHome,
723 keysyms::XF86_Mail => NamedKey::LaunchMail,
724 keysyms::XF86_Search => NamedKey::BrowserSearch,
726 keysyms::XF86_AudioRecord => NamedKey::MediaRecord,
727
728 keysyms::XF86_Calculator => NamedKey::LaunchApplication2,
730 keysyms::XF86_Calendar => NamedKey::LaunchCalendar,
733 keysyms::XF86_PowerDown => NamedKey::Power,
734 keysyms::XF86_Back => NamedKey::BrowserBack,
741 keysyms::XF86_Forward => NamedKey::BrowserForward,
742 keysyms::XF86_Refresh => NamedKey::BrowserRefresh,
744 keysyms::XF86_PowerOff => NamedKey::Power,
745 keysyms::XF86_WakeUp => NamedKey::WakeUp,
746 keysyms::XF86_Eject => NamedKey::Eject,
747 keysyms::XF86_ScreenSaver => NamedKey::LaunchScreenSaver,
748 keysyms::XF86_WWW => NamedKey::LaunchWebBrowser,
749 keysyms::XF86_Sleep => NamedKey::Standby,
750 keysyms::XF86_Favorites => NamedKey::BrowserFavorites,
751 keysyms::XF86_AudioPause => NamedKey::MediaPause,
752 keysyms::XF86_MyComputer => NamedKey::LaunchApplication1,
754 keysyms::XF86_AudioRewind => NamedKey::MediaRewind,
765 keysyms::XF86_Calculater => NamedKey::LaunchApplication2, keysyms::XF86_Close => NamedKey::Close,
772 keysyms::XF86_Copy => NamedKey::Copy,
773 keysyms::XF86_Cut => NamedKey::Cut,
774 keysyms::XF86_Excel => NamedKey::LaunchSpreadsheet,
776 keysyms::XF86_LogOff => NamedKey::LogOff,
778 keysyms::XF86_MySites => NamedKey::BrowserFavorites,
780 keysyms::XF86_New => NamedKey::New,
781 keysyms::XF86_Open => NamedKey::Open,
783 keysyms::XF86_Paste => NamedKey::Paste,
785 keysyms::XF86_Phone => NamedKey::LaunchPhone,
786 keysyms::XF86_Reply => NamedKey::MailReply,
788 keysyms::XF86_Reload => NamedKey::BrowserRefresh,
789 keysyms::XF86_Save => NamedKey::Save,
791 keysyms::XF86_Send => NamedKey::MailSend,
793 keysyms::XF86_Spell => NamedKey::SpellCheck,
794 keysyms::XF86_SplitScreen => NamedKey::SplitScreenToggle,
795 keysyms::XF86_Video => NamedKey::LaunchMediaPlayer,
797 keysyms::XF86_Word => NamedKey::LaunchWordProcessor,
799 keysyms::XF86_ZoomIn => NamedKey::ZoomIn,
801 keysyms::XF86_ZoomOut => NamedKey::ZoomOut,
802
803 keysyms::XF86_WebCam => NamedKey::LaunchWebCam,
805 keysyms::XF86_MailForward => NamedKey::MailForward,
806 keysyms::XF86_Music => NamedKey::LaunchMusicPlayer,
808
809 keysyms::XF86_AudioForward => NamedKey::MediaFastForward,
811 keysyms::XF86_AudioRandomPlay => NamedKey::RandomToggle,
813 keysyms::XF86_Subtitle => NamedKey::Subtitle,
814 keysyms::XF86_AudioCycleTrack => NamedKey::MediaAudioTrack,
815 keysyms::XF86_Suspend => NamedKey::Standby,
817 keysyms::XF86_Hibernate => NamedKey::Hibernate,
818 keysyms::XF86_AudioMute => NamedKey::AudioVolumeMute,
820
821 keysyms::XF86_Next_VMode => NamedKey::VideoModeNext,
825 keysyms::SUN_Copy => NamedKey::Copy,
839 keysyms::SUN_Open => NamedKey::Open,
840 keysyms::SUN_Paste => NamedKey::Paste,
841 keysyms::SUN_Cut => NamedKey::Cut,
842
843 keysyms::SUN_AudioLowerVolume => NamedKey::AudioVolumeDown,
845 keysyms::SUN_AudioMute => NamedKey::AudioVolumeMute,
846 keysyms::SUN_AudioRaiseVolume => NamedKey::AudioVolumeUp,
847 keysyms::SUN_VideoLowerBrightness => NamedKey::BrightnessDown,
849 keysyms::SUN_VideoRaiseBrightness => NamedKey::BrightnessUp,
850 0 => return Key::Unidentified(NativeKey::Unidentified),
852 _ => return Key::Unidentified(NativeKey::Xkb(keysym)),
853 })
854}
855
856pub fn keysym_location(keysym: u32) -> KeyLocation {
857 use xkbcommon_dl::keysyms;
858 match keysym {
859 keysyms::Shift_L
860 | keysyms::Control_L
861 | keysyms::Meta_L
862 | keysyms::Alt_L
863 | keysyms::Super_L
864 | keysyms::Hyper_L => KeyLocation::Left,
865 keysyms::Shift_R
866 | keysyms::Control_R
867 | keysyms::Meta_R
868 | keysyms::Alt_R
869 | keysyms::Super_R
870 | keysyms::Hyper_R => KeyLocation::Right,
871 keysyms::KP_0
872 | keysyms::KP_1
873 | keysyms::KP_2
874 | keysyms::KP_3
875 | keysyms::KP_4
876 | keysyms::KP_5
877 | keysyms::KP_6
878 | keysyms::KP_7
879 | keysyms::KP_8
880 | keysyms::KP_9
881 | keysyms::KP_Space
882 | keysyms::KP_Tab
883 | keysyms::KP_Enter
884 | keysyms::KP_F1
885 | keysyms::KP_F2
886 | keysyms::KP_F3
887 | keysyms::KP_F4
888 | keysyms::KP_Home
889 | keysyms::KP_Left
890 | keysyms::KP_Up
891 | keysyms::KP_Right
892 | keysyms::KP_Down
893 | keysyms::KP_Page_Up
894 | keysyms::KP_Page_Down
895 | keysyms::KP_End
896 | keysyms::KP_Begin
897 | keysyms::KP_Insert
898 | keysyms::KP_Delete
899 | keysyms::KP_Equal
900 | keysyms::KP_Multiply
901 | keysyms::KP_Add
902 | keysyms::KP_Separator
903 | keysyms::KP_Subtract
904 | keysyms::KP_Decimal
905 | keysyms::KP_Divide => KeyLocation::Numpad,
906 _ => KeyLocation::Standard,
907 }
908}
909
910#[derive(Debug)]
911pub struct XkbKeymap {
912 keymap: NonNull<xkb_keymap>,
913 _mods_indices: ModsIndices,
914 pub _core_keyboard_id: i32,
915}
916
917impl XkbKeymap {
918 #[cfg(wayland_platform)]
919 pub fn from_fd(context: &XkbContext, fd: OwnedFd, size: usize) -> Option<Self> {
920 let map = unsafe { MmapOptions::new().len(size).map_copy_read_only(&fd).ok()? };
921
922 let keymap = unsafe {
923 let keymap = (XKBH.xkb_keymap_new_from_string)(
924 (*context).as_ptr(),
925 map.as_ptr() as *const _,
926 xkb::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1,
927 xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS,
928 );
929 NonNull::new(keymap)?
930 };
931
932 Some(Self::new_inner(keymap, 0))
933 }
934
935 #[cfg(x11_platform)]
936 pub fn from_x11_keymap(
937 context: &XkbContext,
938 xcb: *mut xcb_connection_t,
939 core_keyboard_id: i32,
940 ) -> Option<Self> {
941 let keymap = unsafe {
942 (XKBXH.xkb_x11_keymap_new_from_device)(
943 context.as_ptr(),
944 xcb,
945 core_keyboard_id,
946 xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS,
947 )
948 };
949 let keymap = NonNull::new(keymap)?;
950 Some(Self::new_inner(keymap, core_keyboard_id))
951 }
952
953 fn new_inner(keymap: NonNull<xkb_keymap>, _core_keyboard_id: i32) -> Self {
954 let mods_indices = ModsIndices {
955 shift: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_SHIFT),
956 caps: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_CAPS),
957 ctrl: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_CTRL),
958 alt: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_ALT),
959 num: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_NUM),
960 mod3: mod_index_for_name(keymap, b"Mod3\0"),
961 logo: mod_index_for_name(keymap, xkb::XKB_MOD_NAME_LOGO),
962 mod5: mod_index_for_name(keymap, b"Mod5\0"),
963 };
964
965 Self { keymap, _mods_indices: mods_indices, _core_keyboard_id }
966 }
967
968 #[cfg(x11_platform)]
969 pub fn mods_indices(&self) -> ModsIndices {
970 self._mods_indices
971 }
972
973 pub fn first_keysym_by_level(
974 &mut self,
975 layout: xkb_layout_index_t,
976 keycode: xkb_keycode_t,
977 ) -> xkb_keysym_t {
978 unsafe {
979 let mut keysyms = ptr::null();
980 let count = (XKBH.xkb_keymap_key_get_syms_by_level)(
981 self.keymap.as_ptr(),
982 keycode,
983 layout,
984 0,
986 &mut keysyms,
987 );
988
989 if count == 1 {
990 *keysyms
991 } else {
992 0
993 }
994 }
995 }
996
997 pub fn key_repeats(&mut self, keycode: xkb_keycode_t) -> bool {
999 unsafe { (XKBH.xkb_keymap_key_repeats)(self.keymap.as_ptr(), keycode) == 1 }
1000 }
1001}
1002
1003impl Drop for XkbKeymap {
1004 fn drop(&mut self) {
1005 unsafe {
1006 (XKBH.xkb_keymap_unref)(self.keymap.as_ptr());
1007 };
1008 }
1009}
1010
1011impl Deref for XkbKeymap {
1012 type Target = NonNull<xkb_keymap>;
1013
1014 fn deref(&self) -> &Self::Target {
1015 &self.keymap
1016 }
1017}
1018
1019#[cfg_attr(not(x11_platform), allow(dead_code))]
1021#[derive(Default, Debug, Clone, Copy)]
1022pub struct ModsIndices {
1023 pub shift: Option<xkb_mod_index_t>,
1024 pub caps: Option<xkb_mod_index_t>,
1025 pub ctrl: Option<xkb_mod_index_t>,
1026 pub alt: Option<xkb_mod_index_t>,
1027 pub num: Option<xkb_mod_index_t>,
1028 pub mod3: Option<xkb_mod_index_t>,
1029 pub logo: Option<xkb_mod_index_t>,
1030 pub mod5: Option<xkb_mod_index_t>,
1031}
1032
1033fn mod_index_for_name(keymap: NonNull<xkb_keymap>, name: &[u8]) -> Option<xkb_mod_index_t> {
1034 unsafe {
1035 let mod_index =
1036 (XKBH.xkb_keymap_mod_get_index)(keymap.as_ptr(), name.as_ptr() as *const c_char);
1037 if mod_index == XKB_MOD_INVALID {
1038 None
1039 } else {
1040 Some(mod_index)
1041 }
1042 }
1043}