From e96380375cd710d5120fd8b80b29b751ce9cae14 Mon Sep 17 00:00:00 2001 From: Mara Huldra <43048142+vmedea@users.noreply.github.com> Date: Tue, 19 Apr 2022 09:47:39 +0200 Subject: [PATCH] Reduce wayland dependencies (#293) This change removes dependency on the `xkb` and `xkbcommon-sys` crates (and this indirectly, `bindgen` and everything below it) by using our own ffi wrapper, based on sctk's. A new feature `dlopen`, enabled by default, is added that causes xkbcommon to be loaded at runtime instead of linked at build-time. --- Cargo.toml | 22 +-- src/lib.rs | 5 + src/os/posix/mod.rs | 4 + src/os/posix/wayland.rs | 334 +++++++++++++++++++++--------------- src/os/posix/xkb_ffi.rs | 80 +++++++++ src/os/posix/xkb_keysyms.rs | 106 ++++++++++++ 6 files changed, 406 insertions(+), 145 deletions(-) create mode 100644 src/os/posix/xkb_ffi.rs create mode 100644 src/os/posix/xkb_keysyms.rs diff --git a/Cargo.toml b/Cargo.toml index 39bbf4d..7f1e5ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,15 +31,17 @@ version = "0.3" features = ["winuser", "wingdi", "libloaderapi", "errhandlingapi", "fileapi"] [features] -default = ["wayland", "x11"] -x11 = ["x11-dl", "xkb", "libc"] +default = ["wayland", "x11", "dlopen"] +dlopen = ["wayland-client/dlopen"] +x11 = ["x11-dl", "libc"] wayland = [ - "wayland-client", - "wayland-protocols", - "wayland-cursor", - "tempfile", - "xkb", - "xkbcommon-sys", + "dlib", + "lazy_static", + "libc", + "tempfile", + "wayland-client", + "wayland-cursor", + "wayland-protocols", ] web = [ "wasm-bindgen", @@ -56,10 +58,10 @@ wayland-protocols = { version = "0.29", features = [ ], optional = true } wayland-cursor = { version = "0.29", optional = true } tempfile = { version = "3.3", optional = true } -xkb = { version = "0.2.1", optional = true } -xkbcommon-sys = { version = "0.7.5", optional = true } x11-dl = { version = "2.19.1", optional = true } libc = { version = "0.2.107", optional = true } +dlib = { version = "0.5", optional = true } +lazy_static = { version = "1.0", optional = true } diff --git a/src/lib.rs b/src/lib.rs index 2df5148..3361305 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,11 @@ //! #![deny(missing_debug_implementations)] +#[cfg(not(any(target_os = "macos", target_os = "redox", windows)))] +#[cfg(feature = "wayland")] +#[macro_use] +extern crate dlib; + use std::fmt; use std::os::raw; diff --git a/src/os/posix/mod.rs b/src/os/posix/mod.rs index 8b239bf..01377ff 100644 --- a/src/os/posix/mod.rs +++ b/src/os/posix/mod.rs @@ -13,6 +13,10 @@ mod common; mod wayland; #[cfg(feature = "x11")] mod x11; +#[cfg(feature = "wayland")] +mod xkb_ffi; +#[cfg(feature = "wayland")] +mod xkb_keysyms; use crate::icon::Icon; use crate::Result; diff --git a/src/os/posix/wayland.rs b/src/os/posix/wayland.rs index bc7704f..20786dc 100644 --- a/src/os/posix/wayland.rs +++ b/src/os/posix/wayland.rs @@ -9,6 +9,11 @@ use crate::{ }; use super::common::Menu; +use super::xkb_ffi; +#[cfg(feature = "dlopen")] +use super::xkb_ffi::XKBCOMMON_HANDLE as XKBH; +#[cfg(not(feature = "dlopen"))] +use super::xkb_ffi::*; use wayland_client::protocol::wl_buffer::WlBuffer; use wayland_client::protocol::wl_compositor::WlCompositor; @@ -25,8 +30,6 @@ use wayland_protocols::unstable::xdg_decoration::v1::client::zxdg_decoration_man use wayland_protocols::xdg_shell::client::xdg_surface::XdgSurface; use wayland_protocols::xdg_shell::client::xdg_toplevel::XdgToplevel; use wayland_protocols::xdg_shell::client::xdg_wm_base::XdgWmBase; -use xkb::keymap::Keymap; -use xkb::state::State; use std::cell::RefCell; use std::ffi::c_void; @@ -34,6 +37,7 @@ use std::fs::File; use std::io::{self, Seek, SeekFrom, Write}; use std::mem; use std::os::unix::io::{AsRawFd, RawFd}; +use std::ptr; use std::rc::Rc; use std::slice; use std::sync::mpsc; @@ -488,9 +492,11 @@ pub struct Window { active: bool, key_handler: KeyHandler, - // Option because MaybeUninit's get_ref() is nightly-only - keymap: Option, - keymap_state: Option, + + xkb_context: *mut xkb_ffi::xkb_context, + xkb_keymap: *mut xkb_ffi::xkb_keymap, + xkb_state: *mut xkb_ffi::xkb_state, + update_rate: UpdateRate, menu_counter: MenuHandle, menus: Vec, @@ -533,6 +539,27 @@ impl Window { let (resolution, closed) = display.get_toplevel_info(); + #[cfg(feature = "dlopen")] + { + if xkb_ffi::XKBCOMMON_OPTION.as_ref().is_none() { + return Err(Error::WindowCreate( + "Could not load xkbcommon shared library.".to_owned(), + )); + } + } + let context = unsafe { + ffi_dispatch!( + XKBH, + xkb_context_new, + xkb_ffi::xkb_context_flags::XKB_CONTEXT_NO_FLAGS + ) + }; + if context.is_null() { + return Err(Error::WindowCreate( + "Could not create xkb context.".to_owned(), + )); + } + Ok(Self { display, @@ -554,8 +581,11 @@ impl Window { active: false, key_handler: KeyHandler::new(), - keymap: None, - keymap_state: None, + + xkb_context: context, + xkb_keymap: ptr::null_mut(), + xkb_state: ptr::null_mut(), + update_rate: UpdateRate::new(), menu_counter: MenuHandle(0), menus: Vec::new(), @@ -764,9 +794,9 @@ impl Window { match event { Event::Keymap { format, fd, size } => { - let keymap = Self::handle_keymap(format, fd, size).unwrap(); - self.keymap_state = Some(keymap.state()); - self.keymap = Some(keymap); + let keymap = Self::handle_keymap(self.xkb_context, format, fd, size).unwrap(); + self.xkb_keymap = keymap; + self.xkb_state = unsafe { ffi_dispatch!(XKBH, xkb_state_new, keymap) }; } Event::Enter { .. } => { self.active = true; @@ -775,9 +805,9 @@ impl Window { self.active = false; } Event::Key { key, state, .. } => { - if let Some(ref keymap_state) = self.keymap_state { + if !self.xkb_state.is_null() { Self::handle_key( - keymap_state, + self.xkb_state, key + KEY_XKB_OFFSET, state, &mut self.key_handler, @@ -791,9 +821,20 @@ impl Window { group, .. } => { - if let Some(ref mut state) = self.keymap_state { - let mut update = state.update(); - update.mask(mods_depressed, mods_latched, mods_locked, 0, 0, group); + if !self.xkb_state.is_null() { + unsafe { + ffi_dispatch!( + XKBH, + xkb_state_update_mask, + self.xkb_state, + mods_depressed, + mods_latched, + mods_locked, + 0, + 0, + group + ) + }; } } _ => {} @@ -928,20 +969,19 @@ impl Window { } fn handle_key( - keymap_state: &State, + keymap_state: *mut xkb_ffi::xkb_state, key: u32, state: wl_keyboard::KeyState, key_handler: &mut KeyHandler, ) { let is_down = state == wl_keyboard::KeyState::Pressed; - let key_xkb = keymap_state.key(key); - - if let Some(keysym) = key_xkb.sym() { - use xkb::key; + let key_xkb = unsafe { ffi_dispatch!(XKBH, xkb_state_key_get_one_sym, keymap_state, key) }; + if key_xkb != 0 { + use super::xkb_keysyms as key; if state == wl_keyboard::KeyState::Pressed { // Taken from GLFW - let code_point = keysym.utf32(); + let code_point = unsafe { ffi_dispatch!(XKBH, xkb_keysym_to_utf32, key_xkb) }; if !(code_point < 32 || (code_point > 126 && code_point < 160)) { if let Some(ref mut callback) = key_handler.key_callback { callback.add_char(code_point); @@ -949,115 +989,115 @@ impl Window { } } - let key_i = match keysym { - key::_0 => Key::Key0, - key::_1 => Key::Key1, - key::_2 => Key::Key2, - key::_3 => Key::Key3, - key::_4 => Key::Key4, - key::_5 => Key::Key5, - key::_6 => Key::Key6, - key::_7 => Key::Key7, - key::_8 => Key::Key8, - key::_9 => Key::Key9, + let key_i = match key_xkb { + key::XKB_KEY_0 => Key::Key0, + key::XKB_KEY_1 => Key::Key1, + key::XKB_KEY_2 => Key::Key2, + key::XKB_KEY_3 => Key::Key3, + key::XKB_KEY_4 => Key::Key4, + key::XKB_KEY_5 => Key::Key5, + key::XKB_KEY_6 => Key::Key6, + key::XKB_KEY_7 => Key::Key7, + key::XKB_KEY_8 => Key::Key8, + key::XKB_KEY_9 => Key::Key9, - key::a => Key::A, - key::b => Key::B, - key::c => Key::C, - key::d => Key::D, - key::e => Key::E, - key::f => Key::F, - key::g => Key::G, - key::h => Key::H, - key::i => Key::I, - key::j => Key::J, - key::k => Key::K, - key::l => Key::L, - key::m => Key::M, - key::n => Key::N, - key::o => Key::O, - key::p => Key::P, - key::q => Key::Q, - key::r => Key::R, - key::s => Key::S, - key::t => Key::T, - key::u => Key::U, - key::v => Key::V, - key::w => Key::W, - key::x => Key::X, - key::y => Key::Y, - key::z => Key::Z, + key::XKB_KEY_a => Key::A, + key::XKB_KEY_b => Key::B, + key::XKB_KEY_c => Key::C, + key::XKB_KEY_d => Key::D, + key::XKB_KEY_e => Key::E, + key::XKB_KEY_f => Key::F, + key::XKB_KEY_g => Key::G, + key::XKB_KEY_h => Key::H, + key::XKB_KEY_i => Key::I, + key::XKB_KEY_j => Key::J, + key::XKB_KEY_k => Key::K, + key::XKB_KEY_l => Key::L, + key::XKB_KEY_m => Key::M, + key::XKB_KEY_n => Key::N, + key::XKB_KEY_o => Key::O, + key::XKB_KEY_p => Key::P, + key::XKB_KEY_q => Key::Q, + key::XKB_KEY_r => Key::R, + key::XKB_KEY_s => Key::S, + key::XKB_KEY_t => Key::T, + key::XKB_KEY_u => Key::U, + key::XKB_KEY_v => Key::V, + key::XKB_KEY_w => Key::W, + key::XKB_KEY_x => Key::X, + key::XKB_KEY_y => Key::Y, + key::XKB_KEY_z => Key::Z, - key::apostrophe => Key::Apostrophe, - key::grave => Key::Backquote, - key::backslash => Key::Backslash, - key::comma => Key::Comma, - key::equal => Key::Equal, - key::bracketleft => Key::LeftBracket, - key::bracketright => Key::RightBracket, - key::minus => Key::Minus, - key::period => Key::Period, - key::semicolon => Key::Semicolon, - key::slash => Key::Slash, - key::space => Key::Space, + key::XKB_KEY_apostrophe => Key::Apostrophe, + key::XKB_KEY_grave => Key::Backquote, + key::XKB_KEY_backslash => Key::Backslash, + key::XKB_KEY_comma => Key::Comma, + key::XKB_KEY_equal => Key::Equal, + key::XKB_KEY_bracketleft => Key::LeftBracket, + key::XKB_KEY_bracketright => Key::RightBracket, + key::XKB_KEY_minus => Key::Minus, + key::XKB_KEY_period => Key::Period, + key::XKB_KEY_semicolon => Key::Semicolon, + key::XKB_KEY_slash => Key::Slash, + key::XKB_KEY_space => Key::Space, - key::F1 => Key::F1, - key::F2 => Key::F2, - key::F3 => Key::F3, - key::F4 => Key::F4, - key::F5 => Key::F5, - key::F6 => Key::F6, - key::F7 => Key::F7, - key::F8 => Key::F8, - key::F9 => Key::F9, - key::F10 => Key::F10, - key::F11 => Key::F11, - key::F12 => Key::F12, + key::XKB_KEY_F1 => Key::F1, + key::XKB_KEY_F2 => Key::F2, + key::XKB_KEY_F3 => Key::F3, + key::XKB_KEY_F4 => Key::F4, + key::XKB_KEY_F5 => Key::F5, + key::XKB_KEY_F6 => Key::F6, + key::XKB_KEY_F7 => Key::F7, + key::XKB_KEY_F8 => Key::F8, + key::XKB_KEY_F9 => Key::F9, + key::XKB_KEY_F10 => Key::F10, + key::XKB_KEY_F11 => Key::F11, + key::XKB_KEY_F12 => Key::F12, - key::Down => Key::Down, - key::Left => Key::Left, - key::Right => Key::Right, - key::Up => Key::Up, - key::Escape => Key::Escape, - key::BackSpace => Key::Backspace, - key::Delete => Key::Delete, - key::End => Key::End, - key::Return => Key::Enter, - key::Home => Key::Home, - key::Insert => Key::Insert, - key::Menu => Key::Menu, - key::Page_Down => Key::PageDown, - key::Page_Up => Key::PageUp, - key::Pause => Key::Pause, - key::Tab => Key::Tab, - key::Num_Lock => Key::NumLock, - key::Caps_Lock => Key::CapsLock, - key::Scroll_Lock => Key::ScrollLock, - key::Shift_L => Key::LeftShift, - key::Shift_R => Key::RightShift, - key::Alt_L => Key::LeftAlt, - key::Alt_R => Key::RightAlt, - key::Control_L => Key::LeftCtrl, - key::Control_R => Key::RightCtrl, - key::Super_L => Key::LeftSuper, - key::Super_R => Key::RightSuper, + key::XKB_KEY_Down => Key::Down, + key::XKB_KEY_Left => Key::Left, + key::XKB_KEY_Right => Key::Right, + key::XKB_KEY_Up => Key::Up, + key::XKB_KEY_Escape => Key::Escape, + key::XKB_KEY_BackSpace => Key::Backspace, + key::XKB_KEY_Delete => Key::Delete, + key::XKB_KEY_End => Key::End, + key::XKB_KEY_Return => Key::Enter, + key::XKB_KEY_Home => Key::Home, + key::XKB_KEY_Insert => Key::Insert, + key::XKB_KEY_Menu => Key::Menu, + key::XKB_KEY_Page_Down => Key::PageDown, + key::XKB_KEY_Page_Up => Key::PageUp, + key::XKB_KEY_Pause => Key::Pause, + key::XKB_KEY_Tab => Key::Tab, + key::XKB_KEY_Num_Lock => Key::NumLock, + key::XKB_KEY_Caps_Lock => Key::CapsLock, + key::XKB_KEY_Scroll_Lock => Key::ScrollLock, + key::XKB_KEY_Shift_L => Key::LeftShift, + key::XKB_KEY_Shift_R => Key::RightShift, + key::XKB_KEY_Alt_L => Key::LeftAlt, + key::XKB_KEY_Alt_R => Key::RightAlt, + key::XKB_KEY_Control_L => Key::LeftCtrl, + key::XKB_KEY_Control_R => Key::RightCtrl, + key::XKB_KEY_Super_L => Key::LeftSuper, + key::XKB_KEY_Super_R => Key::RightSuper, - key::KP_Insert => Key::NumPad0, - key::KP_End => Key::NumPad1, - key::KP_Down => Key::NumPad2, - key::KP_Next => Key::NumPad3, - key::KP_Left => Key::NumPad4, - key::KP_Begin => Key::NumPad5, - key::KP_Right => Key::NumPad6, - key::KP_Home => Key::NumPad7, - key::KP_Up => Key::NumPad8, - key::KP_Prior => Key::NumPad9, - key::KP_Decimal => Key::NumPadDot, - key::KP_Divide => Key::NumPadSlash, - key::KP_Multiply => Key::NumPadAsterisk, - key::KP_Subtract => Key::NumPadMinus, - key::KP_Add => Key::NumPadPlus, - key::KP_Enter => Key::NumPadEnter, + key::XKB_KEY_KP_Insert => Key::NumPad0, + key::XKB_KEY_KP_End => Key::NumPad1, + key::XKB_KEY_KP_Down => Key::NumPad2, + key::XKB_KEY_KP_Next => Key::NumPad3, + key::XKB_KEY_KP_Left => Key::NumPad4, + key::XKB_KEY_KP_Begin => Key::NumPad5, + key::XKB_KEY_KP_Right => Key::NumPad6, + key::XKB_KEY_KP_Home => Key::NumPad7, + key::XKB_KEY_KP_Up => Key::NumPad8, + key::XKB_KEY_KP_Prior => Key::NumPad9, + key::XKB_KEY_KP_Decimal => Key::NumPadDot, + key::XKB_KEY_KP_Divide => Key::NumPadSlash, + key::XKB_KEY_KP_Multiply => Key::NumPadAsterisk, + key::XKB_KEY_KP_Subtract => Key::NumPadMinus, + key::XKB_KEY_KP_Add => Key::NumPadPlus, + key::XKB_KEY_KP_Enter => Key::NumPadEnter, _ => { // Ignore other keys @@ -1069,7 +1109,12 @@ impl Window { } } - fn handle_keymap(keymap: KeymapFormat, fd: RawFd, len: u32) -> std::io::Result { + fn handle_keymap( + context: *mut xkb_ffi::xkb_context, + keymap: KeymapFormat, + fd: RawFd, + len: u32, + ) -> Result<*mut xkb_ffi::xkb_keymap> { match keymap { KeymapFormat::XkbV1 => { unsafe { @@ -1083,21 +1128,30 @@ impl Window { 0, ); if addr == libc::MAP_FAILED { - return Err(std::io::Error::last_os_error()); + return Err(Error::WindowCreate(format!( + "Could not mmap keymap from compositor ({})", + std::io::Error::last_os_error() + ))); } - let ctx = xkbcommon_sys::xkb_context_new(0); - let kb_map_ptr = xkbcommon_sys::xkb_keymap_new_from_string( - ctx, - addr as _, - xkbcommon_sys::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1, - 0, + let keymap = ffi_dispatch!( + XKBH, + xkb_keymap_new_from_string, + context, + addr as *const _, + xkb_ffi::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1, + xkb_ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS ); libc::munmap(addr, len as usize); - // Wrap keymap - Ok(Keymap::from_ptr(kb_map_ptr as *mut _ as *mut c_void)) + if keymap.is_null() { + Err(Error::WindowCreate( + "Received invalid keymap from compositor.".to_owned(), + )) + } else { + Ok(keymap) + } } } _ => unimplemented!("Only XKB keymaps are supported"), @@ -1224,3 +1278,13 @@ unsafe impl raw_window_handle::HasRawWindowHandle for Window { raw_window_handle::RawWindowHandle::Wayland(handle) } } + +impl Drop for Window { + fn drop(&mut self) { + unsafe { + ffi_dispatch!(XKBH, xkb_state_unref, self.xkb_state); + ffi_dispatch!(XKBH, xkb_keymap_unref, self.xkb_keymap); + ffi_dispatch!(XKBH, xkb_context_unref, self.xkb_context); + } + } +} diff --git a/src/os/posix/xkb_ffi.rs b/src/os/posix/xkb_ffi.rs new file mode 100644 index 0000000..f1fb39a --- /dev/null +++ b/src/os/posix/xkb_ffi.rs @@ -0,0 +1,80 @@ +#![allow(non_camel_case_types, clippy::identity_op)] +/** Minimal xkb_common ffi wrapper, based on sctk's. */ +use std::os::raw::c_char; + +#[repr(C)] +pub struct xkb_context { + _private: [u8; 0], +} +#[repr(C)] +pub struct xkb_keymap { + _private: [u8; 0], +} +#[repr(C)] +pub struct xkb_state { + _private: [u8; 0], +} + +pub type xkb_keycode_t = u32; +pub type xkb_keysym_t = u32; +pub type xkb_layout_index_t = u32; +pub type xkb_mod_mask_t = u32; + +#[repr(C)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum xkb_context_flags { + /** Do not apply any context flags. */ + XKB_CONTEXT_NO_FLAGS = 0, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum xkb_keymap_compile_flags { + /** Do not apply any flags. */ + XKB_KEYMAP_COMPILE_NO_FLAGS = 0, +} + +#[repr(C)] +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum xkb_keymap_format { + /** The current/classic XKB text format, as generated by xkbcomp -xkb. */ + XKB_KEYMAP_FORMAT_TEXT_V1 = 1, +} + +pub type xkb_state_component = u32; + +external_library!(XkbCommon, "xkbcommon", +functions: + fn xkb_keysym_to_utf32(xkb_keysym_t) -> u32, + fn xkb_context_new(xkb_context_flags) -> *mut xkb_context, + fn xkb_context_unref(*mut xkb_context) -> (), + fn xkb_keymap_new_from_string(*mut xkb_context, + *const c_char, + xkb_keymap_format, + xkb_keymap_compile_flags + ) -> *mut xkb_keymap, + fn xkb_keymap_unref(*mut xkb_keymap) -> (), + fn xkb_state_key_get_one_sym(*mut xkb_state, xkb_keycode_t) -> xkb_keysym_t, + fn xkb_state_new(*mut xkb_keymap) -> *mut xkb_state, + fn xkb_state_unref(*mut xkb_state) -> (), + fn xkb_state_update_mask(*mut xkb_state, + xkb_mod_mask_t, + xkb_mod_mask_t, + xkb_mod_mask_t, + xkb_layout_index_t, + xkb_layout_index_t, + xkb_layout_index_t + ) -> xkb_state_component, +); + +#[cfg(feature = "dlopen")] +lazy_static::lazy_static!( + pub static ref XKBCOMMON_OPTION: Option = unsafe { + XkbCommon::open("libxkbcommon.so.0") + .or_else(|_| XkbCommon::open("libxkbcommon.so")) + .ok() + }; + pub static ref XKBCOMMON_HANDLE: &'static XkbCommon = { + XKBCOMMON_OPTION.as_ref().expect("Library libxkbcommon.so could not be loaded.") + }; +); diff --git a/src/os/posix/xkb_keysyms.rs b/src/os/posix/xkb_keysyms.rs new file mode 100644 index 0000000..9a20d52 --- /dev/null +++ b/src/os/posix/xkb_keysyms.rs @@ -0,0 +1,106 @@ +#![allow(missing_docs, non_upper_case_globals, unused_parens, clippy::all)] +/** The subset of XKB_* key symbols that are used in minifb. */ + +pub const XKB_KEY_0: u32 = 0x0030; +pub const XKB_KEY_1: u32 = 0x0031; +pub const XKB_KEY_2: u32 = 0x0032; +pub const XKB_KEY_3: u32 = 0x0033; +pub const XKB_KEY_4: u32 = 0x0034; +pub const XKB_KEY_5: u32 = 0x0035; +pub const XKB_KEY_6: u32 = 0x0036; +pub const XKB_KEY_7: u32 = 0x0037; +pub const XKB_KEY_8: u32 = 0x0038; +pub const XKB_KEY_9: u32 = 0x0039; +pub const XKB_KEY_a: u32 = 0x0061; +pub const XKB_KEY_b: u32 = 0x0062; +pub const XKB_KEY_c: u32 = 0x0063; +pub const XKB_KEY_d: u32 = 0x0064; +pub const XKB_KEY_e: u32 = 0x0065; +pub const XKB_KEY_f: u32 = 0x0066; +pub const XKB_KEY_g: u32 = 0x0067; +pub const XKB_KEY_h: u32 = 0x0068; +pub const XKB_KEY_i: u32 = 0x0069; +pub const XKB_KEY_j: u32 = 0x006a; +pub const XKB_KEY_k: u32 = 0x006b; +pub const XKB_KEY_l: u32 = 0x006c; +pub const XKB_KEY_m: u32 = 0x006d; +pub const XKB_KEY_n: u32 = 0x006e; +pub const XKB_KEY_o: u32 = 0x006f; +pub const XKB_KEY_p: u32 = 0x0070; +pub const XKB_KEY_q: u32 = 0x0071; +pub const XKB_KEY_r: u32 = 0x0072; +pub const XKB_KEY_s: u32 = 0x0073; +pub const XKB_KEY_t: u32 = 0x0074; +pub const XKB_KEY_u: u32 = 0x0075; +pub const XKB_KEY_v: u32 = 0x0076; +pub const XKB_KEY_w: u32 = 0x0077; +pub const XKB_KEY_x: u32 = 0x0078; +pub const XKB_KEY_y: u32 = 0x0079; +pub const XKB_KEY_z: u32 = 0x007a; +pub const XKB_KEY_apostrophe: u32 = 0x0027; +pub const XKB_KEY_grave: u32 = 0x0060; +pub const XKB_KEY_backslash: u32 = 0x005c; +pub const XKB_KEY_comma: u32 = 0x002c; +pub const XKB_KEY_equal: u32 = 0x003d; +pub const XKB_KEY_bracketleft: u32 = 0x005b; +pub const XKB_KEY_bracketright: u32 = 0x005d; +pub const XKB_KEY_minus: u32 = 0x002d; +pub const XKB_KEY_period: u32 = 0x002e; +pub const XKB_KEY_semicolon: u32 = 0x003b; +pub const XKB_KEY_slash: u32 = 0x002f; +pub const XKB_KEY_space: u32 = 0x0020; +pub const XKB_KEY_F1: u32 = 0xffbe; +pub const XKB_KEY_F2: u32 = 0xffbf; +pub const XKB_KEY_F3: u32 = 0xffc0; +pub const XKB_KEY_F4: u32 = 0xffc1; +pub const XKB_KEY_F5: u32 = 0xffc2; +pub const XKB_KEY_F6: u32 = 0xffc3; +pub const XKB_KEY_F7: u32 = 0xffc4; +pub const XKB_KEY_F8: u32 = 0xffc5; +pub const XKB_KEY_F9: u32 = 0xffc6; +pub const XKB_KEY_F10: u32 = 0xffc7; +pub const XKB_KEY_F11: u32 = 0xffc8; +pub const XKB_KEY_F12: u32 = 0xffc9; +pub const XKB_KEY_Down: u32 = 0xff54; +pub const XKB_KEY_Left: u32 = 0xff51; +pub const XKB_KEY_Right: u32 = 0xff53; +pub const XKB_KEY_Up: u32 = 0xff52; +pub const XKB_KEY_Escape: u32 = 0xff1b; +pub const XKB_KEY_BackSpace: u32 = 0xff08; +pub const XKB_KEY_Delete: u32 = 0xffff; +pub const XKB_KEY_End: u32 = 0xff57; +pub const XKB_KEY_Return: u32 = 0xff0d; +pub const XKB_KEY_Home: u32 = 0xff50; +pub const XKB_KEY_Insert: u32 = 0xff63; +pub const XKB_KEY_Menu: u32 = 0xff67; +pub const XKB_KEY_Page_Down: u32 = 0xff56; +pub const XKB_KEY_Page_Up: u32 = 0xff55; +pub const XKB_KEY_Pause: u32 = 0xff13; +pub const XKB_KEY_Tab: u32 = 0xff09; +pub const XKB_KEY_Num_Lock: u32 = 0xff7f; +pub const XKB_KEY_Caps_Lock: u32 = 0xffe5; +pub const XKB_KEY_Scroll_Lock: u32 = 0xff14; +pub const XKB_KEY_Shift_L: u32 = 0xffe1; +pub const XKB_KEY_Shift_R: u32 = 0xffe2; +pub const XKB_KEY_Alt_L: u32 = 0xffe9; +pub const XKB_KEY_Alt_R: u32 = 0xffea; +pub const XKB_KEY_Control_L: u32 = 0xffe3; +pub const XKB_KEY_Control_R: u32 = 0xffe4; +pub const XKB_KEY_Super_L: u32 = 0xffeb; +pub const XKB_KEY_Super_R: u32 = 0xffec; +pub const XKB_KEY_KP_Insert: u32 = 0xff9e; +pub const XKB_KEY_KP_End: u32 = 0xff9c; +pub const XKB_KEY_KP_Down: u32 = 0xff99; +pub const XKB_KEY_KP_Next: u32 = 0xff9b; +pub const XKB_KEY_KP_Left: u32 = 0xff96; +pub const XKB_KEY_KP_Begin: u32 = 0xff9d; +pub const XKB_KEY_KP_Right: u32 = 0xff98; +pub const XKB_KEY_KP_Home: u32 = 0xff95; +pub const XKB_KEY_KP_Up: u32 = 0xff97; +pub const XKB_KEY_KP_Prior: u32 = 0xff9a; +pub const XKB_KEY_KP_Decimal: u32 = 0xffae; +pub const XKB_KEY_KP_Divide: u32 = 0xffaf; +pub const XKB_KEY_KP_Multiply: u32 = 0xffaa; +pub const XKB_KEY_KP_Subtract: u32 = 0xffad; +pub const XKB_KEY_KP_Add: u32 = 0xffab; +pub const XKB_KEY_KP_Enter: u32 = 0xff8d;