From 94ea87889b91ba051e5f725f416b14e5053af7be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Fri, 19 Mar 2021 20:41:14 +0100 Subject: [PATCH 01/58] Get stuff to compile --- src/platform/unix.rs | 17 +- src/platform_impl/linux/mod.rs | 11 + .../linux/wayland/seat/keyboard/handlers.rs | 35 +- .../linux/wayland/seat/keyboard/keymap.rs | 411 ++-- .../linux/wayland/seat/keyboard/mod.rs | 6 +- src/platform_impl/linux/wayland/seat/mod.rs | 2 +- .../linux/wayland/seat/pointer/data.rs | 3 +- .../linux/wayland/seat/pointer/mod.rs | 2 +- .../linux/x11/event_processor.rs | 47 +- src/platform_impl/linux/x11/events.rs | 2010 ++++++++--------- src/platform_impl/linux/x11/util/input.rs | 6 +- src/platform_impl/linux/x11/util/modifiers.rs | 25 +- 12 files changed, 1325 insertions(+), 1250 deletions(-) diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 81b06ad07b..5146dee339 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -11,8 +11,11 @@ use std::os::raw; use std::{ptr, sync::Arc}; use crate::{ - event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + event::KeyEvent, + event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget}, + keyboard::Key, monitor::MonitorHandle, + platform::modifier_supplement::KeyEventExtModifierSupplement, window::{Window, WindowBuilder}, }; @@ -434,3 +437,15 @@ impl MonitorHandleExtUnix for MonitorHandle { self.inner.native_identifier() } } + +impl KeyEventExtModifierSupplement for KeyEvent { + #[inline] + fn text_with_all_modifiers(&self) -> Option<&str> { + self.platform_specific.text_with_all_modifers + } + + #[inline] + fn key_without_modifiers(&self) -> Key<'static> { + self.platform_specific.key_without_modifiers + } +} diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 919d4d740b..9b2ffcade6 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -36,6 +36,7 @@ use crate::{ ControlFlow, DeviceEventFilter, EventLoopClosed, EventLoopWindowTarget as RootELW, }, icon::Icon, + keyboard::Key, monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode}, window::{CursorIcon, Fullscreen, UserAttentionType, WindowAttributes}, }; @@ -47,6 +48,12 @@ pub mod wayland; #[cfg(feature = "x11")] pub mod x11; +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct KeyEventExtra { + pub text_with_all_modifers: Option<&'static str>, + pub key_without_modifiers: Key<'static>, +} + /// Environment variable specifying which backend should be used on unix platform. /// /// Legal values are x11 and wayland. If this variable is set only the named backend @@ -477,6 +484,10 @@ impl Window { x11_or_wayland!(match self; Window(w) => w.set_ime_position(position)) } + pub fn reset_dead_keys(&self) { + todo!() + } + #[inline] pub fn set_ime_allowed(&self, allowed: bool) { x11_or_wayland!(match self; Window(w) => w.set_ime_allowed(allowed)) diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 7c320973b8..d81e440cc5 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -4,7 +4,8 @@ use sctk::reexports::client::protocol::wl_keyboard::KeyState; use sctk::seat::keyboard::Event as KeyboardEvent; -use crate::event::{ElementState, KeyboardInput, ModifiersState, WindowEvent}; +use crate::event::{ElementState, KeyEvent, WindowEvent}; +use crate::keyboard::ModifiersState; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::{self, DeviceId}; @@ -68,19 +69,21 @@ pub(super) fn handle_keyboard( _ => unreachable!(), }; - let virtual_keycode = keymap::keysym_to_vkey(keysym); + // let virtual_keycode = keymap::keysym_to_vkey(keysym); event_sink.push_window_event( - #[allow(deprecated)] WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland( DeviceId, )), - input: KeyboardInput { + event: KeyEvent { + physical_key: todo!(), + logical_key: todo!(), + text: todo!(), + location: todo!(), state, - scancode: rawkey, - virtual_keycode, - modifiers: *inner.modifiers_state.borrow(), + repeat: false, + platform_specific: todo!(), }, is_synthetic: false, }, @@ -94,7 +97,7 @@ pub(super) fn handle_keyboard( if let Some(txt) = utf8 { for ch in txt.chars() { - event_sink.push_window_event(WindowEvent::ReceivedCharacter(ch), window_id); + // event_sink.push_window_event(WindowEvent::ReceivedCharacter(ch), window_id); } } } @@ -109,19 +112,21 @@ pub(super) fn handle_keyboard( None => return, }; - let virtual_keycode = keymap::keysym_to_vkey(keysym); + // let virtual_keycode = keymap::keysym_to_vkey(keysym); event_sink.push_window_event( - #[allow(deprecated)] WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland( DeviceId, )), - input: KeyboardInput { + event: KeyEvent { + physical_key: todo!(), + logical_key: todo!(), + text: todo!(), + location: todo!(), state: ElementState::Pressed, - scancode: rawkey, - virtual_keycode, - modifiers: *inner.modifiers_state.borrow(), + repeat: false, + platform_specific: todo!(), }, is_synthetic: false, }, @@ -130,7 +135,7 @@ pub(super) fn handle_keyboard( if let Some(txt) = utf8 { for ch in txt.chars() { - event_sink.push_window_event(WindowEvent::ReceivedCharacter(ch), window_id); + // event_sink.push_window_event(WindowEvent::ReceivedCharacter(ch), window_id); } } } diff --git a/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs b/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs index 991afff2c9..b674dd2945 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs @@ -1,192 +1,229 @@ -//! Convert Wayland keys to winit keys. +// //! Convert Wayland keys to winit keys. -use crate::event::VirtualKeyCode; +// use crate::keyboard::Key; -pub fn keysym_to_vkey(keysym: u32) -> Option { - use sctk::seat::keyboard::keysyms; - match keysym { - // Numbers. - keysyms::XKB_KEY_1 => Some(VirtualKeyCode::Key1), - keysyms::XKB_KEY_2 => Some(VirtualKeyCode::Key2), - keysyms::XKB_KEY_3 => Some(VirtualKeyCode::Key3), - keysyms::XKB_KEY_4 => Some(VirtualKeyCode::Key4), - keysyms::XKB_KEY_5 => Some(VirtualKeyCode::Key5), - keysyms::XKB_KEY_6 => Some(VirtualKeyCode::Key6), - keysyms::XKB_KEY_7 => Some(VirtualKeyCode::Key7), - keysyms::XKB_KEY_8 => Some(VirtualKeyCode::Key8), - keysyms::XKB_KEY_9 => Some(VirtualKeyCode::Key9), - keysyms::XKB_KEY_0 => Some(VirtualKeyCode::Key0), - // Letters. - keysyms::XKB_KEY_A | keysyms::XKB_KEY_a => Some(VirtualKeyCode::A), - keysyms::XKB_KEY_B | keysyms::XKB_KEY_b => Some(VirtualKeyCode::B), - keysyms::XKB_KEY_C | keysyms::XKB_KEY_c => Some(VirtualKeyCode::C), - keysyms::XKB_KEY_D | keysyms::XKB_KEY_d => Some(VirtualKeyCode::D), - keysyms::XKB_KEY_E | keysyms::XKB_KEY_e => Some(VirtualKeyCode::E), - keysyms::XKB_KEY_F | keysyms::XKB_KEY_f => Some(VirtualKeyCode::F), - keysyms::XKB_KEY_G | keysyms::XKB_KEY_g => Some(VirtualKeyCode::G), - keysyms::XKB_KEY_H | keysyms::XKB_KEY_h => Some(VirtualKeyCode::H), - keysyms::XKB_KEY_I | keysyms::XKB_KEY_i => Some(VirtualKeyCode::I), - keysyms::XKB_KEY_J | keysyms::XKB_KEY_j => Some(VirtualKeyCode::J), - keysyms::XKB_KEY_K | keysyms::XKB_KEY_k => Some(VirtualKeyCode::K), - keysyms::XKB_KEY_L | keysyms::XKB_KEY_l => Some(VirtualKeyCode::L), - keysyms::XKB_KEY_M | keysyms::XKB_KEY_m => Some(VirtualKeyCode::M), - keysyms::XKB_KEY_N | keysyms::XKB_KEY_n => Some(VirtualKeyCode::N), - keysyms::XKB_KEY_O | keysyms::XKB_KEY_o => Some(VirtualKeyCode::O), - keysyms::XKB_KEY_P | keysyms::XKB_KEY_p => Some(VirtualKeyCode::P), - keysyms::XKB_KEY_Q | keysyms::XKB_KEY_q => Some(VirtualKeyCode::Q), - keysyms::XKB_KEY_R | keysyms::XKB_KEY_r => Some(VirtualKeyCode::R), - keysyms::XKB_KEY_S | keysyms::XKB_KEY_s => Some(VirtualKeyCode::S), - keysyms::XKB_KEY_T | keysyms::XKB_KEY_t => Some(VirtualKeyCode::T), - keysyms::XKB_KEY_U | keysyms::XKB_KEY_u => Some(VirtualKeyCode::U), - keysyms::XKB_KEY_V | keysyms::XKB_KEY_v => Some(VirtualKeyCode::V), - keysyms::XKB_KEY_W | keysyms::XKB_KEY_w => Some(VirtualKeyCode::W), - keysyms::XKB_KEY_X | keysyms::XKB_KEY_x => Some(VirtualKeyCode::X), - keysyms::XKB_KEY_Y | keysyms::XKB_KEY_y => Some(VirtualKeyCode::Y), - keysyms::XKB_KEY_Z | keysyms::XKB_KEY_z => Some(VirtualKeyCode::Z), - // Escape. - keysyms::XKB_KEY_Escape => Some(VirtualKeyCode::Escape), - // Function keys. - keysyms::XKB_KEY_F1 => Some(VirtualKeyCode::F1), - keysyms::XKB_KEY_F2 => Some(VirtualKeyCode::F2), - keysyms::XKB_KEY_F3 => Some(VirtualKeyCode::F3), - keysyms::XKB_KEY_F4 => Some(VirtualKeyCode::F4), - keysyms::XKB_KEY_F5 => Some(VirtualKeyCode::F5), - keysyms::XKB_KEY_F6 => Some(VirtualKeyCode::F6), - keysyms::XKB_KEY_F7 => Some(VirtualKeyCode::F7), - keysyms::XKB_KEY_F8 => Some(VirtualKeyCode::F8), - keysyms::XKB_KEY_F9 => Some(VirtualKeyCode::F9), - keysyms::XKB_KEY_F10 => Some(VirtualKeyCode::F10), - keysyms::XKB_KEY_F11 => Some(VirtualKeyCode::F11), - keysyms::XKB_KEY_F12 => Some(VirtualKeyCode::F12), - keysyms::XKB_KEY_F13 => Some(VirtualKeyCode::F13), - keysyms::XKB_KEY_F14 => Some(VirtualKeyCode::F14), - keysyms::XKB_KEY_F15 => Some(VirtualKeyCode::F15), - keysyms::XKB_KEY_F16 => Some(VirtualKeyCode::F16), - keysyms::XKB_KEY_F17 => Some(VirtualKeyCode::F17), - keysyms::XKB_KEY_F18 => Some(VirtualKeyCode::F18), - keysyms::XKB_KEY_F19 => Some(VirtualKeyCode::F19), - keysyms::XKB_KEY_F20 => Some(VirtualKeyCode::F20), - keysyms::XKB_KEY_F21 => Some(VirtualKeyCode::F21), - keysyms::XKB_KEY_F22 => Some(VirtualKeyCode::F22), - keysyms::XKB_KEY_F23 => Some(VirtualKeyCode::F23), - keysyms::XKB_KEY_F24 => Some(VirtualKeyCode::F24), - // Flow control. - keysyms::XKB_KEY_Print => Some(VirtualKeyCode::Snapshot), - keysyms::XKB_KEY_Scroll_Lock => Some(VirtualKeyCode::Scroll), - keysyms::XKB_KEY_Pause => Some(VirtualKeyCode::Pause), - keysyms::XKB_KEY_Insert => Some(VirtualKeyCode::Insert), - keysyms::XKB_KEY_Home => Some(VirtualKeyCode::Home), - keysyms::XKB_KEY_Delete => Some(VirtualKeyCode::Delete), - keysyms::XKB_KEY_End => Some(VirtualKeyCode::End), - keysyms::XKB_KEY_Page_Down => Some(VirtualKeyCode::PageDown), - keysyms::XKB_KEY_Page_Up => Some(VirtualKeyCode::PageUp), - // Arrows. - keysyms::XKB_KEY_Left => Some(VirtualKeyCode::Left), - keysyms::XKB_KEY_Up => Some(VirtualKeyCode::Up), - keysyms::XKB_KEY_Right => Some(VirtualKeyCode::Right), - keysyms::XKB_KEY_Down => Some(VirtualKeyCode::Down), +// pub fn keysym_to_vkey(keysym: u32) -> Option> { +// use sctk::seat::keyboard::keysyms; +// match keysym { +// // Numbers. +// // keysyms::XKB_KEY_1 => Some(Key::Character("1")), +// // keysyms::XKB_KEY_2 => Some(Key::Character("2")), +// // keysyms::XKB_KEY_3 => Some(Key::Character("3")), +// // keysyms::XKB_KEY_4 => Some(Key::Character("4")), +// // keysyms::XKB_KEY_5 => Some(Key::Character("5")), +// // keysyms::XKB_KEY_6 => Some(Key::Character("6")), +// // keysyms::XKB_KEY_7 => Some(Key::Character("7")), +// // keysyms::XKB_KEY_8 => Some(Key::Character("8")), +// // keysyms::XKB_KEY_9 => Some(Key::Character("9")), +// // keysyms::XKB_KEY_0 => Some(Key::Character("0")), +// // Letters. +// // keysyms::XKB_KEY_A => Some(Key::Character("A")), +// // keysyms::XKB_KEY_a => Some(Key::Character("a")), +// // keysyms::XKB_KEY_B => Some(Key::Character("B")), +// // keysyms::XKB_KEY_b => Some(Key::Character("b")), +// // keysyms::XKB_KEY_C => Some(Key::Character("C")), +// // keysyms::XKB_KEY_c => Some(Key::Character("c")), +// // keysyms::XKB_KEY_D => Some(Key::Character("D")), +// // keysyms::XKB_KEY_d => Some(Key::Character("d")), +// // keysyms::XKB_KEY_E => Some(Key::Character("E")), +// // keysyms::XKB_KEY_e => Some(Key::Character("e")), +// // keysyms::XKB_KEY_F => Some(Key::Character("F")), +// // keysyms::XKB_KEY_f => Some(Key::Character("f")), +// // keysyms::XKB_KEY_G => Some(Key::Character("G")), +// // keysyms::XKB_KEY_g => Some(Key::Character("g")), +// // keysyms::XKB_KEY_H => Some(Key::Character("H")), +// // keysyms::XKB_KEY_h => Some(Key::Character("h")), +// // keysyms::XKB_KEY_I => Some(Key::Character("I")), +// // keysyms::XKB_KEY_i => Some(Key::Character("i")), +// // keysyms::XKB_KEY_J => Some(Key::Character("J")), +// // keysyms::XKB_KEY_j => Some(Key::Character("j")), +// // keysyms::XKB_KEY_K => Some(Key::Character("K")), +// // keysyms::XKB_KEY_k => Some(Key::Character("k")), +// // keysyms::XKB_KEY_L => Some(Key::Character("L")), +// // keysyms::XKB_KEY_l => Some(Key::Character("l")), +// // keysyms::XKB_KEY_M => Some(Key::Character("M")), +// // keysyms::XKB_KEY_m => Some(Key::Character("m")), +// // keysyms::XKB_KEY_N => Some(Key::Character("N")), +// // keysyms::XKB_KEY_n => Some(Key::Character("n")), +// // keysyms::XKB_KEY_O => Some(Key::Character("O")), +// // keysyms::XKB_KEY_o => Some(Key::Character("o")), +// // keysyms::XKB_KEY_P => Some(Key::Character("P")), +// // keysyms::XKB_KEY_p => Some(Key::Character("p")), +// // keysyms::XKB_KEY_Q => Some(Key::Character("Q")), +// // keysyms::XKB_KEY_q => Some(Key::Character("q")), +// // keysyms::XKB_KEY_R => Some(Key::Character("R")), +// // keysyms::XKB_KEY_r => Some(Key::Character("r")), +// // keysyms::XKB_KEY_S => Some(Key::Character("S")), +// // keysyms::XKB_KEY_s => Some(Key::Character("s")), +// // keysyms::XKB_KEY_T => Some(Key::Character("T")), +// // keysyms::XKB_KEY_t => Some(Key::Character("t")), +// // keysyms::XKB_KEY_U => Some(Key::Character("U")), +// // keysyms::XKB_KEY_u => Some(Key::Character("u")), +// // keysyms::XKB_KEY_V => Some(Key::Character("V")), +// // keysyms::XKB_KEY_v => Some(Key::Character("v")), +// // keysyms::XKB_KEY_W => Some(Key::Character("W")), +// // keysyms::XKB_KEY_w => Some(Key::Character("w")), +// // keysyms::XKB_KEY_X => Some(Key::Character("X")), +// // keysyms::XKB_KEY_x => Some(Key::Character("x")), +// // keysyms::XKB_KEY_Y => Some(Key::Character("Y")), +// // keysyms::XKB_KEY_y => Some(Key::Character("y")), +// // keysyms::XKB_KEY_Z => Some(Key::Character("Z")), +// // keysyms::XKB_KEY_z => Some(Key::Character("z")), +// // Escape. +// keysyms::XKB_KEY_Escape => Some(Key::Escape), +// // Function keys. +// keysyms::XKB_KEY_F1 => Some(Key::F1), +// keysyms::XKB_KEY_F2 => Some(Key::F2), +// keysyms::XKB_KEY_F3 => Some(Key::F3), +// keysyms::XKB_KEY_F4 => Some(Key::F4), +// keysyms::XKB_KEY_F5 => Some(Key::F5), +// keysyms::XKB_KEY_F6 => Some(Key::F6), +// keysyms::XKB_KEY_F7 => Some(Key::F7), +// keysyms::XKB_KEY_F8 => Some(Key::F8), +// keysyms::XKB_KEY_F9 => Some(Key::F9), +// keysyms::XKB_KEY_F10 => Some(Key::F10), +// keysyms::XKB_KEY_F11 => Some(Key::F11), +// keysyms::XKB_KEY_F12 => Some(Key::F12), +// keysyms::XKB_KEY_F13 => Some(Key::F13), +// keysyms::XKB_KEY_F14 => Some(Key::F14), +// keysyms::XKB_KEY_F15 => Some(Key::F15), +// keysyms::XKB_KEY_F16 => Some(Key::F16), +// keysyms::XKB_KEY_F17 => Some(Key::F17), +// keysyms::XKB_KEY_F18 => Some(Key::F18), +// keysyms::XKB_KEY_F19 => Some(Key::F19), +// keysyms::XKB_KEY_F20 => Some(Key::F20), +// keysyms::XKB_KEY_F21 => Some(Key::F21), +// keysyms::XKB_KEY_F22 => Some(Key::F22), +// keysyms::XKB_KEY_F23 => Some(Key::F23), +// keysyms::XKB_KEY_F24 => Some(Key::F24), +// keysyms::XKB_KEY_F25 => Some(Key::F25), +// keysyms::XKB_KEY_F26 => Some(Key::F26), +// keysyms::XKB_KEY_F27 => Some(Key::F27), +// keysyms::XKB_KEY_F28 => Some(Key::F28), +// keysyms::XKB_KEY_F29 => Some(Key::F29), +// keysyms::XKB_KEY_F30 => Some(Key::F30), +// keysyms::XKB_KEY_F31 => Some(Key::F31), +// keysyms::XKB_KEY_F32 => Some(Key::F32), +// keysyms::XKB_KEY_F33 => Some(Key::F33), +// keysyms::XKB_KEY_F34 => Some(Key::F34), +// keysyms::XKB_KEY_F35 => Some(Key::F35), +// // Flow control. +// keysyms::XKB_KEY_Print => Some(Key::PrintScreen), +// keysyms::XKB_KEY_Scroll_Lock => Some(Key::ScrollLock), +// keysyms::XKB_KEY_Pause => Some(Key::Pause), +// keysyms::XKB_KEY_Insert => Some(Key::Insert), +// keysyms::XKB_KEY_Home => Some(Key::Home), +// keysyms::XKB_KEY_Delete => Some(Key::Delete), +// keysyms::XKB_KEY_End => Some(Key::End), +// keysyms::XKB_KEY_Page_Down => Some(Key::PageDown), +// keysyms::XKB_KEY_Page_Up => Some(Key::PageUp), +// // Arrows. +// keysyms::XKB_KEY_Left => Some(Key::Left), +// keysyms::XKB_KEY_Up => Some(Key::Up), +// keysyms::XKB_KEY_Right => Some(Key::Right), +// keysyms::XKB_KEY_Down => Some(Key::Down), - keysyms::XKB_KEY_BackSpace => Some(VirtualKeyCode::Back), - keysyms::XKB_KEY_Return => Some(VirtualKeyCode::Return), - keysyms::XKB_KEY_space => Some(VirtualKeyCode::Space), +// keysyms::XKB_KEY_BackSpace => Some(Key::Back), +// keysyms::XKB_KEY_Return => Some(Key::Return), +// keysyms::XKB_KEY_space => Some(Key::Space), - keysyms::XKB_KEY_Multi_key => Some(VirtualKeyCode::Compose), - keysyms::XKB_KEY_caret => Some(VirtualKeyCode::Caret), +// keysyms::XKB_KEY_Multi_key => Some(Key::Compose), +// keysyms::XKB_KEY_caret => Some(Key::Caret), - // Keypad. - keysyms::XKB_KEY_Num_Lock => Some(VirtualKeyCode::Numlock), - keysyms::XKB_KEY_KP_0 => Some(VirtualKeyCode::Numpad0), - keysyms::XKB_KEY_KP_1 => Some(VirtualKeyCode::Numpad1), - keysyms::XKB_KEY_KP_2 => Some(VirtualKeyCode::Numpad2), - keysyms::XKB_KEY_KP_3 => Some(VirtualKeyCode::Numpad3), - keysyms::XKB_KEY_KP_4 => Some(VirtualKeyCode::Numpad4), - keysyms::XKB_KEY_KP_5 => Some(VirtualKeyCode::Numpad5), - keysyms::XKB_KEY_KP_6 => Some(VirtualKeyCode::Numpad6), - keysyms::XKB_KEY_KP_7 => Some(VirtualKeyCode::Numpad7), - keysyms::XKB_KEY_KP_8 => Some(VirtualKeyCode::Numpad8), - keysyms::XKB_KEY_KP_9 => Some(VirtualKeyCode::Numpad9), - // Misc. - // => Some(VirtualKeyCode::AbntC1), - // => Some(VirtualKeyCode::AbntC2), - keysyms::XKB_KEY_plus => Some(VirtualKeyCode::Plus), - keysyms::XKB_KEY_apostrophe => Some(VirtualKeyCode::Apostrophe), - // => Some(VirtualKeyCode::Apps), - keysyms::XKB_KEY_at => Some(VirtualKeyCode::At), - // => Some(VirtualKeyCode::Ax), - keysyms::XKB_KEY_backslash => Some(VirtualKeyCode::Backslash), - keysyms::XKB_KEY_XF86Calculator => Some(VirtualKeyCode::Calculator), - // => Some(VirtualKeyCode::Capital), - keysyms::XKB_KEY_colon => Some(VirtualKeyCode::Colon), - keysyms::XKB_KEY_comma => Some(VirtualKeyCode::Comma), - // => Some(VirtualKeyCode::Convert), - keysyms::XKB_KEY_equal => Some(VirtualKeyCode::Equals), - keysyms::XKB_KEY_grave => Some(VirtualKeyCode::Grave), - // => Some(VirtualKeyCode::Kana), - keysyms::XKB_KEY_Kanji => Some(VirtualKeyCode::Kanji), - keysyms::XKB_KEY_Alt_L => Some(VirtualKeyCode::LAlt), - keysyms::XKB_KEY_bracketleft => Some(VirtualKeyCode::LBracket), - keysyms::XKB_KEY_Control_L => Some(VirtualKeyCode::LControl), - keysyms::XKB_KEY_Shift_L => Some(VirtualKeyCode::LShift), - keysyms::XKB_KEY_Super_L => Some(VirtualKeyCode::LWin), - keysyms::XKB_KEY_XF86Mail => Some(VirtualKeyCode::Mail), - // => Some(VirtualKeyCode::MediaSelect), - // => Some(VirtualKeyCode::MediaStop), - keysyms::XKB_KEY_minus => Some(VirtualKeyCode::Minus), - keysyms::XKB_KEY_asterisk => Some(VirtualKeyCode::Asterisk), - keysyms::XKB_KEY_XF86AudioMute => Some(VirtualKeyCode::Mute), - // => Some(VirtualKeyCode::MyComputer), - keysyms::XKB_KEY_XF86AudioNext => Some(VirtualKeyCode::NextTrack), - // => Some(VirtualKeyCode::NoConvert), - keysyms::XKB_KEY_KP_Separator => Some(VirtualKeyCode::NumpadComma), - keysyms::XKB_KEY_KP_Enter => Some(VirtualKeyCode::NumpadEnter), - keysyms::XKB_KEY_KP_Equal => Some(VirtualKeyCode::NumpadEquals), - keysyms::XKB_KEY_KP_Add => Some(VirtualKeyCode::NumpadAdd), - keysyms::XKB_KEY_KP_Subtract => Some(VirtualKeyCode::NumpadSubtract), - keysyms::XKB_KEY_KP_Multiply => Some(VirtualKeyCode::NumpadMultiply), - keysyms::XKB_KEY_KP_Divide => Some(VirtualKeyCode::NumpadDivide), - keysyms::XKB_KEY_KP_Decimal => Some(VirtualKeyCode::NumpadDecimal), - keysyms::XKB_KEY_KP_Page_Up => Some(VirtualKeyCode::PageUp), - keysyms::XKB_KEY_KP_Page_Down => Some(VirtualKeyCode::PageDown), - keysyms::XKB_KEY_KP_Home => Some(VirtualKeyCode::Home), - keysyms::XKB_KEY_KP_End => Some(VirtualKeyCode::End), - keysyms::XKB_KEY_KP_Left => Some(VirtualKeyCode::Left), - keysyms::XKB_KEY_KP_Up => Some(VirtualKeyCode::Up), - keysyms::XKB_KEY_KP_Right => Some(VirtualKeyCode::Right), - keysyms::XKB_KEY_KP_Down => Some(VirtualKeyCode::Down), - // => Some(VirtualKeyCode::OEM102), - keysyms::XKB_KEY_period => Some(VirtualKeyCode::Period), - // => Some(VirtualKeyCode::Playpause), - keysyms::XKB_KEY_XF86PowerOff => Some(VirtualKeyCode::Power), - keysyms::XKB_KEY_XF86AudioPrev => Some(VirtualKeyCode::PrevTrack), - keysyms::XKB_KEY_Alt_R => Some(VirtualKeyCode::RAlt), - keysyms::XKB_KEY_bracketright => Some(VirtualKeyCode::RBracket), - keysyms::XKB_KEY_Control_R => Some(VirtualKeyCode::RControl), - keysyms::XKB_KEY_Shift_R => Some(VirtualKeyCode::RShift), - keysyms::XKB_KEY_Super_R => Some(VirtualKeyCode::RWin), - keysyms::XKB_KEY_semicolon => Some(VirtualKeyCode::Semicolon), - keysyms::XKB_KEY_slash => Some(VirtualKeyCode::Slash), - keysyms::XKB_KEY_XF86Sleep => Some(VirtualKeyCode::Sleep), - // => Some(VirtualKeyCode::Stop), - // => Some(VirtualKeyCode::Sysrq), - keysyms::XKB_KEY_Tab => Some(VirtualKeyCode::Tab), - keysyms::XKB_KEY_ISO_Left_Tab => Some(VirtualKeyCode::Tab), - keysyms::XKB_KEY_underscore => Some(VirtualKeyCode::Underline), - // => Some(VirtualKeyCode::Unlabeled), - keysyms::XKB_KEY_XF86AudioLowerVolume => Some(VirtualKeyCode::VolumeDown), - keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(VirtualKeyCode::VolumeUp), - // => Some(VirtualKeyCode::Wake), - // => Some(VirtualKeyCode::Webback), - // => Some(VirtualKeyCode::WebFavorites), - // => Some(VirtualKeyCode::WebForward), - // => Some(VirtualKeyCode::WebHome), - // => Some(VirtualKeyCode::WebRefresh), - // => Some(VirtualKeyCode::WebSearch), - // => Some(VirtualKeyCode::WebStop), - keysyms::XKB_KEY_yen => Some(VirtualKeyCode::Yen), - keysyms::XKB_KEY_XF86Copy => Some(VirtualKeyCode::Copy), - keysyms::XKB_KEY_XF86Paste => Some(VirtualKeyCode::Paste), - keysyms::XKB_KEY_XF86Cut => Some(VirtualKeyCode::Cut), - // Fallback. - _ => None, - } -} +// // Keypad. +// keysyms::XKB_KEY_Num_Lock => Some(Key::Numlock), +// keysyms::XKB_KEY_KP_0 => Some(Key::Numpad0), +// keysyms::XKB_KEY_KP_1 => Some(Key::Numpad1), +// keysyms::XKB_KEY_KP_2 => Some(Key::Numpad2), +// keysyms::XKB_KEY_KP_3 => Some(Key::Numpad3), +// keysyms::XKB_KEY_KP_4 => Some(Key::Numpad4), +// keysyms::XKB_KEY_KP_5 => Some(Key::Numpad5), +// keysyms::XKB_KEY_KP_6 => Some(Key::Numpad6), +// keysyms::XKB_KEY_KP_7 => Some(Key::Numpad7), +// keysyms::XKB_KEY_KP_8 => Some(Key::Numpad8), +// keysyms::XKB_KEY_KP_9 => Some(Key::Numpad9), +// // Misc. +// // => Some(Key::AbntC1), +// // => Some(Key::AbntC2), +// keysyms::XKB_KEY_plus => Some(Key::Plus), +// keysyms::XKB_KEY_apostrophe => Some(Key::Apostrophe), +// // => Some(Key::Apps), +// keysyms::XKB_KEY_at => Some(Key::At), +// // => Some(Key::Ax), +// keysyms::XKB_KEY_backslash => Some(Key::Backslash), +// keysyms::XKB_KEY_XF86Calculator => Some(Key::Calculator), +// // => Some(Key::Capital), +// keysyms::XKB_KEY_colon => Some(Key::Colon), +// keysyms::XKB_KEY_comma => Some(Key::Comma), +// // => Some(Key::Convert), +// keysyms::XKB_KEY_equal => Some(Key::Equals), +// keysyms::XKB_KEY_grave => Some(Key::Grave), +// // => Some(Key::Kana), +// keysyms::XKB_KEY_Kanji => Some(Key::Kanji), +// keysyms::XKB_KEY_Alt_L => Some(Key::LAlt), +// keysyms::XKB_KEY_bracketleft => Some(Key::LBracket), +// keysyms::XKB_KEY_Control_L => Some(Key::LControl), +// keysyms::XKB_KEY_Shift_L => Some(Key::LShift), +// keysyms::XKB_KEY_Super_L => Some(Key::LWin), +// keysyms::XKB_KEY_XF86Mail => Some(Key::Mail), +// // => Some(Key::MediaSelect), +// // => Some(Key::MediaStop), +// keysyms::XKB_KEY_minus => Some(Key::Minus), +// keysyms::XKB_KEY_asterisk => Some(Key::Asterisk), +// keysyms::XKB_KEY_XF86AudioMute => Some(Key::Mute), +// // => Some(Key::MyComputer), +// keysyms::XKB_KEY_XF86AudioNext => Some(Key::NextTrack), +// // => Some(Key::NoConvert), +// keysyms::XKB_KEY_KP_Separator => Some(Key::NumpadComma), +// keysyms::XKB_KEY_KP_Enter => Some(Key::NumpadEnter), +// keysyms::XKB_KEY_KP_Equal => Some(Key::NumpadEquals), +// keysyms::XKB_KEY_KP_Add => Some(Key::NumpadAdd), +// keysyms::XKB_KEY_KP_Subtract => Some(Key::NumpadSubtract), +// keysyms::XKB_KEY_KP_Multiply => Some(Key::NumpadMultiply), +// keysyms::XKB_KEY_KP_Divide => Some(Key::NumpadDivide), +// keysyms::XKB_KEY_KP_Decimal => Some(Key::NumpadDecimal), +// keysyms::XKB_KEY_KP_Page_Up => Some(Key::PageUp), +// keysyms::XKB_KEY_KP_Page_Down => Some(Key::PageDown), +// keysyms::XKB_KEY_KP_Home => Some(Key::Home), +// keysyms::XKB_KEY_KP_End => Some(Key::End), +// keysyms::XKB_KEY_KP_Left => Some(Key::Left), +// keysyms::XKB_KEY_KP_Up => Some(Key::Up), +// keysyms::XKB_KEY_KP_Right => Some(Key::Right), +// keysyms::XKB_KEY_KP_Down => Some(Key::Down), +// // => Some(Key::OEM102), +// keysyms::XKB_KEY_period => Some(Key::Period), +// // => Some(Key::Playpause), +// keysyms::XKB_KEY_XF86PowerOff => Some(Key::Power), +// keysyms::XKB_KEY_XF86AudioPrev => Some(Key::PrevTrack), +// keysyms::XKB_KEY_Alt_R => Some(Key::RAlt), +// keysyms::XKB_KEY_bracketright => Some(Key::RBracket), +// keysyms::XKB_KEY_Control_R => Some(Key::RControl), +// keysyms::XKB_KEY_Shift_R => Some(Key::RShift), +// keysyms::XKB_KEY_Super_R => Some(Key::RWin), +// keysyms::XKB_KEY_semicolon => Some(Key::Semicolon), +// keysyms::XKB_KEY_slash => Some(Key::Slash), +// keysyms::XKB_KEY_XF86Sleep => Some(Key::Sleep), +// // => Some(Key::Stop), +// // => Some(Key::Sysrq), +// keysyms::XKB_KEY_Tab => Some(Key::Tab), +// keysyms::XKB_KEY_ISO_Left_Tab => Some(Key::Tab), +// keysyms::XKB_KEY_underscore => Some(Key::Underline), +// // => Some(Key::Unlabeled), +// keysyms::XKB_KEY_XF86AudioLowerVolume => Some(Key::VolumeDown), +// keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(Key::VolumeUp), +// // => Some(Key::Wake), +// // => Some(Key::Webback), +// // => Some(Key::WebFavorites), +// // => Some(Key::WebForward), +// // => Some(Key::WebHome), +// // => Some(Key::WebRefresh), +// // => Some(Key::WebSearch), +// // => Some(Key::WebStop), +// keysyms::XKB_KEY_yen => Some(Key::Yen), +// keysyms::XKB_KEY_XF86Copy => Some(Key::Copy), +// keysyms::XKB_KEY_XF86Paste => Some(Key::Paste), +// keysyms::XKB_KEY_XF86Cut => Some(Key::Cut), +// // Fallback. +// _ => None, +// } +// } diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index c6e0ad456e..fb7973f452 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -11,7 +11,7 @@ use sctk::reexports::calloop::{LoopHandle, RegistrationToken}; use sctk::seat::keyboard; -use crate::event::ModifiersState; +use crate::keyboard::ModifiersState; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::WindowId; @@ -97,9 +97,9 @@ impl From for ModifiersState { fn from(mods: keyboard::ModifiersState) -> ModifiersState { let mut wl_mods = ModifiersState::empty(); wl_mods.set(ModifiersState::SHIFT, mods.shift); - wl_mods.set(ModifiersState::CTRL, mods.ctrl); + wl_mods.set(ModifiersState::CONTROL, mods.ctrl); wl_mods.set(ModifiersState::ALT, mods.alt); - wl_mods.set(ModifiersState::LOGO, mods.logo); + wl_mods.set(ModifiersState::SUPER, mods.logo); wl_mods } } diff --git a/src/platform_impl/linux/wayland/seat/mod.rs b/src/platform_impl/linux/wayland/seat/mod.rs index 2d7b7533d0..cf344005f7 100644 --- a/src/platform_impl/linux/wayland/seat/mod.rs +++ b/src/platform_impl/linux/wayland/seat/mod.rs @@ -17,7 +17,7 @@ use sctk::seat::{SeatData, SeatListener}; use super::env::WinitEnv; use super::event_loop::WinitState; -use crate::event::ModifiersState; +use crate::keyboard::ModifiersState; mod keyboard; pub mod pointer; diff --git a/src/platform_impl/linux/wayland/seat/pointer/data.rs b/src/platform_impl/linux/wayland/seat/pointer/data.rs index 310e692b43..ddb22feb45 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/data.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/data.rs @@ -8,7 +8,8 @@ use sctk::reexports::client::Attached; use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_pointer_constraints_v1::{ZwpPointerConstraintsV1}; use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_confined_pointer_v1::ZwpConfinedPointerV1; -use crate::event::{ModifiersState, TouchPhase}; +use crate::event::TouchPhase; +use crate::keyboard::ModifiersState; /// A data being used by pointer handlers. pub(super) struct PointerData { diff --git a/src/platform_impl/linux/wayland/seat/pointer/mod.rs b/src/platform_impl/linux/wayland/seat/pointer/mod.rs index e1b34a5e80..7aad636a07 100644 --- a/src/platform_impl/linux/wayland/seat/pointer/mod.rs +++ b/src/platform_impl/linux/wayland/seat/pointer/mod.rs @@ -15,7 +15,7 @@ use sctk::reexports::protocols::unstable::pointer_constraints::v1::client::zwp_c use sctk::seat::pointer::{ThemeManager, ThemedPointer}; use sctk::window::Window; -use crate::event::ModifiersState; +use crate::keyboard::ModifiersState; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::window::WinitFrame; use crate::window::CursorIcon; diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 1a024ac4e4..7b3b8bd372 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -16,10 +16,10 @@ use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRe use crate::{ dpi::{PhysicalPosition, PhysicalSize}, event::{ - DeviceEvent, ElementState, Event, Ime, KeyboardInput, ModifiersState, TouchPhase, - WindowEvent, + DeviceEvent, ElementState, Event, Ime, KeyEvent, RawKeyEvent, TouchPhase, WindowEvent, }, event_loop::EventLoopWindowTarget as RootELW, + keyboard::ModifiersState, }; /// The X11 documentation states: "Keycodes lie in the inclusive range [8,255]". @@ -574,7 +574,7 @@ impl EventProcessor { if keycode != 0 && !self.is_composing { let scancode = keycode - KEYCODE_OFFSET as u32; let keysym = wt.xconn.lookup_keysym(xkev); - let virtual_keycode = events::keysym_to_element(keysym as c_uint); + // let virtual_keycode = events::keysym_to_element(keysym as c_uint); update_modifiers!( ModifiersState::from_x11_mask(xkev.state), @@ -583,16 +583,18 @@ impl EventProcessor { let modifiers = self.device_mod_state.modifiers(); - #[allow(deprecated)] callback(Event::WindowEvent { window_id, event: WindowEvent::KeyboardInput { device_id, - input: KeyboardInput { + event: KeyEvent { + physical_key: todo!(), + logical_key: todo!(), + text: todo!(), + location: todo!(), state, - scancode, - virtual_keycode, - modifiers, + repeat: todo!(), + platform_specific: todo!(), }, is_synthetic: false, }, @@ -617,6 +619,7 @@ impl EventProcessor { self.is_composing = false; callback(event); } else { + /* for chr in written.chars() { let event = Event::WindowEvent { window_id, @@ -625,6 +628,7 @@ impl EventProcessor { callback(event); } + */ } } } @@ -1117,17 +1121,14 @@ impl EventProcessor { return; } let keysym = wt.xconn.keycode_to_keysym(keycode as ffi::KeyCode); - let virtual_keycode = events::keysym_to_element(keysym as c_uint); + // let virtual_keycode = events::keysym_to_element(keysym as c_uint); let modifiers = self.device_mod_state.modifiers(); - #[allow(deprecated)] callback(Event::DeviceEvent { device_id, - event: DeviceEvent::Key(KeyboardInput { - scancode: scancode as u32, - virtual_keycode, - state, - modifiers, + event: DeviceEvent::Key(RawKeyEvent { + physical_key: todo!(), + state: todo!(), }), }); @@ -1325,7 +1326,7 @@ impl EventProcessor { { let scancode = (keycode - KEYCODE_OFFSET) as u32; let keysym = wt.xconn.keycode_to_keysym(keycode); - let virtual_keycode = events::keysym_to_element(keysym as c_uint); + // let virtual_keycode = events::keysym_to_element(keysym as c_uint); if let Some(modifier) = mod_keymap.get_modifier(keycode as ffi::KeyCode) { device_mod_state.key_event( @@ -1335,16 +1336,18 @@ impl EventProcessor { ); } - #[allow(deprecated)] callback(Event::WindowEvent { window_id, event: WindowEvent::KeyboardInput { device_id, - input: KeyboardInput { - scancode, - state, - virtual_keycode, - modifiers, + event: KeyEvent { + physical_key: todo!(), + logical_key: todo!(), + text: todo!(), + location: todo!(), + state: todo!(), + repeat: todo!(), + platform_specific: todo!(), }, is_synthetic: true, }, diff --git a/src/platform_impl/linux/x11/events.rs b/src/platform_impl/linux/x11/events.rs index 1c34b0d0cb..e721ab5922 100644 --- a/src/platform_impl/linux/x11/events.rs +++ b/src/platform_impl/linux/x11/events.rs @@ -1,1008 +1,1008 @@ use super::ffi; -use crate::event::VirtualKeyCode; +use crate::keyboard::KeyCode; use libc; -pub fn keysym_to_element(keysym: libc::c_uint) -> Option { - Some(match keysym { - ffi::XK_BackSpace => VirtualKeyCode::Back, - ffi::XK_Tab => VirtualKeyCode::Tab, - //ffi::XK_Linefeed => VirtualKeyCode::Linefeed, - //ffi::XK_Clear => VirtualKeyCode::Clear, - ffi::XK_Return => VirtualKeyCode::Return, - ffi::XK_Pause => VirtualKeyCode::Pause, - //ffi::XK_Scroll_Lock => VirtualKeyCode::Scroll_lock, - //ffi::XK_Sys_Req => VirtualKeyCode::Sys_req, - ffi::XK_Escape => VirtualKeyCode::Escape, - ffi::XK_Delete => VirtualKeyCode::Delete, - ffi::XK_Multi_key => VirtualKeyCode::Compose, - //ffi::XK_Kanji => VirtualKeyCode::Kanji, - //ffi::XK_Muhenkan => VirtualKeyCode::Muhenkan, - //ffi::XK_Henkan_Mode => VirtualKeyCode::Henkan_mode, - //ffi::XK_Henkan => VirtualKeyCode::Henkan, - //ffi::XK_Romaji => VirtualKeyCode::Romaji, - //ffi::XK_Hiragana => VirtualKeyCode::Hiragana, - //ffi::XK_Katakana => VirtualKeyCode::Katakana, - //ffi::XK_Hiragana_Katakana => VirtualKeyCode::Hiragana_katakana, - //ffi::XK_Zenkaku => VirtualKeyCode::Zenkaku, - //ffi::XK_Hankaku => VirtualKeyCode::Hankaku, - //ffi::XK_Zenkaku_Hankaku => VirtualKeyCode::Zenkaku_hankaku, - //ffi::XK_Touroku => VirtualKeyCode::Touroku, - //ffi::XK_Massyo => VirtualKeyCode::Massyo, - //ffi::XK_Kana_Lock => VirtualKeyCode::Kana_lock, - //ffi::XK_Kana_Shift => VirtualKeyCode::Kana_shift, - //ffi::XK_Eisu_Shift => VirtualKeyCode::Eisu_shift, - //ffi::XK_Eisu_toggle => VirtualKeyCode::Eisu_toggle, - ffi::XK_Home => VirtualKeyCode::Home, - ffi::XK_Left => VirtualKeyCode::Left, - ffi::XK_Up => VirtualKeyCode::Up, - ffi::XK_Right => VirtualKeyCode::Right, - ffi::XK_Down => VirtualKeyCode::Down, - //ffi::XK_Prior => VirtualKeyCode::Prior, - ffi::XK_Page_Up => VirtualKeyCode::PageUp, - //ffi::XK_Next => VirtualKeyCode::Next, - ffi::XK_Page_Down => VirtualKeyCode::PageDown, - ffi::XK_End => VirtualKeyCode::End, - //ffi::XK_Begin => VirtualKeyCode::Begin, - //ffi::XK_Win_L => VirtualKeyCode::Win_l, - //ffi::XK_Win_R => VirtualKeyCode::Win_r, - //ffi::XK_App => VirtualKeyCode::App, - //ffi::XK_Select => VirtualKeyCode::Select, - //ffi::XK_Print => VirtualKeyCode::Print, - //ffi::XK_Execute => VirtualKeyCode::Execute, - ffi::XK_Insert => VirtualKeyCode::Insert, - //ffi::XK_Undo => VirtualKeyCode::Undo, - //ffi::XK_Redo => VirtualKeyCode::Redo, - //ffi::XK_Menu => VirtualKeyCode::Menu, - //ffi::XK_Find => VirtualKeyCode::Find, - //ffi::XK_Cancel => VirtualKeyCode::Cancel, - //ffi::XK_Help => VirtualKeyCode::Help, - //ffi::XK_Break => VirtualKeyCode::Break, - //ffi::XK_Mode_switch => VirtualKeyCode::Mode_switch, - //ffi::XK_script_switch => VirtualKeyCode::Script_switch, - ffi::XK_Num_Lock => VirtualKeyCode::Numlock, - //ffi::XK_KP_Space => VirtualKeyCode::Kp_space, - //ffi::XK_KP_Tab => VirtualKeyCode::Kp_tab, - ffi::XK_KP_Enter => VirtualKeyCode::NumpadEnter, - //ffi::XK_KP_F1 => VirtualKeyCode::Kp_f1, - //ffi::XK_KP_F2 => VirtualKeyCode::Kp_f2, - //ffi::XK_KP_F3 => VirtualKeyCode::Kp_f3, - //ffi::XK_KP_F4 => VirtualKeyCode::Kp_f4, - ffi::XK_KP_Home => VirtualKeyCode::Home, - ffi::XK_KP_Left => VirtualKeyCode::Left, - ffi::XK_KP_Up => VirtualKeyCode::Up, - ffi::XK_KP_Right => VirtualKeyCode::Right, - ffi::XK_KP_Down => VirtualKeyCode::Down, - //ffi::XK_KP_Prior => VirtualKeyCode::Kp_prior, - ffi::XK_KP_Page_Up => VirtualKeyCode::PageUp, - //ffi::XK_KP_Next => VirtualKeyCode::Kp_next, - ffi::XK_KP_Page_Down => VirtualKeyCode::PageDown, - ffi::XK_KP_End => VirtualKeyCode::End, - //ffi::XK_KP_Begin => VirtualKeyCode::Kp_begin, - ffi::XK_KP_Insert => VirtualKeyCode::Insert, - ffi::XK_KP_Delete => VirtualKeyCode::Delete, - ffi::XK_KP_Equal => VirtualKeyCode::NumpadEquals, - ffi::XK_KP_Multiply => VirtualKeyCode::NumpadMultiply, - ffi::XK_KP_Add => VirtualKeyCode::NumpadAdd, - ffi::XK_KP_Separator => VirtualKeyCode::NumpadComma, - ffi::XK_KP_Subtract => VirtualKeyCode::NumpadSubtract, - ffi::XK_KP_Decimal => VirtualKeyCode::NumpadDecimal, - ffi::XK_KP_Divide => VirtualKeyCode::NumpadDivide, - ffi::XK_KP_0 => VirtualKeyCode::Numpad0, - ffi::XK_KP_1 => VirtualKeyCode::Numpad1, - ffi::XK_KP_2 => VirtualKeyCode::Numpad2, - ffi::XK_KP_3 => VirtualKeyCode::Numpad3, - ffi::XK_KP_4 => VirtualKeyCode::Numpad4, - ffi::XK_KP_5 => VirtualKeyCode::Numpad5, - ffi::XK_KP_6 => VirtualKeyCode::Numpad6, - ffi::XK_KP_7 => VirtualKeyCode::Numpad7, - ffi::XK_KP_8 => VirtualKeyCode::Numpad8, - ffi::XK_KP_9 => VirtualKeyCode::Numpad9, - ffi::XK_F1 => VirtualKeyCode::F1, - ffi::XK_F2 => VirtualKeyCode::F2, - ffi::XK_F3 => VirtualKeyCode::F3, - ffi::XK_F4 => VirtualKeyCode::F4, - ffi::XK_F5 => VirtualKeyCode::F5, - ffi::XK_F6 => VirtualKeyCode::F6, - ffi::XK_F7 => VirtualKeyCode::F7, - ffi::XK_F8 => VirtualKeyCode::F8, - ffi::XK_F9 => VirtualKeyCode::F9, - ffi::XK_F10 => VirtualKeyCode::F10, - ffi::XK_F11 => VirtualKeyCode::F11, - //ffi::XK_L1 => VirtualKeyCode::L1, - ffi::XK_F12 => VirtualKeyCode::F12, - //ffi::XK_L2 => VirtualKeyCode::L2, - ffi::XK_F13 => VirtualKeyCode::F13, - //ffi::XK_L3 => VirtualKeyCode::L3, - ffi::XK_F14 => VirtualKeyCode::F14, - //ffi::XK_L4 => VirtualKeyCode::L4, - ffi::XK_F15 => VirtualKeyCode::F15, - //ffi::XK_L5 => VirtualKeyCode::L5, - ffi::XK_F16 => VirtualKeyCode::F16, - //ffi::XK_L6 => VirtualKeyCode::L6, - ffi::XK_F17 => VirtualKeyCode::F17, - //ffi::XK_L7 => VirtualKeyCode::L7, - ffi::XK_F18 => VirtualKeyCode::F18, - //ffi::XK_L8 => VirtualKeyCode::L8, - ffi::XK_F19 => VirtualKeyCode::F19, - //ffi::XK_L9 => VirtualKeyCode::L9, - ffi::XK_F20 => VirtualKeyCode::F20, - //ffi::XK_L10 => VirtualKeyCode::L10, - ffi::XK_F21 => VirtualKeyCode::F21, - //ffi::XK_R1 => VirtualKeyCode::R1, - ffi::XK_F22 => VirtualKeyCode::F22, - //ffi::XK_R2 => VirtualKeyCode::R2, - ffi::XK_F23 => VirtualKeyCode::F23, - //ffi::XK_R3 => VirtualKeyCode::R3, - ffi::XK_F24 => VirtualKeyCode::F24, - //ffi::XK_R4 => VirtualKeyCode::R4, - //ffi::XK_F25 => VirtualKeyCode::F25, - //ffi::XK_R5 => VirtualKeyCode::R5, - //ffi::XK_F26 => VirtualKeyCode::F26, - //ffi::XK_R6 => VirtualKeyCode::R6, - //ffi::XK_F27 => VirtualKeyCode::F27, - //ffi::XK_R7 => VirtualKeyCode::R7, - //ffi::XK_F28 => VirtualKeyCode::F28, - //ffi::XK_R8 => VirtualKeyCode::R8, - //ffi::XK_F29 => VirtualKeyCode::F29, - //ffi::XK_R9 => VirtualKeyCode::R9, - //ffi::XK_F30 => VirtualKeyCode::F30, - //ffi::XK_R10 => VirtualKeyCode::R10, - //ffi::XK_F31 => VirtualKeyCode::F31, - //ffi::XK_R11 => VirtualKeyCode::R11, - //ffi::XK_F32 => VirtualKeyCode::F32, - //ffi::XK_R12 => VirtualKeyCode::R12, - //ffi::XK_F33 => VirtualKeyCode::F33, - //ffi::XK_R13 => VirtualKeyCode::R13, - //ffi::XK_F34 => VirtualKeyCode::F34, - //ffi::XK_R14 => VirtualKeyCode::R14, - //ffi::XK_F35 => VirtualKeyCode::F35, - //ffi::XK_R15 => VirtualKeyCode::R15, - ffi::XK_Shift_L => VirtualKeyCode::LShift, - ffi::XK_Shift_R => VirtualKeyCode::RShift, - ffi::XK_Control_L => VirtualKeyCode::LControl, - ffi::XK_Control_R => VirtualKeyCode::RControl, - //ffi::XK_Caps_Lock => VirtualKeyCode::Caps_lock, - //ffi::XK_Shift_Lock => VirtualKeyCode::Shift_lock, - //ffi::XK_Meta_L => VirtualKeyCode::Meta_l, - //ffi::XK_Meta_R => VirtualKeyCode::Meta_r, - ffi::XK_Alt_L => VirtualKeyCode::LAlt, - ffi::XK_Alt_R => VirtualKeyCode::RAlt, - //ffi::XK_Super_L => VirtualKeyCode::Super_l, - //ffi::XK_Super_R => VirtualKeyCode::Super_r, - //ffi::XK_Hyper_L => VirtualKeyCode::Hyper_l, - //ffi::XK_Hyper_R => VirtualKeyCode::Hyper_r, - ffi::XK_ISO_Left_Tab => VirtualKeyCode::Tab, - ffi::XK_space => VirtualKeyCode::Space, - //ffi::XK_exclam => VirtualKeyCode::Exclam, - //ffi::XK_quotedbl => VirtualKeyCode::Quotedbl, - //ffi::XK_numbersign => VirtualKeyCode::Numbersign, - //ffi::XK_dollar => VirtualKeyCode::Dollar, - //ffi::XK_percent => VirtualKeyCode::Percent, - //ffi::XK_ampersand => VirtualKeyCode::Ampersand, - ffi::XK_apostrophe => VirtualKeyCode::Apostrophe, - //ffi::XK_quoteright => VirtualKeyCode::Quoteright, - //ffi::XK_parenleft => VirtualKeyCode::Parenleft, - //ffi::XK_parenright => VirtualKeyCode::Parenright, - ffi::XK_asterisk => VirtualKeyCode::Asterisk, - ffi::XK_plus => VirtualKeyCode::Plus, - ffi::XK_comma => VirtualKeyCode::Comma, - ffi::XK_minus => VirtualKeyCode::Minus, - ffi::XK_period => VirtualKeyCode::Period, - ffi::XK_slash => VirtualKeyCode::Slash, - ffi::XK_0 => VirtualKeyCode::Key0, - ffi::XK_1 => VirtualKeyCode::Key1, - ffi::XK_2 => VirtualKeyCode::Key2, - ffi::XK_3 => VirtualKeyCode::Key3, - ffi::XK_4 => VirtualKeyCode::Key4, - ffi::XK_5 => VirtualKeyCode::Key5, - ffi::XK_6 => VirtualKeyCode::Key6, - ffi::XK_7 => VirtualKeyCode::Key7, - ffi::XK_8 => VirtualKeyCode::Key8, - ffi::XK_9 => VirtualKeyCode::Key9, - ffi::XK_colon => VirtualKeyCode::Colon, - ffi::XK_semicolon => VirtualKeyCode::Semicolon, - //ffi::XK_less => VirtualKeyCode::Less, - ffi::XK_equal => VirtualKeyCode::Equals, - //ffi::XK_greater => VirtualKeyCode::Greater, - //ffi::XK_question => VirtualKeyCode::Question, - ffi::XK_at => VirtualKeyCode::At, - ffi::XK_A => VirtualKeyCode::A, - ffi::XK_B => VirtualKeyCode::B, - ffi::XK_C => VirtualKeyCode::C, - ffi::XK_D => VirtualKeyCode::D, - ffi::XK_E => VirtualKeyCode::E, - ffi::XK_F => VirtualKeyCode::F, - ffi::XK_G => VirtualKeyCode::G, - ffi::XK_H => VirtualKeyCode::H, - ffi::XK_I => VirtualKeyCode::I, - ffi::XK_J => VirtualKeyCode::J, - ffi::XK_K => VirtualKeyCode::K, - ffi::XK_L => VirtualKeyCode::L, - ffi::XK_M => VirtualKeyCode::M, - ffi::XK_N => VirtualKeyCode::N, - ffi::XK_O => VirtualKeyCode::O, - ffi::XK_P => VirtualKeyCode::P, - ffi::XK_Q => VirtualKeyCode::Q, - ffi::XK_R => VirtualKeyCode::R, - ffi::XK_S => VirtualKeyCode::S, - ffi::XK_T => VirtualKeyCode::T, - ffi::XK_U => VirtualKeyCode::U, - ffi::XK_V => VirtualKeyCode::V, - ffi::XK_W => VirtualKeyCode::W, - ffi::XK_X => VirtualKeyCode::X, - ffi::XK_Y => VirtualKeyCode::Y, - ffi::XK_Z => VirtualKeyCode::Z, - ffi::XK_bracketleft => VirtualKeyCode::LBracket, - ffi::XK_backslash => VirtualKeyCode::Backslash, - ffi::XK_bracketright => VirtualKeyCode::RBracket, - //ffi::XK_asciicircum => VirtualKeyCode::Asciicircum, - //ffi::XK_underscore => VirtualKeyCode::Underscore, - ffi::XK_grave => VirtualKeyCode::Grave, - //ffi::XK_quoteleft => VirtualKeyCode::Quoteleft, - ffi::XK_a => VirtualKeyCode::A, - ffi::XK_b => VirtualKeyCode::B, - ffi::XK_c => VirtualKeyCode::C, - ffi::XK_d => VirtualKeyCode::D, - ffi::XK_e => VirtualKeyCode::E, - ffi::XK_f => VirtualKeyCode::F, - ffi::XK_g => VirtualKeyCode::G, - ffi::XK_h => VirtualKeyCode::H, - ffi::XK_i => VirtualKeyCode::I, - ffi::XK_j => VirtualKeyCode::J, - ffi::XK_k => VirtualKeyCode::K, - ffi::XK_l => VirtualKeyCode::L, - ffi::XK_m => VirtualKeyCode::M, - ffi::XK_n => VirtualKeyCode::N, - ffi::XK_o => VirtualKeyCode::O, - ffi::XK_p => VirtualKeyCode::P, - ffi::XK_q => VirtualKeyCode::Q, - ffi::XK_r => VirtualKeyCode::R, - ffi::XK_s => VirtualKeyCode::S, - ffi::XK_t => VirtualKeyCode::T, - ffi::XK_u => VirtualKeyCode::U, - ffi::XK_v => VirtualKeyCode::V, - ffi::XK_w => VirtualKeyCode::W, - ffi::XK_x => VirtualKeyCode::X, - ffi::XK_y => VirtualKeyCode::Y, - ffi::XK_z => VirtualKeyCode::Z, - //ffi::XK_braceleft => VirtualKeyCode::Braceleft, - //ffi::XK_bar => VirtualKeyCode::Bar, - //ffi::XK_braceright => VirtualKeyCode::Braceright, - //ffi::XK_asciitilde => VirtualKeyCode::Asciitilde, - //ffi::XK_nobreakspace => VirtualKeyCode::Nobreakspace, - //ffi::XK_exclamdown => VirtualKeyCode::Exclamdown, - //ffi::XK_cent => VirtualKeyCode::Cent, - //ffi::XK_sterling => VirtualKeyCode::Sterling, - //ffi::XK_currency => VirtualKeyCode::Currency, - //ffi::XK_yen => VirtualKeyCode::Yen, - //ffi::XK_brokenbar => VirtualKeyCode::Brokenbar, - //ffi::XK_section => VirtualKeyCode::Section, - //ffi::XK_diaeresis => VirtualKeyCode::Diaeresis, - //ffi::XK_copyright => VirtualKeyCode::Copyright, - //ffi::XK_ordfeminine => VirtualKeyCode::Ordfeminine, - //ffi::XK_guillemotleft => VirtualKeyCode::Guillemotleft, - //ffi::XK_notsign => VirtualKeyCode::Notsign, - //ffi::XK_hyphen => VirtualKeyCode::Hyphen, - //ffi::XK_registered => VirtualKeyCode::Registered, - //ffi::XK_macron => VirtualKeyCode::Macron, - //ffi::XK_degree => VirtualKeyCode::Degree, - //ffi::XK_plusminus => VirtualKeyCode::Plusminus, - //ffi::XK_twosuperior => VirtualKeyCode::Twosuperior, - //ffi::XK_threesuperior => VirtualKeyCode::Threesuperior, - //ffi::XK_acute => VirtualKeyCode::Acute, - //ffi::XK_mu => VirtualKeyCode::Mu, - //ffi::XK_paragraph => VirtualKeyCode::Paragraph, - //ffi::XK_periodcentered => VirtualKeyCode::Periodcentered, - //ffi::XK_cedilla => VirtualKeyCode::Cedilla, - //ffi::XK_onesuperior => VirtualKeyCode::Onesuperior, - //ffi::XK_masculine => VirtualKeyCode::Masculine, - //ffi::XK_guillemotright => VirtualKeyCode::Guillemotright, - //ffi::XK_onequarter => VirtualKeyCode::Onequarter, - //ffi::XK_onehalf => VirtualKeyCode::Onehalf, - //ffi::XK_threequarters => VirtualKeyCode::Threequarters, - //ffi::XK_questiondown => VirtualKeyCode::Questiondown, - //ffi::XK_Agrave => VirtualKeyCode::Agrave, - //ffi::XK_Aacute => VirtualKeyCode::Aacute, - //ffi::XK_Acircumflex => VirtualKeyCode::Acircumflex, - //ffi::XK_Atilde => VirtualKeyCode::Atilde, - //ffi::XK_Adiaeresis => VirtualKeyCode::Adiaeresis, - //ffi::XK_Aring => VirtualKeyCode::Aring, - //ffi::XK_AE => VirtualKeyCode::Ae, - //ffi::XK_Ccedilla => VirtualKeyCode::Ccedilla, - //ffi::XK_Egrave => VirtualKeyCode::Egrave, - //ffi::XK_Eacute => VirtualKeyCode::Eacute, - //ffi::XK_Ecircumflex => VirtualKeyCode::Ecircumflex, - //ffi::XK_Ediaeresis => VirtualKeyCode::Ediaeresis, - //ffi::XK_Igrave => VirtualKeyCode::Igrave, - //ffi::XK_Iacute => VirtualKeyCode::Iacute, - //ffi::XK_Icircumflex => VirtualKeyCode::Icircumflex, - //ffi::XK_Idiaeresis => VirtualKeyCode::Idiaeresis, - //ffi::XK_ETH => VirtualKeyCode::Eth, - //ffi::XK_Eth => VirtualKeyCode::Eth, - //ffi::XK_Ntilde => VirtualKeyCode::Ntilde, - //ffi::XK_Ograve => VirtualKeyCode::Ograve, - //ffi::XK_Oacute => VirtualKeyCode::Oacute, - //ffi::XK_Ocircumflex => VirtualKeyCode::Ocircumflex, - //ffi::XK_Otilde => VirtualKeyCode::Otilde, - //ffi::XK_Odiaeresis => VirtualKeyCode::Odiaeresis, - //ffi::XK_multiply => VirtualKeyCode::Multiply, - //ffi::XK_Ooblique => VirtualKeyCode::Ooblique, - //ffi::XK_Ugrave => VirtualKeyCode::Ugrave, - //ffi::XK_Uacute => VirtualKeyCode::Uacute, - //ffi::XK_Ucircumflex => VirtualKeyCode::Ucircumflex, - //ffi::XK_Udiaeresis => VirtualKeyCode::Udiaeresis, - //ffi::XK_Yacute => VirtualKeyCode::Yacute, - //ffi::XK_THORN => VirtualKeyCode::Thorn, - //ffi::XK_Thorn => VirtualKeyCode::Thorn, - //ffi::XK_ssharp => VirtualKeyCode::Ssharp, - //ffi::XK_agrave => VirtualKeyCode::Agrave, - //ffi::XK_aacute => VirtualKeyCode::Aacute, - //ffi::XK_acircumflex => VirtualKeyCode::Acircumflex, - //ffi::XK_atilde => VirtualKeyCode::Atilde, - //ffi::XK_adiaeresis => VirtualKeyCode::Adiaeresis, - //ffi::XK_aring => VirtualKeyCode::Aring, - //ffi::XK_ae => VirtualKeyCode::Ae, - //ffi::XK_ccedilla => VirtualKeyCode::Ccedilla, - //ffi::XK_egrave => VirtualKeyCode::Egrave, - //ffi::XK_eacute => VirtualKeyCode::Eacute, - //ffi::XK_ecircumflex => VirtualKeyCode::Ecircumflex, - //ffi::XK_ediaeresis => VirtualKeyCode::Ediaeresis, - //ffi::XK_igrave => VirtualKeyCode::Igrave, - //ffi::XK_iacute => VirtualKeyCode::Iacute, - //ffi::XK_icircumflex => VirtualKeyCode::Icircumflex, - //ffi::XK_idiaeresis => VirtualKeyCode::Idiaeresis, - //ffi::XK_eth => VirtualKeyCode::Eth, - //ffi::XK_ntilde => VirtualKeyCode::Ntilde, - //ffi::XK_ograve => VirtualKeyCode::Ograve, - //ffi::XK_oacute => VirtualKeyCode::Oacute, - //ffi::XK_ocircumflex => VirtualKeyCode::Ocircumflex, - //ffi::XK_otilde => VirtualKeyCode::Otilde, - //ffi::XK_odiaeresis => VirtualKeyCode::Odiaeresis, - //ffi::XK_division => VirtualKeyCode::Division, - //ffi::XK_oslash => VirtualKeyCode::Oslash, - //ffi::XK_ugrave => VirtualKeyCode::Ugrave, - //ffi::XK_uacute => VirtualKeyCode::Uacute, - //ffi::XK_ucircumflex => VirtualKeyCode::Ucircumflex, - //ffi::XK_udiaeresis => VirtualKeyCode::Udiaeresis, - //ffi::XK_yacute => VirtualKeyCode::Yacute, - //ffi::XK_thorn => VirtualKeyCode::Thorn, - //ffi::XK_ydiaeresis => VirtualKeyCode::Ydiaeresis, - //ffi::XK_Aogonek => VirtualKeyCode::Aogonek, - //ffi::XK_breve => VirtualKeyCode::Breve, - //ffi::XK_Lstroke => VirtualKeyCode::Lstroke, - //ffi::XK_Lcaron => VirtualKeyCode::Lcaron, - //ffi::XK_Sacute => VirtualKeyCode::Sacute, - //ffi::XK_Scaron => VirtualKeyCode::Scaron, - //ffi::XK_Scedilla => VirtualKeyCode::Scedilla, - //ffi::XK_Tcaron => VirtualKeyCode::Tcaron, - //ffi::XK_Zacute => VirtualKeyCode::Zacute, - //ffi::XK_Zcaron => VirtualKeyCode::Zcaron, - //ffi::XK_Zabovedot => VirtualKeyCode::Zabovedot, - //ffi::XK_aogonek => VirtualKeyCode::Aogonek, - //ffi::XK_ogonek => VirtualKeyCode::Ogonek, - //ffi::XK_lstroke => VirtualKeyCode::Lstroke, - //ffi::XK_lcaron => VirtualKeyCode::Lcaron, - //ffi::XK_sacute => VirtualKeyCode::Sacute, - //ffi::XK_caron => VirtualKeyCode::Caron, - //ffi::XK_scaron => VirtualKeyCode::Scaron, - //ffi::XK_scedilla => VirtualKeyCode::Scedilla, - //ffi::XK_tcaron => VirtualKeyCode::Tcaron, - //ffi::XK_zacute => VirtualKeyCode::Zacute, - //ffi::XK_doubleacute => VirtualKeyCode::Doubleacute, - //ffi::XK_zcaron => VirtualKeyCode::Zcaron, - //ffi::XK_zabovedot => VirtualKeyCode::Zabovedot, - //ffi::XK_Racute => VirtualKeyCode::Racute, - //ffi::XK_Abreve => VirtualKeyCode::Abreve, - //ffi::XK_Lacute => VirtualKeyCode::Lacute, - //ffi::XK_Cacute => VirtualKeyCode::Cacute, - //ffi::XK_Ccaron => VirtualKeyCode::Ccaron, - //ffi::XK_Eogonek => VirtualKeyCode::Eogonek, - //ffi::XK_Ecaron => VirtualKeyCode::Ecaron, - //ffi::XK_Dcaron => VirtualKeyCode::Dcaron, - //ffi::XK_Dstroke => VirtualKeyCode::Dstroke, - //ffi::XK_Nacute => VirtualKeyCode::Nacute, - //ffi::XK_Ncaron => VirtualKeyCode::Ncaron, - //ffi::XK_Odoubleacute => VirtualKeyCode::Odoubleacute, - //ffi::XK_Rcaron => VirtualKeyCode::Rcaron, - //ffi::XK_Uring => VirtualKeyCode::Uring, - //ffi::XK_Udoubleacute => VirtualKeyCode::Udoubleacute, - //ffi::XK_Tcedilla => VirtualKeyCode::Tcedilla, - //ffi::XK_racute => VirtualKeyCode::Racute, - //ffi::XK_abreve => VirtualKeyCode::Abreve, - //ffi::XK_lacute => VirtualKeyCode::Lacute, - //ffi::XK_cacute => VirtualKeyCode::Cacute, - //ffi::XK_ccaron => VirtualKeyCode::Ccaron, - //ffi::XK_eogonek => VirtualKeyCode::Eogonek, - //ffi::XK_ecaron => VirtualKeyCode::Ecaron, - //ffi::XK_dcaron => VirtualKeyCode::Dcaron, - //ffi::XK_dstroke => VirtualKeyCode::Dstroke, - //ffi::XK_nacute => VirtualKeyCode::Nacute, - //ffi::XK_ncaron => VirtualKeyCode::Ncaron, - //ffi::XK_odoubleacute => VirtualKeyCode::Odoubleacute, - //ffi::XK_udoubleacute => VirtualKeyCode::Udoubleacute, - //ffi::XK_rcaron => VirtualKeyCode::Rcaron, - //ffi::XK_uring => VirtualKeyCode::Uring, - //ffi::XK_tcedilla => VirtualKeyCode::Tcedilla, - //ffi::XK_abovedot => VirtualKeyCode::Abovedot, - //ffi::XK_Hstroke => VirtualKeyCode::Hstroke, - //ffi::XK_Hcircumflex => VirtualKeyCode::Hcircumflex, - //ffi::XK_Iabovedot => VirtualKeyCode::Iabovedot, - //ffi::XK_Gbreve => VirtualKeyCode::Gbreve, - //ffi::XK_Jcircumflex => VirtualKeyCode::Jcircumflex, - //ffi::XK_hstroke => VirtualKeyCode::Hstroke, - //ffi::XK_hcircumflex => VirtualKeyCode::Hcircumflex, - //ffi::XK_idotless => VirtualKeyCode::Idotless, - //ffi::XK_gbreve => VirtualKeyCode::Gbreve, - //ffi::XK_jcircumflex => VirtualKeyCode::Jcircumflex, - //ffi::XK_Cabovedot => VirtualKeyCode::Cabovedot, - //ffi::XK_Ccircumflex => VirtualKeyCode::Ccircumflex, - //ffi::XK_Gabovedot => VirtualKeyCode::Gabovedot, - //ffi::XK_Gcircumflex => VirtualKeyCode::Gcircumflex, - //ffi::XK_Ubreve => VirtualKeyCode::Ubreve, - //ffi::XK_Scircumflex => VirtualKeyCode::Scircumflex, - //ffi::XK_cabovedot => VirtualKeyCode::Cabovedot, - //ffi::XK_ccircumflex => VirtualKeyCode::Ccircumflex, - //ffi::XK_gabovedot => VirtualKeyCode::Gabovedot, - //ffi::XK_gcircumflex => VirtualKeyCode::Gcircumflex, - //ffi::XK_ubreve => VirtualKeyCode::Ubreve, - //ffi::XK_scircumflex => VirtualKeyCode::Scircumflex, - //ffi::XK_kra => VirtualKeyCode::Kra, - //ffi::XK_kappa => VirtualKeyCode::Kappa, - //ffi::XK_Rcedilla => VirtualKeyCode::Rcedilla, - //ffi::XK_Itilde => VirtualKeyCode::Itilde, - //ffi::XK_Lcedilla => VirtualKeyCode::Lcedilla, - //ffi::XK_Emacron => VirtualKeyCode::Emacron, - //ffi::XK_Gcedilla => VirtualKeyCode::Gcedilla, - //ffi::XK_Tslash => VirtualKeyCode::Tslash, - //ffi::XK_rcedilla => VirtualKeyCode::Rcedilla, - //ffi::XK_itilde => VirtualKeyCode::Itilde, - //ffi::XK_lcedilla => VirtualKeyCode::Lcedilla, - //ffi::XK_emacron => VirtualKeyCode::Emacron, - //ffi::XK_gcedilla => VirtualKeyCode::Gcedilla, - //ffi::XK_tslash => VirtualKeyCode::Tslash, - //ffi::XK_ENG => VirtualKeyCode::Eng, - //ffi::XK_eng => VirtualKeyCode::Eng, - //ffi::XK_Amacron => VirtualKeyCode::Amacron, - //ffi::XK_Iogonek => VirtualKeyCode::Iogonek, - //ffi::XK_Eabovedot => VirtualKeyCode::Eabovedot, - //ffi::XK_Imacron => VirtualKeyCode::Imacron, - //ffi::XK_Ncedilla => VirtualKeyCode::Ncedilla, - //ffi::XK_Omacron => VirtualKeyCode::Omacron, - //ffi::XK_Kcedilla => VirtualKeyCode::Kcedilla, - //ffi::XK_Uogonek => VirtualKeyCode::Uogonek, - //ffi::XK_Utilde => VirtualKeyCode::Utilde, - //ffi::XK_Umacron => VirtualKeyCode::Umacron, - //ffi::XK_amacron => VirtualKeyCode::Amacron, - //ffi::XK_iogonek => VirtualKeyCode::Iogonek, - //ffi::XK_eabovedot => VirtualKeyCode::Eabovedot, - //ffi::XK_imacron => VirtualKeyCode::Imacron, - //ffi::XK_ncedilla => VirtualKeyCode::Ncedilla, - //ffi::XK_omacron => VirtualKeyCode::Omacron, - //ffi::XK_kcedilla => VirtualKeyCode::Kcedilla, - //ffi::XK_uogonek => VirtualKeyCode::Uogonek, - //ffi::XK_utilde => VirtualKeyCode::Utilde, - //ffi::XK_umacron => VirtualKeyCode::Umacron, - //ffi::XK_overline => VirtualKeyCode::Overline, - //ffi::XK_kana_fullstop => VirtualKeyCode::Kana_fullstop, - //ffi::XK_kana_openingbracket => VirtualKeyCode::Kana_openingbracket, - //ffi::XK_kana_closingbracket => VirtualKeyCode::Kana_closingbracket, - //ffi::XK_kana_comma => VirtualKeyCode::Kana_comma, - //ffi::XK_kana_conjunctive => VirtualKeyCode::Kana_conjunctive, - //ffi::XK_kana_middledot => VirtualKeyCode::Kana_middledot, - //ffi::XK_kana_WO => VirtualKeyCode::Kana_wo, - //ffi::XK_kana_a => VirtualKeyCode::Kana_a, - //ffi::XK_kana_i => VirtualKeyCode::Kana_i, - //ffi::XK_kana_u => VirtualKeyCode::Kana_u, - //ffi::XK_kana_e => VirtualKeyCode::Kana_e, - //ffi::XK_kana_o => VirtualKeyCode::Kana_o, - //ffi::XK_kana_ya => VirtualKeyCode::Kana_ya, - //ffi::XK_kana_yu => VirtualKeyCode::Kana_yu, - //ffi::XK_kana_yo => VirtualKeyCode::Kana_yo, - //ffi::XK_kana_tsu => VirtualKeyCode::Kana_tsu, - //ffi::XK_kana_tu => VirtualKeyCode::Kana_tu, - //ffi::XK_prolongedsound => VirtualKeyCode::Prolongedsound, - //ffi::XK_kana_A => VirtualKeyCode::Kana_a, - //ffi::XK_kana_I => VirtualKeyCode::Kana_i, - //ffi::XK_kana_U => VirtualKeyCode::Kana_u, - //ffi::XK_kana_E => VirtualKeyCode::Kana_e, - //ffi::XK_kana_O => VirtualKeyCode::Kana_o, - //ffi::XK_kana_KA => VirtualKeyCode::Kana_ka, - //ffi::XK_kana_KI => VirtualKeyCode::Kana_ki, - //ffi::XK_kana_KU => VirtualKeyCode::Kana_ku, - //ffi::XK_kana_KE => VirtualKeyCode::Kana_ke, - //ffi::XK_kana_KO => VirtualKeyCode::Kana_ko, - //ffi::XK_kana_SA => VirtualKeyCode::Kana_sa, - //ffi::XK_kana_SHI => VirtualKeyCode::Kana_shi, - //ffi::XK_kana_SU => VirtualKeyCode::Kana_su, - //ffi::XK_kana_SE => VirtualKeyCode::Kana_se, - //ffi::XK_kana_SO => VirtualKeyCode::Kana_so, - //ffi::XK_kana_TA => VirtualKeyCode::Kana_ta, - //ffi::XK_kana_CHI => VirtualKeyCode::Kana_chi, - //ffi::XK_kana_TI => VirtualKeyCode::Kana_ti, - //ffi::XK_kana_TSU => VirtualKeyCode::Kana_tsu, - //ffi::XK_kana_TU => VirtualKeyCode::Kana_tu, - //ffi::XK_kana_TE => VirtualKeyCode::Kana_te, - //ffi::XK_kana_TO => VirtualKeyCode::Kana_to, - //ffi::XK_kana_NA => VirtualKeyCode::Kana_na, - //ffi::XK_kana_NI => VirtualKeyCode::Kana_ni, - //ffi::XK_kana_NU => VirtualKeyCode::Kana_nu, - //ffi::XK_kana_NE => VirtualKeyCode::Kana_ne, - //ffi::XK_kana_NO => VirtualKeyCode::Kana_no, - //ffi::XK_kana_HA => VirtualKeyCode::Kana_ha, - //ffi::XK_kana_HI => VirtualKeyCode::Kana_hi, - //ffi::XK_kana_FU => VirtualKeyCode::Kana_fu, - //ffi::XK_kana_HU => VirtualKeyCode::Kana_hu, - //ffi::XK_kana_HE => VirtualKeyCode::Kana_he, - //ffi::XK_kana_HO => VirtualKeyCode::Kana_ho, - //ffi::XK_kana_MA => VirtualKeyCode::Kana_ma, - //ffi::XK_kana_MI => VirtualKeyCode::Kana_mi, - //ffi::XK_kana_MU => VirtualKeyCode::Kana_mu, - //ffi::XK_kana_ME => VirtualKeyCode::Kana_me, - //ffi::XK_kana_MO => VirtualKeyCode::Kana_mo, - //ffi::XK_kana_YA => VirtualKeyCode::Kana_ya, - //ffi::XK_kana_YU => VirtualKeyCode::Kana_yu, - //ffi::XK_kana_YO => VirtualKeyCode::Kana_yo, - //ffi::XK_kana_RA => VirtualKeyCode::Kana_ra, - //ffi::XK_kana_RI => VirtualKeyCode::Kana_ri, - //ffi::XK_kana_RU => VirtualKeyCode::Kana_ru, - //ffi::XK_kana_RE => VirtualKeyCode::Kana_re, - //ffi::XK_kana_RO => VirtualKeyCode::Kana_ro, - //ffi::XK_kana_WA => VirtualKeyCode::Kana_wa, - //ffi::XK_kana_N => VirtualKeyCode::Kana_n, - //ffi::XK_voicedsound => VirtualKeyCode::Voicedsound, - //ffi::XK_semivoicedsound => VirtualKeyCode::Semivoicedsound, - //ffi::XK_kana_switch => VirtualKeyCode::Kana_switch, - //ffi::XK_Arabic_comma => VirtualKeyCode::Arabic_comma, - //ffi::XK_Arabic_semicolon => VirtualKeyCode::Arabic_semicolon, - //ffi::XK_Arabic_question_mark => VirtualKeyCode::Arabic_question_mark, - //ffi::XK_Arabic_hamza => VirtualKeyCode::Arabic_hamza, - //ffi::XK_Arabic_maddaonalef => VirtualKeyCode::Arabic_maddaonalef, - //ffi::XK_Arabic_hamzaonalef => VirtualKeyCode::Arabic_hamzaonalef, - //ffi::XK_Arabic_hamzaonwaw => VirtualKeyCode::Arabic_hamzaonwaw, - //ffi::XK_Arabic_hamzaunderalef => VirtualKeyCode::Arabic_hamzaunderalef, - //ffi::XK_Arabic_hamzaonyeh => VirtualKeyCode::Arabic_hamzaonyeh, - //ffi::XK_Arabic_alef => VirtualKeyCode::Arabic_alef, - //ffi::XK_Arabic_beh => VirtualKeyCode::Arabic_beh, - //ffi::XK_Arabic_tehmarbuta => VirtualKeyCode::Arabic_tehmarbuta, - //ffi::XK_Arabic_teh => VirtualKeyCode::Arabic_teh, - //ffi::XK_Arabic_theh => VirtualKeyCode::Arabic_theh, - //ffi::XK_Arabic_jeem => VirtualKeyCode::Arabic_jeem, - //ffi::XK_Arabic_hah => VirtualKeyCode::Arabic_hah, - //ffi::XK_Arabic_khah => VirtualKeyCode::Arabic_khah, - //ffi::XK_Arabic_dal => VirtualKeyCode::Arabic_dal, - //ffi::XK_Arabic_thal => VirtualKeyCode::Arabic_thal, - //ffi::XK_Arabic_ra => VirtualKeyCode::Arabic_ra, - //ffi::XK_Arabic_zain => VirtualKeyCode::Arabic_zain, - //ffi::XK_Arabic_seen => VirtualKeyCode::Arabic_seen, - //ffi::XK_Arabic_sheen => VirtualKeyCode::Arabic_sheen, - //ffi::XK_Arabic_sad => VirtualKeyCode::Arabic_sad, - //ffi::XK_Arabic_dad => VirtualKeyCode::Arabic_dad, - //ffi::XK_Arabic_tah => VirtualKeyCode::Arabic_tah, - //ffi::XK_Arabic_zah => VirtualKeyCode::Arabic_zah, - //ffi::XK_Arabic_ain => VirtualKeyCode::Arabic_ain, - //ffi::XK_Arabic_ghain => VirtualKeyCode::Arabic_ghain, - //ffi::XK_Arabic_tatweel => VirtualKeyCode::Arabic_tatweel, - //ffi::XK_Arabic_feh => VirtualKeyCode::Arabic_feh, - //ffi::XK_Arabic_qaf => VirtualKeyCode::Arabic_qaf, - //ffi::XK_Arabic_kaf => VirtualKeyCode::Arabic_kaf, - //ffi::XK_Arabic_lam => VirtualKeyCode::Arabic_lam, - //ffi::XK_Arabic_meem => VirtualKeyCode::Arabic_meem, - //ffi::XK_Arabic_noon => VirtualKeyCode::Arabic_noon, - //ffi::XK_Arabic_ha => VirtualKeyCode::Arabic_ha, - //ffi::XK_Arabic_heh => VirtualKeyCode::Arabic_heh, - //ffi::XK_Arabic_waw => VirtualKeyCode::Arabic_waw, - //ffi::XK_Arabic_alefmaksura => VirtualKeyCode::Arabic_alefmaksura, - //ffi::XK_Arabic_yeh => VirtualKeyCode::Arabic_yeh, - //ffi::XK_Arabic_fathatan => VirtualKeyCode::Arabic_fathatan, - //ffi::XK_Arabic_dammatan => VirtualKeyCode::Arabic_dammatan, - //ffi::XK_Arabic_kasratan => VirtualKeyCode::Arabic_kasratan, - //ffi::XK_Arabic_fatha => VirtualKeyCode::Arabic_fatha, - //ffi::XK_Arabic_damma => VirtualKeyCode::Arabic_damma, - //ffi::XK_Arabic_kasra => VirtualKeyCode::Arabic_kasra, - //ffi::XK_Arabic_shadda => VirtualKeyCode::Arabic_shadda, - //ffi::XK_Arabic_sukun => VirtualKeyCode::Arabic_sukun, - //ffi::XK_Arabic_switch => VirtualKeyCode::Arabic_switch, - //ffi::XK_Serbian_dje => VirtualKeyCode::Serbian_dje, - //ffi::XK_Macedonia_gje => VirtualKeyCode::Macedonia_gje, - //ffi::XK_Cyrillic_io => VirtualKeyCode::Cyrillic_io, - //ffi::XK_Ukrainian_ie => VirtualKeyCode::Ukrainian_ie, - //ffi::XK_Ukranian_je => VirtualKeyCode::Ukranian_je, - //ffi::XK_Macedonia_dse => VirtualKeyCode::Macedonia_dse, - //ffi::XK_Ukrainian_i => VirtualKeyCode::Ukrainian_i, - //ffi::XK_Ukranian_i => VirtualKeyCode::Ukranian_i, - //ffi::XK_Ukrainian_yi => VirtualKeyCode::Ukrainian_yi, - //ffi::XK_Ukranian_yi => VirtualKeyCode::Ukranian_yi, - //ffi::XK_Cyrillic_je => VirtualKeyCode::Cyrillic_je, - //ffi::XK_Serbian_je => VirtualKeyCode::Serbian_je, - //ffi::XK_Cyrillic_lje => VirtualKeyCode::Cyrillic_lje, - //ffi::XK_Serbian_lje => VirtualKeyCode::Serbian_lje, - //ffi::XK_Cyrillic_nje => VirtualKeyCode::Cyrillic_nje, - //ffi::XK_Serbian_nje => VirtualKeyCode::Serbian_nje, - //ffi::XK_Serbian_tshe => VirtualKeyCode::Serbian_tshe, - //ffi::XK_Macedonia_kje => VirtualKeyCode::Macedonia_kje, - //ffi::XK_Byelorussian_shortu => VirtualKeyCode::Byelorussian_shortu, - //ffi::XK_Cyrillic_dzhe => VirtualKeyCode::Cyrillic_dzhe, - //ffi::XK_Serbian_dze => VirtualKeyCode::Serbian_dze, - //ffi::XK_numerosign => VirtualKeyCode::Numerosign, - //ffi::XK_Serbian_DJE => VirtualKeyCode::Serbian_dje, - //ffi::XK_Macedonia_GJE => VirtualKeyCode::Macedonia_gje, - //ffi::XK_Cyrillic_IO => VirtualKeyCode::Cyrillic_io, - //ffi::XK_Ukrainian_IE => VirtualKeyCode::Ukrainian_ie, - //ffi::XK_Ukranian_JE => VirtualKeyCode::Ukranian_je, - //ffi::XK_Macedonia_DSE => VirtualKeyCode::Macedonia_dse, - //ffi::XK_Ukrainian_I => VirtualKeyCode::Ukrainian_i, - //ffi::XK_Ukranian_I => VirtualKeyCode::Ukranian_i, - //ffi::XK_Ukrainian_YI => VirtualKeyCode::Ukrainian_yi, - //ffi::XK_Ukranian_YI => VirtualKeyCode::Ukranian_yi, - //ffi::XK_Cyrillic_JE => VirtualKeyCode::Cyrillic_je, - //ffi::XK_Serbian_JE => VirtualKeyCode::Serbian_je, - //ffi::XK_Cyrillic_LJE => VirtualKeyCode::Cyrillic_lje, - //ffi::XK_Serbian_LJE => VirtualKeyCode::Serbian_lje, - //ffi::XK_Cyrillic_NJE => VirtualKeyCode::Cyrillic_nje, - //ffi::XK_Serbian_NJE => VirtualKeyCode::Serbian_nje, - //ffi::XK_Serbian_TSHE => VirtualKeyCode::Serbian_tshe, - //ffi::XK_Macedonia_KJE => VirtualKeyCode::Macedonia_kje, - //ffi::XK_Byelorussian_SHORTU => VirtualKeyCode::Byelorussian_shortu, - //ffi::XK_Cyrillic_DZHE => VirtualKeyCode::Cyrillic_dzhe, - //ffi::XK_Serbian_DZE => VirtualKeyCode::Serbian_dze, - //ffi::XK_Cyrillic_yu => VirtualKeyCode::Cyrillic_yu, - //ffi::XK_Cyrillic_a => VirtualKeyCode::Cyrillic_a, - //ffi::XK_Cyrillic_be => VirtualKeyCode::Cyrillic_be, - //ffi::XK_Cyrillic_tse => VirtualKeyCode::Cyrillic_tse, - //ffi::XK_Cyrillic_de => VirtualKeyCode::Cyrillic_de, - //ffi::XK_Cyrillic_ie => VirtualKeyCode::Cyrillic_ie, - //ffi::XK_Cyrillic_ef => VirtualKeyCode::Cyrillic_ef, - //ffi::XK_Cyrillic_ghe => VirtualKeyCode::Cyrillic_ghe, - //ffi::XK_Cyrillic_ha => VirtualKeyCode::Cyrillic_ha, - //ffi::XK_Cyrillic_i => VirtualKeyCode::Cyrillic_i, - //ffi::XK_Cyrillic_shorti => VirtualKeyCode::Cyrillic_shorti, - //ffi::XK_Cyrillic_ka => VirtualKeyCode::Cyrillic_ka, - //ffi::XK_Cyrillic_el => VirtualKeyCode::Cyrillic_el, - //ffi::XK_Cyrillic_em => VirtualKeyCode::Cyrillic_em, - //ffi::XK_Cyrillic_en => VirtualKeyCode::Cyrillic_en, - //ffi::XK_Cyrillic_o => VirtualKeyCode::Cyrillic_o, - //ffi::XK_Cyrillic_pe => VirtualKeyCode::Cyrillic_pe, - //ffi::XK_Cyrillic_ya => VirtualKeyCode::Cyrillic_ya, - //ffi::XK_Cyrillic_er => VirtualKeyCode::Cyrillic_er, - //ffi::XK_Cyrillic_es => VirtualKeyCode::Cyrillic_es, - //ffi::XK_Cyrillic_te => VirtualKeyCode::Cyrillic_te, - //ffi::XK_Cyrillic_u => VirtualKeyCode::Cyrillic_u, - //ffi::XK_Cyrillic_zhe => VirtualKeyCode::Cyrillic_zhe, - //ffi::XK_Cyrillic_ve => VirtualKeyCode::Cyrillic_ve, - //ffi::XK_Cyrillic_softsign => VirtualKeyCode::Cyrillic_softsign, - //ffi::XK_Cyrillic_yeru => VirtualKeyCode::Cyrillic_yeru, - //ffi::XK_Cyrillic_ze => VirtualKeyCode::Cyrillic_ze, - //ffi::XK_Cyrillic_sha => VirtualKeyCode::Cyrillic_sha, - //ffi::XK_Cyrillic_e => VirtualKeyCode::Cyrillic_e, - //ffi::XK_Cyrillic_shcha => VirtualKeyCode::Cyrillic_shcha, - //ffi::XK_Cyrillic_che => VirtualKeyCode::Cyrillic_che, - //ffi::XK_Cyrillic_hardsign => VirtualKeyCode::Cyrillic_hardsign, - //ffi::XK_Cyrillic_YU => VirtualKeyCode::Cyrillic_yu, - //ffi::XK_Cyrillic_A => VirtualKeyCode::Cyrillic_a, - //ffi::XK_Cyrillic_BE => VirtualKeyCode::Cyrillic_be, - //ffi::XK_Cyrillic_TSE => VirtualKeyCode::Cyrillic_tse, - //ffi::XK_Cyrillic_DE => VirtualKeyCode::Cyrillic_de, - //ffi::XK_Cyrillic_IE => VirtualKeyCode::Cyrillic_ie, - //ffi::XK_Cyrillic_EF => VirtualKeyCode::Cyrillic_ef, - //ffi::XK_Cyrillic_GHE => VirtualKeyCode::Cyrillic_ghe, - //ffi::XK_Cyrillic_HA => VirtualKeyCode::Cyrillic_ha, - //ffi::XK_Cyrillic_I => VirtualKeyCode::Cyrillic_i, - //ffi::XK_Cyrillic_SHORTI => VirtualKeyCode::Cyrillic_shorti, - //ffi::XK_Cyrillic_KA => VirtualKeyCode::Cyrillic_ka, - //ffi::XK_Cyrillic_EL => VirtualKeyCode::Cyrillic_el, - //ffi::XK_Cyrillic_EM => VirtualKeyCode::Cyrillic_em, - //ffi::XK_Cyrillic_EN => VirtualKeyCode::Cyrillic_en, - //ffi::XK_Cyrillic_O => VirtualKeyCode::Cyrillic_o, - //ffi::XK_Cyrillic_PE => VirtualKeyCode::Cyrillic_pe, - //ffi::XK_Cyrillic_YA => VirtualKeyCode::Cyrillic_ya, - //ffi::XK_Cyrillic_ER => VirtualKeyCode::Cyrillic_er, - //ffi::XK_Cyrillic_ES => VirtualKeyCode::Cyrillic_es, - //ffi::XK_Cyrillic_TE => VirtualKeyCode::Cyrillic_te, - //ffi::XK_Cyrillic_U => VirtualKeyCode::Cyrillic_u, - //ffi::XK_Cyrillic_ZHE => VirtualKeyCode::Cyrillic_zhe, - //ffi::XK_Cyrillic_VE => VirtualKeyCode::Cyrillic_ve, - //ffi::XK_Cyrillic_SOFTSIGN => VirtualKeyCode::Cyrillic_softsign, - //ffi::XK_Cyrillic_YERU => VirtualKeyCode::Cyrillic_yeru, - //ffi::XK_Cyrillic_ZE => VirtualKeyCode::Cyrillic_ze, - //ffi::XK_Cyrillic_SHA => VirtualKeyCode::Cyrillic_sha, - //ffi::XK_Cyrillic_E => VirtualKeyCode::Cyrillic_e, - //ffi::XK_Cyrillic_SHCHA => VirtualKeyCode::Cyrillic_shcha, - //ffi::XK_Cyrillic_CHE => VirtualKeyCode::Cyrillic_che, - //ffi::XK_Cyrillic_HARDSIGN => VirtualKeyCode::Cyrillic_hardsign, - //ffi::XK_Greek_ALPHAaccent => VirtualKeyCode::Greek_alphaaccent, - //ffi::XK_Greek_EPSILONaccent => VirtualKeyCode::Greek_epsilonaccent, - //ffi::XK_Greek_ETAaccent => VirtualKeyCode::Greek_etaaccent, - //ffi::XK_Greek_IOTAaccent => VirtualKeyCode::Greek_iotaaccent, - //ffi::XK_Greek_IOTAdiaeresis => VirtualKeyCode::Greek_iotadiaeresis, - //ffi::XK_Greek_OMICRONaccent => VirtualKeyCode::Greek_omicronaccent, - //ffi::XK_Greek_UPSILONaccent => VirtualKeyCode::Greek_upsilonaccent, - //ffi::XK_Greek_UPSILONdieresis => VirtualKeyCode::Greek_upsilondieresis, - //ffi::XK_Greek_OMEGAaccent => VirtualKeyCode::Greek_omegaaccent, - //ffi::XK_Greek_accentdieresis => VirtualKeyCode::Greek_accentdieresis, - //ffi::XK_Greek_horizbar => VirtualKeyCode::Greek_horizbar, - //ffi::XK_Greek_alphaaccent => VirtualKeyCode::Greek_alphaaccent, - //ffi::XK_Greek_epsilonaccent => VirtualKeyCode::Greek_epsilonaccent, - //ffi::XK_Greek_etaaccent => VirtualKeyCode::Greek_etaaccent, - //ffi::XK_Greek_iotaaccent => VirtualKeyCode::Greek_iotaaccent, - //ffi::XK_Greek_iotadieresis => VirtualKeyCode::Greek_iotadieresis, - //ffi::XK_Greek_iotaaccentdieresis => VirtualKeyCode::Greek_iotaaccentdieresis, - //ffi::XK_Greek_omicronaccent => VirtualKeyCode::Greek_omicronaccent, - //ffi::XK_Greek_upsilonaccent => VirtualKeyCode::Greek_upsilonaccent, - //ffi::XK_Greek_upsilondieresis => VirtualKeyCode::Greek_upsilondieresis, - //ffi::XK_Greek_upsilonaccentdieresis => VirtualKeyCode::Greek_upsilonaccentdieresis, - //ffi::XK_Greek_omegaaccent => VirtualKeyCode::Greek_omegaaccent, - //ffi::XK_Greek_ALPHA => VirtualKeyCode::Greek_alpha, - //ffi::XK_Greek_BETA => VirtualKeyCode::Greek_beta, - //ffi::XK_Greek_GAMMA => VirtualKeyCode::Greek_gamma, - //ffi::XK_Greek_DELTA => VirtualKeyCode::Greek_delta, - //ffi::XK_Greek_EPSILON => VirtualKeyCode::Greek_epsilon, - //ffi::XK_Greek_ZETA => VirtualKeyCode::Greek_zeta, - //ffi::XK_Greek_ETA => VirtualKeyCode::Greek_eta, - //ffi::XK_Greek_THETA => VirtualKeyCode::Greek_theta, - //ffi::XK_Greek_IOTA => VirtualKeyCode::Greek_iota, - //ffi::XK_Greek_KAPPA => VirtualKeyCode::Greek_kappa, - //ffi::XK_Greek_LAMDA => VirtualKeyCode::Greek_lamda, - //ffi::XK_Greek_LAMBDA => VirtualKeyCode::Greek_lambda, - //ffi::XK_Greek_MU => VirtualKeyCode::Greek_mu, - //ffi::XK_Greek_NU => VirtualKeyCode::Greek_nu, - //ffi::XK_Greek_XI => VirtualKeyCode::Greek_xi, - //ffi::XK_Greek_OMICRON => VirtualKeyCode::Greek_omicron, - //ffi::XK_Greek_PI => VirtualKeyCode::Greek_pi, - //ffi::XK_Greek_RHO => VirtualKeyCode::Greek_rho, - //ffi::XK_Greek_SIGMA => VirtualKeyCode::Greek_sigma, - //ffi::XK_Greek_TAU => VirtualKeyCode::Greek_tau, - //ffi::XK_Greek_UPSILON => VirtualKeyCode::Greek_upsilon, - //ffi::XK_Greek_PHI => VirtualKeyCode::Greek_phi, - //ffi::XK_Greek_CHI => VirtualKeyCode::Greek_chi, - //ffi::XK_Greek_PSI => VirtualKeyCode::Greek_psi, - //ffi::XK_Greek_OMEGA => VirtualKeyCode::Greek_omega, - //ffi::XK_Greek_alpha => VirtualKeyCode::Greek_alpha, - //ffi::XK_Greek_beta => VirtualKeyCode::Greek_beta, - //ffi::XK_Greek_gamma => VirtualKeyCode::Greek_gamma, - //ffi::XK_Greek_delta => VirtualKeyCode::Greek_delta, - //ffi::XK_Greek_epsilon => VirtualKeyCode::Greek_epsilon, - //ffi::XK_Greek_zeta => VirtualKeyCode::Greek_zeta, - //ffi::XK_Greek_eta => VirtualKeyCode::Greek_eta, - //ffi::XK_Greek_theta => VirtualKeyCode::Greek_theta, - //ffi::XK_Greek_iota => VirtualKeyCode::Greek_iota, - //ffi::XK_Greek_kappa => VirtualKeyCode::Greek_kappa, - //ffi::XK_Greek_lamda => VirtualKeyCode::Greek_lamda, - //ffi::XK_Greek_lambda => VirtualKeyCode::Greek_lambda, - //ffi::XK_Greek_mu => VirtualKeyCode::Greek_mu, - //ffi::XK_Greek_nu => VirtualKeyCode::Greek_nu, - //ffi::XK_Greek_xi => VirtualKeyCode::Greek_xi, - //ffi::XK_Greek_omicron => VirtualKeyCode::Greek_omicron, - //ffi::XK_Greek_pi => VirtualKeyCode::Greek_pi, - //ffi::XK_Greek_rho => VirtualKeyCode::Greek_rho, - //ffi::XK_Greek_sigma => VirtualKeyCode::Greek_sigma, - //ffi::XK_Greek_finalsmallsigma => VirtualKeyCode::Greek_finalsmallsigma, - //ffi::XK_Greek_tau => VirtualKeyCode::Greek_tau, - //ffi::XK_Greek_upsilon => VirtualKeyCode::Greek_upsilon, - //ffi::XK_Greek_phi => VirtualKeyCode::Greek_phi, - //ffi::XK_Greek_chi => VirtualKeyCode::Greek_chi, - //ffi::XK_Greek_psi => VirtualKeyCode::Greek_psi, - //ffi::XK_Greek_omega => VirtualKeyCode::Greek_omega, - //ffi::XK_Greek_switch => VirtualKeyCode::Greek_switch, - //ffi::XK_leftradical => VirtualKeyCode::Leftradical, - //ffi::XK_topleftradical => VirtualKeyCode::Topleftradical, - //ffi::XK_horizconnector => VirtualKeyCode::Horizconnector, - //ffi::XK_topintegral => VirtualKeyCode::Topintegral, - //ffi::XK_botintegral => VirtualKeyCode::Botintegral, - //ffi::XK_vertconnector => VirtualKeyCode::Vertconnector, - //ffi::XK_topleftsqbracket => VirtualKeyCode::Topleftsqbracket, - //ffi::XK_botleftsqbracket => VirtualKeyCode::Botleftsqbracket, - //ffi::XK_toprightsqbracket => VirtualKeyCode::Toprightsqbracket, - //ffi::XK_botrightsqbracket => VirtualKeyCode::Botrightsqbracket, - //ffi::XK_topleftparens => VirtualKeyCode::Topleftparens, - //ffi::XK_botleftparens => VirtualKeyCode::Botleftparens, - //ffi::XK_toprightparens => VirtualKeyCode::Toprightparens, - //ffi::XK_botrightparens => VirtualKeyCode::Botrightparens, - //ffi::XK_leftmiddlecurlybrace => VirtualKeyCode::Leftmiddlecurlybrace, - //ffi::XK_rightmiddlecurlybrace => VirtualKeyCode::Rightmiddlecurlybrace, - //ffi::XK_topleftsummation => VirtualKeyCode::Topleftsummation, - //ffi::XK_botleftsummation => VirtualKeyCode::Botleftsummation, - //ffi::XK_topvertsummationconnector => VirtualKeyCode::Topvertsummationconnector, - //ffi::XK_botvertsummationconnector => VirtualKeyCode::Botvertsummationconnector, - //ffi::XK_toprightsummation => VirtualKeyCode::Toprightsummation, - //ffi::XK_botrightsummation => VirtualKeyCode::Botrightsummation, - //ffi::XK_rightmiddlesummation => VirtualKeyCode::Rightmiddlesummation, - //ffi::XK_lessthanequal => VirtualKeyCode::Lessthanequal, - //ffi::XK_notequal => VirtualKeyCode::Notequal, - //ffi::XK_greaterthanequal => VirtualKeyCode::Greaterthanequal, - //ffi::XK_integral => VirtualKeyCode::Integral, - //ffi::XK_therefore => VirtualKeyCode::Therefore, - //ffi::XK_variation => VirtualKeyCode::Variation, - //ffi::XK_infinity => VirtualKeyCode::Infinity, - //ffi::XK_nabla => VirtualKeyCode::Nabla, - //ffi::XK_approximate => VirtualKeyCode::Approximate, - //ffi::XK_similarequal => VirtualKeyCode::Similarequal, - //ffi::XK_ifonlyif => VirtualKeyCode::Ifonlyif, - //ffi::XK_implies => VirtualKeyCode::Implies, - //ffi::XK_identical => VirtualKeyCode::Identical, - //ffi::XK_radical => VirtualKeyCode::Radical, - //ffi::XK_includedin => VirtualKeyCode::Includedin, - //ffi::XK_includes => VirtualKeyCode::Includes, - //ffi::XK_intersection => VirtualKeyCode::Intersection, - //ffi::XK_union => VirtualKeyCode::Union, - //ffi::XK_logicaland => VirtualKeyCode::Logicaland, - //ffi::XK_logicalor => VirtualKeyCode::Logicalor, - //ffi::XK_partialderivative => VirtualKeyCode::Partialderivative, - //ffi::XK_function => VirtualKeyCode::Function, - //ffi::XK_leftarrow => VirtualKeyCode::Leftarrow, - //ffi::XK_uparrow => VirtualKeyCode::Uparrow, - //ffi::XK_rightarrow => VirtualKeyCode::Rightarrow, - //ffi::XK_downarrow => VirtualKeyCode::Downarrow, - //ffi::XK_blank => VirtualKeyCode::Blank, - //ffi::XK_soliddiamond => VirtualKeyCode::Soliddiamond, - //ffi::XK_checkerboard => VirtualKeyCode::Checkerboard, - //ffi::XK_ht => VirtualKeyCode::Ht, - //ffi::XK_ff => VirtualKeyCode::Ff, - //ffi::XK_cr => VirtualKeyCode::Cr, - //ffi::XK_lf => VirtualKeyCode::Lf, - //ffi::XK_nl => VirtualKeyCode::Nl, - //ffi::XK_vt => VirtualKeyCode::Vt, - //ffi::XK_lowrightcorner => VirtualKeyCode::Lowrightcorner, - //ffi::XK_uprightcorner => VirtualKeyCode::Uprightcorner, - //ffi::XK_upleftcorner => VirtualKeyCode::Upleftcorner, - //ffi::XK_lowleftcorner => VirtualKeyCode::Lowleftcorner, - //ffi::XK_crossinglines => VirtualKeyCode::Crossinglines, - //ffi::XK_horizlinescan1 => VirtualKeyCode::Horizlinescan1, - //ffi::XK_horizlinescan3 => VirtualKeyCode::Horizlinescan3, - //ffi::XK_horizlinescan5 => VirtualKeyCode::Horizlinescan5, - //ffi::XK_horizlinescan7 => VirtualKeyCode::Horizlinescan7, - //ffi::XK_horizlinescan9 => VirtualKeyCode::Horizlinescan9, - //ffi::XK_leftt => VirtualKeyCode::Leftt, - //ffi::XK_rightt => VirtualKeyCode::Rightt, - //ffi::XK_bott => VirtualKeyCode::Bott, - //ffi::XK_topt => VirtualKeyCode::Topt, - //ffi::XK_vertbar => VirtualKeyCode::Vertbar, - //ffi::XK_emspace => VirtualKeyCode::Emspace, - //ffi::XK_enspace => VirtualKeyCode::Enspace, - //ffi::XK_em3space => VirtualKeyCode::Em3space, - //ffi::XK_em4space => VirtualKeyCode::Em4space, - //ffi::XK_digitspace => VirtualKeyCode::Digitspace, - //ffi::XK_punctspace => VirtualKeyCode::Punctspace, - //ffi::XK_thinspace => VirtualKeyCode::Thinspace, - //ffi::XK_hairspace => VirtualKeyCode::Hairspace, - //ffi::XK_emdash => VirtualKeyCode::Emdash, - //ffi::XK_endash => VirtualKeyCode::Endash, - //ffi::XK_signifblank => VirtualKeyCode::Signifblank, - //ffi::XK_ellipsis => VirtualKeyCode::Ellipsis, - //ffi::XK_doubbaselinedot => VirtualKeyCode::Doubbaselinedot, - //ffi::XK_onethird => VirtualKeyCode::Onethird, - //ffi::XK_twothirds => VirtualKeyCode::Twothirds, - //ffi::XK_onefifth => VirtualKeyCode::Onefifth, - //ffi::XK_twofifths => VirtualKeyCode::Twofifths, - //ffi::XK_threefifths => VirtualKeyCode::Threefifths, - //ffi::XK_fourfifths => VirtualKeyCode::Fourfifths, - //ffi::XK_onesixth => VirtualKeyCode::Onesixth, - //ffi::XK_fivesixths => VirtualKeyCode::Fivesixths, - //ffi::XK_careof => VirtualKeyCode::Careof, - //ffi::XK_figdash => VirtualKeyCode::Figdash, - //ffi::XK_leftanglebracket => VirtualKeyCode::Leftanglebracket, - //ffi::XK_decimalpoint => VirtualKeyCode::Decimalpoint, - //ffi::XK_rightanglebracket => VirtualKeyCode::Rightanglebracket, - //ffi::XK_marker => VirtualKeyCode::Marker, - //ffi::XK_oneeighth => VirtualKeyCode::Oneeighth, - //ffi::XK_threeeighths => VirtualKeyCode::Threeeighths, - //ffi::XK_fiveeighths => VirtualKeyCode::Fiveeighths, - //ffi::XK_seveneighths => VirtualKeyCode::Seveneighths, - //ffi::XK_trademark => VirtualKeyCode::Trademark, - //ffi::XK_signaturemark => VirtualKeyCode::Signaturemark, - //ffi::XK_trademarkincircle => VirtualKeyCode::Trademarkincircle, - //ffi::XK_leftopentriangle => VirtualKeyCode::Leftopentriangle, - //ffi::XK_rightopentriangle => VirtualKeyCode::Rightopentriangle, - //ffi::XK_emopencircle => VirtualKeyCode::Emopencircle, - //ffi::XK_emopenrectangle => VirtualKeyCode::Emopenrectangle, - //ffi::XK_leftsinglequotemark => VirtualKeyCode::Leftsinglequotemark, - //ffi::XK_rightsinglequotemark => VirtualKeyCode::Rightsinglequotemark, - //ffi::XK_leftdoublequotemark => VirtualKeyCode::Leftdoublequotemark, - //ffi::XK_rightdoublequotemark => VirtualKeyCode::Rightdoublequotemark, - //ffi::XK_prescription => VirtualKeyCode::Prescription, - //ffi::XK_minutes => VirtualKeyCode::Minutes, - //ffi::XK_seconds => VirtualKeyCode::Seconds, - //ffi::XK_latincross => VirtualKeyCode::Latincross, - //ffi::XK_hexagram => VirtualKeyCode::Hexagram, - //ffi::XK_filledrectbullet => VirtualKeyCode::Filledrectbullet, - //ffi::XK_filledlefttribullet => VirtualKeyCode::Filledlefttribullet, - //ffi::XK_filledrighttribullet => VirtualKeyCode::Filledrighttribullet, - //ffi::XK_emfilledcircle => VirtualKeyCode::Emfilledcircle, - //ffi::XK_emfilledrect => VirtualKeyCode::Emfilledrect, - //ffi::XK_enopencircbullet => VirtualKeyCode::Enopencircbullet, - //ffi::XK_enopensquarebullet => VirtualKeyCode::Enopensquarebullet, - //ffi::XK_openrectbullet => VirtualKeyCode::Openrectbullet, - //ffi::XK_opentribulletup => VirtualKeyCode::Opentribulletup, - //ffi::XK_opentribulletdown => VirtualKeyCode::Opentribulletdown, - //ffi::XK_openstar => VirtualKeyCode::Openstar, - //ffi::XK_enfilledcircbullet => VirtualKeyCode::Enfilledcircbullet, - //ffi::XK_enfilledsqbullet => VirtualKeyCode::Enfilledsqbullet, - //ffi::XK_filledtribulletup => VirtualKeyCode::Filledtribulletup, - //ffi::XK_filledtribulletdown => VirtualKeyCode::Filledtribulletdown, - //ffi::XK_leftpointer => VirtualKeyCode::Leftpointer, - //ffi::XK_rightpointer => VirtualKeyCode::Rightpointer, - //ffi::XK_club => VirtualKeyCode::Club, - //ffi::XK_diamond => VirtualKeyCode::Diamond, - //ffi::XK_heart => VirtualKeyCode::Heart, - //ffi::XK_maltesecross => VirtualKeyCode::Maltesecross, - //ffi::XK_dagger => VirtualKeyCode::Dagger, - //ffi::XK_doubledagger => VirtualKeyCode::Doubledagger, - //ffi::XK_checkmark => VirtualKeyCode::Checkmark, - //ffi::XK_ballotcross => VirtualKeyCode::Ballotcross, - //ffi::XK_musicalsharp => VirtualKeyCode::Musicalsharp, - //ffi::XK_musicalflat => VirtualKeyCode::Musicalflat, - //ffi::XK_malesymbol => VirtualKeyCode::Malesymbol, - //ffi::XK_femalesymbol => VirtualKeyCode::Femalesymbol, - //ffi::XK_telephone => VirtualKeyCode::Telephone, - //ffi::XK_telephonerecorder => VirtualKeyCode::Telephonerecorder, - //ffi::XK_phonographcopyright => VirtualKeyCode::Phonographcopyright, - //ffi::XK_caret => VirtualKeyCode::Caret, - //ffi::XK_singlelowquotemark => VirtualKeyCode::Singlelowquotemark, - //ffi::XK_doublelowquotemark => VirtualKeyCode::Doublelowquotemark, - //ffi::XK_cursor => VirtualKeyCode::Cursor, - //ffi::XK_leftcaret => VirtualKeyCode::Leftcaret, - //ffi::XK_rightcaret => VirtualKeyCode::Rightcaret, - //ffi::XK_downcaret => VirtualKeyCode::Downcaret, - //ffi::XK_upcaret => VirtualKeyCode::Upcaret, - //ffi::XK_overbar => VirtualKeyCode::Overbar, - //ffi::XK_downtack => VirtualKeyCode::Downtack, - //ffi::XK_upshoe => VirtualKeyCode::Upshoe, - //ffi::XK_downstile => VirtualKeyCode::Downstile, - //ffi::XK_underbar => VirtualKeyCode::Underbar, - //ffi::XK_jot => VirtualKeyCode::Jot, - //ffi::XK_quad => VirtualKeyCode::Quad, - //ffi::XK_uptack => VirtualKeyCode::Uptack, - //ffi::XK_circle => VirtualKeyCode::Circle, - //ffi::XK_upstile => VirtualKeyCode::Upstile, - //ffi::XK_downshoe => VirtualKeyCode::Downshoe, - //ffi::XK_rightshoe => VirtualKeyCode::Rightshoe, - //ffi::XK_leftshoe => VirtualKeyCode::Leftshoe, - //ffi::XK_lefttack => VirtualKeyCode::Lefttack, - //ffi::XK_righttack => VirtualKeyCode::Righttack, - //ffi::XK_hebrew_doublelowline => VirtualKeyCode::Hebrew_doublelowline, - //ffi::XK_hebrew_aleph => VirtualKeyCode::Hebrew_aleph, - //ffi::XK_hebrew_bet => VirtualKeyCode::Hebrew_bet, - //ffi::XK_hebrew_beth => VirtualKeyCode::Hebrew_beth, - //ffi::XK_hebrew_gimel => VirtualKeyCode::Hebrew_gimel, - //ffi::XK_hebrew_gimmel => VirtualKeyCode::Hebrew_gimmel, - //ffi::XK_hebrew_dalet => VirtualKeyCode::Hebrew_dalet, - //ffi::XK_hebrew_daleth => VirtualKeyCode::Hebrew_daleth, - //ffi::XK_hebrew_he => VirtualKeyCode::Hebrew_he, - //ffi::XK_hebrew_waw => VirtualKeyCode::Hebrew_waw, - //ffi::XK_hebrew_zain => VirtualKeyCode::Hebrew_zain, - //ffi::XK_hebrew_zayin => VirtualKeyCode::Hebrew_zayin, - //ffi::XK_hebrew_chet => VirtualKeyCode::Hebrew_chet, - //ffi::XK_hebrew_het => VirtualKeyCode::Hebrew_het, - //ffi::XK_hebrew_tet => VirtualKeyCode::Hebrew_tet, - //ffi::XK_hebrew_teth => VirtualKeyCode::Hebrew_teth, - //ffi::XK_hebrew_yod => VirtualKeyCode::Hebrew_yod, - //ffi::XK_hebrew_finalkaph => VirtualKeyCode::Hebrew_finalkaph, - //ffi::XK_hebrew_kaph => VirtualKeyCode::Hebrew_kaph, - //ffi::XK_hebrew_lamed => VirtualKeyCode::Hebrew_lamed, - //ffi::XK_hebrew_finalmem => VirtualKeyCode::Hebrew_finalmem, - //ffi::XK_hebrew_mem => VirtualKeyCode::Hebrew_mem, - //ffi::XK_hebrew_finalnun => VirtualKeyCode::Hebrew_finalnun, - //ffi::XK_hebrew_nun => VirtualKeyCode::Hebrew_nun, - //ffi::XK_hebrew_samech => VirtualKeyCode::Hebrew_samech, - //ffi::XK_hebrew_samekh => VirtualKeyCode::Hebrew_samekh, - //ffi::XK_hebrew_ayin => VirtualKeyCode::Hebrew_ayin, - //ffi::XK_hebrew_finalpe => VirtualKeyCode::Hebrew_finalpe, - //ffi::XK_hebrew_pe => VirtualKeyCode::Hebrew_pe, - //ffi::XK_hebrew_finalzade => VirtualKeyCode::Hebrew_finalzade, - //ffi::XK_hebrew_finalzadi => VirtualKeyCode::Hebrew_finalzadi, - //ffi::XK_hebrew_zade => VirtualKeyCode::Hebrew_zade, - //ffi::XK_hebrew_zadi => VirtualKeyCode::Hebrew_zadi, - //ffi::XK_hebrew_qoph => VirtualKeyCode::Hebrew_qoph, - //ffi::XK_hebrew_kuf => VirtualKeyCode::Hebrew_kuf, - //ffi::XK_hebrew_resh => VirtualKeyCode::Hebrew_resh, - //ffi::XK_hebrew_shin => VirtualKeyCode::Hebrew_shin, - //ffi::XK_hebrew_taw => VirtualKeyCode::Hebrew_taw, - //ffi::XK_hebrew_taf => VirtualKeyCode::Hebrew_taf, - //ffi::XK_Hebrew_switch => VirtualKeyCode::Hebrew_switch, - ffi::XF86XK_Back => VirtualKeyCode::NavigateBackward, - ffi::XF86XK_Forward => VirtualKeyCode::NavigateForward, - ffi::XF86XK_Copy => VirtualKeyCode::Copy, - ffi::XF86XK_Paste => VirtualKeyCode::Paste, - ffi::XF86XK_Cut => VirtualKeyCode::Cut, - _ => return None, - }) -} +// pub fn keysym_to_element(keysym: libc::c_uint) -> Option { +// Some(match keysym { +// ffi::XK_BackSpace => VirtualKeyCode::Back, +// ffi::XK_Tab => VirtualKeyCode::Tab, +// //ffi::XK_Linefeed => VirtualKeyCode::Linefeed, +// //ffi::XK_Clear => VirtualKeyCode::Clear, +// ffi::XK_Return => VirtualKeyCode::Return, +// //ffi::XK_Pause => VirtualKeyCode::Pause, +// //ffi::XK_Scroll_Lock => VirtualKeyCode::Scroll_lock, +// //ffi::XK_Sys_Req => VirtualKeyCode::Sys_req, +// ffi::XK_Escape => VirtualKeyCode::Escape, +// ffi::XK_Delete => VirtualKeyCode::Delete, +// ffi::XK_Multi_key => VirtualKeyCode::Compose, +// //ffi::XK_Kanji => VirtualKeyCode::Kanji, +// //ffi::XK_Muhenkan => VirtualKeyCode::Muhenkan, +// //ffi::XK_Henkan_Mode => VirtualKeyCode::Henkan_mode, +// //ffi::XK_Henkan => VirtualKeyCode::Henkan, +// //ffi::XK_Romaji => VirtualKeyCode::Romaji, +// //ffi::XK_Hiragana => VirtualKeyCode::Hiragana, +// //ffi::XK_Katakana => VirtualKeyCode::Katakana, +// //ffi::XK_Hiragana_Katakana => VirtualKeyCode::Hiragana_katakana, +// //ffi::XK_Zenkaku => VirtualKeyCode::Zenkaku, +// //ffi::XK_Hankaku => VirtualKeyCode::Hankaku, +// //ffi::XK_Zenkaku_Hankaku => VirtualKeyCode::Zenkaku_hankaku, +// //ffi::XK_Touroku => VirtualKeyCode::Touroku, +// //ffi::XK_Massyo => VirtualKeyCode::Massyo, +// //ffi::XK_Kana_Lock => VirtualKeyCode::Kana_lock, +// //ffi::XK_Kana_Shift => VirtualKeyCode::Kana_shift, +// //ffi::XK_Eisu_Shift => VirtualKeyCode::Eisu_shift, +// //ffi::XK_Eisu_toggle => VirtualKeyCode::Eisu_toggle, +// ffi::XK_Home => VirtualKeyCode::Home, +// ffi::XK_Left => VirtualKeyCode::Left, +// ffi::XK_Up => VirtualKeyCode::Up, +// ffi::XK_Right => VirtualKeyCode::Right, +// ffi::XK_Down => VirtualKeyCode::Down, +// //ffi::XK_Prior => VirtualKeyCode::Prior, +// ffi::XK_Page_Up => VirtualKeyCode::PageUp, +// //ffi::XK_Next => VirtualKeyCode::Next, +// ffi::XK_Page_Down => VirtualKeyCode::PageDown, +// ffi::XK_End => VirtualKeyCode::End, +// //ffi::XK_Begin => VirtualKeyCode::Begin, +// //ffi::XK_Win_L => VirtualKeyCode::Win_l, +// //ffi::XK_Win_R => VirtualKeyCode::Win_r, +// //ffi::XK_App => VirtualKeyCode::App, +// //ffi::XK_Select => VirtualKeyCode::Select, +// //ffi::XK_Print => VirtualKeyCode::Print, +// //ffi::XK_Execute => VirtualKeyCode::Execute, +// ffi::XK_Insert => VirtualKeyCode::Insert, +// //ffi::XK_Undo => VirtualKeyCode::Undo, +// //ffi::XK_Redo => VirtualKeyCode::Redo, +// //ffi::XK_Menu => VirtualKeyCode::Menu, +// //ffi::XK_Find => VirtualKeyCode::Find, +// //ffi::XK_Cancel => VirtualKeyCode::Cancel, +// //ffi::XK_Help => VirtualKeyCode::Help, +// //ffi::XK_Break => VirtualKeyCode::Break, +// //ffi::XK_Mode_switch => VirtualKeyCode::Mode_switch, +// //ffi::XK_script_switch => VirtualKeyCode::Script_switch, +// //ffi::XK_Num_Lock => VirtualKeyCode::Num_lock, +// //ffi::XK_KP_Space => VirtualKeyCode::Kp_space, +// //ffi::XK_KP_Tab => VirtualKeyCode::Kp_tab, +// //ffi::XK_KP_Enter => VirtualKeyCode::Kp_enter, +// //ffi::XK_KP_F1 => VirtualKeyCode::Kp_f1, +// //ffi::XK_KP_F2 => VirtualKeyCode::Kp_f2, +// //ffi::XK_KP_F3 => VirtualKeyCode::Kp_f3, +// //ffi::XK_KP_F4 => VirtualKeyCode::Kp_f4, +// ffi::XK_KP_Home => VirtualKeyCode::Home, +// ffi::XK_KP_Left => VirtualKeyCode::Left, +// ffi::XK_KP_Up => VirtualKeyCode::Up, +// ffi::XK_KP_Right => VirtualKeyCode::Right, +// ffi::XK_KP_Down => VirtualKeyCode::Down, +// //ffi::XK_KP_Prior => VirtualKeyCode::Kp_prior, +// ffi::XK_KP_Page_Up => VirtualKeyCode::PageUp, +// //ffi::XK_KP_Next => VirtualKeyCode::Kp_next, +// ffi::XK_KP_Page_Down => VirtualKeyCode::PageDown, +// ffi::XK_KP_End => VirtualKeyCode::End, +// //ffi::XK_KP_Begin => VirtualKeyCode::Kp_begin, +// ffi::XK_KP_Insert => VirtualKeyCode::Insert, +// ffi::XK_KP_Delete => VirtualKeyCode::Delete, +// ffi::XK_KP_Equal => VirtualKeyCode::NumpadEquals, +// ffi::XK_KP_Multiply => VirtualKeyCode::NumpadMultiply, +// ffi::XK_KP_Add => VirtualKeyCode::NumpadAdd, +// //ffi::XK_KP_Separator => VirtualKeyCode::Kp_separator, +// ffi::XK_KP_Subtract => VirtualKeyCode::NumpadSubtract, +// ffi::XK_KP_Decimal => VirtualKeyCode::NumpadDecimal, +// ffi::XK_KP_Divide => VirtualKeyCode::NumpadDivide, +// ffi::XK_KP_0 => VirtualKeyCode::Numpad0, +// ffi::XK_KP_1 => VirtualKeyCode::Numpad1, +// ffi::XK_KP_2 => VirtualKeyCode::Numpad2, +// ffi::XK_KP_3 => VirtualKeyCode::Numpad3, +// ffi::XK_KP_4 => VirtualKeyCode::Numpad4, +// ffi::XK_KP_5 => VirtualKeyCode::Numpad5, +// ffi::XK_KP_6 => VirtualKeyCode::Numpad6, +// ffi::XK_KP_7 => VirtualKeyCode::Numpad7, +// ffi::XK_KP_8 => VirtualKeyCode::Numpad8, +// ffi::XK_KP_9 => VirtualKeyCode::Numpad9, +// ffi::XK_F1 => VirtualKeyCode::F1, +// ffi::XK_F2 => VirtualKeyCode::F2, +// ffi::XK_F3 => VirtualKeyCode::F3, +// ffi::XK_F4 => VirtualKeyCode::F4, +// ffi::XK_F5 => VirtualKeyCode::F5, +// ffi::XK_F6 => VirtualKeyCode::F6, +// ffi::XK_F7 => VirtualKeyCode::F7, +// ffi::XK_F8 => VirtualKeyCode::F8, +// ffi::XK_F9 => VirtualKeyCode::F9, +// ffi::XK_F10 => VirtualKeyCode::F10, +// ffi::XK_F11 => VirtualKeyCode::F11, +// //ffi::XK_L1 => VirtualKeyCode::L1, +// ffi::XK_F12 => VirtualKeyCode::F12, +// //ffi::XK_L2 => VirtualKeyCode::L2, +// ffi::XK_F13 => VirtualKeyCode::F13, +// //ffi::XK_L3 => VirtualKeyCode::L3, +// ffi::XK_F14 => VirtualKeyCode::F14, +// //ffi::XK_L4 => VirtualKeyCode::L4, +// ffi::XK_F15 => VirtualKeyCode::F15, +// //ffi::XK_L5 => VirtualKeyCode::L5, +// ffi::XK_F16 => VirtualKeyCode::F16, +// //ffi::XK_L6 => VirtualKeyCode::L6, +// ffi::XK_F17 => VirtualKeyCode::F17, +// //ffi::XK_L7 => VirtualKeyCode::L7, +// ffi::XK_F18 => VirtualKeyCode::F18, +// //ffi::XK_L8 => VirtualKeyCode::L8, +// ffi::XK_F19 => VirtualKeyCode::F19, +// //ffi::XK_L9 => VirtualKeyCode::L9, +// ffi::XK_F20 => VirtualKeyCode::F20, +// //ffi::XK_L10 => VirtualKeyCode::L10, +// ffi::XK_F21 => VirtualKeyCode::F21, +// //ffi::XK_R1 => VirtualKeyCode::R1, +// ffi::XK_F22 => VirtualKeyCode::F22, +// //ffi::XK_R2 => VirtualKeyCode::R2, +// ffi::XK_F23 => VirtualKeyCode::F23, +// //ffi::XK_R3 => VirtualKeyCode::R3, +// ffi::XK_F24 => VirtualKeyCode::F24, +// //ffi::XK_R4 => VirtualKeyCode::R4, +// //ffi::XK_F25 => VirtualKeyCode::F25, +// //ffi::XK_R5 => VirtualKeyCode::R5, +// //ffi::XK_F26 => VirtualKeyCode::F26, +// //ffi::XK_R6 => VirtualKeyCode::R6, +// //ffi::XK_F27 => VirtualKeyCode::F27, +// //ffi::XK_R7 => VirtualKeyCode::R7, +// //ffi::XK_F28 => VirtualKeyCode::F28, +// //ffi::XK_R8 => VirtualKeyCode::R8, +// //ffi::XK_F29 => VirtualKeyCode::F29, +// //ffi::XK_R9 => VirtualKeyCode::R9, +// //ffi::XK_F30 => VirtualKeyCode::F30, +// //ffi::XK_R10 => VirtualKeyCode::R10, +// //ffi::XK_F31 => VirtualKeyCode::F31, +// //ffi::XK_R11 => VirtualKeyCode::R11, +// //ffi::XK_F32 => VirtualKeyCode::F32, +// //ffi::XK_R12 => VirtualKeyCode::R12, +// //ffi::XK_F33 => VirtualKeyCode::F33, +// //ffi::XK_R13 => VirtualKeyCode::R13, +// //ffi::XK_F34 => VirtualKeyCode::F34, +// //ffi::XK_R14 => VirtualKeyCode::R14, +// //ffi::XK_F35 => VirtualKeyCode::F35, +// //ffi::XK_R15 => VirtualKeyCode::R15, +// ffi::XK_Shift_L => VirtualKeyCode::LShift, +// ffi::XK_Shift_R => VirtualKeyCode::RShift, +// ffi::XK_Control_L => VirtualKeyCode::LControl, +// ffi::XK_Control_R => VirtualKeyCode::RControl, +// //ffi::XK_Caps_Lock => VirtualKeyCode::Caps_lock, +// //ffi::XK_Shift_Lock => VirtualKeyCode::Shift_lock, +// //ffi::XK_Meta_L => VirtualKeyCode::Meta_l, +// //ffi::XK_Meta_R => VirtualKeyCode::Meta_r, +// ffi::XK_Alt_L => VirtualKeyCode::LAlt, +// ffi::XK_Alt_R => VirtualKeyCode::RAlt, +// //ffi::XK_Super_L => VirtualKeyCode::Super_l, +// //ffi::XK_Super_R => VirtualKeyCode::Super_r, +// //ffi::XK_Hyper_L => VirtualKeyCode::Hyper_l, +// //ffi::XK_Hyper_R => VirtualKeyCode::Hyper_r, +// ffi::XK_ISO_Left_Tab => VirtualKeyCode::Tab, +// ffi::XK_space => VirtualKeyCode::Space, +// //ffi::XK_exclam => VirtualKeyCode::Exclam, +// //ffi::XK_quotedbl => VirtualKeyCode::Quotedbl, +// //ffi::XK_numbersign => VirtualKeyCode::Numbersign, +// //ffi::XK_dollar => VirtualKeyCode::Dollar, +// //ffi::XK_percent => VirtualKeyCode::Percent, +// //ffi::XK_ampersand => VirtualKeyCode::Ampersand, +// ffi::XK_apostrophe => VirtualKeyCode::Apostrophe, +// //ffi::XK_quoteright => VirtualKeyCode::Quoteright, +// //ffi::XK_parenleft => VirtualKeyCode::Parenleft, +// //ffi::XK_parenright => VirtualKeyCode::Parenright, +// ffi::XK_asterisk => VirtualKeyCode::Asterisk, +// ffi::XK_plus => VirtualKeyCode::Plus, +// ffi::XK_comma => VirtualKeyCode::Comma, +// ffi::XK_minus => VirtualKeyCode::Minus, +// ffi::XK_period => VirtualKeyCode::Period, +// ffi::XK_slash => VirtualKeyCode::Slash, +// ffi::XK_0 => VirtualKeyCode::Key0, +// ffi::XK_1 => VirtualKeyCode::Key1, +// ffi::XK_2 => VirtualKeyCode::Key2, +// ffi::XK_3 => VirtualKeyCode::Key3, +// ffi::XK_4 => VirtualKeyCode::Key4, +// ffi::XK_5 => VirtualKeyCode::Key5, +// ffi::XK_6 => VirtualKeyCode::Key6, +// ffi::XK_7 => VirtualKeyCode::Key7, +// ffi::XK_8 => VirtualKeyCode::Key8, +// ffi::XK_9 => VirtualKeyCode::Key9, +// ffi::XK_colon => VirtualKeyCode::Colon, +// ffi::XK_semicolon => VirtualKeyCode::Semicolon, +// //ffi::XK_less => VirtualKeyCode::Less, +// ffi::XK_equal => VirtualKeyCode::Equals, +// //ffi::XK_greater => VirtualKeyCode::Greater, +// //ffi::XK_question => VirtualKeyCode::Question, +// ffi::XK_at => VirtualKeyCode::At, +// ffi::XK_A => VirtualKeyCode::A, +// ffi::XK_B => VirtualKeyCode::B, +// ffi::XK_C => VirtualKeyCode::C, +// ffi::XK_D => VirtualKeyCode::D, +// ffi::XK_E => VirtualKeyCode::E, +// ffi::XK_F => VirtualKeyCode::F, +// ffi::XK_G => VirtualKeyCode::G, +// ffi::XK_H => VirtualKeyCode::H, +// ffi::XK_I => VirtualKeyCode::I, +// ffi::XK_J => VirtualKeyCode::J, +// ffi::XK_K => VirtualKeyCode::K, +// ffi::XK_L => VirtualKeyCode::L, +// ffi::XK_M => VirtualKeyCode::M, +// ffi::XK_N => VirtualKeyCode::N, +// ffi::XK_O => VirtualKeyCode::O, +// ffi::XK_P => VirtualKeyCode::P, +// ffi::XK_Q => VirtualKeyCode::Q, +// ffi::XK_R => VirtualKeyCode::R, +// ffi::XK_S => VirtualKeyCode::S, +// ffi::XK_T => VirtualKeyCode::T, +// ffi::XK_U => VirtualKeyCode::U, +// ffi::XK_V => VirtualKeyCode::V, +// ffi::XK_W => VirtualKeyCode::W, +// ffi::XK_X => VirtualKeyCode::X, +// ffi::XK_Y => VirtualKeyCode::Y, +// ffi::XK_Z => VirtualKeyCode::Z, +// ffi::XK_bracketleft => VirtualKeyCode::LBracket, +// ffi::XK_backslash => VirtualKeyCode::Backslash, +// ffi::XK_bracketright => VirtualKeyCode::RBracket, +// //ffi::XK_asciicircum => VirtualKeyCode::Asciicircum, +// //ffi::XK_underscore => VirtualKeyCode::Underscore, +// ffi::XK_grave => VirtualKeyCode::Grave, +// //ffi::XK_quoteleft => VirtualKeyCode::Quoteleft, +// ffi::XK_a => VirtualKeyCode::A, +// ffi::XK_b => VirtualKeyCode::B, +// ffi::XK_c => VirtualKeyCode::C, +// ffi::XK_d => VirtualKeyCode::D, +// ffi::XK_e => VirtualKeyCode::E, +// ffi::XK_f => VirtualKeyCode::F, +// ffi::XK_g => VirtualKeyCode::G, +// ffi::XK_h => VirtualKeyCode::H, +// ffi::XK_i => VirtualKeyCode::I, +// ffi::XK_j => VirtualKeyCode::J, +// ffi::XK_k => VirtualKeyCode::K, +// ffi::XK_l => VirtualKeyCode::L, +// ffi::XK_m => VirtualKeyCode::M, +// ffi::XK_n => VirtualKeyCode::N, +// ffi::XK_o => VirtualKeyCode::O, +// ffi::XK_p => VirtualKeyCode::P, +// ffi::XK_q => VirtualKeyCode::Q, +// ffi::XK_r => VirtualKeyCode::R, +// ffi::XK_s => VirtualKeyCode::S, +// ffi::XK_t => VirtualKeyCode::T, +// ffi::XK_u => VirtualKeyCode::U, +// ffi::XK_v => VirtualKeyCode::V, +// ffi::XK_w => VirtualKeyCode::W, +// ffi::XK_x => VirtualKeyCode::X, +// ffi::XK_y => VirtualKeyCode::Y, +// ffi::XK_z => VirtualKeyCode::Z, +// //ffi::XK_braceleft => VirtualKeyCode::Braceleft, +// //ffi::XK_bar => VirtualKeyCode::Bar, +// //ffi::XK_braceright => VirtualKeyCode::Braceright, +// //ffi::XK_asciitilde => VirtualKeyCode::Asciitilde, +// //ffi::XK_nobreakspace => VirtualKeyCode::Nobreakspace, +// //ffi::XK_exclamdown => VirtualKeyCode::Exclamdown, +// //ffi::XK_cent => VirtualKeyCode::Cent, +// //ffi::XK_sterling => VirtualKeyCode::Sterling, +// //ffi::XK_currency => VirtualKeyCode::Currency, +// //ffi::XK_yen => VirtualKeyCode::Yen, +// //ffi::XK_brokenbar => VirtualKeyCode::Brokenbar, +// //ffi::XK_section => VirtualKeyCode::Section, +// //ffi::XK_diaeresis => VirtualKeyCode::Diaeresis, +// //ffi::XK_copyright => VirtualKeyCode::Copyright, +// //ffi::XK_ordfeminine => VirtualKeyCode::Ordfeminine, +// //ffi::XK_guillemotleft => VirtualKeyCode::Guillemotleft, +// //ffi::XK_notsign => VirtualKeyCode::Notsign, +// //ffi::XK_hyphen => VirtualKeyCode::Hyphen, +// //ffi::XK_registered => VirtualKeyCode::Registered, +// //ffi::XK_macron => VirtualKeyCode::Macron, +// //ffi::XK_degree => VirtualKeyCode::Degree, +// //ffi::XK_plusminus => VirtualKeyCode::Plusminus, +// //ffi::XK_twosuperior => VirtualKeyCode::Twosuperior, +// //ffi::XK_threesuperior => VirtualKeyCode::Threesuperior, +// //ffi::XK_acute => VirtualKeyCode::Acute, +// //ffi::XK_mu => VirtualKeyCode::Mu, +// //ffi::XK_paragraph => VirtualKeyCode::Paragraph, +// //ffi::XK_periodcentered => VirtualKeyCode::Periodcentered, +// //ffi::XK_cedilla => VirtualKeyCode::Cedilla, +// //ffi::XK_onesuperior => VirtualKeyCode::Onesuperior, +// //ffi::XK_masculine => VirtualKeyCode::Masculine, +// //ffi::XK_guillemotright => VirtualKeyCode::Guillemotright, +// //ffi::XK_onequarter => VirtualKeyCode::Onequarter, +// //ffi::XK_onehalf => VirtualKeyCode::Onehalf, +// //ffi::XK_threequarters => VirtualKeyCode::Threequarters, +// //ffi::XK_questiondown => VirtualKeyCode::Questiondown, +// //ffi::XK_Agrave => VirtualKeyCode::Agrave, +// //ffi::XK_Aacute => VirtualKeyCode::Aacute, +// //ffi::XK_Acircumflex => VirtualKeyCode::Acircumflex, +// //ffi::XK_Atilde => VirtualKeyCode::Atilde, +// //ffi::XK_Adiaeresis => VirtualKeyCode::Adiaeresis, +// //ffi::XK_Aring => VirtualKeyCode::Aring, +// //ffi::XK_AE => VirtualKeyCode::Ae, +// //ffi::XK_Ccedilla => VirtualKeyCode::Ccedilla, +// //ffi::XK_Egrave => VirtualKeyCode::Egrave, +// //ffi::XK_Eacute => VirtualKeyCode::Eacute, +// //ffi::XK_Ecircumflex => VirtualKeyCode::Ecircumflex, +// //ffi::XK_Ediaeresis => VirtualKeyCode::Ediaeresis, +// //ffi::XK_Igrave => VirtualKeyCode::Igrave, +// //ffi::XK_Iacute => VirtualKeyCode::Iacute, +// //ffi::XK_Icircumflex => VirtualKeyCode::Icircumflex, +// //ffi::XK_Idiaeresis => VirtualKeyCode::Idiaeresis, +// //ffi::XK_ETH => VirtualKeyCode::Eth, +// //ffi::XK_Eth => VirtualKeyCode::Eth, +// //ffi::XK_Ntilde => VirtualKeyCode::Ntilde, +// //ffi::XK_Ograve => VirtualKeyCode::Ograve, +// //ffi::XK_Oacute => VirtualKeyCode::Oacute, +// //ffi::XK_Ocircumflex => VirtualKeyCode::Ocircumflex, +// //ffi::XK_Otilde => VirtualKeyCode::Otilde, +// //ffi::XK_Odiaeresis => VirtualKeyCode::Odiaeresis, +// //ffi::XK_multiply => VirtualKeyCode::Multiply, +// //ffi::XK_Ooblique => VirtualKeyCode::Ooblique, +// //ffi::XK_Ugrave => VirtualKeyCode::Ugrave, +// //ffi::XK_Uacute => VirtualKeyCode::Uacute, +// //ffi::XK_Ucircumflex => VirtualKeyCode::Ucircumflex, +// //ffi::XK_Udiaeresis => VirtualKeyCode::Udiaeresis, +// //ffi::XK_Yacute => VirtualKeyCode::Yacute, +// //ffi::XK_THORN => VirtualKeyCode::Thorn, +// //ffi::XK_Thorn => VirtualKeyCode::Thorn, +// //ffi::XK_ssharp => VirtualKeyCode::Ssharp, +// //ffi::XK_agrave => VirtualKeyCode::Agrave, +// //ffi::XK_aacute => VirtualKeyCode::Aacute, +// //ffi::XK_acircumflex => VirtualKeyCode::Acircumflex, +// //ffi::XK_atilde => VirtualKeyCode::Atilde, +// //ffi::XK_adiaeresis => VirtualKeyCode::Adiaeresis, +// //ffi::XK_aring => VirtualKeyCode::Aring, +// //ffi::XK_ae => VirtualKeyCode::Ae, +// //ffi::XK_ccedilla => VirtualKeyCode::Ccedilla, +// //ffi::XK_egrave => VirtualKeyCode::Egrave, +// //ffi::XK_eacute => VirtualKeyCode::Eacute, +// //ffi::XK_ecircumflex => VirtualKeyCode::Ecircumflex, +// //ffi::XK_ediaeresis => VirtualKeyCode::Ediaeresis, +// //ffi::XK_igrave => VirtualKeyCode::Igrave, +// //ffi::XK_iacute => VirtualKeyCode::Iacute, +// //ffi::XK_icircumflex => VirtualKeyCode::Icircumflex, +// //ffi::XK_idiaeresis => VirtualKeyCode::Idiaeresis, +// //ffi::XK_eth => VirtualKeyCode::Eth, +// //ffi::XK_ntilde => VirtualKeyCode::Ntilde, +// //ffi::XK_ograve => VirtualKeyCode::Ograve, +// //ffi::XK_oacute => VirtualKeyCode::Oacute, +// //ffi::XK_ocircumflex => VirtualKeyCode::Ocircumflex, +// //ffi::XK_otilde => VirtualKeyCode::Otilde, +// //ffi::XK_odiaeresis => VirtualKeyCode::Odiaeresis, +// //ffi::XK_division => VirtualKeyCode::Division, +// //ffi::XK_oslash => VirtualKeyCode::Oslash, +// //ffi::XK_ugrave => VirtualKeyCode::Ugrave, +// //ffi::XK_uacute => VirtualKeyCode::Uacute, +// //ffi::XK_ucircumflex => VirtualKeyCode::Ucircumflex, +// //ffi::XK_udiaeresis => VirtualKeyCode::Udiaeresis, +// //ffi::XK_yacute => VirtualKeyCode::Yacute, +// //ffi::XK_thorn => VirtualKeyCode::Thorn, +// //ffi::XK_ydiaeresis => VirtualKeyCode::Ydiaeresis, +// //ffi::XK_Aogonek => VirtualKeyCode::Aogonek, +// //ffi::XK_breve => VirtualKeyCode::Breve, +// //ffi::XK_Lstroke => VirtualKeyCode::Lstroke, +// //ffi::XK_Lcaron => VirtualKeyCode::Lcaron, +// //ffi::XK_Sacute => VirtualKeyCode::Sacute, +// //ffi::XK_Scaron => VirtualKeyCode::Scaron, +// //ffi::XK_Scedilla => VirtualKeyCode::Scedilla, +// //ffi::XK_Tcaron => VirtualKeyCode::Tcaron, +// //ffi::XK_Zacute => VirtualKeyCode::Zacute, +// //ffi::XK_Zcaron => VirtualKeyCode::Zcaron, +// //ffi::XK_Zabovedot => VirtualKeyCode::Zabovedot, +// //ffi::XK_aogonek => VirtualKeyCode::Aogonek, +// //ffi::XK_ogonek => VirtualKeyCode::Ogonek, +// //ffi::XK_lstroke => VirtualKeyCode::Lstroke, +// //ffi::XK_lcaron => VirtualKeyCode::Lcaron, +// //ffi::XK_sacute => VirtualKeyCode::Sacute, +// //ffi::XK_caron => VirtualKeyCode::Caron, +// //ffi::XK_scaron => VirtualKeyCode::Scaron, +// //ffi::XK_scedilla => VirtualKeyCode::Scedilla, +// //ffi::XK_tcaron => VirtualKeyCode::Tcaron, +// //ffi::XK_zacute => VirtualKeyCode::Zacute, +// //ffi::XK_doubleacute => VirtualKeyCode::Doubleacute, +// //ffi::XK_zcaron => VirtualKeyCode::Zcaron, +// //ffi::XK_zabovedot => VirtualKeyCode::Zabovedot, +// //ffi::XK_Racute => VirtualKeyCode::Racute, +// //ffi::XK_Abreve => VirtualKeyCode::Abreve, +// //ffi::XK_Lacute => VirtualKeyCode::Lacute, +// //ffi::XK_Cacute => VirtualKeyCode::Cacute, +// //ffi::XK_Ccaron => VirtualKeyCode::Ccaron, +// //ffi::XK_Eogonek => VirtualKeyCode::Eogonek, +// //ffi::XK_Ecaron => VirtualKeyCode::Ecaron, +// //ffi::XK_Dcaron => VirtualKeyCode::Dcaron, +// //ffi::XK_Dstroke => VirtualKeyCode::Dstroke, +// //ffi::XK_Nacute => VirtualKeyCode::Nacute, +// //ffi::XK_Ncaron => VirtualKeyCode::Ncaron, +// //ffi::XK_Odoubleacute => VirtualKeyCode::Odoubleacute, +// //ffi::XK_Rcaron => VirtualKeyCode::Rcaron, +// //ffi::XK_Uring => VirtualKeyCode::Uring, +// //ffi::XK_Udoubleacute => VirtualKeyCode::Udoubleacute, +// //ffi::XK_Tcedilla => VirtualKeyCode::Tcedilla, +// //ffi::XK_racute => VirtualKeyCode::Racute, +// //ffi::XK_abreve => VirtualKeyCode::Abreve, +// //ffi::XK_lacute => VirtualKeyCode::Lacute, +// //ffi::XK_cacute => VirtualKeyCode::Cacute, +// //ffi::XK_ccaron => VirtualKeyCode::Ccaron, +// //ffi::XK_eogonek => VirtualKeyCode::Eogonek, +// //ffi::XK_ecaron => VirtualKeyCode::Ecaron, +// //ffi::XK_dcaron => VirtualKeyCode::Dcaron, +// //ffi::XK_dstroke => VirtualKeyCode::Dstroke, +// //ffi::XK_nacute => VirtualKeyCode::Nacute, +// //ffi::XK_ncaron => VirtualKeyCode::Ncaron, +// //ffi::XK_odoubleacute => VirtualKeyCode::Odoubleacute, +// //ffi::XK_udoubleacute => VirtualKeyCode::Udoubleacute, +// //ffi::XK_rcaron => VirtualKeyCode::Rcaron, +// //ffi::XK_uring => VirtualKeyCode::Uring, +// //ffi::XK_tcedilla => VirtualKeyCode::Tcedilla, +// //ffi::XK_abovedot => VirtualKeyCode::Abovedot, +// //ffi::XK_Hstroke => VirtualKeyCode::Hstroke, +// //ffi::XK_Hcircumflex => VirtualKeyCode::Hcircumflex, +// //ffi::XK_Iabovedot => VirtualKeyCode::Iabovedot, +// //ffi::XK_Gbreve => VirtualKeyCode::Gbreve, +// //ffi::XK_Jcircumflex => VirtualKeyCode::Jcircumflex, +// //ffi::XK_hstroke => VirtualKeyCode::Hstroke, +// //ffi::XK_hcircumflex => VirtualKeyCode::Hcircumflex, +// //ffi::XK_idotless => VirtualKeyCode::Idotless, +// //ffi::XK_gbreve => VirtualKeyCode::Gbreve, +// //ffi::XK_jcircumflex => VirtualKeyCode::Jcircumflex, +// //ffi::XK_Cabovedot => VirtualKeyCode::Cabovedot, +// //ffi::XK_Ccircumflex => VirtualKeyCode::Ccircumflex, +// //ffi::XK_Gabovedot => VirtualKeyCode::Gabovedot, +// //ffi::XK_Gcircumflex => VirtualKeyCode::Gcircumflex, +// //ffi::XK_Ubreve => VirtualKeyCode::Ubreve, +// //ffi::XK_Scircumflex => VirtualKeyCode::Scircumflex, +// //ffi::XK_cabovedot => VirtualKeyCode::Cabovedot, +// //ffi::XK_ccircumflex => VirtualKeyCode::Ccircumflex, +// //ffi::XK_gabovedot => VirtualKeyCode::Gabovedot, +// //ffi::XK_gcircumflex => VirtualKeyCode::Gcircumflex, +// //ffi::XK_ubreve => VirtualKeyCode::Ubreve, +// //ffi::XK_scircumflex => VirtualKeyCode::Scircumflex, +// //ffi::XK_kra => VirtualKeyCode::Kra, +// //ffi::XK_kappa => VirtualKeyCode::Kappa, +// //ffi::XK_Rcedilla => VirtualKeyCode::Rcedilla, +// //ffi::XK_Itilde => VirtualKeyCode::Itilde, +// //ffi::XK_Lcedilla => VirtualKeyCode::Lcedilla, +// //ffi::XK_Emacron => VirtualKeyCode::Emacron, +// //ffi::XK_Gcedilla => VirtualKeyCode::Gcedilla, +// //ffi::XK_Tslash => VirtualKeyCode::Tslash, +// //ffi::XK_rcedilla => VirtualKeyCode::Rcedilla, +// //ffi::XK_itilde => VirtualKeyCode::Itilde, +// //ffi::XK_lcedilla => VirtualKeyCode::Lcedilla, +// //ffi::XK_emacron => VirtualKeyCode::Emacron, +// //ffi::XK_gcedilla => VirtualKeyCode::Gcedilla, +// //ffi::XK_tslash => VirtualKeyCode::Tslash, +// //ffi::XK_ENG => VirtualKeyCode::Eng, +// //ffi::XK_eng => VirtualKeyCode::Eng, +// //ffi::XK_Amacron => VirtualKeyCode::Amacron, +// //ffi::XK_Iogonek => VirtualKeyCode::Iogonek, +// //ffi::XK_Eabovedot => VirtualKeyCode::Eabovedot, +// //ffi::XK_Imacron => VirtualKeyCode::Imacron, +// //ffi::XK_Ncedilla => VirtualKeyCode::Ncedilla, +// //ffi::XK_Omacron => VirtualKeyCode::Omacron, +// //ffi::XK_Kcedilla => VirtualKeyCode::Kcedilla, +// //ffi::XK_Uogonek => VirtualKeyCode::Uogonek, +// //ffi::XK_Utilde => VirtualKeyCode::Utilde, +// //ffi::XK_Umacron => VirtualKeyCode::Umacron, +// //ffi::XK_amacron => VirtualKeyCode::Amacron, +// //ffi::XK_iogonek => VirtualKeyCode::Iogonek, +// //ffi::XK_eabovedot => VirtualKeyCode::Eabovedot, +// //ffi::XK_imacron => VirtualKeyCode::Imacron, +// //ffi::XK_ncedilla => VirtualKeyCode::Ncedilla, +// //ffi::XK_omacron => VirtualKeyCode::Omacron, +// //ffi::XK_kcedilla => VirtualKeyCode::Kcedilla, +// //ffi::XK_uogonek => VirtualKeyCode::Uogonek, +// //ffi::XK_utilde => VirtualKeyCode::Utilde, +// //ffi::XK_umacron => VirtualKeyCode::Umacron, +// //ffi::XK_overline => VirtualKeyCode::Overline, +// //ffi::XK_kana_fullstop => VirtualKeyCode::Kana_fullstop, +// //ffi::XK_kana_openingbracket => VirtualKeyCode::Kana_openingbracket, +// //ffi::XK_kana_closingbracket => VirtualKeyCode::Kana_closingbracket, +// //ffi::XK_kana_comma => VirtualKeyCode::Kana_comma, +// //ffi::XK_kana_conjunctive => VirtualKeyCode::Kana_conjunctive, +// //ffi::XK_kana_middledot => VirtualKeyCode::Kana_middledot, +// //ffi::XK_kana_WO => VirtualKeyCode::Kana_wo, +// //ffi::XK_kana_a => VirtualKeyCode::Kana_a, +// //ffi::XK_kana_i => VirtualKeyCode::Kana_i, +// //ffi::XK_kana_u => VirtualKeyCode::Kana_u, +// //ffi::XK_kana_e => VirtualKeyCode::Kana_e, +// //ffi::XK_kana_o => VirtualKeyCode::Kana_o, +// //ffi::XK_kana_ya => VirtualKeyCode::Kana_ya, +// //ffi::XK_kana_yu => VirtualKeyCode::Kana_yu, +// //ffi::XK_kana_yo => VirtualKeyCode::Kana_yo, +// //ffi::XK_kana_tsu => VirtualKeyCode::Kana_tsu, +// //ffi::XK_kana_tu => VirtualKeyCode::Kana_tu, +// //ffi::XK_prolongedsound => VirtualKeyCode::Prolongedsound, +// //ffi::XK_kana_A => VirtualKeyCode::Kana_a, +// //ffi::XK_kana_I => VirtualKeyCode::Kana_i, +// //ffi::XK_kana_U => VirtualKeyCode::Kana_u, +// //ffi::XK_kana_E => VirtualKeyCode::Kana_e, +// //ffi::XK_kana_O => VirtualKeyCode::Kana_o, +// //ffi::XK_kana_KA => VirtualKeyCode::Kana_ka, +// //ffi::XK_kana_KI => VirtualKeyCode::Kana_ki, +// //ffi::XK_kana_KU => VirtualKeyCode::Kana_ku, +// //ffi::XK_kana_KE => VirtualKeyCode::Kana_ke, +// //ffi::XK_kana_KO => VirtualKeyCode::Kana_ko, +// //ffi::XK_kana_SA => VirtualKeyCode::Kana_sa, +// //ffi::XK_kana_SHI => VirtualKeyCode::Kana_shi, +// //ffi::XK_kana_SU => VirtualKeyCode::Kana_su, +// //ffi::XK_kana_SE => VirtualKeyCode::Kana_se, +// //ffi::XK_kana_SO => VirtualKeyCode::Kana_so, +// //ffi::XK_kana_TA => VirtualKeyCode::Kana_ta, +// //ffi::XK_kana_CHI => VirtualKeyCode::Kana_chi, +// //ffi::XK_kana_TI => VirtualKeyCode::Kana_ti, +// //ffi::XK_kana_TSU => VirtualKeyCode::Kana_tsu, +// //ffi::XK_kana_TU => VirtualKeyCode::Kana_tu, +// //ffi::XK_kana_TE => VirtualKeyCode::Kana_te, +// //ffi::XK_kana_TO => VirtualKeyCode::Kana_to, +// //ffi::XK_kana_NA => VirtualKeyCode::Kana_na, +// //ffi::XK_kana_NI => VirtualKeyCode::Kana_ni, +// //ffi::XK_kana_NU => VirtualKeyCode::Kana_nu, +// //ffi::XK_kana_NE => VirtualKeyCode::Kana_ne, +// //ffi::XK_kana_NO => VirtualKeyCode::Kana_no, +// //ffi::XK_kana_HA => VirtualKeyCode::Kana_ha, +// //ffi::XK_kana_HI => VirtualKeyCode::Kana_hi, +// //ffi::XK_kana_FU => VirtualKeyCode::Kana_fu, +// //ffi::XK_kana_HU => VirtualKeyCode::Kana_hu, +// //ffi::XK_kana_HE => VirtualKeyCode::Kana_he, +// //ffi::XK_kana_HO => VirtualKeyCode::Kana_ho, +// //ffi::XK_kana_MA => VirtualKeyCode::Kana_ma, +// //ffi::XK_kana_MI => VirtualKeyCode::Kana_mi, +// //ffi::XK_kana_MU => VirtualKeyCode::Kana_mu, +// //ffi::XK_kana_ME => VirtualKeyCode::Kana_me, +// //ffi::XK_kana_MO => VirtualKeyCode::Kana_mo, +// //ffi::XK_kana_YA => VirtualKeyCode::Kana_ya, +// //ffi::XK_kana_YU => VirtualKeyCode::Kana_yu, +// //ffi::XK_kana_YO => VirtualKeyCode::Kana_yo, +// //ffi::XK_kana_RA => VirtualKeyCode::Kana_ra, +// //ffi::XK_kana_RI => VirtualKeyCode::Kana_ri, +// //ffi::XK_kana_RU => VirtualKeyCode::Kana_ru, +// //ffi::XK_kana_RE => VirtualKeyCode::Kana_re, +// //ffi::XK_kana_RO => VirtualKeyCode::Kana_ro, +// //ffi::XK_kana_WA => VirtualKeyCode::Kana_wa, +// //ffi::XK_kana_N => VirtualKeyCode::Kana_n, +// //ffi::XK_voicedsound => VirtualKeyCode::Voicedsound, +// //ffi::XK_semivoicedsound => VirtualKeyCode::Semivoicedsound, +// //ffi::XK_kana_switch => VirtualKeyCode::Kana_switch, +// //ffi::XK_Arabic_comma => VirtualKeyCode::Arabic_comma, +// //ffi::XK_Arabic_semicolon => VirtualKeyCode::Arabic_semicolon, +// //ffi::XK_Arabic_question_mark => VirtualKeyCode::Arabic_question_mark, +// //ffi::XK_Arabic_hamza => VirtualKeyCode::Arabic_hamza, +// //ffi::XK_Arabic_maddaonalef => VirtualKeyCode::Arabic_maddaonalef, +// //ffi::XK_Arabic_hamzaonalef => VirtualKeyCode::Arabic_hamzaonalef, +// //ffi::XK_Arabic_hamzaonwaw => VirtualKeyCode::Arabic_hamzaonwaw, +// //ffi::XK_Arabic_hamzaunderalef => VirtualKeyCode::Arabic_hamzaunderalef, +// //ffi::XK_Arabic_hamzaonyeh => VirtualKeyCode::Arabic_hamzaonyeh, +// //ffi::XK_Arabic_alef => VirtualKeyCode::Arabic_alef, +// //ffi::XK_Arabic_beh => VirtualKeyCode::Arabic_beh, +// //ffi::XK_Arabic_tehmarbuta => VirtualKeyCode::Arabic_tehmarbuta, +// //ffi::XK_Arabic_teh => VirtualKeyCode::Arabic_teh, +// //ffi::XK_Arabic_theh => VirtualKeyCode::Arabic_theh, +// //ffi::XK_Arabic_jeem => VirtualKeyCode::Arabic_jeem, +// //ffi::XK_Arabic_hah => VirtualKeyCode::Arabic_hah, +// //ffi::XK_Arabic_khah => VirtualKeyCode::Arabic_khah, +// //ffi::XK_Arabic_dal => VirtualKeyCode::Arabic_dal, +// //ffi::XK_Arabic_thal => VirtualKeyCode::Arabic_thal, +// //ffi::XK_Arabic_ra => VirtualKeyCode::Arabic_ra, +// //ffi::XK_Arabic_zain => VirtualKeyCode::Arabic_zain, +// //ffi::XK_Arabic_seen => VirtualKeyCode::Arabic_seen, +// //ffi::XK_Arabic_sheen => VirtualKeyCode::Arabic_sheen, +// //ffi::XK_Arabic_sad => VirtualKeyCode::Arabic_sad, +// //ffi::XK_Arabic_dad => VirtualKeyCode::Arabic_dad, +// //ffi::XK_Arabic_tah => VirtualKeyCode::Arabic_tah, +// //ffi::XK_Arabic_zah => VirtualKeyCode::Arabic_zah, +// //ffi::XK_Arabic_ain => VirtualKeyCode::Arabic_ain, +// //ffi::XK_Arabic_ghain => VirtualKeyCode::Arabic_ghain, +// //ffi::XK_Arabic_tatweel => VirtualKeyCode::Arabic_tatweel, +// //ffi::XK_Arabic_feh => VirtualKeyCode::Arabic_feh, +// //ffi::XK_Arabic_qaf => VirtualKeyCode::Arabic_qaf, +// //ffi::XK_Arabic_kaf => VirtualKeyCode::Arabic_kaf, +// //ffi::XK_Arabic_lam => VirtualKeyCode::Arabic_lam, +// //ffi::XK_Arabic_meem => VirtualKeyCode::Arabic_meem, +// //ffi::XK_Arabic_noon => VirtualKeyCode::Arabic_noon, +// //ffi::XK_Arabic_ha => VirtualKeyCode::Arabic_ha, +// //ffi::XK_Arabic_heh => VirtualKeyCode::Arabic_heh, +// //ffi::XK_Arabic_waw => VirtualKeyCode::Arabic_waw, +// //ffi::XK_Arabic_alefmaksura => VirtualKeyCode::Arabic_alefmaksura, +// //ffi::XK_Arabic_yeh => VirtualKeyCode::Arabic_yeh, +// //ffi::XK_Arabic_fathatan => VirtualKeyCode::Arabic_fathatan, +// //ffi::XK_Arabic_dammatan => VirtualKeyCode::Arabic_dammatan, +// //ffi::XK_Arabic_kasratan => VirtualKeyCode::Arabic_kasratan, +// //ffi::XK_Arabic_fatha => VirtualKeyCode::Arabic_fatha, +// //ffi::XK_Arabic_damma => VirtualKeyCode::Arabic_damma, +// //ffi::XK_Arabic_kasra => VirtualKeyCode::Arabic_kasra, +// //ffi::XK_Arabic_shadda => VirtualKeyCode::Arabic_shadda, +// //ffi::XK_Arabic_sukun => VirtualKeyCode::Arabic_sukun, +// //ffi::XK_Arabic_switch => VirtualKeyCode::Arabic_switch, +// //ffi::XK_Serbian_dje => VirtualKeyCode::Serbian_dje, +// //ffi::XK_Macedonia_gje => VirtualKeyCode::Macedonia_gje, +// //ffi::XK_Cyrillic_io => VirtualKeyCode::Cyrillic_io, +// //ffi::XK_Ukrainian_ie => VirtualKeyCode::Ukrainian_ie, +// //ffi::XK_Ukranian_je => VirtualKeyCode::Ukranian_je, +// //ffi::XK_Macedonia_dse => VirtualKeyCode::Macedonia_dse, +// //ffi::XK_Ukrainian_i => VirtualKeyCode::Ukrainian_i, +// //ffi::XK_Ukranian_i => VirtualKeyCode::Ukranian_i, +// //ffi::XK_Ukrainian_yi => VirtualKeyCode::Ukrainian_yi, +// //ffi::XK_Ukranian_yi => VirtualKeyCode::Ukranian_yi, +// //ffi::XK_Cyrillic_je => VirtualKeyCode::Cyrillic_je, +// //ffi::XK_Serbian_je => VirtualKeyCode::Serbian_je, +// //ffi::XK_Cyrillic_lje => VirtualKeyCode::Cyrillic_lje, +// //ffi::XK_Serbian_lje => VirtualKeyCode::Serbian_lje, +// //ffi::XK_Cyrillic_nje => VirtualKeyCode::Cyrillic_nje, +// //ffi::XK_Serbian_nje => VirtualKeyCode::Serbian_nje, +// //ffi::XK_Serbian_tshe => VirtualKeyCode::Serbian_tshe, +// //ffi::XK_Macedonia_kje => VirtualKeyCode::Macedonia_kje, +// //ffi::XK_Byelorussian_shortu => VirtualKeyCode::Byelorussian_shortu, +// //ffi::XK_Cyrillic_dzhe => VirtualKeyCode::Cyrillic_dzhe, +// //ffi::XK_Serbian_dze => VirtualKeyCode::Serbian_dze, +// //ffi::XK_numerosign => VirtualKeyCode::Numerosign, +// //ffi::XK_Serbian_DJE => VirtualKeyCode::Serbian_dje, +// //ffi::XK_Macedonia_GJE => VirtualKeyCode::Macedonia_gje, +// //ffi::XK_Cyrillic_IO => VirtualKeyCode::Cyrillic_io, +// //ffi::XK_Ukrainian_IE => VirtualKeyCode::Ukrainian_ie, +// //ffi::XK_Ukranian_JE => VirtualKeyCode::Ukranian_je, +// //ffi::XK_Macedonia_DSE => VirtualKeyCode::Macedonia_dse, +// //ffi::XK_Ukrainian_I => VirtualKeyCode::Ukrainian_i, +// //ffi::XK_Ukranian_I => VirtualKeyCode::Ukranian_i, +// //ffi::XK_Ukrainian_YI => VirtualKeyCode::Ukrainian_yi, +// //ffi::XK_Ukranian_YI => VirtualKeyCode::Ukranian_yi, +// //ffi::XK_Cyrillic_JE => VirtualKeyCode::Cyrillic_je, +// //ffi::XK_Serbian_JE => VirtualKeyCode::Serbian_je, +// //ffi::XK_Cyrillic_LJE => VirtualKeyCode::Cyrillic_lje, +// //ffi::XK_Serbian_LJE => VirtualKeyCode::Serbian_lje, +// //ffi::XK_Cyrillic_NJE => VirtualKeyCode::Cyrillic_nje, +// //ffi::XK_Serbian_NJE => VirtualKeyCode::Serbian_nje, +// //ffi::XK_Serbian_TSHE => VirtualKeyCode::Serbian_tshe, +// //ffi::XK_Macedonia_KJE => VirtualKeyCode::Macedonia_kje, +// //ffi::XK_Byelorussian_SHORTU => VirtualKeyCode::Byelorussian_shortu, +// //ffi::XK_Cyrillic_DZHE => VirtualKeyCode::Cyrillic_dzhe, +// //ffi::XK_Serbian_DZE => VirtualKeyCode::Serbian_dze, +// //ffi::XK_Cyrillic_yu => VirtualKeyCode::Cyrillic_yu, +// //ffi::XK_Cyrillic_a => VirtualKeyCode::Cyrillic_a, +// //ffi::XK_Cyrillic_be => VirtualKeyCode::Cyrillic_be, +// //ffi::XK_Cyrillic_tse => VirtualKeyCode::Cyrillic_tse, +// //ffi::XK_Cyrillic_de => VirtualKeyCode::Cyrillic_de, +// //ffi::XK_Cyrillic_ie => VirtualKeyCode::Cyrillic_ie, +// //ffi::XK_Cyrillic_ef => VirtualKeyCode::Cyrillic_ef, +// //ffi::XK_Cyrillic_ghe => VirtualKeyCode::Cyrillic_ghe, +// //ffi::XK_Cyrillic_ha => VirtualKeyCode::Cyrillic_ha, +// //ffi::XK_Cyrillic_i => VirtualKeyCode::Cyrillic_i, +// //ffi::XK_Cyrillic_shorti => VirtualKeyCode::Cyrillic_shorti, +// //ffi::XK_Cyrillic_ka => VirtualKeyCode::Cyrillic_ka, +// //ffi::XK_Cyrillic_el => VirtualKeyCode::Cyrillic_el, +// //ffi::XK_Cyrillic_em => VirtualKeyCode::Cyrillic_em, +// //ffi::XK_Cyrillic_en => VirtualKeyCode::Cyrillic_en, +// //ffi::XK_Cyrillic_o => VirtualKeyCode::Cyrillic_o, +// //ffi::XK_Cyrillic_pe => VirtualKeyCode::Cyrillic_pe, +// //ffi::XK_Cyrillic_ya => VirtualKeyCode::Cyrillic_ya, +// //ffi::XK_Cyrillic_er => VirtualKeyCode::Cyrillic_er, +// //ffi::XK_Cyrillic_es => VirtualKeyCode::Cyrillic_es, +// //ffi::XK_Cyrillic_te => VirtualKeyCode::Cyrillic_te, +// //ffi::XK_Cyrillic_u => VirtualKeyCode::Cyrillic_u, +// //ffi::XK_Cyrillic_zhe => VirtualKeyCode::Cyrillic_zhe, +// //ffi::XK_Cyrillic_ve => VirtualKeyCode::Cyrillic_ve, +// //ffi::XK_Cyrillic_softsign => VirtualKeyCode::Cyrillic_softsign, +// //ffi::XK_Cyrillic_yeru => VirtualKeyCode::Cyrillic_yeru, +// //ffi::XK_Cyrillic_ze => VirtualKeyCode::Cyrillic_ze, +// //ffi::XK_Cyrillic_sha => VirtualKeyCode::Cyrillic_sha, +// //ffi::XK_Cyrillic_e => VirtualKeyCode::Cyrillic_e, +// //ffi::XK_Cyrillic_shcha => VirtualKeyCode::Cyrillic_shcha, +// //ffi::XK_Cyrillic_che => VirtualKeyCode::Cyrillic_che, +// //ffi::XK_Cyrillic_hardsign => VirtualKeyCode::Cyrillic_hardsign, +// //ffi::XK_Cyrillic_YU => VirtualKeyCode::Cyrillic_yu, +// //ffi::XK_Cyrillic_A => VirtualKeyCode::Cyrillic_a, +// //ffi::XK_Cyrillic_BE => VirtualKeyCode::Cyrillic_be, +// //ffi::XK_Cyrillic_TSE => VirtualKeyCode::Cyrillic_tse, +// //ffi::XK_Cyrillic_DE => VirtualKeyCode::Cyrillic_de, +// //ffi::XK_Cyrillic_IE => VirtualKeyCode::Cyrillic_ie, +// //ffi::XK_Cyrillic_EF => VirtualKeyCode::Cyrillic_ef, +// //ffi::XK_Cyrillic_GHE => VirtualKeyCode::Cyrillic_ghe, +// //ffi::XK_Cyrillic_HA => VirtualKeyCode::Cyrillic_ha, +// //ffi::XK_Cyrillic_I => VirtualKeyCode::Cyrillic_i, +// //ffi::XK_Cyrillic_SHORTI => VirtualKeyCode::Cyrillic_shorti, +// //ffi::XK_Cyrillic_KA => VirtualKeyCode::Cyrillic_ka, +// //ffi::XK_Cyrillic_EL => VirtualKeyCode::Cyrillic_el, +// //ffi::XK_Cyrillic_EM => VirtualKeyCode::Cyrillic_em, +// //ffi::XK_Cyrillic_EN => VirtualKeyCode::Cyrillic_en, +// //ffi::XK_Cyrillic_O => VirtualKeyCode::Cyrillic_o, +// //ffi::XK_Cyrillic_PE => VirtualKeyCode::Cyrillic_pe, +// //ffi::XK_Cyrillic_YA => VirtualKeyCode::Cyrillic_ya, +// //ffi::XK_Cyrillic_ER => VirtualKeyCode::Cyrillic_er, +// //ffi::XK_Cyrillic_ES => VirtualKeyCode::Cyrillic_es, +// //ffi::XK_Cyrillic_TE => VirtualKeyCode::Cyrillic_te, +// //ffi::XK_Cyrillic_U => VirtualKeyCode::Cyrillic_u, +// //ffi::XK_Cyrillic_ZHE => VirtualKeyCode::Cyrillic_zhe, +// //ffi::XK_Cyrillic_VE => VirtualKeyCode::Cyrillic_ve, +// //ffi::XK_Cyrillic_SOFTSIGN => VirtualKeyCode::Cyrillic_softsign, +// //ffi::XK_Cyrillic_YERU => VirtualKeyCode::Cyrillic_yeru, +// //ffi::XK_Cyrillic_ZE => VirtualKeyCode::Cyrillic_ze, +// //ffi::XK_Cyrillic_SHA => VirtualKeyCode::Cyrillic_sha, +// //ffi::XK_Cyrillic_E => VirtualKeyCode::Cyrillic_e, +// //ffi::XK_Cyrillic_SHCHA => VirtualKeyCode::Cyrillic_shcha, +// //ffi::XK_Cyrillic_CHE => VirtualKeyCode::Cyrillic_che, +// //ffi::XK_Cyrillic_HARDSIGN => VirtualKeyCode::Cyrillic_hardsign, +// //ffi::XK_Greek_ALPHAaccent => VirtualKeyCode::Greek_alphaaccent, +// //ffi::XK_Greek_EPSILONaccent => VirtualKeyCode::Greek_epsilonaccent, +// //ffi::XK_Greek_ETAaccent => VirtualKeyCode::Greek_etaaccent, +// //ffi::XK_Greek_IOTAaccent => VirtualKeyCode::Greek_iotaaccent, +// //ffi::XK_Greek_IOTAdiaeresis => VirtualKeyCode::Greek_iotadiaeresis, +// //ffi::XK_Greek_OMICRONaccent => VirtualKeyCode::Greek_omicronaccent, +// //ffi::XK_Greek_UPSILONaccent => VirtualKeyCode::Greek_upsilonaccent, +// //ffi::XK_Greek_UPSILONdieresis => VirtualKeyCode::Greek_upsilondieresis, +// //ffi::XK_Greek_OMEGAaccent => VirtualKeyCode::Greek_omegaaccent, +// //ffi::XK_Greek_accentdieresis => VirtualKeyCode::Greek_accentdieresis, +// //ffi::XK_Greek_horizbar => VirtualKeyCode::Greek_horizbar, +// //ffi::XK_Greek_alphaaccent => VirtualKeyCode::Greek_alphaaccent, +// //ffi::XK_Greek_epsilonaccent => VirtualKeyCode::Greek_epsilonaccent, +// //ffi::XK_Greek_etaaccent => VirtualKeyCode::Greek_etaaccent, +// //ffi::XK_Greek_iotaaccent => VirtualKeyCode::Greek_iotaaccent, +// //ffi::XK_Greek_iotadieresis => VirtualKeyCode::Greek_iotadieresis, +// //ffi::XK_Greek_iotaaccentdieresis => VirtualKeyCode::Greek_iotaaccentdieresis, +// //ffi::XK_Greek_omicronaccent => VirtualKeyCode::Greek_omicronaccent, +// //ffi::XK_Greek_upsilonaccent => VirtualKeyCode::Greek_upsilonaccent, +// //ffi::XK_Greek_upsilondieresis => VirtualKeyCode::Greek_upsilondieresis, +// //ffi::XK_Greek_upsilonaccentdieresis => VirtualKeyCode::Greek_upsilonaccentdieresis, +// //ffi::XK_Greek_omegaaccent => VirtualKeyCode::Greek_omegaaccent, +// //ffi::XK_Greek_ALPHA => VirtualKeyCode::Greek_alpha, +// //ffi::XK_Greek_BETA => VirtualKeyCode::Greek_beta, +// //ffi::XK_Greek_GAMMA => VirtualKeyCode::Greek_gamma, +// //ffi::XK_Greek_DELTA => VirtualKeyCode::Greek_delta, +// //ffi::XK_Greek_EPSILON => VirtualKeyCode::Greek_epsilon, +// //ffi::XK_Greek_ZETA => VirtualKeyCode::Greek_zeta, +// //ffi::XK_Greek_ETA => VirtualKeyCode::Greek_eta, +// //ffi::XK_Greek_THETA => VirtualKeyCode::Greek_theta, +// //ffi::XK_Greek_IOTA => VirtualKeyCode::Greek_iota, +// //ffi::XK_Greek_KAPPA => VirtualKeyCode::Greek_kappa, +// //ffi::XK_Greek_LAMDA => VirtualKeyCode::Greek_lamda, +// //ffi::XK_Greek_LAMBDA => VirtualKeyCode::Greek_lambda, +// //ffi::XK_Greek_MU => VirtualKeyCode::Greek_mu, +// //ffi::XK_Greek_NU => VirtualKeyCode::Greek_nu, +// //ffi::XK_Greek_XI => VirtualKeyCode::Greek_xi, +// //ffi::XK_Greek_OMICRON => VirtualKeyCode::Greek_omicron, +// //ffi::XK_Greek_PI => VirtualKeyCode::Greek_pi, +// //ffi::XK_Greek_RHO => VirtualKeyCode::Greek_rho, +// //ffi::XK_Greek_SIGMA => VirtualKeyCode::Greek_sigma, +// //ffi::XK_Greek_TAU => VirtualKeyCode::Greek_tau, +// //ffi::XK_Greek_UPSILON => VirtualKeyCode::Greek_upsilon, +// //ffi::XK_Greek_PHI => VirtualKeyCode::Greek_phi, +// //ffi::XK_Greek_CHI => VirtualKeyCode::Greek_chi, +// //ffi::XK_Greek_PSI => VirtualKeyCode::Greek_psi, +// //ffi::XK_Greek_OMEGA => VirtualKeyCode::Greek_omega, +// //ffi::XK_Greek_alpha => VirtualKeyCode::Greek_alpha, +// //ffi::XK_Greek_beta => VirtualKeyCode::Greek_beta, +// //ffi::XK_Greek_gamma => VirtualKeyCode::Greek_gamma, +// //ffi::XK_Greek_delta => VirtualKeyCode::Greek_delta, +// //ffi::XK_Greek_epsilon => VirtualKeyCode::Greek_epsilon, +// //ffi::XK_Greek_zeta => VirtualKeyCode::Greek_zeta, +// //ffi::XK_Greek_eta => VirtualKeyCode::Greek_eta, +// //ffi::XK_Greek_theta => VirtualKeyCode::Greek_theta, +// //ffi::XK_Greek_iota => VirtualKeyCode::Greek_iota, +// //ffi::XK_Greek_kappa => VirtualKeyCode::Greek_kappa, +// //ffi::XK_Greek_lamda => VirtualKeyCode::Greek_lamda, +// //ffi::XK_Greek_lambda => VirtualKeyCode::Greek_lambda, +// //ffi::XK_Greek_mu => VirtualKeyCode::Greek_mu, +// //ffi::XK_Greek_nu => VirtualKeyCode::Greek_nu, +// //ffi::XK_Greek_xi => VirtualKeyCode::Greek_xi, +// //ffi::XK_Greek_omicron => VirtualKeyCode::Greek_omicron, +// //ffi::XK_Greek_pi => VirtualKeyCode::Greek_pi, +// //ffi::XK_Greek_rho => VirtualKeyCode::Greek_rho, +// //ffi::XK_Greek_sigma => VirtualKeyCode::Greek_sigma, +// //ffi::XK_Greek_finalsmallsigma => VirtualKeyCode::Greek_finalsmallsigma, +// //ffi::XK_Greek_tau => VirtualKeyCode::Greek_tau, +// //ffi::XK_Greek_upsilon => VirtualKeyCode::Greek_upsilon, +// //ffi::XK_Greek_phi => VirtualKeyCode::Greek_phi, +// //ffi::XK_Greek_chi => VirtualKeyCode::Greek_chi, +// //ffi::XK_Greek_psi => VirtualKeyCode::Greek_psi, +// //ffi::XK_Greek_omega => VirtualKeyCode::Greek_omega, +// //ffi::XK_Greek_switch => VirtualKeyCode::Greek_switch, +// //ffi::XK_leftradical => VirtualKeyCode::Leftradical, +// //ffi::XK_topleftradical => VirtualKeyCode::Topleftradical, +// //ffi::XK_horizconnector => VirtualKeyCode::Horizconnector, +// //ffi::XK_topintegral => VirtualKeyCode::Topintegral, +// //ffi::XK_botintegral => VirtualKeyCode::Botintegral, +// //ffi::XK_vertconnector => VirtualKeyCode::Vertconnector, +// //ffi::XK_topleftsqbracket => VirtualKeyCode::Topleftsqbracket, +// //ffi::XK_botleftsqbracket => VirtualKeyCode::Botleftsqbracket, +// //ffi::XK_toprightsqbracket => VirtualKeyCode::Toprightsqbracket, +// //ffi::XK_botrightsqbracket => VirtualKeyCode::Botrightsqbracket, +// //ffi::XK_topleftparens => VirtualKeyCode::Topleftparens, +// //ffi::XK_botleftparens => VirtualKeyCode::Botleftparens, +// //ffi::XK_toprightparens => VirtualKeyCode::Toprightparens, +// //ffi::XK_botrightparens => VirtualKeyCode::Botrightparens, +// //ffi::XK_leftmiddlecurlybrace => VirtualKeyCode::Leftmiddlecurlybrace, +// //ffi::XK_rightmiddlecurlybrace => VirtualKeyCode::Rightmiddlecurlybrace, +// //ffi::XK_topleftsummation => VirtualKeyCode::Topleftsummation, +// //ffi::XK_botleftsummation => VirtualKeyCode::Botleftsummation, +// //ffi::XK_topvertsummationconnector => VirtualKeyCode::Topvertsummationconnector, +// //ffi::XK_botvertsummationconnector => VirtualKeyCode::Botvertsummationconnector, +// //ffi::XK_toprightsummation => VirtualKeyCode::Toprightsummation, +// //ffi::XK_botrightsummation => VirtualKeyCode::Botrightsummation, +// //ffi::XK_rightmiddlesummation => VirtualKeyCode::Rightmiddlesummation, +// //ffi::XK_lessthanequal => VirtualKeyCode::Lessthanequal, +// //ffi::XK_notequal => VirtualKeyCode::Notequal, +// //ffi::XK_greaterthanequal => VirtualKeyCode::Greaterthanequal, +// //ffi::XK_integral => VirtualKeyCode::Integral, +// //ffi::XK_therefore => VirtualKeyCode::Therefore, +// //ffi::XK_variation => VirtualKeyCode::Variation, +// //ffi::XK_infinity => VirtualKeyCode::Infinity, +// //ffi::XK_nabla => VirtualKeyCode::Nabla, +// //ffi::XK_approximate => VirtualKeyCode::Approximate, +// //ffi::XK_similarequal => VirtualKeyCode::Similarequal, +// //ffi::XK_ifonlyif => VirtualKeyCode::Ifonlyif, +// //ffi::XK_implies => VirtualKeyCode::Implies, +// //ffi::XK_identical => VirtualKeyCode::Identical, +// //ffi::XK_radical => VirtualKeyCode::Radical, +// //ffi::XK_includedin => VirtualKeyCode::Includedin, +// //ffi::XK_includes => VirtualKeyCode::Includes, +// //ffi::XK_intersection => VirtualKeyCode::Intersection, +// //ffi::XK_union => VirtualKeyCode::Union, +// //ffi::XK_logicaland => VirtualKeyCode::Logicaland, +// //ffi::XK_logicalor => VirtualKeyCode::Logicalor, +// //ffi::XK_partialderivative => VirtualKeyCode::Partialderivative, +// //ffi::XK_function => VirtualKeyCode::Function, +// //ffi::XK_leftarrow => VirtualKeyCode::Leftarrow, +// //ffi::XK_uparrow => VirtualKeyCode::Uparrow, +// //ffi::XK_rightarrow => VirtualKeyCode::Rightarrow, +// //ffi::XK_downarrow => VirtualKeyCode::Downarrow, +// //ffi::XK_blank => VirtualKeyCode::Blank, +// //ffi::XK_soliddiamond => VirtualKeyCode::Soliddiamond, +// //ffi::XK_checkerboard => VirtualKeyCode::Checkerboard, +// //ffi::XK_ht => VirtualKeyCode::Ht, +// //ffi::XK_ff => VirtualKeyCode::Ff, +// //ffi::XK_cr => VirtualKeyCode::Cr, +// //ffi::XK_lf => VirtualKeyCode::Lf, +// //ffi::XK_nl => VirtualKeyCode::Nl, +// //ffi::XK_vt => VirtualKeyCode::Vt, +// //ffi::XK_lowrightcorner => VirtualKeyCode::Lowrightcorner, +// //ffi::XK_uprightcorner => VirtualKeyCode::Uprightcorner, +// //ffi::XK_upleftcorner => VirtualKeyCode::Upleftcorner, +// //ffi::XK_lowleftcorner => VirtualKeyCode::Lowleftcorner, +// //ffi::XK_crossinglines => VirtualKeyCode::Crossinglines, +// //ffi::XK_horizlinescan1 => VirtualKeyCode::Horizlinescan1, +// //ffi::XK_horizlinescan3 => VirtualKeyCode::Horizlinescan3, +// //ffi::XK_horizlinescan5 => VirtualKeyCode::Horizlinescan5, +// //ffi::XK_horizlinescan7 => VirtualKeyCode::Horizlinescan7, +// //ffi::XK_horizlinescan9 => VirtualKeyCode::Horizlinescan9, +// //ffi::XK_leftt => VirtualKeyCode::Leftt, +// //ffi::XK_rightt => VirtualKeyCode::Rightt, +// //ffi::XK_bott => VirtualKeyCode::Bott, +// //ffi::XK_topt => VirtualKeyCode::Topt, +// //ffi::XK_vertbar => VirtualKeyCode::Vertbar, +// //ffi::XK_emspace => VirtualKeyCode::Emspace, +// //ffi::XK_enspace => VirtualKeyCode::Enspace, +// //ffi::XK_em3space => VirtualKeyCode::Em3space, +// //ffi::XK_em4space => VirtualKeyCode::Em4space, +// //ffi::XK_digitspace => VirtualKeyCode::Digitspace, +// //ffi::XK_punctspace => VirtualKeyCode::Punctspace, +// //ffi::XK_thinspace => VirtualKeyCode::Thinspace, +// //ffi::XK_hairspace => VirtualKeyCode::Hairspace, +// //ffi::XK_emdash => VirtualKeyCode::Emdash, +// //ffi::XK_endash => VirtualKeyCode::Endash, +// //ffi::XK_signifblank => VirtualKeyCode::Signifblank, +// //ffi::XK_ellipsis => VirtualKeyCode::Ellipsis, +// //ffi::XK_doubbaselinedot => VirtualKeyCode::Doubbaselinedot, +// //ffi::XK_onethird => VirtualKeyCode::Onethird, +// //ffi::XK_twothirds => VirtualKeyCode::Twothirds, +// //ffi::XK_onefifth => VirtualKeyCode::Onefifth, +// //ffi::XK_twofifths => VirtualKeyCode::Twofifths, +// //ffi::XK_threefifths => VirtualKeyCode::Threefifths, +// //ffi::XK_fourfifths => VirtualKeyCode::Fourfifths, +// //ffi::XK_onesixth => VirtualKeyCode::Onesixth, +// //ffi::XK_fivesixths => VirtualKeyCode::Fivesixths, +// //ffi::XK_careof => VirtualKeyCode::Careof, +// //ffi::XK_figdash => VirtualKeyCode::Figdash, +// //ffi::XK_leftanglebracket => VirtualKeyCode::Leftanglebracket, +// //ffi::XK_decimalpoint => VirtualKeyCode::Decimalpoint, +// //ffi::XK_rightanglebracket => VirtualKeyCode::Rightanglebracket, +// //ffi::XK_marker => VirtualKeyCode::Marker, +// //ffi::XK_oneeighth => VirtualKeyCode::Oneeighth, +// //ffi::XK_threeeighths => VirtualKeyCode::Threeeighths, +// //ffi::XK_fiveeighths => VirtualKeyCode::Fiveeighths, +// //ffi::XK_seveneighths => VirtualKeyCode::Seveneighths, +// //ffi::XK_trademark => VirtualKeyCode::Trademark, +// //ffi::XK_signaturemark => VirtualKeyCode::Signaturemark, +// //ffi::XK_trademarkincircle => VirtualKeyCode::Trademarkincircle, +// //ffi::XK_leftopentriangle => VirtualKeyCode::Leftopentriangle, +// //ffi::XK_rightopentriangle => VirtualKeyCode::Rightopentriangle, +// //ffi::XK_emopencircle => VirtualKeyCode::Emopencircle, +// //ffi::XK_emopenrectangle => VirtualKeyCode::Emopenrectangle, +// //ffi::XK_leftsinglequotemark => VirtualKeyCode::Leftsinglequotemark, +// //ffi::XK_rightsinglequotemark => VirtualKeyCode::Rightsinglequotemark, +// //ffi::XK_leftdoublequotemark => VirtualKeyCode::Leftdoublequotemark, +// //ffi::XK_rightdoublequotemark => VirtualKeyCode::Rightdoublequotemark, +// //ffi::XK_prescription => VirtualKeyCode::Prescription, +// //ffi::XK_minutes => VirtualKeyCode::Minutes, +// //ffi::XK_seconds => VirtualKeyCode::Seconds, +// //ffi::XK_latincross => VirtualKeyCode::Latincross, +// //ffi::XK_hexagram => VirtualKeyCode::Hexagram, +// //ffi::XK_filledrectbullet => VirtualKeyCode::Filledrectbullet, +// //ffi::XK_filledlefttribullet => VirtualKeyCode::Filledlefttribullet, +// //ffi::XK_filledrighttribullet => VirtualKeyCode::Filledrighttribullet, +// //ffi::XK_emfilledcircle => VirtualKeyCode::Emfilledcircle, +// //ffi::XK_emfilledrect => VirtualKeyCode::Emfilledrect, +// //ffi::XK_enopencircbullet => VirtualKeyCode::Enopencircbullet, +// //ffi::XK_enopensquarebullet => VirtualKeyCode::Enopensquarebullet, +// //ffi::XK_openrectbullet => VirtualKeyCode::Openrectbullet, +// //ffi::XK_opentribulletup => VirtualKeyCode::Opentribulletup, +// //ffi::XK_opentribulletdown => VirtualKeyCode::Opentribulletdown, +// //ffi::XK_openstar => VirtualKeyCode::Openstar, +// //ffi::XK_enfilledcircbullet => VirtualKeyCode::Enfilledcircbullet, +// //ffi::XK_enfilledsqbullet => VirtualKeyCode::Enfilledsqbullet, +// //ffi::XK_filledtribulletup => VirtualKeyCode::Filledtribulletup, +// //ffi::XK_filledtribulletdown => VirtualKeyCode::Filledtribulletdown, +// //ffi::XK_leftpointer => VirtualKeyCode::Leftpointer, +// //ffi::XK_rightpointer => VirtualKeyCode::Rightpointer, +// //ffi::XK_club => VirtualKeyCode::Club, +// //ffi::XK_diamond => VirtualKeyCode::Diamond, +// //ffi::XK_heart => VirtualKeyCode::Heart, +// //ffi::XK_maltesecross => VirtualKeyCode::Maltesecross, +// //ffi::XK_dagger => VirtualKeyCode::Dagger, +// //ffi::XK_doubledagger => VirtualKeyCode::Doubledagger, +// //ffi::XK_checkmark => VirtualKeyCode::Checkmark, +// //ffi::XK_ballotcross => VirtualKeyCode::Ballotcross, +// //ffi::XK_musicalsharp => VirtualKeyCode::Musicalsharp, +// //ffi::XK_musicalflat => VirtualKeyCode::Musicalflat, +// //ffi::XK_malesymbol => VirtualKeyCode::Malesymbol, +// //ffi::XK_femalesymbol => VirtualKeyCode::Femalesymbol, +// //ffi::XK_telephone => VirtualKeyCode::Telephone, +// //ffi::XK_telephonerecorder => VirtualKeyCode::Telephonerecorder, +// //ffi::XK_phonographcopyright => VirtualKeyCode::Phonographcopyright, +// //ffi::XK_caret => VirtualKeyCode::Caret, +// //ffi::XK_singlelowquotemark => VirtualKeyCode::Singlelowquotemark, +// //ffi::XK_doublelowquotemark => VirtualKeyCode::Doublelowquotemark, +// //ffi::XK_cursor => VirtualKeyCode::Cursor, +// //ffi::XK_leftcaret => VirtualKeyCode::Leftcaret, +// //ffi::XK_rightcaret => VirtualKeyCode::Rightcaret, +// //ffi::XK_downcaret => VirtualKeyCode::Downcaret, +// //ffi::XK_upcaret => VirtualKeyCode::Upcaret, +// //ffi::XK_overbar => VirtualKeyCode::Overbar, +// //ffi::XK_downtack => VirtualKeyCode::Downtack, +// //ffi::XK_upshoe => VirtualKeyCode::Upshoe, +// //ffi::XK_downstile => VirtualKeyCode::Downstile, +// //ffi::XK_underbar => VirtualKeyCode::Underbar, +// //ffi::XK_jot => VirtualKeyCode::Jot, +// //ffi::XK_quad => VirtualKeyCode::Quad, +// //ffi::XK_uptack => VirtualKeyCode::Uptack, +// //ffi::XK_circle => VirtualKeyCode::Circle, +// //ffi::XK_upstile => VirtualKeyCode::Upstile, +// //ffi::XK_downshoe => VirtualKeyCode::Downshoe, +// //ffi::XK_rightshoe => VirtualKeyCode::Rightshoe, +// //ffi::XK_leftshoe => VirtualKeyCode::Leftshoe, +// //ffi::XK_lefttack => VirtualKeyCode::Lefttack, +// //ffi::XK_righttack => VirtualKeyCode::Righttack, +// //ffi::XK_hebrew_doublelowline => VirtualKeyCode::Hebrew_doublelowline, +// //ffi::XK_hebrew_aleph => VirtualKeyCode::Hebrew_aleph, +// //ffi::XK_hebrew_bet => VirtualKeyCode::Hebrew_bet, +// //ffi::XK_hebrew_beth => VirtualKeyCode::Hebrew_beth, +// //ffi::XK_hebrew_gimel => VirtualKeyCode::Hebrew_gimel, +// //ffi::XK_hebrew_gimmel => VirtualKeyCode::Hebrew_gimmel, +// //ffi::XK_hebrew_dalet => VirtualKeyCode::Hebrew_dalet, +// //ffi::XK_hebrew_daleth => VirtualKeyCode::Hebrew_daleth, +// //ffi::XK_hebrew_he => VirtualKeyCode::Hebrew_he, +// //ffi::XK_hebrew_waw => VirtualKeyCode::Hebrew_waw, +// //ffi::XK_hebrew_zain => VirtualKeyCode::Hebrew_zain, +// //ffi::XK_hebrew_zayin => VirtualKeyCode::Hebrew_zayin, +// //ffi::XK_hebrew_chet => VirtualKeyCode::Hebrew_chet, +// //ffi::XK_hebrew_het => VirtualKeyCode::Hebrew_het, +// //ffi::XK_hebrew_tet => VirtualKeyCode::Hebrew_tet, +// //ffi::XK_hebrew_teth => VirtualKeyCode::Hebrew_teth, +// //ffi::XK_hebrew_yod => VirtualKeyCode::Hebrew_yod, +// //ffi::XK_hebrew_finalkaph => VirtualKeyCode::Hebrew_finalkaph, +// //ffi::XK_hebrew_kaph => VirtualKeyCode::Hebrew_kaph, +// //ffi::XK_hebrew_lamed => VirtualKeyCode::Hebrew_lamed, +// //ffi::XK_hebrew_finalmem => VirtualKeyCode::Hebrew_finalmem, +// //ffi::XK_hebrew_mem => VirtualKeyCode::Hebrew_mem, +// //ffi::XK_hebrew_finalnun => VirtualKeyCode::Hebrew_finalnun, +// //ffi::XK_hebrew_nun => VirtualKeyCode::Hebrew_nun, +// //ffi::XK_hebrew_samech => VirtualKeyCode::Hebrew_samech, +// //ffi::XK_hebrew_samekh => VirtualKeyCode::Hebrew_samekh, +// //ffi::XK_hebrew_ayin => VirtualKeyCode::Hebrew_ayin, +// //ffi::XK_hebrew_finalpe => VirtualKeyCode::Hebrew_finalpe, +// //ffi::XK_hebrew_pe => VirtualKeyCode::Hebrew_pe, +// //ffi::XK_hebrew_finalzade => VirtualKeyCode::Hebrew_finalzade, +// //ffi::XK_hebrew_finalzadi => VirtualKeyCode::Hebrew_finalzadi, +// //ffi::XK_hebrew_zade => VirtualKeyCode::Hebrew_zade, +// //ffi::XK_hebrew_zadi => VirtualKeyCode::Hebrew_zadi, +// //ffi::XK_hebrew_qoph => VirtualKeyCode::Hebrew_qoph, +// //ffi::XK_hebrew_kuf => VirtualKeyCode::Hebrew_kuf, +// //ffi::XK_hebrew_resh => VirtualKeyCode::Hebrew_resh, +// //ffi::XK_hebrew_shin => VirtualKeyCode::Hebrew_shin, +// //ffi::XK_hebrew_taw => VirtualKeyCode::Hebrew_taw, +// //ffi::XK_hebrew_taf => VirtualKeyCode::Hebrew_taf, +// //ffi::XK_Hebrew_switch => VirtualKeyCode::Hebrew_switch, +// ffi::XF86XK_Back => VirtualKeyCode::NavigateBackward, +// ffi::XF86XK_Forward => VirtualKeyCode::NavigateForward, +// ffi::XF86XK_Copy => VirtualKeyCode::Copy, +// ffi::XF86XK_Paste => VirtualKeyCode::Paste, +// ffi::XF86XK_Cut => VirtualKeyCode::Cut, +// _ => return None, +// }) +// } diff --git a/src/platform_impl/linux/x11/util/input.rs b/src/platform_impl/linux/x11/util/input.rs index e9f45aee1c..6c7c651eed 100644 --- a/src/platform_impl/linux/x11/util/input.rs +++ b/src/platform_impl/linux/x11/util/input.rs @@ -1,7 +1,7 @@ use std::{slice, str}; use super::*; -use crate::event::ModifiersState; +use crate::keyboard::ModifiersState; pub const VIRTUAL_CORE_POINTER: c_int = 2; pub const VIRTUAL_CORE_KEYBOARD: c_int = 3; @@ -20,8 +20,8 @@ impl ModifiersState { let mut m = ModifiersState::empty(); m.set(ModifiersState::ALT, mask & ffi::Mod1Mask != 0); m.set(ModifiersState::SHIFT, mask & ffi::ShiftMask != 0); - m.set(ModifiersState::CTRL, mask & ffi::ControlMask != 0); - m.set(ModifiersState::LOGO, mask & ffi::Mod4Mask != 0); + m.set(ModifiersState::CONTROL, mask & ffi::ControlMask != 0); + m.set(ModifiersState::SUPER, mask & ffi::Mod4Mask != 0); m } } diff --git a/src/platform_impl/linux/x11/util/modifiers.rs b/src/platform_impl/linux/x11/util/modifiers.rs index acdab577e0..31db220263 100644 --- a/src/platform_impl/linux/x11/util/modifiers.rs +++ b/src/platform_impl/linux/x11/util/modifiers.rs @@ -2,7 +2,8 @@ use std::{collections::HashMap, slice}; use super::*; -use crate::event::{ElementState, ModifiersState}; +use crate::event::ElementState; +use crate::keyboard::ModifiersState; // Offsets within XModifierKeymap to each set of keycodes. // We are only interested in Shift, Control, Alt, and Logo. @@ -116,10 +117,12 @@ impl ModifierKeyState { let mut new_state = *state; match except { - Some(Modifier::Alt) => new_state.set(ModifiersState::ALT, self.state.alt()), - Some(Modifier::Ctrl) => new_state.set(ModifiersState::CTRL, self.state.ctrl()), - Some(Modifier::Shift) => new_state.set(ModifiersState::SHIFT, self.state.shift()), - Some(Modifier::Logo) => new_state.set(ModifiersState::LOGO, self.state.logo()), + Some(Modifier::Alt) => new_state.set(ModifiersState::ALT, self.state.alt_key()), + Some(Modifier::Ctrl) => { + new_state.set(ModifiersState::CONTROL, self.state.control_key()) + } + Some(Modifier::Shift) => new_state.set(ModifiersState::SHIFT, self.state.shift_key()), + Some(Modifier::Logo) => new_state.set(ModifiersState::SUPER, self.state.super_key()), None => (), } @@ -170,18 +173,18 @@ impl ModifierKeyState { fn get_modifier(state: &ModifiersState, modifier: Modifier) -> bool { match modifier { - Modifier::Alt => state.alt(), - Modifier::Ctrl => state.ctrl(), - Modifier::Shift => state.shift(), - Modifier::Logo => state.logo(), + Modifier::Alt => state.alt_key(), + Modifier::Ctrl => state.control_key(), + Modifier::Shift => state.shift_key(), + Modifier::Logo => state.super_key(), } } fn set_modifier(state: &mut ModifiersState, modifier: Modifier, value: bool) { match modifier { Modifier::Alt => state.set(ModifiersState::ALT, value), - Modifier::Ctrl => state.set(ModifiersState::CTRL, value), + Modifier::Ctrl => state.set(ModifiersState::CONTROL, value), Modifier::Shift => state.set(ModifiersState::SHIFT, value), - Modifier::Logo => state.set(ModifiersState::LOGO, value), + Modifier::Logo => state.set(ModifiersState::SUPER, value), } } From 6ddf1f843628180a951fdb014a7dc9de2cd8182f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sat, 20 Mar 2021 00:46:14 +0100 Subject: [PATCH 02/58] WIP --- .../linux/wayland/seat/keyboard/handlers.rs | 35 +- .../linux/wayland/seat/keyboard/keymap.rs | 694 ++++++++++++------ 2 files changed, 493 insertions(+), 236 deletions(-) diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index d81e440cc5..47cbc984ad 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -5,9 +5,10 @@ use sctk::reexports::client::protocol::wl_keyboard::KeyState; use sctk::seat::keyboard::Event as KeyboardEvent; use crate::event::{ElementState, KeyEvent, WindowEvent}; -use crate::keyboard::ModifiersState; +use crate::keyboard::{Key, KeyLocation, ModifiersState, NativeKeyCode}; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::{self, DeviceId}; +use crate::platform_impl::KeyEventExtra; use super::keymap; use super::KeyboardInner; @@ -69,7 +70,8 @@ pub(super) fn handle_keyboard( _ => unreachable!(), }; - // let virtual_keycode = keymap::keysym_to_vkey(keysym); + let physical_key = keymap::rawkey_to_keycode(rawkey); + let logical_key = keymap::keysym_to_key(keysym); event_sink.push_window_event( WindowEvent::KeyboardInput { @@ -77,13 +79,16 @@ pub(super) fn handle_keyboard( DeviceId, )), event: KeyEvent { - physical_key: todo!(), - logical_key: todo!(), - text: todo!(), - location: todo!(), + physical_key, + logical_key, + text: None, + location: KeyLocation::Standard, state, repeat: false, - platform_specific: todo!(), + platform_specific: KeyEventExtra { + key_without_modifiers: Key::Unidentified(NativeKeyCode::Unidentified), + text_with_all_modifers: None, + }, }, is_synthetic: false, }, @@ -112,7 +117,8 @@ pub(super) fn handle_keyboard( None => return, }; - // let virtual_keycode = keymap::keysym_to_vkey(keysym); + let physical_key = keymap::rawkey_to_keycode(rawkey); + let logical_key = keymap::keysym_to_key(keysym); event_sink.push_window_event( WindowEvent::KeyboardInput { @@ -120,13 +126,16 @@ pub(super) fn handle_keyboard( DeviceId, )), event: KeyEvent { - physical_key: todo!(), - logical_key: todo!(), - text: todo!(), - location: todo!(), + physical_key, + logical_key, + text: None, + location: KeyLocation::Standard, state: ElementState::Pressed, repeat: false, - platform_specific: todo!(), + platform_specific: KeyEventExtra { + key_without_modifiers: Key::Unidentified(NativeKeyCode::Unidentified), + text_with_all_modifers: None, + }, }, is_synthetic: false, }, diff --git a/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs b/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs index b674dd2945..ae48fc95cf 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs @@ -1,229 +1,477 @@ // //! Convert Wayland keys to winit keys. -// use crate::keyboard::Key; +use crate::keyboard::{Key, KeyCode, NativeKeyCode}; -// pub fn keysym_to_vkey(keysym: u32) -> Option> { -// use sctk::seat::keyboard::keysyms; -// match keysym { -// // Numbers. -// // keysyms::XKB_KEY_1 => Some(Key::Character("1")), -// // keysyms::XKB_KEY_2 => Some(Key::Character("2")), -// // keysyms::XKB_KEY_3 => Some(Key::Character("3")), -// // keysyms::XKB_KEY_4 => Some(Key::Character("4")), -// // keysyms::XKB_KEY_5 => Some(Key::Character("5")), -// // keysyms::XKB_KEY_6 => Some(Key::Character("6")), -// // keysyms::XKB_KEY_7 => Some(Key::Character("7")), -// // keysyms::XKB_KEY_8 => Some(Key::Character("8")), -// // keysyms::XKB_KEY_9 => Some(Key::Character("9")), -// // keysyms::XKB_KEY_0 => Some(Key::Character("0")), -// // Letters. -// // keysyms::XKB_KEY_A => Some(Key::Character("A")), -// // keysyms::XKB_KEY_a => Some(Key::Character("a")), -// // keysyms::XKB_KEY_B => Some(Key::Character("B")), -// // keysyms::XKB_KEY_b => Some(Key::Character("b")), -// // keysyms::XKB_KEY_C => Some(Key::Character("C")), -// // keysyms::XKB_KEY_c => Some(Key::Character("c")), -// // keysyms::XKB_KEY_D => Some(Key::Character("D")), -// // keysyms::XKB_KEY_d => Some(Key::Character("d")), -// // keysyms::XKB_KEY_E => Some(Key::Character("E")), -// // keysyms::XKB_KEY_e => Some(Key::Character("e")), -// // keysyms::XKB_KEY_F => Some(Key::Character("F")), -// // keysyms::XKB_KEY_f => Some(Key::Character("f")), -// // keysyms::XKB_KEY_G => Some(Key::Character("G")), -// // keysyms::XKB_KEY_g => Some(Key::Character("g")), -// // keysyms::XKB_KEY_H => Some(Key::Character("H")), -// // keysyms::XKB_KEY_h => Some(Key::Character("h")), -// // keysyms::XKB_KEY_I => Some(Key::Character("I")), -// // keysyms::XKB_KEY_i => Some(Key::Character("i")), -// // keysyms::XKB_KEY_J => Some(Key::Character("J")), -// // keysyms::XKB_KEY_j => Some(Key::Character("j")), -// // keysyms::XKB_KEY_K => Some(Key::Character("K")), -// // keysyms::XKB_KEY_k => Some(Key::Character("k")), -// // keysyms::XKB_KEY_L => Some(Key::Character("L")), -// // keysyms::XKB_KEY_l => Some(Key::Character("l")), -// // keysyms::XKB_KEY_M => Some(Key::Character("M")), -// // keysyms::XKB_KEY_m => Some(Key::Character("m")), -// // keysyms::XKB_KEY_N => Some(Key::Character("N")), -// // keysyms::XKB_KEY_n => Some(Key::Character("n")), -// // keysyms::XKB_KEY_O => Some(Key::Character("O")), -// // keysyms::XKB_KEY_o => Some(Key::Character("o")), -// // keysyms::XKB_KEY_P => Some(Key::Character("P")), -// // keysyms::XKB_KEY_p => Some(Key::Character("p")), -// // keysyms::XKB_KEY_Q => Some(Key::Character("Q")), -// // keysyms::XKB_KEY_q => Some(Key::Character("q")), -// // keysyms::XKB_KEY_R => Some(Key::Character("R")), -// // keysyms::XKB_KEY_r => Some(Key::Character("r")), -// // keysyms::XKB_KEY_S => Some(Key::Character("S")), -// // keysyms::XKB_KEY_s => Some(Key::Character("s")), -// // keysyms::XKB_KEY_T => Some(Key::Character("T")), -// // keysyms::XKB_KEY_t => Some(Key::Character("t")), -// // keysyms::XKB_KEY_U => Some(Key::Character("U")), -// // keysyms::XKB_KEY_u => Some(Key::Character("u")), -// // keysyms::XKB_KEY_V => Some(Key::Character("V")), -// // keysyms::XKB_KEY_v => Some(Key::Character("v")), -// // keysyms::XKB_KEY_W => Some(Key::Character("W")), -// // keysyms::XKB_KEY_w => Some(Key::Character("w")), -// // keysyms::XKB_KEY_X => Some(Key::Character("X")), -// // keysyms::XKB_KEY_x => Some(Key::Character("x")), -// // keysyms::XKB_KEY_Y => Some(Key::Character("Y")), -// // keysyms::XKB_KEY_y => Some(Key::Character("y")), -// // keysyms::XKB_KEY_Z => Some(Key::Character("Z")), -// // keysyms::XKB_KEY_z => Some(Key::Character("z")), -// // Escape. -// keysyms::XKB_KEY_Escape => Some(Key::Escape), -// // Function keys. -// keysyms::XKB_KEY_F1 => Some(Key::F1), -// keysyms::XKB_KEY_F2 => Some(Key::F2), -// keysyms::XKB_KEY_F3 => Some(Key::F3), -// keysyms::XKB_KEY_F4 => Some(Key::F4), -// keysyms::XKB_KEY_F5 => Some(Key::F5), -// keysyms::XKB_KEY_F6 => Some(Key::F6), -// keysyms::XKB_KEY_F7 => Some(Key::F7), -// keysyms::XKB_KEY_F8 => Some(Key::F8), -// keysyms::XKB_KEY_F9 => Some(Key::F9), -// keysyms::XKB_KEY_F10 => Some(Key::F10), -// keysyms::XKB_KEY_F11 => Some(Key::F11), -// keysyms::XKB_KEY_F12 => Some(Key::F12), -// keysyms::XKB_KEY_F13 => Some(Key::F13), -// keysyms::XKB_KEY_F14 => Some(Key::F14), -// keysyms::XKB_KEY_F15 => Some(Key::F15), -// keysyms::XKB_KEY_F16 => Some(Key::F16), -// keysyms::XKB_KEY_F17 => Some(Key::F17), -// keysyms::XKB_KEY_F18 => Some(Key::F18), -// keysyms::XKB_KEY_F19 => Some(Key::F19), -// keysyms::XKB_KEY_F20 => Some(Key::F20), -// keysyms::XKB_KEY_F21 => Some(Key::F21), -// keysyms::XKB_KEY_F22 => Some(Key::F22), -// keysyms::XKB_KEY_F23 => Some(Key::F23), -// keysyms::XKB_KEY_F24 => Some(Key::F24), -// keysyms::XKB_KEY_F25 => Some(Key::F25), -// keysyms::XKB_KEY_F26 => Some(Key::F26), -// keysyms::XKB_KEY_F27 => Some(Key::F27), -// keysyms::XKB_KEY_F28 => Some(Key::F28), -// keysyms::XKB_KEY_F29 => Some(Key::F29), -// keysyms::XKB_KEY_F30 => Some(Key::F30), -// keysyms::XKB_KEY_F31 => Some(Key::F31), -// keysyms::XKB_KEY_F32 => Some(Key::F32), -// keysyms::XKB_KEY_F33 => Some(Key::F33), -// keysyms::XKB_KEY_F34 => Some(Key::F34), -// keysyms::XKB_KEY_F35 => Some(Key::F35), -// // Flow control. -// keysyms::XKB_KEY_Print => Some(Key::PrintScreen), -// keysyms::XKB_KEY_Scroll_Lock => Some(Key::ScrollLock), -// keysyms::XKB_KEY_Pause => Some(Key::Pause), -// keysyms::XKB_KEY_Insert => Some(Key::Insert), -// keysyms::XKB_KEY_Home => Some(Key::Home), -// keysyms::XKB_KEY_Delete => Some(Key::Delete), -// keysyms::XKB_KEY_End => Some(Key::End), -// keysyms::XKB_KEY_Page_Down => Some(Key::PageDown), -// keysyms::XKB_KEY_Page_Up => Some(Key::PageUp), -// // Arrows. -// keysyms::XKB_KEY_Left => Some(Key::Left), -// keysyms::XKB_KEY_Up => Some(Key::Up), -// keysyms::XKB_KEY_Right => Some(Key::Right), -// keysyms::XKB_KEY_Down => Some(Key::Down), +pub fn rawkey_to_keycode(rawkey: u32) -> KeyCode { + // keycodes are taken from linux/include/uapi/linux/input-event-codes.h + match rawkey { + 0 => todo!("What should be done in this case? Return `NativeKeyCode`, or perhaps `None`?"), + 1 => KeyCode::Escape, + 2 => KeyCode::Digit1, + 3 => KeyCode::Digit2, + 4 => KeyCode::Digit3, + 5 => KeyCode::Digit4, + 6 => KeyCode::Digit5, + 7 => KeyCode::Digit6, + 8 => KeyCode::Digit7, + 9 => KeyCode::Digit8, + 10 => KeyCode::Digit9, + 11 => KeyCode::Digit0, + 12 => KeyCode::Minus, + 13 => KeyCode::Equal, + 14 => KeyCode::Backspace, + 15 => KeyCode::Tab, + 16 => KeyCode::KeyQ, + 17 => KeyCode::KeyW, + 18 => KeyCode::KeyE, + 19 => KeyCode::KeyR, + 20 => KeyCode::KeyT, + 21 => KeyCode::KeyY, + 22 => KeyCode::KeyU, + 23 => KeyCode::KeyI, + 24 => KeyCode::KeyO, + 25 => KeyCode::KeyP, + 26 => KeyCode::BracketLeft, + 27 => KeyCode::BracketRight, + 28 => KeyCode::Enter, + 29 => KeyCode::ControlLeft, + 30 => KeyCode::KeyA, + 31 => KeyCode::KeyS, + 32 => KeyCode::KeyD, + 33 => KeyCode::KeyF, + 34 => KeyCode::KeyG, + 35 => KeyCode::KeyH, + 36 => KeyCode::KeyJ, + 37 => KeyCode::KeyK, + 38 => KeyCode::KeyL, + 39 => KeyCode::Semicolon, + 40 => KeyCode::Quote, + 41 => KeyCode::Backquote, + 42 => KeyCode::ShiftLeft, + 43 => KeyCode::Backslash, + 44 => KeyCode::KeyZ, + 45 => KeyCode::KeyX, + 46 => KeyCode::KeyC, + 47 => KeyCode::KeyV, + 48 => KeyCode::KeyB, + 49 => KeyCode::KeyN, + 50 => KeyCode::KeyM, + 51 => KeyCode::Comma, + 52 => KeyCode::Period, + 53 => KeyCode::Slash, + 54 => KeyCode::ShiftRight, + 55 => KeyCode::NumpadMultiply, + 56 => KeyCode::AltLeft, + 57 => KeyCode::Space, + 58 => KeyCode::CapsLock, + 59 => KeyCode::F1, + 60 => KeyCode::F2, + 61 => KeyCode::F3, + 62 => KeyCode::F4, + 63 => KeyCode::F5, + 64 => KeyCode::F6, + 65 => KeyCode::F7, + 66 => KeyCode::F8, + 67 => KeyCode::F9, + 68 => KeyCode::F10, + 69 => KeyCode::NumLock, + 70 => KeyCode::ScrollLock, + 71 => KeyCode::Numpad7, + 72 => KeyCode::Numpad8, + 73 => KeyCode::Numpad9, + 74 => KeyCode::NumpadSubtract, + 75 => KeyCode::Numpad4, + 76 => KeyCode::Numpad4, + 77 => KeyCode::Numpad6, + 78 => KeyCode::NumpadAdd, + 79 => KeyCode::Numpad1, + 80 => KeyCode::Numpad2, + 81 => KeyCode::Numpad3, + 82 => KeyCode::Numpad0, + 83 => KeyCode::NumpadDecimal, + 85 => KeyCode::Lang5, + 86 => KeyCode::IntlBackslash, // TODO: Verify. + 87 => KeyCode::F11, + 88 => KeyCode::F12, + 89 => KeyCode::IntlRo, + 90 => KeyCode::Lang3, + 91 => KeyCode::Lang4, + 92 => KeyCode::Convert, + 93 => KeyCode::KanaMode, + 94 => KeyCode::NonConvert, + // 95 => KeyCode::KPJPCOMMA, // TODO: What the heck is this supposed to be? + 96 => KeyCode::NumpadEnter, + 97 => KeyCode::ControlRight, + 98 => KeyCode::NumpadDivide, + 99 => KeyCode::PrintScreen, // TODO: Verify. + 100 => KeyCode::AltRight, + // 101 => KeyCode::LINEFEED, // TODO: What the heck is this supposed to be? + 102 => KeyCode::Home, + 103 => KeyCode::ArrowUp, + 104 => KeyCode::PageUp, + 105 => KeyCode::ArrowLeft, + 106 => KeyCode::ArrowRight, + 107 => KeyCode::End, + 108 => KeyCode::ArrowDown, + 109 => KeyCode::PageDown, + 110 => KeyCode::Insert, + 111 => KeyCode::Delete, + // 112 => KeyCode::MACRO, // TODO: What the heck is this supposed to be? + 113 => KeyCode::AudioVolumeMute, + 114 => KeyCode::AudioVolumeDown, + 115 => KeyCode::AudioVolumeUp, + // TODO: I have no idea if this should be mapped to `KeyCode::Power` + // Neither the Linux header or the uievents-code document disambigues this. + // 116 => KeyCode::POWER, + 117 => KeyCode::NumpadEqual, + // 118 => KeyCode::KPPLUSMINUS, // TODO: What the heck is this supposed to be? + 119 => KeyCode::Pause, + // 120 => KeyCode::SCALE, // TODO: What the heck is this supposed to be? + 121 => KeyCode::NumpadComma, + 122 => KeyCode::Lang1, + 123 => KeyCode::Lang2, + 124 => KeyCode::IntlYen, + 125 => KeyCode::SuperLeft, + 126 => KeyCode::SuperRight, + 127 => KeyCode::ContextMenu, + // 128 => KeyCode::STOP, + // 129 => KeyCode::AGAIN, + // 130 => KeyCode::PROPS, + // 131 => KeyCode::UNDO, + // 132 => KeyCode::FRONT, + // 133 => KeyCode::COPY, + // 134 => KeyCode::OPEN, + // 135 => KeyCode::PASTE, + // 136 => KeyCode::FIND, + // 137 => KeyCode::CUT, + // 138 => KeyCode::HELP, + // 139 => KeyCode::MENU, + // 140 => KeyCode::CALC, + // 141 => KeyCode::SETUP, + // 142 => KeyCode::SLEEP, + // 143 => KeyCode::WAKEUP, + // 144 => KeyCode::FILE, + // 145 => KeyCode::SENDFILE, + // 146 => KeyCode::DELETEFILE, + // 147 => KeyCode::XFER, + // 148 => KeyCode::PROG1, + // 149 => KeyCode::PROG2, + // 150 => KeyCode::WWW, + // 151 => KeyCode::MSDOS, + // 152 => KeyCode::COFFEE, + // 153 => KeyCode::ROTATE_DISPLAY, + // 154 => KeyCode::CYCLEWINDOWS, + // 155 => KeyCode::MAIL, + // 156 => KeyCode::BOOKMARKS, + // 157 => KeyCode::COMPUTER, + // 158 => KeyCode::BACK, + // 159 => KeyCode::FORWARD, + // 160 => KeyCode::CLOSECD, + // 161 => KeyCode::EJECTCD, + // 162 => KeyCode::EJECTCLOSECD, + 163 => KeyCode::MediaTrackNext, + 164 => KeyCode::MediaPlayPause, + 165 => KeyCode::MediaTrackPrevious, + 166 => KeyCode::MediaStop, + // 167 => KeyCode::RECORD, + // 168 => KeyCode::REWIND, + // 169 => KeyCode::PHONE, + // 170 => KeyCode::ISO, + // 171 => KeyCode::CONFIG, + // 172 => KeyCode::HOMEPAGE, + // 173 => KeyCode::REFRESH, + // 174 => KeyCode::EXIT, + // 175 => KeyCode::MOVE, + // 176 => KeyCode::EDIT, + // 177 => KeyCode::SCROLLUP, + // 178 => KeyCode::SCROLLDOWN, + // 179 => KeyCode::KPLEFTPAREN, + // 180 => KeyCode::KPRIGHTPAREN, + // 181 => KeyCode::NEW, + // 182 => KeyCode::REDO, + 183 => KeyCode::F13, + 184 => KeyCode::F14, + 185 => KeyCode::F15, + 186 => KeyCode::F16, + 187 => KeyCode::F17, + 188 => KeyCode::F18, + 189 => KeyCode::F19, + 190 => KeyCode::F20, + 191 => KeyCode::F21, + 192 => KeyCode::F22, + 193 => KeyCode::F23, + 194 => KeyCode::F24, + // 200 => KeyCode::PLAYCD, + // 201 => KeyCode::PAUSECD, + // 202 => KeyCode::PROG3, + // 203 => KeyCode::PROG4, + // 204 => KeyCode::DASHBOARD, + // 205 => KeyCode::SUSPEND, + // 206 => KeyCode::CLOSE, + // 207 => KeyCode::PLAY, + // 208 => KeyCode::FASTFORWARD, + // 209 => KeyCode::BASSBOOST, + // 210 => KeyCode::PRINT, + // 211 => KeyCode::HP, + // 212 => KeyCode::CAMERA, + // 213 => KeyCode::SOUND, + // 214 => KeyCode::QUESTION, + // 215 => KeyCode::EMAIL, + // 216 => KeyCode::CHAT, + // 217 => KeyCode::SEARCH, + // 218 => KeyCode::CONNECT, + // 219 => KeyCode::FINANCE, + // 220 => KeyCode::SPORT, + // 221 => KeyCode::SHOP, + // 222 => KeyCode::ALTERASE, + // 223 => KeyCode::CANCEL, + // 224 => KeyCode::BRIGHTNESSDOW, + // 225 => KeyCode::BRIGHTNESSU, + // 226 => KeyCode::MEDIA, + // 227 => KeyCode::SWITCHVIDEOMODE, + // 228 => KeyCode::KBDILLUMTOGGLE, + // 229 => KeyCode::KBDILLUMDOWN, + // 230 => KeyCode::KBDILLUMUP, + // 231 => KeyCode::SEND, + // 232 => KeyCode::REPLY, + // 233 => KeyCode::FORWARDMAIL, + // 234 => KeyCode::SAVE, + // 235 => KeyCode::DOCUMENTS, + // 236 => KeyCode::BATTERY, + // 237 => KeyCode::BLUETOOTH, + // 238 => KeyCode::WLAN, + // 239 => KeyCode::UWB, + 240 => KeyCode::Unidentified(NativeKeyCode::Unidentified), + // 241 => KeyCode::VIDEO_NEXT, + // 242 => KeyCode::VIDEO_PREV, + // 243 => KeyCode::BRIGHTNESS_CYCLE, + // 244 => KeyCode::BRIGHTNESS_AUTO, + _ => KeyCode::Unidentified(NativeKeyCode::XKB(rawkey)), + } +} -// keysyms::XKB_KEY_BackSpace => Some(Key::Back), -// keysyms::XKB_KEY_Return => Some(Key::Return), -// keysyms::XKB_KEY_space => Some(Key::Space), +pub fn keysym_to_key(keysym: u32) -> Key<'static> { + use sctk::seat::keyboard::keysyms; + match keysym { + // // Numbers. + // // keysyms::XKB_KEY_1 => Some(Key::Character("1")), + // // keysyms::XKB_KEY_2 => Some(Key::Character("2")), + // // keysyms::XKB_KEY_3 => Some(Key::Character("3")), + // // keysyms::XKB_KEY_4 => Some(Key::Character("4")), + // // keysyms::XKB_KEY_5 => Some(Key::Character("5")), + // // keysyms::XKB_KEY_6 => Some(Key::Character("6")), + // // keysyms::XKB_KEY_7 => Some(Key::Character("7")), + // // keysyms::XKB_KEY_8 => Some(Key::Character("8")), + // // keysyms::XKB_KEY_9 => Some(Key::Character("9")), + // // keysyms::XKB_KEY_0 => Some(Key::Character("0")), + // // Letters. + // // keysyms::XKB_KEY_A => Some(Key::Character("A")), + // // keysyms::XKB_KEY_a => Some(Key::Character("a")), + // // keysyms::XKB_KEY_B => Some(Key::Character("B")), + // // keysyms::XKB_KEY_b => Some(Key::Character("b")), + // // keysyms::XKB_KEY_C => Some(Key::Character("C")), + // // keysyms::XKB_KEY_c => Some(Key::Character("c")), + // // keysyms::XKB_KEY_D => Some(Key::Character("D")), + // // keysyms::XKB_KEY_d => Some(Key::Character("d")), + // // keysyms::XKB_KEY_E => Some(Key::Character("E")), + // // keysyms::XKB_KEY_e => Some(Key::Character("e")), + // // keysyms::XKB_KEY_F => Some(Key::Character("F")), + // // keysyms::XKB_KEY_f => Some(Key::Character("f")), + // // keysyms::XKB_KEY_G => Some(Key::Character("G")), + // // keysyms::XKB_KEY_g => Some(Key::Character("g")), + // // keysyms::XKB_KEY_H => Some(Key::Character("H")), + // // keysyms::XKB_KEY_h => Some(Key::Character("h")), + // // keysyms::XKB_KEY_I => Some(Key::Character("I")), + // // keysyms::XKB_KEY_i => Some(Key::Character("i")), + // // keysyms::XKB_KEY_J => Some(Key::Character("J")), + // // keysyms::XKB_KEY_j => Some(Key::Character("j")), + // // keysyms::XKB_KEY_K => Some(Key::Character("K")), + // // keysyms::XKB_KEY_k => Some(Key::Character("k")), + // // keysyms::XKB_KEY_L => Some(Key::Character("L")), + // // keysyms::XKB_KEY_l => Some(Key::Character("l")), + // // keysyms::XKB_KEY_M => Some(Key::Character("M")), + // // keysyms::XKB_KEY_m => Some(Key::Character("m")), + // // keysyms::XKB_KEY_N => Some(Key::Character("N")), + // // keysyms::XKB_KEY_n => Some(Key::Character("n")), + // // keysyms::XKB_KEY_O => Some(Key::Character("O")), + // // keysyms::XKB_KEY_o => Some(Key::Character("o")), + // // keysyms::XKB_KEY_P => Some(Key::Character("P")), + // // keysyms::XKB_KEY_p => Some(Key::Character("p")), + // // keysyms::XKB_KEY_Q => Some(Key::Character("Q")), + // // keysyms::XKB_KEY_q => Some(Key::Character("q")), + // // keysyms::XKB_KEY_R => Some(Key::Character("R")), + // // keysyms::XKB_KEY_r => Some(Key::Character("r")), + // // keysyms::XKB_KEY_S => Some(Key::Character("S")), + // // keysyms::XKB_KEY_s => Some(Key::Character("s")), + // // keysyms::XKB_KEY_T => Some(Key::Character("T")), + // // keysyms::XKB_KEY_t => Some(Key::Character("t")), + // // keysyms::XKB_KEY_U => Some(Key::Character("U")), + // // keysyms::XKB_KEY_u => Some(Key::Character("u")), + // // keysyms::XKB_KEY_V => Some(Key::Character("V")), + // // keysyms::XKB_KEY_v => Some(Key::Character("v")), + // // keysyms::XKB_KEY_W => Some(Key::Character("W")), + // // keysyms::XKB_KEY_w => Some(Key::Character("w")), + // // keysyms::XKB_KEY_X => Some(Key::Character("X")), + // // keysyms::XKB_KEY_x => Some(Key::Character("x")), + // // keysyms::XKB_KEY_Y => Some(Key::Character("Y")), + // // keysyms::XKB_KEY_y => Some(Key::Character("y")), + // // keysyms::XKB_KEY_Z => Some(Key::Character("Z")), + // // keysyms::XKB_KEY_z => Some(Key::Character("z")), + // // Escape. + // keysyms::XKB_KEY_Escape => Some(Key::Escape), + // // Function keys. + // keysyms::XKB_KEY_F1 => Some(Key::F1), + // keysyms::XKB_KEY_F2 => Some(Key::F2), + // keysyms::XKB_KEY_F3 => Some(Key::F3), + // keysyms::XKB_KEY_F4 => Some(Key::F4), + // keysyms::XKB_KEY_F5 => Some(Key::F5), + // keysyms::XKB_KEY_F6 => Some(Key::F6), + // keysyms::XKB_KEY_F7 => Some(Key::F7), + // keysyms::XKB_KEY_F8 => Some(Key::F8), + // keysyms::XKB_KEY_F9 => Some(Key::F9), + // keysyms::XKB_KEY_F10 => Some(Key::F10), + // keysyms::XKB_KEY_F11 => Some(Key::F11), + // keysyms::XKB_KEY_F12 => Some(Key::F12), + // keysyms::XKB_KEY_F13 => Some(Key::F13), + // keysyms::XKB_KEY_F14 => Some(Key::F14), + // keysyms::XKB_KEY_F15 => Some(Key::F15), + // keysyms::XKB_KEY_F16 => Some(Key::F16), + // keysyms::XKB_KEY_F17 => Some(Key::F17), + // keysyms::XKB_KEY_F18 => Some(Key::F18), + // keysyms::XKB_KEY_F19 => Some(Key::F19), + // keysyms::XKB_KEY_F20 => Some(Key::F20), + // keysyms::XKB_KEY_F21 => Some(Key::F21), + // keysyms::XKB_KEY_F22 => Some(Key::F22), + // keysyms::XKB_KEY_F23 => Some(Key::F23), + // keysyms::XKB_KEY_F24 => Some(Key::F24), + // keysyms::XKB_KEY_F25 => Some(Key::F25), + // keysyms::XKB_KEY_F26 => Some(Key::F26), + // keysyms::XKB_KEY_F27 => Some(Key::F27), + // keysyms::XKB_KEY_F28 => Some(Key::F28), + // keysyms::XKB_KEY_F29 => Some(Key::F29), + // keysyms::XKB_KEY_F30 => Some(Key::F30), + // keysyms::XKB_KEY_F31 => Some(Key::F31), + // keysyms::XKB_KEY_F32 => Some(Key::F32), + // keysyms::XKB_KEY_F33 => Some(Key::F33), + // keysyms::XKB_KEY_F34 => Some(Key::F34), + // keysyms::XKB_KEY_F35 => Some(Key::F35), + // // Flow control. + // keysyms::XKB_KEY_Print => Some(Key::PrintScreen), + // keysyms::XKB_KEY_Scroll_Lock => Some(Key::ScrollLock), + // keysyms::XKB_KEY_Pause => Some(Key::Pause), + // keysyms::XKB_KEY_Insert => Some(Key::Insert), + // keysyms::XKB_KEY_Home => Some(Key::Home), + // keysyms::XKB_KEY_Delete => Some(Key::Delete), + // keysyms::XKB_KEY_End => Some(Key::End), + // keysyms::XKB_KEY_Page_Down => Some(Key::PageDown), + // keysyms::XKB_KEY_Page_Up => Some(Key::PageUp), + // // Arrows. + // keysyms::XKB_KEY_Left => Some(Key::Left), + // keysyms::XKB_KEY_Up => Some(Key::Up), + // keysyms::XKB_KEY_Right => Some(Key::Right), + // keysyms::XKB_KEY_Down => Some(Key::Down), -// keysyms::XKB_KEY_Multi_key => Some(Key::Compose), -// keysyms::XKB_KEY_caret => Some(Key::Caret), + // keysyms::XKB_KEY_BackSpace => Some(Key::Back), + // keysyms::XKB_KEY_Return => Some(Key::Return), + // keysyms::XKB_KEY_space => Some(Key::Space), -// // Keypad. -// keysyms::XKB_KEY_Num_Lock => Some(Key::Numlock), -// keysyms::XKB_KEY_KP_0 => Some(Key::Numpad0), -// keysyms::XKB_KEY_KP_1 => Some(Key::Numpad1), -// keysyms::XKB_KEY_KP_2 => Some(Key::Numpad2), -// keysyms::XKB_KEY_KP_3 => Some(Key::Numpad3), -// keysyms::XKB_KEY_KP_4 => Some(Key::Numpad4), -// keysyms::XKB_KEY_KP_5 => Some(Key::Numpad5), -// keysyms::XKB_KEY_KP_6 => Some(Key::Numpad6), -// keysyms::XKB_KEY_KP_7 => Some(Key::Numpad7), -// keysyms::XKB_KEY_KP_8 => Some(Key::Numpad8), -// keysyms::XKB_KEY_KP_9 => Some(Key::Numpad9), -// // Misc. -// // => Some(Key::AbntC1), -// // => Some(Key::AbntC2), -// keysyms::XKB_KEY_plus => Some(Key::Plus), -// keysyms::XKB_KEY_apostrophe => Some(Key::Apostrophe), -// // => Some(Key::Apps), -// keysyms::XKB_KEY_at => Some(Key::At), -// // => Some(Key::Ax), -// keysyms::XKB_KEY_backslash => Some(Key::Backslash), -// keysyms::XKB_KEY_XF86Calculator => Some(Key::Calculator), -// // => Some(Key::Capital), -// keysyms::XKB_KEY_colon => Some(Key::Colon), -// keysyms::XKB_KEY_comma => Some(Key::Comma), -// // => Some(Key::Convert), -// keysyms::XKB_KEY_equal => Some(Key::Equals), -// keysyms::XKB_KEY_grave => Some(Key::Grave), -// // => Some(Key::Kana), -// keysyms::XKB_KEY_Kanji => Some(Key::Kanji), -// keysyms::XKB_KEY_Alt_L => Some(Key::LAlt), -// keysyms::XKB_KEY_bracketleft => Some(Key::LBracket), -// keysyms::XKB_KEY_Control_L => Some(Key::LControl), -// keysyms::XKB_KEY_Shift_L => Some(Key::LShift), -// keysyms::XKB_KEY_Super_L => Some(Key::LWin), -// keysyms::XKB_KEY_XF86Mail => Some(Key::Mail), -// // => Some(Key::MediaSelect), -// // => Some(Key::MediaStop), -// keysyms::XKB_KEY_minus => Some(Key::Minus), -// keysyms::XKB_KEY_asterisk => Some(Key::Asterisk), -// keysyms::XKB_KEY_XF86AudioMute => Some(Key::Mute), -// // => Some(Key::MyComputer), -// keysyms::XKB_KEY_XF86AudioNext => Some(Key::NextTrack), -// // => Some(Key::NoConvert), -// keysyms::XKB_KEY_KP_Separator => Some(Key::NumpadComma), -// keysyms::XKB_KEY_KP_Enter => Some(Key::NumpadEnter), -// keysyms::XKB_KEY_KP_Equal => Some(Key::NumpadEquals), -// keysyms::XKB_KEY_KP_Add => Some(Key::NumpadAdd), -// keysyms::XKB_KEY_KP_Subtract => Some(Key::NumpadSubtract), -// keysyms::XKB_KEY_KP_Multiply => Some(Key::NumpadMultiply), -// keysyms::XKB_KEY_KP_Divide => Some(Key::NumpadDivide), -// keysyms::XKB_KEY_KP_Decimal => Some(Key::NumpadDecimal), -// keysyms::XKB_KEY_KP_Page_Up => Some(Key::PageUp), -// keysyms::XKB_KEY_KP_Page_Down => Some(Key::PageDown), -// keysyms::XKB_KEY_KP_Home => Some(Key::Home), -// keysyms::XKB_KEY_KP_End => Some(Key::End), -// keysyms::XKB_KEY_KP_Left => Some(Key::Left), -// keysyms::XKB_KEY_KP_Up => Some(Key::Up), -// keysyms::XKB_KEY_KP_Right => Some(Key::Right), -// keysyms::XKB_KEY_KP_Down => Some(Key::Down), -// // => Some(Key::OEM102), -// keysyms::XKB_KEY_period => Some(Key::Period), -// // => Some(Key::Playpause), -// keysyms::XKB_KEY_XF86PowerOff => Some(Key::Power), -// keysyms::XKB_KEY_XF86AudioPrev => Some(Key::PrevTrack), -// keysyms::XKB_KEY_Alt_R => Some(Key::RAlt), -// keysyms::XKB_KEY_bracketright => Some(Key::RBracket), -// keysyms::XKB_KEY_Control_R => Some(Key::RControl), -// keysyms::XKB_KEY_Shift_R => Some(Key::RShift), -// keysyms::XKB_KEY_Super_R => Some(Key::RWin), -// keysyms::XKB_KEY_semicolon => Some(Key::Semicolon), -// keysyms::XKB_KEY_slash => Some(Key::Slash), -// keysyms::XKB_KEY_XF86Sleep => Some(Key::Sleep), -// // => Some(Key::Stop), -// // => Some(Key::Sysrq), -// keysyms::XKB_KEY_Tab => Some(Key::Tab), -// keysyms::XKB_KEY_ISO_Left_Tab => Some(Key::Tab), -// keysyms::XKB_KEY_underscore => Some(Key::Underline), -// // => Some(Key::Unlabeled), -// keysyms::XKB_KEY_XF86AudioLowerVolume => Some(Key::VolumeDown), -// keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(Key::VolumeUp), -// // => Some(Key::Wake), -// // => Some(Key::Webback), -// // => Some(Key::WebFavorites), -// // => Some(Key::WebForward), -// // => Some(Key::WebHome), -// // => Some(Key::WebRefresh), -// // => Some(Key::WebSearch), -// // => Some(Key::WebStop), -// keysyms::XKB_KEY_yen => Some(Key::Yen), -// keysyms::XKB_KEY_XF86Copy => Some(Key::Copy), -// keysyms::XKB_KEY_XF86Paste => Some(Key::Paste), -// keysyms::XKB_KEY_XF86Cut => Some(Key::Cut), -// // Fallback. -// _ => None, -// } -// } + // keysyms::XKB_KEY_Multi_key => Some(Key::Compose), + // keysyms::XKB_KEY_caret => Some(Key::Caret), + + // // Keypad. + // keysyms::XKB_KEY_Num_Lock => Some(Key::Numlock), + // keysyms::XKB_KEY_KP_0 => Some(Key::Numpad0), + // keysyms::XKB_KEY_KP_1 => Some(Key::Numpad1), + // keysyms::XKB_KEY_KP_2 => Some(Key::Numpad2), + // keysyms::XKB_KEY_KP_3 => Some(Key::Numpad3), + // keysyms::XKB_KEY_KP_4 => Some(Key::Numpad4), + // keysyms::XKB_KEY_KP_5 => Some(Key::Numpad5), + // keysyms::XKB_KEY_KP_6 => Some(Key::Numpad6), + // keysyms::XKB_KEY_KP_7 => Some(Key::Numpad7), + // keysyms::XKB_KEY_KP_8 => Some(Key::Numpad8), + // keysyms::XKB_KEY_KP_9 => Some(Key::Numpad9), + // // Misc. + // // => Some(Key::AbntC1), + // // => Some(Key::AbntC2), + // keysyms::XKB_KEY_plus => Some(Key::Plus), + // keysyms::XKB_KEY_apostrophe => Some(Key::Apostrophe), + // // => Some(Key::Apps), + // keysyms::XKB_KEY_at => Some(Key::At), + // // => Some(Key::Ax), + // keysyms::XKB_KEY_backslash => Some(Key::Backslash), + // keysyms::XKB_KEY_XF86Calculator => Some(Key::Calculator), + // // => Some(Key::Capital), + // keysyms::XKB_KEY_colon => Some(Key::Colon), + // keysyms::XKB_KEY_comma => Some(Key::Comma), + // // => Some(Key::Convert), + // keysyms::XKB_KEY_equal => Some(Key::Equals), + // keysyms::XKB_KEY_grave => Some(Key::Grave), + // // => Some(Key::Kana), + // keysyms::XKB_KEY_Kanji => Some(Key::Kanji), + // keysyms::XKB_KEY_Alt_L => Some(Key::LAlt), + // keysyms::XKB_KEY_bracketleft => Some(Key::LBracket), + // keysyms::XKB_KEY_Control_L => Some(Key::LControl), + // keysyms::XKB_KEY_Shift_L => Some(Key::LShift), + // keysyms::XKB_KEY_Super_L => Some(Key::LWin), + // keysyms::XKB_KEY_XF86Mail => Some(Key::Mail), + // // => Some(Key::MediaSelect), + // // => Some(Key::MediaStop), + // keysyms::XKB_KEY_minus => Some(Key::Minus), + // keysyms::XKB_KEY_asterisk => Some(Key::Asterisk), + // keysyms::XKB_KEY_XF86AudioMute => Some(Key::Mute), + // // => Some(Key::MyComputer), + // keysyms::XKB_KEY_XF86AudioNext => Some(Key::NextTrack), + // // => Some(Key::NoConvert), + // keysyms::XKB_KEY_KP_Separator => Some(Key::NumpadComma), + // keysyms::XKB_KEY_KP_Enter => Some(Key::NumpadEnter), + // keysyms::XKB_KEY_KP_Equal => Some(Key::NumpadEquals), + // keysyms::XKB_KEY_KP_Add => Some(Key::NumpadAdd), + // keysyms::XKB_KEY_KP_Subtract => Some(Key::NumpadSubtract), + // keysyms::XKB_KEY_KP_Multiply => Some(Key::NumpadMultiply), + // keysyms::XKB_KEY_KP_Divide => Some(Key::NumpadDivide), + // keysyms::XKB_KEY_KP_Decimal => Some(Key::NumpadDecimal), + // keysyms::XKB_KEY_KP_Page_Up => Some(Key::PageUp), + // keysyms::XKB_KEY_KP_Page_Down => Some(Key::PageDown), + // keysyms::XKB_KEY_KP_Home => Some(Key::Home), + // keysyms::XKB_KEY_KP_End => Some(Key::End), + // keysyms::XKB_KEY_KP_Left => Some(Key::Left), + // keysyms::XKB_KEY_KP_Up => Some(Key::Up), + // keysyms::XKB_KEY_KP_Right => Some(Key::Right), + // keysyms::XKB_KEY_KP_Down => Some(Key::Down), + // // => Some(Key::OEM102), + // keysyms::XKB_KEY_period => Some(Key::Period), + // // => Some(Key::Playpause), + // keysyms::XKB_KEY_XF86PowerOff => Some(Key::Power), + // keysyms::XKB_KEY_XF86AudioPrev => Some(Key::PrevTrack), + // keysyms::XKB_KEY_Alt_R => Some(Key::RAlt), + // keysyms::XKB_KEY_bracketright => Some(Key::RBracket), + // keysyms::XKB_KEY_Control_R => Some(Key::RControl), + // keysyms::XKB_KEY_Shift_R => Some(Key::RShift), + // keysyms::XKB_KEY_Super_R => Some(Key::RWin), + // keysyms::XKB_KEY_semicolon => Some(Key::Semicolon), + // keysyms::XKB_KEY_slash => Some(Key::Slash), + // keysyms::XKB_KEY_XF86Sleep => Some(Key::Sleep), + // // => Some(Key::Stop), + // // => Some(Key::Sysrq), + // keysyms::XKB_KEY_Tab => Some(Key::Tab), + // keysyms::XKB_KEY_ISO_Left_Tab => Some(Key::Tab), + // keysyms::XKB_KEY_underscore => Some(Key::Underline), + // // => Some(Key::Unlabeled), + // keysyms::XKB_KEY_XF86AudioLowerVolume => Some(Key::VolumeDown), + // keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(Key::VolumeUp), + // // => Some(Key::Wake), + // // => Some(Key::Webback), + // // => Some(Key::WebFavorites), + // // => Some(Key::WebForward), + // // => Some(Key::WebHome), + // // => Some(Key::WebRefresh), + // // => Some(Key::WebSearch), + // // => Some(Key::WebStop), + // keysyms::XKB_KEY_yen => Some(Key::Yen), + // keysyms::XKB_KEY_XF86Copy => Some(Key::Copy), + // keysyms::XKB_KEY_XF86Paste => Some(Key::Paste), + // keysyms::XKB_KEY_XF86Cut => Some(Key::Cut), + // // Fallback. + _ => Key::Unidentified(NativeKeyCode::Unidentified), + } +} From 280eb7479ea1c5c96d7aa0aa0678081ac390fc20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Mon, 29 Mar 2021 01:49:30 +0200 Subject: [PATCH 03/58] Add some keysym mappings and move the keymap.rs file --- Cargo.toml | 1 + src/platform_impl/linux/common/keymap.rs | 685 ++++++++++++++++++ src/platform_impl/linux/common/mod.rs | 1 + src/platform_impl/linux/mod.rs | 3 + .../linux/wayland/seat/keyboard/handlers.rs | 3 +- .../linux/wayland/seat/keyboard/keymap.rs | 477 ------------ .../linux/wayland/seat/keyboard/mod.rs | 1 - 7 files changed, 692 insertions(+), 479 deletions(-) create mode 100644 src/platform_impl/linux/common/keymap.rs create mode 100644 src/platform_impl/linux/common/mod.rs delete mode 100644 src/platform_impl/linux/wayland/seat/keyboard/keymap.rs diff --git a/Cargo.toml b/Cargo.toml index f5a848bb9e..ec6a6ac680 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,6 +112,7 @@ x11-dl = { version = "2.18.5", optional = true } percent-encoding = { version = "2.0", optional = true } parking_lot = { version = "0.12.0", optional = true } libc = "0.2.64" +xkbcommon = "0.4.0" [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs new file mode 100644 index 0000000000..eeccf65a97 --- /dev/null +++ b/src/platform_impl/linux/common/keymap.rs @@ -0,0 +1,685 @@ +//! Convert Wayland keys to winit keys. + +use crate::keyboard::{Key, KeyCode, KeyLocation, NativeKeyCode}; + +// TODO: Do another pass on all of this + +pub fn rawkey_to_keycode(rawkey: u32) -> KeyCode { + // The keycode values are taken from linux/include/uapi/linux/input-event-codes.h, as + // libxkbcommon's documentation indicates that the keycode values we're getting from it are + // defined by the Linux kernel. If Winit programs end up being run on other Unix-likes which + // also use libxkbcommon, then I dearly hope the keycode values mean the same thing. + // + // Some of the keycodes are likely superfluous for our purposes, and some are ones which are + // difficult to test the correctness of, or discover the purpose of. Because of this, they've + // either been commented out here, or not included at all. + // + // TODO: There are probably a couple more unproblematic keycodes to map here. + match rawkey { + 0 => KeyCode::Unidentified(NativeKeyCode::XKB(0)), // TODO: Is `NativeKeyCode::Unidentified` better? + 1 => KeyCode::Escape, + 2 => KeyCode::Digit1, + 3 => KeyCode::Digit2, + 4 => KeyCode::Digit3, + 5 => KeyCode::Digit4, + 6 => KeyCode::Digit5, + 7 => KeyCode::Digit6, + 8 => KeyCode::Digit7, + 9 => KeyCode::Digit8, + 10 => KeyCode::Digit9, + 11 => KeyCode::Digit0, + 12 => KeyCode::Minus, + 13 => KeyCode::Equal, + 14 => KeyCode::Backspace, + 15 => KeyCode::Tab, + 16 => KeyCode::KeyQ, + 17 => KeyCode::KeyW, + 18 => KeyCode::KeyE, + 19 => KeyCode::KeyR, + 20 => KeyCode::KeyT, + 21 => KeyCode::KeyY, + 22 => KeyCode::KeyU, + 23 => KeyCode::KeyI, + 24 => KeyCode::KeyO, + 25 => KeyCode::KeyP, + 26 => KeyCode::BracketLeft, + 27 => KeyCode::BracketRight, + 28 => KeyCode::Enter, + 29 => KeyCode::ControlLeft, + 30 => KeyCode::KeyA, + 31 => KeyCode::KeyS, + 32 => KeyCode::KeyD, + 33 => KeyCode::KeyF, + 34 => KeyCode::KeyG, + 35 => KeyCode::KeyH, + 36 => KeyCode::KeyJ, + 37 => KeyCode::KeyK, + 38 => KeyCode::KeyL, + 39 => KeyCode::Semicolon, + 40 => KeyCode::Quote, + 41 => KeyCode::Backquote, + 42 => KeyCode::ShiftLeft, + 43 => KeyCode::Backslash, + 44 => KeyCode::KeyZ, + 45 => KeyCode::KeyX, + 46 => KeyCode::KeyC, + 47 => KeyCode::KeyV, + 48 => KeyCode::KeyB, + 49 => KeyCode::KeyN, + 50 => KeyCode::KeyM, + 51 => KeyCode::Comma, + 52 => KeyCode::Period, + 53 => KeyCode::Slash, + 54 => KeyCode::ShiftRight, + 55 => KeyCode::NumpadMultiply, + 56 => KeyCode::AltLeft, + 57 => KeyCode::Space, + 58 => KeyCode::CapsLock, + 59 => KeyCode::F1, + 60 => KeyCode::F2, + 61 => KeyCode::F3, + 62 => KeyCode::F4, + 63 => KeyCode::F5, + 64 => KeyCode::F6, + 65 => KeyCode::F7, + 66 => KeyCode::F8, + 67 => KeyCode::F9, + 68 => KeyCode::F10, + 69 => KeyCode::NumLock, + 70 => KeyCode::ScrollLock, + 71 => KeyCode::Numpad7, + 72 => KeyCode::Numpad8, + 73 => KeyCode::Numpad9, + 74 => KeyCode::NumpadSubtract, + 75 => KeyCode::Numpad4, + 76 => KeyCode::Numpad4, + 77 => KeyCode::Numpad6, + 78 => KeyCode::NumpadAdd, + 79 => KeyCode::Numpad1, + 80 => KeyCode::Numpad2, + 81 => KeyCode::Numpad3, + 82 => KeyCode::Numpad0, + 83 => KeyCode::NumpadDecimal, + 85 => KeyCode::Lang5, + 86 => KeyCode::IntlBackslash, + 87 => KeyCode::F11, + 88 => KeyCode::F12, + 89 => KeyCode::IntlRo, + 90 => KeyCode::Lang3, + 91 => KeyCode::Lang4, + 92 => KeyCode::Convert, + 93 => KeyCode::KanaMode, + 94 => KeyCode::NonConvert, + // 95 => KeyCode::KPJPCOMMA, + 96 => KeyCode::NumpadEnter, + 97 => KeyCode::ControlRight, + 98 => KeyCode::NumpadDivide, + 99 => KeyCode::PrintScreen, + 100 => KeyCode::AltRight, + // 101 => KeyCode::LINEFEED, + 102 => KeyCode::Home, + 103 => KeyCode::ArrowUp, + 104 => KeyCode::PageUp, + 105 => KeyCode::ArrowLeft, + 106 => KeyCode::ArrowRight, + 107 => KeyCode::End, + 108 => KeyCode::ArrowDown, + 109 => KeyCode::PageDown, + 110 => KeyCode::Insert, + 111 => KeyCode::Delete, + // 112 => KeyCode::MACRO, + 113 => KeyCode::AudioVolumeMute, + 114 => KeyCode::AudioVolumeDown, + 115 => KeyCode::AudioVolumeUp, + // 116 => KeyCode::POWER, + 117 => KeyCode::NumpadEqual, + // 118 => KeyCode::KPPLUSMINUS, + 119 => KeyCode::Pause, + // 120 => KeyCode::SCALE, + 121 => KeyCode::NumpadComma, + 122 => KeyCode::Lang1, + 123 => KeyCode::Lang2, + 124 => KeyCode::IntlYen, + 125 => KeyCode::SuperLeft, + 126 => KeyCode::SuperRight, + 127 => KeyCode::ContextMenu, + // 128 => KeyCode::STOP, + // 129 => KeyCode::AGAIN, + // 130 => KeyCode::PROPS, + // 131 => KeyCode::UNDO, + // 132 => KeyCode::FRONT, + // 133 => KeyCode::COPY, + // 134 => KeyCode::OPEN, + // 135 => KeyCode::PASTE, + // 136 => KeyCode::FIND, + // 137 => KeyCode::CUT, + // 138 => KeyCode::HELP, + // 139 => KeyCode::MENU, + // 140 => KeyCode::CALC, + // 141 => KeyCode::SETUP, + // 142 => KeyCode::SLEEP, + // 143 => KeyCode::WAKEUP, + // 144 => KeyCode::FILE, + // 145 => KeyCode::SENDFILE, + // 146 => KeyCode::DELETEFILE, + // 147 => KeyCode::XFER, + // 148 => KeyCode::PROG1, + // 149 => KeyCode::PROG2, + // 150 => KeyCode::WWW, + // 151 => KeyCode::MSDOS, + // 152 => KeyCode::COFFEE, + // 153 => KeyCode::ROTATE_DISPLAY, + // 154 => KeyCode::CYCLEWINDOWS, + // 155 => KeyCode::MAIL, + // 156 => KeyCode::BOOKMARKS, + // 157 => KeyCode::COMPUTER, + // 158 => KeyCode::BACK, + // 159 => KeyCode::FORWARD, + // 160 => KeyCode::CLOSECD, + // 161 => KeyCode::EJECTCD, + // 162 => KeyCode::EJECTCLOSECD, + 163 => KeyCode::MediaTrackNext, + 164 => KeyCode::MediaPlayPause, + 165 => KeyCode::MediaTrackPrevious, + 166 => KeyCode::MediaStop, + // 167 => KeyCode::RECORD, + // 168 => KeyCode::REWIND, + // 169 => KeyCode::PHONE, + // 170 => KeyCode::ISO, + // 171 => KeyCode::CONFIG, + // 172 => KeyCode::HOMEPAGE, + // 173 => KeyCode::REFRESH, + // 174 => KeyCode::EXIT, + // 175 => KeyCode::MOVE, + // 176 => KeyCode::EDIT, + // 177 => KeyCode::SCROLLUP, + // 178 => KeyCode::SCROLLDOWN, + // 179 => KeyCode::KPLEFTPAREN, + // 180 => KeyCode::KPRIGHTPAREN, + // 181 => KeyCode::NEW, + // 182 => KeyCode::REDO, + 183 => KeyCode::F13, + 184 => KeyCode::F14, + 185 => KeyCode::F15, + 186 => KeyCode::F16, + 187 => KeyCode::F17, + 188 => KeyCode::F18, + 189 => KeyCode::F19, + 190 => KeyCode::F20, + 191 => KeyCode::F21, + 192 => KeyCode::F22, + 193 => KeyCode::F23, + 194 => KeyCode::F24, + // 200 => KeyCode::PLAYCD, + // 201 => KeyCode::PAUSECD, + // 202 => KeyCode::PROG3, + // 203 => KeyCode::PROG4, + // 204 => KeyCode::DASHBOARD, + // 205 => KeyCode::SUSPEND, + // 206 => KeyCode::CLOSE, + // 207 => KeyCode::PLAY, + // 208 => KeyCode::FASTFORWARD, + // 209 => KeyCode::BASSBOOST, + // 210 => KeyCode::PRINT, + // 211 => KeyCode::HP, + // 212 => KeyCode::CAMERA, + // 213 => KeyCode::SOUND, + // 214 => KeyCode::QUESTION, + // 215 => KeyCode::EMAIL, + // 216 => KeyCode::CHAT, + // 217 => KeyCode::SEARCH, + // 218 => KeyCode::CONNECT, + // 219 => KeyCode::FINANCE, + // 220 => KeyCode::SPORT, + // 221 => KeyCode::SHOP, + // 222 => KeyCode::ALTERASE, + // 223 => KeyCode::CANCEL, + // 224 => KeyCode::BRIGHTNESSDOW, + // 225 => KeyCode::BRIGHTNESSU, + // 226 => KeyCode::MEDIA, + // 227 => KeyCode::SWITCHVIDEOMODE, + // 228 => KeyCode::KBDILLUMTOGGLE, + // 229 => KeyCode::KBDILLUMDOWN, + // 230 => KeyCode::KBDILLUMUP, + // 231 => KeyCode::SEND, + // 232 => KeyCode::REPLY, + // 233 => KeyCode::FORWARDMAIL, + // 234 => KeyCode::SAVE, + // 235 => KeyCode::DOCUMENTS, + // 236 => KeyCode::BATTERY, + // 237 => KeyCode::BLUETOOTH, + // 238 => KeyCode::WLAN, + // 239 => KeyCode::UWB, + 240 => KeyCode::Unidentified(NativeKeyCode::Unidentified), + // 241 => KeyCode::VIDEO_NEXT, + // 242 => KeyCode::VIDEO_PREV, + // 243 => KeyCode::BRIGHTNESS_CYCLE, + // 244 => KeyCode::BRIGHTNESS_AUTO, + // 245 => KeyCode::DISPLAY_OFF, + // 246 => KeyCode::WWAN, + // 247 => KeyCode::RFKILL, + // 248 => KeyCode::KEY_MICMUTE, + _ => KeyCode::Unidentified(NativeKeyCode::XKB(rawkey)), + } +} + +pub fn keysym_to_key(keysym: u32) -> Key<'static> { + use xkbcommon::xkb; + match keysym { + // TTY function keys + xkb::KEY_BackSpace => Key::Backspace, + xkb::KEY_Tab => Key::Tab, + // xkb::KEY_Linefeed => Key::Linefeed, + xkb::KEY_Clear => Key::Clear, + xkb::KEY_Return => Key::Enter, + // xkb::KEY_Pause => Key::Pause, + xkb::KEY_Scroll_Lock => Key::ScrollLock, + xkb::KEY_Sys_Req => Key::PrintScreen, + xkb::KEY_Escape => Key::Escape, + xkb::KEY_Delete => Key::Delete, + + // IME keys + xkb::KEY_Multi_key => Key::Compose, + xkb::KEY_Codeinput => Key::CodeInput, + xkb::KEY_SingleCandidate => Key::SingleCandidate, + xkb::KEY_MultipleCandidate => Key::AllCandidates, + xkb::KEY_PreviousCandidate => Key::PreviousCandidate, + + // Japanese keys + xkb::KEY_Kanji => Key::KanjiMode, + xkb::KEY_Muhenkan => Key::NonConvert, + xkb::KEY_Henkan_Mode => Key::Convert, + xkb::KEY_Romaji => Key::Romaji, + xkb::KEY_Hiragana => Key::Hiragana, + xkb::KEY_Hiragana_Katakana => Key::HiraganaKatakana, + xkb::KEY_Zenkaku => Key::Zenkaku, + xkb::KEY_Hankaku => Key::Hankaku, + xkb::KEY_Zenkaku_Hankaku => Key::ZenkakuHankaku, + // xkb::KEY_Touroku => Key::Touroku, + // xkb::KEY_Massyo => Key::Massyo, + xkb::KEY_Kana_Lock => Key::KanaMode, + // TODO: This seems a tad perverse, but I'm not really familiar with japanese keyboards. + // MDN documents this as a valid mapping, however. + // xkb::KEY_Kana_Shift => Key::KanaMode, + // TODO: Is this the correct mapping? + // xkb::KEY_Eisu_Shift => Key::Alphanumeric, + // xkb::KEY_Eisu_toggle => Key::Alphanumeric, + // NOTE: The next three items are aliases for values we've already mapped. + // xkb::KEY_Kanji_Bangou => Key::CodeInput, + // xkb::KEY_Zen_Koho => Key::AllCandidates, + // xkb::KEY_Mae_Koho => Key::PreviousCandidate, + + // Cursor control & motion + xkb::KEY_Home => Key::Home, + xkb::KEY_Left => Key::ArrowLeft, + xkb::KEY_Up => Key::ArrowUp, + xkb::KEY_Right => Key::ArrowRight, + xkb::KEY_Down => Key::ArrowDown, + // xkb::KEY_Prior => Key::Prior, + xkb::KEY_Page_Up => Key::PageUp, + // xkb::KEY_Next => Key::Next, + xkb::KEY_End => Key::End, + // xkb::KEY_Begin => Key::Begin, + + // Misc. functions + xkb::KEY_Select => Key::Select, + xkb::KEY_Print => Key::PrintScreen, + xkb::KEY_Execute => Key::Execute, + xkb::KEY_Insert => Key::Insert, + xkb::KEY_Undo => Key::Undo, + xkb::KEY_Redo => Key::Redo, + xkb::KEY_Menu => Key::ContextMenu, + xkb::KEY_Find => Key::Find, + xkb::KEY_Cancel => Key::Cancel, + xkb::KEY_Help => Key::Help, + xkb::KEY_Break => Key::Pause, + xkb::KEY_Mode_switch => Key::ModeChange, + // xkb::KEY_script_switch => Key::ModeChange, + xkb::KEY_Num_Lock => Key::NumLock, + + // Keypad keys + // xkb::KEY_KP_Space => Key::Character(" "), + xkb::KEY_KP_Tab => Key::Tab, + xkb::KEY_KP_Enter => Key::Enter, + xkb::KEY_KP_F1 => Key::F1, + xkb::KEY_KP_F2 => Key::F2, + xkb::KEY_KP_F3 => Key::F3, + xkb::KEY_KP_F4 => Key::F4, + xkb::KEY_KP_Home => Key::Home, + xkb::KEY_KP_Left => Key::ArrowLeft, + xkb::KEY_KP_Up => Key::ArrowLeft, + xkb::KEY_KP_Right => Key::ArrowRight, + xkb::KEY_KP_Down => Key::ArrowDown, + // xkb::KEY_KP_Prior => Key::Prior, + xkb::KEY_KP_Page_Up => Key::PageUp, + // xkb::KEY_KP_Next => Key::Next, + xkb::KEY_KP_Page_Down => Key::PageDown, + xkb::KEY_KP_End => Key::End, + // xkb::KEY_KP_Begin => Key::Begin, + xkb::KEY_KP_Insert => Key::Insert, + xkb::KEY_KP_Delete => Key::Delete, + // xkb::KEY_KP_Equal => Key::Equal, + // xkb::KEY_KP_Multiply => Key::Multiply, + // xkb::KEY_KP_Add => Key::Add, + // xkb::KEY_KP_Separator => Key::Separator, + // xkb::KEY_KP_Subtract => Key::Subtract, + // xkb::KEY_KP_Decimal => Key::Decimal, + // xkb::KEY_KP_Divide => Key::Divide, + + // xkb::KEY_KP_0 => Key::Character("0"), + // xkb::KEY_KP_1 => Key::Character("1"), + // xkb::KEY_KP_2 => Key::Character("2"), + // xkb::KEY_KP_3 => Key::Character("3"), + // xkb::KEY_KP_4 => Key::Character("4"), + // xkb::KEY_KP_5 => Key::Character("5"), + // xkb::KEY_KP_6 => Key::Character("6"), + // xkb::KEY_KP_7 => Key::Character("7"), + // xkb::KEY_KP_8 => Key::Character("8"), + // xkb::KEY_KP_9 => Key::Character("9"), + + // Function keys + xkb::KEY_F1 => Key::F1, + xkb::KEY_F2 => Key::F2, + xkb::KEY_F3 => Key::F3, + xkb::KEY_F4 => Key::F4, + xkb::KEY_F5 => Key::F5, + xkb::KEY_F6 => Key::F6, + xkb::KEY_F7 => Key::F7, + xkb::KEY_F8 => Key::F8, + xkb::KEY_F9 => Key::F9, + xkb::KEY_F10 => Key::F10, + xkb::KEY_F11 => Key::F11, + xkb::KEY_F12 => Key::F12, + xkb::KEY_F13 => Key::F13, + xkb::KEY_F14 => Key::F14, + xkb::KEY_F15 => Key::F15, + xkb::KEY_F16 => Key::F16, + xkb::KEY_F17 => Key::F17, + xkb::KEY_F18 => Key::F18, + xkb::KEY_F19 => Key::F19, + xkb::KEY_F20 => Key::F20, + xkb::KEY_F21 => Key::F21, + xkb::KEY_F22 => Key::F22, + xkb::KEY_F23 => Key::F23, + xkb::KEY_F24 => Key::F24, + xkb::KEY_F25 => Key::F25, + xkb::KEY_F26 => Key::F26, + xkb::KEY_F27 => Key::F27, + xkb::KEY_F28 => Key::F28, + xkb::KEY_F29 => Key::F29, + xkb::KEY_F30 => Key::F30, + xkb::KEY_F31 => Key::F31, + xkb::KEY_F32 => Key::F32, + xkb::KEY_F33 => Key::F33, + xkb::KEY_F34 => Key::F34, + xkb::KEY_F35 => Key::F35, + + // Modifiers + xkb::KEY_Shift_L => Key::Shift, + xkb::KEY_Shift_R => Key::Shift, + xkb::KEY_Control_L => Key::Control, + xkb::KEY_Control_R => Key::Control, + xkb::KEY_Caps_Lock => Key::CapsLock, + // xkb::KEY_Shift_Lock => Key::ShiftLock, + // + xkb::KEY_Meta_L => Key::Super, + xkb::KEY_Meta_R => Key::Super, + xkb::KEY_Alt_L => Key::Alt, + xkb::KEY_Alt_R => Key::Alt, + // NOTE: The key xkb calls "Meta" is called "Super" by Winit. + // xkb::KEY_Super_L => Key::Super, + // xkb::KEY_Super_R => Key::Super, + xkb::KEY_Hyper_L => Key::Hyper, + xkb::KEY_Hyper_R => Key::Hyper, + + // XKB function and modifier keys + // xkb::KEY_ISO_Lock => Key::IsoLock, + // xkb::KEY_ISO_Level2_Latch => Key::IsoLevel2Latch, + // NOTE: I'm not quite certain if mapping the next 3 values to AltGraph is correct. + // xkb::KEY_ISO_Level3_Shift => Key::AltGraph, + // xkb::KEY_ISO_Level3_Latch => Key::AltGraph, + // xkb::KEY_ISO_Level3_Lock => Key::AltGraph, + // xkb::KEY_ISO_Level5_Shift => Key::IsoLevel5Shift, + // xkb::KEY_ISO_Level5_Latch => Key::IsoLevel5Latch, + // xkb::KEY_ISO_Level5_Lock => Key::IsoLevel5Lock, + // xkb::KEY_ISO_Group_Shift => Key::IsoGroupShift, + // xkb::KEY_ISO_Group_Latch => Key::IsoGroupLatch, + // xkb::KEY_ISO_Group_Lock => Key::IsoGroupLock, + xkb::KEY_ISO_Next_Group => Key::GroupNext, + // xkb::KEY_ISO_Next_Group_Lock => Key::GroupNextLock, + xkb::KEY_ISO_Prev_Group => Key::GroupPrevious, + // xkb::KEY_ISO_Prev_Group_Lock => Key::GroupPreviousLock, + xkb::KEY_ISO_First_Group => Key::GroupFirst, + // xkb::KEY_ISO_First_Group_Lock => Key::GroupFirstLock, + xkb::KEY_ISO_Last_Group => Key::GroupLast, + // xkb::KEY_ISO_Last_Group_Lock => Key::GroupLastLock, + // + xkb::KEY_ISO_Left_Tab => Key::Tab, + // xkb::KEY_ISO_Move_Line_Up => Key::IsoMoveLineUp, + // xkb::KEY_ISO_Move_Line_Down => Key::IsoMoveLineDown, + // xkb::KEY_ISO_Partial_Line_Up => Key::IsoPartialLineUp, + // xkb::KEY_ISO_Partial_Line_Down => Key::IsoPartialLineDown, + // xkb::KEY_ISO_Partial_Space_Left => Key::IsoPartialSpaceLeft, + // xkb::KEY_ISO_Partial_Space_Right => Key::IsoPartialSpaceRight, + // xkb::KEY_ISO_Set_Margin_Left => Key::IsoSetMarginLeft, + // xkb::KEY_ISO_Set_Margin_Right => Key::IsoSetMarginRight, + // xkb::KEY_ISO_Release_Margin_Left => Key::IsoReleaseMarginLeft, + // xkb::KEY_ISO_Release_Margin_Right => Key::IsoReleaseMarginRight, + // xkb::KEY_ISO_Release_Both_Margins => Key::IsoReleaseBothMargins, + // xkb::KEY_ISO_Fast_Cursor_Left => Key::IsoFastCursorLeft, + // xkb::KEY_ISO_Fast_Cursor_Right => Key::IsoFastCursorRight, + // xkb::KEY_ISO_Fast_Cursor_Up => Key::IsoFastCursorUp, + // xkb::KEY_ISO_Fast_Cursor_Down => Key::IsoFastCursorDown, + // xkb::KEY_ISO_Continuous_Underline => Key::IsoContinuousUnderline, + // xkb::KEY_ISO_Discontinuous_Underline => Key::IsoDiscontinuousUnderline, + // xkb::KEY_ISO_Emphasize => Key::IsoEmphasize, + // xkb::KEY_ISO_Center_Object => Key::IsoCenterObject, + xkb::KEY_ISO_Enter => Key::Enter, + + // KEY_dead_grave..KEY_dead_currency + + // KEY_dead_lowline..KEY_dead_longsolidusoverlay + + // KEY_dead_a..KEY_dead_capital_schwa + + // KEY_dead_greek + + // KEY_First_Virtual_Screen..KEY_Terminate_Server + + // KEY_AccessX_Enable..KEY_AudibleBell_Enable + + // KEY_Pointer_Left..KEY_Pointer_Drag5 + + // KEY_Pointer_EnableKeys..KEY_Pointer_DfltBtnPrev + + // KEY_ch..KEY_C_H + + // 3270 terminal keys + // xkb::KEY_3270_Duplicate => Key::Duplicate, + // xkb::KEY_3270_FieldMark => Key::FieldMark, + // xkb::KEY_3270_Right2 => Key::Right2, + // xkb::KEY_3270_Left2 => Key::Left2, + // xkb::KEY_3270_BackTab => Key::BackTab, + xkb::KEY_3270_EraseEOF => Key::EraseEof, + // xkb::KEY_3270_EraseInput => Key::EraseInput, + // xkb::KEY_3270_Reset => Key::Reset, + // xkb::KEY_3270_Quit => Key::Quit, + // xkb::KEY_3270_PA1 => Key::Pa1, + // xkb::KEY_3270_PA2 => Key::Pa2, + // xkb::KEY_3270_PA3 => Key::Pa3, + // xkb::KEY_3270_Test => Key::Test, + xkb::KEY_3270_Attn => Key::Attn, + // xkb::KEY_3270_CursorBlink => Key::CursorBlink, + // xkb::KEY_3270_AltCursor => Key::AltCursor, + // xkb::KEY_3270_KeyClick => Key::KeyClick, + // xkb::KEY_3270_Jump => Key::Jump, + // xkb::KEY_3270_Ident => Key::Ident, + // xkb::KEY_3270_Rule => Key::Rule, + // xkb::KEY_3270_Copy => Key::Copy, + xkb::KEY_3270_Play => Key::Play, + // xkb::KEY_3270_Setup => Key::Setup, + // xkb::KEY_3270_Record => Key::Record, + // xkb::KEY_3270_ChangeScreen => Key::ChangeScreen, + // xkb::KEY_3270_DeleteWord => Key::DeleteWord, + xkb::KEY_3270_ExSelect => Key::ExSel, + xkb::KEY_3270_CursorSelect => Key::CrSel, + xkb::KEY_3270_PrintScreen => Key::PrintScreen, + xkb::KEY_3270_Enter => Key::Enter, + + xkb::KEY_space => Key::Space, + // KEY_exclam..KEY_Sinh_kunddaliya + + // XFree86 + // xkb::KEY_XF86ModeLock => Key::ModeLock, + + // XFree86 - Backlight controls + xkb::KEY_XF86MonBrightnessUp => Key::BrightnessUp, + xkb::KEY_XF86MonBrightnessDown => Key::BrightnessDown, + // xkb::KEY_XF86KbdLightOnOff => Key::LightOnOff, + // xkb::KEY_XF86KbdBrightnessUp => Key::KeyboardBrightnessUp, + // xkb::KEY_XF86KbdBrightnessDown => Key::KeyboardBrightnessDown, + + // XFree86 - "Internet" + xkb::KEY_XF86Standby => Key::Standby, + xkb::KEY_XF86AudioLowerVolume => Key::AudioVolumeDown, + xkb::KEY_XF86AudioRaiseVolume => Key::AudioVolumeUp, + xkb::KEY_XF86AudioPlay => Key::MediaPlay, + xkb::KEY_XF86AudioStop => Key::MediaStop, + xkb::KEY_XF86AudioPrev => Key::MediaTrackPrevious, + xkb::KEY_XF86AudioNext => Key::MediaTrackNext, + xkb::KEY_XF86HomePage => Key::BrowserHome, + xkb::KEY_XF86Mail => Key::LaunchMail, + // xkb::KEY_XF86Start => Key::Start, + xkb::KEY_XF86Search => Key::BrowserSearch, + xkb::KEY_XF86AudioRecord => Key::MediaRecord, + + // XFree86 - PDA + xkb::KEY_XF86Calculator => Key::LaunchApplication2, + // xkb::KEY_XF86Memo => Key::Memo, + // xkb::KEY_XF86ToDoList => Key::ToDoList, + xkb::KEY_XF86Calendar => Key::LaunchCalendar, + xkb::KEY_XF86PowerDown => Key::Power, + // xkb::KEY_XF86ContrastAdjust => Key::AdjustContrast, + // xkb::KEY_XF86RockerUp => Key::RockerUp, // TODO: Use Key::ArrowUp? + // xkb::KEY_XF86RockerDown => Key::RockerDown, // TODO: Use Key::ArrowDown? + // xkb::KEY_XF86RockerEnter => Key::RockerEnter, // TODO: Use Key::Enter? + + // XFree86 - More "Internet" + xkb::KEY_XF86Back => Key::BrowserBack, + xkb::KEY_XF86Forward => Key::BrowserForward, + // xkb::KEY_XF86Stop => Key::Stop, + xkb::KEY_XF86Refresh => Key::BrowserRefresh, + xkb::KEY_XF86PowerOff => Key::Power, + xkb::KEY_XF86WakeUp => Key::WakeUp, + xkb::KEY_XF86Eject => Key::Eject, + xkb::KEY_XF86ScreenSaver => Key::LaunchScreenSaver, + xkb::KEY_XF86WWW => Key::LaunchWebBrowser, + xkb::KEY_XF86Sleep => Key::Standby, + xkb::KEY_XF86Favorites => Key::BrowserFavorites, + xkb::KEY_XF86AudioPause => Key::MediaPause, + // xkb::KEY_XF86AudioMedia => Key::AudioMedia, + xkb::KEY_XF86MyComputer => Key::LaunchApplication1, + // xkb::KEY_XF86VendorHome => Key::VendorHome, + // xkb::KEY_XF86LightBulb => Key::LightBulb, + // xkb::KEY_XF86Shop => Key::BrowserShop, + // xkb::KEY_XF86History => Key::BrowserHistory, + // xkb::KEY_XF86OpenURL => Key::OpenUrl, + // xkb::KEY_XF86AddFavorite => Key::AddFavorite, + // xkb::KEY_XF86HotLinks => Key::HotLinks, + // xkb::KEY_XF86BrightnessAdjust => Key::BrightnessAdjust, + // xkb::KEY_XF86Finance => Key::BrowserFinance, + // xkb::KEY_XF86Community => Key::BrowserCommunity, + xkb::KEY_XF86AudioRewind => Key::MediaRewind, + // xkb::KEY_XF86BackForward => Key::???, + // KEY_XF86Launch0..KEY_XF86LaunchF + + // KEY_XF86ApplicationLeft..KEY_XF86CD + xkb::KEY_XF86Calculater => Key::LaunchApplication2, // This must be a typo, right? + // KEY_XF86Clear + xkb::KEY_XF86Close => Key::Close, + xkb::KEY_XF86Copy => Key::Copy, + xkb::KEY_XF86Cut => Key::Cut, + // KEY_XF86Display..KEY_XF86Documents + xkb::KEY_XF86Excel => Key::LaunchSpreadsheet, + // KEY_XF86Explorer..KEY_XF86iTouch + xkb::KEY_XF86LogOff => Key::LogOff, + // KEY_XF86Market..KEY_XF86MenuPB + xkb::KEY_XF86MySites => Key::BrowserFavorites, + xkb::KEY_XF86New => Key::New, + // KEY_XF86News..KEY_XF86OfficeHome + xkb::KEY_XF86Open => Key::Open, + // KEY_XF86Option + xkb::KEY_XF86Paste => Key::Paste, + xkb::KEY_XF86Phone => Key::LaunchPhone, + // KEY_XF86Q + xkb::KEY_XF86Reply => Key::MailReply, + xkb::KEY_XF86Reload => Key::BrowserRefresh, + // KEY_XF86RotateWindows..KEY_XF86RotationKB + xkb::KEY_XF86Save => Key::Save, + // KEY_XF86ScrollUp..KEY_XF86ScrollClick + xkb::KEY_XF86Send => Key::MailSend, + xkb::KEY_XF86Spell => Key::SpellCheck, + xkb::KEY_XF86SplitScreen => Key::SplitScreenToggle, + // KEY_XF86Support..KEY_XF86User2KB + xkb::KEY_XF86Video => Key::LaunchMediaPlayer, + // KEY_XF86WheelButton + xkb::KEY_XF86Word => Key::LaunchWordProcessor, + // KEY_XF86Xfer + xkb::KEY_XF86ZoomIn => Key::ZoomIn, + xkb::KEY_XF86ZoomOut => Key::ZoomOut, + + // KEY_XF86Away..KEY_XF86Messenger + xkb::KEY_XF86WebCam => Key::LaunchWebCam, + xkb::KEY_XF86MailForward => Key::MailForward, + // KEY_XF86Pictures + xkb::KEY_XF86Music => Key::LaunchMusicPlayer, + + // KEY_XF86Battery..KEY_XF86UWB + // + xkb::KEY_XF86AudioForward => Key::MediaFastForward, + // KEY_XF86AudioRepeat + xkb::KEY_XF86AudioRandomPlay => Key::RandomToggle, + xkb::KEY_XF86Subtitle => Key::Subtitle, + xkb::KEY_XF86AudioCycleTrack => Key::MediaAudioTrack, + // KEY_XF86CycleAngle..KEY_XF86Blue + // + xkb::KEY_XF86Suspend => Key::Standby, + xkb::KEY_XF86Hibernate => Key::Hibernate, + // KEY_XF86TouchpadToggle..KEY_XF86TouchpadOff + // + xkb::KEY_XF86AudioMute => Key::AudioVolumeMute, + + // KEY_XF86Switch_VT_1..KEY_XF86Switch_VT_12 + + // KEY_XF86Ungrab..KEY_XF86ClearGrab + xkb::KEY_XF86Next_VMode => Key::VideoModeNext, + // xkb::KEY_XF86Prev_VMode => Key::VideoModePrevious, + // KEY_XF86LogWindowTree..KEY_XF86LogGrabInfo + + // KEY_SunFA_Grave..KEY_SunFA_Cedilla + + // xkb::KEY_SunF36 => Key::F36 | Key::F11, + // xkb::KEY_SunF37 => Key::F37 | Key::F12, + + // xkb::KEY_SunSys_Req => Key::PrintScreen, + // The next couple of xkb (until KEY_SunStop) are already handled. + // KEY_SunPrint_Screen..KEY_SunPageDown + + // KEY_SunUndo..KEY_SunFront + xkb::KEY_SunCopy => Key::Copy, + xkb::KEY_SunOpen => Key::Open, + xkb::KEY_SunPaste => Key::Paste, + xkb::KEY_SunCut => Key::Cut, + + // KEY_SunPowerSwitch + xkb::KEY_SunAudioLowerVolume => Key::AudioVolumeDown, + xkb::KEY_SunAudioMute => Key::AudioVolumeMute, + xkb::KEY_SunAudioRaiseVolume => Key::AudioVolumeUp, + // KEY_SunVideoDegauss + xkb::KEY_SunVideoLowerBrightness => Key::BrightnessDown, + xkb::KEY_SunVideoRaiseBrightness => Key::BrightnessUp, + // KEY_SunPowerSwitchShift + // + _ => Key::Unidentified(NativeKeyCode::XKB(keysym)), + } +} diff --git a/src/platform_impl/linux/common/mod.rs b/src/platform_impl/linux/common/mod.rs new file mode 100644 index 0000000000..32030aff05 --- /dev/null +++ b/src/platform_impl/linux/common/mod.rs @@ -0,0 +1 @@ +pub mod keymap; diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 9b2ffcade6..ca8cc5c490 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -48,6 +48,9 @@ pub mod wayland; #[cfg(feature = "x11")] pub mod x11; +#[cfg(any(feature = "x11", feature = "wayland"))] +mod common; + #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct KeyEventExtra { pub text_with_all_modifers: Option<&'static str>, diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 47cbc984ad..91c1edf8cc 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -10,7 +10,8 @@ use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::{self, DeviceId}; use crate::platform_impl::KeyEventExtra; -use super::keymap; +// TODO: This is kind of terrible +use super::super::super::super::common::keymap; use super::KeyboardInner; #[inline] diff --git a/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs b/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs deleted file mode 100644 index ae48fc95cf..0000000000 --- a/src/platform_impl/linux/wayland/seat/keyboard/keymap.rs +++ /dev/null @@ -1,477 +0,0 @@ -// //! Convert Wayland keys to winit keys. - -use crate::keyboard::{Key, KeyCode, NativeKeyCode}; - -pub fn rawkey_to_keycode(rawkey: u32) -> KeyCode { - // keycodes are taken from linux/include/uapi/linux/input-event-codes.h - match rawkey { - 0 => todo!("What should be done in this case? Return `NativeKeyCode`, or perhaps `None`?"), - 1 => KeyCode::Escape, - 2 => KeyCode::Digit1, - 3 => KeyCode::Digit2, - 4 => KeyCode::Digit3, - 5 => KeyCode::Digit4, - 6 => KeyCode::Digit5, - 7 => KeyCode::Digit6, - 8 => KeyCode::Digit7, - 9 => KeyCode::Digit8, - 10 => KeyCode::Digit9, - 11 => KeyCode::Digit0, - 12 => KeyCode::Minus, - 13 => KeyCode::Equal, - 14 => KeyCode::Backspace, - 15 => KeyCode::Tab, - 16 => KeyCode::KeyQ, - 17 => KeyCode::KeyW, - 18 => KeyCode::KeyE, - 19 => KeyCode::KeyR, - 20 => KeyCode::KeyT, - 21 => KeyCode::KeyY, - 22 => KeyCode::KeyU, - 23 => KeyCode::KeyI, - 24 => KeyCode::KeyO, - 25 => KeyCode::KeyP, - 26 => KeyCode::BracketLeft, - 27 => KeyCode::BracketRight, - 28 => KeyCode::Enter, - 29 => KeyCode::ControlLeft, - 30 => KeyCode::KeyA, - 31 => KeyCode::KeyS, - 32 => KeyCode::KeyD, - 33 => KeyCode::KeyF, - 34 => KeyCode::KeyG, - 35 => KeyCode::KeyH, - 36 => KeyCode::KeyJ, - 37 => KeyCode::KeyK, - 38 => KeyCode::KeyL, - 39 => KeyCode::Semicolon, - 40 => KeyCode::Quote, - 41 => KeyCode::Backquote, - 42 => KeyCode::ShiftLeft, - 43 => KeyCode::Backslash, - 44 => KeyCode::KeyZ, - 45 => KeyCode::KeyX, - 46 => KeyCode::KeyC, - 47 => KeyCode::KeyV, - 48 => KeyCode::KeyB, - 49 => KeyCode::KeyN, - 50 => KeyCode::KeyM, - 51 => KeyCode::Comma, - 52 => KeyCode::Period, - 53 => KeyCode::Slash, - 54 => KeyCode::ShiftRight, - 55 => KeyCode::NumpadMultiply, - 56 => KeyCode::AltLeft, - 57 => KeyCode::Space, - 58 => KeyCode::CapsLock, - 59 => KeyCode::F1, - 60 => KeyCode::F2, - 61 => KeyCode::F3, - 62 => KeyCode::F4, - 63 => KeyCode::F5, - 64 => KeyCode::F6, - 65 => KeyCode::F7, - 66 => KeyCode::F8, - 67 => KeyCode::F9, - 68 => KeyCode::F10, - 69 => KeyCode::NumLock, - 70 => KeyCode::ScrollLock, - 71 => KeyCode::Numpad7, - 72 => KeyCode::Numpad8, - 73 => KeyCode::Numpad9, - 74 => KeyCode::NumpadSubtract, - 75 => KeyCode::Numpad4, - 76 => KeyCode::Numpad4, - 77 => KeyCode::Numpad6, - 78 => KeyCode::NumpadAdd, - 79 => KeyCode::Numpad1, - 80 => KeyCode::Numpad2, - 81 => KeyCode::Numpad3, - 82 => KeyCode::Numpad0, - 83 => KeyCode::NumpadDecimal, - 85 => KeyCode::Lang5, - 86 => KeyCode::IntlBackslash, // TODO: Verify. - 87 => KeyCode::F11, - 88 => KeyCode::F12, - 89 => KeyCode::IntlRo, - 90 => KeyCode::Lang3, - 91 => KeyCode::Lang4, - 92 => KeyCode::Convert, - 93 => KeyCode::KanaMode, - 94 => KeyCode::NonConvert, - // 95 => KeyCode::KPJPCOMMA, // TODO: What the heck is this supposed to be? - 96 => KeyCode::NumpadEnter, - 97 => KeyCode::ControlRight, - 98 => KeyCode::NumpadDivide, - 99 => KeyCode::PrintScreen, // TODO: Verify. - 100 => KeyCode::AltRight, - // 101 => KeyCode::LINEFEED, // TODO: What the heck is this supposed to be? - 102 => KeyCode::Home, - 103 => KeyCode::ArrowUp, - 104 => KeyCode::PageUp, - 105 => KeyCode::ArrowLeft, - 106 => KeyCode::ArrowRight, - 107 => KeyCode::End, - 108 => KeyCode::ArrowDown, - 109 => KeyCode::PageDown, - 110 => KeyCode::Insert, - 111 => KeyCode::Delete, - // 112 => KeyCode::MACRO, // TODO: What the heck is this supposed to be? - 113 => KeyCode::AudioVolumeMute, - 114 => KeyCode::AudioVolumeDown, - 115 => KeyCode::AudioVolumeUp, - // TODO: I have no idea if this should be mapped to `KeyCode::Power` - // Neither the Linux header or the uievents-code document disambigues this. - // 116 => KeyCode::POWER, - 117 => KeyCode::NumpadEqual, - // 118 => KeyCode::KPPLUSMINUS, // TODO: What the heck is this supposed to be? - 119 => KeyCode::Pause, - // 120 => KeyCode::SCALE, // TODO: What the heck is this supposed to be? - 121 => KeyCode::NumpadComma, - 122 => KeyCode::Lang1, - 123 => KeyCode::Lang2, - 124 => KeyCode::IntlYen, - 125 => KeyCode::SuperLeft, - 126 => KeyCode::SuperRight, - 127 => KeyCode::ContextMenu, - // 128 => KeyCode::STOP, - // 129 => KeyCode::AGAIN, - // 130 => KeyCode::PROPS, - // 131 => KeyCode::UNDO, - // 132 => KeyCode::FRONT, - // 133 => KeyCode::COPY, - // 134 => KeyCode::OPEN, - // 135 => KeyCode::PASTE, - // 136 => KeyCode::FIND, - // 137 => KeyCode::CUT, - // 138 => KeyCode::HELP, - // 139 => KeyCode::MENU, - // 140 => KeyCode::CALC, - // 141 => KeyCode::SETUP, - // 142 => KeyCode::SLEEP, - // 143 => KeyCode::WAKEUP, - // 144 => KeyCode::FILE, - // 145 => KeyCode::SENDFILE, - // 146 => KeyCode::DELETEFILE, - // 147 => KeyCode::XFER, - // 148 => KeyCode::PROG1, - // 149 => KeyCode::PROG2, - // 150 => KeyCode::WWW, - // 151 => KeyCode::MSDOS, - // 152 => KeyCode::COFFEE, - // 153 => KeyCode::ROTATE_DISPLAY, - // 154 => KeyCode::CYCLEWINDOWS, - // 155 => KeyCode::MAIL, - // 156 => KeyCode::BOOKMARKS, - // 157 => KeyCode::COMPUTER, - // 158 => KeyCode::BACK, - // 159 => KeyCode::FORWARD, - // 160 => KeyCode::CLOSECD, - // 161 => KeyCode::EJECTCD, - // 162 => KeyCode::EJECTCLOSECD, - 163 => KeyCode::MediaTrackNext, - 164 => KeyCode::MediaPlayPause, - 165 => KeyCode::MediaTrackPrevious, - 166 => KeyCode::MediaStop, - // 167 => KeyCode::RECORD, - // 168 => KeyCode::REWIND, - // 169 => KeyCode::PHONE, - // 170 => KeyCode::ISO, - // 171 => KeyCode::CONFIG, - // 172 => KeyCode::HOMEPAGE, - // 173 => KeyCode::REFRESH, - // 174 => KeyCode::EXIT, - // 175 => KeyCode::MOVE, - // 176 => KeyCode::EDIT, - // 177 => KeyCode::SCROLLUP, - // 178 => KeyCode::SCROLLDOWN, - // 179 => KeyCode::KPLEFTPAREN, - // 180 => KeyCode::KPRIGHTPAREN, - // 181 => KeyCode::NEW, - // 182 => KeyCode::REDO, - 183 => KeyCode::F13, - 184 => KeyCode::F14, - 185 => KeyCode::F15, - 186 => KeyCode::F16, - 187 => KeyCode::F17, - 188 => KeyCode::F18, - 189 => KeyCode::F19, - 190 => KeyCode::F20, - 191 => KeyCode::F21, - 192 => KeyCode::F22, - 193 => KeyCode::F23, - 194 => KeyCode::F24, - // 200 => KeyCode::PLAYCD, - // 201 => KeyCode::PAUSECD, - // 202 => KeyCode::PROG3, - // 203 => KeyCode::PROG4, - // 204 => KeyCode::DASHBOARD, - // 205 => KeyCode::SUSPEND, - // 206 => KeyCode::CLOSE, - // 207 => KeyCode::PLAY, - // 208 => KeyCode::FASTFORWARD, - // 209 => KeyCode::BASSBOOST, - // 210 => KeyCode::PRINT, - // 211 => KeyCode::HP, - // 212 => KeyCode::CAMERA, - // 213 => KeyCode::SOUND, - // 214 => KeyCode::QUESTION, - // 215 => KeyCode::EMAIL, - // 216 => KeyCode::CHAT, - // 217 => KeyCode::SEARCH, - // 218 => KeyCode::CONNECT, - // 219 => KeyCode::FINANCE, - // 220 => KeyCode::SPORT, - // 221 => KeyCode::SHOP, - // 222 => KeyCode::ALTERASE, - // 223 => KeyCode::CANCEL, - // 224 => KeyCode::BRIGHTNESSDOW, - // 225 => KeyCode::BRIGHTNESSU, - // 226 => KeyCode::MEDIA, - // 227 => KeyCode::SWITCHVIDEOMODE, - // 228 => KeyCode::KBDILLUMTOGGLE, - // 229 => KeyCode::KBDILLUMDOWN, - // 230 => KeyCode::KBDILLUMUP, - // 231 => KeyCode::SEND, - // 232 => KeyCode::REPLY, - // 233 => KeyCode::FORWARDMAIL, - // 234 => KeyCode::SAVE, - // 235 => KeyCode::DOCUMENTS, - // 236 => KeyCode::BATTERY, - // 237 => KeyCode::BLUETOOTH, - // 238 => KeyCode::WLAN, - // 239 => KeyCode::UWB, - 240 => KeyCode::Unidentified(NativeKeyCode::Unidentified), - // 241 => KeyCode::VIDEO_NEXT, - // 242 => KeyCode::VIDEO_PREV, - // 243 => KeyCode::BRIGHTNESS_CYCLE, - // 244 => KeyCode::BRIGHTNESS_AUTO, - _ => KeyCode::Unidentified(NativeKeyCode::XKB(rawkey)), - } -} - -pub fn keysym_to_key(keysym: u32) -> Key<'static> { - use sctk::seat::keyboard::keysyms; - match keysym { - // // Numbers. - // // keysyms::XKB_KEY_1 => Some(Key::Character("1")), - // // keysyms::XKB_KEY_2 => Some(Key::Character("2")), - // // keysyms::XKB_KEY_3 => Some(Key::Character("3")), - // // keysyms::XKB_KEY_4 => Some(Key::Character("4")), - // // keysyms::XKB_KEY_5 => Some(Key::Character("5")), - // // keysyms::XKB_KEY_6 => Some(Key::Character("6")), - // // keysyms::XKB_KEY_7 => Some(Key::Character("7")), - // // keysyms::XKB_KEY_8 => Some(Key::Character("8")), - // // keysyms::XKB_KEY_9 => Some(Key::Character("9")), - // // keysyms::XKB_KEY_0 => Some(Key::Character("0")), - // // Letters. - // // keysyms::XKB_KEY_A => Some(Key::Character("A")), - // // keysyms::XKB_KEY_a => Some(Key::Character("a")), - // // keysyms::XKB_KEY_B => Some(Key::Character("B")), - // // keysyms::XKB_KEY_b => Some(Key::Character("b")), - // // keysyms::XKB_KEY_C => Some(Key::Character("C")), - // // keysyms::XKB_KEY_c => Some(Key::Character("c")), - // // keysyms::XKB_KEY_D => Some(Key::Character("D")), - // // keysyms::XKB_KEY_d => Some(Key::Character("d")), - // // keysyms::XKB_KEY_E => Some(Key::Character("E")), - // // keysyms::XKB_KEY_e => Some(Key::Character("e")), - // // keysyms::XKB_KEY_F => Some(Key::Character("F")), - // // keysyms::XKB_KEY_f => Some(Key::Character("f")), - // // keysyms::XKB_KEY_G => Some(Key::Character("G")), - // // keysyms::XKB_KEY_g => Some(Key::Character("g")), - // // keysyms::XKB_KEY_H => Some(Key::Character("H")), - // // keysyms::XKB_KEY_h => Some(Key::Character("h")), - // // keysyms::XKB_KEY_I => Some(Key::Character("I")), - // // keysyms::XKB_KEY_i => Some(Key::Character("i")), - // // keysyms::XKB_KEY_J => Some(Key::Character("J")), - // // keysyms::XKB_KEY_j => Some(Key::Character("j")), - // // keysyms::XKB_KEY_K => Some(Key::Character("K")), - // // keysyms::XKB_KEY_k => Some(Key::Character("k")), - // // keysyms::XKB_KEY_L => Some(Key::Character("L")), - // // keysyms::XKB_KEY_l => Some(Key::Character("l")), - // // keysyms::XKB_KEY_M => Some(Key::Character("M")), - // // keysyms::XKB_KEY_m => Some(Key::Character("m")), - // // keysyms::XKB_KEY_N => Some(Key::Character("N")), - // // keysyms::XKB_KEY_n => Some(Key::Character("n")), - // // keysyms::XKB_KEY_O => Some(Key::Character("O")), - // // keysyms::XKB_KEY_o => Some(Key::Character("o")), - // // keysyms::XKB_KEY_P => Some(Key::Character("P")), - // // keysyms::XKB_KEY_p => Some(Key::Character("p")), - // // keysyms::XKB_KEY_Q => Some(Key::Character("Q")), - // // keysyms::XKB_KEY_q => Some(Key::Character("q")), - // // keysyms::XKB_KEY_R => Some(Key::Character("R")), - // // keysyms::XKB_KEY_r => Some(Key::Character("r")), - // // keysyms::XKB_KEY_S => Some(Key::Character("S")), - // // keysyms::XKB_KEY_s => Some(Key::Character("s")), - // // keysyms::XKB_KEY_T => Some(Key::Character("T")), - // // keysyms::XKB_KEY_t => Some(Key::Character("t")), - // // keysyms::XKB_KEY_U => Some(Key::Character("U")), - // // keysyms::XKB_KEY_u => Some(Key::Character("u")), - // // keysyms::XKB_KEY_V => Some(Key::Character("V")), - // // keysyms::XKB_KEY_v => Some(Key::Character("v")), - // // keysyms::XKB_KEY_W => Some(Key::Character("W")), - // // keysyms::XKB_KEY_w => Some(Key::Character("w")), - // // keysyms::XKB_KEY_X => Some(Key::Character("X")), - // // keysyms::XKB_KEY_x => Some(Key::Character("x")), - // // keysyms::XKB_KEY_Y => Some(Key::Character("Y")), - // // keysyms::XKB_KEY_y => Some(Key::Character("y")), - // // keysyms::XKB_KEY_Z => Some(Key::Character("Z")), - // // keysyms::XKB_KEY_z => Some(Key::Character("z")), - // // Escape. - // keysyms::XKB_KEY_Escape => Some(Key::Escape), - // // Function keys. - // keysyms::XKB_KEY_F1 => Some(Key::F1), - // keysyms::XKB_KEY_F2 => Some(Key::F2), - // keysyms::XKB_KEY_F3 => Some(Key::F3), - // keysyms::XKB_KEY_F4 => Some(Key::F4), - // keysyms::XKB_KEY_F5 => Some(Key::F5), - // keysyms::XKB_KEY_F6 => Some(Key::F6), - // keysyms::XKB_KEY_F7 => Some(Key::F7), - // keysyms::XKB_KEY_F8 => Some(Key::F8), - // keysyms::XKB_KEY_F9 => Some(Key::F9), - // keysyms::XKB_KEY_F10 => Some(Key::F10), - // keysyms::XKB_KEY_F11 => Some(Key::F11), - // keysyms::XKB_KEY_F12 => Some(Key::F12), - // keysyms::XKB_KEY_F13 => Some(Key::F13), - // keysyms::XKB_KEY_F14 => Some(Key::F14), - // keysyms::XKB_KEY_F15 => Some(Key::F15), - // keysyms::XKB_KEY_F16 => Some(Key::F16), - // keysyms::XKB_KEY_F17 => Some(Key::F17), - // keysyms::XKB_KEY_F18 => Some(Key::F18), - // keysyms::XKB_KEY_F19 => Some(Key::F19), - // keysyms::XKB_KEY_F20 => Some(Key::F20), - // keysyms::XKB_KEY_F21 => Some(Key::F21), - // keysyms::XKB_KEY_F22 => Some(Key::F22), - // keysyms::XKB_KEY_F23 => Some(Key::F23), - // keysyms::XKB_KEY_F24 => Some(Key::F24), - // keysyms::XKB_KEY_F25 => Some(Key::F25), - // keysyms::XKB_KEY_F26 => Some(Key::F26), - // keysyms::XKB_KEY_F27 => Some(Key::F27), - // keysyms::XKB_KEY_F28 => Some(Key::F28), - // keysyms::XKB_KEY_F29 => Some(Key::F29), - // keysyms::XKB_KEY_F30 => Some(Key::F30), - // keysyms::XKB_KEY_F31 => Some(Key::F31), - // keysyms::XKB_KEY_F32 => Some(Key::F32), - // keysyms::XKB_KEY_F33 => Some(Key::F33), - // keysyms::XKB_KEY_F34 => Some(Key::F34), - // keysyms::XKB_KEY_F35 => Some(Key::F35), - // // Flow control. - // keysyms::XKB_KEY_Print => Some(Key::PrintScreen), - // keysyms::XKB_KEY_Scroll_Lock => Some(Key::ScrollLock), - // keysyms::XKB_KEY_Pause => Some(Key::Pause), - // keysyms::XKB_KEY_Insert => Some(Key::Insert), - // keysyms::XKB_KEY_Home => Some(Key::Home), - // keysyms::XKB_KEY_Delete => Some(Key::Delete), - // keysyms::XKB_KEY_End => Some(Key::End), - // keysyms::XKB_KEY_Page_Down => Some(Key::PageDown), - // keysyms::XKB_KEY_Page_Up => Some(Key::PageUp), - // // Arrows. - // keysyms::XKB_KEY_Left => Some(Key::Left), - // keysyms::XKB_KEY_Up => Some(Key::Up), - // keysyms::XKB_KEY_Right => Some(Key::Right), - // keysyms::XKB_KEY_Down => Some(Key::Down), - - // keysyms::XKB_KEY_BackSpace => Some(Key::Back), - // keysyms::XKB_KEY_Return => Some(Key::Return), - // keysyms::XKB_KEY_space => Some(Key::Space), - - // keysyms::XKB_KEY_Multi_key => Some(Key::Compose), - // keysyms::XKB_KEY_caret => Some(Key::Caret), - - // // Keypad. - // keysyms::XKB_KEY_Num_Lock => Some(Key::Numlock), - // keysyms::XKB_KEY_KP_0 => Some(Key::Numpad0), - // keysyms::XKB_KEY_KP_1 => Some(Key::Numpad1), - // keysyms::XKB_KEY_KP_2 => Some(Key::Numpad2), - // keysyms::XKB_KEY_KP_3 => Some(Key::Numpad3), - // keysyms::XKB_KEY_KP_4 => Some(Key::Numpad4), - // keysyms::XKB_KEY_KP_5 => Some(Key::Numpad5), - // keysyms::XKB_KEY_KP_6 => Some(Key::Numpad6), - // keysyms::XKB_KEY_KP_7 => Some(Key::Numpad7), - // keysyms::XKB_KEY_KP_8 => Some(Key::Numpad8), - // keysyms::XKB_KEY_KP_9 => Some(Key::Numpad9), - // // Misc. - // // => Some(Key::AbntC1), - // // => Some(Key::AbntC2), - // keysyms::XKB_KEY_plus => Some(Key::Plus), - // keysyms::XKB_KEY_apostrophe => Some(Key::Apostrophe), - // // => Some(Key::Apps), - // keysyms::XKB_KEY_at => Some(Key::At), - // // => Some(Key::Ax), - // keysyms::XKB_KEY_backslash => Some(Key::Backslash), - // keysyms::XKB_KEY_XF86Calculator => Some(Key::Calculator), - // // => Some(Key::Capital), - // keysyms::XKB_KEY_colon => Some(Key::Colon), - // keysyms::XKB_KEY_comma => Some(Key::Comma), - // // => Some(Key::Convert), - // keysyms::XKB_KEY_equal => Some(Key::Equals), - // keysyms::XKB_KEY_grave => Some(Key::Grave), - // // => Some(Key::Kana), - // keysyms::XKB_KEY_Kanji => Some(Key::Kanji), - // keysyms::XKB_KEY_Alt_L => Some(Key::LAlt), - // keysyms::XKB_KEY_bracketleft => Some(Key::LBracket), - // keysyms::XKB_KEY_Control_L => Some(Key::LControl), - // keysyms::XKB_KEY_Shift_L => Some(Key::LShift), - // keysyms::XKB_KEY_Super_L => Some(Key::LWin), - // keysyms::XKB_KEY_XF86Mail => Some(Key::Mail), - // // => Some(Key::MediaSelect), - // // => Some(Key::MediaStop), - // keysyms::XKB_KEY_minus => Some(Key::Minus), - // keysyms::XKB_KEY_asterisk => Some(Key::Asterisk), - // keysyms::XKB_KEY_XF86AudioMute => Some(Key::Mute), - // // => Some(Key::MyComputer), - // keysyms::XKB_KEY_XF86AudioNext => Some(Key::NextTrack), - // // => Some(Key::NoConvert), - // keysyms::XKB_KEY_KP_Separator => Some(Key::NumpadComma), - // keysyms::XKB_KEY_KP_Enter => Some(Key::NumpadEnter), - // keysyms::XKB_KEY_KP_Equal => Some(Key::NumpadEquals), - // keysyms::XKB_KEY_KP_Add => Some(Key::NumpadAdd), - // keysyms::XKB_KEY_KP_Subtract => Some(Key::NumpadSubtract), - // keysyms::XKB_KEY_KP_Multiply => Some(Key::NumpadMultiply), - // keysyms::XKB_KEY_KP_Divide => Some(Key::NumpadDivide), - // keysyms::XKB_KEY_KP_Decimal => Some(Key::NumpadDecimal), - // keysyms::XKB_KEY_KP_Page_Up => Some(Key::PageUp), - // keysyms::XKB_KEY_KP_Page_Down => Some(Key::PageDown), - // keysyms::XKB_KEY_KP_Home => Some(Key::Home), - // keysyms::XKB_KEY_KP_End => Some(Key::End), - // keysyms::XKB_KEY_KP_Left => Some(Key::Left), - // keysyms::XKB_KEY_KP_Up => Some(Key::Up), - // keysyms::XKB_KEY_KP_Right => Some(Key::Right), - // keysyms::XKB_KEY_KP_Down => Some(Key::Down), - // // => Some(Key::OEM102), - // keysyms::XKB_KEY_period => Some(Key::Period), - // // => Some(Key::Playpause), - // keysyms::XKB_KEY_XF86PowerOff => Some(Key::Power), - // keysyms::XKB_KEY_XF86AudioPrev => Some(Key::PrevTrack), - // keysyms::XKB_KEY_Alt_R => Some(Key::RAlt), - // keysyms::XKB_KEY_bracketright => Some(Key::RBracket), - // keysyms::XKB_KEY_Control_R => Some(Key::RControl), - // keysyms::XKB_KEY_Shift_R => Some(Key::RShift), - // keysyms::XKB_KEY_Super_R => Some(Key::RWin), - // keysyms::XKB_KEY_semicolon => Some(Key::Semicolon), - // keysyms::XKB_KEY_slash => Some(Key::Slash), - // keysyms::XKB_KEY_XF86Sleep => Some(Key::Sleep), - // // => Some(Key::Stop), - // // => Some(Key::Sysrq), - // keysyms::XKB_KEY_Tab => Some(Key::Tab), - // keysyms::XKB_KEY_ISO_Left_Tab => Some(Key::Tab), - // keysyms::XKB_KEY_underscore => Some(Key::Underline), - // // => Some(Key::Unlabeled), - // keysyms::XKB_KEY_XF86AudioLowerVolume => Some(Key::VolumeDown), - // keysyms::XKB_KEY_XF86AudioRaiseVolume => Some(Key::VolumeUp), - // // => Some(Key::Wake), - // // => Some(Key::Webback), - // // => Some(Key::WebFavorites), - // // => Some(Key::WebForward), - // // => Some(Key::WebHome), - // // => Some(Key::WebRefresh), - // // => Some(Key::WebSearch), - // // => Some(Key::WebStop), - // keysyms::XKB_KEY_yen => Some(Key::Yen), - // keysyms::XKB_KEY_XF86Copy => Some(Key::Copy), - // keysyms::XKB_KEY_XF86Paste => Some(Key::Paste), - // keysyms::XKB_KEY_XF86Cut => Some(Key::Cut), - // // Fallback. - _ => Key::Unidentified(NativeKeyCode::Unidentified), - } -} diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index fb7973f452..b63fe8bd9c 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -16,7 +16,6 @@ use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::WindowId; mod handlers; -mod keymap; pub(crate) struct Keyboard { pub keyboard: WlKeyboard, From 2417022c395ca945c72e4ffeed6cb6218df72d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Mon, 29 Mar 2021 02:24:03 +0200 Subject: [PATCH 04/58] Add key location and some minor corrections Also add a `Meta` key (code) value. --- src/keyboard.rs | 6 ++ src/platform_impl/linux/common/keymap.rs | 71 ++++++++++++++++--- .../linux/wayland/seat/keyboard/handlers.rs | 13 ++-- 3 files changed, 76 insertions(+), 14 deletions(-) diff --git a/src/keyboard.rs b/src/keyboard.rs index 9e005b32e4..a63ef31a9a 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -536,6 +536,9 @@ pub enum KeyCode { AudioVolumeMute, AudioVolumeUp, WakeUp, + // Legacy modifier key. Also called "Super" in certain places. + Meta, + // Legacy modifier key. Hyper, Turbo, Abort, @@ -731,6 +734,9 @@ pub enum Key<'a> { /// The Symbol modifier key (used on some virtual keyboards). Symbol, SymbolLock, + // Legacy modifier key. Also called "Super" in certain places. + Meta, + // Legacy modifier key. Hyper, /// Used to enable "super" modifier function for interpreting concurrent or subsequent keyboard /// input. This key value is used for the "Windows Logo" key and the Apple `Command` or `⌘` key. diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index eeccf65a97..d3438f0ef9 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -315,9 +315,9 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { xkb::KEY_Up => Key::ArrowUp, xkb::KEY_Right => Key::ArrowRight, xkb::KEY_Down => Key::ArrowDown, - // xkb::KEY_Prior => Key::Prior, + // xkb::KEY_Prior => Key::PageUp, xkb::KEY_Page_Up => Key::PageUp, - // xkb::KEY_Next => Key::Next, + // xkb::KEY_Next => Key::PageDown, xkb::KEY_End => Key::End, // xkb::KEY_Begin => Key::Begin, @@ -350,9 +350,9 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { xkb::KEY_KP_Up => Key::ArrowLeft, xkb::KEY_KP_Right => Key::ArrowRight, xkb::KEY_KP_Down => Key::ArrowDown, - // xkb::KEY_KP_Prior => Key::Prior, + // xkb::KEY_KP_Prior => Key::PageUp, xkb::KEY_KP_Page_Up => Key::PageUp, - // xkb::KEY_KP_Next => Key::Next, + // xkb::KEY_KP_Next => Key::PageDown, xkb::KEY_KP_Page_Down => Key::PageDown, xkb::KEY_KP_End => Key::End, // xkb::KEY_KP_Begin => Key::Begin, @@ -421,14 +421,15 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { xkb::KEY_Control_R => Key::Control, xkb::KEY_Caps_Lock => Key::CapsLock, // xkb::KEY_Shift_Lock => Key::ShiftLock, - // + + // NOTE: The key xkb calls "Meta" is called "Super" by Winit, and vice versa. + // This is a tad confusing, but these keys have different names depending on who you ask. xkb::KEY_Meta_L => Key::Super, xkb::KEY_Meta_R => Key::Super, xkb::KEY_Alt_L => Key::Alt, xkb::KEY_Alt_R => Key::Alt, - // NOTE: The key xkb calls "Meta" is called "Super" by Winit. - // xkb::KEY_Super_L => Key::Super, - // xkb::KEY_Super_R => Key::Super, + xkb::KEY_Super_L => Key::Meta, + xkb::KEY_Super_R => Key::Meta, xkb::KEY_Hyper_L => Key::Hyper, xkb::KEY_Hyper_R => Key::Hyper, @@ -683,3 +684,57 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { _ => Key::Unidentified(NativeKeyCode::XKB(keysym)), } } + +pub fn keysym_location(keysym: u32) -> KeyLocation { + use xkbcommon::xkb; + match keysym { + xkb::KEY_Shift_L + | xkb::KEY_Control_L + | xkb::KEY_Meta_L + | xkb::KEY_Alt_L + | xkb::KEY_Super_L + | xkb::KEY_Hyper_L => KeyLocation::Left, + xkb::KEY_Shift_R + | xkb::KEY_Control_R + | xkb::KEY_Meta_R + | xkb::KEY_Alt_R + | xkb::KEY_Super_R + | xkb::KEY_Hyper_R => KeyLocation::Right, + xkb::KEY_KP_0 + | xkb::KEY_KP_1 + | xkb::KEY_KP_2 + | xkb::KEY_KP_3 + | xkb::KEY_KP_4 + | xkb::KEY_KP_5 + | xkb::KEY_KP_6 + | xkb::KEY_KP_7 + | xkb::KEY_KP_8 + | xkb::KEY_KP_9 + | xkb::KEY_KP_Space + | xkb::KEY_KP_Tab + | xkb::KEY_KP_Enter + | xkb::KEY_KP_F1 + | xkb::KEY_KP_F2 + | xkb::KEY_KP_F3 + | xkb::KEY_KP_F4 + | xkb::KEY_KP_Home + | xkb::KEY_KP_Left + | xkb::KEY_KP_Up + | xkb::KEY_KP_Right + | xkb::KEY_KP_Down + | xkb::KEY_KP_Page_Up + | xkb::KEY_KP_Page_Down + | xkb::KEY_KP_End + | xkb::KEY_KP_Begin + | xkb::KEY_KP_Insert + | xkb::KEY_KP_Delete + | xkb::KEY_KP_Equal + | xkb::KEY_KP_Multiply + | xkb::KEY_KP_Add + | xkb::KEY_KP_Separator + | xkb::KEY_KP_Subtract + | xkb::KEY_KP_Decimal + | xkb::KEY_KP_Divide => KeyLocation::Numpad, + _ => KeyLocation::Standard, + } +} diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 91c1edf8cc..268beb6fa3 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -5,13 +5,12 @@ use sctk::reexports::client::protocol::wl_keyboard::KeyState; use sctk::seat::keyboard::Event as KeyboardEvent; use crate::event::{ElementState, KeyEvent, WindowEvent}; -use crate::keyboard::{Key, KeyLocation, ModifiersState, NativeKeyCode}; +use crate::keyboard::{Key, ModifiersState, NativeKeyCode}; +use crate::platform_impl::platform::common::keymap; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::{self, DeviceId}; use crate::platform_impl::KeyEventExtra; -// TODO: This is kind of terrible -use super::super::super::super::common::keymap; use super::KeyboardInner; #[inline] @@ -73,6 +72,7 @@ pub(super) fn handle_keyboard( let physical_key = keymap::rawkey_to_keycode(rawkey); let logical_key = keymap::keysym_to_key(keysym); + let location = keymap::keysym_location(keysym); event_sink.push_window_event( WindowEvent::KeyboardInput { @@ -83,7 +83,7 @@ pub(super) fn handle_keyboard( physical_key, logical_key, text: None, - location: KeyLocation::Standard, + location, state, repeat: false, platform_specific: KeyEventExtra { @@ -120,6 +120,7 @@ pub(super) fn handle_keyboard( let physical_key = keymap::rawkey_to_keycode(rawkey); let logical_key = keymap::keysym_to_key(keysym); + let location = keymap::keysym_location(keysym); event_sink.push_window_event( WindowEvent::KeyboardInput { @@ -130,9 +131,9 @@ pub(super) fn handle_keyboard( physical_key, logical_key, text: None, - location: KeyLocation::Standard, + location, state: ElementState::Pressed, - repeat: false, + repeat: true, platform_specific: KeyEventExtra { key_without_modifiers: Key::Unidentified(NativeKeyCode::Unidentified), text_with_all_modifers: None, From a7445b1e7bc912eeb2479d83f4c9f3e39ae0e081 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Tue, 30 Mar 2021 00:12:38 +0200 Subject: [PATCH 05/58] Use xkbcommon-dl rather than xkbcommon --- Cargo.toml | 2 +- src/platform_impl/linux/common/keymap.rs | 826 +++++++++++------------ 2 files changed, 414 insertions(+), 414 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ec6a6ac680..66686274c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,7 +112,7 @@ x11-dl = { version = "2.18.5", optional = true } percent-encoding = { version = "2.0", optional = true } parking_lot = { version = "0.12.0", optional = true } libc = "0.2.64" -xkbcommon = "0.4.0" +xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "224646a" } [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index d3438f0ef9..3016851dd0 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -264,477 +264,477 @@ pub fn rawkey_to_keycode(rawkey: u32) -> KeyCode { } pub fn keysym_to_key(keysym: u32) -> Key<'static> { - use xkbcommon::xkb; + use xkbcommon_dl::keysyms; match keysym { // TTY function keys - xkb::KEY_BackSpace => Key::Backspace, - xkb::KEY_Tab => Key::Tab, - // xkb::KEY_Linefeed => Key::Linefeed, - xkb::KEY_Clear => Key::Clear, - xkb::KEY_Return => Key::Enter, - // xkb::KEY_Pause => Key::Pause, - xkb::KEY_Scroll_Lock => Key::ScrollLock, - xkb::KEY_Sys_Req => Key::PrintScreen, - xkb::KEY_Escape => Key::Escape, - xkb::KEY_Delete => Key::Delete, + keysyms::XKB_KEY_BackSpace => Key::Backspace, + keysyms::XKB_KEY_Tab => Key::Tab, + // keysyms::XKB_KEY_Linefeed => Key::Linefeed, + keysyms::XKB_KEY_Clear => Key::Clear, + keysyms::XKB_KEY_Return => Key::Enter, + // keysyms::XKB_KEY_Pause => Key::Pause, + keysyms::XKB_KEY_Scroll_Lock => Key::ScrollLock, + keysyms::XKB_KEY_Sys_Req => Key::PrintScreen, + keysyms::XKB_KEY_Escape => Key::Escape, + keysyms::XKB_KEY_Delete => Key::Delete, // IME keys - xkb::KEY_Multi_key => Key::Compose, - xkb::KEY_Codeinput => Key::CodeInput, - xkb::KEY_SingleCandidate => Key::SingleCandidate, - xkb::KEY_MultipleCandidate => Key::AllCandidates, - xkb::KEY_PreviousCandidate => Key::PreviousCandidate, + keysyms::XKB_KEY_Multi_key => Key::Compose, + keysyms::XKB_KEY_Codeinput => Key::CodeInput, + keysyms::XKB_KEY_SingleCandidate => Key::SingleCandidate, + keysyms::XKB_KEY_MultipleCandidate => Key::AllCandidates, + keysyms::XKB_KEY_PreviousCandidate => Key::PreviousCandidate, // Japanese keys - xkb::KEY_Kanji => Key::KanjiMode, - xkb::KEY_Muhenkan => Key::NonConvert, - xkb::KEY_Henkan_Mode => Key::Convert, - xkb::KEY_Romaji => Key::Romaji, - xkb::KEY_Hiragana => Key::Hiragana, - xkb::KEY_Hiragana_Katakana => Key::HiraganaKatakana, - xkb::KEY_Zenkaku => Key::Zenkaku, - xkb::KEY_Hankaku => Key::Hankaku, - xkb::KEY_Zenkaku_Hankaku => Key::ZenkakuHankaku, - // xkb::KEY_Touroku => Key::Touroku, - // xkb::KEY_Massyo => Key::Massyo, - xkb::KEY_Kana_Lock => Key::KanaMode, + keysyms::XKB_KEY_Kanji => Key::KanjiMode, + keysyms::XKB_KEY_Muhenkan => Key::NonConvert, + keysyms::XKB_KEY_Henkan_Mode => Key::Convert, + keysyms::XKB_KEY_Romaji => Key::Romaji, + keysyms::XKB_KEY_Hiragana => Key::Hiragana, + keysyms::XKB_KEY_Hiragana_Katakana => Key::HiraganaKatakana, + keysyms::XKB_KEY_Zenkaku => Key::Zenkaku, + keysyms::XKB_KEY_Hankaku => Key::Hankaku, + keysyms::XKB_KEY_Zenkaku_Hankaku => Key::ZenkakuHankaku, + // keysyms::XKB_KEY_Touroku => Key::Touroku, + // keysyms::XKB_KEY_Massyo => Key::Massyo, + keysyms::XKB_KEY_Kana_Lock => Key::KanaMode, // TODO: This seems a tad perverse, but I'm not really familiar with japanese keyboards. // MDN documents this as a valid mapping, however. - // xkb::KEY_Kana_Shift => Key::KanaMode, + // keysyms::XKB_KEY_Kana_Shift => Key::KanaMode, // TODO: Is this the correct mapping? - // xkb::KEY_Eisu_Shift => Key::Alphanumeric, - // xkb::KEY_Eisu_toggle => Key::Alphanumeric, + // keysyms::XKB_KEY_Eisu_Shift => Key::Alphanumeric, + // keysyms::XKB_KEY_Eisu_toggle => Key::Alphanumeric, // NOTE: The next three items are aliases for values we've already mapped. - // xkb::KEY_Kanji_Bangou => Key::CodeInput, - // xkb::KEY_Zen_Koho => Key::AllCandidates, - // xkb::KEY_Mae_Koho => Key::PreviousCandidate, + // keysyms::XKB_KEY_Kanji_Bangou => Key::CodeInput, + // keysyms::XKB_KEY_Zen_Koho => Key::AllCandidates, + // keysyms::XKB_KEY_Mae_Koho => Key::PreviousCandidate, // Cursor control & motion - xkb::KEY_Home => Key::Home, - xkb::KEY_Left => Key::ArrowLeft, - xkb::KEY_Up => Key::ArrowUp, - xkb::KEY_Right => Key::ArrowRight, - xkb::KEY_Down => Key::ArrowDown, - // xkb::KEY_Prior => Key::PageUp, - xkb::KEY_Page_Up => Key::PageUp, - // xkb::KEY_Next => Key::PageDown, - xkb::KEY_End => Key::End, - // xkb::KEY_Begin => Key::Begin, + keysyms::XKB_KEY_Home => Key::Home, + keysyms::XKB_KEY_Left => Key::ArrowLeft, + keysyms::XKB_KEY_Up => Key::ArrowUp, + keysyms::XKB_KEY_Right => Key::ArrowRight, + keysyms::XKB_KEY_Down => Key::ArrowDown, + // keysyms::XKB_KEY_Prior => Key::PageUp, + keysyms::XKB_KEY_Page_Up => Key::PageUp, + // keysyms::XKB_KEY_Next => Key::PageDown, + keysyms::XKB_KEY_End => Key::End, + // keysyms::XKB_KEY_Begin => Key::Begin, // Misc. functions - xkb::KEY_Select => Key::Select, - xkb::KEY_Print => Key::PrintScreen, - xkb::KEY_Execute => Key::Execute, - xkb::KEY_Insert => Key::Insert, - xkb::KEY_Undo => Key::Undo, - xkb::KEY_Redo => Key::Redo, - xkb::KEY_Menu => Key::ContextMenu, - xkb::KEY_Find => Key::Find, - xkb::KEY_Cancel => Key::Cancel, - xkb::KEY_Help => Key::Help, - xkb::KEY_Break => Key::Pause, - xkb::KEY_Mode_switch => Key::ModeChange, - // xkb::KEY_script_switch => Key::ModeChange, - xkb::KEY_Num_Lock => Key::NumLock, + keysyms::XKB_KEY_Select => Key::Select, + keysyms::XKB_KEY_Print => Key::PrintScreen, + keysyms::XKB_KEY_Execute => Key::Execute, + keysyms::XKB_KEY_Insert => Key::Insert, + keysyms::XKB_KEY_Undo => Key::Undo, + keysyms::XKB_KEY_Redo => Key::Redo, + keysyms::XKB_KEY_Menu => Key::ContextMenu, + keysyms::XKB_KEY_Find => Key::Find, + keysyms::XKB_KEY_Cancel => Key::Cancel, + keysyms::XKB_KEY_Help => Key::Help, + keysyms::XKB_KEY_Break => Key::Pause, + keysyms::XKB_KEY_Mode_switch => Key::ModeChange, + // keysyms::XKB_KEY_script_switch => Key::ModeChange, + keysyms::XKB_KEY_Num_Lock => Key::NumLock, // Keypad keys - // xkb::KEY_KP_Space => Key::Character(" "), - xkb::KEY_KP_Tab => Key::Tab, - xkb::KEY_KP_Enter => Key::Enter, - xkb::KEY_KP_F1 => Key::F1, - xkb::KEY_KP_F2 => Key::F2, - xkb::KEY_KP_F3 => Key::F3, - xkb::KEY_KP_F4 => Key::F4, - xkb::KEY_KP_Home => Key::Home, - xkb::KEY_KP_Left => Key::ArrowLeft, - xkb::KEY_KP_Up => Key::ArrowLeft, - xkb::KEY_KP_Right => Key::ArrowRight, - xkb::KEY_KP_Down => Key::ArrowDown, - // xkb::KEY_KP_Prior => Key::PageUp, - xkb::KEY_KP_Page_Up => Key::PageUp, - // xkb::KEY_KP_Next => Key::PageDown, - xkb::KEY_KP_Page_Down => Key::PageDown, - xkb::KEY_KP_End => Key::End, - // xkb::KEY_KP_Begin => Key::Begin, - xkb::KEY_KP_Insert => Key::Insert, - xkb::KEY_KP_Delete => Key::Delete, - // xkb::KEY_KP_Equal => Key::Equal, - // xkb::KEY_KP_Multiply => Key::Multiply, - // xkb::KEY_KP_Add => Key::Add, - // xkb::KEY_KP_Separator => Key::Separator, - // xkb::KEY_KP_Subtract => Key::Subtract, - // xkb::KEY_KP_Decimal => Key::Decimal, - // xkb::KEY_KP_Divide => Key::Divide, - - // xkb::KEY_KP_0 => Key::Character("0"), - // xkb::KEY_KP_1 => Key::Character("1"), - // xkb::KEY_KP_2 => Key::Character("2"), - // xkb::KEY_KP_3 => Key::Character("3"), - // xkb::KEY_KP_4 => Key::Character("4"), - // xkb::KEY_KP_5 => Key::Character("5"), - // xkb::KEY_KP_6 => Key::Character("6"), - // xkb::KEY_KP_7 => Key::Character("7"), - // xkb::KEY_KP_8 => Key::Character("8"), - // xkb::KEY_KP_9 => Key::Character("9"), + // keysyms::XKB_KEY_KP_Space => Key::Character(" "), + keysyms::XKB_KEY_KP_Tab => Key::Tab, + keysyms::XKB_KEY_KP_Enter => Key::Enter, + keysyms::XKB_KEY_KP_F1 => Key::F1, + keysyms::XKB_KEY_KP_F2 => Key::F2, + keysyms::XKB_KEY_KP_F3 => Key::F3, + keysyms::XKB_KEY_KP_F4 => Key::F4, + keysyms::XKB_KEY_KP_Home => Key::Home, + keysyms::XKB_KEY_KP_Left => Key::ArrowLeft, + keysyms::XKB_KEY_KP_Up => Key::ArrowLeft, + keysyms::XKB_KEY_KP_Right => Key::ArrowRight, + keysyms::XKB_KEY_KP_Down => Key::ArrowDown, + // keysyms::XKB_KEY_KP_Prior => Key::PageUp, + keysyms::XKB_KEY_KP_Page_Up => Key::PageUp, + // keysyms::XKB_KEY_KP_Next => Key::PageDown, + keysyms::XKB_KEY_KP_Page_Down => Key::PageDown, + keysyms::XKB_KEY_KP_End => Key::End, + // keysyms::XKB_KEY_KP_Begin => Key::Begin, + keysyms::XKB_KEY_KP_Insert => Key::Insert, + keysyms::XKB_KEY_KP_Delete => Key::Delete, + // keysyms::XKB_KEY_KP_Equal => Key::Equal, + // keysyms::XKB_KEY_KP_Multiply => Key::Multiply, + // keysyms::XKB_KEY_KP_Add => Key::Add, + // keysyms::XKB_KEY_KP_Separator => Key::Separator, + // keysyms::XKB_KEY_KP_Subtract => Key::Subtract, + // keysyms::XKB_KEY_KP_Decimal => Key::Decimal, + // keysyms::XKB_KEY_KP_Divide => Key::Divide, + + // keysyms::XKB_KEY_KP_0 => Key::Character("0"), + // keysyms::XKB_KEY_KP_1 => Key::Character("1"), + // keysyms::XKB_KEY_KP_2 => Key::Character("2"), + // keysyms::XKB_KEY_KP_3 => Key::Character("3"), + // keysyms::XKB_KEY_KP_4 => Key::Character("4"), + // keysyms::XKB_KEY_KP_5 => Key::Character("5"), + // keysyms::XKB_KEY_KP_6 => Key::Character("6"), + // keysyms::XKB_KEY_KP_7 => Key::Character("7"), + // keysyms::XKB_KEY_KP_8 => Key::Character("8"), + // keysyms::XKB_KEY_KP_9 => Key::Character("9"), // Function keys - xkb::KEY_F1 => Key::F1, - xkb::KEY_F2 => Key::F2, - xkb::KEY_F3 => Key::F3, - xkb::KEY_F4 => Key::F4, - xkb::KEY_F5 => Key::F5, - xkb::KEY_F6 => Key::F6, - xkb::KEY_F7 => Key::F7, - xkb::KEY_F8 => Key::F8, - xkb::KEY_F9 => Key::F9, - xkb::KEY_F10 => Key::F10, - xkb::KEY_F11 => Key::F11, - xkb::KEY_F12 => Key::F12, - xkb::KEY_F13 => Key::F13, - xkb::KEY_F14 => Key::F14, - xkb::KEY_F15 => Key::F15, - xkb::KEY_F16 => Key::F16, - xkb::KEY_F17 => Key::F17, - xkb::KEY_F18 => Key::F18, - xkb::KEY_F19 => Key::F19, - xkb::KEY_F20 => Key::F20, - xkb::KEY_F21 => Key::F21, - xkb::KEY_F22 => Key::F22, - xkb::KEY_F23 => Key::F23, - xkb::KEY_F24 => Key::F24, - xkb::KEY_F25 => Key::F25, - xkb::KEY_F26 => Key::F26, - xkb::KEY_F27 => Key::F27, - xkb::KEY_F28 => Key::F28, - xkb::KEY_F29 => Key::F29, - xkb::KEY_F30 => Key::F30, - xkb::KEY_F31 => Key::F31, - xkb::KEY_F32 => Key::F32, - xkb::KEY_F33 => Key::F33, - xkb::KEY_F34 => Key::F34, - xkb::KEY_F35 => Key::F35, + keysyms::XKB_KEY_F1 => Key::F1, + keysyms::XKB_KEY_F2 => Key::F2, + keysyms::XKB_KEY_F3 => Key::F3, + keysyms::XKB_KEY_F4 => Key::F4, + keysyms::XKB_KEY_F5 => Key::F5, + keysyms::XKB_KEY_F6 => Key::F6, + keysyms::XKB_KEY_F7 => Key::F7, + keysyms::XKB_KEY_F8 => Key::F8, + keysyms::XKB_KEY_F9 => Key::F9, + keysyms::XKB_KEY_F10 => Key::F10, + keysyms::XKB_KEY_F11 => Key::F11, + keysyms::XKB_KEY_F12 => Key::F12, + keysyms::XKB_KEY_F13 => Key::F13, + keysyms::XKB_KEY_F14 => Key::F14, + keysyms::XKB_KEY_F15 => Key::F15, + keysyms::XKB_KEY_F16 => Key::F16, + keysyms::XKB_KEY_F17 => Key::F17, + keysyms::XKB_KEY_F18 => Key::F18, + keysyms::XKB_KEY_F19 => Key::F19, + keysyms::XKB_KEY_F20 => Key::F20, + keysyms::XKB_KEY_F21 => Key::F21, + keysyms::XKB_KEY_F22 => Key::F22, + keysyms::XKB_KEY_F23 => Key::F23, + keysyms::XKB_KEY_F24 => Key::F24, + keysyms::XKB_KEY_F25 => Key::F25, + keysyms::XKB_KEY_F26 => Key::F26, + keysyms::XKB_KEY_F27 => Key::F27, + keysyms::XKB_KEY_F28 => Key::F28, + keysyms::XKB_KEY_F29 => Key::F29, + keysyms::XKB_KEY_F30 => Key::F30, + keysyms::XKB_KEY_F31 => Key::F31, + keysyms::XKB_KEY_F32 => Key::F32, + keysyms::XKB_KEY_F33 => Key::F33, + keysyms::XKB_KEY_F34 => Key::F34, + keysyms::XKB_KEY_F35 => Key::F35, // Modifiers - xkb::KEY_Shift_L => Key::Shift, - xkb::KEY_Shift_R => Key::Shift, - xkb::KEY_Control_L => Key::Control, - xkb::KEY_Control_R => Key::Control, - xkb::KEY_Caps_Lock => Key::CapsLock, - // xkb::KEY_Shift_Lock => Key::ShiftLock, + keysyms::XKB_KEY_Shift_L => Key::Shift, + keysyms::XKB_KEY_Shift_R => Key::Shift, + keysyms::XKB_KEY_Control_L => Key::Control, + keysyms::XKB_KEY_Control_R => Key::Control, + keysyms::XKB_KEY_Caps_Lock => Key::CapsLock, + // keysyms::XKB_KEY_Shift_Lock => Key::ShiftLock, // NOTE: The key xkb calls "Meta" is called "Super" by Winit, and vice versa. // This is a tad confusing, but these keys have different names depending on who you ask. - xkb::KEY_Meta_L => Key::Super, - xkb::KEY_Meta_R => Key::Super, - xkb::KEY_Alt_L => Key::Alt, - xkb::KEY_Alt_R => Key::Alt, - xkb::KEY_Super_L => Key::Meta, - xkb::KEY_Super_R => Key::Meta, - xkb::KEY_Hyper_L => Key::Hyper, - xkb::KEY_Hyper_R => Key::Hyper, + keysyms::XKB_KEY_Meta_L => Key::Super, + keysyms::XKB_KEY_Meta_R => Key::Super, + keysyms::XKB_KEY_Alt_L => Key::Alt, + keysyms::XKB_KEY_Alt_R => Key::Alt, + keysyms::XKB_KEY_Super_L => Key::Meta, + keysyms::XKB_KEY_Super_R => Key::Meta, + keysyms::XKB_KEY_Hyper_L => Key::Hyper, + keysyms::XKB_KEY_Hyper_R => Key::Hyper, // XKB function and modifier keys - // xkb::KEY_ISO_Lock => Key::IsoLock, - // xkb::KEY_ISO_Level2_Latch => Key::IsoLevel2Latch, + // keysyms::XKB_KEY_ISO_Lock => Key::IsoLock, + // keysyms::XKB_KEY_ISO_Level2_Latch => Key::IsoLevel2Latch, // NOTE: I'm not quite certain if mapping the next 3 values to AltGraph is correct. - // xkb::KEY_ISO_Level3_Shift => Key::AltGraph, - // xkb::KEY_ISO_Level3_Latch => Key::AltGraph, - // xkb::KEY_ISO_Level3_Lock => Key::AltGraph, - // xkb::KEY_ISO_Level5_Shift => Key::IsoLevel5Shift, - // xkb::KEY_ISO_Level5_Latch => Key::IsoLevel5Latch, - // xkb::KEY_ISO_Level5_Lock => Key::IsoLevel5Lock, - // xkb::KEY_ISO_Group_Shift => Key::IsoGroupShift, - // xkb::KEY_ISO_Group_Latch => Key::IsoGroupLatch, - // xkb::KEY_ISO_Group_Lock => Key::IsoGroupLock, - xkb::KEY_ISO_Next_Group => Key::GroupNext, - // xkb::KEY_ISO_Next_Group_Lock => Key::GroupNextLock, - xkb::KEY_ISO_Prev_Group => Key::GroupPrevious, - // xkb::KEY_ISO_Prev_Group_Lock => Key::GroupPreviousLock, - xkb::KEY_ISO_First_Group => Key::GroupFirst, - // xkb::KEY_ISO_First_Group_Lock => Key::GroupFirstLock, - xkb::KEY_ISO_Last_Group => Key::GroupLast, - // xkb::KEY_ISO_Last_Group_Lock => Key::GroupLastLock, + // keysyms::XKB_KEY_ISO_Level3_Shift => Key::AltGraph, + // keysyms::XKB_KEY_ISO_Level3_Latch => Key::AltGraph, + // keysyms::XKB_KEY_ISO_Level3_Lock => Key::AltGraph, + // keysyms::XKB_KEY_ISO_Level5_Shift => Key::IsoLevel5Shift, + // keysyms::XKB_KEY_ISO_Level5_Latch => Key::IsoLevel5Latch, + // keysyms::XKB_KEY_ISO_Level5_Lock => Key::IsoLevel5Lock, + // keysyms::XKB_KEY_ISO_Group_Shift => Key::IsoGroupShift, + // keysyms::XKB_KEY_ISO_Group_Latch => Key::IsoGroupLatch, + // keysyms::XKB_KEY_ISO_Group_Lock => Key::IsoGroupLock, + keysyms::XKB_KEY_ISO_Next_Group => Key::GroupNext, + // keysyms::XKB_KEY_ISO_Next_Group_Lock => Key::GroupNextLock, + keysyms::XKB_KEY_ISO_Prev_Group => Key::GroupPrevious, + // keysyms::XKB_KEY_ISO_Prev_Group_Lock => Key::GroupPreviousLock, + keysyms::XKB_KEY_ISO_First_Group => Key::GroupFirst, + // keysyms::XKB_KEY_ISO_First_Group_Lock => Key::GroupFirstLock, + keysyms::XKB_KEY_ISO_Last_Group => Key::GroupLast, + // keysyms::XKB_KEY_ISO_Last_Group_Lock => Key::GroupLastLock, // - xkb::KEY_ISO_Left_Tab => Key::Tab, - // xkb::KEY_ISO_Move_Line_Up => Key::IsoMoveLineUp, - // xkb::KEY_ISO_Move_Line_Down => Key::IsoMoveLineDown, - // xkb::KEY_ISO_Partial_Line_Up => Key::IsoPartialLineUp, - // xkb::KEY_ISO_Partial_Line_Down => Key::IsoPartialLineDown, - // xkb::KEY_ISO_Partial_Space_Left => Key::IsoPartialSpaceLeft, - // xkb::KEY_ISO_Partial_Space_Right => Key::IsoPartialSpaceRight, - // xkb::KEY_ISO_Set_Margin_Left => Key::IsoSetMarginLeft, - // xkb::KEY_ISO_Set_Margin_Right => Key::IsoSetMarginRight, - // xkb::KEY_ISO_Release_Margin_Left => Key::IsoReleaseMarginLeft, - // xkb::KEY_ISO_Release_Margin_Right => Key::IsoReleaseMarginRight, - // xkb::KEY_ISO_Release_Both_Margins => Key::IsoReleaseBothMargins, - // xkb::KEY_ISO_Fast_Cursor_Left => Key::IsoFastCursorLeft, - // xkb::KEY_ISO_Fast_Cursor_Right => Key::IsoFastCursorRight, - // xkb::KEY_ISO_Fast_Cursor_Up => Key::IsoFastCursorUp, - // xkb::KEY_ISO_Fast_Cursor_Down => Key::IsoFastCursorDown, - // xkb::KEY_ISO_Continuous_Underline => Key::IsoContinuousUnderline, - // xkb::KEY_ISO_Discontinuous_Underline => Key::IsoDiscontinuousUnderline, - // xkb::KEY_ISO_Emphasize => Key::IsoEmphasize, - // xkb::KEY_ISO_Center_Object => Key::IsoCenterObject, - xkb::KEY_ISO_Enter => Key::Enter, + keysyms::XKB_KEY_ISO_Left_Tab => Key::Tab, + // keysyms::XKB_KEY_ISO_Move_Line_Up => Key::IsoMoveLineUp, + // keysyms::XKB_KEY_ISO_Move_Line_Down => Key::IsoMoveLineDown, + // keysyms::XKB_KEY_ISO_Partial_Line_Up => Key::IsoPartialLineUp, + // keysyms::XKB_KEY_ISO_Partial_Line_Down => Key::IsoPartialLineDown, + // keysyms::XKB_KEY_ISO_Partial_Space_Left => Key::IsoPartialSpaceLeft, + // keysyms::XKB_KEY_ISO_Partial_Space_Right => Key::IsoPartialSpaceRight, + // keysyms::XKB_KEY_ISO_Set_Margin_Left => Key::IsoSetMarginLeft, + // keysyms::XKB_KEY_ISO_Set_Margin_Right => Key::IsoSetMarginRight, + // keysyms::XKB_KEY_ISO_Release_Margin_Left => Key::IsoReleaseMarginLeft, + // keysyms::XKB_KEY_ISO_Release_Margin_Right => Key::IsoReleaseMarginRight, + // keysyms::XKB_KEY_ISO_Release_Both_Margins => Key::IsoReleaseBothMargins, + // keysyms::XKB_KEY_ISO_Fast_Cursor_Left => Key::IsoFastCursorLeft, + // keysyms::XKB_KEY_ISO_Fast_Cursor_Right => Key::IsoFastCursorRight, + // keysyms::XKB_KEY_ISO_Fast_Cursor_Up => Key::IsoFastCursorUp, + // keysyms::XKB_KEY_ISO_Fast_Cursor_Down => Key::IsoFastCursorDown, + // keysyms::XKB_KEY_ISO_Continuous_Underline => Key::IsoContinuousUnderline, + // keysyms::XKB_KEY_ISO_Discontinuous_Underline => Key::IsoDiscontinuousUnderline, + // keysyms::XKB_KEY_ISO_Emphasize => Key::IsoEmphasize, + // keysyms::XKB_KEY_ISO_Center_Object => Key::IsoCenterObject, + keysyms::XKB_KEY_ISO_Enter => Key::Enter, - // KEY_dead_grave..KEY_dead_currency + // XKB_KEY_dead_grave..XKB_KEY_dead_currency - // KEY_dead_lowline..KEY_dead_longsolidusoverlay + // XKB_KEY_dead_lowline..XKB_KEY_dead_longsolidusoverlay - // KEY_dead_a..KEY_dead_capital_schwa + // XKB_KEY_dead_a..XKB_KEY_dead_capital_schwa - // KEY_dead_greek + // XKB_KEY_dead_greek - // KEY_First_Virtual_Screen..KEY_Terminate_Server + // XKB_KEY_First_Virtual_Screen..XKB_KEY_Terminate_Server - // KEY_AccessX_Enable..KEY_AudibleBell_Enable + // XKB_KEY_AccessX_Enable..XKB_KEY_AudibleBell_Enable - // KEY_Pointer_Left..KEY_Pointer_Drag5 + // XKB_KEY_Pointer_Left..XKB_KEY_Pointer_Drag5 - // KEY_Pointer_EnableKeys..KEY_Pointer_DfltBtnPrev + // XKB_KEY_Pointer_EnableKeys..XKB_KEY_Pointer_DfltBtnPrev - // KEY_ch..KEY_C_H + // XKB_KEY_ch..XKB_KEY_C_H // 3270 terminal keys - // xkb::KEY_3270_Duplicate => Key::Duplicate, - // xkb::KEY_3270_FieldMark => Key::FieldMark, - // xkb::KEY_3270_Right2 => Key::Right2, - // xkb::KEY_3270_Left2 => Key::Left2, - // xkb::KEY_3270_BackTab => Key::BackTab, - xkb::KEY_3270_EraseEOF => Key::EraseEof, - // xkb::KEY_3270_EraseInput => Key::EraseInput, - // xkb::KEY_3270_Reset => Key::Reset, - // xkb::KEY_3270_Quit => Key::Quit, - // xkb::KEY_3270_PA1 => Key::Pa1, - // xkb::KEY_3270_PA2 => Key::Pa2, - // xkb::KEY_3270_PA3 => Key::Pa3, - // xkb::KEY_3270_Test => Key::Test, - xkb::KEY_3270_Attn => Key::Attn, - // xkb::KEY_3270_CursorBlink => Key::CursorBlink, - // xkb::KEY_3270_AltCursor => Key::AltCursor, - // xkb::KEY_3270_KeyClick => Key::KeyClick, - // xkb::KEY_3270_Jump => Key::Jump, - // xkb::KEY_3270_Ident => Key::Ident, - // xkb::KEY_3270_Rule => Key::Rule, - // xkb::KEY_3270_Copy => Key::Copy, - xkb::KEY_3270_Play => Key::Play, - // xkb::KEY_3270_Setup => Key::Setup, - // xkb::KEY_3270_Record => Key::Record, - // xkb::KEY_3270_ChangeScreen => Key::ChangeScreen, - // xkb::KEY_3270_DeleteWord => Key::DeleteWord, - xkb::KEY_3270_ExSelect => Key::ExSel, - xkb::KEY_3270_CursorSelect => Key::CrSel, - xkb::KEY_3270_PrintScreen => Key::PrintScreen, - xkb::KEY_3270_Enter => Key::Enter, - - xkb::KEY_space => Key::Space, - // KEY_exclam..KEY_Sinh_kunddaliya + // keysyms::XKB_KEY_3270_Duplicate => Key::Duplicate, + // keysyms::XKB_KEY_3270_FieldMark => Key::FieldMark, + // keysyms::XKB_KEY_3270_Right2 => Key::Right2, + // keysyms::XKB_KEY_3270_Left2 => Key::Left2, + // keysyms::XKB_KEY_3270_BackTab => Key::BackTab, + keysyms::XKB_KEY_3270_EraseEOF => Key::EraseEof, + // keysyms::XKB_KEY_3270_EraseInput => Key::EraseInput, + // keysyms::XKB_KEY_3270_Reset => Key::Reset, + // keysyms::XKB_KEY_3270_Quit => Key::Quit, + // keysyms::XKB_KEY_3270_PA1 => Key::Pa1, + // keysyms::XKB_KEY_3270_PA2 => Key::Pa2, + // keysyms::XKB_KEY_3270_PA3 => Key::Pa3, + // keysyms::XKB_KEY_3270_Test => Key::Test, + keysyms::XKB_KEY_3270_Attn => Key::Attn, + // keysyms::XKB_KEY_3270_CursorBlink => Key::CursorBlink, + // keysyms::XKB_KEY_3270_AltCursor => Key::AltCursor, + // keysyms::XKB_KEY_3270_KeyClick => Key::KeyClick, + // keysyms::XKB_KEY_3270_Jump => Key::Jump, + // keysyms::XKB_KEY_3270_Ident => Key::Ident, + // keysyms::XKB_KEY_3270_Rule => Key::Rule, + // keysyms::XKB_KEY_3270_Copy => Key::Copy, + keysyms::XKB_KEY_3270_Play => Key::Play, + // keysyms::XKB_KEY_3270_Setup => Key::Setup, + // keysyms::XKB_KEY_3270_Record => Key::Record, + // keysyms::XKB_KEY_3270_ChangeScreen => Key::ChangeScreen, + // keysyms::XKB_KEY_3270_DeleteWord => Key::DeleteWord, + keysyms::XKB_KEY_3270_ExSelect => Key::ExSel, + keysyms::XKB_KEY_3270_CursorSelect => Key::CrSel, + keysyms::XKB_KEY_3270_PrintScreen => Key::PrintScreen, + keysyms::XKB_KEY_3270_Enter => Key::Enter, + + keysyms::XKB_KEY_space => Key::Space, + // XKB_KEY_exclam..XKB_KEY_Sinh_kunddaliya // XFree86 - // xkb::KEY_XF86ModeLock => Key::ModeLock, + // keysyms::XKB_KEY_XF86ModeLock => Key::ModeLock, // XFree86 - Backlight controls - xkb::KEY_XF86MonBrightnessUp => Key::BrightnessUp, - xkb::KEY_XF86MonBrightnessDown => Key::BrightnessDown, - // xkb::KEY_XF86KbdLightOnOff => Key::LightOnOff, - // xkb::KEY_XF86KbdBrightnessUp => Key::KeyboardBrightnessUp, - // xkb::KEY_XF86KbdBrightnessDown => Key::KeyboardBrightnessDown, + keysyms::XKB_KEY_XF86MonBrightnessUp => Key::BrightnessUp, + keysyms::XKB_KEY_XF86MonBrightnessDown => Key::BrightnessDown, + // keysyms::XKB_KEY_XF86KbdLightOnOff => Key::LightOnOff, + // keysyms::XKB_KEY_XF86KbdBrightnessUp => Key::KeyboardBrightnessUp, + // keysyms::XKB_KEY_XF86KbdBrightnessDown => Key::KeyboardBrightnessDown, // XFree86 - "Internet" - xkb::KEY_XF86Standby => Key::Standby, - xkb::KEY_XF86AudioLowerVolume => Key::AudioVolumeDown, - xkb::KEY_XF86AudioRaiseVolume => Key::AudioVolumeUp, - xkb::KEY_XF86AudioPlay => Key::MediaPlay, - xkb::KEY_XF86AudioStop => Key::MediaStop, - xkb::KEY_XF86AudioPrev => Key::MediaTrackPrevious, - xkb::KEY_XF86AudioNext => Key::MediaTrackNext, - xkb::KEY_XF86HomePage => Key::BrowserHome, - xkb::KEY_XF86Mail => Key::LaunchMail, - // xkb::KEY_XF86Start => Key::Start, - xkb::KEY_XF86Search => Key::BrowserSearch, - xkb::KEY_XF86AudioRecord => Key::MediaRecord, + keysyms::XKB_KEY_XF86Standby => Key::Standby, + keysyms::XKB_KEY_XF86AudioLowerVolume => Key::AudioVolumeDown, + keysyms::XKB_KEY_XF86AudioRaiseVolume => Key::AudioVolumeUp, + keysyms::XKB_KEY_XF86AudioPlay => Key::MediaPlay, + keysyms::XKB_KEY_XF86AudioStop => Key::MediaStop, + keysyms::XKB_KEY_XF86AudioPrev => Key::MediaTrackPrevious, + keysyms::XKB_KEY_XF86AudioNext => Key::MediaTrackNext, + keysyms::XKB_KEY_XF86HomePage => Key::BrowserHome, + keysyms::XKB_KEY_XF86Mail => Key::LaunchMail, + // keysyms::XKB_KEY_XF86Start => Key::Start, + keysyms::XKB_KEY_XF86Search => Key::BrowserSearch, + keysyms::XKB_KEY_XF86AudioRecord => Key::MediaRecord, // XFree86 - PDA - xkb::KEY_XF86Calculator => Key::LaunchApplication2, - // xkb::KEY_XF86Memo => Key::Memo, - // xkb::KEY_XF86ToDoList => Key::ToDoList, - xkb::KEY_XF86Calendar => Key::LaunchCalendar, - xkb::KEY_XF86PowerDown => Key::Power, - // xkb::KEY_XF86ContrastAdjust => Key::AdjustContrast, - // xkb::KEY_XF86RockerUp => Key::RockerUp, // TODO: Use Key::ArrowUp? - // xkb::KEY_XF86RockerDown => Key::RockerDown, // TODO: Use Key::ArrowDown? - // xkb::KEY_XF86RockerEnter => Key::RockerEnter, // TODO: Use Key::Enter? + keysyms::XKB_KEY_XF86Calculator => Key::LaunchApplication2, + // keysyms::XKB_KEY_XF86Memo => Key::Memo, + // keysyms::XKB_KEY_XF86ToDoList => Key::ToDoList, + keysyms::XKB_KEY_XF86Calendar => Key::LaunchCalendar, + keysyms::XKB_KEY_XF86PowerDown => Key::Power, + // keysyms::XKB_KEY_XF86ContrastAdjust => Key::AdjustContrast, + // keysyms::XKB_KEY_XF86RockerUp => Key::RockerUp, // TODO: Use Key::ArrowUp? + // keysyms::XKB_KEY_XF86RockerDown => Key::RockerDown, // TODO: Use Key::ArrowDown? + // keysyms::XKB_KEY_XF86RockerEnter => Key::RockerEnter, // TODO: Use Key::Enter? // XFree86 - More "Internet" - xkb::KEY_XF86Back => Key::BrowserBack, - xkb::KEY_XF86Forward => Key::BrowserForward, - // xkb::KEY_XF86Stop => Key::Stop, - xkb::KEY_XF86Refresh => Key::BrowserRefresh, - xkb::KEY_XF86PowerOff => Key::Power, - xkb::KEY_XF86WakeUp => Key::WakeUp, - xkb::KEY_XF86Eject => Key::Eject, - xkb::KEY_XF86ScreenSaver => Key::LaunchScreenSaver, - xkb::KEY_XF86WWW => Key::LaunchWebBrowser, - xkb::KEY_XF86Sleep => Key::Standby, - xkb::KEY_XF86Favorites => Key::BrowserFavorites, - xkb::KEY_XF86AudioPause => Key::MediaPause, - // xkb::KEY_XF86AudioMedia => Key::AudioMedia, - xkb::KEY_XF86MyComputer => Key::LaunchApplication1, - // xkb::KEY_XF86VendorHome => Key::VendorHome, - // xkb::KEY_XF86LightBulb => Key::LightBulb, - // xkb::KEY_XF86Shop => Key::BrowserShop, - // xkb::KEY_XF86History => Key::BrowserHistory, - // xkb::KEY_XF86OpenURL => Key::OpenUrl, - // xkb::KEY_XF86AddFavorite => Key::AddFavorite, - // xkb::KEY_XF86HotLinks => Key::HotLinks, - // xkb::KEY_XF86BrightnessAdjust => Key::BrightnessAdjust, - // xkb::KEY_XF86Finance => Key::BrowserFinance, - // xkb::KEY_XF86Community => Key::BrowserCommunity, - xkb::KEY_XF86AudioRewind => Key::MediaRewind, - // xkb::KEY_XF86BackForward => Key::???, - // KEY_XF86Launch0..KEY_XF86LaunchF - - // KEY_XF86ApplicationLeft..KEY_XF86CD - xkb::KEY_XF86Calculater => Key::LaunchApplication2, // This must be a typo, right? - // KEY_XF86Clear - xkb::KEY_XF86Close => Key::Close, - xkb::KEY_XF86Copy => Key::Copy, - xkb::KEY_XF86Cut => Key::Cut, - // KEY_XF86Display..KEY_XF86Documents - xkb::KEY_XF86Excel => Key::LaunchSpreadsheet, - // KEY_XF86Explorer..KEY_XF86iTouch - xkb::KEY_XF86LogOff => Key::LogOff, - // KEY_XF86Market..KEY_XF86MenuPB - xkb::KEY_XF86MySites => Key::BrowserFavorites, - xkb::KEY_XF86New => Key::New, - // KEY_XF86News..KEY_XF86OfficeHome - xkb::KEY_XF86Open => Key::Open, - // KEY_XF86Option - xkb::KEY_XF86Paste => Key::Paste, - xkb::KEY_XF86Phone => Key::LaunchPhone, - // KEY_XF86Q - xkb::KEY_XF86Reply => Key::MailReply, - xkb::KEY_XF86Reload => Key::BrowserRefresh, - // KEY_XF86RotateWindows..KEY_XF86RotationKB - xkb::KEY_XF86Save => Key::Save, - // KEY_XF86ScrollUp..KEY_XF86ScrollClick - xkb::KEY_XF86Send => Key::MailSend, - xkb::KEY_XF86Spell => Key::SpellCheck, - xkb::KEY_XF86SplitScreen => Key::SplitScreenToggle, - // KEY_XF86Support..KEY_XF86User2KB - xkb::KEY_XF86Video => Key::LaunchMediaPlayer, - // KEY_XF86WheelButton - xkb::KEY_XF86Word => Key::LaunchWordProcessor, - // KEY_XF86Xfer - xkb::KEY_XF86ZoomIn => Key::ZoomIn, - xkb::KEY_XF86ZoomOut => Key::ZoomOut, - - // KEY_XF86Away..KEY_XF86Messenger - xkb::KEY_XF86WebCam => Key::LaunchWebCam, - xkb::KEY_XF86MailForward => Key::MailForward, - // KEY_XF86Pictures - xkb::KEY_XF86Music => Key::LaunchMusicPlayer, - - // KEY_XF86Battery..KEY_XF86UWB + keysyms::XKB_KEY_XF86Back => Key::BrowserBack, + keysyms::XKB_KEY_XF86Forward => Key::BrowserForward, + // keysyms::XKB_KEY_XF86Stop => Key::Stop, + keysyms::XKB_KEY_XF86Refresh => Key::BrowserRefresh, + keysyms::XKB_KEY_XF86PowerOff => Key::Power, + keysyms::XKB_KEY_XF86WakeUp => Key::WakeUp, + keysyms::XKB_KEY_XF86Eject => Key::Eject, + keysyms::XKB_KEY_XF86ScreenSaver => Key::LaunchScreenSaver, + keysyms::XKB_KEY_XF86WWW => Key::LaunchWebBrowser, + keysyms::XKB_KEY_XF86Sleep => Key::Standby, + keysyms::XKB_KEY_XF86Favorites => Key::BrowserFavorites, + keysyms::XKB_KEY_XF86AudioPause => Key::MediaPause, + // keysyms::XKB_KEY_XF86AudioMedia => Key::AudioMedia, + keysyms::XKB_KEY_XF86MyComputer => Key::LaunchApplication1, + // keysyms::XKB_KEY_XF86VendorHome => Key::VendorHome, + // keysyms::XKB_KEY_XF86LightBulb => Key::LightBulb, + // keysyms::XKB_KEY_XF86Shop => Key::BrowserShop, + // keysyms::XKB_KEY_XF86History => Key::BrowserHistory, + // keysyms::XKB_KEY_XF86OpenURL => Key::OpenUrl, + // keysyms::XKB_KEY_XF86AddFavorite => Key::AddFavorite, + // keysyms::XKB_KEY_XF86HotLinks => Key::HotLinks, + // keysyms::XKB_KEY_XF86BrightnessAdjust => Key::BrightnessAdjust, + // keysyms::XKB_KEY_XF86Finance => Key::BrowserFinance, + // keysyms::XKB_KEY_XF86Community => Key::BrowserCommunity, + keysyms::XKB_KEY_XF86AudioRewind => Key::MediaRewind, + // keysyms::XKB_KEY_XF86BackForward => Key::???, + // XKB_KEY_XF86Launch0..XKB_KEY_XF86LaunchF + + // XKB_KEY_XF86ApplicationLeft..XKB_KEY_XF86CD + keysyms::XKB_KEY_XF86Calculater => Key::LaunchApplication2, // This must be a typo, right? + // XKB_KEY_XF86Clear + keysyms::XKB_KEY_XF86Close => Key::Close, + keysyms::XKB_KEY_XF86Copy => Key::Copy, + keysyms::XKB_KEY_XF86Cut => Key::Cut, + // XKB_KEY_XF86Display..XKB_KEY_XF86Documents + keysyms::XKB_KEY_XF86Excel => Key::LaunchSpreadsheet, + // XKB_KEY_XF86Explorer..XKB_KEY_XF86iTouch + keysyms::XKB_KEY_XF86LogOff => Key::LogOff, + // XKB_KEY_XF86Market..XKB_KEY_XF86MenuPB + keysyms::XKB_KEY_XF86MySites => Key::BrowserFavorites, + keysyms::XKB_KEY_XF86New => Key::New, + // XKB_KEY_XF86News..XKB_KEY_XF86OfficeHome + keysyms::XKB_KEY_XF86Open => Key::Open, + // XKB_KEY_XF86Option + keysyms::XKB_KEY_XF86Paste => Key::Paste, + keysyms::XKB_KEY_XF86Phone => Key::LaunchPhone, + // XKB_KEY_XF86Q + keysyms::XKB_KEY_XF86Reply => Key::MailReply, + keysyms::XKB_KEY_XF86Reload => Key::BrowserRefresh, + // XKB_KEY_XF86RotateWindows..XKB_KEY_XF86RotationKB + keysyms::XKB_KEY_XF86Save => Key::Save, + // XKB_KEY_XF86ScrollUp..XKB_KEY_XF86ScrollClick + keysyms::XKB_KEY_XF86Send => Key::MailSend, + keysyms::XKB_KEY_XF86Spell => Key::SpellCheck, + keysyms::XKB_KEY_XF86SplitScreen => Key::SplitScreenToggle, + // XKB_KEY_XF86Support..XKB_KEY_XF86User2KB + keysyms::XKB_KEY_XF86Video => Key::LaunchMediaPlayer, + // XKB_KEY_XF86WheelButton + keysyms::XKB_KEY_XF86Word => Key::LaunchWordProcessor, + // XKB_KEY_XF86Xfer + keysyms::XKB_KEY_XF86ZoomIn => Key::ZoomIn, + keysyms::XKB_KEY_XF86ZoomOut => Key::ZoomOut, + + // XKB_KEY_XF86Away..XKB_KEY_XF86Messenger + keysyms::XKB_KEY_XF86WebCam => Key::LaunchWebCam, + keysyms::XKB_KEY_XF86MailForward => Key::MailForward, + // XKB_KEY_XF86Pictures + keysyms::XKB_KEY_XF86Music => Key::LaunchMusicPlayer, + + // XKB_KEY_XF86Battery..XKB_KEY_XF86UWB // - xkb::KEY_XF86AudioForward => Key::MediaFastForward, - // KEY_XF86AudioRepeat - xkb::KEY_XF86AudioRandomPlay => Key::RandomToggle, - xkb::KEY_XF86Subtitle => Key::Subtitle, - xkb::KEY_XF86AudioCycleTrack => Key::MediaAudioTrack, - // KEY_XF86CycleAngle..KEY_XF86Blue + keysyms::XKB_KEY_XF86AudioForward => Key::MediaFastForward, + // XKB_KEY_XF86AudioRepeat + keysyms::XKB_KEY_XF86AudioRandomPlay => Key::RandomToggle, + keysyms::XKB_KEY_XF86Subtitle => Key::Subtitle, + keysyms::XKB_KEY_XF86AudioCycleTrack => Key::MediaAudioTrack, + // XKB_KEY_XF86CycleAngle..XKB_KEY_XF86Blue // - xkb::KEY_XF86Suspend => Key::Standby, - xkb::KEY_XF86Hibernate => Key::Hibernate, - // KEY_XF86TouchpadToggle..KEY_XF86TouchpadOff + keysyms::XKB_KEY_XF86Suspend => Key::Standby, + keysyms::XKB_KEY_XF86Hibernate => Key::Hibernate, + // XKB_KEY_XF86TouchpadToggle..XKB_KEY_XF86TouchpadOff // - xkb::KEY_XF86AudioMute => Key::AudioVolumeMute, - - // KEY_XF86Switch_VT_1..KEY_XF86Switch_VT_12 - - // KEY_XF86Ungrab..KEY_XF86ClearGrab - xkb::KEY_XF86Next_VMode => Key::VideoModeNext, - // xkb::KEY_XF86Prev_VMode => Key::VideoModePrevious, - // KEY_XF86LogWindowTree..KEY_XF86LogGrabInfo - - // KEY_SunFA_Grave..KEY_SunFA_Cedilla - - // xkb::KEY_SunF36 => Key::F36 | Key::F11, - // xkb::KEY_SunF37 => Key::F37 | Key::F12, - - // xkb::KEY_SunSys_Req => Key::PrintScreen, - // The next couple of xkb (until KEY_SunStop) are already handled. - // KEY_SunPrint_Screen..KEY_SunPageDown - - // KEY_SunUndo..KEY_SunFront - xkb::KEY_SunCopy => Key::Copy, - xkb::KEY_SunOpen => Key::Open, - xkb::KEY_SunPaste => Key::Paste, - xkb::KEY_SunCut => Key::Cut, - - // KEY_SunPowerSwitch - xkb::KEY_SunAudioLowerVolume => Key::AudioVolumeDown, - xkb::KEY_SunAudioMute => Key::AudioVolumeMute, - xkb::KEY_SunAudioRaiseVolume => Key::AudioVolumeUp, - // KEY_SunVideoDegauss - xkb::KEY_SunVideoLowerBrightness => Key::BrightnessDown, - xkb::KEY_SunVideoRaiseBrightness => Key::BrightnessUp, - // KEY_SunPowerSwitchShift + keysyms::XKB_KEY_XF86AudioMute => Key::AudioVolumeMute, + + // XKB_KEY_XF86Switch_VT_1..XKB_KEY_XF86Switch_VT_12 + + // XKB_KEY_XF86Ungrab..XKB_KEY_XF86ClearGrab + keysyms::XKB_KEY_XF86Next_VMode => Key::VideoModeNext, + // keysyms::XKB_KEY_XF86Prev_VMode => Key::VideoModePrevious, + // XKB_KEY_XF86LogWindowTree..XKB_KEY_XF86LogGrabInfo + + // XKB_KEY_SunFA_Grave..XKB_KEY_SunFA_Cedilla + + // keysyms::XKB_KEY_SunF36 => Key::F36 | Key::F11, + // keysyms::XKB_KEY_SunF37 => Key::F37 | Key::F12, + + // keysyms::XKB_KEY_SunSys_Req => Key::PrintScreen, + // The next couple of xkb (until XKB_KEY_SunStop) are already handled. + // XKB_KEY_SunPrint_Screen..XKB_KEY_SunPageDown + + // XKB_KEY_SunUndo..XKB_KEY_SunFront + keysyms::XKB_KEY_SunCopy => Key::Copy, + keysyms::XKB_KEY_SunOpen => Key::Open, + keysyms::XKB_KEY_SunPaste => Key::Paste, + keysyms::XKB_KEY_SunCut => Key::Cut, + + // XKB_KEY_SunPowerSwitch + keysyms::XKB_KEY_SunAudioLowerVolume => Key::AudioVolumeDown, + keysyms::XKB_KEY_SunAudioMute => Key::AudioVolumeMute, + keysyms::XKB_KEY_SunAudioRaiseVolume => Key::AudioVolumeUp, + // XKB_KEY_SunVideoDegauss + keysyms::XKB_KEY_SunVideoLowerBrightness => Key::BrightnessDown, + keysyms::XKB_KEY_SunVideoRaiseBrightness => Key::BrightnessUp, + // XKB_KEY_SunPowerSwitchShift // _ => Key::Unidentified(NativeKeyCode::XKB(keysym)), } } pub fn keysym_location(keysym: u32) -> KeyLocation { - use xkbcommon::xkb; + use xkbcommon_dl::keysyms; match keysym { - xkb::KEY_Shift_L - | xkb::KEY_Control_L - | xkb::KEY_Meta_L - | xkb::KEY_Alt_L - | xkb::KEY_Super_L - | xkb::KEY_Hyper_L => KeyLocation::Left, - xkb::KEY_Shift_R - | xkb::KEY_Control_R - | xkb::KEY_Meta_R - | xkb::KEY_Alt_R - | xkb::KEY_Super_R - | xkb::KEY_Hyper_R => KeyLocation::Right, - xkb::KEY_KP_0 - | xkb::KEY_KP_1 - | xkb::KEY_KP_2 - | xkb::KEY_KP_3 - | xkb::KEY_KP_4 - | xkb::KEY_KP_5 - | xkb::KEY_KP_6 - | xkb::KEY_KP_7 - | xkb::KEY_KP_8 - | xkb::KEY_KP_9 - | xkb::KEY_KP_Space - | xkb::KEY_KP_Tab - | xkb::KEY_KP_Enter - | xkb::KEY_KP_F1 - | xkb::KEY_KP_F2 - | xkb::KEY_KP_F3 - | xkb::KEY_KP_F4 - | xkb::KEY_KP_Home - | xkb::KEY_KP_Left - | xkb::KEY_KP_Up - | xkb::KEY_KP_Right - | xkb::KEY_KP_Down - | xkb::KEY_KP_Page_Up - | xkb::KEY_KP_Page_Down - | xkb::KEY_KP_End - | xkb::KEY_KP_Begin - | xkb::KEY_KP_Insert - | xkb::KEY_KP_Delete - | xkb::KEY_KP_Equal - | xkb::KEY_KP_Multiply - | xkb::KEY_KP_Add - | xkb::KEY_KP_Separator - | xkb::KEY_KP_Subtract - | xkb::KEY_KP_Decimal - | xkb::KEY_KP_Divide => KeyLocation::Numpad, + keysyms::XKB_KEY_Shift_L + | keysyms::XKB_KEY_Control_L + | keysyms::XKB_KEY_Meta_L + | keysyms::XKB_KEY_Alt_L + | keysyms::XKB_KEY_Super_L + | keysyms::XKB_KEY_Hyper_L => KeyLocation::Left, + keysyms::XKB_KEY_Shift_R + | keysyms::XKB_KEY_Control_R + | keysyms::XKB_KEY_Meta_R + | keysyms::XKB_KEY_Alt_R + | keysyms::XKB_KEY_Super_R + | keysyms::XKB_KEY_Hyper_R => KeyLocation::Right, + keysyms::XKB_KEY_KP_0 + | keysyms::XKB_KEY_KP_1 + | keysyms::XKB_KEY_KP_2 + | keysyms::XKB_KEY_KP_3 + | keysyms::XKB_KEY_KP_4 + | keysyms::XKB_KEY_KP_5 + | keysyms::XKB_KEY_KP_6 + | keysyms::XKB_KEY_KP_7 + | keysyms::XKB_KEY_KP_8 + | keysyms::XKB_KEY_KP_9 + | keysyms::XKB_KEY_KP_Space + | keysyms::XKB_KEY_KP_Tab + | keysyms::XKB_KEY_KP_Enter + | keysyms::XKB_KEY_KP_F1 + | keysyms::XKB_KEY_KP_F2 + | keysyms::XKB_KEY_KP_F3 + | keysyms::XKB_KEY_KP_F4 + | keysyms::XKB_KEY_KP_Home + | keysyms::XKB_KEY_KP_Left + | keysyms::XKB_KEY_KP_Up + | keysyms::XKB_KEY_KP_Right + | keysyms::XKB_KEY_KP_Down + | keysyms::XKB_KEY_KP_Page_Up + | keysyms::XKB_KEY_KP_Page_Down + | keysyms::XKB_KEY_KP_End + | keysyms::XKB_KEY_KP_Begin + | keysyms::XKB_KEY_KP_Insert + | keysyms::XKB_KEY_KP_Delete + | keysyms::XKB_KEY_KP_Equal + | keysyms::XKB_KEY_KP_Multiply + | keysyms::XKB_KEY_KP_Add + | keysyms::XKB_KEY_KP_Separator + | keysyms::XKB_KEY_KP_Subtract + | keysyms::XKB_KEY_KP_Decimal + | keysyms::XKB_KEY_KP_Divide => KeyLocation::Numpad, _ => KeyLocation::Standard, } } From 0cb11c06a2ac755840351c8e6d03ff23f1bbfe2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Wed, 31 Mar 2021 04:31:56 +0200 Subject: [PATCH 06/58] Hoist keyboard handling code from sctk into Winit --- Cargo.toml | 5 +- src/platform_impl/linux/common/mod.rs | 1 + src/platform_impl/linux/common/xkb_state.rs | 383 +++++++++++ .../linux/wayland/seat/keyboard/handlers.rs | 601 +++++++++++++++++- .../linux/wayland/seat/keyboard/mod.rs | 30 +- 5 files changed, 992 insertions(+), 28 deletions(-) create mode 100644 src/platform_impl/linux/common/xkb_state.rs diff --git a/Cargo.toml b/Cargo.toml index 66686274c4..d0cb67a869 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,7 +35,7 @@ targets = [ [features] default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"] x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] -wayland = ["wayland-client", "wayland-protocols", "sctk"] +wayland = ["wayland-client", "wayland-protocols", "sctk", "memmap2"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/title"] wayland-csd-adwaita-notitle = ["sctk-adwaita"] @@ -112,7 +112,8 @@ x11-dl = { version = "2.18.5", optional = true } percent-encoding = { version = "2.0", optional = true } parking_lot = { version = "0.12.0", optional = true } libc = "0.2.64" -xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "224646a" } +memmap2 = { version = "0.2.1", optional = true } +xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "e175ffe" } [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" diff --git a/src/platform_impl/linux/common/mod.rs b/src/platform_impl/linux/common/mod.rs index 32030aff05..fa23919676 100644 --- a/src/platform_impl/linux/common/mod.rs +++ b/src/platform_impl/linux/common/mod.rs @@ -1 +1,2 @@ pub mod keymap; +pub mod xkb_state; diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs new file mode 100644 index 0000000000..5bb3fd278c --- /dev/null +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -0,0 +1,383 @@ +use std::env; +use std::ffi::CString; +use std::fs::File; +use std::os::raw::c_char; +use std::os::unix::ffi::OsStringExt; +use std::ptr; + +use memmap2::MmapOptions; +use xkbcommon_dl::{ + self as ffi, xkb_state_component, XKBCOMMON_COMPOSE_HANDLE as XKBCH, XKBCOMMON_HANDLE as XKBH, +}; + +pub use sctk::seat::keyboard::RMLVO; + +pub(crate) struct KbState { + xkb_context: *mut ffi::xkb_context, + xkb_keymap: *mut ffi::xkb_keymap, + xkb_state: *mut ffi::xkb_state, + xkb_compose_table: *mut ffi::xkb_compose_table, + xkb_compose_state: *mut ffi::xkb_compose_state, + mods_state: ModifiersState, + locked: bool, +} + +/// Represents the current state of the keyboard modifiers +/// +/// Each field of this struct represents a modifier and is `true` if this modifier is active. +/// +/// For some modifiers, this means that the key is currently pressed, others are toggled +/// (like caps lock). +#[derive(Copy, Clone, Debug, Default)] +pub struct ModifiersState { + /// The "control" key + pub ctrl: bool, + /// The "alt" key + pub alt: bool, + /// The "shift" key + pub shift: bool, + /// The "Caps lock" key + pub caps_lock: bool, + /// The "logo" key + /// + /// Also known as the "windows" key on most keyboards + pub logo: bool, + /// The "Num lock" key + pub num_lock: bool, +} + +impl ModifiersState { + fn new() -> ModifiersState { + ModifiersState::default() + } + + fn update_with(&mut self, state: *mut ffi::xkb_state) { + self.ctrl = unsafe { + (XKBH.xkb_state_mod_name_is_active)( + state, + ffi::XKB_MOD_NAME_CTRL.as_ptr() as *const c_char, + xkb_state_component::XKB_STATE_MODS_EFFECTIVE, + ) > 0 + }; + self.alt = unsafe { + (XKBH.xkb_state_mod_name_is_active)( + state, + ffi::XKB_MOD_NAME_ALT.as_ptr() as *const c_char, + xkb_state_component::XKB_STATE_MODS_EFFECTIVE, + ) > 0 + }; + self.shift = unsafe { + (XKBH.xkb_state_mod_name_is_active)( + state, + ffi::XKB_MOD_NAME_SHIFT.as_ptr() as *const c_char, + xkb_state_component::XKB_STATE_MODS_EFFECTIVE, + ) > 0 + }; + self.caps_lock = unsafe { + (XKBH.xkb_state_mod_name_is_active)( + state, + ffi::XKB_MOD_NAME_CAPS.as_ptr() as *const c_char, + xkb_state_component::XKB_STATE_MODS_EFFECTIVE, + ) > 0 + }; + self.logo = unsafe { + (XKBH.xkb_state_mod_name_is_active)( + state, + ffi::XKB_MOD_NAME_LOGO.as_ptr() as *const c_char, + xkb_state_component::XKB_STATE_MODS_EFFECTIVE, + ) > 0 + }; + self.num_lock = unsafe { + (XKBH.xkb_state_mod_name_is_active)( + state, + ffi::XKB_MOD_NAME_NUM.as_ptr() as *const c_char, + xkb_state_component::XKB_STATE_MODS_EFFECTIVE, + ) > 0 + }; + } +} + +impl KbState { + pub(crate) fn update_modifiers( + &mut self, + mods_depressed: u32, + mods_latched: u32, + mods_locked: u32, + group: u32, + ) { + if !self.ready() { + return; + } + let mask = unsafe { + (XKBH.xkb_state_update_mask)( + self.xkb_state, + mods_depressed, + mods_latched, + mods_locked, + 0, + 0, + group, + ) + }; + if mask.contains(xkb_state_component::XKB_STATE_MODS_EFFECTIVE) { + // effective value of mods have changed, we need to update our state + self.mods_state.update_with(self.xkb_state); + } + } + + pub(crate) fn get_one_sym_raw(&mut self, keycode: u32) -> u32 { + if !self.ready() { + return 0; + } + unsafe { (XKBH.xkb_state_key_get_one_sym)(self.xkb_state, keycode + 8) } + } + + pub(crate) fn get_utf8_raw(&mut self, keycode: u32) -> Option { + if !self.ready() { + return None; + } + let size = unsafe { + (XKBH.xkb_state_key_get_utf8)(self.xkb_state, keycode + 8, ptr::null_mut(), 0) + } + 1; + if size <= 1 { + return None; + }; + let mut buffer = Vec::with_capacity(size as usize); + unsafe { + buffer.set_len(size as usize); + (XKBH.xkb_state_key_get_utf8)( + self.xkb_state, + keycode + 8, + buffer.as_mut_ptr() as *mut _, + size as usize, + ); + }; + // remove the final `\0` + buffer.pop(); + // libxkbcommon will always provide valid UTF8 + Some(unsafe { String::from_utf8_unchecked(buffer) }) + } + + pub(crate) fn compose_feed(&mut self, keysym: u32) -> Option { + if !self.ready() || self.xkb_compose_state.is_null() { + return None; + } + Some(unsafe { (XKBCH.xkb_compose_state_feed)(self.xkb_compose_state, keysym) }) + } + + pub(crate) fn compose_status(&mut self) -> Option { + if !self.ready() || self.xkb_compose_state.is_null() { + return None; + } + Some(unsafe { (XKBCH.xkb_compose_state_get_status)(self.xkb_compose_state) }) + } + + pub(crate) fn compose_get_utf8(&mut self) -> Option { + if !self.ready() || self.xkb_compose_state.is_null() { + return None; + } + let size = unsafe { + (XKBCH.xkb_compose_state_get_utf8)(self.xkb_compose_state, ptr::null_mut(), 0) + } + 1; + if size <= 1 { + return None; + }; + let mut buffer = Vec::with_capacity(size as usize); + unsafe { + buffer.set_len(size as usize); + (XKBCH.xkb_compose_state_get_utf8)( + self.xkb_compose_state, + buffer.as_mut_ptr() as *mut _, + size as usize, + ); + }; + // remove the final `\0` + buffer.pop(); + // libxkbcommon will always provide valid UTF8 + Some(unsafe { String::from_utf8_unchecked(buffer) }) + } + + pub(crate) fn new() -> Result { + { + if ffi::XKBCOMMON_OPTION.as_ref().is_none() { + return Err(Error::XKBNotFound); + } + } + let context = + unsafe { (XKBH.xkb_context_new)(ffi::xkb_context_flags::XKB_CONTEXT_NO_FLAGS) }; + if context.is_null() { + return Err(Error::XKBNotFound); + } + + let mut me = KbState { + xkb_context: context, + xkb_keymap: ptr::null_mut(), + xkb_state: ptr::null_mut(), + xkb_compose_table: ptr::null_mut(), + xkb_compose_state: ptr::null_mut(), + mods_state: ModifiersState::new(), + locked: false, + }; + + unsafe { + me.init_compose(); + } + + Ok(me) + } + + pub(crate) fn from_rmlvo(rmlvo: RMLVO) -> Result { + fn to_cstring(s: Option) -> Result, Error> { + s.map_or(Ok(None), |s| CString::new(s).map(Option::Some)) + .map_err(|_| Error::BadNames) + } + + let mut state = KbState::new()?; + + let rules = to_cstring(rmlvo.rules)?; + let model = to_cstring(rmlvo.model)?; + let layout = to_cstring(rmlvo.layout)?; + let variant = to_cstring(rmlvo.variant)?; + let options = to_cstring(rmlvo.options)?; + + let xkb_names = ffi::xkb_rule_names { + rules: rules.map_or(ptr::null(), |s| s.as_ptr()), + model: model.map_or(ptr::null(), |s| s.as_ptr()), + layout: layout.map_or(ptr::null(), |s| s.as_ptr()), + variant: variant.map_or(ptr::null(), |s| s.as_ptr()), + options: options.map_or(ptr::null(), |s| s.as_ptr()), + }; + + unsafe { + state.init_with_rmlvo(xkb_names)?; + } + + state.locked = true; + Ok(state) + } + + pub(crate) unsafe fn init_compose(&mut self) { + let locale = env::var_os("LC_ALL") + .and_then(|v| if v.is_empty() { None } else { Some(v) }) + .or_else(|| env::var_os("LC_CTYPE")) + .and_then(|v| if v.is_empty() { None } else { Some(v) }) + .or_else(|| env::var_os("LANG")) + .and_then(|v| if v.is_empty() { None } else { Some(v) }) + .unwrap_or_else(|| "C".into()); + let locale = CString::new(locale.into_vec()).unwrap(); + + let compose_table = (XKBCH.xkb_compose_table_new_from_locale)( + self.xkb_context, + locale.as_ptr(), + ffi::xkb_compose_compile_flags::XKB_COMPOSE_COMPILE_NO_FLAGS, + ); + + if compose_table.is_null() { + // init of compose table failed, continue without compose + return; + } + + let compose_state = (XKBCH.xkb_compose_state_new)( + compose_table, + ffi::xkb_compose_state_flags::XKB_COMPOSE_STATE_NO_FLAGS, + ); + + if compose_state.is_null() { + // init of compose state failed, continue without compose + (XKBCH.xkb_compose_table_unref)(compose_table); + return; + } + + self.xkb_compose_table = compose_table; + self.xkb_compose_state = compose_state; + } + + pub(crate) unsafe fn post_init(&mut self, keymap: *mut ffi::xkb_keymap) { + let state = (XKBH.xkb_state_new)(keymap); + self.xkb_keymap = keymap; + self.xkb_state = state; + self.mods_state.update_with(state); + } + + pub(crate) unsafe fn de_init(&mut self) { + (XKBH.xkb_state_unref)(self.xkb_state); + self.xkb_state = ptr::null_mut(); + (XKBH.xkb_keymap_unref)(self.xkb_keymap); + self.xkb_keymap = ptr::null_mut(); + } + + pub(crate) unsafe fn init_with_fd(&mut self, fd: File, size: usize) { + let map = MmapOptions::new().len(size).map(&fd).unwrap(); + + let keymap = (XKBH.xkb_keymap_new_from_string)( + self.xkb_context, + map.as_ptr() as *const _, + ffi::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1, + ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS, + ); + + if keymap.is_null() { + panic!("Received invalid keymap from compositor."); + } + + self.post_init(keymap); + } + + pub(crate) unsafe fn init_with_rmlvo( + &mut self, + names: ffi::xkb_rule_names, + ) -> Result<(), Error> { + let keymap = (XKBH.xkb_keymap_new_from_names)( + self.xkb_context, + &names, + ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS, + ); + + if keymap.is_null() { + return Err(Error::BadNames); + } + + self.post_init(keymap); + + Ok(()) + } + + pub(crate) unsafe fn key_repeats(&mut self, xkb_keycode_t: ffi::xkb_keycode_t) -> bool { + (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, xkb_keycode_t) == 1 + } + + #[inline] + pub(crate) fn ready(&self) -> bool { + !self.xkb_state.is_null() + } + + #[inline] + pub(crate) fn locked(&self) -> bool { + self.locked + } + + #[inline] + pub(crate) fn mods_state(&self) -> ModifiersState { + self.mods_state + } +} + +impl Drop for KbState { + fn drop(&mut self) { + unsafe { + (XKBCH.xkb_compose_state_unref)(self.xkb_compose_state); + (XKBCH.xkb_compose_table_unref)(self.xkb_compose_table); + (XKBH.xkb_state_unref)(self.xkb_state); + (XKBH.xkb_keymap_unref)(self.xkb_keymap); + (XKBH.xkb_context_unref)(self.xkb_context); + } + } +} + +#[derive(Debug)] +pub enum Error { + /// libxkbcommon is not available + XKBNotFound, + /// Provided RMLVO specified a keymap that would not be loaded + BadNames, +} diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 268beb6fa3..acb5dc1852 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -1,12 +1,13 @@ //! Handling of various keyboard events. +use sctk::reexports::calloop; +use sctk::reexports::client; use sctk::reexports::client::protocol::wl_keyboard::KeyState; -use sctk::seat::keyboard::Event as KeyboardEvent; - use crate::event::{ElementState, KeyEvent, WindowEvent}; use crate::keyboard::{Key, ModifiersState, NativeKeyCode}; use crate::platform_impl::platform::common::keymap; +use crate::platform_impl::platform::common::xkb_state::{self, RMLVO}; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::{self, DeviceId}; use crate::platform_impl::KeyEventExtra; @@ -15,13 +16,13 @@ use super::KeyboardInner; #[inline] pub(super) fn handle_keyboard( - event: KeyboardEvent<'_>, + event: Event<'_>, inner: &mut KeyboardInner, winit_state: &mut WinitState, ) { let event_sink = &mut winit_state.event_sink; match event { - KeyboardEvent::Enter { surface, .. } => { + Event::Enter { surface, .. } => { let window_id = wayland::make_wid(&surface); // Window gained focus. @@ -35,7 +36,7 @@ pub(super) fn handle_keyboard( inner.target_window_id = Some(window_id); } - KeyboardEvent::Leave { surface, .. } => { + Event::Leave { surface, .. } => { let window_id = wayland::make_wid(&surface); // Notify that no modifiers are being pressed. @@ -52,7 +53,7 @@ pub(super) fn handle_keyboard( // Reset the id. inner.target_window_id = None; } - KeyboardEvent::Key { + Event::Key { rawkey, keysym, state, @@ -107,7 +108,7 @@ pub(super) fn handle_keyboard( } } } - KeyboardEvent::Repeat { + Event::Repeat { rawkey, keysym, utf8, @@ -148,9 +149,7 @@ pub(super) fn handle_keyboard( for ch in txt.chars() { // event_sink.push_window_event(WindowEvent::ReceivedCharacter(ch), window_id); } - } - } - KeyboardEvent::Modifiers { modifiers } => { + Event::Modifiers { modifiers } => { let modifiers = ModifiersState::from(modifiers); if let Some(window_id) = inner.target_window_id { *inner.modifiers_state.borrow_mut() = modifiers; @@ -165,3 +164,585 @@ pub(super) fn handle_keyboard( } } } + +// ! ====================================================================================================== ! +// ! "INSPIRED" BY SCTK ! +// ! ====================================================================================================== ! + +use std::num::NonZeroU32; +use std::time::Duration; +use std::{ + cell::RefCell, + convert::TryInto, + fs::File, + os::unix::io::{FromRawFd, RawFd}, + rc::Rc, +}; + +use sctk::reexports::client::{ + protocol::{wl_keyboard, wl_seat, wl_surface}, + Attached, +}; +use xkbcommon_dl as ffi; + +use super::super::super::super::common::xkb_state::KbState; + +const MICROS_IN_SECOND: u32 = 1000000; + +/// Possible kinds of key repetition +pub enum RepeatKind { + /// keys will be repeated at a set rate and delay + Fixed { + /// The number of repetitions per second that should occur. + rate: u32, + /// delay (in milliseconds) between a key press and the start of repetition + delay: u32, + }, + /// keys will be repeated at a rate and delay set by the wayland server + System, +} + +#[derive(Debug)] +/// An error that occurred while trying to initialize a mapped keyboard +pub enum Error { + XkbState(xkb_state::Error), + /// The provided seat does not have the keyboard capability + NoKeyboard, + /// Failed to init timers for repetition + TimerError(std::io::Error), +} + +impl From for Error { + fn from(err: xkb_state::Error) -> Self { + Self::XkbState(err) + } +} + +/// Events received from a mapped keyboard +pub enum Event<'a> { + /// The keyboard focus has entered a surface + Enter { + /// serial number of the event + serial: u32, + /// surface that was entered + surface: wl_surface::WlSurface, + /// raw values of the currently pressed keys + rawkeys: &'a [u32], + /// interpreted symbols of the currently pressed keys + keysyms: &'a [u32], + }, + /// The keyboard focus has left a surface + Leave { + /// serial number of the event + serial: u32, + /// surface that was left + surface: wl_surface::WlSurface, + }, + /// The key modifiers have changed state + Modifiers { + /// current state of the modifiers + modifiers: xkb_state::ModifiersState, + }, + /// A key event occurred + Key { + /// serial number of the event + serial: u32, + /// time at which the keypress occurred + time: u32, + /// raw value of the key + rawkey: u32, + /// interpreted symbol of the key + keysym: u32, + /// new state of the key + state: KeyState, + /// utf8 interpretation of the entered text + /// + /// will always be `None` on key release events + utf8: Option, + }, + /// A key repetition event + Repeat { + /// time at which the repetition occured + time: u32, + /// raw value of the key + rawkey: u32, + /// interpreted symbol of the key + keysym: u32, + /// utf8 interpretation of the entered text + utf8: Option, + }, +} + +/// Implement a keyboard for keymap translation with key repetition +/// +/// This requires you to provide a callback to receive the events after they +/// have been interpreted with the keymap. +/// +/// The keymap will be loaded from the provided RMLVO rules, or from the compositor +/// provided keymap if `None`. +/// +/// Returns an error if xkbcommon could not be initialized, the RMLVO specification +/// contained invalid values, or if the provided seat does not have keyboard capability. +pub fn map_keyboard_repeat( + loop_handle: calloop::LoopHandle, + seat: &Attached, + rmlvo: Option, + repeatkind: RepeatKind, + callback: F, +) -> Result<(wl_keyboard::WlKeyboard, calloop::Source), Error> +where + F: FnMut(Event<'_>, wl_keyboard::WlKeyboard, wayland_client::DispatchData<'_>) + 'static, +{ + let has_kbd = sctk::seat::with_seat_data(seat, |data| data.has_keyboard).unwrap_or(false); + let keyboard = if has_kbd { + seat.get_keyboard() + } else { + return Err(Error::NoKeyboard); + }; + + let state = Rc::new(RefCell::new( + rmlvo + .map(KbState::from_rmlvo) + .unwrap_or_else(KbState::new)?, + )); + + let callback = Rc::new(RefCell::new(callback)); + + let repeat = match repeatkind { + RepeatKind::System => RepeatDetails { + locked: false, + gap: None, + delay: 200, + }, + RepeatKind::Fixed { rate, delay } => { + let gap = rate_to_gap(rate as i32); + RepeatDetails { + locked: true, + gap, + delay, + } + } + }; + + // Prepare the repetition handling. + let (mut kbd_handler, source) = { + let current_repeat = Rc::new(RefCell::new(None)); + + let source = RepeatSource { + timer: calloop::timer::Timer::new().map_err(Error::TimerError)?, + state: state.clone(), + current_repeat: current_repeat.clone(), + }; + + let timer_handle = source.timer.handle(); + + let handler = KbdHandler { + callback: callback.clone(), + state, + repeat: Some(KbdRepeat { + timer_handle, + current_repeat, + details: repeat, + }), + }; + (handler, source) + }; + + let source = loop_handle + .insert_source(source, move |event, kbd, ddata| { + (&mut *callback.borrow_mut())( + event, + kbd.clone(), + wayland_client::DispatchData::wrap(ddata), + ) + }) + .map_err(|e| Error::TimerError(e.error))?; + + keyboard.quick_assign(move |keyboard, event, data| { + kbd_handler.event(keyboard.detach(), event, data) + }); + + Ok((keyboard.detach(), source)) +} + +fn rate_to_gap(rate: i32) -> Option { + if rate <= 0 { + None + } else if MICROS_IN_SECOND < rate as u32 { + NonZeroU32::new(1) + } else { + NonZeroU32::new(MICROS_IN_SECOND / rate as u32) + } +} + +/* + * Classic handling + */ + +type KbdCallback = dyn FnMut(Event<'_>, wl_keyboard::WlKeyboard, wayland_client::DispatchData<'_>); + +struct RepeatDetails { + locked: bool, + /// Gap between key presses in microseconds. + /// + /// If the `gap` is `None`, it means that repeat is disabled. + gap: Option, + /// Delay before starting key repeat in milliseconds. + delay: u32, +} + +struct KbdHandler { + state: Rc>, + callback: Rc>, + repeat: Option, +} + +struct KbdRepeat { + timer_handle: calloop::timer::TimerHandle<()>, + current_repeat: Rc>>, + details: RepeatDetails, +} + +impl KbdRepeat { + fn start_repeat(&self, key: u32, keyboard: wl_keyboard::WlKeyboard, time: u32) { + // Start a new repetition, overwriting the previous ones + self.timer_handle.cancel_all_timeouts(); + + // Handle disabled repeat rate. + let gap = match self.details.gap { + Some(gap) => gap.get() as u64, + None => return, + }; + + *self.current_repeat.borrow_mut() = Some(RepeatData { + keyboard, + keycode: key, + gap, + time: (time + self.details.delay) as u64 * 1000, + }); + self.timer_handle + .add_timeout(Duration::from_micros(self.details.delay as u64 * 1000), ()); + } + + fn stop_repeat(&self, key: u32) { + // only cancel if the released key is the currently repeating key + let mut guard = self.current_repeat.borrow_mut(); + let stop = (*guard).as_ref().map(|d| d.keycode == key).unwrap_or(false); + if stop { + self.timer_handle.cancel_all_timeouts(); + *guard = None; + } + } + + fn stop_all_repeat(&self) { + self.timer_handle.cancel_all_timeouts(); + *self.current_repeat.borrow_mut() = None; + } +} + +impl KbdHandler { + fn event( + &mut self, + kbd: wl_keyboard::WlKeyboard, + event: wl_keyboard::Event, + dispatch_data: client::DispatchData<'_>, + ) { + use wl_keyboard::Event; + + match event { + Event::Keymap { format, fd, size } => self.keymap(kbd, format, fd, size), + Event::Enter { + serial, + surface, + keys, + } => self.enter(kbd, serial, surface, keys, dispatch_data), + Event::Leave { serial, surface } => self.leave(kbd, serial, surface, dispatch_data), + Event::Key { + serial, + time, + key, + state, + } => self.key(kbd, serial, time, key, state, dispatch_data), + Event::Modifiers { + mods_depressed, + mods_latched, + mods_locked, + group, + .. + } => self.modifiers( + kbd, + mods_depressed, + mods_latched, + mods_locked, + group, + dispatch_data, + ), + Event::RepeatInfo { rate, delay } => self.repeat_info(kbd, rate, delay), + _ => {} + } + } + + fn keymap( + &mut self, + _: wl_keyboard::WlKeyboard, + format: wl_keyboard::KeymapFormat, + fd: RawFd, + size: u32, + ) { + let fd = unsafe { File::from_raw_fd(fd) }; + let mut state = self.state.borrow_mut(); + if state.locked() { + // state is locked, ignore keymap updates + return; + } + if state.ready() { + // new keymap, we first deinit to free resources + unsafe { + state.de_init(); + } + } + match format { + wl_keyboard::KeymapFormat::XkbV1 => unsafe { + state.init_with_fd(fd, size as usize); + }, + wl_keyboard::KeymapFormat::NoKeymap => { + // TODO: how to handle this (hopefully never occuring) case? + } + _ => unreachable!(), + } + } + + fn enter( + &mut self, + object: wl_keyboard::WlKeyboard, + serial: u32, + surface: wl_surface::WlSurface, + keys: Vec, + dispatch_data: client::DispatchData<'_>, + ) { + let mut state = self.state.borrow_mut(); + let rawkeys = keys + .chunks_exact(4) + .map(|c| u32::from_ne_bytes(c.try_into().unwrap())) + .collect::>(); + let keys: Vec = rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); + (&mut *self.callback.borrow_mut())( + Event::Enter { + serial, + surface, + rawkeys: &rawkeys, + keysyms: &keys, + }, + object, + dispatch_data, + ); + } + + fn leave( + &mut self, + object: wl_keyboard::WlKeyboard, + serial: u32, + surface: wl_surface::WlSurface, + dispatch_data: client::DispatchData<'_>, + ) { + { + if let Some(ref mut repeat) = self.repeat { + repeat.stop_all_repeat(); + } + } + (&mut *self.callback.borrow_mut())(Event::Leave { serial, surface }, object, dispatch_data); + } + + fn key( + &mut self, + object: wl_keyboard::WlKeyboard, + serial: u32, + time: u32, + key: u32, + key_state: wl_keyboard::KeyState, + dispatch_data: client::DispatchData<'_>, + ) { + let (sym, utf8, repeats) = { + let mut state = self.state.borrow_mut(); + // Get the values to generate a key event + let sym = state.get_one_sym_raw(key); + let utf8 = if key_state == wl_keyboard::KeyState::Pressed { + match state.compose_feed(sym) { + Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) => { + if let Some(status) = state.compose_status() { + match status { + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + state.compose_get_utf8() + } + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => { + state.get_utf8_raw(key) + } + _ => None, + } + } else { + state.get_utf8_raw(key) + } + } + Some(_) => { + // XKB_COMPOSE_FEED_IGNORED + None + } + None => { + // XKB COMPOSE is not initialized + state.get_utf8_raw(key) + } + } + } else { + None + }; + let repeats = unsafe { state.key_repeats(key + 8) }; + (sym, utf8, repeats) + }; + + { + if let Some(ref mut repeat_handle) = self.repeat { + if repeats { + if key_state == wl_keyboard::KeyState::Pressed { + repeat_handle.start_repeat(key, object.clone(), time); + } else { + repeat_handle.stop_repeat(key); + } + } + } + } + + (&mut *self.callback.borrow_mut())( + Event::Key { + serial, + time, + rawkey: key, + keysym: sym, + state: key_state, + utf8, + }, + object, + dispatch_data, + ); + } + + fn modifiers( + &mut self, + object: wl_keyboard::WlKeyboard, + mods_depressed: u32, + mods_latched: u32, + mods_locked: u32, + group: u32, + dispatch_data: client::DispatchData<'_>, + ) { + { + let mut state = self.state.borrow_mut(); + state.update_modifiers(mods_depressed, mods_latched, mods_locked, group); + (&mut *self.callback.borrow_mut())( + Event::Modifiers { + modifiers: state.mods_state(), + }, + object, + dispatch_data, + ); + } + } + + fn repeat_info(&mut self, _: wl_keyboard::WlKeyboard, rate: i32, delay: i32) { + { + if let Some(ref mut repeat_handle) = self.repeat { + if !repeat_handle.details.locked { + repeat_handle.details.gap = rate_to_gap(rate); + repeat_handle.details.delay = delay as u32; + } + } + } + } +} + +/* + * Repeat handling + */ + +struct RepeatData { + keyboard: wl_keyboard::WlKeyboard, + keycode: u32, + /// Gap between key presses in microseconds. + gap: u64, + /// Time of the last event in microseconds. + time: u64, +} + +/// An event source managing the key repetition of a keyboard +/// +/// It is given to you from [`map_keyboard`](fn.map_keyboard.html), and you need to +/// insert it in your calloop event loop if you want to have functionning key repetition. +/// +/// If don't want key repetition you can just drop it. +/// +/// This source will not directly generate calloop events, and the callback provided to +/// `EventLoopHandle::insert_source()` will be ignored. Instead it triggers the +/// callback you provided to [`map_keyboard`](fn.map_keyboard.html). +pub struct RepeatSource { + timer: calloop::timer::Timer<()>, + state: Rc>, + current_repeat: Rc>>, +} + +impl calloop::EventSource for RepeatSource { + type Event = Event<'static>; + type Metadata = wl_keyboard::WlKeyboard; + type Ret = (); + + fn process_events( + &mut self, + readiness: calloop::Readiness, + token: calloop::Token, + mut callback: F, + ) -> std::io::Result<()> + where + F: FnMut(Event<'static>, &mut wl_keyboard::WlKeyboard), + { + let current_repeat = &self.current_repeat; + let state = &self.state; + self.timer + .process_events(readiness, token, |(), timer_handle| { + if let Some(ref mut data) = *current_repeat.borrow_mut() { + // there is something to repeat + let mut state = state.borrow_mut(); + let keysym = state.get_one_sym_raw(data.keycode); + let utf8 = state.get_utf8_raw(data.keycode); + let new_time = data.gap + data.time; + // Notify the callback. + callback( + Event::Repeat { + time: (new_time / 1000) as u32, + rawkey: data.keycode, + keysym, + utf8, + }, + &mut data.keyboard, + ); + // Update the time of last event. + data.time = new_time; + // Schedule the next timeout. + timer_handle.add_timeout(Duration::from_micros(data.gap), ()); + } + }) + } + + fn register(&mut self, poll: &mut calloop::Poll, token: calloop::Token) -> std::io::Result<()> { + self.timer.register(poll, token) + } + + fn reregister( + &mut self, + poll: &mut calloop::Poll, + token: calloop::Token, + ) -> std::io::Result<()> { + self.timer.reregister(poll, token) + } + + fn unregister(&mut self, poll: &mut calloop::Poll) -> std::io::Result<()> { + self.timer.unregister(poll) + } +} diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index b63fe8bd9c..1a57b441b0 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -3,15 +3,13 @@ use std::cell::RefCell; use std::rc::Rc; +use sctk::reexports::calloop::{LoopHandle, Source}; use sctk::reexports::client::protocol::wl_keyboard::WlKeyboard; use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::client::Attached; -use sctk::reexports::calloop::{LoopHandle, RegistrationToken}; - -use sctk::seat::keyboard; - use crate::keyboard::ModifiersState; +use crate::platform_impl::platform::common::xkb_state; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::WindowId; @@ -21,36 +19,36 @@ pub(crate) struct Keyboard { pub keyboard: WlKeyboard, /// The source for repeat keys. - pub repeat_token: Option, + pub repeat_source: Option>, /// LoopHandle to drop `RepeatSource`, when dropping the keyboard. - pub loop_handle: LoopHandle<'static, WinitState>, + pub loop_handle: LoopHandle, } impl Keyboard { pub fn new( seat: &Attached, - loop_handle: LoopHandle<'static, WinitState>, + loop_handle: LoopHandle, modifiers_state: Rc>, ) -> Option { let mut inner = KeyboardInner::new(modifiers_state); - let keyboard_data = keyboard::map_keyboard_repeat( + let keyboard_data = handlers::map_keyboard_repeat( loop_handle.clone(), - seat, + &seat, None, - keyboard::RepeatKind::System, + handlers::RepeatKind::System, move |event, _, mut dispatch_data| { let winit_state = dispatch_data.get::().unwrap(); handlers::handle_keyboard(event, &mut inner, winit_state); }, ); - let (keyboard, repeat_token) = keyboard_data.ok()?; + let (keyboard, repeat_source) = keyboard_data.ok()?; Some(Self { keyboard, loop_handle, - repeat_token: Some(repeat_token), + repeat_source: Some(repeat_source), }) } } @@ -61,8 +59,8 @@ impl Drop for Keyboard { self.keyboard.release(); } - if let Some(repeat_token) = self.repeat_token.take() { - self.loop_handle.remove(repeat_token); + if let Some(repeat_source) = self.repeat_source.take() { + self.loop_handle.remove(repeat_source); } } } @@ -92,8 +90,8 @@ impl KeyboardInner { } } -impl From for ModifiersState { - fn from(mods: keyboard::ModifiersState) -> ModifiersState { +impl From for ModifiersState { + fn from(mods: xkb_state::ModifiersState) -> ModifiersState { let mut wl_mods = ModifiersState::empty(); wl_mods.set(ModifiersState::SHIFT, mods.shift); wl_mods.set(ModifiersState::CONTROL, mods.ctrl); From b444cd1deb6f490c9158aab9428ba89374260199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Mon, 10 Jan 2022 16:44:49 +0100 Subject: [PATCH 07/58] fixup! Hoist keyboard handling code from sctk into Winit --- .../linux/wayland/seat/keyboard/handlers.rs | 20 ++++++++++++------- .../linux/wayland/seat/keyboard/mod.rs | 8 ++++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index acb5dc1852..99101f8cc2 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -149,6 +149,8 @@ pub(super) fn handle_keyboard( for ch in txt.chars() { // event_sink.push_window_event(WindowEvent::ReceivedCharacter(ch), window_id); } + } + } Event::Modifiers { modifiers } => { let modifiers = ModifiersState::from(modifiers); if let Some(window_id) = inner.target_window_id { @@ -284,12 +286,12 @@ pub enum Event<'a> { /// Returns an error if xkbcommon could not be initialized, the RMLVO specification /// contained invalid values, or if the provided seat does not have keyboard capability. pub fn map_keyboard_repeat( - loop_handle: calloop::LoopHandle, + loop_handle: calloop::LoopHandle<'static, Data>, seat: &Attached, rmlvo: Option, repeatkind: RepeatKind, callback: F, -) -> Result<(wl_keyboard::WlKeyboard, calloop::Source), Error> +) -> Result<(wl_keyboard::WlKeyboard, calloop::RegistrationToken), Error> where F: FnMut(Event<'_>, wl_keyboard::WlKeyboard, wayland_client::DispatchData<'_>) + 'static, { @@ -698,7 +700,7 @@ impl calloop::EventSource for RepeatSource { readiness: calloop::Readiness, token: calloop::Token, mut callback: F, - ) -> std::io::Result<()> + ) -> std::io::Result where F: FnMut(Event<'static>, &mut wl_keyboard::WlKeyboard), { @@ -730,16 +732,20 @@ impl calloop::EventSource for RepeatSource { }) } - fn register(&mut self, poll: &mut calloop::Poll, token: calloop::Token) -> std::io::Result<()> { - self.timer.register(poll, token) + fn register( + &mut self, + poll: &mut calloop::Poll, + token_factory: &mut calloop::TokenFactory, + ) -> std::io::Result<()> { + self.timer.register(poll, token_factory) } fn reregister( &mut self, poll: &mut calloop::Poll, - token: calloop::Token, + token_factory: &mut calloop::TokenFactory, ) -> std::io::Result<()> { - self.timer.reregister(poll, token) + self.timer.reregister(poll, token_factory) } fn unregister(&mut self, poll: &mut calloop::Poll) -> std::io::Result<()> { diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index 1a57b441b0..c5d9ef6c0b 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -3,7 +3,7 @@ use std::cell::RefCell; use std::rc::Rc; -use sctk::reexports::calloop::{LoopHandle, Source}; +use sctk::reexports::calloop::{LoopHandle, RegistrationToken}; use sctk::reexports::client::protocol::wl_keyboard::WlKeyboard; use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::client::Attached; @@ -19,16 +19,16 @@ pub(crate) struct Keyboard { pub keyboard: WlKeyboard, /// The source for repeat keys. - pub repeat_source: Option>, + pub repeat_source: Option, /// LoopHandle to drop `RepeatSource`, when dropping the keyboard. - pub loop_handle: LoopHandle, + pub loop_handle: LoopHandle<'static, WinitState>, } impl Keyboard { pub fn new( seat: &Attached, - loop_handle: LoopHandle, + loop_handle: LoopHandle<'static, WinitState>, modifiers_state: Rc>, ) -> Option { let mut inner = KeyboardInner::new(modifiers_state); From 63c0370df9d22f40dd7d2ede6886115bb6b459fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 1 Apr 2021 05:40:02 +0200 Subject: [PATCH 08/58] Wire up the new events properly --- Cargo.toml | 2 +- src/platform/unix.rs | 2 +- src/platform_impl/linux/common/keymap.rs | 13 +- src/platform_impl/linux/common/xkb_state.rs | 144 +++++++++++++ src/platform_impl/linux/mod.rs | 2 +- .../linux/wayland/seat/keyboard/handlers.rs | 199 ++++++++---------- 6 files changed, 246 insertions(+), 116 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d0cb67a869..688f0f0514 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,7 +113,7 @@ percent-encoding = { version = "2.0", optional = true } parking_lot = { version = "0.12.0", optional = true } libc = "0.2.64" memmap2 = { version = "0.2.1", optional = true } -xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "e175ffe" } +xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "f335e626c" } [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 5146dee339..1c00f1674d 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -441,7 +441,7 @@ impl MonitorHandleExtUnix for MonitorHandle { impl KeyEventExtModifierSupplement for KeyEvent { #[inline] fn text_with_all_modifiers(&self) -> Option<&str> { - self.platform_specific.text_with_all_modifers + self.platform_specific.text_with_all_modifiers } #[inline] diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index 3016851dd0..86bd90b840 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -421,15 +421,13 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { keysyms::XKB_KEY_Control_R => Key::Control, keysyms::XKB_KEY_Caps_Lock => Key::CapsLock, // keysyms::XKB_KEY_Shift_Lock => Key::ShiftLock, - - // NOTE: The key xkb calls "Meta" is called "Super" by Winit, and vice versa. - // This is a tad confusing, but these keys have different names depending on who you ask. - keysyms::XKB_KEY_Meta_L => Key::Super, - keysyms::XKB_KEY_Meta_R => Key::Super, + // + keysyms::XKB_KEY_Meta_L => Key::Meta, + keysyms::XKB_KEY_Meta_R => Key::Meta, keysyms::XKB_KEY_Alt_L => Key::Alt, keysyms::XKB_KEY_Alt_R => Key::Alt, - keysyms::XKB_KEY_Super_L => Key::Meta, - keysyms::XKB_KEY_Super_R => Key::Meta, + keysyms::XKB_KEY_Super_L => Key::Super, + keysyms::XKB_KEY_Super_R => Key::Super, keysyms::XKB_KEY_Hyper_L => Key::Hyper, keysyms::XKB_KEY_Hyper_R => Key::Hyper, @@ -681,6 +679,7 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { keysyms::XKB_KEY_SunVideoRaiseBrightness => Key::BrightnessUp, // XKB_KEY_SunPowerSwitchShift // + 0 => Key::Unidentified(NativeKeyCode::Unidentified), _ => Key::Unidentified(NativeKeyCode::XKB(keysym)), } } diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 5bb3fd278c..1fa6f34a58 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -1,3 +1,5 @@ +use std::cell::RefCell; +use std::convert::TryInto; use std::env; use std::ffi::CString; use std::fs::File; @@ -12,6 +14,11 @@ use xkbcommon_dl::{ pub use sctk::seat::keyboard::RMLVO; +use crate::{ + event::ElementState, + keyboard::{Key, KeyCode, KeyLocation}, +}; + pub(crate) struct KbState { xkb_context: *mut ffi::xkb_context, xkb_keymap: *mut ffi::xkb_keymap, @@ -381,3 +388,140 @@ pub enum Error { /// Provided RMLVO specified a keymap that would not be loaded BadNames, } + +impl KbState { + pub fn process_key_event(&mut self, keycode: u32, state: ElementState) -> KeyEventResults<'_> { + KeyEventResults::new(self, keycode, state == ElementState::Pressed) + } + + pub fn process_key_repeat_event(&mut self, keycode: u32) -> KeyEventResults<'_> { + KeyEventResults::new(self, keycode, false) + } +} + +enum XkbCompose { + Accepted(ffi::xkb_compose_status), + Ignored, + Uninitialized, +} + +pub(crate) struct KeyEventResults<'a> { + state: RefCell<&'a mut KbState>, + keycode: u32, + keysym: u32, + compose: Option, +} + +impl<'a> KeyEventResults<'a> { + fn new(state: &'a mut KbState, keycode: u32, compose: bool) -> Self { + let keysym = state.get_one_sym_raw(keycode); + + let compose = if compose { + Some(match state.compose_feed(keysym) { + Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) => { + // Unwrapping is safe here, as `compose_feed` returns `None` when composition is uninitialized. + XkbCompose::Accepted(state.compose_status().unwrap()) + } + Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_IGNORED) => XkbCompose::Ignored, + None => XkbCompose::Uninitialized, + }) + } else { + None + }; + + KeyEventResults { + state: RefCell::new(state), + keycode, + keysym, + compose, + } + } + + pub fn keycode(&mut self) -> KeyCode { + super::keymap::rawkey_to_keycode(self.keycode) + } + + pub fn key(&mut self) -> (Key<'static>, KeyLocation) { + let location = super::keymap::keysym_location(self.keysym); + let mut key = super::keymap::keysym_to_key(self.keysym); + if matches!(key, Key::Unidentified(_)) { + if let Some(string) = self.state.borrow_mut().get_utf8_raw(self.keycode) { + key = Key::Character(cached_string(string)); + } + } + (key, location) + } + + pub fn key_without_modifiers(&mut self) -> (Key<'static>, KeyLocation) { + // This will become a pointer to an array which libxkbcommon owns, so we don't need to deallocate it. + let mut keysyms = ptr::null(); + let keysym_count = unsafe { + (XKBH.xkb_keymap_key_get_syms_by_level)( + self.state.borrow_mut().xkb_keymap, + self.keycode, + 0, + 0, + &mut keysyms, + ) + }; + let keysym = if keysym_count == 1 { + unsafe { *keysyms } + } else { + 0 + }; + let key = super::keymap::keysym_to_key(keysym); + let location = super::keymap::keysym_location(keysym); + (key, location) + } + + pub fn text(&mut self) -> Option<&'static str> { + let keysym = self.keysym; + self._text(|| keysym_to_utf8_raw(keysym)) + } + + pub fn text_with_all_modifiers(&mut self) -> Option<&'static str> { + // TODO: Should Ctrl override any attempts to compose text? + // gnome-terminal agrees, but konsole disagrees. + // Should it be configurable instead? + let keycode = self.keycode; + self._text(|| self.state.borrow_mut().get_utf8_raw(keycode)) + } + + fn _text(&self, fallback: F) -> Option<&'static str> + where + F: FnOnce() -> Option, + { + if let Some(compose) = &self.compose { + match compose { + XkbCompose::Accepted(status) => match status { + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + self.state.borrow_mut().compose_get_utf8() + } + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => fallback(), + _ => None, + }, + XkbCompose::Ignored | XkbCompose::Uninitialized => fallback(), + } + } else { + fallback() + } + .map(cached_string) + } +} + +fn keysym_to_utf8_raw(keysym: u32) -> Option { + let size = unsafe { (XKBH.xkb_keysym_to_utf8)(keysym, ptr::null_mut(), 0) } + 1; + if size <= 1 { + return None; + } + let mut buffer: Vec = Vec::with_capacity(size.try_into().unwrap()); + unsafe { (XKBH.xkb_keysym_to_utf8)(keysym, buffer.as_mut_ptr().cast(), buffer.len()) }; + // remove the final `\0` + buffer.pop(); + // libxkbcommon will always provide valid UTF8 + Some(unsafe { String::from_utf8_unchecked(buffer) }) +} + +fn cached_string>(string: S) -> &'static str { + Box::leak(string.into().into_boxed_str()) +} diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index ca8cc5c490..d352e68e88 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -53,8 +53,8 @@ mod common; #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct KeyEventExtra { - pub text_with_all_modifers: Option<&'static str>, pub key_without_modifiers: Key<'static>, + pub text_with_all_modifiers: Option<&'static str>, } /// Environment variable specifying which backend should be used on unix platform. diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 99101f8cc2..23e658a305 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -2,15 +2,16 @@ use sctk::reexports::calloop; use sctk::reexports::client; -use sctk::reexports::client::protocol::wl_keyboard::KeyState; -use crate::event::{ElementState, KeyEvent, WindowEvent}; -use crate::keyboard::{Key, ModifiersState, NativeKeyCode}; -use crate::platform_impl::platform::common::keymap; +use crate::keyboard::{Key, KeyLocation, ModifiersState}; use crate::platform_impl::platform::common::xkb_state::{self, RMLVO}; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::{self, DeviceId}; use crate::platform_impl::KeyEventExtra; +use crate::{ + event::{ElementState, KeyEvent, WindowEvent}, + keyboard::KeyCode, +}; use super::KeyboardInner; @@ -54,10 +55,13 @@ pub(super) fn handle_keyboard( inner.target_window_id = None; } Event::Key { - rawkey, - keysym, + physical_key, + logical_key, + text, + location, state, - utf8, + key_without_modifiers, + text_with_all_modifiers, .. } => { let window_id = match inner.target_window_id { @@ -65,16 +69,6 @@ pub(super) fn handle_keyboard( None => return, }; - let state = match state { - KeyState::Pressed => ElementState::Pressed, - KeyState::Released => ElementState::Released, - _ => unreachable!(), - }; - - let physical_key = keymap::rawkey_to_keycode(rawkey); - let logical_key = keymap::keysym_to_key(keysym); - let location = keymap::keysym_location(keysym); - event_sink.push_window_event( WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland( @@ -83,35 +77,27 @@ pub(super) fn handle_keyboard( event: KeyEvent { physical_key, logical_key, - text: None, + text, location, state, repeat: false, platform_specific: KeyEventExtra { - key_without_modifiers: Key::Unidentified(NativeKeyCode::Unidentified), - text_with_all_modifers: None, + key_without_modifiers, + text_with_all_modifiers, }, }, is_synthetic: false, }, window_id, ); - - // Send ReceivedCharacter event only on ElementState::Pressed. - if ElementState::Released == state { - return; - } - - if let Some(txt) = utf8 { - for ch in txt.chars() { - // event_sink.push_window_event(WindowEvent::ReceivedCharacter(ch), window_id); - } - } } Event::Repeat { - rawkey, - keysym, - utf8, + physical_key, + logical_key, + text, + location, + key_without_modifiers, + text_with_all_modifiers, .. } => { let window_id = match inner.target_window_id { @@ -119,10 +105,6 @@ pub(super) fn handle_keyboard( None => return, }; - let physical_key = keymap::rawkey_to_keycode(rawkey); - let logical_key = keymap::keysym_to_key(keysym); - let location = keymap::keysym_location(keysym); - event_sink.push_window_event( WindowEvent::KeyboardInput { device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland( @@ -131,25 +113,19 @@ pub(super) fn handle_keyboard( event: KeyEvent { physical_key, logical_key, - text: None, + text, location, state: ElementState::Pressed, repeat: true, platform_specific: KeyEventExtra { - key_without_modifiers: Key::Unidentified(NativeKeyCode::Unidentified), - text_with_all_modifers: None, + key_without_modifiers, + text_with_all_modifiers, }, }, is_synthetic: false, }, window_id, ); - - if let Some(txt) = utf8 { - for ch in txt.chars() { - // event_sink.push_window_event(WindowEvent::ReceivedCharacter(ch), window_id); - } - } } Event::Modifiers { modifiers } => { let modifiers = ModifiersState::from(modifiers); @@ -185,7 +161,6 @@ use sctk::reexports::client::{ protocol::{wl_keyboard, wl_seat, wl_surface}, Attached, }; -use xkbcommon_dl as ffi; use super::super::super::super::common::xkb_state::KbState; @@ -194,6 +169,7 @@ const MICROS_IN_SECOND: u32 = 1000000; /// Possible kinds of key repetition pub enum RepeatKind { /// keys will be repeated at a set rate and delay + #[allow(dead_code)] Fixed { /// The number of repetitions per second that should occur. rate: u32, @@ -251,27 +227,24 @@ pub enum Event<'a> { serial: u32, /// time at which the keypress occurred time: u32, - /// raw value of the key - rawkey: u32, - /// interpreted symbol of the key - keysym: u32, - /// new state of the key - state: KeyState, - /// utf8 interpretation of the entered text - /// - /// will always be `None` on key release events - utf8: Option, + physical_key: KeyCode, + logical_key: Key<'static>, + text: Option<&'static str>, + location: KeyLocation, + state: ElementState, + key_without_modifiers: Key<'static>, + text_with_all_modifiers: Option<&'static str>, }, /// A key repetition event Repeat { /// time at which the repetition occured time: u32, - /// raw value of the key - rawkey: u32, - /// interpreted symbol of the key - keysym: u32, - /// utf8 interpretation of the entered text - utf8: Option, + physical_key: KeyCode, + logical_key: Key<'static>, + text: Option<&'static str>, + location: KeyLocation, + key_without_modifiers: Key<'static>, + text_with_all_modifiers: Option<&'static str>, }, } @@ -564,47 +537,49 @@ impl KbdHandler { key_state: wl_keyboard::KeyState, dispatch_data: client::DispatchData<'_>, ) { - let (sym, utf8, repeats) = { + let ( + physical_key, + logical_key, + text, + location, + state, + key_without_modifiers, + text_with_all_modifiers, + repeats, + ) = { let mut state = self.state.borrow_mut(); - // Get the values to generate a key event - let sym = state.get_one_sym_raw(key); - let utf8 = if key_state == wl_keyboard::KeyState::Pressed { - match state.compose_feed(sym) { - Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) => { - if let Some(status) = state.compose_status() { - match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { - state.compose_get_utf8() - } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => { - state.get_utf8_raw(key) - } - _ => None, - } - } else { - state.get_utf8_raw(key) - } - } - Some(_) => { - // XKB_COMPOSE_FEED_IGNORED - None - } - None => { - // XKB COMPOSE is not initialized - state.get_utf8_raw(key) - } - } - } else { - None + let key_state = match key_state { + wl_keyboard::KeyState::Pressed => ElementState::Pressed, + wl_keyboard::KeyState::Released => ElementState::Released, + _ => unreachable!(), }; + + let mut ker = state.process_key_event(key, key_state); + + let physical_key = ker.keycode(); + let (logical_key, location) = ker.key(); + let text = ker.text(); + let (key_without_modifiers, _) = ker.key_without_modifiers(); + let text_with_all_modifiers = ker.text_with_all_modifiers(); + let repeats = unsafe { state.key_repeats(key + 8) }; - (sym, utf8, repeats) + + ( + physical_key, + logical_key, + text, + location, + key_state, + key_without_modifiers, + text_with_all_modifiers, + repeats, + ) }; { if let Some(ref mut repeat_handle) = self.repeat { if repeats { - if key_state == wl_keyboard::KeyState::Pressed { + if state == ElementState::Pressed { repeat_handle.start_repeat(key, object.clone(), time); } else { repeat_handle.stop_repeat(key); @@ -617,10 +592,13 @@ impl KbdHandler { Event::Key { serial, time, - rawkey: key, - keysym: sym, - state: key_state, - utf8, + physical_key, + logical_key, + text, + location, + state, + key_without_modifiers, + text_with_all_modifiers, }, object, dispatch_data, @@ -711,16 +689,25 @@ impl calloop::EventSource for RepeatSource { if let Some(ref mut data) = *current_repeat.borrow_mut() { // there is something to repeat let mut state = state.borrow_mut(); - let keysym = state.get_one_sym_raw(data.keycode); - let utf8 = state.get_utf8_raw(data.keycode); + let mut ker = state.process_key_repeat_event(data.keycode); + + let physical_key = ker.keycode(); + let (logical_key, location) = ker.key(); + let text = ker.text(); + let (key_without_modifiers, _) = ker.key_without_modifiers(); + let text_with_all_modifiers = ker.text_with_all_modifiers(); + let new_time = data.gap + data.time; // Notify the callback. callback( Event::Repeat { time: (new_time / 1000) as u32, - rawkey: data.keycode, - keysym, - utf8, + physical_key, + logical_key, + text, + location, + key_without_modifiers, + text_with_all_modifiers, }, &mut data.keyboard, ); From 2a39d69aeaed3ed41bf2156471f94bdcaa6a0d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 1 Apr 2021 06:03:36 +0200 Subject: [PATCH 09/58] Fix creation of key value strings Use `xkb_keysym_to_utf8` rather than `xkb_state_key_get_utf8` to create key value strings, as the latter performs keysym transformations, while the former doesn't. --- src/platform_impl/linux/common/xkb_state.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 1fa6f34a58..2983a503cf 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -445,7 +445,7 @@ impl<'a> KeyEventResults<'a> { let location = super::keymap::keysym_location(self.keysym); let mut key = super::keymap::keysym_to_key(self.keysym); if matches!(key, Key::Unidentified(_)) { - if let Some(string) = self.state.borrow_mut().get_utf8_raw(self.keycode) { + if let Some(string) = keysym_to_utf8_raw(self.keysym) { key = Key::Character(cached_string(string)); } } @@ -510,12 +510,21 @@ impl<'a> KeyEventResults<'a> { } fn keysym_to_utf8_raw(keysym: u32) -> Option { - let size = unsafe { (XKBH.xkb_keysym_to_utf8)(keysym, ptr::null_mut(), 0) } + 1; - if size <= 1 { - return None; + let mut buffer: Vec = Vec::with_capacity(8); + loop { + let bytes_written = unsafe { + (XKBH.xkb_keysym_to_utf8)(keysym, buffer.as_mut_ptr().cast(), buffer.capacity()) + }; + if bytes_written == 0 { + return None; + } else if bytes_written == -1 { + buffer.reserve(8); + } else { + unsafe { buffer.set_len(bytes_written.try_into().unwrap()) }; + break; + } } - let mut buffer: Vec = Vec::with_capacity(size.try_into().unwrap()); - unsafe { (XKBH.xkb_keysym_to_utf8)(keysym, buffer.as_mut_ptr().cast(), buffer.len()) }; + // remove the final `\0` buffer.pop(); // libxkbcommon will always provide valid UTF8 From 0f57043c48b6b087aca56ff59197840566b881c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 1 Apr 2021 07:37:32 +0200 Subject: [PATCH 10/58] Add missing keysym mapping I accidentally skipped over `XKB_KEY_Page_Down` while initially mapping keysyms. --- src/platform_impl/linux/common/keymap.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index 86bd90b840..dbd0431679 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -318,6 +318,7 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // keysyms::XKB_KEY_Prior => Key::PageUp, keysyms::XKB_KEY_Page_Up => Key::PageUp, // keysyms::XKB_KEY_Next => Key::PageDown, + keysyms::XKB_KEY_Page_Down => Key::PageDown, keysyms::XKB_KEY_End => Key::End, // keysyms::XKB_KEY_Begin => Key::Begin, From e41c35b9466a078b877d3a1518a29d72e569a521 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 1 Apr 2021 08:18:20 +0200 Subject: [PATCH 11/58] Fix `key_without_modifiers` I forgot about the offset between evdev keycodes and xkb keycodes. --- src/platform_impl/linux/common/xkb_state.rs | 22 +++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 2983a503cf..cc200c3a5d 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -442,14 +442,7 @@ impl<'a> KeyEventResults<'a> { } pub fn key(&mut self) -> (Key<'static>, KeyLocation) { - let location = super::keymap::keysym_location(self.keysym); - let mut key = super::keymap::keysym_to_key(self.keysym); - if matches!(key, Key::Unidentified(_)) { - if let Some(string) = keysym_to_utf8_raw(self.keysym) { - key = Key::Character(cached_string(string)); - } - } - (key, location) + Self::keysym_to_key(self.keysym) } pub fn key_without_modifiers(&mut self) -> (Key<'static>, KeyLocation) { @@ -458,7 +451,7 @@ impl<'a> KeyEventResults<'a> { let keysym_count = unsafe { (XKBH.xkb_keymap_key_get_syms_by_level)( self.state.borrow_mut().xkb_keymap, - self.keycode, + self.keycode + 8, 0, 0, &mut keysyms, @@ -469,8 +462,17 @@ impl<'a> KeyEventResults<'a> { } else { 0 }; - let key = super::keymap::keysym_to_key(keysym); + Self::keysym_to_key(keysym) + } + + fn keysym_to_key(keysym: u32) -> (Key<'static>, KeyLocation) { let location = super::keymap::keysym_location(keysym); + let mut key = super::keymap::keysym_to_key(keysym); + if matches!(key, Key::Unidentified(_)) { + if let Some(string) = keysym_to_utf8_raw(keysym) { + key = Key::Character(cached_string(string)); + } + } (key, location) } From c9f8bb0ea5b89046b6bd824b7d65d545366d4441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 1 Apr 2021 08:42:24 +0200 Subject: [PATCH 12/58] Feature-gate things which depend on memmap2 --- src/platform_impl/linux/common/xkb_state.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index cc200c3a5d..147a009e31 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -7,6 +7,7 @@ use std::os::raw::c_char; use std::os::unix::ffi::OsStringExt; use std::ptr; +#[cfg(feature = "wayland")] use memmap2::MmapOptions; use xkbcommon_dl::{ self as ffi, xkb_state_component, XKBCOMMON_COMPOSE_HANDLE as XKBCH, XKBCOMMON_HANDLE as XKBH, @@ -313,6 +314,7 @@ impl KbState { self.xkb_keymap = ptr::null_mut(); } + #[cfg(feature = "wayland")] pub(crate) unsafe fn init_with_fd(&mut self, fd: File, size: usize) { let map = MmapOptions::new().len(size).map(&fd).unwrap(); From a5bcc620cccff6e55c301073c9082dab5d5c3b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 1 Apr 2021 08:47:01 +0200 Subject: [PATCH 13/58] Be more consistent with what `keycode` means --- src/platform_impl/linux/common/xkb_state.rs | 4 ++-- src/platform_impl/linux/wayland/seat/keyboard/handlers.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 147a009e31..fa1e3e4fda 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -351,8 +351,8 @@ impl KbState { Ok(()) } - pub(crate) unsafe fn key_repeats(&mut self, xkb_keycode_t: ffi::xkb_keycode_t) -> bool { - (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, xkb_keycode_t) == 1 + pub(crate) unsafe fn key_repeats(&mut self, keycode: ffi::xkb_keycode_t) -> bool { + (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, keycode + 8) == 1 } #[inline] diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 23e658a305..15bc1869d4 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -562,7 +562,7 @@ impl KbdHandler { let (key_without_modifiers, _) = ker.key_without_modifiers(); let text_with_all_modifiers = ker.text_with_all_modifiers(); - let repeats = unsafe { state.key_repeats(key + 8) }; + let repeats = unsafe { state.key_repeats(key) }; ( physical_key, From 5d91b7951de9ad46bc79b41fb57e9bd69d3cafd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 1 Apr 2021 10:12:12 +0200 Subject: [PATCH 14/58] Improve key string handling --- src/platform_impl/linux/common/xkb_state.rs | 141 ++++++++++++-------- 1 file changed, 83 insertions(+), 58 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index fa1e3e4fda..ab957920f9 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -1,4 +1,3 @@ -use std::cell::RefCell; use std::convert::TryInto; use std::env; use std::ffi::CString; @@ -28,6 +27,7 @@ pub(crate) struct KbState { xkb_compose_state: *mut ffi::xkb_compose_state, mods_state: ModifiersState, locked: bool, + scratch_buffer: Vec, } /// Represents the current state of the keyboard modifiers @@ -140,7 +140,7 @@ impl KbState { unsafe { (XKBH.xkb_state_key_get_one_sym)(self.xkb_state, keycode + 8) } } - pub(crate) fn get_utf8_raw(&mut self, keycode: u32) -> Option { + pub(crate) fn get_utf8_raw(&mut self, keycode: u32) -> Option<&'static str> { if !self.ready() { return None; } @@ -150,20 +150,21 @@ impl KbState { if size <= 1 { return None; }; - let mut buffer = Vec::with_capacity(size as usize); + self.scratch_buffer.clear(); + let size = size.try_into().unwrap(); + self.scratch_buffer.reserve(size); unsafe { - buffer.set_len(size as usize); + self.scratch_buffer.set_len(size); (XKBH.xkb_state_key_get_utf8)( self.xkb_state, keycode + 8, - buffer.as_mut_ptr() as *mut _, - size as usize, + self.scratch_buffer.as_mut_ptr() as *mut _, + size, ); }; // remove the final `\0` - buffer.pop(); - // libxkbcommon will always provide valid UTF8 - Some(unsafe { String::from_utf8_unchecked(buffer) }) + self.scratch_buffer.pop(); + Some(byte_slice_to_cached_string(&self.scratch_buffer)) } pub(crate) fn compose_feed(&mut self, keysym: u32) -> Option { @@ -180,7 +181,7 @@ impl KbState { Some(unsafe { (XKBCH.xkb_compose_state_get_status)(self.xkb_compose_state) }) } - pub(crate) fn compose_get_utf8(&mut self) -> Option { + pub(crate) fn compose_get_utf8(&mut self) -> Option<&'static str> { if !self.ready() || self.xkb_compose_state.is_null() { return None; } @@ -190,19 +191,20 @@ impl KbState { if size <= 1 { return None; }; - let mut buffer = Vec::with_capacity(size as usize); + self.scratch_buffer.clear(); + let size = size.try_into().unwrap(); + self.scratch_buffer.reserve(size); unsafe { - buffer.set_len(size as usize); + self.scratch_buffer.set_len(size); (XKBCH.xkb_compose_state_get_utf8)( self.xkb_compose_state, - buffer.as_mut_ptr() as *mut _, + self.scratch_buffer.as_mut_ptr() as *mut _, size as usize, ); }; // remove the final `\0` - buffer.pop(); - // libxkbcommon will always provide valid UTF8 - Some(unsafe { String::from_utf8_unchecked(buffer) }) + self.scratch_buffer.pop(); + Some(byte_slice_to_cached_string(&self.scratch_buffer)) } pub(crate) fn new() -> Result { @@ -225,6 +227,7 @@ impl KbState { xkb_compose_state: ptr::null_mut(), mods_state: ModifiersState::new(), locked: false, + scratch_buffer: Vec::new(), }; unsafe { @@ -399,6 +402,36 @@ impl KbState { pub fn process_key_repeat_event(&mut self, keycode: u32) -> KeyEventResults<'_> { KeyEventResults::new(self, keycode, false) } + + fn keysym_to_utf8_raw(&mut self, keysym: u32) -> Option<&'static str> { + self.scratch_buffer.clear(); + self.scratch_buffer.reserve(8); + loop { + unsafe { self.scratch_buffer.set_len(8) }; + let bytes_written = unsafe { + (XKBH.xkb_keysym_to_utf8)( + keysym, + self.scratch_buffer.as_mut_ptr().cast(), + self.scratch_buffer.capacity(), + ) + }; + if bytes_written == 0 { + return None; + } else if bytes_written == -1 { + self.scratch_buffer.reserve(8); + } else { + unsafe { + self.scratch_buffer + .set_len(bytes_written.try_into().unwrap()) + }; + break; + } + } + + // remove the final `\0` + self.scratch_buffer.pop(); + Some(byte_slice_to_cached_string(&self.scratch_buffer)) + } } enum XkbCompose { @@ -408,7 +441,7 @@ enum XkbCompose { } pub(crate) struct KeyEventResults<'a> { - state: RefCell<&'a mut KbState>, + state: &'a mut KbState, keycode: u32, keysym: u32, compose: Option, @@ -432,7 +465,7 @@ impl<'a> KeyEventResults<'a> { }; KeyEventResults { - state: RefCell::new(state), + state, keycode, keysym, compose, @@ -444,7 +477,7 @@ impl<'a> KeyEventResults<'a> { } pub fn key(&mut self) -> (Key<'static>, KeyLocation) { - Self::keysym_to_key(self.keysym) + self.keysym_to_key(self.keysym) } pub fn key_without_modifiers(&mut self) -> (Key<'static>, KeyLocation) { @@ -452,7 +485,7 @@ impl<'a> KeyEventResults<'a> { let mut keysyms = ptr::null(); let keysym_count = unsafe { (XKBH.xkb_keymap_key_get_syms_by_level)( - self.state.borrow_mut().xkb_keymap, + self.state.xkb_keymap, self.keycode + 8, 0, 0, @@ -464,77 +497,69 @@ impl<'a> KeyEventResults<'a> { } else { 0 }; - Self::keysym_to_key(keysym) + self.keysym_to_key(keysym) } - fn keysym_to_key(keysym: u32) -> (Key<'static>, KeyLocation) { + fn keysym_to_key(&mut self, keysym: u32) -> (Key<'static>, KeyLocation) { let location = super::keymap::keysym_location(keysym); let mut key = super::keymap::keysym_to_key(keysym); if matches!(key, Key::Unidentified(_)) { - if let Some(string) = keysym_to_utf8_raw(keysym) { - key = Key::Character(cached_string(string)); + if let Some(string) = self.state.keysym_to_utf8_raw(keysym) { + key = Key::Character(string); } } (key, location) } pub fn text(&mut self) -> Option<&'static str> { - let keysym = self.keysym; - self._text(|| keysym_to_utf8_raw(keysym)) + self._text(|this| this.state.keysym_to_utf8_raw(this.keysym)) } pub fn text_with_all_modifiers(&mut self) -> Option<&'static str> { // TODO: Should Ctrl override any attempts to compose text? // gnome-terminal agrees, but konsole disagrees. // Should it be configurable instead? - let keycode = self.keycode; - self._text(|| self.state.borrow_mut().get_utf8_raw(keycode)) + self._text(|this| this.state.get_utf8_raw(this.keycode)) } - fn _text(&self, fallback: F) -> Option<&'static str> + fn _text(&mut self, fallback: F) -> Option<&'static str> where - F: FnOnce() -> Option, + F: FnOnce(&mut Self) -> Option<&'static str>, { if let Some(compose) = &self.compose { match compose { XkbCompose::Accepted(status) => match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { - self.state.borrow_mut().compose_get_utf8() - } - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => fallback(), + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => self.state.compose_get_utf8(), + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => fallback(self), _ => None, }, - XkbCompose::Ignored | XkbCompose::Uninitialized => fallback(), + XkbCompose::Ignored | XkbCompose::Uninitialized => fallback(self), } } else { - fallback() + fallback(self) } - .map(cached_string) } } -fn keysym_to_utf8_raw(keysym: u32) -> Option { - let mut buffer: Vec = Vec::with_capacity(8); - loop { - let bytes_written = unsafe { - (XKBH.xkb_keysym_to_utf8)(keysym, buffer.as_mut_ptr().cast(), buffer.capacity()) - }; - if bytes_written == 0 { - return None; - } else if bytes_written == -1 { - buffer.reserve(8); - } else { - unsafe { buffer.set_len(bytes_written.try_into().unwrap()) }; - break; - } +fn byte_slice_to_cached_string(bytes: &[u8]) -> &'static str { + use std::cell::RefCell; + use std::collections::HashSet; + + thread_local! { + static STRING_CACHE: RefCell> = RefCell::new(HashSet::new()); } - // remove the final `\0` - buffer.pop(); - // libxkbcommon will always provide valid UTF8 - Some(unsafe { String::from_utf8_unchecked(buffer) }) -} + let string = std::str::from_utf8(bytes).unwrap(); -fn cached_string>(string: S) -> &'static str { - Box::leak(string.into().into_boxed_str()) + STRING_CACHE.with(|cache| { + let mut cache = cache.borrow_mut(); + if let Some(string) = cache.get(string) { + *string + } else { + // borrowck couldn't quite figure out this one on its own + let string: &'static str = Box::leak(String::from(string).into_boxed_str()); + cache.insert(string); + string + } + }) } From 08df35cecbd69040ad29ca0012d1e6375539f183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sat, 24 Apr 2021 18:06:34 +0200 Subject: [PATCH 15/58] Add initial X11 support --- src/platform_impl/linux/common/xkb_state.rs | 41 ++++++++++ .../linux/x11/event_processor.rs | 78 ++++++++++++------- src/platform_impl/linux/x11/mod.rs | 6 ++ 3 files changed, 96 insertions(+), 29 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index ab957920f9..59e03146f4 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -8,6 +8,11 @@ use std::ptr; #[cfg(feature = "wayland")] use memmap2::MmapOptions; +#[cfg(feature = "x11")] +use x11_dl::xlib_xcb::xcb_connection_t; +#[cfg(feature = "x11")] +use xkbcommon_dl::x11::XKBCOMMON_X11_HANDLE as XKBXH; + use xkbcommon_dl::{ self as ffi, xkb_state_component, XKBCOMMON_COMPOSE_HANDLE as XKBCH, XKBCOMMON_HANDLE as XKBH, }; @@ -237,6 +242,42 @@ impl KbState { Ok(me) } + #[cfg(feature = "x11")] + pub(crate) fn from_x11_xkb(connection: *mut xcb_connection_t) -> Result { + let mut me = Self::new()?; + + let result = unsafe { + (XKBXH.xkb_x11_setup_xkb_extension)( + connection, + 1, + 2, + xkbcommon_dl::x11::xkb_x11_setup_xkb_extension_flags::XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ) + }; + assert_eq!(result, 1, "Failed to initialize libxkbcommon"); + + // TODO: Support keyboards other than the "virtual core keyboard device". + let core_keyboard_id = unsafe { (XKBXH.xkb_x11_get_core_keyboard_device_id)(connection) }; + let keymap = unsafe { + (XKBXH.xkb_x11_keymap_new_from_device)( + me.xkb_context, + connection, + core_keyboard_id, + xkbcommon_dl::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS, + ) + }; + assert_ne!(keymap, ptr::null_mut()); + me.xkb_keymap = keymap; + + unsafe { me.post_init(keymap) }; + + Ok(me) + } + pub(crate) fn from_rmlvo(rmlvo: RMLVO) -> Result { fn to_cstring(s: Option) -> Result, Error> { s.map_or(Ok(None), |s| CString::new(s).map(Option::Some)) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 7b3b8bd372..832e32c223 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1,13 +1,12 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc, slice, sync::Arc}; -use libc::{c_char, c_int, c_long, c_uint, c_ulong}; +use libc::{c_char, c_int, c_long, c_ulong}; use parking_lot::MutexGuard; use super::{ - events, ffi, get_xtarget, mkdid, mkwid, monitor, util, Device, DeviceId, DeviceInfo, Dnd, - DndState, GenericEventCookie, ImeReceiver, ScrollOrientation, UnownedWindow, WindowId, - XExtension, + ffi, get_xtarget, mkdid, mkwid, monitor, util, Device, DeviceId, DeviceInfo, Dnd, DndState, + GenericEventCookie, ImeReceiver, ScrollOrientation, UnownedWindow, WindowId, XExtension, }; use util::modifiers::{ModifierKeyState, ModifierKeymap}; @@ -20,6 +19,10 @@ use crate::{ }, event_loop::EventLoopWindowTarget as RootELW, keyboard::ModifiersState, + platform_impl::platform::{ + common::{keymap, xkb_state::KbState}, + KeyEventExtra, + }, }; /// The X11 documentation states: "Keycodes lie in the inclusive range [8,255]". @@ -33,6 +36,7 @@ pub(super) struct EventProcessor { pub(super) devices: RefCell>, pub(super) xi2ext: XExtension, pub(super) target: Rc>, + pub(super) kb_state: KbState, pub(super) mod_keymap: ModifierKeymap, pub(super) device_mod_state: ModifierKeyState, // Number of touch events currently in progress @@ -572,29 +576,34 @@ impl EventProcessor { // When a compose sequence or IME pre-edit is finished, it ends in a KeyPress with // a keycode of 0. if keycode != 0 && !self.is_composing { - let scancode = keycode - KEYCODE_OFFSET as u32; - let keysym = wt.xconn.lookup_keysym(xkev); - // let virtual_keycode = events::keysym_to_element(keysym as c_uint); + let keycode = keycode - KEYCODE_OFFSET as u32; + let mut ker = self.kb_state.process_key_event(keycode, state); + let physical_key = ker.keycode(); + let (logical_key, location) = ker.key(); + let text = ker.text(); + let (key_without_modifiers, _) = ker.key_without_modifiers(); + let text_with_all_modifiers = ker.text_with_all_modifiers(); update_modifiers!( ModifiersState::from_x11_mask(xkev.state), self.mod_keymap.get_modifier(xkev.keycode as ffi::KeyCode) ); - let modifiers = self.device_mod_state.modifiers(); - callback(Event::WindowEvent { window_id, event: WindowEvent::KeyboardInput { device_id, event: KeyEvent { - physical_key: todo!(), - logical_key: todo!(), - text: todo!(), - location: todo!(), + physical_key, + logical_key, + text, + location, state, - repeat: todo!(), - platform_specific: todo!(), + repeat: false, + platform_specific: KeyEventExtra { + key_without_modifiers, + text_with_all_modifiers, + }, }, is_synthetic: false, }, @@ -951,6 +960,7 @@ impl EventProcessor { wt, window_id, ElementState::Pressed, + &mut self.kb_state, &self.mod_keymap, &mut self.device_mod_state, &mut callback, @@ -978,6 +988,7 @@ impl EventProcessor { wt, window_id, ElementState::Released, + &mut self.kb_state, &self.mod_keymap, &mut self.device_mod_state, &mut callback, @@ -1120,18 +1131,19 @@ impl EventProcessor { if scancode < 0 { return; } - let keysym = wt.xconn.keycode_to_keysym(keycode as ffi::KeyCode); - // let virtual_keycode = events::keysym_to_element(keysym as c_uint); + let physical_key = keymap::rawkey_to_keycode(scancode as u32); let modifiers = self.device_mod_state.modifiers(); callback(Event::DeviceEvent { device_id, event: DeviceEvent::Key(RawKeyEvent { - physical_key: todo!(), - state: todo!(), + physical_key, + state, }), }); + // `ModifiersChanged` is dispatched here because we assume that every `KeyPress` is + // preceeded by a `RawKeyPress`. if let Some(modifier) = self.mod_keymap.get_modifier(keycode as ffi::KeyCode) { @@ -1308,6 +1320,7 @@ impl EventProcessor { wt: &super::EventLoopWindowTarget, window_id: crate::window::WindowId, state: ElementState, + kb_state: &mut KbState, mod_keymap: &ModifierKeymap, device_mod_state: &mut ModifierKeyState, callback: &mut F, @@ -1324,9 +1337,13 @@ impl EventProcessor { .into_iter() .filter(|k| *k >= KEYCODE_OFFSET) { - let scancode = (keycode - KEYCODE_OFFSET) as u32; - let keysym = wt.xconn.keycode_to_keysym(keycode); - // let virtual_keycode = events::keysym_to_element(keysym as c_uint); + let keycode = (keycode - KEYCODE_OFFSET) as u32; + let mut ker = kb_state.process_key_event(keycode, state); + let physical_key = ker.keycode(); + let (logical_key, location) = ker.key(); + let text = ker.text(); + let (key_without_modifiers, _) = ker.key_without_modifiers(); + let text_with_all_modifiers = ker.text_with_all_modifiers(); if let Some(modifier) = mod_keymap.get_modifier(keycode as ffi::KeyCode) { device_mod_state.key_event( @@ -1341,13 +1358,16 @@ impl EventProcessor { event: WindowEvent::KeyboardInput { device_id, event: KeyEvent { - physical_key: todo!(), - logical_key: todo!(), - text: todo!(), - location: todo!(), - state: todo!(), - repeat: todo!(), - platform_specific: todo!(), + physical_key, + logical_key, + text, + location, + state, + repeat: false, + platform_specific: KeyEventExtra { + key_without_modifiers, + text_with_all_modifiers, + }, }, is_synthetic: true, }, diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 966d526188..f0027440fa 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -47,6 +47,7 @@ use self::{ ime::{Ime, ImeCreationError, ImeReceiver, ImeRequest, ImeSender}, util::modifiers::ModifierKeymap, }; +use super::common::xkb_state::KbState; use crate::{ error::OsError as RootOsError, event::{Event, StartCause}, @@ -233,6 +234,10 @@ impl EventLoop { let (user_sender, user_channel) = std::sync::mpsc::channel(); let (redraw_sender, redraw_channel) = std::sync::mpsc::channel(); + let kb_state = + KbState::from_x11_xkb(unsafe { (xconn.xlib_xcb.XGetXCBConnection)(xconn.display) }) + .unwrap(); + let window_target = EventLoopWindowTarget { ime, root, @@ -265,6 +270,7 @@ impl EventLoop { ime_receiver, ime_event_receiver, xi2ext, + kb_state, mod_keymap, device_mod_state: Default::default(), num_touch: 0, From 6297e99411a0aa16ffdf1cb2cb28e4cc1adfdfe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sun, 25 Apr 2021 18:55:46 +0200 Subject: [PATCH 16/58] Address compilation errors --- Cargo.toml | 4 ++-- src/platform_impl/linux/common/keymap.rs | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 688f0f0514..363bf15819 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ targets = [ [features] default = ["x11", "wayland", "wayland-dlopen", "wayland-csd-adwaita"] -x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot"] +x11 = ["x11-dl", "mio", "percent-encoding", "parking_lot", "xkbcommon-dl/x11"] wayland = ["wayland-client", "wayland-protocols", "sctk", "memmap2"] wayland-dlopen = ["sctk/dlopen", "wayland-client/dlopen"] wayland-csd-adwaita = ["sctk-adwaita", "sctk-adwaita/title"] @@ -113,7 +113,7 @@ percent-encoding = { version = "2.0", optional = true } parking_lot = { version = "0.12.0", optional = true } libc = "0.2.64" memmap2 = { version = "0.2.1", optional = true } -xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "f335e626c" } +xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "5307184" } [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index dbd0431679..4f72adc8f9 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -423,8 +423,9 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { keysyms::XKB_KEY_Caps_Lock => Key::CapsLock, // keysyms::XKB_KEY_Shift_Lock => Key::ShiftLock, // - keysyms::XKB_KEY_Meta_L => Key::Meta, - keysyms::XKB_KEY_Meta_R => Key::Meta, + // TODO: Address how renaming `Meta` to `Super` affects this set of keys. + // keysyms::XKB_KEY_Meta_L => Key::Meta, + // keysyms::XKB_KEY_Meta_R => Key::Meta, keysyms::XKB_KEY_Alt_L => Key::Alt, keysyms::XKB_KEY_Alt_R => Key::Alt, keysyms::XKB_KEY_Super_L => Key::Super, From 31759f783ce980f5d38d3f1574fa50653482243f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sat, 24 Apr 2021 18:06:59 +0200 Subject: [PATCH 17/58] Improve debug printing of `NativeKeyCode` --- src/keyboard.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/keyboard.rs b/src/keyboard.rs index a63ef31a9a..9ab9919979 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -195,7 +195,7 @@ impl std::fmt::Debug for NativeKeyCode { } XKB(v) => { debug_tuple = f.debug_tuple(name_of!(XKB)); - debug_tuple.field(v); + debug_tuple.field(&format_args!("0x{:04X}", v)); } } debug_tuple.finish() From 2729cd9b3709cc74737252d93549cd1aa2bc9ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Wed, 28 Apr 2021 17:33:41 +0200 Subject: [PATCH 18/58] Hook up X11 XKB modifier keys --- src/platform_impl/linux/common/xkb_state.rs | 10 +++--- .../linux/wayland/seat/keyboard/handlers.rs | 2 +- .../linux/x11/event_processor.rs | 24 +++++++++++++- src/platform_impl/linux/x11/mod.rs | 31 +++++++++++++++++++ 4 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 59e03146f4..ce85501ee4 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -116,7 +116,9 @@ impl KbState { mods_depressed: u32, mods_latched: u32, mods_locked: u32, - group: u32, + depressed_group: u32, + latched_group: u32, + locked_group: u32, ) { if !self.ready() { return; @@ -127,9 +129,9 @@ impl KbState { mods_depressed, mods_latched, mods_locked, - 0, - 0, - group, + depressed_group, + latched_group, + locked_group, ) }; if mask.contains(xkb_state_component::XKB_STATE_MODS_EFFECTIVE) { diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 15bc1869d4..ee4188bde5 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -616,7 +616,7 @@ impl KbdHandler { ) { { let mut state = self.state.borrow_mut(); - state.update_modifiers(mods_depressed, mods_latched, mods_locked, group); + state.update_modifiers(mods_depressed, mods_latched, mods_locked, 0, 0, group); (&mut *self.callback.borrow_mut())( Event::Modifiers { modifiers: state.mods_state(), diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 832e32c223..2f7f1dd934 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, collections::HashMap, rc::Rc, slice, sync::Arc}; +use std::{cell::RefCell, collections::HashMap, convert::identity, rc::Rc, slice, sync::Arc}; use libc::{c_char, c_int, c_long, c_ulong}; @@ -35,6 +35,7 @@ pub(super) struct EventProcessor { pub(super) randr_event_offset: c_int, pub(super) devices: RefCell>, pub(super) xi2ext: XExtension, + pub(super) xkbext: XExtension, pub(super) target: Rc>, pub(super) kb_state: KbState, pub(super) mod_keymap: ModifierKeymap, @@ -1193,6 +1194,27 @@ impl EventProcessor { } } _ => { + if event_type == self.xkbext.first_event_id { + let xev = unsafe { &*(identity(xev) as *const _ as *const ffi::XkbAnyEvent) }; + match xev.xkb_type { + ffi::XkbStateNotify => { + let xev = + unsafe { &*(xev as *const _ as *const ffi::XkbStateNotifyEvent) }; + if matches!(xev.event_type, 2 | 3) { + // TODO: Is `as u32` fine here? + self.kb_state.update_modifiers( + xev.base_mods, + xev.latched_mods, + xev.locked_mods, + u32::from_ne_bytes(xev.base_group.to_ne_bytes()), + u32::from_ne_bytes(xev.latched_group.to_ne_bytes()), + u32::from_ne_bytes(xev.locked_group.to_ne_bytes()), + ) + } + } + _ => {} + } + } if event_type == self.randr_event_offset { // In the future, it would be quite easy to emit monitor hotplug events. let prev_list = monitor::invalidate_cached_monitor_list(); diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index f0027440fa..795c0ccb20 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -203,6 +203,27 @@ impl EventLoop { ext }; + let xkbext = { + let mut ext = XExtension::default(); + + let res = unsafe { + (xconn.xlib.XkbQueryExtension)( + xconn.display, + &mut ext.opcode, + &mut ext.first_event_id, + &mut ext.first_error_id, + &mut 1, + &mut 0, + ) + }; + + if res == ffi::False { + panic!("X server missing XKB extension"); + } + + ext + }; + unsafe { let mut xinput_major_ver = ffi::XI_2_Major; let mut xinput_minor_ver = ffi::XI_2_Minor; @@ -270,6 +291,7 @@ impl EventLoop { ime_receiver, ime_event_receiver, xi2ext, + xkbext, kb_state, mod_keymap, device_mod_state: Default::default(), @@ -286,6 +308,15 @@ impl EventLoop { .select_xinput_events(root, ffi::XIAllDevices, ffi::XI_HierarchyChangedMask) .queue(); + get_xtarget(&target) + .xconn + .select_xkb_events( + 0x100, // Use the "core keyboard device" + ffi::XkbNewKeyboardNotifyMask | ffi::XkbMapNotifyMask | ffi::XkbStateNotifyMask, + ) + .unwrap() + .queue(); + event_processor.init_device(ffi::XIAllDevices); EventLoop { From b33759062c9a88cbae17d0e4ce9788091eb43a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sat, 1 May 2021 19:56:51 +0200 Subject: [PATCH 19/58] Use XInput2 for regular key events --- .../linux/x11/event_processor.rs | 92 +++++++++++-------- src/platform_impl/linux/x11/mod.rs | 1 + src/platform_impl/linux/x11/util/input.rs | 2 +- src/platform_impl/linux/x11/window.rs | 2 - 4 files changed, 54 insertions(+), 43 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 2f7f1dd934..1ab4a4b7e7 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -574,43 +574,6 @@ impl EventProcessor { let device_id = mkdid(device); let keycode = xkev.keycode; - // When a compose sequence or IME pre-edit is finished, it ends in a KeyPress with - // a keycode of 0. - if keycode != 0 && !self.is_composing { - let keycode = keycode - KEYCODE_OFFSET as u32; - let mut ker = self.kb_state.process_key_event(keycode, state); - let physical_key = ker.keycode(); - let (logical_key, location) = ker.key(); - let text = ker.text(); - let (key_without_modifiers, _) = ker.key_without_modifiers(); - let text_with_all_modifiers = ker.text_with_all_modifiers(); - - update_modifiers!( - ModifiersState::from_x11_mask(xkev.state), - self.mod_keymap.get_modifier(xkev.keycode as ffi::KeyCode) - ); - - callback(Event::WindowEvent { - window_id, - event: WindowEvent::KeyboardInput { - device_id, - event: KeyEvent { - physical_key, - logical_key, - text, - location, - state, - repeat: false, - platform_specific: KeyEventExtra { - key_without_modifiers, - text_with_all_modifiers, - }, - }, - is_synthetic: false, - }, - }); - } - if state == Pressed { let written = if let Some(ic) = wt.ime.borrow().get_context(window) { wt.xconn.lookup_utf8(ic, xkev) @@ -1117,6 +1080,56 @@ impl EventProcessor { } } + // The regular KeyPress event has a problem where if you press a dead key, a KeyPress + // event won't be emitted. XInput 2 does not have this problem. + ffi::XI_KeyPress | ffi::XI_KeyRelease if !self.is_composing => { + if let Some(active_window) = self.active_window { + let state = if xev.evtype == ffi::XI_KeyPress { + Pressed + } else { + Released + }; + + let xkev: &ffi::XIDeviceEvent = unsafe { &*(xev.data as *const _) }; + + // We use `self.active_window` here as `xkev.event` has a completely different + // value for some reason. + let window_id = mkwid(active_window); + + let device_id = mkdid(xkev.deviceid); + let keycode = xkev.detail as u32; + + let keycode = keycode - KEYCODE_OFFSET as u32; + let mut ker = self.kb_state.process_key_event(keycode, state); + let physical_key = ker.keycode(); + let (logical_key, location) = ker.key(); + let text = ker.text(); + let (key_without_modifiers, _) = ker.key_without_modifiers(); + let text_with_all_modifiers = ker.text_with_all_modifiers(); + let repeat = xkev.flags & ffi::XIKeyRepeat == ffi::XIKeyRepeat; + + callback(Event::WindowEvent { + window_id, + event: WindowEvent::KeyboardInput { + device_id, + event: KeyEvent { + physical_key, + logical_key, + text, + location, + state, + repeat, + platform_specific: KeyEventExtra { + key_without_modifiers, + text_with_all_modifiers, + }, + }, + is_synthetic: false, + }, + }); + } + } + ffi::XI_RawKeyPress | ffi::XI_RawKeyRelease => { let xev: &ffi::XIRawEvent = unsafe { &*(xev.data as *const _) }; @@ -1143,8 +1156,8 @@ impl EventProcessor { }), }); - // `ModifiersChanged` is dispatched here because we assume that every `KeyPress` is - // preceeded by a `RawKeyPress`. + // `ModifiersChanged` is dispatched here because we assume that every `XI_KeyPress` + // is preceeded by a `XI_RawKeyPress`. if let Some(modifier) = self.mod_keymap.get_modifier(keycode as ffi::KeyCode) { @@ -1350,7 +1363,6 @@ impl EventProcessor { F: FnMut(Event<'_, T>), { let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD); - let modifiers = device_mod_state.modifiers(); // Update modifiers state and emit key events based on which keys are currently pressed. for keycode in wt diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 795c0ccb20..c6a33645b6 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -590,6 +590,7 @@ impl EventLoopWindowTarget { | ffi::XI_RawKeyPressMask | ffi::XI_RawKeyReleaseMask; } + mask |= ffi::XI_KeyPressMask | ffi::XI_KeyReleaseMask; self.xconn .select_xinput_events(self.root, ffi::XIAllDevices, mask) diff --git a/src/platform_impl/linux/x11/util/input.rs b/src/platform_impl/linux/x11/util/input.rs index 6c7c651eed..db0f22eb03 100644 --- a/src/platform_impl/linux/x11/util/input.rs +++ b/src/platform_impl/linux/x11/util/input.rs @@ -81,12 +81,12 @@ impl XConnection { Flusher::new(self) } - #[allow(dead_code)] pub fn select_xkb_events(&self, device_id: c_uint, mask: c_ulong) -> Option> { let status = unsafe { (self.xlib.XkbSelectEvents)(self.display, device_id, mask, mask) }; if status == ffi::True { Some(Flusher::new(self)) } else { + // This should only happen if the XKB extension isn't initialized. None } } diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 89ac8e46c6..3cbcb30ac7 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -235,8 +235,6 @@ impl UnownedWindow { swa.event_mask = ffi::ExposureMask | ffi::StructureNotifyMask | ffi::VisibilityChangeMask - | ffi::KeyPressMask - | ffi::KeyReleaseMask | ffi::KeymapStateMask | ffi::ButtonPressMask | ffi::ButtonReleaseMask From ad0916dc06dc990357403636c4a25397f3b5ff50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Fri, 7 May 2021 17:20:54 +0200 Subject: [PATCH 20/58] Implement dead-key handling --- src/platform_impl/linux/common/xkb_state.rs | 156 +++++++++++++++----- 1 file changed, 121 insertions(+), 35 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index ce85501ee4..7651d8370b 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -30,6 +30,7 @@ pub(crate) struct KbState { xkb_state: *mut ffi::xkb_state, xkb_compose_table: *mut ffi::xkb_compose_table, xkb_compose_state: *mut ffi::xkb_compose_state, + xkb_compose_state_2: *mut ffi::xkb_compose_state, mods_state: ModifiersState, locked: bool, scratch_buffer: Vec, @@ -174,27 +175,62 @@ impl KbState { Some(byte_slice_to_cached_string(&self.scratch_buffer)) } - pub(crate) fn compose_feed(&mut self, keysym: u32) -> Option { + fn compose_feed_normal(&mut self, keysym: u32) -> Option { + self.compose_feed(self.xkb_compose_state, keysym) + } + + fn compose_feed_2(&mut self, keysym: u32) -> Option { + self.compose_feed(self.xkb_compose_state_2, keysym) + } + + fn compose_feed( + &mut self, + xkb_compose_state: *mut ffi::xkb_compose_state, + keysym: u32, + ) -> Option { if !self.ready() || self.xkb_compose_state.is_null() { return None; } - Some(unsafe { (XKBCH.xkb_compose_state_feed)(self.xkb_compose_state, keysym) }) + Some(unsafe { (XKBCH.xkb_compose_state_feed)(xkb_compose_state, keysym) }) } - pub(crate) fn compose_status(&mut self) -> Option { - if !self.ready() || self.xkb_compose_state.is_null() { + fn compose_status_normal(&mut self) -> Option { + self.compose_status(self.xkb_compose_state) + } + + #[allow(dead_code)] + fn compose_status_2(&mut self) -> Option { + self.compose_status(self.xkb_compose_state_2) + } + + fn compose_status( + &mut self, + xkb_compose_state: *mut ffi::xkb_compose_state, + ) -> Option { + if !self.ready() || xkb_compose_state.is_null() { return None; } - Some(unsafe { (XKBCH.xkb_compose_state_get_status)(self.xkb_compose_state) }) + Some(unsafe { (XKBCH.xkb_compose_state_get_status)(xkb_compose_state) }) } - pub(crate) fn compose_get_utf8(&mut self) -> Option<&'static str> { - if !self.ready() || self.xkb_compose_state.is_null() { + fn compose_get_utf8_normal(&mut self) -> Option<&'static str> { + self.compose_get_utf8(self.xkb_compose_state) + } + + fn compose_get_utf8_2(&mut self) -> Option<&'static str> { + self.compose_get_utf8(self.xkb_compose_state_2) + } + + fn compose_get_utf8( + &mut self, + xkb_compose_state: *mut ffi::xkb_compose_state, + ) -> Option<&'static str> { + if !self.ready() || xkb_compose_state.is_null() { return None; } - let size = unsafe { - (XKBCH.xkb_compose_state_get_utf8)(self.xkb_compose_state, ptr::null_mut(), 0) - } + 1; + let size = + unsafe { (XKBCH.xkb_compose_state_get_utf8)(xkb_compose_state, ptr::null_mut(), 0) } + + 1; if size <= 1 { return None; }; @@ -204,7 +240,7 @@ impl KbState { unsafe { self.scratch_buffer.set_len(size); (XKBCH.xkb_compose_state_get_utf8)( - self.xkb_compose_state, + xkb_compose_state, self.scratch_buffer.as_mut_ptr() as *mut _, size as usize, ); @@ -232,18 +268,19 @@ impl KbState { xkb_state: ptr::null_mut(), xkb_compose_table: ptr::null_mut(), xkb_compose_state: ptr::null_mut(), + xkb_compose_state_2: ptr::null_mut(), mods_state: ModifiersState::new(), locked: false, scratch_buffer: Vec::new(), }; - unsafe { - me.init_compose(); - } + unsafe { me.init_compose() }; Ok(me) } +} +impl KbState { #[cfg(feature = "x11")] pub(crate) fn from_x11_xkb(connection: *mut xcb_connection_t) -> Result { let mut me = Self::new()?; @@ -310,7 +347,7 @@ impl KbState { Ok(state) } - pub(crate) unsafe fn init_compose(&mut self) { + unsafe fn init_compose(&mut self) { let locale = env::var_os("LC_ALL") .and_then(|v| if v.is_empty() { None } else { Some(v) }) .or_else(|| env::var_os("LC_CTYPE")) @@ -336,7 +373,12 @@ impl KbState { ffi::xkb_compose_state_flags::XKB_COMPOSE_STATE_NO_FLAGS, ); - if compose_state.is_null() { + let compose_state_2 = (XKBCH.xkb_compose_state_new)( + compose_table, + ffi::xkb_compose_state_flags::XKB_COMPOSE_STATE_NO_FLAGS, + ); + + if compose_state.is_null() || compose_state_2.is_null() { // init of compose state failed, continue without compose (XKBCH.xkb_compose_table_unref)(compose_table); return; @@ -344,6 +386,7 @@ impl KbState { self.xkb_compose_table = compose_table; self.xkb_compose_state = compose_state; + self.xkb_compose_state_2 = compose_state_2; } pub(crate) unsafe fn post_init(&mut self, keymap: *mut ffi::xkb_keymap) { @@ -396,7 +439,9 @@ impl KbState { Ok(()) } +} +impl KbState { pub(crate) unsafe fn key_repeats(&mut self, keycode: ffi::xkb_keycode_t) -> bool { (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, keycode + 8) == 1 } @@ -477,6 +522,7 @@ impl KbState { } } +#[derive(Copy, Clone, Debug)] enum XkbCompose { Accepted(ffi::xkb_compose_status), Ignored, @@ -495,10 +541,10 @@ impl<'a> KeyEventResults<'a> { let keysym = state.get_one_sym_raw(keycode); let compose = if compose { - Some(match state.compose_feed(keysym) { + Some(match state.compose_feed_normal(keysym) { Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) => { // Unwrapping is safe here, as `compose_feed` returns `None` when composition is uninitialized. - XkbCompose::Accepted(state.compose_status().unwrap()) + XkbCompose::Accepted(state.compose_status_normal().unwrap()) } Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_IGNORED) => XkbCompose::Ignored, None => XkbCompose::Uninitialized, @@ -521,6 +567,34 @@ impl<'a> KeyEventResults<'a> { pub fn key(&mut self) -> (Key<'static>, KeyLocation) { self.keysym_to_key(self.keysym) + .unwrap_or_else(|(key, location)| match self.compose { + Some(XkbCompose::Accepted(ffi::xkb_compose_status::XKB_COMPOSE_COMPOSING)) => { + // When pressing a dead key twice, the non-combining variant of that character will be + // produced. Since this function only concerns itself with a single keypress, we simulate + // this double press here by feeding the keysym to the compose state twice. + self.state.compose_feed_2(self.keysym); + match self.state.compose_feed_2(self.keysym) { + Some(ffi::xkb_compose_feed_result::XKB_COMPOSE_FEED_ACCEPTED) => ( + // Extracting only a single `char` here *should* be fine, assuming that no dead + // key's non-combining variant ever occupies more than one `char`. + Key::Dead( + self.state + .compose_get_utf8_2() + .map(|s| s.chars().nth(0).unwrap()), + ), + location, + ), + _ => (key, location), + } + } + _ => ( + self.composed_text() + .unwrap_or_else(|_| self.state.keysym_to_utf8_raw(self.keysym)) + .map(Key::Character) + .unwrap_or(key), + location, + ), + }) } pub fn key_without_modifiers(&mut self) -> (Key<'static>, KeyLocation) { @@ -541,45 +615,57 @@ impl<'a> KeyEventResults<'a> { 0 }; self.keysym_to_key(keysym) + .unwrap_or_else(|(key, location)| { + ( + self.state + .keysym_to_utf8_raw(keysym) + .map(Key::Character) + .unwrap_or(key), + location, + ) + }) } - fn keysym_to_key(&mut self, keysym: u32) -> (Key<'static>, KeyLocation) { + fn keysym_to_key( + &mut self, + keysym: u32, + ) -> Result<(Key<'static>, KeyLocation), (Key<'static>, KeyLocation)> { let location = super::keymap::keysym_location(keysym); - let mut key = super::keymap::keysym_to_key(keysym); + let key = super::keymap::keysym_to_key(keysym); if matches!(key, Key::Unidentified(_)) { - if let Some(string) = self.state.keysym_to_utf8_raw(keysym) { - key = Key::Character(string); - } + Err((key, location)) + } else { + Ok((key, location)) } - (key, location) } pub fn text(&mut self) -> Option<&'static str> { - self._text(|this| this.state.keysym_to_utf8_raw(this.keysym)) + self.composed_text() + .unwrap_or_else(|_| self.state.keysym_to_utf8_raw(self.keysym)) } pub fn text_with_all_modifiers(&mut self) -> Option<&'static str> { // TODO: Should Ctrl override any attempts to compose text? // gnome-terminal agrees, but konsole disagrees. // Should it be configurable instead? - self._text(|this| this.state.get_utf8_raw(this.keycode)) + self.composed_text() + .unwrap_or_else(|_| self.state.get_utf8_raw(self.keycode)) } - fn _text(&mut self, fallback: F) -> Option<&'static str> - where - F: FnOnce(&mut Self) -> Option<&'static str>, - { + fn composed_text(&mut self) -> Result, ()> { if let Some(compose) = &self.compose { match compose { XkbCompose::Accepted(status) => match status { - ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => self.state.compose_get_utf8(), - ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => fallback(self), - _ => None, + ffi::xkb_compose_status::XKB_COMPOSE_COMPOSED => { + Ok(self.state.compose_get_utf8_normal()) + } + ffi::xkb_compose_status::XKB_COMPOSE_NOTHING => Err(()), + _ => Ok(None), }, - XkbCompose::Ignored | XkbCompose::Uninitialized => fallback(self), + XkbCompose::Ignored | XkbCompose::Uninitialized => Err(()), } } else { - fallback(self) + Err(()) } } } From 8f08e9536c11058a2294064bd55b87a7ca32b605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Fri, 7 May 2021 17:21:39 +0200 Subject: [PATCH 21/58] Remove unused module --- src/platform_impl/linux/x11/events.rs | 1008 ------------------------- src/platform_impl/linux/x11/mod.rs | 2 +- 2 files changed, 1 insertion(+), 1009 deletions(-) delete mode 100644 src/platform_impl/linux/x11/events.rs diff --git a/src/platform_impl/linux/x11/events.rs b/src/platform_impl/linux/x11/events.rs deleted file mode 100644 index e721ab5922..0000000000 --- a/src/platform_impl/linux/x11/events.rs +++ /dev/null @@ -1,1008 +0,0 @@ -use super::ffi; -use crate::keyboard::KeyCode; -use libc; - -// pub fn keysym_to_element(keysym: libc::c_uint) -> Option { -// Some(match keysym { -// ffi::XK_BackSpace => VirtualKeyCode::Back, -// ffi::XK_Tab => VirtualKeyCode::Tab, -// //ffi::XK_Linefeed => VirtualKeyCode::Linefeed, -// //ffi::XK_Clear => VirtualKeyCode::Clear, -// ffi::XK_Return => VirtualKeyCode::Return, -// //ffi::XK_Pause => VirtualKeyCode::Pause, -// //ffi::XK_Scroll_Lock => VirtualKeyCode::Scroll_lock, -// //ffi::XK_Sys_Req => VirtualKeyCode::Sys_req, -// ffi::XK_Escape => VirtualKeyCode::Escape, -// ffi::XK_Delete => VirtualKeyCode::Delete, -// ffi::XK_Multi_key => VirtualKeyCode::Compose, -// //ffi::XK_Kanji => VirtualKeyCode::Kanji, -// //ffi::XK_Muhenkan => VirtualKeyCode::Muhenkan, -// //ffi::XK_Henkan_Mode => VirtualKeyCode::Henkan_mode, -// //ffi::XK_Henkan => VirtualKeyCode::Henkan, -// //ffi::XK_Romaji => VirtualKeyCode::Romaji, -// //ffi::XK_Hiragana => VirtualKeyCode::Hiragana, -// //ffi::XK_Katakana => VirtualKeyCode::Katakana, -// //ffi::XK_Hiragana_Katakana => VirtualKeyCode::Hiragana_katakana, -// //ffi::XK_Zenkaku => VirtualKeyCode::Zenkaku, -// //ffi::XK_Hankaku => VirtualKeyCode::Hankaku, -// //ffi::XK_Zenkaku_Hankaku => VirtualKeyCode::Zenkaku_hankaku, -// //ffi::XK_Touroku => VirtualKeyCode::Touroku, -// //ffi::XK_Massyo => VirtualKeyCode::Massyo, -// //ffi::XK_Kana_Lock => VirtualKeyCode::Kana_lock, -// //ffi::XK_Kana_Shift => VirtualKeyCode::Kana_shift, -// //ffi::XK_Eisu_Shift => VirtualKeyCode::Eisu_shift, -// //ffi::XK_Eisu_toggle => VirtualKeyCode::Eisu_toggle, -// ffi::XK_Home => VirtualKeyCode::Home, -// ffi::XK_Left => VirtualKeyCode::Left, -// ffi::XK_Up => VirtualKeyCode::Up, -// ffi::XK_Right => VirtualKeyCode::Right, -// ffi::XK_Down => VirtualKeyCode::Down, -// //ffi::XK_Prior => VirtualKeyCode::Prior, -// ffi::XK_Page_Up => VirtualKeyCode::PageUp, -// //ffi::XK_Next => VirtualKeyCode::Next, -// ffi::XK_Page_Down => VirtualKeyCode::PageDown, -// ffi::XK_End => VirtualKeyCode::End, -// //ffi::XK_Begin => VirtualKeyCode::Begin, -// //ffi::XK_Win_L => VirtualKeyCode::Win_l, -// //ffi::XK_Win_R => VirtualKeyCode::Win_r, -// //ffi::XK_App => VirtualKeyCode::App, -// //ffi::XK_Select => VirtualKeyCode::Select, -// //ffi::XK_Print => VirtualKeyCode::Print, -// //ffi::XK_Execute => VirtualKeyCode::Execute, -// ffi::XK_Insert => VirtualKeyCode::Insert, -// //ffi::XK_Undo => VirtualKeyCode::Undo, -// //ffi::XK_Redo => VirtualKeyCode::Redo, -// //ffi::XK_Menu => VirtualKeyCode::Menu, -// //ffi::XK_Find => VirtualKeyCode::Find, -// //ffi::XK_Cancel => VirtualKeyCode::Cancel, -// //ffi::XK_Help => VirtualKeyCode::Help, -// //ffi::XK_Break => VirtualKeyCode::Break, -// //ffi::XK_Mode_switch => VirtualKeyCode::Mode_switch, -// //ffi::XK_script_switch => VirtualKeyCode::Script_switch, -// //ffi::XK_Num_Lock => VirtualKeyCode::Num_lock, -// //ffi::XK_KP_Space => VirtualKeyCode::Kp_space, -// //ffi::XK_KP_Tab => VirtualKeyCode::Kp_tab, -// //ffi::XK_KP_Enter => VirtualKeyCode::Kp_enter, -// //ffi::XK_KP_F1 => VirtualKeyCode::Kp_f1, -// //ffi::XK_KP_F2 => VirtualKeyCode::Kp_f2, -// //ffi::XK_KP_F3 => VirtualKeyCode::Kp_f3, -// //ffi::XK_KP_F4 => VirtualKeyCode::Kp_f4, -// ffi::XK_KP_Home => VirtualKeyCode::Home, -// ffi::XK_KP_Left => VirtualKeyCode::Left, -// ffi::XK_KP_Up => VirtualKeyCode::Up, -// ffi::XK_KP_Right => VirtualKeyCode::Right, -// ffi::XK_KP_Down => VirtualKeyCode::Down, -// //ffi::XK_KP_Prior => VirtualKeyCode::Kp_prior, -// ffi::XK_KP_Page_Up => VirtualKeyCode::PageUp, -// //ffi::XK_KP_Next => VirtualKeyCode::Kp_next, -// ffi::XK_KP_Page_Down => VirtualKeyCode::PageDown, -// ffi::XK_KP_End => VirtualKeyCode::End, -// //ffi::XK_KP_Begin => VirtualKeyCode::Kp_begin, -// ffi::XK_KP_Insert => VirtualKeyCode::Insert, -// ffi::XK_KP_Delete => VirtualKeyCode::Delete, -// ffi::XK_KP_Equal => VirtualKeyCode::NumpadEquals, -// ffi::XK_KP_Multiply => VirtualKeyCode::NumpadMultiply, -// ffi::XK_KP_Add => VirtualKeyCode::NumpadAdd, -// //ffi::XK_KP_Separator => VirtualKeyCode::Kp_separator, -// ffi::XK_KP_Subtract => VirtualKeyCode::NumpadSubtract, -// ffi::XK_KP_Decimal => VirtualKeyCode::NumpadDecimal, -// ffi::XK_KP_Divide => VirtualKeyCode::NumpadDivide, -// ffi::XK_KP_0 => VirtualKeyCode::Numpad0, -// ffi::XK_KP_1 => VirtualKeyCode::Numpad1, -// ffi::XK_KP_2 => VirtualKeyCode::Numpad2, -// ffi::XK_KP_3 => VirtualKeyCode::Numpad3, -// ffi::XK_KP_4 => VirtualKeyCode::Numpad4, -// ffi::XK_KP_5 => VirtualKeyCode::Numpad5, -// ffi::XK_KP_6 => VirtualKeyCode::Numpad6, -// ffi::XK_KP_7 => VirtualKeyCode::Numpad7, -// ffi::XK_KP_8 => VirtualKeyCode::Numpad8, -// ffi::XK_KP_9 => VirtualKeyCode::Numpad9, -// ffi::XK_F1 => VirtualKeyCode::F1, -// ffi::XK_F2 => VirtualKeyCode::F2, -// ffi::XK_F3 => VirtualKeyCode::F3, -// ffi::XK_F4 => VirtualKeyCode::F4, -// ffi::XK_F5 => VirtualKeyCode::F5, -// ffi::XK_F6 => VirtualKeyCode::F6, -// ffi::XK_F7 => VirtualKeyCode::F7, -// ffi::XK_F8 => VirtualKeyCode::F8, -// ffi::XK_F9 => VirtualKeyCode::F9, -// ffi::XK_F10 => VirtualKeyCode::F10, -// ffi::XK_F11 => VirtualKeyCode::F11, -// //ffi::XK_L1 => VirtualKeyCode::L1, -// ffi::XK_F12 => VirtualKeyCode::F12, -// //ffi::XK_L2 => VirtualKeyCode::L2, -// ffi::XK_F13 => VirtualKeyCode::F13, -// //ffi::XK_L3 => VirtualKeyCode::L3, -// ffi::XK_F14 => VirtualKeyCode::F14, -// //ffi::XK_L4 => VirtualKeyCode::L4, -// ffi::XK_F15 => VirtualKeyCode::F15, -// //ffi::XK_L5 => VirtualKeyCode::L5, -// ffi::XK_F16 => VirtualKeyCode::F16, -// //ffi::XK_L6 => VirtualKeyCode::L6, -// ffi::XK_F17 => VirtualKeyCode::F17, -// //ffi::XK_L7 => VirtualKeyCode::L7, -// ffi::XK_F18 => VirtualKeyCode::F18, -// //ffi::XK_L8 => VirtualKeyCode::L8, -// ffi::XK_F19 => VirtualKeyCode::F19, -// //ffi::XK_L9 => VirtualKeyCode::L9, -// ffi::XK_F20 => VirtualKeyCode::F20, -// //ffi::XK_L10 => VirtualKeyCode::L10, -// ffi::XK_F21 => VirtualKeyCode::F21, -// //ffi::XK_R1 => VirtualKeyCode::R1, -// ffi::XK_F22 => VirtualKeyCode::F22, -// //ffi::XK_R2 => VirtualKeyCode::R2, -// ffi::XK_F23 => VirtualKeyCode::F23, -// //ffi::XK_R3 => VirtualKeyCode::R3, -// ffi::XK_F24 => VirtualKeyCode::F24, -// //ffi::XK_R4 => VirtualKeyCode::R4, -// //ffi::XK_F25 => VirtualKeyCode::F25, -// //ffi::XK_R5 => VirtualKeyCode::R5, -// //ffi::XK_F26 => VirtualKeyCode::F26, -// //ffi::XK_R6 => VirtualKeyCode::R6, -// //ffi::XK_F27 => VirtualKeyCode::F27, -// //ffi::XK_R7 => VirtualKeyCode::R7, -// //ffi::XK_F28 => VirtualKeyCode::F28, -// //ffi::XK_R8 => VirtualKeyCode::R8, -// //ffi::XK_F29 => VirtualKeyCode::F29, -// //ffi::XK_R9 => VirtualKeyCode::R9, -// //ffi::XK_F30 => VirtualKeyCode::F30, -// //ffi::XK_R10 => VirtualKeyCode::R10, -// //ffi::XK_F31 => VirtualKeyCode::F31, -// //ffi::XK_R11 => VirtualKeyCode::R11, -// //ffi::XK_F32 => VirtualKeyCode::F32, -// //ffi::XK_R12 => VirtualKeyCode::R12, -// //ffi::XK_F33 => VirtualKeyCode::F33, -// //ffi::XK_R13 => VirtualKeyCode::R13, -// //ffi::XK_F34 => VirtualKeyCode::F34, -// //ffi::XK_R14 => VirtualKeyCode::R14, -// //ffi::XK_F35 => VirtualKeyCode::F35, -// //ffi::XK_R15 => VirtualKeyCode::R15, -// ffi::XK_Shift_L => VirtualKeyCode::LShift, -// ffi::XK_Shift_R => VirtualKeyCode::RShift, -// ffi::XK_Control_L => VirtualKeyCode::LControl, -// ffi::XK_Control_R => VirtualKeyCode::RControl, -// //ffi::XK_Caps_Lock => VirtualKeyCode::Caps_lock, -// //ffi::XK_Shift_Lock => VirtualKeyCode::Shift_lock, -// //ffi::XK_Meta_L => VirtualKeyCode::Meta_l, -// //ffi::XK_Meta_R => VirtualKeyCode::Meta_r, -// ffi::XK_Alt_L => VirtualKeyCode::LAlt, -// ffi::XK_Alt_R => VirtualKeyCode::RAlt, -// //ffi::XK_Super_L => VirtualKeyCode::Super_l, -// //ffi::XK_Super_R => VirtualKeyCode::Super_r, -// //ffi::XK_Hyper_L => VirtualKeyCode::Hyper_l, -// //ffi::XK_Hyper_R => VirtualKeyCode::Hyper_r, -// ffi::XK_ISO_Left_Tab => VirtualKeyCode::Tab, -// ffi::XK_space => VirtualKeyCode::Space, -// //ffi::XK_exclam => VirtualKeyCode::Exclam, -// //ffi::XK_quotedbl => VirtualKeyCode::Quotedbl, -// //ffi::XK_numbersign => VirtualKeyCode::Numbersign, -// //ffi::XK_dollar => VirtualKeyCode::Dollar, -// //ffi::XK_percent => VirtualKeyCode::Percent, -// //ffi::XK_ampersand => VirtualKeyCode::Ampersand, -// ffi::XK_apostrophe => VirtualKeyCode::Apostrophe, -// //ffi::XK_quoteright => VirtualKeyCode::Quoteright, -// //ffi::XK_parenleft => VirtualKeyCode::Parenleft, -// //ffi::XK_parenright => VirtualKeyCode::Parenright, -// ffi::XK_asterisk => VirtualKeyCode::Asterisk, -// ffi::XK_plus => VirtualKeyCode::Plus, -// ffi::XK_comma => VirtualKeyCode::Comma, -// ffi::XK_minus => VirtualKeyCode::Minus, -// ffi::XK_period => VirtualKeyCode::Period, -// ffi::XK_slash => VirtualKeyCode::Slash, -// ffi::XK_0 => VirtualKeyCode::Key0, -// ffi::XK_1 => VirtualKeyCode::Key1, -// ffi::XK_2 => VirtualKeyCode::Key2, -// ffi::XK_3 => VirtualKeyCode::Key3, -// ffi::XK_4 => VirtualKeyCode::Key4, -// ffi::XK_5 => VirtualKeyCode::Key5, -// ffi::XK_6 => VirtualKeyCode::Key6, -// ffi::XK_7 => VirtualKeyCode::Key7, -// ffi::XK_8 => VirtualKeyCode::Key8, -// ffi::XK_9 => VirtualKeyCode::Key9, -// ffi::XK_colon => VirtualKeyCode::Colon, -// ffi::XK_semicolon => VirtualKeyCode::Semicolon, -// //ffi::XK_less => VirtualKeyCode::Less, -// ffi::XK_equal => VirtualKeyCode::Equals, -// //ffi::XK_greater => VirtualKeyCode::Greater, -// //ffi::XK_question => VirtualKeyCode::Question, -// ffi::XK_at => VirtualKeyCode::At, -// ffi::XK_A => VirtualKeyCode::A, -// ffi::XK_B => VirtualKeyCode::B, -// ffi::XK_C => VirtualKeyCode::C, -// ffi::XK_D => VirtualKeyCode::D, -// ffi::XK_E => VirtualKeyCode::E, -// ffi::XK_F => VirtualKeyCode::F, -// ffi::XK_G => VirtualKeyCode::G, -// ffi::XK_H => VirtualKeyCode::H, -// ffi::XK_I => VirtualKeyCode::I, -// ffi::XK_J => VirtualKeyCode::J, -// ffi::XK_K => VirtualKeyCode::K, -// ffi::XK_L => VirtualKeyCode::L, -// ffi::XK_M => VirtualKeyCode::M, -// ffi::XK_N => VirtualKeyCode::N, -// ffi::XK_O => VirtualKeyCode::O, -// ffi::XK_P => VirtualKeyCode::P, -// ffi::XK_Q => VirtualKeyCode::Q, -// ffi::XK_R => VirtualKeyCode::R, -// ffi::XK_S => VirtualKeyCode::S, -// ffi::XK_T => VirtualKeyCode::T, -// ffi::XK_U => VirtualKeyCode::U, -// ffi::XK_V => VirtualKeyCode::V, -// ffi::XK_W => VirtualKeyCode::W, -// ffi::XK_X => VirtualKeyCode::X, -// ffi::XK_Y => VirtualKeyCode::Y, -// ffi::XK_Z => VirtualKeyCode::Z, -// ffi::XK_bracketleft => VirtualKeyCode::LBracket, -// ffi::XK_backslash => VirtualKeyCode::Backslash, -// ffi::XK_bracketright => VirtualKeyCode::RBracket, -// //ffi::XK_asciicircum => VirtualKeyCode::Asciicircum, -// //ffi::XK_underscore => VirtualKeyCode::Underscore, -// ffi::XK_grave => VirtualKeyCode::Grave, -// //ffi::XK_quoteleft => VirtualKeyCode::Quoteleft, -// ffi::XK_a => VirtualKeyCode::A, -// ffi::XK_b => VirtualKeyCode::B, -// ffi::XK_c => VirtualKeyCode::C, -// ffi::XK_d => VirtualKeyCode::D, -// ffi::XK_e => VirtualKeyCode::E, -// ffi::XK_f => VirtualKeyCode::F, -// ffi::XK_g => VirtualKeyCode::G, -// ffi::XK_h => VirtualKeyCode::H, -// ffi::XK_i => VirtualKeyCode::I, -// ffi::XK_j => VirtualKeyCode::J, -// ffi::XK_k => VirtualKeyCode::K, -// ffi::XK_l => VirtualKeyCode::L, -// ffi::XK_m => VirtualKeyCode::M, -// ffi::XK_n => VirtualKeyCode::N, -// ffi::XK_o => VirtualKeyCode::O, -// ffi::XK_p => VirtualKeyCode::P, -// ffi::XK_q => VirtualKeyCode::Q, -// ffi::XK_r => VirtualKeyCode::R, -// ffi::XK_s => VirtualKeyCode::S, -// ffi::XK_t => VirtualKeyCode::T, -// ffi::XK_u => VirtualKeyCode::U, -// ffi::XK_v => VirtualKeyCode::V, -// ffi::XK_w => VirtualKeyCode::W, -// ffi::XK_x => VirtualKeyCode::X, -// ffi::XK_y => VirtualKeyCode::Y, -// ffi::XK_z => VirtualKeyCode::Z, -// //ffi::XK_braceleft => VirtualKeyCode::Braceleft, -// //ffi::XK_bar => VirtualKeyCode::Bar, -// //ffi::XK_braceright => VirtualKeyCode::Braceright, -// //ffi::XK_asciitilde => VirtualKeyCode::Asciitilde, -// //ffi::XK_nobreakspace => VirtualKeyCode::Nobreakspace, -// //ffi::XK_exclamdown => VirtualKeyCode::Exclamdown, -// //ffi::XK_cent => VirtualKeyCode::Cent, -// //ffi::XK_sterling => VirtualKeyCode::Sterling, -// //ffi::XK_currency => VirtualKeyCode::Currency, -// //ffi::XK_yen => VirtualKeyCode::Yen, -// //ffi::XK_brokenbar => VirtualKeyCode::Brokenbar, -// //ffi::XK_section => VirtualKeyCode::Section, -// //ffi::XK_diaeresis => VirtualKeyCode::Diaeresis, -// //ffi::XK_copyright => VirtualKeyCode::Copyright, -// //ffi::XK_ordfeminine => VirtualKeyCode::Ordfeminine, -// //ffi::XK_guillemotleft => VirtualKeyCode::Guillemotleft, -// //ffi::XK_notsign => VirtualKeyCode::Notsign, -// //ffi::XK_hyphen => VirtualKeyCode::Hyphen, -// //ffi::XK_registered => VirtualKeyCode::Registered, -// //ffi::XK_macron => VirtualKeyCode::Macron, -// //ffi::XK_degree => VirtualKeyCode::Degree, -// //ffi::XK_plusminus => VirtualKeyCode::Plusminus, -// //ffi::XK_twosuperior => VirtualKeyCode::Twosuperior, -// //ffi::XK_threesuperior => VirtualKeyCode::Threesuperior, -// //ffi::XK_acute => VirtualKeyCode::Acute, -// //ffi::XK_mu => VirtualKeyCode::Mu, -// //ffi::XK_paragraph => VirtualKeyCode::Paragraph, -// //ffi::XK_periodcentered => VirtualKeyCode::Periodcentered, -// //ffi::XK_cedilla => VirtualKeyCode::Cedilla, -// //ffi::XK_onesuperior => VirtualKeyCode::Onesuperior, -// //ffi::XK_masculine => VirtualKeyCode::Masculine, -// //ffi::XK_guillemotright => VirtualKeyCode::Guillemotright, -// //ffi::XK_onequarter => VirtualKeyCode::Onequarter, -// //ffi::XK_onehalf => VirtualKeyCode::Onehalf, -// //ffi::XK_threequarters => VirtualKeyCode::Threequarters, -// //ffi::XK_questiondown => VirtualKeyCode::Questiondown, -// //ffi::XK_Agrave => VirtualKeyCode::Agrave, -// //ffi::XK_Aacute => VirtualKeyCode::Aacute, -// //ffi::XK_Acircumflex => VirtualKeyCode::Acircumflex, -// //ffi::XK_Atilde => VirtualKeyCode::Atilde, -// //ffi::XK_Adiaeresis => VirtualKeyCode::Adiaeresis, -// //ffi::XK_Aring => VirtualKeyCode::Aring, -// //ffi::XK_AE => VirtualKeyCode::Ae, -// //ffi::XK_Ccedilla => VirtualKeyCode::Ccedilla, -// //ffi::XK_Egrave => VirtualKeyCode::Egrave, -// //ffi::XK_Eacute => VirtualKeyCode::Eacute, -// //ffi::XK_Ecircumflex => VirtualKeyCode::Ecircumflex, -// //ffi::XK_Ediaeresis => VirtualKeyCode::Ediaeresis, -// //ffi::XK_Igrave => VirtualKeyCode::Igrave, -// //ffi::XK_Iacute => VirtualKeyCode::Iacute, -// //ffi::XK_Icircumflex => VirtualKeyCode::Icircumflex, -// //ffi::XK_Idiaeresis => VirtualKeyCode::Idiaeresis, -// //ffi::XK_ETH => VirtualKeyCode::Eth, -// //ffi::XK_Eth => VirtualKeyCode::Eth, -// //ffi::XK_Ntilde => VirtualKeyCode::Ntilde, -// //ffi::XK_Ograve => VirtualKeyCode::Ograve, -// //ffi::XK_Oacute => VirtualKeyCode::Oacute, -// //ffi::XK_Ocircumflex => VirtualKeyCode::Ocircumflex, -// //ffi::XK_Otilde => VirtualKeyCode::Otilde, -// //ffi::XK_Odiaeresis => VirtualKeyCode::Odiaeresis, -// //ffi::XK_multiply => VirtualKeyCode::Multiply, -// //ffi::XK_Ooblique => VirtualKeyCode::Ooblique, -// //ffi::XK_Ugrave => VirtualKeyCode::Ugrave, -// //ffi::XK_Uacute => VirtualKeyCode::Uacute, -// //ffi::XK_Ucircumflex => VirtualKeyCode::Ucircumflex, -// //ffi::XK_Udiaeresis => VirtualKeyCode::Udiaeresis, -// //ffi::XK_Yacute => VirtualKeyCode::Yacute, -// //ffi::XK_THORN => VirtualKeyCode::Thorn, -// //ffi::XK_Thorn => VirtualKeyCode::Thorn, -// //ffi::XK_ssharp => VirtualKeyCode::Ssharp, -// //ffi::XK_agrave => VirtualKeyCode::Agrave, -// //ffi::XK_aacute => VirtualKeyCode::Aacute, -// //ffi::XK_acircumflex => VirtualKeyCode::Acircumflex, -// //ffi::XK_atilde => VirtualKeyCode::Atilde, -// //ffi::XK_adiaeresis => VirtualKeyCode::Adiaeresis, -// //ffi::XK_aring => VirtualKeyCode::Aring, -// //ffi::XK_ae => VirtualKeyCode::Ae, -// //ffi::XK_ccedilla => VirtualKeyCode::Ccedilla, -// //ffi::XK_egrave => VirtualKeyCode::Egrave, -// //ffi::XK_eacute => VirtualKeyCode::Eacute, -// //ffi::XK_ecircumflex => VirtualKeyCode::Ecircumflex, -// //ffi::XK_ediaeresis => VirtualKeyCode::Ediaeresis, -// //ffi::XK_igrave => VirtualKeyCode::Igrave, -// //ffi::XK_iacute => VirtualKeyCode::Iacute, -// //ffi::XK_icircumflex => VirtualKeyCode::Icircumflex, -// //ffi::XK_idiaeresis => VirtualKeyCode::Idiaeresis, -// //ffi::XK_eth => VirtualKeyCode::Eth, -// //ffi::XK_ntilde => VirtualKeyCode::Ntilde, -// //ffi::XK_ograve => VirtualKeyCode::Ograve, -// //ffi::XK_oacute => VirtualKeyCode::Oacute, -// //ffi::XK_ocircumflex => VirtualKeyCode::Ocircumflex, -// //ffi::XK_otilde => VirtualKeyCode::Otilde, -// //ffi::XK_odiaeresis => VirtualKeyCode::Odiaeresis, -// //ffi::XK_division => VirtualKeyCode::Division, -// //ffi::XK_oslash => VirtualKeyCode::Oslash, -// //ffi::XK_ugrave => VirtualKeyCode::Ugrave, -// //ffi::XK_uacute => VirtualKeyCode::Uacute, -// //ffi::XK_ucircumflex => VirtualKeyCode::Ucircumflex, -// //ffi::XK_udiaeresis => VirtualKeyCode::Udiaeresis, -// //ffi::XK_yacute => VirtualKeyCode::Yacute, -// //ffi::XK_thorn => VirtualKeyCode::Thorn, -// //ffi::XK_ydiaeresis => VirtualKeyCode::Ydiaeresis, -// //ffi::XK_Aogonek => VirtualKeyCode::Aogonek, -// //ffi::XK_breve => VirtualKeyCode::Breve, -// //ffi::XK_Lstroke => VirtualKeyCode::Lstroke, -// //ffi::XK_Lcaron => VirtualKeyCode::Lcaron, -// //ffi::XK_Sacute => VirtualKeyCode::Sacute, -// //ffi::XK_Scaron => VirtualKeyCode::Scaron, -// //ffi::XK_Scedilla => VirtualKeyCode::Scedilla, -// //ffi::XK_Tcaron => VirtualKeyCode::Tcaron, -// //ffi::XK_Zacute => VirtualKeyCode::Zacute, -// //ffi::XK_Zcaron => VirtualKeyCode::Zcaron, -// //ffi::XK_Zabovedot => VirtualKeyCode::Zabovedot, -// //ffi::XK_aogonek => VirtualKeyCode::Aogonek, -// //ffi::XK_ogonek => VirtualKeyCode::Ogonek, -// //ffi::XK_lstroke => VirtualKeyCode::Lstroke, -// //ffi::XK_lcaron => VirtualKeyCode::Lcaron, -// //ffi::XK_sacute => VirtualKeyCode::Sacute, -// //ffi::XK_caron => VirtualKeyCode::Caron, -// //ffi::XK_scaron => VirtualKeyCode::Scaron, -// //ffi::XK_scedilla => VirtualKeyCode::Scedilla, -// //ffi::XK_tcaron => VirtualKeyCode::Tcaron, -// //ffi::XK_zacute => VirtualKeyCode::Zacute, -// //ffi::XK_doubleacute => VirtualKeyCode::Doubleacute, -// //ffi::XK_zcaron => VirtualKeyCode::Zcaron, -// //ffi::XK_zabovedot => VirtualKeyCode::Zabovedot, -// //ffi::XK_Racute => VirtualKeyCode::Racute, -// //ffi::XK_Abreve => VirtualKeyCode::Abreve, -// //ffi::XK_Lacute => VirtualKeyCode::Lacute, -// //ffi::XK_Cacute => VirtualKeyCode::Cacute, -// //ffi::XK_Ccaron => VirtualKeyCode::Ccaron, -// //ffi::XK_Eogonek => VirtualKeyCode::Eogonek, -// //ffi::XK_Ecaron => VirtualKeyCode::Ecaron, -// //ffi::XK_Dcaron => VirtualKeyCode::Dcaron, -// //ffi::XK_Dstroke => VirtualKeyCode::Dstroke, -// //ffi::XK_Nacute => VirtualKeyCode::Nacute, -// //ffi::XK_Ncaron => VirtualKeyCode::Ncaron, -// //ffi::XK_Odoubleacute => VirtualKeyCode::Odoubleacute, -// //ffi::XK_Rcaron => VirtualKeyCode::Rcaron, -// //ffi::XK_Uring => VirtualKeyCode::Uring, -// //ffi::XK_Udoubleacute => VirtualKeyCode::Udoubleacute, -// //ffi::XK_Tcedilla => VirtualKeyCode::Tcedilla, -// //ffi::XK_racute => VirtualKeyCode::Racute, -// //ffi::XK_abreve => VirtualKeyCode::Abreve, -// //ffi::XK_lacute => VirtualKeyCode::Lacute, -// //ffi::XK_cacute => VirtualKeyCode::Cacute, -// //ffi::XK_ccaron => VirtualKeyCode::Ccaron, -// //ffi::XK_eogonek => VirtualKeyCode::Eogonek, -// //ffi::XK_ecaron => VirtualKeyCode::Ecaron, -// //ffi::XK_dcaron => VirtualKeyCode::Dcaron, -// //ffi::XK_dstroke => VirtualKeyCode::Dstroke, -// //ffi::XK_nacute => VirtualKeyCode::Nacute, -// //ffi::XK_ncaron => VirtualKeyCode::Ncaron, -// //ffi::XK_odoubleacute => VirtualKeyCode::Odoubleacute, -// //ffi::XK_udoubleacute => VirtualKeyCode::Udoubleacute, -// //ffi::XK_rcaron => VirtualKeyCode::Rcaron, -// //ffi::XK_uring => VirtualKeyCode::Uring, -// //ffi::XK_tcedilla => VirtualKeyCode::Tcedilla, -// //ffi::XK_abovedot => VirtualKeyCode::Abovedot, -// //ffi::XK_Hstroke => VirtualKeyCode::Hstroke, -// //ffi::XK_Hcircumflex => VirtualKeyCode::Hcircumflex, -// //ffi::XK_Iabovedot => VirtualKeyCode::Iabovedot, -// //ffi::XK_Gbreve => VirtualKeyCode::Gbreve, -// //ffi::XK_Jcircumflex => VirtualKeyCode::Jcircumflex, -// //ffi::XK_hstroke => VirtualKeyCode::Hstroke, -// //ffi::XK_hcircumflex => VirtualKeyCode::Hcircumflex, -// //ffi::XK_idotless => VirtualKeyCode::Idotless, -// //ffi::XK_gbreve => VirtualKeyCode::Gbreve, -// //ffi::XK_jcircumflex => VirtualKeyCode::Jcircumflex, -// //ffi::XK_Cabovedot => VirtualKeyCode::Cabovedot, -// //ffi::XK_Ccircumflex => VirtualKeyCode::Ccircumflex, -// //ffi::XK_Gabovedot => VirtualKeyCode::Gabovedot, -// //ffi::XK_Gcircumflex => VirtualKeyCode::Gcircumflex, -// //ffi::XK_Ubreve => VirtualKeyCode::Ubreve, -// //ffi::XK_Scircumflex => VirtualKeyCode::Scircumflex, -// //ffi::XK_cabovedot => VirtualKeyCode::Cabovedot, -// //ffi::XK_ccircumflex => VirtualKeyCode::Ccircumflex, -// //ffi::XK_gabovedot => VirtualKeyCode::Gabovedot, -// //ffi::XK_gcircumflex => VirtualKeyCode::Gcircumflex, -// //ffi::XK_ubreve => VirtualKeyCode::Ubreve, -// //ffi::XK_scircumflex => VirtualKeyCode::Scircumflex, -// //ffi::XK_kra => VirtualKeyCode::Kra, -// //ffi::XK_kappa => VirtualKeyCode::Kappa, -// //ffi::XK_Rcedilla => VirtualKeyCode::Rcedilla, -// //ffi::XK_Itilde => VirtualKeyCode::Itilde, -// //ffi::XK_Lcedilla => VirtualKeyCode::Lcedilla, -// //ffi::XK_Emacron => VirtualKeyCode::Emacron, -// //ffi::XK_Gcedilla => VirtualKeyCode::Gcedilla, -// //ffi::XK_Tslash => VirtualKeyCode::Tslash, -// //ffi::XK_rcedilla => VirtualKeyCode::Rcedilla, -// //ffi::XK_itilde => VirtualKeyCode::Itilde, -// //ffi::XK_lcedilla => VirtualKeyCode::Lcedilla, -// //ffi::XK_emacron => VirtualKeyCode::Emacron, -// //ffi::XK_gcedilla => VirtualKeyCode::Gcedilla, -// //ffi::XK_tslash => VirtualKeyCode::Tslash, -// //ffi::XK_ENG => VirtualKeyCode::Eng, -// //ffi::XK_eng => VirtualKeyCode::Eng, -// //ffi::XK_Amacron => VirtualKeyCode::Amacron, -// //ffi::XK_Iogonek => VirtualKeyCode::Iogonek, -// //ffi::XK_Eabovedot => VirtualKeyCode::Eabovedot, -// //ffi::XK_Imacron => VirtualKeyCode::Imacron, -// //ffi::XK_Ncedilla => VirtualKeyCode::Ncedilla, -// //ffi::XK_Omacron => VirtualKeyCode::Omacron, -// //ffi::XK_Kcedilla => VirtualKeyCode::Kcedilla, -// //ffi::XK_Uogonek => VirtualKeyCode::Uogonek, -// //ffi::XK_Utilde => VirtualKeyCode::Utilde, -// //ffi::XK_Umacron => VirtualKeyCode::Umacron, -// //ffi::XK_amacron => VirtualKeyCode::Amacron, -// //ffi::XK_iogonek => VirtualKeyCode::Iogonek, -// //ffi::XK_eabovedot => VirtualKeyCode::Eabovedot, -// //ffi::XK_imacron => VirtualKeyCode::Imacron, -// //ffi::XK_ncedilla => VirtualKeyCode::Ncedilla, -// //ffi::XK_omacron => VirtualKeyCode::Omacron, -// //ffi::XK_kcedilla => VirtualKeyCode::Kcedilla, -// //ffi::XK_uogonek => VirtualKeyCode::Uogonek, -// //ffi::XK_utilde => VirtualKeyCode::Utilde, -// //ffi::XK_umacron => VirtualKeyCode::Umacron, -// //ffi::XK_overline => VirtualKeyCode::Overline, -// //ffi::XK_kana_fullstop => VirtualKeyCode::Kana_fullstop, -// //ffi::XK_kana_openingbracket => VirtualKeyCode::Kana_openingbracket, -// //ffi::XK_kana_closingbracket => VirtualKeyCode::Kana_closingbracket, -// //ffi::XK_kana_comma => VirtualKeyCode::Kana_comma, -// //ffi::XK_kana_conjunctive => VirtualKeyCode::Kana_conjunctive, -// //ffi::XK_kana_middledot => VirtualKeyCode::Kana_middledot, -// //ffi::XK_kana_WO => VirtualKeyCode::Kana_wo, -// //ffi::XK_kana_a => VirtualKeyCode::Kana_a, -// //ffi::XK_kana_i => VirtualKeyCode::Kana_i, -// //ffi::XK_kana_u => VirtualKeyCode::Kana_u, -// //ffi::XK_kana_e => VirtualKeyCode::Kana_e, -// //ffi::XK_kana_o => VirtualKeyCode::Kana_o, -// //ffi::XK_kana_ya => VirtualKeyCode::Kana_ya, -// //ffi::XK_kana_yu => VirtualKeyCode::Kana_yu, -// //ffi::XK_kana_yo => VirtualKeyCode::Kana_yo, -// //ffi::XK_kana_tsu => VirtualKeyCode::Kana_tsu, -// //ffi::XK_kana_tu => VirtualKeyCode::Kana_tu, -// //ffi::XK_prolongedsound => VirtualKeyCode::Prolongedsound, -// //ffi::XK_kana_A => VirtualKeyCode::Kana_a, -// //ffi::XK_kana_I => VirtualKeyCode::Kana_i, -// //ffi::XK_kana_U => VirtualKeyCode::Kana_u, -// //ffi::XK_kana_E => VirtualKeyCode::Kana_e, -// //ffi::XK_kana_O => VirtualKeyCode::Kana_o, -// //ffi::XK_kana_KA => VirtualKeyCode::Kana_ka, -// //ffi::XK_kana_KI => VirtualKeyCode::Kana_ki, -// //ffi::XK_kana_KU => VirtualKeyCode::Kana_ku, -// //ffi::XK_kana_KE => VirtualKeyCode::Kana_ke, -// //ffi::XK_kana_KO => VirtualKeyCode::Kana_ko, -// //ffi::XK_kana_SA => VirtualKeyCode::Kana_sa, -// //ffi::XK_kana_SHI => VirtualKeyCode::Kana_shi, -// //ffi::XK_kana_SU => VirtualKeyCode::Kana_su, -// //ffi::XK_kana_SE => VirtualKeyCode::Kana_se, -// //ffi::XK_kana_SO => VirtualKeyCode::Kana_so, -// //ffi::XK_kana_TA => VirtualKeyCode::Kana_ta, -// //ffi::XK_kana_CHI => VirtualKeyCode::Kana_chi, -// //ffi::XK_kana_TI => VirtualKeyCode::Kana_ti, -// //ffi::XK_kana_TSU => VirtualKeyCode::Kana_tsu, -// //ffi::XK_kana_TU => VirtualKeyCode::Kana_tu, -// //ffi::XK_kana_TE => VirtualKeyCode::Kana_te, -// //ffi::XK_kana_TO => VirtualKeyCode::Kana_to, -// //ffi::XK_kana_NA => VirtualKeyCode::Kana_na, -// //ffi::XK_kana_NI => VirtualKeyCode::Kana_ni, -// //ffi::XK_kana_NU => VirtualKeyCode::Kana_nu, -// //ffi::XK_kana_NE => VirtualKeyCode::Kana_ne, -// //ffi::XK_kana_NO => VirtualKeyCode::Kana_no, -// //ffi::XK_kana_HA => VirtualKeyCode::Kana_ha, -// //ffi::XK_kana_HI => VirtualKeyCode::Kana_hi, -// //ffi::XK_kana_FU => VirtualKeyCode::Kana_fu, -// //ffi::XK_kana_HU => VirtualKeyCode::Kana_hu, -// //ffi::XK_kana_HE => VirtualKeyCode::Kana_he, -// //ffi::XK_kana_HO => VirtualKeyCode::Kana_ho, -// //ffi::XK_kana_MA => VirtualKeyCode::Kana_ma, -// //ffi::XK_kana_MI => VirtualKeyCode::Kana_mi, -// //ffi::XK_kana_MU => VirtualKeyCode::Kana_mu, -// //ffi::XK_kana_ME => VirtualKeyCode::Kana_me, -// //ffi::XK_kana_MO => VirtualKeyCode::Kana_mo, -// //ffi::XK_kana_YA => VirtualKeyCode::Kana_ya, -// //ffi::XK_kana_YU => VirtualKeyCode::Kana_yu, -// //ffi::XK_kana_YO => VirtualKeyCode::Kana_yo, -// //ffi::XK_kana_RA => VirtualKeyCode::Kana_ra, -// //ffi::XK_kana_RI => VirtualKeyCode::Kana_ri, -// //ffi::XK_kana_RU => VirtualKeyCode::Kana_ru, -// //ffi::XK_kana_RE => VirtualKeyCode::Kana_re, -// //ffi::XK_kana_RO => VirtualKeyCode::Kana_ro, -// //ffi::XK_kana_WA => VirtualKeyCode::Kana_wa, -// //ffi::XK_kana_N => VirtualKeyCode::Kana_n, -// //ffi::XK_voicedsound => VirtualKeyCode::Voicedsound, -// //ffi::XK_semivoicedsound => VirtualKeyCode::Semivoicedsound, -// //ffi::XK_kana_switch => VirtualKeyCode::Kana_switch, -// //ffi::XK_Arabic_comma => VirtualKeyCode::Arabic_comma, -// //ffi::XK_Arabic_semicolon => VirtualKeyCode::Arabic_semicolon, -// //ffi::XK_Arabic_question_mark => VirtualKeyCode::Arabic_question_mark, -// //ffi::XK_Arabic_hamza => VirtualKeyCode::Arabic_hamza, -// //ffi::XK_Arabic_maddaonalef => VirtualKeyCode::Arabic_maddaonalef, -// //ffi::XK_Arabic_hamzaonalef => VirtualKeyCode::Arabic_hamzaonalef, -// //ffi::XK_Arabic_hamzaonwaw => VirtualKeyCode::Arabic_hamzaonwaw, -// //ffi::XK_Arabic_hamzaunderalef => VirtualKeyCode::Arabic_hamzaunderalef, -// //ffi::XK_Arabic_hamzaonyeh => VirtualKeyCode::Arabic_hamzaonyeh, -// //ffi::XK_Arabic_alef => VirtualKeyCode::Arabic_alef, -// //ffi::XK_Arabic_beh => VirtualKeyCode::Arabic_beh, -// //ffi::XK_Arabic_tehmarbuta => VirtualKeyCode::Arabic_tehmarbuta, -// //ffi::XK_Arabic_teh => VirtualKeyCode::Arabic_teh, -// //ffi::XK_Arabic_theh => VirtualKeyCode::Arabic_theh, -// //ffi::XK_Arabic_jeem => VirtualKeyCode::Arabic_jeem, -// //ffi::XK_Arabic_hah => VirtualKeyCode::Arabic_hah, -// //ffi::XK_Arabic_khah => VirtualKeyCode::Arabic_khah, -// //ffi::XK_Arabic_dal => VirtualKeyCode::Arabic_dal, -// //ffi::XK_Arabic_thal => VirtualKeyCode::Arabic_thal, -// //ffi::XK_Arabic_ra => VirtualKeyCode::Arabic_ra, -// //ffi::XK_Arabic_zain => VirtualKeyCode::Arabic_zain, -// //ffi::XK_Arabic_seen => VirtualKeyCode::Arabic_seen, -// //ffi::XK_Arabic_sheen => VirtualKeyCode::Arabic_sheen, -// //ffi::XK_Arabic_sad => VirtualKeyCode::Arabic_sad, -// //ffi::XK_Arabic_dad => VirtualKeyCode::Arabic_dad, -// //ffi::XK_Arabic_tah => VirtualKeyCode::Arabic_tah, -// //ffi::XK_Arabic_zah => VirtualKeyCode::Arabic_zah, -// //ffi::XK_Arabic_ain => VirtualKeyCode::Arabic_ain, -// //ffi::XK_Arabic_ghain => VirtualKeyCode::Arabic_ghain, -// //ffi::XK_Arabic_tatweel => VirtualKeyCode::Arabic_tatweel, -// //ffi::XK_Arabic_feh => VirtualKeyCode::Arabic_feh, -// //ffi::XK_Arabic_qaf => VirtualKeyCode::Arabic_qaf, -// //ffi::XK_Arabic_kaf => VirtualKeyCode::Arabic_kaf, -// //ffi::XK_Arabic_lam => VirtualKeyCode::Arabic_lam, -// //ffi::XK_Arabic_meem => VirtualKeyCode::Arabic_meem, -// //ffi::XK_Arabic_noon => VirtualKeyCode::Arabic_noon, -// //ffi::XK_Arabic_ha => VirtualKeyCode::Arabic_ha, -// //ffi::XK_Arabic_heh => VirtualKeyCode::Arabic_heh, -// //ffi::XK_Arabic_waw => VirtualKeyCode::Arabic_waw, -// //ffi::XK_Arabic_alefmaksura => VirtualKeyCode::Arabic_alefmaksura, -// //ffi::XK_Arabic_yeh => VirtualKeyCode::Arabic_yeh, -// //ffi::XK_Arabic_fathatan => VirtualKeyCode::Arabic_fathatan, -// //ffi::XK_Arabic_dammatan => VirtualKeyCode::Arabic_dammatan, -// //ffi::XK_Arabic_kasratan => VirtualKeyCode::Arabic_kasratan, -// //ffi::XK_Arabic_fatha => VirtualKeyCode::Arabic_fatha, -// //ffi::XK_Arabic_damma => VirtualKeyCode::Arabic_damma, -// //ffi::XK_Arabic_kasra => VirtualKeyCode::Arabic_kasra, -// //ffi::XK_Arabic_shadda => VirtualKeyCode::Arabic_shadda, -// //ffi::XK_Arabic_sukun => VirtualKeyCode::Arabic_sukun, -// //ffi::XK_Arabic_switch => VirtualKeyCode::Arabic_switch, -// //ffi::XK_Serbian_dje => VirtualKeyCode::Serbian_dje, -// //ffi::XK_Macedonia_gje => VirtualKeyCode::Macedonia_gje, -// //ffi::XK_Cyrillic_io => VirtualKeyCode::Cyrillic_io, -// //ffi::XK_Ukrainian_ie => VirtualKeyCode::Ukrainian_ie, -// //ffi::XK_Ukranian_je => VirtualKeyCode::Ukranian_je, -// //ffi::XK_Macedonia_dse => VirtualKeyCode::Macedonia_dse, -// //ffi::XK_Ukrainian_i => VirtualKeyCode::Ukrainian_i, -// //ffi::XK_Ukranian_i => VirtualKeyCode::Ukranian_i, -// //ffi::XK_Ukrainian_yi => VirtualKeyCode::Ukrainian_yi, -// //ffi::XK_Ukranian_yi => VirtualKeyCode::Ukranian_yi, -// //ffi::XK_Cyrillic_je => VirtualKeyCode::Cyrillic_je, -// //ffi::XK_Serbian_je => VirtualKeyCode::Serbian_je, -// //ffi::XK_Cyrillic_lje => VirtualKeyCode::Cyrillic_lje, -// //ffi::XK_Serbian_lje => VirtualKeyCode::Serbian_lje, -// //ffi::XK_Cyrillic_nje => VirtualKeyCode::Cyrillic_nje, -// //ffi::XK_Serbian_nje => VirtualKeyCode::Serbian_nje, -// //ffi::XK_Serbian_tshe => VirtualKeyCode::Serbian_tshe, -// //ffi::XK_Macedonia_kje => VirtualKeyCode::Macedonia_kje, -// //ffi::XK_Byelorussian_shortu => VirtualKeyCode::Byelorussian_shortu, -// //ffi::XK_Cyrillic_dzhe => VirtualKeyCode::Cyrillic_dzhe, -// //ffi::XK_Serbian_dze => VirtualKeyCode::Serbian_dze, -// //ffi::XK_numerosign => VirtualKeyCode::Numerosign, -// //ffi::XK_Serbian_DJE => VirtualKeyCode::Serbian_dje, -// //ffi::XK_Macedonia_GJE => VirtualKeyCode::Macedonia_gje, -// //ffi::XK_Cyrillic_IO => VirtualKeyCode::Cyrillic_io, -// //ffi::XK_Ukrainian_IE => VirtualKeyCode::Ukrainian_ie, -// //ffi::XK_Ukranian_JE => VirtualKeyCode::Ukranian_je, -// //ffi::XK_Macedonia_DSE => VirtualKeyCode::Macedonia_dse, -// //ffi::XK_Ukrainian_I => VirtualKeyCode::Ukrainian_i, -// //ffi::XK_Ukranian_I => VirtualKeyCode::Ukranian_i, -// //ffi::XK_Ukrainian_YI => VirtualKeyCode::Ukrainian_yi, -// //ffi::XK_Ukranian_YI => VirtualKeyCode::Ukranian_yi, -// //ffi::XK_Cyrillic_JE => VirtualKeyCode::Cyrillic_je, -// //ffi::XK_Serbian_JE => VirtualKeyCode::Serbian_je, -// //ffi::XK_Cyrillic_LJE => VirtualKeyCode::Cyrillic_lje, -// //ffi::XK_Serbian_LJE => VirtualKeyCode::Serbian_lje, -// //ffi::XK_Cyrillic_NJE => VirtualKeyCode::Cyrillic_nje, -// //ffi::XK_Serbian_NJE => VirtualKeyCode::Serbian_nje, -// //ffi::XK_Serbian_TSHE => VirtualKeyCode::Serbian_tshe, -// //ffi::XK_Macedonia_KJE => VirtualKeyCode::Macedonia_kje, -// //ffi::XK_Byelorussian_SHORTU => VirtualKeyCode::Byelorussian_shortu, -// //ffi::XK_Cyrillic_DZHE => VirtualKeyCode::Cyrillic_dzhe, -// //ffi::XK_Serbian_DZE => VirtualKeyCode::Serbian_dze, -// //ffi::XK_Cyrillic_yu => VirtualKeyCode::Cyrillic_yu, -// //ffi::XK_Cyrillic_a => VirtualKeyCode::Cyrillic_a, -// //ffi::XK_Cyrillic_be => VirtualKeyCode::Cyrillic_be, -// //ffi::XK_Cyrillic_tse => VirtualKeyCode::Cyrillic_tse, -// //ffi::XK_Cyrillic_de => VirtualKeyCode::Cyrillic_de, -// //ffi::XK_Cyrillic_ie => VirtualKeyCode::Cyrillic_ie, -// //ffi::XK_Cyrillic_ef => VirtualKeyCode::Cyrillic_ef, -// //ffi::XK_Cyrillic_ghe => VirtualKeyCode::Cyrillic_ghe, -// //ffi::XK_Cyrillic_ha => VirtualKeyCode::Cyrillic_ha, -// //ffi::XK_Cyrillic_i => VirtualKeyCode::Cyrillic_i, -// //ffi::XK_Cyrillic_shorti => VirtualKeyCode::Cyrillic_shorti, -// //ffi::XK_Cyrillic_ka => VirtualKeyCode::Cyrillic_ka, -// //ffi::XK_Cyrillic_el => VirtualKeyCode::Cyrillic_el, -// //ffi::XK_Cyrillic_em => VirtualKeyCode::Cyrillic_em, -// //ffi::XK_Cyrillic_en => VirtualKeyCode::Cyrillic_en, -// //ffi::XK_Cyrillic_o => VirtualKeyCode::Cyrillic_o, -// //ffi::XK_Cyrillic_pe => VirtualKeyCode::Cyrillic_pe, -// //ffi::XK_Cyrillic_ya => VirtualKeyCode::Cyrillic_ya, -// //ffi::XK_Cyrillic_er => VirtualKeyCode::Cyrillic_er, -// //ffi::XK_Cyrillic_es => VirtualKeyCode::Cyrillic_es, -// //ffi::XK_Cyrillic_te => VirtualKeyCode::Cyrillic_te, -// //ffi::XK_Cyrillic_u => VirtualKeyCode::Cyrillic_u, -// //ffi::XK_Cyrillic_zhe => VirtualKeyCode::Cyrillic_zhe, -// //ffi::XK_Cyrillic_ve => VirtualKeyCode::Cyrillic_ve, -// //ffi::XK_Cyrillic_softsign => VirtualKeyCode::Cyrillic_softsign, -// //ffi::XK_Cyrillic_yeru => VirtualKeyCode::Cyrillic_yeru, -// //ffi::XK_Cyrillic_ze => VirtualKeyCode::Cyrillic_ze, -// //ffi::XK_Cyrillic_sha => VirtualKeyCode::Cyrillic_sha, -// //ffi::XK_Cyrillic_e => VirtualKeyCode::Cyrillic_e, -// //ffi::XK_Cyrillic_shcha => VirtualKeyCode::Cyrillic_shcha, -// //ffi::XK_Cyrillic_che => VirtualKeyCode::Cyrillic_che, -// //ffi::XK_Cyrillic_hardsign => VirtualKeyCode::Cyrillic_hardsign, -// //ffi::XK_Cyrillic_YU => VirtualKeyCode::Cyrillic_yu, -// //ffi::XK_Cyrillic_A => VirtualKeyCode::Cyrillic_a, -// //ffi::XK_Cyrillic_BE => VirtualKeyCode::Cyrillic_be, -// //ffi::XK_Cyrillic_TSE => VirtualKeyCode::Cyrillic_tse, -// //ffi::XK_Cyrillic_DE => VirtualKeyCode::Cyrillic_de, -// //ffi::XK_Cyrillic_IE => VirtualKeyCode::Cyrillic_ie, -// //ffi::XK_Cyrillic_EF => VirtualKeyCode::Cyrillic_ef, -// //ffi::XK_Cyrillic_GHE => VirtualKeyCode::Cyrillic_ghe, -// //ffi::XK_Cyrillic_HA => VirtualKeyCode::Cyrillic_ha, -// //ffi::XK_Cyrillic_I => VirtualKeyCode::Cyrillic_i, -// //ffi::XK_Cyrillic_SHORTI => VirtualKeyCode::Cyrillic_shorti, -// //ffi::XK_Cyrillic_KA => VirtualKeyCode::Cyrillic_ka, -// //ffi::XK_Cyrillic_EL => VirtualKeyCode::Cyrillic_el, -// //ffi::XK_Cyrillic_EM => VirtualKeyCode::Cyrillic_em, -// //ffi::XK_Cyrillic_EN => VirtualKeyCode::Cyrillic_en, -// //ffi::XK_Cyrillic_O => VirtualKeyCode::Cyrillic_o, -// //ffi::XK_Cyrillic_PE => VirtualKeyCode::Cyrillic_pe, -// //ffi::XK_Cyrillic_YA => VirtualKeyCode::Cyrillic_ya, -// //ffi::XK_Cyrillic_ER => VirtualKeyCode::Cyrillic_er, -// //ffi::XK_Cyrillic_ES => VirtualKeyCode::Cyrillic_es, -// //ffi::XK_Cyrillic_TE => VirtualKeyCode::Cyrillic_te, -// //ffi::XK_Cyrillic_U => VirtualKeyCode::Cyrillic_u, -// //ffi::XK_Cyrillic_ZHE => VirtualKeyCode::Cyrillic_zhe, -// //ffi::XK_Cyrillic_VE => VirtualKeyCode::Cyrillic_ve, -// //ffi::XK_Cyrillic_SOFTSIGN => VirtualKeyCode::Cyrillic_softsign, -// //ffi::XK_Cyrillic_YERU => VirtualKeyCode::Cyrillic_yeru, -// //ffi::XK_Cyrillic_ZE => VirtualKeyCode::Cyrillic_ze, -// //ffi::XK_Cyrillic_SHA => VirtualKeyCode::Cyrillic_sha, -// //ffi::XK_Cyrillic_E => VirtualKeyCode::Cyrillic_e, -// //ffi::XK_Cyrillic_SHCHA => VirtualKeyCode::Cyrillic_shcha, -// //ffi::XK_Cyrillic_CHE => VirtualKeyCode::Cyrillic_che, -// //ffi::XK_Cyrillic_HARDSIGN => VirtualKeyCode::Cyrillic_hardsign, -// //ffi::XK_Greek_ALPHAaccent => VirtualKeyCode::Greek_alphaaccent, -// //ffi::XK_Greek_EPSILONaccent => VirtualKeyCode::Greek_epsilonaccent, -// //ffi::XK_Greek_ETAaccent => VirtualKeyCode::Greek_etaaccent, -// //ffi::XK_Greek_IOTAaccent => VirtualKeyCode::Greek_iotaaccent, -// //ffi::XK_Greek_IOTAdiaeresis => VirtualKeyCode::Greek_iotadiaeresis, -// //ffi::XK_Greek_OMICRONaccent => VirtualKeyCode::Greek_omicronaccent, -// //ffi::XK_Greek_UPSILONaccent => VirtualKeyCode::Greek_upsilonaccent, -// //ffi::XK_Greek_UPSILONdieresis => VirtualKeyCode::Greek_upsilondieresis, -// //ffi::XK_Greek_OMEGAaccent => VirtualKeyCode::Greek_omegaaccent, -// //ffi::XK_Greek_accentdieresis => VirtualKeyCode::Greek_accentdieresis, -// //ffi::XK_Greek_horizbar => VirtualKeyCode::Greek_horizbar, -// //ffi::XK_Greek_alphaaccent => VirtualKeyCode::Greek_alphaaccent, -// //ffi::XK_Greek_epsilonaccent => VirtualKeyCode::Greek_epsilonaccent, -// //ffi::XK_Greek_etaaccent => VirtualKeyCode::Greek_etaaccent, -// //ffi::XK_Greek_iotaaccent => VirtualKeyCode::Greek_iotaaccent, -// //ffi::XK_Greek_iotadieresis => VirtualKeyCode::Greek_iotadieresis, -// //ffi::XK_Greek_iotaaccentdieresis => VirtualKeyCode::Greek_iotaaccentdieresis, -// //ffi::XK_Greek_omicronaccent => VirtualKeyCode::Greek_omicronaccent, -// //ffi::XK_Greek_upsilonaccent => VirtualKeyCode::Greek_upsilonaccent, -// //ffi::XK_Greek_upsilondieresis => VirtualKeyCode::Greek_upsilondieresis, -// //ffi::XK_Greek_upsilonaccentdieresis => VirtualKeyCode::Greek_upsilonaccentdieresis, -// //ffi::XK_Greek_omegaaccent => VirtualKeyCode::Greek_omegaaccent, -// //ffi::XK_Greek_ALPHA => VirtualKeyCode::Greek_alpha, -// //ffi::XK_Greek_BETA => VirtualKeyCode::Greek_beta, -// //ffi::XK_Greek_GAMMA => VirtualKeyCode::Greek_gamma, -// //ffi::XK_Greek_DELTA => VirtualKeyCode::Greek_delta, -// //ffi::XK_Greek_EPSILON => VirtualKeyCode::Greek_epsilon, -// //ffi::XK_Greek_ZETA => VirtualKeyCode::Greek_zeta, -// //ffi::XK_Greek_ETA => VirtualKeyCode::Greek_eta, -// //ffi::XK_Greek_THETA => VirtualKeyCode::Greek_theta, -// //ffi::XK_Greek_IOTA => VirtualKeyCode::Greek_iota, -// //ffi::XK_Greek_KAPPA => VirtualKeyCode::Greek_kappa, -// //ffi::XK_Greek_LAMDA => VirtualKeyCode::Greek_lamda, -// //ffi::XK_Greek_LAMBDA => VirtualKeyCode::Greek_lambda, -// //ffi::XK_Greek_MU => VirtualKeyCode::Greek_mu, -// //ffi::XK_Greek_NU => VirtualKeyCode::Greek_nu, -// //ffi::XK_Greek_XI => VirtualKeyCode::Greek_xi, -// //ffi::XK_Greek_OMICRON => VirtualKeyCode::Greek_omicron, -// //ffi::XK_Greek_PI => VirtualKeyCode::Greek_pi, -// //ffi::XK_Greek_RHO => VirtualKeyCode::Greek_rho, -// //ffi::XK_Greek_SIGMA => VirtualKeyCode::Greek_sigma, -// //ffi::XK_Greek_TAU => VirtualKeyCode::Greek_tau, -// //ffi::XK_Greek_UPSILON => VirtualKeyCode::Greek_upsilon, -// //ffi::XK_Greek_PHI => VirtualKeyCode::Greek_phi, -// //ffi::XK_Greek_CHI => VirtualKeyCode::Greek_chi, -// //ffi::XK_Greek_PSI => VirtualKeyCode::Greek_psi, -// //ffi::XK_Greek_OMEGA => VirtualKeyCode::Greek_omega, -// //ffi::XK_Greek_alpha => VirtualKeyCode::Greek_alpha, -// //ffi::XK_Greek_beta => VirtualKeyCode::Greek_beta, -// //ffi::XK_Greek_gamma => VirtualKeyCode::Greek_gamma, -// //ffi::XK_Greek_delta => VirtualKeyCode::Greek_delta, -// //ffi::XK_Greek_epsilon => VirtualKeyCode::Greek_epsilon, -// //ffi::XK_Greek_zeta => VirtualKeyCode::Greek_zeta, -// //ffi::XK_Greek_eta => VirtualKeyCode::Greek_eta, -// //ffi::XK_Greek_theta => VirtualKeyCode::Greek_theta, -// //ffi::XK_Greek_iota => VirtualKeyCode::Greek_iota, -// //ffi::XK_Greek_kappa => VirtualKeyCode::Greek_kappa, -// //ffi::XK_Greek_lamda => VirtualKeyCode::Greek_lamda, -// //ffi::XK_Greek_lambda => VirtualKeyCode::Greek_lambda, -// //ffi::XK_Greek_mu => VirtualKeyCode::Greek_mu, -// //ffi::XK_Greek_nu => VirtualKeyCode::Greek_nu, -// //ffi::XK_Greek_xi => VirtualKeyCode::Greek_xi, -// //ffi::XK_Greek_omicron => VirtualKeyCode::Greek_omicron, -// //ffi::XK_Greek_pi => VirtualKeyCode::Greek_pi, -// //ffi::XK_Greek_rho => VirtualKeyCode::Greek_rho, -// //ffi::XK_Greek_sigma => VirtualKeyCode::Greek_sigma, -// //ffi::XK_Greek_finalsmallsigma => VirtualKeyCode::Greek_finalsmallsigma, -// //ffi::XK_Greek_tau => VirtualKeyCode::Greek_tau, -// //ffi::XK_Greek_upsilon => VirtualKeyCode::Greek_upsilon, -// //ffi::XK_Greek_phi => VirtualKeyCode::Greek_phi, -// //ffi::XK_Greek_chi => VirtualKeyCode::Greek_chi, -// //ffi::XK_Greek_psi => VirtualKeyCode::Greek_psi, -// //ffi::XK_Greek_omega => VirtualKeyCode::Greek_omega, -// //ffi::XK_Greek_switch => VirtualKeyCode::Greek_switch, -// //ffi::XK_leftradical => VirtualKeyCode::Leftradical, -// //ffi::XK_topleftradical => VirtualKeyCode::Topleftradical, -// //ffi::XK_horizconnector => VirtualKeyCode::Horizconnector, -// //ffi::XK_topintegral => VirtualKeyCode::Topintegral, -// //ffi::XK_botintegral => VirtualKeyCode::Botintegral, -// //ffi::XK_vertconnector => VirtualKeyCode::Vertconnector, -// //ffi::XK_topleftsqbracket => VirtualKeyCode::Topleftsqbracket, -// //ffi::XK_botleftsqbracket => VirtualKeyCode::Botleftsqbracket, -// //ffi::XK_toprightsqbracket => VirtualKeyCode::Toprightsqbracket, -// //ffi::XK_botrightsqbracket => VirtualKeyCode::Botrightsqbracket, -// //ffi::XK_topleftparens => VirtualKeyCode::Topleftparens, -// //ffi::XK_botleftparens => VirtualKeyCode::Botleftparens, -// //ffi::XK_toprightparens => VirtualKeyCode::Toprightparens, -// //ffi::XK_botrightparens => VirtualKeyCode::Botrightparens, -// //ffi::XK_leftmiddlecurlybrace => VirtualKeyCode::Leftmiddlecurlybrace, -// //ffi::XK_rightmiddlecurlybrace => VirtualKeyCode::Rightmiddlecurlybrace, -// //ffi::XK_topleftsummation => VirtualKeyCode::Topleftsummation, -// //ffi::XK_botleftsummation => VirtualKeyCode::Botleftsummation, -// //ffi::XK_topvertsummationconnector => VirtualKeyCode::Topvertsummationconnector, -// //ffi::XK_botvertsummationconnector => VirtualKeyCode::Botvertsummationconnector, -// //ffi::XK_toprightsummation => VirtualKeyCode::Toprightsummation, -// //ffi::XK_botrightsummation => VirtualKeyCode::Botrightsummation, -// //ffi::XK_rightmiddlesummation => VirtualKeyCode::Rightmiddlesummation, -// //ffi::XK_lessthanequal => VirtualKeyCode::Lessthanequal, -// //ffi::XK_notequal => VirtualKeyCode::Notequal, -// //ffi::XK_greaterthanequal => VirtualKeyCode::Greaterthanequal, -// //ffi::XK_integral => VirtualKeyCode::Integral, -// //ffi::XK_therefore => VirtualKeyCode::Therefore, -// //ffi::XK_variation => VirtualKeyCode::Variation, -// //ffi::XK_infinity => VirtualKeyCode::Infinity, -// //ffi::XK_nabla => VirtualKeyCode::Nabla, -// //ffi::XK_approximate => VirtualKeyCode::Approximate, -// //ffi::XK_similarequal => VirtualKeyCode::Similarequal, -// //ffi::XK_ifonlyif => VirtualKeyCode::Ifonlyif, -// //ffi::XK_implies => VirtualKeyCode::Implies, -// //ffi::XK_identical => VirtualKeyCode::Identical, -// //ffi::XK_radical => VirtualKeyCode::Radical, -// //ffi::XK_includedin => VirtualKeyCode::Includedin, -// //ffi::XK_includes => VirtualKeyCode::Includes, -// //ffi::XK_intersection => VirtualKeyCode::Intersection, -// //ffi::XK_union => VirtualKeyCode::Union, -// //ffi::XK_logicaland => VirtualKeyCode::Logicaland, -// //ffi::XK_logicalor => VirtualKeyCode::Logicalor, -// //ffi::XK_partialderivative => VirtualKeyCode::Partialderivative, -// //ffi::XK_function => VirtualKeyCode::Function, -// //ffi::XK_leftarrow => VirtualKeyCode::Leftarrow, -// //ffi::XK_uparrow => VirtualKeyCode::Uparrow, -// //ffi::XK_rightarrow => VirtualKeyCode::Rightarrow, -// //ffi::XK_downarrow => VirtualKeyCode::Downarrow, -// //ffi::XK_blank => VirtualKeyCode::Blank, -// //ffi::XK_soliddiamond => VirtualKeyCode::Soliddiamond, -// //ffi::XK_checkerboard => VirtualKeyCode::Checkerboard, -// //ffi::XK_ht => VirtualKeyCode::Ht, -// //ffi::XK_ff => VirtualKeyCode::Ff, -// //ffi::XK_cr => VirtualKeyCode::Cr, -// //ffi::XK_lf => VirtualKeyCode::Lf, -// //ffi::XK_nl => VirtualKeyCode::Nl, -// //ffi::XK_vt => VirtualKeyCode::Vt, -// //ffi::XK_lowrightcorner => VirtualKeyCode::Lowrightcorner, -// //ffi::XK_uprightcorner => VirtualKeyCode::Uprightcorner, -// //ffi::XK_upleftcorner => VirtualKeyCode::Upleftcorner, -// //ffi::XK_lowleftcorner => VirtualKeyCode::Lowleftcorner, -// //ffi::XK_crossinglines => VirtualKeyCode::Crossinglines, -// //ffi::XK_horizlinescan1 => VirtualKeyCode::Horizlinescan1, -// //ffi::XK_horizlinescan3 => VirtualKeyCode::Horizlinescan3, -// //ffi::XK_horizlinescan5 => VirtualKeyCode::Horizlinescan5, -// //ffi::XK_horizlinescan7 => VirtualKeyCode::Horizlinescan7, -// //ffi::XK_horizlinescan9 => VirtualKeyCode::Horizlinescan9, -// //ffi::XK_leftt => VirtualKeyCode::Leftt, -// //ffi::XK_rightt => VirtualKeyCode::Rightt, -// //ffi::XK_bott => VirtualKeyCode::Bott, -// //ffi::XK_topt => VirtualKeyCode::Topt, -// //ffi::XK_vertbar => VirtualKeyCode::Vertbar, -// //ffi::XK_emspace => VirtualKeyCode::Emspace, -// //ffi::XK_enspace => VirtualKeyCode::Enspace, -// //ffi::XK_em3space => VirtualKeyCode::Em3space, -// //ffi::XK_em4space => VirtualKeyCode::Em4space, -// //ffi::XK_digitspace => VirtualKeyCode::Digitspace, -// //ffi::XK_punctspace => VirtualKeyCode::Punctspace, -// //ffi::XK_thinspace => VirtualKeyCode::Thinspace, -// //ffi::XK_hairspace => VirtualKeyCode::Hairspace, -// //ffi::XK_emdash => VirtualKeyCode::Emdash, -// //ffi::XK_endash => VirtualKeyCode::Endash, -// //ffi::XK_signifblank => VirtualKeyCode::Signifblank, -// //ffi::XK_ellipsis => VirtualKeyCode::Ellipsis, -// //ffi::XK_doubbaselinedot => VirtualKeyCode::Doubbaselinedot, -// //ffi::XK_onethird => VirtualKeyCode::Onethird, -// //ffi::XK_twothirds => VirtualKeyCode::Twothirds, -// //ffi::XK_onefifth => VirtualKeyCode::Onefifth, -// //ffi::XK_twofifths => VirtualKeyCode::Twofifths, -// //ffi::XK_threefifths => VirtualKeyCode::Threefifths, -// //ffi::XK_fourfifths => VirtualKeyCode::Fourfifths, -// //ffi::XK_onesixth => VirtualKeyCode::Onesixth, -// //ffi::XK_fivesixths => VirtualKeyCode::Fivesixths, -// //ffi::XK_careof => VirtualKeyCode::Careof, -// //ffi::XK_figdash => VirtualKeyCode::Figdash, -// //ffi::XK_leftanglebracket => VirtualKeyCode::Leftanglebracket, -// //ffi::XK_decimalpoint => VirtualKeyCode::Decimalpoint, -// //ffi::XK_rightanglebracket => VirtualKeyCode::Rightanglebracket, -// //ffi::XK_marker => VirtualKeyCode::Marker, -// //ffi::XK_oneeighth => VirtualKeyCode::Oneeighth, -// //ffi::XK_threeeighths => VirtualKeyCode::Threeeighths, -// //ffi::XK_fiveeighths => VirtualKeyCode::Fiveeighths, -// //ffi::XK_seveneighths => VirtualKeyCode::Seveneighths, -// //ffi::XK_trademark => VirtualKeyCode::Trademark, -// //ffi::XK_signaturemark => VirtualKeyCode::Signaturemark, -// //ffi::XK_trademarkincircle => VirtualKeyCode::Trademarkincircle, -// //ffi::XK_leftopentriangle => VirtualKeyCode::Leftopentriangle, -// //ffi::XK_rightopentriangle => VirtualKeyCode::Rightopentriangle, -// //ffi::XK_emopencircle => VirtualKeyCode::Emopencircle, -// //ffi::XK_emopenrectangle => VirtualKeyCode::Emopenrectangle, -// //ffi::XK_leftsinglequotemark => VirtualKeyCode::Leftsinglequotemark, -// //ffi::XK_rightsinglequotemark => VirtualKeyCode::Rightsinglequotemark, -// //ffi::XK_leftdoublequotemark => VirtualKeyCode::Leftdoublequotemark, -// //ffi::XK_rightdoublequotemark => VirtualKeyCode::Rightdoublequotemark, -// //ffi::XK_prescription => VirtualKeyCode::Prescription, -// //ffi::XK_minutes => VirtualKeyCode::Minutes, -// //ffi::XK_seconds => VirtualKeyCode::Seconds, -// //ffi::XK_latincross => VirtualKeyCode::Latincross, -// //ffi::XK_hexagram => VirtualKeyCode::Hexagram, -// //ffi::XK_filledrectbullet => VirtualKeyCode::Filledrectbullet, -// //ffi::XK_filledlefttribullet => VirtualKeyCode::Filledlefttribullet, -// //ffi::XK_filledrighttribullet => VirtualKeyCode::Filledrighttribullet, -// //ffi::XK_emfilledcircle => VirtualKeyCode::Emfilledcircle, -// //ffi::XK_emfilledrect => VirtualKeyCode::Emfilledrect, -// //ffi::XK_enopencircbullet => VirtualKeyCode::Enopencircbullet, -// //ffi::XK_enopensquarebullet => VirtualKeyCode::Enopensquarebullet, -// //ffi::XK_openrectbullet => VirtualKeyCode::Openrectbullet, -// //ffi::XK_opentribulletup => VirtualKeyCode::Opentribulletup, -// //ffi::XK_opentribulletdown => VirtualKeyCode::Opentribulletdown, -// //ffi::XK_openstar => VirtualKeyCode::Openstar, -// //ffi::XK_enfilledcircbullet => VirtualKeyCode::Enfilledcircbullet, -// //ffi::XK_enfilledsqbullet => VirtualKeyCode::Enfilledsqbullet, -// //ffi::XK_filledtribulletup => VirtualKeyCode::Filledtribulletup, -// //ffi::XK_filledtribulletdown => VirtualKeyCode::Filledtribulletdown, -// //ffi::XK_leftpointer => VirtualKeyCode::Leftpointer, -// //ffi::XK_rightpointer => VirtualKeyCode::Rightpointer, -// //ffi::XK_club => VirtualKeyCode::Club, -// //ffi::XK_diamond => VirtualKeyCode::Diamond, -// //ffi::XK_heart => VirtualKeyCode::Heart, -// //ffi::XK_maltesecross => VirtualKeyCode::Maltesecross, -// //ffi::XK_dagger => VirtualKeyCode::Dagger, -// //ffi::XK_doubledagger => VirtualKeyCode::Doubledagger, -// //ffi::XK_checkmark => VirtualKeyCode::Checkmark, -// //ffi::XK_ballotcross => VirtualKeyCode::Ballotcross, -// //ffi::XK_musicalsharp => VirtualKeyCode::Musicalsharp, -// //ffi::XK_musicalflat => VirtualKeyCode::Musicalflat, -// //ffi::XK_malesymbol => VirtualKeyCode::Malesymbol, -// //ffi::XK_femalesymbol => VirtualKeyCode::Femalesymbol, -// //ffi::XK_telephone => VirtualKeyCode::Telephone, -// //ffi::XK_telephonerecorder => VirtualKeyCode::Telephonerecorder, -// //ffi::XK_phonographcopyright => VirtualKeyCode::Phonographcopyright, -// //ffi::XK_caret => VirtualKeyCode::Caret, -// //ffi::XK_singlelowquotemark => VirtualKeyCode::Singlelowquotemark, -// //ffi::XK_doublelowquotemark => VirtualKeyCode::Doublelowquotemark, -// //ffi::XK_cursor => VirtualKeyCode::Cursor, -// //ffi::XK_leftcaret => VirtualKeyCode::Leftcaret, -// //ffi::XK_rightcaret => VirtualKeyCode::Rightcaret, -// //ffi::XK_downcaret => VirtualKeyCode::Downcaret, -// //ffi::XK_upcaret => VirtualKeyCode::Upcaret, -// //ffi::XK_overbar => VirtualKeyCode::Overbar, -// //ffi::XK_downtack => VirtualKeyCode::Downtack, -// //ffi::XK_upshoe => VirtualKeyCode::Upshoe, -// //ffi::XK_downstile => VirtualKeyCode::Downstile, -// //ffi::XK_underbar => VirtualKeyCode::Underbar, -// //ffi::XK_jot => VirtualKeyCode::Jot, -// //ffi::XK_quad => VirtualKeyCode::Quad, -// //ffi::XK_uptack => VirtualKeyCode::Uptack, -// //ffi::XK_circle => VirtualKeyCode::Circle, -// //ffi::XK_upstile => VirtualKeyCode::Upstile, -// //ffi::XK_downshoe => VirtualKeyCode::Downshoe, -// //ffi::XK_rightshoe => VirtualKeyCode::Rightshoe, -// //ffi::XK_leftshoe => VirtualKeyCode::Leftshoe, -// //ffi::XK_lefttack => VirtualKeyCode::Lefttack, -// //ffi::XK_righttack => VirtualKeyCode::Righttack, -// //ffi::XK_hebrew_doublelowline => VirtualKeyCode::Hebrew_doublelowline, -// //ffi::XK_hebrew_aleph => VirtualKeyCode::Hebrew_aleph, -// //ffi::XK_hebrew_bet => VirtualKeyCode::Hebrew_bet, -// //ffi::XK_hebrew_beth => VirtualKeyCode::Hebrew_beth, -// //ffi::XK_hebrew_gimel => VirtualKeyCode::Hebrew_gimel, -// //ffi::XK_hebrew_gimmel => VirtualKeyCode::Hebrew_gimmel, -// //ffi::XK_hebrew_dalet => VirtualKeyCode::Hebrew_dalet, -// //ffi::XK_hebrew_daleth => VirtualKeyCode::Hebrew_daleth, -// //ffi::XK_hebrew_he => VirtualKeyCode::Hebrew_he, -// //ffi::XK_hebrew_waw => VirtualKeyCode::Hebrew_waw, -// //ffi::XK_hebrew_zain => VirtualKeyCode::Hebrew_zain, -// //ffi::XK_hebrew_zayin => VirtualKeyCode::Hebrew_zayin, -// //ffi::XK_hebrew_chet => VirtualKeyCode::Hebrew_chet, -// //ffi::XK_hebrew_het => VirtualKeyCode::Hebrew_het, -// //ffi::XK_hebrew_tet => VirtualKeyCode::Hebrew_tet, -// //ffi::XK_hebrew_teth => VirtualKeyCode::Hebrew_teth, -// //ffi::XK_hebrew_yod => VirtualKeyCode::Hebrew_yod, -// //ffi::XK_hebrew_finalkaph => VirtualKeyCode::Hebrew_finalkaph, -// //ffi::XK_hebrew_kaph => VirtualKeyCode::Hebrew_kaph, -// //ffi::XK_hebrew_lamed => VirtualKeyCode::Hebrew_lamed, -// //ffi::XK_hebrew_finalmem => VirtualKeyCode::Hebrew_finalmem, -// //ffi::XK_hebrew_mem => VirtualKeyCode::Hebrew_mem, -// //ffi::XK_hebrew_finalnun => VirtualKeyCode::Hebrew_finalnun, -// //ffi::XK_hebrew_nun => VirtualKeyCode::Hebrew_nun, -// //ffi::XK_hebrew_samech => VirtualKeyCode::Hebrew_samech, -// //ffi::XK_hebrew_samekh => VirtualKeyCode::Hebrew_samekh, -// //ffi::XK_hebrew_ayin => VirtualKeyCode::Hebrew_ayin, -// //ffi::XK_hebrew_finalpe => VirtualKeyCode::Hebrew_finalpe, -// //ffi::XK_hebrew_pe => VirtualKeyCode::Hebrew_pe, -// //ffi::XK_hebrew_finalzade => VirtualKeyCode::Hebrew_finalzade, -// //ffi::XK_hebrew_finalzadi => VirtualKeyCode::Hebrew_finalzadi, -// //ffi::XK_hebrew_zade => VirtualKeyCode::Hebrew_zade, -// //ffi::XK_hebrew_zadi => VirtualKeyCode::Hebrew_zadi, -// //ffi::XK_hebrew_qoph => VirtualKeyCode::Hebrew_qoph, -// //ffi::XK_hebrew_kuf => VirtualKeyCode::Hebrew_kuf, -// //ffi::XK_hebrew_resh => VirtualKeyCode::Hebrew_resh, -// //ffi::XK_hebrew_shin => VirtualKeyCode::Hebrew_shin, -// //ffi::XK_hebrew_taw => VirtualKeyCode::Hebrew_taw, -// //ffi::XK_hebrew_taf => VirtualKeyCode::Hebrew_taf, -// //ffi::XK_Hebrew_switch => VirtualKeyCode::Hebrew_switch, -// ffi::XF86XK_Back => VirtualKeyCode::NavigateBackward, -// ffi::XF86XK_Forward => VirtualKeyCode::NavigateForward, -// ffi::XF86XK_Copy => VirtualKeyCode::Copy, -// ffi::XF86XK_Paste => VirtualKeyCode::Paste, -// ffi::XF86XK_Cut => VirtualKeyCode::Cut, -// _ => return None, -// }) -// } diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index c6a33645b6..aaf70dc57c 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -5,10 +5,10 @@ target_os = "netbsd", target_os = "openbsd" ))] +#![allow(non_fmt_panic)] mod dnd; mod event_processor; -mod events; pub mod ffi; mod ime; mod monitor; From 297c19cfcfaba0142eeada57952e54c08eb5ad79 Mon Sep 17 00:00:00 2001 From: Artur Kovacs Date: Mon, 10 May 2021 19:45:39 +0200 Subject: [PATCH 22/58] Update xkbcommon-dl --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 363bf15819..c4f664e86d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,7 +113,7 @@ percent-encoding = { version = "2.0", optional = true } parking_lot = { version = "0.12.0", optional = true } libc = "0.2.64" memmap2 = { version = "0.2.1", optional = true } -xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "5307184" } +xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "802388064d0e5775fa09578bcad45842874f08e0" } [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" From b2372b58de95fb06368033629742a280f36722a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sun, 16 May 2021 23:20:45 +0200 Subject: [PATCH 23/58] Update xkbcommon-dl again --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index c4f664e86d..16b2138db9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -113,7 +113,7 @@ percent-encoding = { version = "2.0", optional = true } parking_lot = { version = "0.12.0", optional = true } libc = "0.2.64" memmap2 = { version = "0.2.1", optional = true } -xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "802388064d0e5775fa09578bcad45842874f08e0" } +xkbcommon-dl = { git = "https://github.com/maroider/xkbcommon-dl", rev = "900832888ad6f11011d1369befb344a9aa8a9610" } [target.'cfg(target_arch = "wasm32")'.dependencies.web_sys] package = "web-sys" From da6d1c745f747df0739429be6229005ffebcbacd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sun, 16 May 2021 23:23:18 +0200 Subject: [PATCH 24/58] Remove accidentally included attribute --- src/platform_impl/linux/x11/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index aaf70dc57c..405440e6f5 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -5,7 +5,6 @@ target_os = "netbsd", target_os = "openbsd" ))] -#![allow(non_fmt_panic)] mod dnd; mod event_processor; From c41ad69c8ddc0cc299c74e9086a2fd46f4c4ab26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sun, 16 May 2021 23:26:51 +0200 Subject: [PATCH 25/58] Use `as u32` to cast `i32`s to `u32`s --- src/platform_impl/linux/x11/event_processor.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 1ab4a4b7e7..6f8ff7e7d5 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1214,14 +1214,13 @@ impl EventProcessor { let xev = unsafe { &*(xev as *const _ as *const ffi::XkbStateNotifyEvent) }; if matches!(xev.event_type, 2 | 3) { - // TODO: Is `as u32` fine here? self.kb_state.update_modifiers( xev.base_mods, xev.latched_mods, xev.locked_mods, - u32::from_ne_bytes(xev.base_group.to_ne_bytes()), - u32::from_ne_bytes(xev.latched_group.to_ne_bytes()), - u32::from_ne_bytes(xev.locked_group.to_ne_bytes()), + xev.base_group as u32, + xev.latched_group as u32, + xev.locked_group as u32, ) } } From 94f02bbed79211a7abac5005c1fefc397891caf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sun, 16 May 2021 23:55:48 +0200 Subject: [PATCH 26/58] Put more things behind the "wayland" feature --- src/platform_impl/linux/common/xkb_state.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 7651d8370b..e3e187a388 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -8,6 +8,9 @@ use std::ptr; #[cfg(feature = "wayland")] use memmap2::MmapOptions; +#[cfg(feature = "wayland")] +pub use sctk::seat::keyboard::RMLVO; + #[cfg(feature = "x11")] use x11_dl::xlib_xcb::xcb_connection_t; #[cfg(feature = "x11")] @@ -17,8 +20,6 @@ use xkbcommon_dl::{ self as ffi, xkb_state_component, XKBCOMMON_COMPOSE_HANDLE as XKBCH, XKBCOMMON_HANDLE as XKBH, }; -pub use sctk::seat::keyboard::RMLVO; - use crate::{ event::ElementState, keyboard::{Key, KeyCode, KeyLocation}, @@ -317,6 +318,7 @@ impl KbState { Ok(me) } + #[cfg(feature = "wayland")] pub(crate) fn from_rmlvo(rmlvo: RMLVO) -> Result { fn to_cstring(s: Option) -> Result, Error> { s.map_or(Ok(None), |s| CString::new(s).map(Option::Some)) @@ -421,6 +423,7 @@ impl KbState { self.post_init(keymap); } + #[cfg(feature = "wayland")] pub(crate) unsafe fn init_with_rmlvo( &mut self, names: ffi::xkb_rule_names, From 1603f6bf355937d522a6af65e09547c03183dd27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sun, 16 May 2021 23:58:48 +0200 Subject: [PATCH 27/58] Remove superfluous scope --- src/platform_impl/linux/common/xkb_state.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index e3e187a388..bc1a388c10 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -252,11 +252,10 @@ impl KbState { } pub(crate) fn new() -> Result { - { - if ffi::XKBCOMMON_OPTION.as_ref().is_none() { - return Err(Error::XKBNotFound); - } + if ffi::XKBCOMMON_OPTION.as_ref().is_none() { + return Err(Error::XKBNotFound); } + let context = unsafe { (XKBH.xkb_context_new)(ffi::xkb_context_flags::XKB_CONTEXT_NO_FLAGS) }; if context.is_null() { From 69dc88b7efecc0e904861e9cb00f1e808588884c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Wed, 16 Jun 2021 03:46:22 +0200 Subject: [PATCH 28/58] Separate out loading of the X11 keymap --- src/platform_impl/linux/common/xkb_state.rs | 38 ++++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index bc1a388c10..446975c6de 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -26,6 +26,8 @@ use crate::{ }; pub(crate) struct KbState { + #[cfg(feature = "x11")] + xcb_connection: *mut xcb_connection_t, xkb_context: *mut ffi::xkb_context, xkb_keymap: *mut ffi::xkb_keymap, xkb_state: *mut ffi::xkb_state, @@ -263,6 +265,8 @@ impl KbState { } let mut me = KbState { + #[cfg(feature = "x11")] + xcb_connection: ptr::null_mut(), xkb_context: context, xkb_keymap: ptr::null_mut(), xkb_state: ptr::null_mut(), @@ -284,6 +288,7 @@ impl KbState { #[cfg(feature = "x11")] pub(crate) fn from_x11_xkb(connection: *mut xcb_connection_t) -> Result { let mut me = Self::new()?; + me.xcb_connection = connection; let result = unsafe { (XKBXH.xkb_x11_setup_xkb_extension)( @@ -299,22 +304,29 @@ impl KbState { }; assert_eq!(result, 1, "Failed to initialize libxkbcommon"); + unsafe { me.load_x11_keymap() }; + + Ok(me) + } + + #[cfg(feature = "x11")] + pub(crate) unsafe fn load_x11_keymap(&mut self) { + if !self.xkb_keymap.is_null() { + self.de_init(); + } + // TODO: Support keyboards other than the "virtual core keyboard device". - let core_keyboard_id = unsafe { (XKBXH.xkb_x11_get_core_keyboard_device_id)(connection) }; - let keymap = unsafe { - (XKBXH.xkb_x11_keymap_new_from_device)( - me.xkb_context, - connection, - core_keyboard_id, - xkbcommon_dl::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS, - ) - }; + let core_keyboard_id = (XKBXH.xkb_x11_get_core_keyboard_device_id)(self.xcb_connection); + let keymap = (XKBXH.xkb_x11_keymap_new_from_device)( + self.xkb_context, + self.xcb_connection, + core_keyboard_id, + xkbcommon_dl::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS, + ); assert_ne!(keymap, ptr::null_mut()); - me.xkb_keymap = keymap; - - unsafe { me.post_init(keymap) }; + self.xkb_keymap = keymap; - Ok(me) + self.post_init(keymap); } #[cfg(feature = "wayland")] From f919bdb3d52cc162144c59dbc63db0539f7a246e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Wed, 16 Jun 2021 05:41:04 +0200 Subject: [PATCH 29/58] Wire up X11 IME support --- .../linux/x11/event_processor.rs | 20 ++----------------- src/platform_impl/linux/x11/window.rs | 1 + 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 6f8ff7e7d5..3ffdd5afa4 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -554,6 +554,7 @@ impl EventProcessor { } ffi::KeyPress | ffi::KeyRelease => { + // TODO: Is it possible to exclusively use XInput2 events here? use crate::event::ElementState::{Pressed, Released}; // Note that in compose/pre-edit sequences, this will always be Released. @@ -568,12 +569,6 @@ impl EventProcessor { let window = xkev.window; let window_id = mkwid(window); - // Standard virtual core keyboard ID. XInput2 needs to be used to get a reliable - // value, though this should only be an issue under multiseat configurations. - let device = util::VIRTUAL_CORE_KEYBOARD; - let device_id = mkdid(device); - let keycode = xkev.keycode; - if state == Pressed { let written = if let Some(ic) = wt.ime.borrow().get_context(window) { wt.xconn.lookup_utf8(ic, xkev) @@ -583,7 +578,7 @@ impl EventProcessor { // If we're composing right now, send the string we've got from X11 via // Ime::Commit. - if self.is_composing && keycode == 0 && !written.is_empty() { + if self.is_composing && xev.keycode == 0 && !written.is_empty() { let event = Event::WindowEvent { window_id, event: WindowEvent::Ime(Ime::Commit(written)), @@ -591,17 +586,6 @@ impl EventProcessor { self.is_composing = false; callback(event); - } else { - /* - for chr in written.chars() { - let event = Event::WindowEvent { - window_id, - event: WindowEvent::ReceivedCharacter(chr), - }; - - callback(event); - } - */ } } } diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 3cbcb30ac7..23335fc15a 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -235,6 +235,7 @@ impl UnownedWindow { swa.event_mask = ffi::ExposureMask | ffi::StructureNotifyMask | ffi::VisibilityChangeMask + | ffi::KeyPressMask | ffi::KeymapStateMask | ffi::ButtonPressMask | ffi::ButtonReleaseMask From d8e281f93780b7a0c3fe53b3ed325245eed82817 Mon Sep 17 00:00:00 2001 From: Artur Kovacs Date: Sun, 4 Jul 2021 21:46:04 +0200 Subject: [PATCH 30/58] Use the currently active keyboard layout on X11 --- src/platform_impl/linux/common/xkb_state.rs | 13 +++++++++++-- src/platform_impl/linux/x11/event_processor.rs | 18 +++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 446975c6de..8c82f2df06 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -325,8 +325,9 @@ impl KbState { ); assert_ne!(keymap, ptr::null_mut()); self.xkb_keymap = keymap; - - self.post_init(keymap); + self.xkb_state = + (XKBXH.xkb_x11_state_new_from_device)(keymap, self.xcb_connection, core_keyboard_id); + self.mods_state.update_with(self.xkb_state); } #[cfg(feature = "wayland")] @@ -567,6 +568,14 @@ impl<'a> KeyEventResults<'a> { None }; + // let key_text = state.keysym_to_utf8_raw(keysym); + // unsafe { + // let layout_id = (XKBH.xkb_state_serialize_layout)(state.xkb_state, xkb_state_component::XKB_STATE_LAYOUT_EFFECTIVE); + // let layout_name_cstr = (XKBH.xkb_keymap_layout_get_name)(state.xkb_keymap, layout_id); + // let layout_name = std::ffi::CStr::from_ptr(layout_name_cstr as *mut _); + // debug!("KeyEventResults::new {:?}, {:?}", key_text, layout_name); + // } + KeyEventResults { state, keycode, diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 3ffdd5afa4..21e7c82caa 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1197,7 +1197,23 @@ impl EventProcessor { ffi::XkbStateNotify => { let xev = unsafe { &*(xev as *const _ as *const ffi::XkbStateNotifyEvent) }; - if matches!(xev.event_type, 2 | 3) { + debug!( + "XkbStateNotify. group: {}, event_type: {}", + xev.group, xev.event_type + ); + if xev.event_type == 0 { + // This probably indicates that the keyboard layout was switched. + // Let's update the groups (i.e. the layout) + self.kb_state.update_modifiers( + xev.base_mods, + xev.latched_mods, + xev.locked_mods, + xev.base_group as u32, + xev.latched_group as u32, + xev.locked_group as u32, + ); + } + if matches!(xev.event_type as i32, ffi::KeyPress | ffi::KeyRelease) { self.kb_state.update_modifiers( xev.base_mods, xev.latched_mods, From 21c6a57aed906129b51f4bcc5f325d108fe8e991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sun, 4 Jul 2021 23:22:59 +0200 Subject: [PATCH 31/58] fixup! Wire up X11 IME support --- .../linux/x11/event_processor.rs | 42 +++++++------------ 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 21e7c82caa..fbe0c0345e 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -553,40 +553,30 @@ impl EventProcessor { } } - ffi::KeyPress | ffi::KeyRelease => { + // Note that in compose/pre-edit sequences, we'll always receive KeyRelease events + ffi::KeyPress => { // TODO: Is it possible to exclusively use XInput2 events here? - use crate::event::ElementState::{Pressed, Released}; - - // Note that in compose/pre-edit sequences, this will always be Released. - let state = if xev.get_type() == ffi::KeyPress { - Pressed - } else { - Released - }; - let xkev: &mut ffi::XKeyEvent = xev.as_mut(); let window = xkev.window; let window_id = mkwid(window); - if state == Pressed { - let written = if let Some(ic) = wt.ime.borrow().get_context(window) { - wt.xconn.lookup_utf8(ic, xkev) - } else { - return; - }; + let written = if let Some(ic) = wt.ime.borrow().get_context(window) { + wt.xconn.lookup_utf8(ic, xkev) + } else { + return; + }; - // If we're composing right now, send the string we've got from X11 via - // Ime::Commit. - if self.is_composing && xev.keycode == 0 && !written.is_empty() { - let event = Event::WindowEvent { - window_id, - event: WindowEvent::Ime(Ime::Commit(written)), - }; + // If we're composing right now, send the string we've got from X11 via + // Ime::Commit. + if self.is_composing && xkev.keycode == 0 && !written.is_empty() { + let event = Event::WindowEvent { + window_id, + event: WindowEvent::Ime(Ime::Commit(written)), + }; - self.is_composing = false; - callback(event); - } + self.is_composing = false; + callback(event); } } From a40acad72164a4578490049f34a093915f382c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Tue, 3 Aug 2021 15:58:48 +0200 Subject: [PATCH 32/58] Enable keysym mapping for "Alt Graph" --- src/platform_impl/linux/common/keymap.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index 4f72adc8f9..b54a1776ab 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -436,10 +436,10 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // XKB function and modifier keys // keysyms::XKB_KEY_ISO_Lock => Key::IsoLock, // keysyms::XKB_KEY_ISO_Level2_Latch => Key::IsoLevel2Latch, - // NOTE: I'm not quite certain if mapping the next 3 values to AltGraph is correct. - // keysyms::XKB_KEY_ISO_Level3_Shift => Key::AltGraph, - // keysyms::XKB_KEY_ISO_Level3_Latch => Key::AltGraph, - // keysyms::XKB_KEY_ISO_Level3_Lock => Key::AltGraph, + keysyms::XKB_KEY_ISO_Level3_Shift => Key::AltGraph, + // NOTE: I'm not quite certain if mapping the next 2 values to AltGraph is correct. + keysyms::XKB_KEY_ISO_Level3_Latch => Key::AltGraph, + keysyms::XKB_KEY_ISO_Level3_Lock => Key::AltGraph, // keysyms::XKB_KEY_ISO_Level5_Shift => Key::IsoLevel5Shift, // keysyms::XKB_KEY_ISO_Level5_Latch => Key::IsoLevel5Latch, // keysyms::XKB_KEY_ISO_Level5_Lock => Key::IsoLevel5Lock, From fd3139e7438f77e60fd0d2fc35db123e5b15713a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 5 Aug 2021 00:13:45 +0200 Subject: [PATCH 33/58] Actually respect keyboard layout changes 9486ac0 did not work for me --- .../linux/x11/event_processor.rs | 67 +++++++++---------- 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index fbe0c0345e..cb0ef26458 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -164,24 +164,6 @@ impl EventProcessor { let event_type = xev.get_type(); match event_type { - ffi::MappingNotify => { - let mapping: &ffi::XMappingEvent = xev.as_ref(); - - if mapping.request == ffi::MappingModifier - || mapping.request == ffi::MappingKeyboard - { - unsafe { - (wt.xconn.xlib.XRefreshKeyboardMapping)(xev.as_mut()); - } - wt.xconn - .check_errors() - .expect("Failed to call XRefreshKeyboardMapping"); - - self.mod_keymap.reset_from_x_connection(&wt.xconn); - self.device_mod_state.update_keymap(&self.mod_keymap); - } - } - ffi::ClientMessage => { let client_msg: &ffi::XClientMessageEvent = xev.as_ref(); @@ -1105,6 +1087,39 @@ impl EventProcessor { } ffi::XI_RawKeyPress | ffi::XI_RawKeyRelease => { + // This is horrible, but I couldn't manage to respect keyboard layout changes + // in any other way. In fact, getting this to work at all proved so frustrating + // that I (@maroider) lost motivation to work on the keyboard event rework for + // some months. Thankfully, @ArturKovacs offered to help debug the problem + // over discord, and the following is the result of that debugging session. + // + // Without the XKB extension, the X.Org server sends us the `MappingNotify` + // event when there's been a change in the keyboard layout. This stops + // being the case when we select ourselves some XKB events with `XkbSelectEvents` + // and the "core keyboard device (0x100)" (we haven't tried with any other + // devices). We managed to reproduce this on both our machines. + // + // With the XKB extension active, it would seem like we're supposed to use the + // `XkbStateNotify` event to detect keyboard layout changes, but the `group` + // never changes value (it is always `0`). This worked for @ArturKovacs, but + // not for me. We also tried to use the `group` given to us in keypress events, + // but it remained constant there, too. + // + // We also tried to see if there was some other event that got fired when the + // keyboard layout changed, and we found a mysterious event with the value + // `85` (`0x55`). We couldn't find any reference to it in the X11 headers or + // in the X.Org server source. + // + // `KeymapNotify` did briefly look interesting based purely on the name, but + // it is only useful for checking what keys are pressed when we receive the + // event. + // + // So instead of any vaguely reasonable approach, we get this: reloading the + // keymap on *every* keypress. That's peak efficiency right there! + // + // FIXME: Someone please save our souls! Or at least our wasted CPU cycles. + unsafe { self.kb_state.load_x11_keymap() }; + let xev: &ffi::XIRawEvent = unsafe { &*(xev.data as *const _) }; let state = match xev.evtype { @@ -1187,22 +1202,6 @@ impl EventProcessor { ffi::XkbStateNotify => { let xev = unsafe { &*(xev as *const _ as *const ffi::XkbStateNotifyEvent) }; - debug!( - "XkbStateNotify. group: {}, event_type: {}", - xev.group, xev.event_type - ); - if xev.event_type == 0 { - // This probably indicates that the keyboard layout was switched. - // Let's update the groups (i.e. the layout) - self.kb_state.update_modifiers( - xev.base_mods, - xev.latched_mods, - xev.locked_mods, - xev.base_group as u32, - xev.latched_group as u32, - xev.locked_group as u32, - ); - } if matches!(xev.event_type as i32, ffi::KeyPress | ffi::KeyRelease) { self.kb_state.update_modifiers( xev.base_mods, From 42c85e161f775e19535916c8906caf85436e6d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 5 Aug 2021 19:03:25 +0200 Subject: [PATCH 34/58] Make `xkb_state` more internally consistent --- src/platform_impl/linux/common/xkb_state.rs | 77 +++++++++++-------- .../linux/wayland/seat/keyboard/handlers.rs | 6 -- .../linux/x11/event_processor.rs | 2 +- 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 8c82f2df06..437e5ddf0a 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -64,8 +64,8 @@ pub struct ModifiersState { } impl ModifiersState { - fn new() -> ModifiersState { - ModifiersState::default() + fn new() -> Self { + Self::default() } fn update_with(&mut self, state: *mut ffi::xkb_state) { @@ -253,7 +253,7 @@ impl KbState { Some(byte_slice_to_cached_string(&self.scratch_buffer)) } - pub(crate) fn new() -> Result { + pub(crate) fn new() -> Result { if ffi::XKBCOMMON_OPTION.as_ref().is_none() { return Err(Error::XKBNotFound); } @@ -264,7 +264,7 @@ impl KbState { return Err(Error::XKBNotFound); } - let mut me = KbState { + let mut me = Self { #[cfg(feature = "x11")] xcb_connection: ptr::null_mut(), xkb_context: context, @@ -286,7 +286,7 @@ impl KbState { impl KbState { #[cfg(feature = "x11")] - pub(crate) fn from_x11_xkb(connection: *mut xcb_connection_t) -> Result { + pub(crate) fn from_x11_xkb(connection: *mut xcb_connection_t) -> Result { let mut me = Self::new()?; me.xcb_connection = connection; @@ -304,40 +304,19 @@ impl KbState { }; assert_eq!(result, 1, "Failed to initialize libxkbcommon"); - unsafe { me.load_x11_keymap() }; + unsafe { me.init_with_x11_keymap() }; Ok(me) } - #[cfg(feature = "x11")] - pub(crate) unsafe fn load_x11_keymap(&mut self) { - if !self.xkb_keymap.is_null() { - self.de_init(); - } - - // TODO: Support keyboards other than the "virtual core keyboard device". - let core_keyboard_id = (XKBXH.xkb_x11_get_core_keyboard_device_id)(self.xcb_connection); - let keymap = (XKBXH.xkb_x11_keymap_new_from_device)( - self.xkb_context, - self.xcb_connection, - core_keyboard_id, - xkbcommon_dl::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS, - ); - assert_ne!(keymap, ptr::null_mut()); - self.xkb_keymap = keymap; - self.xkb_state = - (XKBXH.xkb_x11_state_new_from_device)(keymap, self.xcb_connection, core_keyboard_id); - self.mods_state.update_with(self.xkb_state); - } - #[cfg(feature = "wayland")] - pub(crate) fn from_rmlvo(rmlvo: RMLVO) -> Result { + pub(crate) fn from_rmlvo(rmlvo: RMLVO) -> Result { fn to_cstring(s: Option) -> Result, Error> { s.map_or(Ok(None), |s| CString::new(s).map(Option::Some)) .map_err(|_| Error::BadNames) } - let mut state = KbState::new()?; + let mut state = Self::new()?; let rules = to_cstring(rmlvo.rules)?; let model = to_cstring(rmlvo.model)?; @@ -403,22 +382,46 @@ impl KbState { self.xkb_compose_state_2 = compose_state_2; } - pub(crate) unsafe fn post_init(&mut self, keymap: *mut ffi::xkb_keymap) { - let state = (XKBH.xkb_state_new)(keymap); + unsafe fn post_init(&mut self, state: *mut ffi::xkb_state, keymap: *mut ffi::xkb_keymap) { self.xkb_keymap = keymap; self.xkb_state = state; self.mods_state.update_with(state); } - pub(crate) unsafe fn de_init(&mut self) { + unsafe fn de_init(&mut self) { (XKBH.xkb_state_unref)(self.xkb_state); self.xkb_state = ptr::null_mut(); (XKBH.xkb_keymap_unref)(self.xkb_keymap); self.xkb_keymap = ptr::null_mut(); } + #[cfg(feature = "x11")] + pub(crate) unsafe fn init_with_x11_keymap(&mut self) { + if !self.xkb_keymap.is_null() { + self.de_init(); + } + + // TODO: Support keyboards other than the "virtual core keyboard device". + let core_keyboard_id = (XKBXH.xkb_x11_get_core_keyboard_device_id)(self.xcb_connection); + let keymap = (XKBXH.xkb_x11_keymap_new_from_device)( + self.xkb_context, + self.xcb_connection, + core_keyboard_id, + xkbcommon_dl::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS, + ); + assert_ne!(keymap, ptr::null_mut()); + + let state = + (XKBXH.xkb_x11_state_new_from_device)(keymap, self.xcb_connection, core_keyboard_id); + self.post_init(state, keymap); + } + #[cfg(feature = "wayland")] pub(crate) unsafe fn init_with_fd(&mut self, fd: File, size: usize) { + if !self.xkb_keymap.is_null() { + self.de_init(); + } + let map = MmapOptions::new().len(size).map(&fd).unwrap(); let keymap = (XKBH.xkb_keymap_new_from_string)( @@ -432,7 +435,8 @@ impl KbState { panic!("Received invalid keymap from compositor."); } - self.post_init(keymap); + let state = (XKBH.xkb_state_new)(keymap); + self.post_init(state, keymap); } #[cfg(feature = "wayland")] @@ -440,6 +444,10 @@ impl KbState { &mut self, names: ffi::xkb_rule_names, ) -> Result<(), Error> { + if !self.xkb_keymap.is_null() { + self.de_init(); + } + let keymap = (XKBH.xkb_keymap_new_from_names)( self.xkb_context, &names, @@ -450,7 +458,8 @@ impl KbState { return Err(Error::BadNames); } - self.post_init(keymap); + let state = (XKBH.xkb_state_new)(keymap); + self.post_init(state, keymap); Ok(()) } diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index ee4188bde5..26b1faeb46 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -470,12 +470,6 @@ impl KbdHandler { // state is locked, ignore keymap updates return; } - if state.ready() { - // new keymap, we first deinit to free resources - unsafe { - state.de_init(); - } - } match format { wl_keyboard::KeymapFormat::XkbV1 => unsafe { state.init_with_fd(fd, size as usize); diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index cb0ef26458..b9dca34af5 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1118,7 +1118,7 @@ impl EventProcessor { // keymap on *every* keypress. That's peak efficiency right there! // // FIXME: Someone please save our souls! Or at least our wasted CPU cycles. - unsafe { self.kb_state.load_x11_keymap() }; + unsafe { self.kb_state.init_with_x11_keymap() }; let xev: &ffi::XIRawEvent = unsafe { &*(xev.data as *const _) }; From 05af68adfc3469ac70e9cec600b11a47427e5f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 5 Aug 2021 19:14:25 +0200 Subject: [PATCH 35/58] Improve the safety of `KbState` --- src/platform_impl/linux/common/xkb_state.rs | 31 +++++++++++++++++---- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 437e5ddf0a..0b7ca1638a 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -366,14 +366,21 @@ impl KbState { ffi::xkb_compose_state_flags::XKB_COMPOSE_STATE_NO_FLAGS, ); + if compose_table.is_null() { + // init of compose state failed, continue without compose + (XKBCH.xkb_compose_table_unref)(compose_table); + return; + } + let compose_state_2 = (XKBCH.xkb_compose_state_new)( compose_table, ffi::xkb_compose_state_flags::XKB_COMPOSE_STATE_NO_FLAGS, ); - if compose_state.is_null() || compose_state_2.is_null() { + if compose_state_2.is_null() { // init of compose state failed, continue without compose (XKBCH.xkb_compose_table_unref)(compose_table); + (XKBCH.xkb_compose_state_unref)(compose_state); return; } @@ -489,10 +496,24 @@ impl KbState { impl Drop for KbState { fn drop(&mut self) { unsafe { - (XKBCH.xkb_compose_state_unref)(self.xkb_compose_state); - (XKBCH.xkb_compose_table_unref)(self.xkb_compose_table); - (XKBH.xkb_state_unref)(self.xkb_state); - (XKBH.xkb_keymap_unref)(self.xkb_keymap); + // TODO: Simplify this. We can currently only safely assume that the `xkb_context` + // is always valid. If we can somehow guarantee the same for `xkb_state` and + // `xkb_keymap`, then we could omit their null-checks. + if !self.xkb_compose_state.is_null() { + (XKBCH.xkb_compose_state_unref)(self.xkb_compose_state); + } + if !self.xkb_compose_state_2.is_null() { + (XKBCH.xkb_compose_state_unref)(self.xkb_compose_state_2); + } + if !self.xkb_compose_table.is_null() { + (XKBCH.xkb_compose_table_unref)(self.xkb_compose_table); + } + if !self.xkb_state.is_null() { + (XKBH.xkb_state_unref)(self.xkb_state); + } + if !self.xkb_keymap.is_null() { + (XKBH.xkb_keymap_unref)(self.xkb_keymap); + } (XKBH.xkb_context_unref)(self.xkb_context); } } From 5195072b32f8c18d9b63582ae4d387b754630273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 5 Aug 2021 19:21:40 +0200 Subject: [PATCH 36/58] Make a decision on control characters and dead keys --- src/platform_impl/linux/common/xkb_state.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 0b7ca1638a..40403d02ab 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -698,9 +698,9 @@ impl<'a> KeyEventResults<'a> { } pub fn text_with_all_modifiers(&mut self) -> Option<&'static str> { - // TODO: Should Ctrl override any attempts to compose text? - // gnome-terminal agrees, but konsole disagrees. - // Should it be configurable instead? + // The current behaviour makes it so composing a character overrides attempts to input a + // control character with the `Ctrl` key. We can potentially add a configuration option + // if someone specifically wants the oppsite behaviour. self.composed_text() .unwrap_or_else(|_| self.state.get_utf8_raw(self.keycode)) } From 1e1ec76145adf2700a58daa3c5a0a23c93c13010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 5 Aug 2021 19:56:09 +0200 Subject: [PATCH 37/58] Store keycodes with X11's keycode offset --- src/platform_impl/linux/common/keymap.rs | 3 ++- src/platform_impl/linux/common/xkb_state.rs | 16 ++++++++-------- .../linux/wayland/seat/keyboard/handlers.rs | 4 ++-- src/platform_impl/linux/x11/event_processor.rs | 11 +++++------ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index b54a1776ab..b64932e918 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -4,7 +4,8 @@ use crate::keyboard::{Key, KeyCode, KeyLocation, NativeKeyCode}; // TODO: Do another pass on all of this -pub fn rawkey_to_keycode(rawkey: u32) -> KeyCode { +pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { + let rawkey = keycode - 8; // The keycode values are taken from linux/include/uapi/linux/input-event-codes.h, as // libxkbcommon's documentation indicates that the keycode values we're getting from it are // defined by the Linux kernel. If Winit programs end up being run on other Unix-likes which diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 40403d02ab..558a30303f 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -148,16 +148,16 @@ impl KbState { if !self.ready() { return 0; } - unsafe { (XKBH.xkb_state_key_get_one_sym)(self.xkb_state, keycode + 8) } + unsafe { (XKBH.xkb_state_key_get_one_sym)(self.xkb_state, keycode) } } pub(crate) fn get_utf8_raw(&mut self, keycode: u32) -> Option<&'static str> { if !self.ready() { return None; } - let size = unsafe { - (XKBH.xkb_state_key_get_utf8)(self.xkb_state, keycode + 8, ptr::null_mut(), 0) - } + 1; + let size = + unsafe { (XKBH.xkb_state_key_get_utf8)(self.xkb_state, keycode, ptr::null_mut(), 0) } + + 1; if size <= 1 { return None; }; @@ -168,7 +168,7 @@ impl KbState { self.scratch_buffer.set_len(size); (XKBH.xkb_state_key_get_utf8)( self.xkb_state, - keycode + 8, + keycode, self.scratch_buffer.as_mut_ptr() as *mut _, size, ); @@ -474,7 +474,7 @@ impl KbState { impl KbState { pub(crate) unsafe fn key_repeats(&mut self, keycode: ffi::xkb_keycode_t) -> bool { - (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, keycode + 8) == 1 + (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, keycode) == 1 } #[inline] @@ -615,7 +615,7 @@ impl<'a> KeyEventResults<'a> { } pub fn keycode(&mut self) -> KeyCode { - super::keymap::rawkey_to_keycode(self.keycode) + super::keymap::raw_keycode_to_keycode(self.keycode) } pub fn key(&mut self) -> (Key<'static>, KeyLocation) { @@ -656,7 +656,7 @@ impl<'a> KeyEventResults<'a> { let keysym_count = unsafe { (XKBH.xkb_keymap_key_get_syms_by_level)( self.state.xkb_keymap, - self.keycode + 8, + self.keycode, 0, 0, &mut keysyms, diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 26b1faeb46..fddecc09fc 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -548,7 +548,7 @@ impl KbdHandler { _ => unreachable!(), }; - let mut ker = state.process_key_event(key, key_state); + let mut ker = state.process_key_event(key + 8, key_state); let physical_key = ker.keycode(); let (logical_key, location) = ker.key(); @@ -683,7 +683,7 @@ impl calloop::EventSource for RepeatSource { if let Some(ref mut data) = *current_repeat.borrow_mut() { // there is something to repeat let mut state = state.borrow_mut(); - let mut ker = state.process_key_repeat_event(data.keycode); + let mut ker = state.process_key_repeat_event(data.keycode + 8); let physical_key = ker.keycode(); let (logical_key, location) = ker.key(); diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index b9dca34af5..5e4681351d 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1055,7 +1055,6 @@ impl EventProcessor { let device_id = mkdid(xkev.deviceid); let keycode = xkev.detail as u32; - let keycode = keycode - KEYCODE_OFFSET as u32; let mut ker = self.kb_state.process_key_event(keycode, state); let physical_key = ker.keycode(); let (logical_key, location) = ker.key(); @@ -1129,12 +1128,11 @@ impl EventProcessor { }; let device_id = mkdid(xev.sourceid); - let keycode = xev.detail; - let scancode = keycode - KEYCODE_OFFSET as i32; - if scancode < 0 { + let keycode = xev.detail as u32; + if keycode < KEYCODE_OFFSET as u32 { return; } - let physical_key = keymap::rawkey_to_keycode(scancode as u32); + let physical_key = keymap::raw_keycode_to_keycode(keycode); let modifiers = self.device_mod_state.modifiers(); callback(Event::DeviceEvent { @@ -1359,7 +1357,8 @@ impl EventProcessor { .into_iter() .filter(|k| *k >= KEYCODE_OFFSET) { - let keycode = (keycode - KEYCODE_OFFSET) as u32; + let keycode = keycode as u32; + let mut ker = kb_state.process_key_event(keycode, state); let physical_key = ker.keycode(); let (logical_key, location) = ker.key(); From 7784cfdcd7ac192c57cfe03fa99ccdf9a302c052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 5 Aug 2021 19:59:32 +0200 Subject: [PATCH 38/58] Log an error if we can't select XKB events --- src/platform_impl/linux/x11/util/input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/x11/util/input.rs b/src/platform_impl/linux/x11/util/input.rs index db0f22eb03..24aad57937 100644 --- a/src/platform_impl/linux/x11/util/input.rs +++ b/src/platform_impl/linux/x11/util/input.rs @@ -86,7 +86,7 @@ impl XConnection { if status == ffi::True { Some(Flusher::new(self)) } else { - // This should only happen if the XKB extension isn't initialized. + error!("Could not select XKB events: The XKB extension is not initialized!"); None } } From 23c4bfb4dcc8e089ac6cfedae8692a4d716b6624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 5 Aug 2021 20:08:40 +0200 Subject: [PATCH 39/58] Remove superfluous call to `Vec::set_len` --- src/platform_impl/linux/common/xkb_state.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 558a30303f..6cdc335637 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -540,7 +540,6 @@ impl KbState { self.scratch_buffer.clear(); self.scratch_buffer.reserve(8); loop { - unsafe { self.scratch_buffer.set_len(8) }; let bytes_written = unsafe { (XKBH.xkb_keysym_to_utf8)( keysym, From 9e8310b01fe7fe327aac8be50812ec2735f0c219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 12 Aug 2021 01:51:50 +0200 Subject: [PATCH 40/58] Send a warning if the server doesn't send a keymap --- src/platform_impl/linux/wayland/seat/keyboard/handlers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index fddecc09fc..232cac4be2 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -475,7 +475,7 @@ impl KbdHandler { state.init_with_fd(fd, size as usize); }, wl_keyboard::KeymapFormat::NoKeymap => { - // TODO: how to handle this (hopefully never occuring) case? + warn!("The Wayland server did not send a keymap!"); } _ => unreachable!(), } From 446f24355ae5ec03bccf04b91faf5086c4dda37f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Wed, 25 Aug 2021 00:32:07 +0200 Subject: [PATCH 41/58] Implement `KeyCodeExtScancode` on Wayland and X11 --- src/platform/scancode.rs | 1 + src/platform/unix.rs | 17 ++- src/platform_impl/linux/common/keymap.rs | 172 +++++++++++++++++++++-- src/platform_impl/linux/mod.rs | 2 +- 4 files changed, 174 insertions(+), 18 deletions(-) diff --git a/src/platform/scancode.rs b/src/platform/scancode.rs index 078fe74dea..00188c6212 100644 --- a/src/platform/scancode.rs +++ b/src/platform/scancode.rs @@ -20,6 +20,7 @@ pub trait KeyCodeExtScancode { /// /// ## Platform-specific /// - **Windows:** A 16bit extended scancode + /// - **Wayland/X11**: A 32-bit X11-style keycode. // TODO: Describe what this value contains for each platform fn to_scancode(self) -> Option; diff --git a/src/platform/unix.rs b/src/platform/unix.rs index 1c00f1674d..78dd1e93a7 100644 --- a/src/platform/unix.rs +++ b/src/platform/unix.rs @@ -12,10 +12,11 @@ use std::{ptr, sync::Arc}; use crate::{ event::KeyEvent, - event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget}, - keyboard::Key, + event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + keyboard::{Key, KeyCode}, monitor::MonitorHandle, - platform::modifier_supplement::KeyEventExtModifierSupplement, + platform::{modifier_supplement::KeyEventExtModifierSupplement, scancode::KeyCodeExtScancode}, + platform_impl::common::keymap, window::{Window, WindowBuilder}, }; @@ -449,3 +450,13 @@ impl KeyEventExtModifierSupplement for KeyEvent { self.platform_specific.key_without_modifiers } } + +impl KeyCodeExtScancode for KeyCode { + fn from_scancode(scancode: u32) -> KeyCode { + keymap::raw_keycode_to_keycode(scancode) + } + + fn to_scancode(self) -> Option { + keymap::keycode_to_raw(self) + } +} diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index b64932e918..610fc4f38a 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -2,8 +2,9 @@ use crate::keyboard::{Key, KeyCode, KeyLocation, NativeKeyCode}; -// TODO: Do another pass on all of this - +/// Map the raw X11-style keycode to the `KeyCode` enum. +/// +/// X11-style keycodes are offset by 8 from the keycodes the Linux kernel uses. pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { let rawkey = keycode - 8; // The keycode values are taken from linux/include/uapi/linux/input-event-codes.h, as @@ -14,10 +15,8 @@ pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { // Some of the keycodes are likely superfluous for our purposes, and some are ones which are // difficult to test the correctness of, or discover the purpose of. Because of this, they've // either been commented out here, or not included at all. - // - // TODO: There are probably a couple more unproblematic keycodes to map here. match rawkey { - 0 => KeyCode::Unidentified(NativeKeyCode::XKB(0)), // TODO: Is `NativeKeyCode::Unidentified` better? + 0 => KeyCode::Unidentified(NativeKeyCode::XKB(0)), 1 => KeyCode::Escape, 2 => KeyCode::Digit1, 3 => KeyCode::Digit2, @@ -93,7 +92,7 @@ pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { 73 => KeyCode::Numpad9, 74 => KeyCode::NumpadSubtract, 75 => KeyCode::Numpad4, - 76 => KeyCode::Numpad4, + 76 => KeyCode::Numpad5, 77 => KeyCode::Numpad6, 78 => KeyCode::NumpadAdd, 79 => KeyCode::Numpad1, @@ -264,6 +263,151 @@ pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { } } +pub fn keycode_to_raw(keycode: KeyCode) -> Option { + match keycode { + KeyCode::Unidentified(NativeKeyCode::Unidentified) => Some(240), + KeyCode::Unidentified(NativeKeyCode::XKB(raw)) => Some(raw), + KeyCode::Escape => Some(1), + KeyCode::Digit1 => Some(2), + KeyCode::Digit2 => Some(3), + KeyCode::Digit3 => Some(4), + KeyCode::Digit4 => Some(5), + KeyCode::Digit5 => Some(6), + KeyCode::Digit6 => Some(7), + KeyCode::Digit7 => Some(8), + KeyCode::Digit8 => Some(9), + KeyCode::Digit9 => Some(10), + KeyCode::Digit0 => Some(11), + KeyCode::Minus => Some(12), + KeyCode::Equal => Some(13), + KeyCode::Backspace => Some(14), + KeyCode::Tab => Some(15), + KeyCode::KeyQ => Some(16), + KeyCode::KeyW => Some(17), + KeyCode::KeyE => Some(18), + KeyCode::KeyR => Some(19), + KeyCode::KeyT => Some(20), + KeyCode::KeyY => Some(21), + KeyCode::KeyU => Some(22), + KeyCode::KeyI => Some(23), + KeyCode::KeyO => Some(24), + KeyCode::KeyP => Some(25), + KeyCode::BracketLeft => Some(26), + KeyCode::BracketRight => Some(27), + KeyCode::Enter => Some(28), + KeyCode::ControlLeft => Some(29), + KeyCode::KeyA => Some(30), + KeyCode::KeyS => Some(31), + KeyCode::KeyD => Some(32), + KeyCode::KeyF => Some(33), + KeyCode::KeyG => Some(34), + KeyCode::KeyH => Some(35), + KeyCode::KeyJ => Some(36), + KeyCode::KeyK => Some(37), + KeyCode::KeyL => Some(38), + KeyCode::Semicolon => Some(39), + KeyCode::Quote => Some(40), + KeyCode::Backquote => Some(41), + KeyCode::ShiftLeft => Some(42), + KeyCode::Backslash => Some(43), + KeyCode::KeyZ => Some(44), + KeyCode::KeyX => Some(45), + KeyCode::KeyC => Some(46), + KeyCode::KeyV => Some(47), + KeyCode::KeyB => Some(48), + KeyCode::KeyN => Some(49), + KeyCode::KeyM => Some(50), + KeyCode::Comma => Some(51), + KeyCode::Period => Some(52), + KeyCode::Slash => Some(53), + KeyCode::ShiftRight => Some(54), + KeyCode::NumpadMultiply => Some(55), + KeyCode::AltLeft => Some(56), + KeyCode::Space => Some(57), + KeyCode::CapsLock => Some(58), + KeyCode::F1 => Some(59), + KeyCode::F2 => Some(60), + KeyCode::F3 => Some(61), + KeyCode::F4 => Some(62), + KeyCode::F5 => Some(63), + KeyCode::F6 => Some(64), + KeyCode::F7 => Some(65), + KeyCode::F8 => Some(66), + KeyCode::F9 => Some(67), + KeyCode::F10 => Some(68), + KeyCode::NumLock => Some(69), + KeyCode::ScrollLock => Some(70), + KeyCode::Numpad7 => Some(71), + KeyCode::Numpad8 => Some(72), + KeyCode::Numpad9 => Some(73), + KeyCode::NumpadSubtract => Some(74), + KeyCode::Numpad4 => Some(75), + KeyCode::Numpad5 => Some(76), + KeyCode::Numpad6 => Some(77), + KeyCode::NumpadAdd => Some(78), + KeyCode::Numpad1 => Some(79), + KeyCode::Numpad2 => Some(80), + KeyCode::Numpad3 => Some(81), + KeyCode::Numpad0 => Some(82), + KeyCode::NumpadDecimal => Some(83), + KeyCode::Lang5 => Some(85), + KeyCode::IntlBackslash => Some(86), + KeyCode::F11 => Some(87), + KeyCode::F12 => Some(88), + KeyCode::IntlRo => Some(89), + KeyCode::Lang3 => Some(90), + KeyCode::Lang4 => Some(91), + KeyCode::Convert => Some(92), + KeyCode::KanaMode => Some(93), + KeyCode::NonConvert => Some(94), + KeyCode::NumpadEnter => Some(96), + KeyCode::ControlRight => Some(97), + KeyCode::NumpadDivide => Some(98), + KeyCode::PrintScreen => Some(99), + KeyCode::AltRight => Some(100), + KeyCode::Home => Some(102), + KeyCode::ArrowUp => Some(103), + KeyCode::PageUp => Some(104), + KeyCode::ArrowLeft => Some(105), + KeyCode::ArrowRight => Some(106), + KeyCode::End => Some(107), + KeyCode::ArrowDown => Some(108), + KeyCode::PageDown => Some(109), + KeyCode::Insert => Some(110), + KeyCode::Delete => Some(111), + KeyCode::AudioVolumeMute => Some(113), + KeyCode::AudioVolumeDown => Some(114), + KeyCode::AudioVolumeUp => Some(115), + KeyCode::NumpadEqual => Some(117), + KeyCode::Pause => Some(119), + KeyCode::NumpadComma => Some(121), + KeyCode::Lang1 => Some(122), + KeyCode::Lang2 => Some(123), + KeyCode::IntlYen => Some(124), + KeyCode::SuperLeft => Some(125), + KeyCode::SuperRight => Some(126), + KeyCode::ContextMenu => Some(127), + KeyCode::MediaTrackNext => Some(163), + KeyCode::MediaPlayPause => Some(164), + KeyCode::MediaTrackPrevious => Some(165), + KeyCode::MediaStop => Some(166), + KeyCode::F13 => Some(183), + KeyCode::F14 => Some(184), + KeyCode::F15 => Some(185), + KeyCode::F16 => Some(186), + KeyCode::F17 => Some(187), + KeyCode::F18 => Some(188), + KeyCode::F19 => Some(189), + KeyCode::F20 => Some(190), + KeyCode::F21 => Some(191), + KeyCode::F22 => Some(192), + KeyCode::F23 => Some(193), + KeyCode::F24 => Some(194), + _ => None, + } + .map(|raw| raw + 8) +} + pub fn keysym_to_key(keysym: u32) -> Key<'static> { use xkbcommon_dl::keysyms; match keysym { @@ -273,7 +417,7 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // keysyms::XKB_KEY_Linefeed => Key::Linefeed, keysyms::XKB_KEY_Clear => Key::Clear, keysyms::XKB_KEY_Return => Key::Enter, - // keysyms::XKB_KEY_Pause => Key::Pause, + keysyms::XKB_KEY_Pause => Key::Pause, keysyms::XKB_KEY_Scroll_Lock => Key::ScrollLock, keysyms::XKB_KEY_Sys_Req => Key::PrintScreen, keysyms::XKB_KEY_Escape => Key::Escape, @@ -357,6 +501,8 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // keysyms::XKB_KEY_KP_Next => Key::PageDown, keysyms::XKB_KEY_KP_Page_Down => Key::PageDown, keysyms::XKB_KEY_KP_End => Key::End, + // TODO: What is this supposed to map to? + // This is the key labeled "5" on the numpad when NumLock is off. // keysyms::XKB_KEY_KP_Begin => Key::Begin, keysyms::XKB_KEY_KP_Insert => Key::Insert, keysyms::XKB_KEY_KP_Delete => Key::Delete, @@ -423,8 +569,7 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { keysyms::XKB_KEY_Control_R => Key::Control, keysyms::XKB_KEY_Caps_Lock => Key::CapsLock, // keysyms::XKB_KEY_Shift_Lock => Key::ShiftLock, - // - // TODO: Address how renaming `Meta` to `Super` affects this set of keys. + // keysyms::XKB_KEY_Meta_L => Key::Meta, // keysyms::XKB_KEY_Meta_R => Key::Meta, keysyms::XKB_KEY_Alt_L => Key::Alt, @@ -438,7 +583,6 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // keysyms::XKB_KEY_ISO_Lock => Key::IsoLock, // keysyms::XKB_KEY_ISO_Level2_Latch => Key::IsoLevel2Latch, keysyms::XKB_KEY_ISO_Level3_Shift => Key::AltGraph, - // NOTE: I'm not quite certain if mapping the next 2 values to AltGraph is correct. keysyms::XKB_KEY_ISO_Level3_Latch => Key::AltGraph, keysyms::XKB_KEY_ISO_Level3_Lock => Key::AltGraph, // keysyms::XKB_KEY_ISO_Level5_Shift => Key::IsoLevel5Shift, @@ -562,9 +706,9 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { keysyms::XKB_KEY_XF86Calendar => Key::LaunchCalendar, keysyms::XKB_KEY_XF86PowerDown => Key::Power, // keysyms::XKB_KEY_XF86ContrastAdjust => Key::AdjustContrast, - // keysyms::XKB_KEY_XF86RockerUp => Key::RockerUp, // TODO: Use Key::ArrowUp? - // keysyms::XKB_KEY_XF86RockerDown => Key::RockerDown, // TODO: Use Key::ArrowDown? - // keysyms::XKB_KEY_XF86RockerEnter => Key::RockerEnter, // TODO: Use Key::Enter? + // keysyms::XKB_KEY_XF86RockerUp => Key::RockerUp, + // keysyms::XKB_KEY_XF86RockerDown => Key::RockerDown, + // keysyms::XKB_KEY_XF86RockerEnter => Key::RockerEnter, // XFree86 - More "Internet" keysyms::XKB_KEY_XF86Back => Key::BrowserBack, @@ -596,7 +740,7 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // XKB_KEY_XF86Launch0..XKB_KEY_XF86LaunchF // XKB_KEY_XF86ApplicationLeft..XKB_KEY_XF86CD - keysyms::XKB_KEY_XF86Calculater => Key::LaunchApplication2, // This must be a typo, right? + keysyms::XKB_KEY_XF86Calculater => Key::LaunchApplication2, // Nice typo, libxkbcommon :) // XKB_KEY_XF86Clear keysyms::XKB_KEY_XF86Close => Key::Close, keysyms::XKB_KEY_XF86Copy => Key::Copy, diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index d352e68e88..8c59abe034 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -49,7 +49,7 @@ pub mod wayland; pub mod x11; #[cfg(any(feature = "x11", feature = "wayland"))] -mod common; +pub mod common; #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub struct KeyEventExtra { From 48cce91ca9f2cb9d505b36b79b8fa01f572cba72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Wed, 25 Aug 2021 00:47:28 +0200 Subject: [PATCH 42/58] Implement `reset_dead_keys` (poorly) --- src/platform_impl/linux/common/xkb_state.rs | 43 ++++++++++++++++--- src/platform_impl/linux/mod.rs | 3 +- .../linux/x11/event_processor.rs | 10 +++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 6cdc335637..f3aeedb79e 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -5,12 +5,16 @@ use std::fs::File; use std::os::raw::c_char; use std::os::unix::ffi::OsStringExt; use std::ptr; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Mutex; #[cfg(feature = "wayland")] use memmap2::MmapOptions; #[cfg(feature = "wayland")] pub use sctk::seat::keyboard::RMLVO; +#[cfg(feature = "x11")] +use once_cell::sync::Lazy; #[cfg(feature = "x11")] use x11_dl::xlib_xcb::xcb_connection_t; #[cfg(feature = "x11")] @@ -25,6 +29,19 @@ use crate::{ keyboard::{Key, KeyCode, KeyLocation}, }; +// TODO: Wire this up without using a static `Mutex>`. +#[cfg(feature = "x11")] +pub(crate) static X11_EVPROC_NEXT_COMPOSE: Lazy>> = + Lazy::new(|| Mutex::new(None)); + +// TODO: Wire this up without using a static `AtomicBool`. +static RESET_DEAD_KEYS: AtomicBool = AtomicBool::new(false); + +#[inline] +pub(crate) fn reset_dead_keys() { + RESET_DEAD_KEYS.store(true, Ordering::SeqCst); +} + pub(crate) struct KbState { #[cfg(feature = "x11")] xcb_connection: *mut xcb_connection_t, @@ -194,6 +211,9 @@ impl KbState { if !self.ready() || self.xkb_compose_state.is_null() { return None; } + if RESET_DEAD_KEYS.swap(false, Ordering::SeqCst) { + unsafe { self.init_compose() }; + } Some(unsafe { (XKBCH.xkb_compose_state_feed)(xkb_compose_state, keysym) }) } @@ -639,13 +659,22 @@ impl<'a> KeyEventResults<'a> { _ => (key, location), } } - _ => ( - self.composed_text() - .unwrap_or_else(|_| self.state.keysym_to_utf8_raw(self.keysym)) - .map(Key::Character) - .unwrap_or(key), - location, - ), + _ => { + let composed_text = self.composed_text(); + + #[cfg(feature = "x11")] + if let Ok(Some(composed_text)) = composed_text { + *X11_EVPROC_NEXT_COMPOSE.lock().unwrap() = Some(composed_text); + } + + ( + composed_text + .unwrap_or_else(|_| self.state.keysym_to_utf8_raw(self.keysym)) + .map(Key::Character) + .unwrap_or(key), + location, + ) + } }) } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 8c59abe034..b6a467bc43 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -487,8 +487,9 @@ impl Window { x11_or_wayland!(match self; Window(w) => w.set_ime_position(position)) } + #[inline] pub fn reset_dead_keys(&self) { - todo!() + common::xkb_state::reset_dead_keys() } #[inline] diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 5e4681351d..0f8902c606 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -552,6 +552,16 @@ impl EventProcessor { // If we're composing right now, send the string we've got from X11 via // Ime::Commit. if self.is_composing && xkev.keycode == 0 && !written.is_empty() { + if super::super::common::xkb_state::X11_EVPROC_NEXT_COMPOSE + .lock() + .unwrap() + .take() + .map(|composed| composed == written) + .unwrap_or(false) + { + return; + } + let event = Event::WindowEvent { window_id, event: WindowEvent::Ime(Ime::Commit(written)), From e7a3043bee57c883bfb34f8d9f7a110e5af389cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 9 Sep 2021 19:25:57 +0200 Subject: [PATCH 43/58] Split the native XKB keycode enum variant in two `XkbCode` now contains keycodes while `XkbSym` contains keysyms. This may change sooner rather than later. --- src/keyboard.rs | 13 +++++++++---- src/platform_impl/linux/common/keymap.rs | 8 ++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/keyboard.rs b/src/keyboard.rs index 9ab9919979..72c7b6128a 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -175,11 +175,12 @@ pub enum NativeKeyCode { Unidentified, Windows(u16), MacOS(u32), - XKB(u32), + XkbCode(u32), + XkbSym(u32), } impl std::fmt::Debug for NativeKeyCode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use NativeKeyCode::{MacOS, Unidentified, Windows, XKB}; + use NativeKeyCode::{MacOS, Unidentified, Windows, XkbCode, XkbSym}; let mut debug_tuple; match self { Unidentified => { @@ -193,8 +194,12 @@ impl std::fmt::Debug for NativeKeyCode { debug_tuple = f.debug_tuple(name_of!(MacOS)); debug_tuple.field(v); } - XKB(v) => { - debug_tuple = f.debug_tuple(name_of!(XKB)); + XkbCode(v) => { + debug_tuple = f.debug_tuple(name_of!(XkbCode)); + debug_tuple.field(&format_args!("0x{:04X}", v)); + } + XkbSym(v) => { + debug_tuple = f.debug_tuple(name_of!(XkbSym)); debug_tuple.field(&format_args!("0x{:04X}", v)); } } diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index 610fc4f38a..8e2e6c2458 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -16,7 +16,7 @@ pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { // difficult to test the correctness of, or discover the purpose of. Because of this, they've // either been commented out here, or not included at all. match rawkey { - 0 => KeyCode::Unidentified(NativeKeyCode::XKB(0)), + 0 => KeyCode::Unidentified(NativeKeyCode::XkbCode(0)), 1 => KeyCode::Escape, 2 => KeyCode::Digit1, 3 => KeyCode::Digit2, @@ -259,14 +259,14 @@ pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { // 246 => KeyCode::WWAN, // 247 => KeyCode::RFKILL, // 248 => KeyCode::KEY_MICMUTE, - _ => KeyCode::Unidentified(NativeKeyCode::XKB(rawkey)), + _ => KeyCode::Unidentified(NativeKeyCode::XkbCode(rawkey)), } } pub fn keycode_to_raw(keycode: KeyCode) -> Option { match keycode { KeyCode::Unidentified(NativeKeyCode::Unidentified) => Some(240), - KeyCode::Unidentified(NativeKeyCode::XKB(raw)) => Some(raw), + KeyCode::Unidentified(NativeKeyCode::XkbCode(raw)) => Some(raw), KeyCode::Escape => Some(1), KeyCode::Digit1 => Some(2), KeyCode::Digit2 => Some(3), @@ -827,7 +827,7 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // XKB_KEY_SunPowerSwitchShift // 0 => Key::Unidentified(NativeKeyCode::Unidentified), - _ => Key::Unidentified(NativeKeyCode::XKB(keysym)), + _ => Key::Unidentified(NativeKeyCode::XkbSym(keysym)), } } From b68b364abca5e678f8707959c3912f014f003812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 9 Sep 2021 20:41:46 +0200 Subject: [PATCH 44/58] Add a TODO regarding the `ModifiersChanged` event. --- src/platform_impl/linux/x11/event_processor.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 0f8902c606..7b630ee956 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1143,6 +1143,13 @@ impl EventProcessor { return; } let physical_key = keymap::raw_keycode_to_keycode(keycode); + // TODO: Figure out how redundant this is. + // This is the set of modifiers end users end up seeing. However, the set of + // modifiers used internally by the `KbState` are sourced directly from the XKB + // extension. Since we currently panic when the extension doesn't load, we should + // be able to use the modifiers supplied to us by the XKB extension. This + // requires us to have consensus on what to do if we can't load and initialize + // libxkbcommon. let modifiers = self.device_mod_state.modifiers(); callback(Event::DeviceEvent { @@ -1153,8 +1160,6 @@ impl EventProcessor { }), }); - // `ModifiersChanged` is dispatched here because we assume that every `XI_KeyPress` - // is preceeded by a `XI_RawKeyPress`. if let Some(modifier) = self.mod_keymap.get_modifier(keycode as ffi::KeyCode) { From 31103b86d43a56172bd18e886fff96ecaf8b7865 Mon Sep 17 00:00:00 2001 From: Robert Timm Date: Thu, 9 Sep 2021 21:35:46 +0200 Subject: [PATCH 45/58] fix: meta mod key on focus handling for gnome/x11 This patch addresses an issue in the modifier key handling appearing on gnome/x11 while focussing a winit window using a meta/super/logo key shortcut. As soon as the window gained focus via a shortcut using a meta key, gnome/x11 reports a meta modifier as pressed in the focus event, even though it was just released. No key release events were sent afterwards, so the meta modifier remained "stuck" in the winit state. This patch refactors the modifier key handling following this goals: - Only rely on winit's own modifier state tracking for key and focus events, do not mix it with x11's modifier reporting - Track modifiers only via non-raw key events, so winit does not track modifier changes when not focussed - Integrate modifier handling with the synthetic key events mechanism in order to report release of all currently held modifiers when unfocussed and report set for all currently held modifiers when focussed. --- .../linux/x11/event_processor.rs | 93 +++++++++---------- 1 file changed, 43 insertions(+), 50 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 7b630ee956..5edf0ecc23 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -843,10 +843,6 @@ impl EventProcessor { .focus(xev.event) .expect("Failed to focus input context"); - let modifiers = ModifiersState::from_x11(&xev.mods); - - self.device_mod_state.update_state(&modifiers, None); - if self.active_window != Some(xev.event) { self.active_window = Some(xev.event); @@ -860,12 +856,16 @@ impl EventProcessor { event: Focused(true), }); - if !modifiers.is_empty() { - callback(Event::WindowEvent { - window_id, - event: WindowEvent::ModifiersChanged(modifiers), - }); - } + // Issue key press events for all pressed keys + Self::handle_pressed_keys( + &wt, + window_id, + ElementState::Pressed, + &mut self.kb_state, + &self.mod_keymap, + &mut self.device_mod_state, + &mut callback, + ); // The deviceid for this event is for a keyboard instead of a pointer, // so we have to do a little extra work. @@ -881,7 +881,7 @@ impl EventProcessor { event: CursorMoved { device_id: mkdid(pointer_id), position, - modifiers, + modifiers: self.device_mod_state.modifiers(), }, }); @@ -897,6 +897,7 @@ impl EventProcessor { ); } } + ffi::XI_FocusOut => { let xev: &ffi::XIFocusOutEvent = unsafe { &*(xev.data as *const _) }; if !self.window_exists(xev.event) { @@ -924,11 +925,6 @@ impl EventProcessor { &mut callback, ); - callback(Event::WindowEvent { - window_id, - event: WindowEvent::ModifiersChanged(ModifiersState::empty()), - }); - callback(Event::WindowEvent { window_id, event: Focused(false), @@ -1073,6 +1069,27 @@ impl EventProcessor { let text_with_all_modifiers = ker.text_with_all_modifiers(); let repeat = xkev.flags & ffi::XIKeyRepeat == ffi::XIKeyRepeat; + if let Some(modifier) = + self.mod_keymap.get_modifier(keycode as ffi::KeyCode) + { + let old_modifiers = self.device_mod_state.modifiers(); + + self.device_mod_state.key_event( + state, + keycode as ffi::KeyCode, + modifier, + ); + + if old_modifiers != self.device_mod_state.modifiers() { + callback(Event::WindowEvent { + window_id, + event: WindowEvent::ModifiersChanged( + self.device_mod_state.modifiers(), + ), + }); + } + } + callback(Event::WindowEvent { window_id, event: WindowEvent::KeyboardInput { @@ -1143,14 +1160,6 @@ impl EventProcessor { return; } let physical_key = keymap::raw_keycode_to_keycode(keycode); - // TODO: Figure out how redundant this is. - // This is the set of modifiers end users end up seeing. However, the set of - // modifiers used internally by the `KbState` are sourced directly from the XKB - // extension. Since we currently panic when the extension doesn't load, we should - // be able to use the modifiers supplied to us by the XKB extension. This - // requires us to have consensus on what to do if we can't load and initialize - // libxkbcommon. - let modifiers = self.device_mod_state.modifiers(); callback(Event::DeviceEvent { device_id, @@ -1159,27 +1168,6 @@ impl EventProcessor { state, }), }); - - if let Some(modifier) = - self.mod_keymap.get_modifier(keycode as ffi::KeyCode) - { - self.device_mod_state.key_event( - state, - keycode as ffi::KeyCode, - modifier, - ); - - let new_modifiers = self.device_mod_state.modifiers(); - - if modifiers != new_modifiers { - if let Some(window_id) = self.active_window { - callback(Event::WindowEvent { - window_id: mkwid(window_id), - event: WindowEvent::ModifiersChanged(new_modifiers), - }); - } - } - } } ffi::XI_HierarchyChanged => { @@ -1382,11 +1370,16 @@ impl EventProcessor { let text_with_all_modifiers = ker.text_with_all_modifiers(); if let Some(modifier) = mod_keymap.get_modifier(keycode as ffi::KeyCode) { - device_mod_state.key_event( - ElementState::Pressed, - keycode as ffi::KeyCode, - modifier, - ); + let old_modifiers = device_mod_state.modifiers(); + + device_mod_state.key_event(state, keycode as ffi::KeyCode, modifier); + + if old_modifiers != device_mod_state.modifiers() { + callback(Event::WindowEvent { + window_id, + event: WindowEvent::ModifiersChanged(device_mod_state.modifiers()), + }); + } } callback(Event::WindowEvent { From 53c28f8c27e95978bce08bf1cff6741c31995511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Wed, 6 Oct 2021 18:21:48 +0200 Subject: [PATCH 46/58] Remove the `XkbStateNotify` handler The only thing we did in response to said event is update the `xkb_state`, but we throw that away on every keypress anyway due to the keyeyboard layout change detection hack. This commit also removes associated code which let us recieve and react to the event in the first place. If a fix is ever introduced, then this commit ought to be reverted. --- .../linux/x11/event_processor.rs | 28 ++++------------- src/platform_impl/linux/x11/mod.rs | 31 ------------------- 2 files changed, 6 insertions(+), 53 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 5edf0ecc23..89d764f622 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, collections::HashMap, convert::identity, rc::Rc, slice, sync::Arc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc, slice, sync::Arc}; use libc::{c_char, c_int, c_long, c_ulong}; @@ -35,7 +35,6 @@ pub(super) struct EventProcessor { pub(super) randr_event_offset: c_int, pub(super) devices: RefCell>, pub(super) xi2ext: XExtension, - pub(super) xkbext: XExtension, pub(super) target: Rc>, pub(super) kb_state: KbState, pub(super) mod_keymap: ModifierKeymap, @@ -1144,6 +1143,11 @@ impl EventProcessor { // keymap on *every* keypress. That's peak efficiency right there! // // FIXME: Someone please save our souls! Or at least our wasted CPU cycles. + // + // If you do manage to find a solution, remember to re-enable (and handle) the + // `XkbStateNotify` event with `XkbSelectEventDetails` with a mask of + // `XkbAllStateComponentsMask & !XkbPointerButtonMask` like in + // . unsafe { self.kb_state.init_with_x11_keymap() }; let xev: &ffi::XIRawEvent = unsafe { &*(xev.data as *const _) }; @@ -1197,26 +1201,6 @@ impl EventProcessor { } } _ => { - if event_type == self.xkbext.first_event_id { - let xev = unsafe { &*(identity(xev) as *const _ as *const ffi::XkbAnyEvent) }; - match xev.xkb_type { - ffi::XkbStateNotify => { - let xev = - unsafe { &*(xev as *const _ as *const ffi::XkbStateNotifyEvent) }; - if matches!(xev.event_type as i32, ffi::KeyPress | ffi::KeyRelease) { - self.kb_state.update_modifiers( - xev.base_mods, - xev.latched_mods, - xev.locked_mods, - xev.base_group as u32, - xev.latched_group as u32, - xev.locked_group as u32, - ) - } - } - _ => {} - } - } if event_type == self.randr_event_offset { // In the future, it would be quite easy to emit monitor hotplug events. let prev_list = monitor::invalidate_cached_monitor_list(); diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 405440e6f5..06f0a4a218 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -202,27 +202,6 @@ impl EventLoop { ext }; - let xkbext = { - let mut ext = XExtension::default(); - - let res = unsafe { - (xconn.xlib.XkbQueryExtension)( - xconn.display, - &mut ext.opcode, - &mut ext.first_event_id, - &mut ext.first_error_id, - &mut 1, - &mut 0, - ) - }; - - if res == ffi::False { - panic!("X server missing XKB extension"); - } - - ext - }; - unsafe { let mut xinput_major_ver = ffi::XI_2_Major; let mut xinput_minor_ver = ffi::XI_2_Minor; @@ -290,7 +269,6 @@ impl EventLoop { ime_receiver, ime_event_receiver, xi2ext, - xkbext, kb_state, mod_keymap, device_mod_state: Default::default(), @@ -307,15 +285,6 @@ impl EventLoop { .select_xinput_events(root, ffi::XIAllDevices, ffi::XI_HierarchyChangedMask) .queue(); - get_xtarget(&target) - .xconn - .select_xkb_events( - 0x100, // Use the "core keyboard device" - ffi::XkbNewKeyboardNotifyMask | ffi::XkbMapNotifyMask | ffi::XkbStateNotifyMask, - ) - .unwrap() - .queue(); - event_processor.init_device(ffi::XIAllDevices); EventLoop { From a160354be77323d72c3c74beb5f1ffe649833f81 Mon Sep 17 00:00:00 2001 From: Julian Orth Date: Thu, 21 Oct 2021 11:12:27 +0200 Subject: [PATCH 47/58] X11: Only fetch virtual keyboard events from master devices We must not report virtual keyboard events for keys that were grabbed by other applications (XGrabKey, etc.). Since grabs only affect master devices, we must consume virtual events from master devices only. --- src/platform_impl/linux/x11/mod.rs | 1 - src/platform_impl/linux/x11/window.rs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 06f0a4a218..676f612ce6 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -558,7 +558,6 @@ impl EventLoopWindowTarget { | ffi::XI_RawKeyPressMask | ffi::XI_RawKeyReleaseMask; } - mask |= ffi::XI_KeyPressMask | ffi::XI_KeyReleaseMask; self.xconn .select_xinput_events(self.root, ffi::XIAllDevices, mask) diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 23335fc15a..0a5a79f2f8 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -439,8 +439,8 @@ impl UnownedWindow { let mask = ffi::XI_MotionMask | ffi::XI_ButtonPressMask | ffi::XI_ButtonReleaseMask - //| ffi::XI_KeyPressMask - //| ffi::XI_KeyReleaseMask + | ffi::XI_KeyPressMask + | ffi::XI_KeyReleaseMask | ffi::XI_EnterMask | ffi::XI_LeaveMask | ffi::XI_FocusInMask From 6363ab0049f2165316c9d50ad2356dad67a6e9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Sun, 12 Jun 2022 10:13:24 +0200 Subject: [PATCH 48/58] Revert "fix: meta mod key on focus handling for gnome/x11" It's not clear if this change is working properly This reverts commit 333c5bc2675d956684731b75dc5fe35251f6b1cb. --- .../linux/x11/event_processor.rs | 93 ++++++++++--------- 1 file changed, 50 insertions(+), 43 deletions(-) diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 89d764f622..2995768372 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -842,6 +842,10 @@ impl EventProcessor { .focus(xev.event) .expect("Failed to focus input context"); + let modifiers = ModifiersState::from_x11(&xev.mods); + + self.device_mod_state.update_state(&modifiers, None); + if self.active_window != Some(xev.event) { self.active_window = Some(xev.event); @@ -855,16 +859,12 @@ impl EventProcessor { event: Focused(true), }); - // Issue key press events for all pressed keys - Self::handle_pressed_keys( - &wt, - window_id, - ElementState::Pressed, - &mut self.kb_state, - &self.mod_keymap, - &mut self.device_mod_state, - &mut callback, - ); + if !modifiers.is_empty() { + callback(Event::WindowEvent { + window_id, + event: WindowEvent::ModifiersChanged(modifiers), + }); + } // The deviceid for this event is for a keyboard instead of a pointer, // so we have to do a little extra work. @@ -880,7 +880,7 @@ impl EventProcessor { event: CursorMoved { device_id: mkdid(pointer_id), position, - modifiers: self.device_mod_state.modifiers(), + modifiers, }, }); @@ -896,7 +896,6 @@ impl EventProcessor { ); } } - ffi::XI_FocusOut => { let xev: &ffi::XIFocusOutEvent = unsafe { &*(xev.data as *const _) }; if !self.window_exists(xev.event) { @@ -924,6 +923,11 @@ impl EventProcessor { &mut callback, ); + callback(Event::WindowEvent { + window_id, + event: WindowEvent::ModifiersChanged(ModifiersState::empty()), + }); + callback(Event::WindowEvent { window_id, event: Focused(false), @@ -1068,27 +1072,6 @@ impl EventProcessor { let text_with_all_modifiers = ker.text_with_all_modifiers(); let repeat = xkev.flags & ffi::XIKeyRepeat == ffi::XIKeyRepeat; - if let Some(modifier) = - self.mod_keymap.get_modifier(keycode as ffi::KeyCode) - { - let old_modifiers = self.device_mod_state.modifiers(); - - self.device_mod_state.key_event( - state, - keycode as ffi::KeyCode, - modifier, - ); - - if old_modifiers != self.device_mod_state.modifiers() { - callback(Event::WindowEvent { - window_id, - event: WindowEvent::ModifiersChanged( - self.device_mod_state.modifiers(), - ), - }); - } - } - callback(Event::WindowEvent { window_id, event: WindowEvent::KeyboardInput { @@ -1164,6 +1147,14 @@ impl EventProcessor { return; } let physical_key = keymap::raw_keycode_to_keycode(keycode); + // TODO: Figure out how redundant this is. + // This is the set of modifiers end users end up seeing. However, the set of + // modifiers used internally by the `KbState` are sourced directly from the XKB + // extension. Since we currently panic when the extension doesn't load, we should + // be able to use the modifiers supplied to us by the XKB extension. This + // requires us to have consensus on what to do if we can't load and initialize + // libxkbcommon. + let modifiers = self.device_mod_state.modifiers(); callback(Event::DeviceEvent { device_id, @@ -1172,6 +1163,27 @@ impl EventProcessor { state, }), }); + + if let Some(modifier) = + self.mod_keymap.get_modifier(keycode as ffi::KeyCode) + { + self.device_mod_state.key_event( + state, + keycode as ffi::KeyCode, + modifier, + ); + + let new_modifiers = self.device_mod_state.modifiers(); + + if modifiers != new_modifiers { + if let Some(window_id) = self.active_window { + callback(Event::WindowEvent { + window_id: mkwid(window_id), + event: WindowEvent::ModifiersChanged(new_modifiers), + }); + } + } + } } ffi::XI_HierarchyChanged => { @@ -1354,16 +1366,11 @@ impl EventProcessor { let text_with_all_modifiers = ker.text_with_all_modifiers(); if let Some(modifier) = mod_keymap.get_modifier(keycode as ffi::KeyCode) { - let old_modifiers = device_mod_state.modifiers(); - - device_mod_state.key_event(state, keycode as ffi::KeyCode, modifier); - - if old_modifiers != device_mod_state.modifiers() { - callback(Event::WindowEvent { - window_id, - event: WindowEvent::ModifiersChanged(device_mod_state.modifiers()), - }); - } + device_mod_state.key_event( + ElementState::Pressed, + keycode as ffi::KeyCode, + modifier, + ); } callback(Event::WindowEvent { From 9dc461d3260fc83c0ae59dc367c7e30fbb9b743b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Mon, 13 Jun 2022 12:09:53 +0200 Subject: [PATCH 49/58] General clippy fixes and formatting --- src/platform_impl/linux/common/xkb_state.rs | 18 ++++++++++++--- .../linux/wayland/seat/keyboard/handlers.rs | 16 +++++++------- .../linux/wayland/seat/keyboard/mod.rs | 2 +- src/platform_impl/linux/x11/window.rs | 22 +++++++++---------- 4 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index f3aeedb79e..5117ef63e6 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -1,18 +1,22 @@ use std::convert::TryInto; use std::env; use std::ffi::CString; -use std::fs::File; use std::os::raw::c_char; use std::os::unix::ffi::OsStringExt; use std::ptr; use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Mutex; + +#[cfg(feature = "wayland")] +use std::fs::File; #[cfg(feature = "wayland")] use memmap2::MmapOptions; #[cfg(feature = "wayland")] pub use sctk::seat::keyboard::RMLVO; +#[cfg(feature = "x11")] +use std::sync::Mutex; + #[cfg(feature = "x11")] use once_cell::sync::Lazy; #[cfg(feature = "x11")] @@ -52,6 +56,7 @@ pub(crate) struct KbState { xkb_compose_state: *mut ffi::xkb_compose_state, xkb_compose_state_2: *mut ffi::xkb_compose_state, mods_state: ModifiersState, + #[cfg(feature = "wayland")] locked: bool, scratch_buffer: Vec, } @@ -132,6 +137,7 @@ impl ModifiersState { } impl KbState { + #[cfg(feature = "wayland")] pub(crate) fn update_modifiers( &mut self, mods_depressed: u32, @@ -294,6 +300,7 @@ impl KbState { xkb_compose_state: ptr::null_mut(), xkb_compose_state_2: ptr::null_mut(), mods_state: ModifiersState::new(), + #[cfg(feature = "wayland")] locked: false, scratch_buffer: Vec::new(), }; @@ -493,6 +500,7 @@ impl KbState { } impl KbState { + #[cfg(feature = "wayland")] pub(crate) unsafe fn key_repeats(&mut self, keycode: ffi::xkb_keycode_t) -> bool { (XKBH.xkb_keymap_key_repeats)(self.xkb_keymap, keycode) == 1 } @@ -503,11 +511,13 @@ impl KbState { } #[inline] + #[cfg(feature = "wayland")] pub(crate) fn locked(&self) -> bool { self.locked } #[inline] + #[cfg(feature = "wayland")] pub(crate) fn mods_state(&self) -> ModifiersState { self.mods_state } @@ -544,6 +554,7 @@ pub enum Error { /// libxkbcommon is not available XKBNotFound, /// Provided RMLVO specified a keymap that would not be loaded + #[cfg(feature = "wayland")] BadNames, } @@ -552,6 +563,7 @@ impl KbState { KeyEventResults::new(self, keycode, state == ElementState::Pressed) } + #[cfg(feature = "wayland")] pub fn process_key_repeat_event(&mut self, keycode: u32) -> KeyEventResults<'_> { KeyEventResults::new(self, keycode, false) } @@ -652,7 +664,7 @@ impl<'a> KeyEventResults<'a> { Key::Dead( self.state .compose_get_utf8_2() - .map(|s| s.chars().nth(0).unwrap()), + .map(|s| s.chars().next().unwrap()), ), location, ), diff --git a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs index 232cac4be2..85cd1588e1 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/handlers.rs @@ -187,7 +187,7 @@ pub enum Error { /// The provided seat does not have the keyboard capability NoKeyboard, /// Failed to init timers for repetition - TimerError(std::io::Error), + Timer(std::io::Error), } impl From for Error { @@ -304,7 +304,7 @@ where let current_repeat = Rc::new(RefCell::new(None)); let source = RepeatSource { - timer: calloop::timer::Timer::new().map_err(Error::TimerError)?, + timer: calloop::timer::Timer::new().map_err(Error::Timer)?, state: state.clone(), current_repeat: current_repeat.clone(), }; @@ -325,13 +325,13 @@ where let source = loop_handle .insert_source(source, move |event, kbd, ddata| { - (&mut *callback.borrow_mut())( + (callback.borrow_mut())( event, kbd.clone(), wayland_client::DispatchData::wrap(ddata), ) }) - .map_err(|e| Error::TimerError(e.error))?; + .map_err(|e| Error::Timer(e.error))?; keyboard.quick_assign(move |keyboard, event, data| { kbd_handler.event(keyboard.detach(), event, data) @@ -495,7 +495,7 @@ impl KbdHandler { .map(|c| u32::from_ne_bytes(c.try_into().unwrap())) .collect::>(); let keys: Vec = rawkeys.iter().map(|k| state.get_one_sym_raw(*k)).collect(); - (&mut *self.callback.borrow_mut())( + (self.callback.borrow_mut())( Event::Enter { serial, surface, @@ -519,7 +519,7 @@ impl KbdHandler { repeat.stop_all_repeat(); } } - (&mut *self.callback.borrow_mut())(Event::Leave { serial, surface }, object, dispatch_data); + (self.callback.borrow_mut())(Event::Leave { serial, surface }, object, dispatch_data); } fn key( @@ -582,7 +582,7 @@ impl KbdHandler { } } - (&mut *self.callback.borrow_mut())( + (self.callback.borrow_mut())( Event::Key { serial, time, @@ -611,7 +611,7 @@ impl KbdHandler { { let mut state = self.state.borrow_mut(); state.update_modifiers(mods_depressed, mods_latched, mods_locked, 0, 0, group); - (&mut *self.callback.borrow_mut())( + (self.callback.borrow_mut())( Event::Modifiers { modifiers: state.mods_state(), }, diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index c5d9ef6c0b..a0b4b6c9e0 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -34,7 +34,7 @@ impl Keyboard { let mut inner = KeyboardInner::new(modifiers_state); let keyboard_data = handlers::map_keyboard_repeat( loop_handle.clone(), - &seat, + seat, None, handlers::RepeatKind::System, move |event, _, mut dispatch_data| { diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 0a5a79f2f8..606172f859 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -437,17 +437,17 @@ impl UnownedWindow { // Select XInput2 events let mask = ffi::XI_MotionMask - | ffi::XI_ButtonPressMask - | ffi::XI_ButtonReleaseMask - | ffi::XI_KeyPressMask - | ffi::XI_KeyReleaseMask - | ffi::XI_EnterMask - | ffi::XI_LeaveMask - | ffi::XI_FocusInMask - | ffi::XI_FocusOutMask - | ffi::XI_TouchBeginMask - | ffi::XI_TouchUpdateMask - | ffi::XI_TouchEndMask; + | ffi::XI_ButtonPressMask + | ffi::XI_ButtonReleaseMask + | ffi::XI_KeyPressMask + | ffi::XI_KeyReleaseMask + | ffi::XI_EnterMask + | ffi::XI_LeaveMask + | ffi::XI_FocusInMask + | ffi::XI_FocusOutMask + | ffi::XI_TouchBeginMask + | ffi::XI_TouchUpdateMask + | ffi::XI_TouchEndMask; xconn .select_xinput_events(window.xwindow, ffi::XIAllMasterDevices, mask) .queue(); From f012932addf95851ec1a9567b66fe879d69524f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Mon, 13 Jun 2022 12:18:24 +0200 Subject: [PATCH 50/58] Improve libxkbcommon string handling --- src/platform_impl/linux/common/xkb_state.rs | 64 +++++++++------------ 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 5117ef63e6..980e6f3f80 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -178,27 +178,10 @@ impl KbState { if !self.ready() { return None; } - let size = - unsafe { (XKBH.xkb_state_key_get_utf8)(self.xkb_state, keycode, ptr::null_mut(), 0) } - + 1; - if size <= 1 { - return None; - }; - self.scratch_buffer.clear(); - let size = size.try_into().unwrap(); - self.scratch_buffer.reserve(size); - unsafe { - self.scratch_buffer.set_len(size); - (XKBH.xkb_state_key_get_utf8)( - self.xkb_state, - keycode, - self.scratch_buffer.as_mut_ptr() as *mut _, - size, - ); - }; - // remove the final `\0` - self.scratch_buffer.pop(); - Some(byte_slice_to_cached_string(&self.scratch_buffer)) + let xkb_state = self.xkb_state; + self._get_utf8({ + |ptr, len| unsafe { (XKBH.xkb_state_key_get_utf8)(xkb_state, keycode, ptr, len) } + }) } fn compose_feed_normal(&mut self, keysym: u32) -> Option { @@ -257,25 +240,34 @@ impl KbState { if !self.ready() || xkb_compose_state.is_null() { return None; } - let size = - unsafe { (XKBCH.xkb_compose_state_get_utf8)(xkb_compose_state, ptr::null_mut(), 0) } - + 1; - if size <= 1 { + self._get_utf8(|ptr, len| unsafe { + (XKBCH.xkb_compose_state_get_utf8)(xkb_compose_state, ptr, len) + }) + } + + fn _get_utf8(&mut self, mut f: F) -> Option<&'static str> + where + F: FnMut(*mut i8, usize) -> i32, + { + let size = f(ptr::null_mut(), 0); + if size == 0 { return None; - }; + } + let size = usize::try_from(size).unwrap(); self.scratch_buffer.clear(); - let size = size.try_into().unwrap(); - self.scratch_buffer.reserve(size); + // The allocated buffer must include space for the null-terminator + self.scratch_buffer.reserve(size + 1); unsafe { - self.scratch_buffer.set_len(size); - (XKBCH.xkb_compose_state_get_utf8)( - xkb_compose_state, - self.scratch_buffer.as_mut_ptr() as *mut _, - size as usize, + let written = f( + self.scratch_buffer.as_mut_ptr().cast(), + self.scratch_buffer.capacity(), ); + if usize::try_from(written).unwrap() != size { + // This will likely never happen + return None; + } + self.scratch_buffer.set_len(size); }; - // remove the final `\0` - self.scratch_buffer.pop(); Some(byte_slice_to_cached_string(&self.scratch_buffer)) } @@ -592,7 +584,7 @@ impl KbState { } } - // remove the final `\0` + // Remove the null-terminator self.scratch_buffer.pop(); Some(byte_slice_to_cached_string(&self.scratch_buffer)) } From 21508a18497702e144bc5df71128f89587d09566 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 12 Jun 2022 09:53:28 +0300 Subject: [PATCH 51/58] Add `WindowBuilder::transparent` This is required to help hardware accelerated libraries like glutin that accept WindowBuilder instead of RawWindowHandle, since the api to access builder properties directly was removed. Follow up to 44288f6. --- CHANGELOG.md | 1 + src/window.rs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d103cdb8e..d98478e907 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ And please only add new entries to the top of this list, right below the `# Unre - Build docs on `docs.rs` for iOS and Android as well. - **Breaking:** Removed the `WindowAttributes` struct, since all its functionality is accessible from `WindowBuilder`. +- Added `WindowBuilder::transparent` getter to check if the user set `transparent` attribute. - On macOS, Fix emitting `Event::LoopDestroyed` on CMD+Q. - On macOS, fixed an issue where having multiple windows would prevent run_return from ever returning. - On Wayland, fix bug where the cursor wouldn't hide in GNOME. diff --git a/src/window.rs b/src/window.rs index e689eaf2e6..f522dc236a 100644 --- a/src/window.rs +++ b/src/window.rs @@ -296,6 +296,12 @@ impl WindowBuilder { self } + /// Get whether the window will support transparency. + #[inline] + pub fn transparent(&self) -> bool { + self.window.transparent + } + /// Sets whether the window should have a border, a title bar, etc. /// /// The default is `true`. From 246dd5197f9ea3aa74645c6d7d1d8e72ab2bc8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Mon, 13 Jun 2022 18:24:56 +0200 Subject: [PATCH 52/58] Fix doubled device events on X11 Fixes #2332 --- src/platform_impl/linux/x11/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 676f612ce6..92e30f73c9 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -560,7 +560,7 @@ impl EventLoopWindowTarget { } self.xconn - .select_xinput_events(self.root, ffi::XIAllDevices, mask) + .select_xinput_events(self.root, ffi::XIAllMasterDevices, mask) .queue(); } } From da1652ee0ba04904d078b6784f2754f2cf2b02c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Wed, 15 Jun 2022 03:47:07 +0200 Subject: [PATCH 53/58] Don't reload the keymap on every keypress Turns out I was an idiot when initially working on this. Don't listen to XkbMapNotify This event appears to be subsumed by XkbNewKeyboardNotify when we start listening to XkbNewKeyboardNotify, although the documentation feels a little unclear on the matter. --- src/platform_impl/linux/common/xkb_state.rs | 15 +++-- .../linux/x11/event_processor.rs | 65 ++++++++----------- src/platform_impl/linux/x11/mod.rs | 31 +++++++++ 3 files changed, 69 insertions(+), 42 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 980e6f3f80..5e4a10054e 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -58,6 +58,8 @@ pub(crate) struct KbState { mods_state: ModifiersState, #[cfg(feature = "wayland")] locked: bool, + #[cfg(feature = "x11")] + pub(crate) core_keyboard_id: i32, scratch_buffer: Vec, } @@ -294,6 +296,8 @@ impl KbState { mods_state: ModifiersState::new(), #[cfg(feature = "wayland")] locked: false, + #[cfg(feature = "x11")] + core_keyboard_id: 0, scratch_buffer: Vec::new(), }; @@ -428,17 +432,20 @@ impl KbState { } // TODO: Support keyboards other than the "virtual core keyboard device". - let core_keyboard_id = (XKBXH.xkb_x11_get_core_keyboard_device_id)(self.xcb_connection); + self.core_keyboard_id = (XKBXH.xkb_x11_get_core_keyboard_device_id)(self.xcb_connection); let keymap = (XKBXH.xkb_x11_keymap_new_from_device)( self.xkb_context, self.xcb_connection, - core_keyboard_id, + self.core_keyboard_id, xkbcommon_dl::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS, ); assert_ne!(keymap, ptr::null_mut()); - let state = - (XKBXH.xkb_x11_state_new_from_device)(keymap, self.xcb_connection, core_keyboard_id); + let state = (XKBXH.xkb_x11_state_new_from_device)( + keymap, + self.xcb_connection, + self.core_keyboard_id, + ); self.post_init(state, keymap); } diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 2995768372..6dc9f11993 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -35,6 +35,7 @@ pub(super) struct EventProcessor { pub(super) randr_event_offset: c_int, pub(super) devices: RefCell>, pub(super) xi2ext: XExtension, + pub(super) xkbext: XExtension, pub(super) target: Rc>, pub(super) kb_state: KbState, pub(super) mod_keymap: ModifierKeymap, @@ -1095,44 +1096,6 @@ impl EventProcessor { } ffi::XI_RawKeyPress | ffi::XI_RawKeyRelease => { - // This is horrible, but I couldn't manage to respect keyboard layout changes - // in any other way. In fact, getting this to work at all proved so frustrating - // that I (@maroider) lost motivation to work on the keyboard event rework for - // some months. Thankfully, @ArturKovacs offered to help debug the problem - // over discord, and the following is the result of that debugging session. - // - // Without the XKB extension, the X.Org server sends us the `MappingNotify` - // event when there's been a change in the keyboard layout. This stops - // being the case when we select ourselves some XKB events with `XkbSelectEvents` - // and the "core keyboard device (0x100)" (we haven't tried with any other - // devices). We managed to reproduce this on both our machines. - // - // With the XKB extension active, it would seem like we're supposed to use the - // `XkbStateNotify` event to detect keyboard layout changes, but the `group` - // never changes value (it is always `0`). This worked for @ArturKovacs, but - // not for me. We also tried to use the `group` given to us in keypress events, - // but it remained constant there, too. - // - // We also tried to see if there was some other event that got fired when the - // keyboard layout changed, and we found a mysterious event with the value - // `85` (`0x55`). We couldn't find any reference to it in the X11 headers or - // in the X.Org server source. - // - // `KeymapNotify` did briefly look interesting based purely on the name, but - // it is only useful for checking what keys are pressed when we receive the - // event. - // - // So instead of any vaguely reasonable approach, we get this: reloading the - // keymap on *every* keypress. That's peak efficiency right there! - // - // FIXME: Someone please save our souls! Or at least our wasted CPU cycles. - // - // If you do manage to find a solution, remember to re-enable (and handle) the - // `XkbStateNotify` event with `XkbSelectEventDetails` with a mask of - // `XkbAllStateComponentsMask & !XkbPointerButtonMask` like in - // . - unsafe { self.kb_state.init_with_x11_keymap() }; - let xev: &ffi::XIRawEvent = unsafe { &*(xev.data as *const _) }; let state = match xev.evtype { @@ -1213,6 +1176,32 @@ impl EventProcessor { } } _ => { + if event_type == self.xkbext.first_event_id { + let xev = unsafe { &*(xev as *const _ as *const ffi::XkbAnyEvent) }; + #[allow(clippy::single_match)] + match xev.xkb_type { + ffi::XkbNewKeyboardNotify => { + let xev = unsafe { + &*(xev as *const _ as *const ffi::XkbNewKeyboardNotifyEvent) + }; + let keycodes_changed_flag = 0x1; + let geometry_changed_flag = 0x1 << 1; + + // TODO: What do we do about the "geometry changed" case? + let keycodes_changed = + util::has_flag(xev.changed, keycodes_changed_flag); + let geometry_changed = + util::has_flag(xev.changed, geometry_changed_flag); + + if xev.device == self.kb_state.core_keyboard_id + && (keycodes_changed || geometry_changed) + { + unsafe { self.kb_state.init_with_x11_keymap() }; + } + } + _ => {} + } + } if event_type == self.randr_event_offset { // In the future, it would be quite easy to emit monitor hotplug events. let prev_list = monitor::invalidate_cached_monitor_list(); diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 92e30f73c9..c22340fd7e 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -202,6 +202,27 @@ impl EventLoop { ext }; + let xkbext = { + let mut ext = XExtension::default(); + + let res = unsafe { + (xconn.xlib.XkbQueryExtension)( + xconn.display, + &mut ext.opcode, + &mut ext.first_event_id, + &mut ext.first_error_id, + &mut 1, + &mut 0, + ) + }; + + if res == ffi::False { + panic!("X server missing XKB extension"); + } + + ext + }; + unsafe { let mut xinput_major_ver = ffi::XI_2_Major; let mut xinput_minor_ver = ffi::XI_2_Minor; @@ -269,6 +290,7 @@ impl EventLoop { ime_receiver, ime_event_receiver, xi2ext, + xkbext, kb_state, mod_keymap, device_mod_state: Default::default(), @@ -285,6 +307,15 @@ impl EventLoop { .select_xinput_events(root, ffi::XIAllDevices, ffi::XI_HierarchyChangedMask) .queue(); + get_xtarget(&target) + .xconn + .select_xkb_events( + 0x100, // Use the "core keyboard device" + ffi::XkbNewKeyboardNotifyMask, + ) + .unwrap() + .queue(); + event_processor.init_device(ffi::XIAllDevices); EventLoop { From 0d5ae7ca4792493975d2c785be26fc403a4300f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 7 Jul 2022 09:32:23 +0200 Subject: [PATCH 54/58] Use XkbStateNotify to track the active set of modifiers This commit retains the old code-path for doing this tracking in order to test for regressions introduced by this change. It appears that we manage to avoid any visible regressions due to having already removed the long since deprecated `modifiers` field from keyboard events, which hides the fact that using XkbStateNotify makes ModifiersChanged events arrive _after_ the WindowEvent for the keypress instead of between the DeviceEvent and the WindowEvent. --- src/platform_impl/linux/common/xkb_state.rs | 15 ++- .../linux/wayland/seat/keyboard/mod.rs | 12 --- .../linux/x11/event_processor.rs | 94 +++++++++---------- src/platform_impl/linux/x11/mod.rs | 3 +- 4 files changed, 61 insertions(+), 63 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 5e4a10054e..49ac66df69 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -69,7 +69,7 @@ pub(crate) struct KbState { /// /// For some modifiers, this means that the key is currently pressed, others are toggled /// (like caps lock). -#[derive(Copy, Clone, Debug, Default)] +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub struct ModifiersState { /// The "control" key pub ctrl: bool, @@ -138,8 +138,18 @@ impl ModifiersState { } } +impl From for crate::keyboard::ModifiersState { + fn from(mods: ModifiersState) -> crate::keyboard::ModifiersState { + let mut to_mods = crate::keyboard::ModifiersState::empty(); + to_mods.set(crate::keyboard::ModifiersState::SHIFT, mods.shift); + to_mods.set(crate::keyboard::ModifiersState::CONTROL, mods.ctrl); + to_mods.set(crate::keyboard::ModifiersState::ALT, mods.alt); + to_mods.set(crate::keyboard::ModifiersState::SUPER, mods.logo); + to_mods + } +} + impl KbState { - #[cfg(feature = "wayland")] pub(crate) fn update_modifiers( &mut self, mods_depressed: u32, @@ -516,7 +526,6 @@ impl KbState { } #[inline] - #[cfg(feature = "wayland")] pub(crate) fn mods_state(&self) -> ModifiersState { self.mods_state } diff --git a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs index a0b4b6c9e0..6f5ce4fccf 100644 --- a/src/platform_impl/linux/wayland/seat/keyboard/mod.rs +++ b/src/platform_impl/linux/wayland/seat/keyboard/mod.rs @@ -9,7 +9,6 @@ use sctk::reexports::client::protocol::wl_seat::WlSeat; use sctk::reexports::client::Attached; use crate::keyboard::ModifiersState; -use crate::platform_impl::platform::common::xkb_state; use crate::platform_impl::wayland::event_loop::WinitState; use crate::platform_impl::wayland::WindowId; @@ -89,14 +88,3 @@ impl KeyboardInner { } } } - -impl From for ModifiersState { - fn from(mods: xkb_state::ModifiersState) -> ModifiersState { - let mut wl_mods = ModifiersState::empty(); - wl_mods.set(ModifiersState::SHIFT, mods.shift); - wl_mods.set(ModifiersState::CONTROL, mods.ctrl); - wl_mods.set(ModifiersState::ALT, mods.alt); - wl_mods.set(ModifiersState::SUPER, mods.logo); - wl_mods - } -} diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 6dc9f11993..b5f3f6b9b4 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -40,6 +40,7 @@ pub(super) struct EventProcessor { pub(super) kb_state: KbState, pub(super) mod_keymap: ModifierKeymap, pub(super) device_mod_state: ModifierKeyState, + pub(super) pending_mod_change: Option, // Number of touch events currently in progress pub(super) num_touch: u32, pub(super) first_touch: Option, @@ -141,25 +142,14 @@ impl EventProcessor { return; } - // We can't call a `&mut self` method because of the above borrow, - // so we use this macro for repeated modifier state updates. - macro_rules! update_modifiers { - ( $state:expr , $modifier:expr ) => {{ - match ($state, $modifier) { - (state, modifier) => { - if let Some(modifiers) = - self.device_mod_state.update_state(&state, modifier) - { - if let Some(window_id) = self.active_window { - callback(Event::WindowEvent { - window_id: mkwid(window_id), - event: WindowEvent::ModifiersChanged(modifiers), - }); - } - } - } + macro_rules! assert_mods_eq { + ($old:expr, $new:expr) => { + if $old != $new { + println!("New modifier tracking differed from the old one."); + println!("Old: {:?}", $old); + println!("New: {:?}", $new); } - }}; + } } let event_type = xev.get_type(); @@ -604,8 +594,9 @@ impl EventProcessor { return; } - let modifiers = ModifiersState::from_x11(&xev.mods); - update_modifiers!(modifiers, None); + let old_modifiers = ModifiersState::from_x11(&xev.mods); + let modifiers = self.kb_state.mods_state().into(); + assert_mods_eq!(old_modifiers, modifiers); let state = if xev.evtype == ffi::XI_ButtonPress { Pressed @@ -681,8 +672,9 @@ impl EventProcessor { let window_id = mkwid(xev.event); let new_cursor_pos = (xev.event_x, xev.event_y); - let modifiers = ModifiersState::from_x11(&xev.mods); - update_modifiers!(modifiers, None); + let old_modifiers = ModifiersState::from_x11(&xev.mods); + let modifiers = self.kb_state.mods_state().into(); + assert_mods_eq!(old_modifiers, modifiers); let cursor_moved = self.with_window(xev.event, |window| { let mut shared_state_lock = window.shared_state.lock(); @@ -843,9 +835,10 @@ impl EventProcessor { .focus(xev.event) .expect("Failed to focus input context"); - let modifiers = ModifiersState::from_x11(&xev.mods); - - self.device_mod_state.update_state(&modifiers, None); + let old_modifiers = ModifiersState::from_x11(&xev.mods); + self.device_mod_state.update_state(&old_modifiers, None); + let modifiers = self.kb_state.mods_state().into(); + assert_mods_eq!(old_modifiers, modifiers); if self.active_window != Some(xev.event) { self.active_window = Some(xev.event); @@ -860,7 +853,7 @@ impl EventProcessor { event: Focused(true), }); - if !modifiers.is_empty() { + if let Some(modifiers) = self.pending_mod_change.take() { callback(Event::WindowEvent { window_id, event: WindowEvent::ModifiersChanged(modifiers), @@ -947,7 +940,9 @@ impl EventProcessor { }; if self.window_exists(xev.event) { let id = xev.detail as u64; - let modifiers = self.device_mod_state.modifiers(); + let old_modifiers = ModifiersState::from_x11(&xev.mods); + let modifiers = self.kb_state.mods_state().into(); + assert_mods_eq!(old_modifiers, modifiers); let location = PhysicalPosition::new(xev.event_x as f64, xev.event_y as f64); @@ -1110,14 +1105,6 @@ impl EventProcessor { return; } let physical_key = keymap::raw_keycode_to_keycode(keycode); - // TODO: Figure out how redundant this is. - // This is the set of modifiers end users end up seeing. However, the set of - // modifiers used internally by the `KbState` are sourced directly from the XKB - // extension. Since we currently panic when the extension doesn't load, we should - // be able to use the modifiers supplied to us by the XKB extension. This - // requires us to have consensus on what to do if we can't load and initialize - // libxkbcommon. - let modifiers = self.device_mod_state.modifiers(); callback(Event::DeviceEvent { device_id, @@ -1135,17 +1122,6 @@ impl EventProcessor { keycode as ffi::KeyCode, modifier, ); - - let new_modifiers = self.device_mod_state.modifiers(); - - if modifiers != new_modifiers { - if let Some(window_id) = self.active_window { - callback(Event::WindowEvent { - window_id: mkwid(window_id), - event: WindowEvent::ModifiersChanged(new_modifiers), - }); - } - } } } @@ -1178,7 +1154,6 @@ impl EventProcessor { _ => { if event_type == self.xkbext.first_event_id { let xev = unsafe { &*(xev as *const _ as *const ffi::XkbAnyEvent) }; - #[allow(clippy::single_match)] match xev.xkb_type { ffi::XkbNewKeyboardNotify => { let xev = unsafe { @@ -1199,6 +1174,31 @@ impl EventProcessor { unsafe { self.kb_state.init_with_x11_keymap() }; } } + ffi::XkbStateNotify => { + let xev = + unsafe { &*(xev as *const _ as *const ffi::XkbStateNotifyEvent) }; + + let prev_mods = self.kb_state.mods_state(); + self.kb_state.update_modifiers( + xev.base_mods, + xev.latched_mods, + xev.locked_mods, + xev.base_group as u32, + xev.latched_group as u32, + xev.locked_group as u32, + ); + let new_mods = self.kb_state.mods_state(); + if prev_mods != new_mods { + if let Some(window) = self.active_window { + callback(Event::WindowEvent { + window_id: mkwid(window), + event: WindowEvent::ModifiersChanged(new_mods.into()), + }); + } else { + self.pending_mod_change = Some(new_mods.into()); + } + } + } _ => {} } } diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index c22340fd7e..7c3c2d876b 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -294,6 +294,7 @@ impl EventLoop { kb_state, mod_keymap, device_mod_state: Default::default(), + pending_mod_change: Default::default(), num_touch: 0, first_touch: None, active_window: None, @@ -311,7 +312,7 @@ impl EventLoop { .xconn .select_xkb_events( 0x100, // Use the "core keyboard device" - ffi::XkbNewKeyboardNotifyMask, + ffi::XkbNewKeyboardNotifyMask | ffi::XkbStateNotifyMask, ) .unwrap() .queue(); From 6c7820eb2d72e55bbf8136ecb351a2459c0a9365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 7 Jul 2022 09:40:59 +0200 Subject: [PATCH 55/58] Rip out the old code-path for modifier state tracking on X11 --- .../linux/x11/event_processor.rs | 47 ----- src/platform_impl/linux/x11/mod.rs | 6 - src/platform_impl/linux/x11/util/mod.rs | 1 - src/platform_impl/linux/x11/util/modifiers.rs | 190 ------------------ 4 files changed, 244 deletions(-) delete mode 100644 src/platform_impl/linux/x11/util/modifiers.rs diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index b5f3f6b9b4..20feeef5c3 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -9,8 +9,6 @@ use super::{ GenericEventCookie, ImeReceiver, ScrollOrientation, UnownedWindow, WindowId, XExtension, }; -use util::modifiers::{ModifierKeyState, ModifierKeymap}; - use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest}; use crate::{ dpi::{PhysicalPosition, PhysicalSize}, @@ -38,8 +36,6 @@ pub(super) struct EventProcessor { pub(super) xkbext: XExtension, pub(super) target: Rc>, pub(super) kb_state: KbState, - pub(super) mod_keymap: ModifierKeymap, - pub(super) device_mod_state: ModifierKeyState, pub(super) pending_mod_change: Option, // Number of touch events currently in progress pub(super) num_touch: u32, @@ -142,16 +138,6 @@ impl EventProcessor { return; } - macro_rules! assert_mods_eq { - ($old:expr, $new:expr) => { - if $old != $new { - println!("New modifier tracking differed from the old one."); - println!("Old: {:?}", $old); - println!("New: {:?}", $new); - } - } - } - let event_type = xev.get_type(); match event_type { ffi::ClientMessage => { @@ -594,9 +580,7 @@ impl EventProcessor { return; } - let old_modifiers = ModifiersState::from_x11(&xev.mods); let modifiers = self.kb_state.mods_state().into(); - assert_mods_eq!(old_modifiers, modifiers); let state = if xev.evtype == ffi::XI_ButtonPress { Pressed @@ -672,9 +656,7 @@ impl EventProcessor { let window_id = mkwid(xev.event); let new_cursor_pos = (xev.event_x, xev.event_y); - let old_modifiers = ModifiersState::from_x11(&xev.mods); let modifiers = self.kb_state.mods_state().into(); - assert_mods_eq!(old_modifiers, modifiers); let cursor_moved = self.with_window(xev.event, |window| { let mut shared_state_lock = window.shared_state.lock(); @@ -835,10 +817,7 @@ impl EventProcessor { .focus(xev.event) .expect("Failed to focus input context"); - let old_modifiers = ModifiersState::from_x11(&xev.mods); - self.device_mod_state.update_state(&old_modifiers, None); let modifiers = self.kb_state.mods_state().into(); - assert_mods_eq!(old_modifiers, modifiers); if self.active_window != Some(xev.event) { self.active_window = Some(xev.event); @@ -884,8 +863,6 @@ impl EventProcessor { window_id, ElementState::Pressed, &mut self.kb_state, - &self.mod_keymap, - &mut self.device_mod_state, &mut callback, ); } @@ -912,8 +889,6 @@ impl EventProcessor { window_id, ElementState::Released, &mut self.kb_state, - &self.mod_keymap, - &mut self.device_mod_state, &mut callback, ); @@ -940,9 +915,7 @@ impl EventProcessor { }; if self.window_exists(xev.event) { let id = xev.detail as u64; - let old_modifiers = ModifiersState::from_x11(&xev.mods); let modifiers = self.kb_state.mods_state().into(); - assert_mods_eq!(old_modifiers, modifiers); let location = PhysicalPosition::new(xev.event_x as f64, xev.event_y as f64); @@ -1113,16 +1086,6 @@ impl EventProcessor { state, }), }); - - if let Some(modifier) = - self.mod_keymap.get_modifier(keycode as ffi::KeyCode) - { - self.device_mod_state.key_event( - state, - keycode as ffi::KeyCode, - modifier, - ); - } } ffi::XI_HierarchyChanged => { @@ -1330,8 +1293,6 @@ impl EventProcessor { window_id: crate::window::WindowId, state: ElementState, kb_state: &mut KbState, - mod_keymap: &ModifierKeymap, - device_mod_state: &mut ModifierKeyState, callback: &mut F, ) where F: FnMut(Event<'_, T>), @@ -1354,14 +1315,6 @@ impl EventProcessor { let (key_without_modifiers, _) = ker.key_without_modifiers(); let text_with_all_modifiers = ker.text_with_all_modifiers(); - if let Some(modifier) = mod_keymap.get_modifier(keycode as ffi::KeyCode) { - device_mod_state.key_event( - ElementState::Pressed, - keycode as ffi::KeyCode, - modifier, - ); - } - callback(Event::WindowEvent { window_id, event: WindowEvent::KeyboardInput { diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 7c3c2d876b..1317b101f0 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -44,7 +44,6 @@ use self::{ dnd::{Dnd, DndState}, event_processor::EventProcessor, ime::{Ime, ImeCreationError, ImeReceiver, ImeRequest, ImeSender}, - util::modifiers::ModifierKeymap, }; use super::common::xkb_state::KbState; use crate::{ @@ -241,9 +240,6 @@ impl EventLoop { xconn.update_cached_wm_info(root); - let mut mod_keymap = ModifierKeymap::new(); - mod_keymap.reset_from_x_connection(&xconn); - let poll = Poll::new().unwrap(); let waker = Arc::new(Waker::new(poll.registry(), USER_REDRAW_TOKEN).unwrap()); @@ -292,8 +288,6 @@ impl EventLoop { xi2ext, xkbext, kb_state, - mod_keymap, - device_mod_state: Default::default(), pending_mod_change: Default::default(), num_touch: 0, first_touch: None, diff --git a/src/platform_impl/linux/x11/util/mod.rs b/src/platform_impl/linux/x11/util/mod.rs index df3d89138a..0eed788e5f 100644 --- a/src/platform_impl/linux/x11/util/mod.rs +++ b/src/platform_impl/linux/x11/util/mod.rs @@ -11,7 +11,6 @@ mod icon; mod input; pub mod keys; mod memory; -pub mod modifiers; mod randr; mod window_property; mod wm; diff --git a/src/platform_impl/linux/x11/util/modifiers.rs b/src/platform_impl/linux/x11/util/modifiers.rs deleted file mode 100644 index 31db220263..0000000000 --- a/src/platform_impl/linux/x11/util/modifiers.rs +++ /dev/null @@ -1,190 +0,0 @@ -use std::{collections::HashMap, slice}; - -use super::*; - -use crate::event::ElementState; -use crate::keyboard::ModifiersState; - -// Offsets within XModifierKeymap to each set of keycodes. -// We are only interested in Shift, Control, Alt, and Logo. -// -// There are 8 sets total. The order of keycode sets is: -// Shift, Lock, Control, Mod1 (Alt), Mod2, Mod3, Mod4 (Logo), Mod5 -// -// https://tronche.com/gui/x/xlib/input/XSetModifierMapping.html -const SHIFT_OFFSET: usize = 0; -const CONTROL_OFFSET: usize = 2; -const ALT_OFFSET: usize = 3; -const LOGO_OFFSET: usize = 6; -const NUM_MODS: usize = 8; - -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum Modifier { - Alt, - Ctrl, - Shift, - Logo, -} - -#[derive(Debug, Default)] -pub struct ModifierKeymap { - // Maps keycodes to modifiers - keys: HashMap, -} - -#[derive(Clone, Debug, Default)] -pub struct ModifierKeyState { - // Contains currently pressed modifier keys and their corresponding modifiers - keys: HashMap, - state: ModifiersState, -} - -impl ModifierKeymap { - pub fn new() -> ModifierKeymap { - ModifierKeymap::default() - } - - pub fn get_modifier(&self, keycode: ffi::KeyCode) -> Option { - self.keys.get(&keycode).cloned() - } - - pub fn reset_from_x_connection(&mut self, xconn: &XConnection) { - unsafe { - let keymap = (xconn.xlib.XGetModifierMapping)(xconn.display); - - if keymap.is_null() { - panic!("failed to allocate XModifierKeymap"); - } - - self.reset_from_x_keymap(&*keymap); - - (xconn.xlib.XFreeModifiermap)(keymap); - } - } - - pub fn reset_from_x_keymap(&mut self, keymap: &ffi::XModifierKeymap) { - let keys_per_mod = keymap.max_keypermod as usize; - - let keys = unsafe { - slice::from_raw_parts(keymap.modifiermap as *const _, keys_per_mod * NUM_MODS) - }; - - self.keys.clear(); - - self.read_x_keys(keys, SHIFT_OFFSET, keys_per_mod, Modifier::Shift); - self.read_x_keys(keys, CONTROL_OFFSET, keys_per_mod, Modifier::Ctrl); - self.read_x_keys(keys, ALT_OFFSET, keys_per_mod, Modifier::Alt); - self.read_x_keys(keys, LOGO_OFFSET, keys_per_mod, Modifier::Logo); - } - - fn read_x_keys( - &mut self, - keys: &[ffi::KeyCode], - offset: usize, - keys_per_mod: usize, - modifier: Modifier, - ) { - let start = offset * keys_per_mod; - let end = start + keys_per_mod; - - for &keycode in &keys[start..end] { - if keycode != 0 { - self.keys.insert(keycode, modifier); - } - } - } -} - -impl ModifierKeyState { - pub fn update_keymap(&mut self, mods: &ModifierKeymap) { - self.keys.retain(|k, v| { - if let Some(m) = mods.get_modifier(*k) { - *v = m; - true - } else { - false - } - }); - - self.reset_state(); - } - - pub fn update_state( - &mut self, - state: &ModifiersState, - except: Option, - ) -> Option { - let mut new_state = *state; - - match except { - Some(Modifier::Alt) => new_state.set(ModifiersState::ALT, self.state.alt_key()), - Some(Modifier::Ctrl) => { - new_state.set(ModifiersState::CONTROL, self.state.control_key()) - } - Some(Modifier::Shift) => new_state.set(ModifiersState::SHIFT, self.state.shift_key()), - Some(Modifier::Logo) => new_state.set(ModifiersState::SUPER, self.state.super_key()), - None => (), - } - - if self.state == new_state { - None - } else { - self.keys.retain(|_k, v| get_modifier(&new_state, *v)); - self.state = new_state; - Some(new_state) - } - } - - pub fn modifiers(&self) -> ModifiersState { - self.state - } - - pub fn key_event(&mut self, state: ElementState, keycode: ffi::KeyCode, modifier: Modifier) { - match state { - ElementState::Pressed => self.key_press(keycode, modifier), - ElementState::Released => self.key_release(keycode), - } - } - - pub fn key_press(&mut self, keycode: ffi::KeyCode, modifier: Modifier) { - self.keys.insert(keycode, modifier); - - set_modifier(&mut self.state, modifier, true); - } - - pub fn key_release(&mut self, keycode: ffi::KeyCode) { - if let Some(modifier) = self.keys.remove(&keycode) { - if !self.keys.values().any(|&m| m == modifier) { - set_modifier(&mut self.state, modifier, false); - } - } - } - - fn reset_state(&mut self) { - let mut new_state = ModifiersState::default(); - - for &m in self.keys.values() { - set_modifier(&mut new_state, m, true); - } - - self.state = new_state; - } -} - -fn get_modifier(state: &ModifiersState, modifier: Modifier) -> bool { - match modifier { - Modifier::Alt => state.alt_key(), - Modifier::Ctrl => state.control_key(), - Modifier::Shift => state.shift_key(), - Modifier::Logo => state.super_key(), - } -} - -fn set_modifier(state: &mut ModifiersState, modifier: Modifier, value: bool) { - match modifier { - Modifier::Alt => state.set(ModifiersState::ALT, value), - Modifier::Ctrl => state.set(ModifiersState::CONTROL, value), - Modifier::Shift => state.set(ModifiersState::SHIFT, value), - Modifier::Logo => state.set(ModifiersState::SUPER, value), - } -} From 51975efd0d87b0aa891e34f0943bd5648f4b7985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 7 Jul 2022 10:08:53 +0200 Subject: [PATCH 56/58] Rip out some vestigial parts In particular, this removes the X11_EVPROC_NEXT_COMPOSE hack now that our IME event code-path seems to ignore compose sequences. --- src/platform_impl/linux/common/xkb_state.rs | 41 ++++--------------- .../linux/x11/event_processor.rs | 11 ----- 2 files changed, 7 insertions(+), 45 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 49ac66df69..9aac9e2104 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -14,11 +14,6 @@ use memmap2::MmapOptions; #[cfg(feature = "wayland")] pub use sctk::seat::keyboard::RMLVO; -#[cfg(feature = "x11")] -use std::sync::Mutex; - -#[cfg(feature = "x11")] -use once_cell::sync::Lazy; #[cfg(feature = "x11")] use x11_dl::xlib_xcb::xcb_connection_t; #[cfg(feature = "x11")] @@ -33,11 +28,6 @@ use crate::{ keyboard::{Key, KeyCode, KeyLocation}, }; -// TODO: Wire this up without using a static `Mutex>`. -#[cfg(feature = "x11")] -pub(crate) static X11_EVPROC_NEXT_COMPOSE: Lazy>> = - Lazy::new(|| Mutex::new(None)); - // TODO: Wire this up without using a static `AtomicBool`. static RESET_DEAD_KEYS: AtomicBool = AtomicBool::new(false); @@ -637,14 +627,6 @@ impl<'a> KeyEventResults<'a> { None }; - // let key_text = state.keysym_to_utf8_raw(keysym); - // unsafe { - // let layout_id = (XKBH.xkb_state_serialize_layout)(state.xkb_state, xkb_state_component::XKB_STATE_LAYOUT_EFFECTIVE); - // let layout_name_cstr = (XKBH.xkb_keymap_layout_get_name)(state.xkb_keymap, layout_id); - // let layout_name = std::ffi::CStr::from_ptr(layout_name_cstr as *mut _); - // debug!("KeyEventResults::new {:?}, {:?}", key_text, layout_name); - // } - KeyEventResults { state, keycode, @@ -679,22 +661,13 @@ impl<'a> KeyEventResults<'a> { _ => (key, location), } } - _ => { - let composed_text = self.composed_text(); - - #[cfg(feature = "x11")] - if let Ok(Some(composed_text)) = composed_text { - *X11_EVPROC_NEXT_COMPOSE.lock().unwrap() = Some(composed_text); - } - - ( - composed_text - .unwrap_or_else(|_| self.state.keysym_to_utf8_raw(self.keysym)) - .map(Key::Character) - .unwrap_or(key), - location, - ) - } + _ => ( + self.composed_text() + .unwrap_or_else(|_| self.state.keysym_to_utf8_raw(self.keysym)) + .map(Key::Character) + .unwrap_or(key), + location, + ), }) } diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 20feeef5c3..6085fcd333 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -513,7 +513,6 @@ impl EventProcessor { // Note that in compose/pre-edit sequences, we'll always receive KeyRelease events ffi::KeyPress => { - // TODO: Is it possible to exclusively use XInput2 events here? let xkev: &mut ffi::XKeyEvent = xev.as_mut(); let window = xkev.window; @@ -528,16 +527,6 @@ impl EventProcessor { // If we're composing right now, send the string we've got from X11 via // Ime::Commit. if self.is_composing && xkev.keycode == 0 && !written.is_empty() { - if super::super::common::xkb_state::X11_EVPROC_NEXT_COMPOSE - .lock() - .unwrap() - .take() - .map(|composed| composed == written) - .unwrap_or(false) - { - return; - } - let event = Event::WindowEvent { window_id, event: WindowEvent::Ime(Ime::Commit(written)), From 9d077ab72955b60e9467eefd5962675496c6879c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Thu, 7 Jul 2022 10:27:37 +0200 Subject: [PATCH 57/58] Deal with various TODOs --- src/platform_impl/linux/common/keymap.rs | 12 ++++-------- src/platform_impl/linux/common/xkb_state.rs | 3 --- src/platform_impl/linux/x11/event_processor.rs | 1 - 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index 8e2e6c2458..eabdb963f5 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -443,12 +443,9 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // keysyms::XKB_KEY_Touroku => Key::Touroku, // keysyms::XKB_KEY_Massyo => Key::Massyo, keysyms::XKB_KEY_Kana_Lock => Key::KanaMode, - // TODO: This seems a tad perverse, but I'm not really familiar with japanese keyboards. - // MDN documents this as a valid mapping, however. - // keysyms::XKB_KEY_Kana_Shift => Key::KanaMode, - // TODO: Is this the correct mapping? - // keysyms::XKB_KEY_Eisu_Shift => Key::Alphanumeric, - // keysyms::XKB_KEY_Eisu_toggle => Key::Alphanumeric, + keysyms::XKB_KEY_Kana_Shift => Key::KanaMode, + keysyms::XKB_KEY_Eisu_Shift => Key::Alphanumeric, + keysyms::XKB_KEY_Eisu_toggle => Key::Alphanumeric, // NOTE: The next three items are aliases for values we've already mapped. // keysyms::XKB_KEY_Kanji_Bangou => Key::CodeInput, // keysyms::XKB_KEY_Zen_Koho => Key::AllCandidates, @@ -501,8 +498,7 @@ pub fn keysym_to_key(keysym: u32) -> Key<'static> { // keysyms::XKB_KEY_KP_Next => Key::PageDown, keysyms::XKB_KEY_KP_Page_Down => Key::PageDown, keysyms::XKB_KEY_KP_End => Key::End, - // TODO: What is this supposed to map to? - // This is the key labeled "5" on the numpad when NumLock is off. + // This is the key labeled "5" on the numpad when NumLock is off. // keysyms::XKB_KEY_KP_Begin => Key::Begin, keysyms::XKB_KEY_KP_Insert => Key::Insert, keysyms::XKB_KEY_KP_Delete => Key::Delete, diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 9aac9e2104..e8ed9e9812 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -524,9 +524,6 @@ impl KbState { impl Drop for KbState { fn drop(&mut self) { unsafe { - // TODO: Simplify this. We can currently only safely assume that the `xkb_context` - // is always valid. If we can somehow guarantee the same for `xkb_state` and - // `xkb_keymap`, then we could omit their null-checks. if !self.xkb_compose_state.is_null() { (XKBCH.xkb_compose_state_unref)(self.xkb_compose_state); } diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 6085fcd333..41e06b4548 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1114,7 +1114,6 @@ impl EventProcessor { let keycodes_changed_flag = 0x1; let geometry_changed_flag = 0x1 << 1; - // TODO: What do we do about the "geometry changed" case? let keycodes_changed = util::has_flag(xev.changed, keycodes_changed_flag); let geometry_changed = From 29c6762e74c1c301350525c0ab03c768aff5703e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20R=C3=B8yset?= Date: Fri, 18 Nov 2022 11:12:06 +0100 Subject: [PATCH 58/58] Deduplicate code in ModifiersState::update_with --- src/platform_impl/linux/common/xkb_state.rs | 45 ++++----------------- 1 file changed, 8 insertions(+), 37 deletions(-) diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index e8ed9e9812..24839bd9b7 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -83,48 +83,19 @@ impl ModifiersState { } fn update_with(&mut self, state: *mut ffi::xkb_state) { - self.ctrl = unsafe { + let mod_name_is_active = |mod_name: &[u8]| unsafe { (XKBH.xkb_state_mod_name_is_active)( state, - ffi::XKB_MOD_NAME_CTRL.as_ptr() as *const c_char, - xkb_state_component::XKB_STATE_MODS_EFFECTIVE, - ) > 0 - }; - self.alt = unsafe { - (XKBH.xkb_state_mod_name_is_active)( - state, - ffi::XKB_MOD_NAME_ALT.as_ptr() as *const c_char, - xkb_state_component::XKB_STATE_MODS_EFFECTIVE, - ) > 0 - }; - self.shift = unsafe { - (XKBH.xkb_state_mod_name_is_active)( - state, - ffi::XKB_MOD_NAME_SHIFT.as_ptr() as *const c_char, - xkb_state_component::XKB_STATE_MODS_EFFECTIVE, - ) > 0 - }; - self.caps_lock = unsafe { - (XKBH.xkb_state_mod_name_is_active)( - state, - ffi::XKB_MOD_NAME_CAPS.as_ptr() as *const c_char, - xkb_state_component::XKB_STATE_MODS_EFFECTIVE, - ) > 0 - }; - self.logo = unsafe { - (XKBH.xkb_state_mod_name_is_active)( - state, - ffi::XKB_MOD_NAME_LOGO.as_ptr() as *const c_char, - xkb_state_component::XKB_STATE_MODS_EFFECTIVE, - ) > 0 - }; - self.num_lock = unsafe { - (XKBH.xkb_state_mod_name_is_active)( - state, - ffi::XKB_MOD_NAME_NUM.as_ptr() as *const c_char, + mod_name.as_ptr() as *const c_char, xkb_state_component::XKB_STATE_MODS_EFFECTIVE, ) > 0 }; + self.ctrl = mod_name_is_active(ffi::XKB_MOD_NAME_CTRL); + self.alt = mod_name_is_active(ffi::XKB_MOD_NAME_ALT); + self.shift = mod_name_is_active(ffi::XKB_MOD_NAME_SHIFT); + self.caps_lock = mod_name_is_active(ffi::XKB_MOD_NAME_CAPS); + self.logo = mod_name_is_active(ffi::XKB_MOD_NAME_LOGO); + self.num_lock = mod_name_is_active(ffi::XKB_MOD_NAME_NUM); } }