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 = ["winuser", "wingdi", "libloaderapi", "errhandlingapi", "fileapi"]
[features] [features]
default = ["wayland", "x11"] default = ["wayland", "x11", "dlopen"]
x11 = ["x11-dl", "xkb", "libc"] dlopen = ["wayland-client/dlopen"]
x11 = ["x11-dl", "libc"]
wayland = [ wayland = [
"wayland-client", "dlib",
"wayland-protocols", "lazy_static",
"wayland-cursor", "libc",
"tempfile", "tempfile",
"xkb", "wayland-client",
"xkbcommon-sys", "wayland-cursor",
"wayland-protocols",
] ]
web = [ web = [
"wasm-bindgen", "wasm-bindgen",
@ -56,10 +58,10 @@ wayland-protocols = { version = "0.29", features = [
], optional = true } ], optional = true }
wayland-cursor = { version = "0.29", optional = true } wayland-cursor = { version = "0.29", optional = true }
tempfile = { version = "3.3", 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 } x11-dl = { version = "2.19.1", optional = true }
libc = { version = "0.2.107", 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)] #![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::fmt;
use std::os::raw; use std::os::raw;

View file

@ -13,6 +13,10 @@ mod common;
mod wayland; mod wayland;
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
mod x11; mod x11;
#[cfg(feature = "wayland")]
mod xkb_ffi;
#[cfg(feature = "wayland")]
mod xkb_keysyms;
use crate::icon::Icon; use crate::icon::Icon;
use crate::Result; use crate::Result;

View file

