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.
This commit is contained in:
Mara Huldra 2022-04-19 09:47:39 +02:00 committed by GitHub
parent 7019ba41ea
commit e96380375c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 406 additions and 145 deletions

View file

@ -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",
"dlib",
"lazy_static",
"libc",
"tempfile",
"xkb",
"xkbcommon-sys",
"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 }

View file

@ -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;

View file

@ -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;

View file

@ -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>,
keymap_state: Option<State>,
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<UnixMenu>,
@ -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<Keymap> {
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);
}
}
}

80
src/os/posix/xkb_ffi.rs Normal file
View file

@ -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<XkbCommon> = 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.")
};
);

106
src/os/posix/xkb_keysyms.rs Normal file
View file

@ -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;