diff --git a/bin/darkwallet/src/editbox.rs b/bin/darkwallet/src/editbox.rs index b28658893..39b942a83 100644 --- a/bin/darkwallet/src/editbox.rs +++ b/bin/darkwallet/src/editbox.rs @@ -1,6 +1,8 @@ use miniquad::{KeyMods, UniformType, MouseButton, window}; use log::info; -use std::{io::Cursor, sync::{Arc, Mutex}}; +use std::{ + collections::HashMap, + io::Cursor, sync::{Arc, Mutex}, time::{Instant, Duration}}; use darkfi_serial::Decodable; use freetype as ft; @@ -10,6 +12,69 @@ use crate::{error::{Error, Result}, prop::{ const CURSOR_WIDTH: f32 = 4.; +struct PressedKeysSmoothRepeat { + /// When holding keys, we track from start and last sent time. + /// This is useful for initial delay and smooth scrolling. + pressed_keys: HashMap, + /// Initial delay before allowing keys + start_delay: u32, + /// Minimum time between repeated keys + step_time: u32, +} + +impl PressedKeysSmoothRepeat { + fn new(start_delay: u32, step_time: u32) -> Self { + Self { + pressed_keys: HashMap::new(), + start_delay, + step_time + } + } + + fn key_down(&mut self, key: &str, repeat: bool) -> u32 { + if !repeat { + return 1; + } + + // Insert key if not exists + if !self.pressed_keys.contains_key(key) { + self.pressed_keys.insert(key.to_string(), RepeatingKeyTimer::new()); + } + + let repeater = self.pressed_keys.get_mut(key).expect("repeat map"); + repeater.update(self.start_delay, self.step_time) + } + + fn key_up(&mut self, key: &str) { + self.pressed_keys.remove(key); + } +} + +struct RepeatingKeyTimer { + start: Instant, + actions: u32, +} + +impl RepeatingKeyTimer { + fn new() -> Self { + Self { + start: Instant::now(), + actions: 0 + } + } + + fn update(&mut self, start_delay: u32, step_time: u32) -> u32 { + let elapsed = self.start.elapsed().as_millis(); + if elapsed < start_delay as u128 { + return 0 + } + let total_actions = ((elapsed - start_delay as u128) / step_time as u128) as u32; + let remaining_actions = total_actions - self.actions; + self.actions = total_actions; + remaining_actions + } +} + pub type EditBoxPtr = Arc; pub struct EditBox { @@ -28,11 +93,13 @@ pub struct EditBox { world_rect: Mutex>, glyphs: Mutex>, text_shaper: TextShaper, + key_repeat: Mutex, } impl EditBox { pub fn new(scene_graph: &mut SceneGraph, node_id: SceneNodeId, font_faces: Vec) -> Result { let node = scene_graph.get_node(node_id).unwrap(); + let node_name = node.name.clone(); let is_active = PropertyBool::wrap(node, "is_active", 0)?; let debug = PropertyBool::wrap(node, "debug", 0)?; let baseline = PropertyFloat32::wrap(node, "baseline", 0)?; @@ -65,12 +132,13 @@ impl EditBox { world_rect: Mutex::new(Rectangle { x: 0., y: 0., w: 0., h: 0. }), glyphs: Mutex::new(vec![]), text_shaper, + key_repeat: Mutex::new(PressedKeysSmoothRepeat::new(400, 50)), }); self_.regen_glyphs().unwrap(); let weak_self = Arc::downgrade(&self_); - let slot = Slot { - name: "editbox::key_down".to_string(), + let slot_key_down = Slot { + name: format!("{}::key_down", node_name), func: Box::new(move |data| { let mut cur = Cursor::new(&data); let keymods = KeyMods { @@ -84,7 +152,26 @@ impl EditBox { let self_ = weak_self.upgrade(); if let Some(self_) = self_ { - self_.key_press(key, keymods, repeat); + self_.key_down(key, keymods, repeat); + } + }), + }; + let weak_self = Arc::downgrade(&self_); + let slot_key_up = Slot { + name: format!("{}::key_up", node_name), + func: Box::new(move |data| { + let mut cur = Cursor::new(&data); + let keymods = KeyMods { + shift: Decodable::decode(&mut cur).unwrap(), + ctrl: Decodable::decode(&mut cur).unwrap(), + alt: Decodable::decode(&mut cur).unwrap(), + logo: Decodable::decode(&mut cur).unwrap(), + }; + let key = String::decode(&mut cur).unwrap(); + + let self_ = weak_self.upgrade(); + if let Some(self_) = self_ { + self_.key_up(key, keymods); } }), }; @@ -93,11 +180,12 @@ impl EditBox { scene_graph .lookup_node_mut("/window/input/keyboard") .expect("no keyboard attached!"); - keyb_node.register("key_down", slot); + keyb_node.register("key_down", slot_key_down); + keyb_node.register("key_up", slot_key_up); let weak_self = Arc::downgrade(&self_); let slot_btn_down = Slot { - name: "editbox::mouse_button_down".to_string(), + name: format!("{}::mouse_button_down", node_name), func: Box::new(move |data| { let mut cur = Cursor::new(&data); let button = MouseButton::from_u8(u8::decode(&mut cur).unwrap()); @@ -113,7 +201,7 @@ impl EditBox { let weak_self = Arc::downgrade(&self_); let slot_btn_up = Slot { - name: "editbox::mouse_button_up".to_string(), + name: format!("{}::mouse_button_up", node_name), func: Box::new(move |data| { let mut cur = Cursor::new(&data); let button = MouseButton::from_u8(u8::decode(&mut cur).unwrap()); @@ -129,7 +217,7 @@ impl EditBox { let weak_self = Arc::downgrade(&self_); let slot_move = Slot { - name: "editbox::mouse_move".to_string(), + name: format!("{}::mouse_move", node_name), func: Box::new(move |data| { let mut cur = Cursor::new(&data); let x = f32::decode(&mut cur).unwrap(); @@ -325,14 +413,21 @@ impl EditBox { Ok(()) } - fn key_press(self: Arc, key: String, mods: KeyMods, repeat: bool) { - if repeat { - return; - } + fn key_down(self: Arc, key: String, mods: KeyMods, repeat: bool) { if !self.is_active.get() { return } - match key.as_str() { + let actions = { + let mut repeater = self.key_repeat.lock().unwrap(); + repeater.key_down(&key, repeat) + }; + for _ in 0..actions { + self.do_key_down(&key, &mods) + } + } + + fn do_key_down(&self, key: &str, mods: &KeyMods) { + match key { "PageUp" => { println!("pageup!"); } @@ -429,6 +524,9 @@ impl EditBox { } } + fn insert_char(key: String) { + } + fn copy_highlighted_text(&self) -> Result<()> { let start = self.selected.get_u32(0)? as usize; let end = self.selected.get_u32(1)? as usize; @@ -450,6 +548,11 @@ impl EditBox { Ok(()) } + fn key_up(self: Arc, key: String, mods: KeyMods) { + let mut repeater = self.key_repeat.lock().unwrap(); + repeater.key_up(&key); + } + fn mouse_button_down(self: Arc, button: MouseButton, x: f32, y: f32) { let mouse_pos = Point { x, y }; let rect = self.world_rect.lock().unwrap(); diff --git a/bin/darkwallet/src/gfx.rs b/bin/darkwallet/src/gfx.rs index a2eff4fa3..81c802fbe 100644 --- a/bin/darkwallet/src/gfx.rs +++ b/bin/darkwallet/src/gfx.rs @@ -18,7 +18,7 @@ use crate::{ error::{Error, Result}, editbox, expr::{SExprMachine, SExprVal}, - keysym::MouseButtonAsU8, + keysym::{KeyCodeAsStr, MouseButtonAsU8}, prop::{Property, PropertySubType, PropertyType}, res::{ResourceId, ResourceManager}, scene::{ @@ -288,6 +288,19 @@ impl Stage { ], ) .unwrap(); + keyb.add_signal( + "key_up", + "Key press up event", + vec![ + ("shift", "", PropertyType::Bool), + ("ctrl", "", PropertyType::Bool), + ("alt", "", PropertyType::Bool), + ("logo", "", PropertyType::Bool), + ("repeat", "", PropertyType::Bool), + ("keycode", "", PropertyType::Enum), + ], + ) + .unwrap(); let keyb_id = keyb.id; scene_graph.link(keyb_id, input_id).unwrap(); @@ -1035,140 +1048,30 @@ impl EventHandler for Stage { let mut scene_graph = self.scene_graph.lock().unwrap(); let win = scene_graph.lookup_node_mut("/window/input/keyboard").unwrap(); - let send_key_down = |key: &str| { - let mut data = vec![]; - modifiers.shift.encode(&mut data).unwrap(); - modifiers.ctrl.encode(&mut data).unwrap(); - modifiers.alt.encode(&mut data).unwrap(); - modifiers.logo.encode(&mut data).unwrap(); - repeat.encode(&mut data).unwrap(); - key.encode(&mut data).unwrap(); - win.trigger("key_down", data).unwrap(); - }; + let key = keycode.to_str(); - match keycode { - KeyCode::Space => send_key_down(" "), - KeyCode::Apostrophe => send_key_down("'"), - KeyCode::Comma => send_key_down(","), - KeyCode::Minus => send_key_down("-"), - KeyCode::Period => send_key_down("."), - KeyCode::Slash => send_key_down("/"), - KeyCode::Key0 => send_key_down("0"), - KeyCode::Key1 => send_key_down("1"), - KeyCode::Key2 => send_key_down("2"), - KeyCode::Key3 => send_key_down("3"), - KeyCode::Key4 => send_key_down("4"), - KeyCode::Key5 => send_key_down("5"), - KeyCode::Key6 => send_key_down("6"), - KeyCode::Key7 => send_key_down("7"), - KeyCode::Key8 => send_key_down("8"), - KeyCode::Key9 => send_key_down("9"), - KeyCode::Semicolon => send_key_down(":"), - KeyCode::Equal => send_key_down("="), - KeyCode::A => send_key_down("A"), - KeyCode::B => send_key_down("B"), - KeyCode::C => send_key_down("C"), - KeyCode::D => send_key_down("D"), - KeyCode::E => send_key_down("E"), - KeyCode::F => send_key_down("F"), - KeyCode::G => send_key_down("G"), - KeyCode::H => send_key_down("H"), - KeyCode::I => send_key_down("I"), - KeyCode::J => send_key_down("J"), - KeyCode::K => send_key_down("K"), - KeyCode::L => send_key_down("L"), - KeyCode::M => send_key_down("M"), - KeyCode::N => send_key_down("N"), - KeyCode::O => send_key_down("O"), - KeyCode::P => send_key_down("P"), - KeyCode::Q => send_key_down("Q"), - KeyCode::R => send_key_down("R"), - KeyCode::S => send_key_down("S"), - KeyCode::T => send_key_down("T"), - KeyCode::U => send_key_down("U"), - KeyCode::V => send_key_down("V"), - KeyCode::W => send_key_down("W"), - KeyCode::X => send_key_down("X"), - KeyCode::Y => send_key_down("Y"), - KeyCode::Z => send_key_down("Z"), - KeyCode::LeftBracket => send_key_down("("), - KeyCode::Backslash => send_key_down("\\"), - KeyCode::RightBracket => send_key_down(")"), - KeyCode::GraveAccent => send_key_down("GraveAccent"), - KeyCode::World1 => send_key_down("World1"), - KeyCode::World2 => send_key_down("World2"), - KeyCode::Escape => send_key_down("Escape"), - KeyCode::Enter => send_key_down("Enter"), - KeyCode::Tab => send_key_down("Tab"), - KeyCode::Backspace => send_key_down("Backspace"), - KeyCode::Insert => send_key_down("Insert"), - KeyCode::Delete => send_key_down("Delete"), - KeyCode::Right => send_key_down("Right"), - KeyCode::Left => send_key_down("Left"), - KeyCode::Down => send_key_down("Down"), - KeyCode::Up => send_key_down("Up"), - KeyCode::PageUp => send_key_down("PageUp"), - KeyCode::PageDown => send_key_down("PageDown"), - KeyCode::Home => send_key_down("Home"), - KeyCode::End => send_key_down("End"), - KeyCode::CapsLock => send_key_down("CapsLock"), - KeyCode::ScrollLock => send_key_down("ScrollLock"), - KeyCode::NumLock => send_key_down("NumLock"), - KeyCode::PrintScreen => send_key_down("PrintScreen"), - KeyCode::Pause => send_key_down("Pause"), - KeyCode::F1 => send_key_down("F1"), - KeyCode::F2 => send_key_down("F2"), - KeyCode::F3 => send_key_down("F3"), - KeyCode::F4 => send_key_down("F4"), - KeyCode::F5 => send_key_down("F5"), - KeyCode::F6 => send_key_down("F6"), - KeyCode::F7 => send_key_down("F7"), - KeyCode::F8 => send_key_down("F8"), - KeyCode::F9 => send_key_down("F9"), - KeyCode::F10 => send_key_down("F10"), - KeyCode::F11 => send_key_down("F11"), - KeyCode::F12 => send_key_down("F12"), - KeyCode::F13 => send_key_down("F13"), - KeyCode::F14 => send_key_down("F14"), - KeyCode::F15 => send_key_down("F15"), - KeyCode::F16 => send_key_down("F16"), - KeyCode::F17 => send_key_down("F17"), - KeyCode::F18 => send_key_down("F18"), - KeyCode::F19 => send_key_down("F19"), - KeyCode::F20 => send_key_down("F20"), - KeyCode::F21 => send_key_down("F21"), - KeyCode::F22 => send_key_down("F22"), - KeyCode::F23 => send_key_down("F23"), - KeyCode::F24 => send_key_down("F24"), - KeyCode::F25 => send_key_down("F25"), - KeyCode::Kp0 => send_key_down("Kp0"), - KeyCode::Kp1 => send_key_down("Kp1"), - KeyCode::Kp2 => send_key_down("Kp2"), - KeyCode::Kp3 => send_key_down("Kp3"), - KeyCode::Kp4 => send_key_down("Kp4"), - KeyCode::Kp5 => send_key_down("Kp5"), - KeyCode::Kp6 => send_key_down("Kp6"), - KeyCode::Kp7 => send_key_down("Kp7"), - KeyCode::Kp8 => send_key_down("Kp8"), - KeyCode::Kp9 => send_key_down("Kp9"), - KeyCode::KpDecimal => send_key_down("KpDecimal"), - KeyCode::KpDivide => send_key_down("KpDivide"), - KeyCode::KpMultiply => send_key_down("KpMultiply"), - KeyCode::KpSubtract => send_key_down("KpSubtract"), - KeyCode::KpAdd => send_key_down("KpAdd"), - KeyCode::KpEnter => send_key_down("KpEnter"), - KeyCode::KpEqual => send_key_down("KpEqual"), - KeyCode::LeftShift => send_key_down("LeftShift"), - KeyCode::LeftControl => send_key_down("LeftControl"), - KeyCode::LeftAlt => send_key_down("LeftAlt"), - KeyCode::LeftSuper => send_key_down("LeftSuper"), - KeyCode::RightShift => send_key_down("RightShift"), - KeyCode::RightControl => send_key_down("RightControl"), - KeyCode::RightAlt => send_key_down("RightAlt"), - KeyCode::RightSuper => send_key_down("RightSuper"), - KeyCode::Menu => send_key_down("Menu"), - KeyCode::Unknown => send_key_down("Unknown"), - } + let mut data = vec![]; + modifiers.shift.encode(&mut data).unwrap(); + modifiers.ctrl.encode(&mut data).unwrap(); + modifiers.alt.encode(&mut data).unwrap(); + modifiers.logo.encode(&mut data).unwrap(); + repeat.encode(&mut data).unwrap(); + key.encode(&mut data).unwrap(); + win.trigger("key_down", data).unwrap(); + } + fn key_up_event(&mut self, keycode: KeyCode, modifiers: KeyMods) { + let mut scene_graph = self.scene_graph.lock().unwrap(); + let win = scene_graph.lookup_node_mut("/window/input/keyboard").unwrap(); + + let key = keycode.to_str(); + + let mut data = vec![]; + modifiers.shift.encode(&mut data).unwrap(); + modifiers.ctrl.encode(&mut data).unwrap(); + modifiers.alt.encode(&mut data).unwrap(); + modifiers.logo.encode(&mut data).unwrap(); + key.encode(&mut data).unwrap(); + win.trigger("key_up", data).unwrap(); } fn mouse_motion_event(&mut self, x: f32, y: f32) { let mut scene_graph = self.scene_graph.lock().unwrap(); diff --git a/bin/darkwallet/src/keysym.rs b/bin/darkwallet/src/keysym.rs new file mode 100644 index 000000000..2c7e01f92 --- /dev/null +++ b/bin/darkwallet/src/keysym.rs @@ -0,0 +1,419 @@ +use miniquad::{ + KeyCode, MouseButton +}; + +pub trait KeyCodeAsStr { + fn to_str(&self) -> &str; +} + +impl KeyCodeAsStr for KeyCode { + fn to_str(&self) -> &str { + match self { + Self::Space => " ", + Self::Apostrophe => "'", + Self::Comma => ",", + Self::Minus => "-", + Self::Period => ".", + Self::Slash => "/", + Self::Key0 => "0", + Self::Key1 => "1", + Self::Key2 => "2", + Self::Key3 => "3", + Self::Key4 => "4", + Self::Key5 => "5", + Self::Key6 => "6", + Self::Key7 => "7", + Self::Key8 => "8", + Self::Key9 => "9", + Self::Semicolon => ":", + Self::Equal => "=", + Self::A => "A", + Self::B => "B", + Self::C => "C", + Self::D => "D", + Self::E => "E", + Self::F => "F", + Self::G => "G", + Self::H => "H", + Self::I => "I", + Self::J => "J", + Self::K => "K", + Self::L => "L", + Self::M => "M", + Self::N => "N", + Self::O => "O", + Self::P => "P", + Self::Q => "Q", + Self::R => "R", + Self::S => "S", + Self::T => "T", + Self::U => "U", + Self::V => "V", + Self::W => "W", + Self::X => "X", + Self::Y => "Y", + Self::Z => "Z", + Self::LeftBracket => "(", + Self::Backslash => "\\", + Self::RightBracket => ")", + Self::GraveAccent => "GraveAccent", + Self::World1 => "World1", + Self::World2 => "World2", + Self::Escape => "Escape", + Self::Enter => "Enter", + Self::Tab => "Tab", + Self::Backspace => "Backspace", + Self::Insert => "Insert", + Self::Delete => "Delete", + Self::Right => "Right", + Self::Left => "Left", + Self::Down => "Down", + Self::Up => "Up", + Self::PageUp => "PageUp", + Self::PageDown => "PageDown", + Self::Home => "Home", + Self::End => "End", + Self::CapsLock => "CapsLock", + Self::ScrollLock => "ScrollLock", + Self::NumLock => "NumLock", + Self::PrintScreen => "PrintScreen", + Self::Pause => "Pause", + Self::F1 => "F1", + Self::F2 => "F2", + Self::F3 => "F3", + Self::F4 => "F4", + Self::F5 => "F5", + Self::F6 => "F6", + Self::F7 => "F7", + Self::F8 => "F8", + Self::F9 => "F9", + Self::F10 => "F10", + Self::F11 => "F11", + Self::F12 => "F12", + Self::F13 => "F13", + Self::F14 => "F14", + Self::F15 => "F15", + Self::F16 => "F16", + Self::F17 => "F17", + Self::F18 => "F18", + Self::F19 => "F19", + Self::F20 => "F20", + Self::F21 => "F21", + Self::F22 => "F22", + Self::F23 => "F23", + Self::F24 => "F24", + Self::F25 => "F25", + Self::Kp0 => "Kp0", + Self::Kp1 => "Kp1", + Self::Kp2 => "Kp2", + Self::Kp3 => "Kp3", + Self::Kp4 => "Kp4", + Self::Kp5 => "Kp5", + Self::Kp6 => "Kp6", + Self::Kp7 => "Kp7", + Self::Kp8 => "Kp8", + Self::Kp9 => "Kp9", + Self::KpDecimal => "KpDecimal", + Self::KpDivide => "KpDivide", + Self::KpMultiply => "KpMultiply", + Self::KpSubtract => "KpSubtract", + Self::KpAdd => "KpAdd", + Self::KpEnter => "KpEnter", + Self::KpEqual => "KpEqual", + Self::LeftShift => "LeftShift", + Self::LeftControl => "LeftControl", + Self::LeftAlt => "LeftAlt", + Self::LeftSuper => "LeftSuper", + Self::RightShift => "RightShift", + Self::RightControl => "RightControl", + Self::RightAlt => "RightAlt", + Self::RightSuper => "RightSuper", + Self::Menu => "Menu", + Self::Unknown => "Unknown", + } + } +} + +pub trait KeyCodeAsU16 { + fn to_u16(&self) -> u16; + fn from_u16(keysym: u16) -> Self; +} + +impl KeyCodeAsU16 for KeyCode { + fn to_u16(&self) -> u16 { + match self { + Self::Space => 0x0020, + Self::Apostrophe => 0x0027, + Self::Comma => 0x002c, + Self::Minus => 0x002d, + Self::Period => 0x002e, + Self::Slash => 0x002f, + Self::Key0 => 0x0030, + Self::Key1 => 0x0031, + Self::Key2 => 0x0032, + Self::Key3 => 0x0033, + Self::Key4 => 0x0034, + Self::Key5 => 0x0035, + Self::Key6 => 0x0036, + Self::Key7 => 0x0037, + Self::Key8 => 0x0038, + Self::Key9 => 0x0039, + Self::Semicolon => 0x003b, + Self::Equal => 0x003d, + Self::A => 0x0041, + Self::B => 0x0042, + Self::C => 0x0043, + Self::D => 0x0044, + Self::E => 0x0045, + Self::F => 0x0046, + Self::G => 0x0047, + Self::H => 0x0048, + Self::I => 0x0049, + Self::J => 0x004a, + Self::K => 0x004b, + Self::L => 0x004c, + Self::M => 0x004d, + Self::N => 0x004e, + Self::O => 0x004f, + Self::P => 0x0050, + Self::Q => 0x0051, + Self::R => 0x0052, + Self::S => 0x0053, + Self::T => 0x0054, + Self::U => 0x0055, + Self::V => 0x0056, + Self::W => 0x0057, + Self::X => 0x0058, + Self::Y => 0x0059, + Self::Z => 0x005a, + Self::LeftBracket => 0x005b, + Self::Backslash => 0x005c, + Self::RightBracket => 0x005d, + Self::GraveAccent => 0x0060, + Self::World1 => 0x0100, + Self::World2 => 0x0101, + Self::Escape => 0xff1b, + Self::Enter => 0xff0d, + Self::Tab => 0xff09, + Self::Backspace => 0xff08, + Self::Insert => 0xff63, + Self::Delete => 0xffff, + Self::Right => 0xff53, + Self::Left => 0xff51, + Self::Down => 0xff54, + Self::Up => 0xff52, + Self::PageUp => 0xff55, + Self::PageDown => 0xff56, + Self::Home => 0xff50, + Self::End => 0xff57, + Self::CapsLock => 0xffe5, + Self::ScrollLock => 0xff14, + Self::NumLock => 0xff7f, + Self::PrintScreen => 0xfd1d, + Self::Pause => 0xff13, + Self::F1 => 0xffbe, + Self::F2 => 0xffbf, + Self::F3 => 0xffc0, + Self::F4 => 0xffc1, + Self::F5 => 0xffc2, + Self::F6 => 0xffc3, + Self::F7 => 0xffc4, + Self::F8 => 0xffc5, + Self::F9 => 0xffc6, + Self::F10 => 0xffc7, + Self::F11 => 0xffc8, + Self::F12 => 0xffc9, + Self::F13 => 0xffca, + Self::F14 => 0xffcb, + Self::F15 => 0xffcc, + Self::F16 => 0xffcd, + Self::F17 => 0xffce, + Self::F18 => 0xffcf, + Self::F19 => 0xffd0, + Self::F20 => 0xffd1, + Self::F21 => 0xffd2, + Self::F22 => 0xffd3, + Self::F23 => 0xffd4, + Self::F24 => 0xffd5, + Self::F25 => 0xffd6, + Self::Kp0 => 0xffb0, + Self::Kp1 => 0xffb1, + Self::Kp2 => 0xffb2, + Self::Kp3 => 0xffb3, + Self::Kp4 => 0xffb4, + Self::Kp5 => 0xffb5, + Self::Kp6 => 0xffb6, + Self::Kp7 => 0xffb7, + Self::Kp8 => 0xffb8, + Self::Kp9 => 0xffb9, + Self::KpDecimal => 0xffae, + Self::KpDivide => 0xffaf, + Self::KpMultiply => 0xffaa, + Self::KpSubtract => 0xffad, + Self::KpAdd => 0xffab, + Self::KpEnter => 0xff8d, + Self::KpEqual => 0xffbd, + Self::LeftShift => 0xffe1, + Self::LeftControl => 0xffe3, + Self::LeftAlt => 0xffe9, + Self::LeftSuper => 0xffeb, + Self::RightShift => 0xffe2, + Self::RightControl => 0xffe4, + Self::RightAlt => 0xffea, + Self::RightSuper => 0xffec, + Self::Menu => 0xff67, + Self::Unknown => 0x01ff, + } + } + fn from_u16(keysym: u16) -> Self { + match keysym { + 0x0020 => Self::Space, + 0x0027 => Self::Apostrophe, + 0x002c => Self::Comma, + 0x002d => Self::Minus, + 0x002e => Self::Period, + 0x002f => Self::Slash, + 0x0030 => Self::Key0, + 0x0031 => Self::Key1, + 0x0032 => Self::Key2, + 0x0033 => Self::Key3, + 0x0034 => Self::Key4, + 0x0035 => Self::Key5, + 0x0036 => Self::Key6, + 0x0037 => Self::Key7, + 0x0038 => Self::Key8, + 0x0039 => Self::Key9, + 0x003b => Self::Semicolon, + 0x003d => Self::Equal, + 0x0041 => Self::A, + 0x0042 => Self::B, + 0x0043 => Self::C, + 0x0044 => Self::D, + 0x0045 => Self::E, + 0x0046 => Self::F, + 0x0047 => Self::G, + 0x0048 => Self::H, + 0x0049 => Self::I, + 0x004a => Self::J, + 0x004b => Self::K, + 0x004c => Self::L, + 0x004d => Self::M, + 0x004e => Self::N, + 0x004f => Self::O, + 0x0050 => Self::P, + 0x0051 => Self::Q, + 0x0052 => Self::R, + 0x0053 => Self::S, + 0x0054 => Self::T, + 0x0055 => Self::U, + 0x0056 => Self::V, + 0x0057 => Self::W, + 0x0058 => Self::X, + 0x0059 => Self::Y, + 0x005a => Self::Z, + 0x005b => Self::LeftBracket, + 0x005c => Self::Backslash, + 0x005d => Self::RightBracket, + 0x0060 => Self::GraveAccent, + 0x0100 => Self::World1, + 0x0101 => Self::World2, + 0xff1b => Self::Escape, + 0xff0d => Self::Enter, + 0xff09 => Self::Tab, + 0xff08 => Self::Backspace, + 0xff63 => Self::Insert, + 0xffff => Self::Delete, + 0xff53 => Self::Right, + 0xff51 => Self::Left, + 0xff54 => Self::Down, + 0xff52 => Self::Up, + 0xff55 => Self::PageUp, + 0xff56 => Self::PageDown, + 0xff50 => Self::Home, + 0xff57 => Self::End, + 0xffe5 => Self::CapsLock, + 0xff14 => Self::ScrollLock, + 0xff7f => Self::NumLock, + 0xfd1d => Self::PrintScreen, + 0xff13 => Self::Pause, + 0xffbe => Self::F1, + 0xffbf => Self::F2, + 0xffc0 => Self::F3, + 0xffc1 => Self::F4, + 0xffc2 => Self::F5, + 0xffc3 => Self::F6, + 0xffc4 => Self::F7, + 0xffc5 => Self::F8, + 0xffc6 => Self::F9, + 0xffc7 => Self::F10, + 0xffc8 => Self::F11, + 0xffc9 => Self::F12, + 0xffca => Self::F13, + 0xffcb => Self::F14, + 0xffcc => Self::F15, + 0xffcd => Self::F16, + 0xffce => Self::F17, + 0xffcf => Self::F18, + 0xffd0 => Self::F19, + 0xffd1 => Self::F20, + 0xffd2 => Self::F21, + 0xffd3 => Self::F22, + 0xffd4 => Self::F23, + 0xffd5 => Self::F24, + 0xffd6 => Self::F25, + 0xffb0 => Self::Kp0, + 0xffb1 => Self::Kp1, + 0xffb2 => Self::Kp2, + 0xffb3 => Self::Kp3, + 0xffb4 => Self::Kp4, + 0xffb5 => Self::Kp5, + 0xffb6 => Self::Kp6, + 0xffb7 => Self::Kp7, + 0xffb8 => Self::Kp8, + 0xffb9 => Self::Kp9, + 0xffae => Self::KpDecimal, + 0xffaf => Self::KpDivide, + 0xffaa => Self::KpMultiply, + 0xffad => Self::KpSubtract, + 0xffab => Self::KpAdd, + 0xff8d => Self::KpEnter, + 0xffbd => Self::KpEqual, + 0xffe1 => Self::LeftShift, + 0xffe3 => Self::LeftControl, + 0xffe9 => Self::LeftAlt, + 0xffeb => Self::LeftSuper, + 0xffe2 => Self::RightShift, + 0xffe4 => Self::RightControl, + 0xffea => Self::RightAlt, + 0xffec => Self::RightSuper, + 0xff67 => Self::Menu, + _ => Self::Unknown, + } + } +} + +pub trait MouseButtonAsU8 { + fn to_u8(&self) -> u8; + fn from_u8(btn: u8) -> Self; +} + +impl MouseButtonAsU8 for MouseButton { + fn to_u8(&self) -> u8 { + match self { + Self::Left => 0, + Self::Middle => 1, + Self::Right => 2, + Self::Unknown => 3, + } + } + + fn from_u8(btn: u8) -> Self { + match btn { + 0 => Self::Left, + 1 => Self::Middle, + 2 => Self::Right, + _ => Self::Unknown, + } + } +} +