@ -9,6 +9,11 @@ use crate::{
}; };
use super::common::Menu; 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_buffer::WlBuffer;
use wayland_client::protocol::wl_compositor::WlCompositor; 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_surface::XdgSurface;
use wayland_protocols::xdg_shell::client::xdg_toplevel::XdgToplevel; use wayland_protocols::xdg_shell::client::xdg_toplevel::XdgToplevel;
use wayland_protocols::xdg_shell::client::xdg_wm_base::XdgWmBase; use wayland_protocols::xdg_shell::client::xdg_wm_base::XdgWmBase;
use xkb::keymap::Keymap;
use xkb::state::State;
use std::cell::RefCell; use std::cell::RefCell;
use std::ffi::c_void; use std::ffi::c_void;
@ -34,6 +37,7 @@ use std::fs::File;
use std::io::{self, Seek, SeekFrom, Write}; use std::io::{self, Seek, SeekFrom, Write};
use std::mem; use std::mem;
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use std::ptr;
use std::rc::Rc; use std::rc::Rc;
use std::slice; use std::slice;
use std::sync::mpsc; use std::sync::mpsc;
@ -488,9 +492,11 @@ pub struct Window {
active: bool, active: bool,
key_handler: KeyHandler, key_handler: KeyHandler,
// Option because MaybeUninit's get_ref() is nightly-only
keymap: Option<Keymap>, xkb_context: *mut xkb_ffi::xkb_context,
keymap_state: Option<State>, xkb_keymap: *mut xkb_ffi::xkb_keymap,
xkb_state: *mut xkb_ffi::xkb_state,
update_rate: UpdateRate, update_rate: UpdateRate,
menu_counter: MenuHandle, menu_counter: MenuHandle,
menus: Vec<UnixMenu>, menus: Vec<UnixMenu>,
@ -533,6 +539,27 @@ impl Window {
let (resolution, closed) = display.get_toplevel_info(); 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 { Ok(Self {
display, display,
@ -554,8 +581,11 @@ impl Window {
active: false, active: false,
key_handler: KeyHandler::new(), 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(), update_rate: UpdateRate::new(),
menu_counter: MenuHandle(0), menu_counter: MenuHandle(0),
menus: Vec::new(), menus: Vec::new(),
@ -764,9 +794,9 @@ impl Window {
match event { match event {
Event::Keymap { format, fd, size } => { Event::Keymap { format, fd, size } => {
let keymap = Self::handle_keymap(format, fd, size).unwrap(); let keymap = Self::handle_keymap(self.xkb_context, format, fd, size).unwrap();
self.keymap_state = Some(keymap.state()); self.xkb_keymap = keymap;
self.keymap = Some(keymap); self.xkb_state = unsafe { ffi_dispatch!(XKBH, xkb_state_new, keymap) };
} }
Event::Enter { .. } => { Event::Enter { .. } => {
self.active = true; self.active = true;
@ -775,9 +805,9 @@ impl Window {
self.active = false; self.active = false;
} }
Event::Key { key, state, .. } => { Event::Key { key, state, .. } => {
if let Some(ref keymap_state) = self.keymap_state { if !self.xkb_state.is_null() {
Self::handle_key( Self::handle_key(
keymap_state, self.xkb_state,
key + KEY_XKB_OFFSET, key + KEY_XKB_OFFSET,
state, state,
&mut self.key_handler, &mut self.key_handler,
@ -791,9 +821,20 @@ impl Window {
group, group,
.. ..
} => { } => {
if let Some(ref mut state) = self.keymap_state { if !self.xkb_state.is_null() {
let mut update = state.update(); unsafe {
update.mask(mods_depressed, mods_latched, mods_locked, 0, 0, group); 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( fn handle_key(
keymap_state: &State, keymap_state: *mut xkb_ffi::xkb_state,
key: u32, key: u32,
state: wl_keyboard::KeyState, state: wl_keyboard::KeyState,
key_handler: &mut KeyHandler, key_handler: &mut KeyHandler,
) { ) {
let is_down = state == wl_keyboard::KeyState::Pressed; let is_down = state == wl_keyboard::KeyState::Pressed;
let key_xkb = keymap_state.key(key); let key_xkb = unsafe { ffi_dispatch!(XKBH, xkb_state_key_get_one_sym, keymap_state, key) };
if key_xkb != 0 {
if let Some(keysym) = key_xkb.sym() { use super::xkb_keysyms as key;
use xkb::key;
if state == wl_keyboard::KeyState::Pressed { if state == wl_keyboard::KeyState::Pressed {
// Taken from GLFW // 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 !(code_point < 32 || (code_point > 126 && code_point < 160)) {
if let Some(ref mut callback) = key_handler.key_callback { if let Some(ref mut callback) = key_handler.key_callback {
callback.add_char(code_point); callback.add_char(code_point);
@ -949,115 +989,115 @@ impl Window {
} }
} }
let key_i = match keysym { let key_i = match key_xkb {
key::_0 => Key::Key0, key::XKB_KEY_0 => Key::Key0,
key::_1 => Key::Key1, key::XKB_KEY_1 => Key::Key1,
key::_2 => Key::Key2, key::XKB_KEY_2 => Key::Key2,
key::_3 => Key::Key3, key::XKB_KEY_3 => Key::Key3,
key::_4 => Key::Key4, key::XKB_KEY_4 => Key::Key4,
key::_5 => Key::Key5, key::XKB_KEY_5 => Key::Key5,
key::_6 => Key::Key6, key::XKB_KEY_6 => Key::Key6,
key::_7 => Key::Key7, key::XKB_KEY_7 => Key::Key7,
key::_8 => Key::Key8, key::XKB_KEY_8 => Key::Key8,
key::_9 => Key::Key9, key::XKB_KEY_9 => Key::Key9,
key::a => Key::A, key::XKB_KEY_a => Key::A,
key::b => Key::B, key::XKB_KEY_b => Key::B,
key::c => Key::C, key::XKB_KEY_c => Key::C,
key::d => Key::D, key::XKB_KEY_d => Key::D,
key::e => Key::E, key::XKB_KEY_e => Key::E,
key::f => Key::F, key::XKB_KEY_f => Key::F,
key::g => Key::G, key::XKB_KEY_g => Key::G,
key::h => Key::H, key::XKB_KEY_h => Key::H,
key::i => Key::I, key::XKB_KEY_i => Key::I,
key::j => Key::J, key::XKB_KEY_j => Key::J,
key::k => Key::K, key::XKB_KEY_k => Key::K,
key::l => Key::L, key::XKB_KEY_l => Key::L,
key::m => Key::M, key::XKB_KEY_m => Key::M,
key::n => Key::N, key::XKB_KEY_n => Key::N,
key::o => Key::O, key::XKB_KEY_o => Key::O,
key::p => Key::P, key::XKB_KEY_p => Key::P,
key::q => Key::Q, key::XKB_KEY_q => Key::Q,
key::r => Key::R, key::XKB_KEY_r => Key::R,
key::s => Key::S, key::XKB_KEY_s => Key::S,
key::t => Key::T, key::XKB_KEY_t => Key::T,
key::u => Key::U, key::XKB_KEY_u => Key::U,
key::v => Key::V, key::XKB_KEY_v => Key::V,
key::w => Key::W, key::XKB_KEY_w => Key::W,
key::x => Key::X, key::XKB_KEY_x => Key::X,
key::y => Key::Y, key::XKB_KEY_y => Key::Y,
key::z => Key::Z, key::XKB_KEY_z => Key::Z,
key::apostrophe => Key::Apostrophe, key::XKB_KEY_apostrophe => Key::Apostrophe,
key::grave => Key::Backquote, key::XKB_KEY_grave => Key::Backquote,
key::backslash => Key::Backslash, key::XKB_KEY_backslash => Key::Backslash,
key::comma => Key::Comma, key::XKB_KEY_comma => Key::Comma,
key::equal => Key::Equal, key::XKB_KEY_equal => Key::Equal,
key::bracketleft => Key::LeftBracket, key::XKB_KEY_bracketleft => Key::LeftBracket,
key::bracketright => Key::RightBracket, key::XKB_KEY_bracketright => Key::RightBracket,
key::minus => Key::Minus, key::XKB_KEY_minus => Key::Minus,
key::period => Key::Period, key::XKB_KEY_period => Key::Period,
key::semicolon => Key::Semicolon, key::XKB_KEY_semicolon => Key::Semicolon,
key::slash => Key::Slash, key::XKB_KEY_slash => Key::Slash,
key::space => Key::Space, key::XKB_KEY_space => Key::Space,
key::F1 => Key::F1, key::XKB_KEY_F1 => Key::F1,
key::F2 => Key::F2, key::XKB_KEY_F2 => Key::F2,
key::F3 => Key::F3, key::XKB_KEY_F3 => Key::F3,
key::F4 => Key::F4, key::XKB_KEY_F4 => Key::F4,
key::F5 => Key::F5, key::XKB_KEY_F5 => Key::F5,
key::F6 => Key::F6, key::XKB_KEY_F6 => Key::F6,
key::F7 => Key::F7, key::XKB_KEY_F7 => Key::F7,
key::F8 => Key::F8, key::XKB_KEY_F8 => Key::F8,
key::F9 => Key::F9, key::XKB_KEY_F9 => Key::F9,
key::F10 => Key::F10, key::XKB_KEY_F10 => Key::F10,
key::F11 => Key::F11, key::XKB_KEY_F11 => Key::F11,
key::F12 => Key::F12, key::XKB_KEY_F12 => Key::F12,
key::Down => Key::Down, key::XKB_KEY_Down => Key::Down,
key::Left => Key::Left, key::XKB_KEY_Left => Key::Left,
key::Right => Key::Right, key::XKB_KEY_Right => Key::Right,
key::Up => Key::Up, key::XKB_KEY_Up => Key::Up,
key::Escape => Key::Escape, key::XKB_KEY_Escape => Key::Escape,
key::BackSpace => Key::Backspace, key::XKB_KEY_BackSpace => Key::Backspace,
key::Delete => Key::Delete, key::XKB_KEY_Delete => Key::Delete,
key::End => Key::End, key::XKB_KEY_End => Key::End,
key::Return => Key::Enter, key::XKB_KEY_Return => Key::Enter,
key::Home => Key::Home, key::XKB_KEY_Home => Key::Home,
key::Insert => Key::Insert, key::XKB_KEY_Insert => Key::Insert,
key::Menu => Key::Menu, key::XKB_KEY_Menu => Key::Menu,
key::Page_Down => Key::PageDown, key::XKB_KEY_Page_Down => Key::PageDown,
key::Page_Up => Key::PageUp, key::XKB_KEY_Page_Up => Key::PageUp,
key::Pause => Key::Pause, key::XKB_KEY_Pause => Key::Pause,
key::Tab => Key::Tab, key::XKB_KEY_Tab => Key::Tab,
key::Num_Lock => Key::NumLock, key::XKB_KEY_Num_Lock => Key::NumLock,
key::Caps_Lock => Key::CapsLock, key::XKB_KEY_Caps_Lock => Key::CapsLock,
key::Scroll_Lock => Key::ScrollLock, key::XKB_KEY_Scroll_Lock => Key::ScrollLock,
key::Shift_L => Key::LeftShift, key::XKB_KEY_Shift_L => Key::LeftShift,
key::Shift_R => Key::RightShift, key::XKB_KEY_Shift_R => Key::RightShift,
key::Alt_L => Key::LeftAlt, key::XKB_KEY_Alt_L => Key::LeftAlt,
key::Alt_R => Key::RightAlt, key::XKB_KEY_Alt_R => Key::RightAlt,
key::Control_L => Key::LeftCtrl, key::XKB_KEY_Control_L => Key::LeftCtrl,
key::Control_R => Key::RightCtrl, key::XKB_KEY_Control_R => Key::RightCtrl,
key::Super_L => Key::LeftSuper, key::XKB_KEY_Super_L => Key::LeftSuper,
key::Super_R => Key::RightSuper, key::XKB_KEY_Super_R => Key::RightSuper,
key::KP_Insert => Key::NumPad0, key::XKB_KEY_KP_Insert => Key::NumPad0,
key::KP_End => Key::NumPad1, key::XKB_KEY_KP_End => Key::NumPad1,
key::KP_Down => Key::NumPad2, key::XKB_KEY_KP_Down => Key::NumPad2,
key::KP_Next => Key::NumPad3, key::XKB_KEY_KP_Next => Key::NumPad3,
key::KP_Left => Key::NumPad4, key::XKB_KEY_KP_Left => Key::NumPad4,
key::KP_Begin => Key::NumPad5, key::XKB_KEY_KP_Begin => Key::NumPad5,
key::KP_Right => Key::NumPad6, key::XKB_KEY_KP_Right => Key::NumPad6,
key::KP_Home => Key::NumPad7, key::XKB_KEY_KP_Home => Key::NumPad7,
key::KP_Up => Key::NumPad8, key::XKB_KEY_KP_Up => Key::NumPad8,
key::KP_Prior => Key::NumPad9, key::XKB_KEY_KP_Prior => Key::NumPad9,
key::KP_Decimal => Key::NumPadDot, key::XKB_KEY_KP_Decimal => Key::NumPadDot,
key::KP_Divide => Key::NumPadSlash, key::XKB_KEY_KP_Divide => Key::NumPadSlash,
key::KP_Multiply => Key::NumPadAsterisk, key::XKB_KEY_KP_Multiply => Key::NumPadAsterisk,
key::KP_Subtract => Key::NumPadMinus, key::XKB_KEY_KP_Subtract => Key::NumPadMinus,
key::KP_Add => Key::NumPadPlus, key::XKB_KEY_KP_Add => Key::NumPadPlus,
key::KP_Enter => Key::NumPadEnter, key::XKB_KEY_KP_Enter => Key::NumPadEnter,
_ => { _ => {
// Ignore other keys // 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 { match keymap {
KeymapFormat::XkbV1 => { KeymapFormat::XkbV1 => {
unsafe { unsafe {
@ -1083,21 +1128,30 @@ impl Window {
0, 0,
); );
if addr == libc::MAP_FAILED { 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 keymap = ffi_dispatch!(
let kb_map_ptr = xkbcommon_sys::xkb_keymap_new_from_string( XKBH,
ctx, xkb_keymap_new_from_string,
addr as _, context,
xkbcommon_sys::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1, addr as *const _,
0, 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); libc::munmap(addr, len as usize);
// Wrap keymap if keymap.is_null() {
Ok(Keymap::from_ptr(kb_map_ptr as *mut _ as *mut c_void)) Err(Error::WindowCreate(
"Received invalid keymap from compositor.".to_owned(),
))
} else {
Ok(keymap)
}
} }
} }
_ => unimplemented!("Only XKB keymaps are supported"), _ => unimplemented!("Only XKB keymaps are supported"),
@ -1224,3 +1278,13 @@ unsafe impl raw_window_handle::HasRawWindowHandle for Window {
raw_window_handle::RawWindowHandle::Wayland(handle) 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;