use windows::Win32::{ Foundation::{LPARAM, WPARAM}, UI::{ Input::KeyboardAndMouse::{GetKeyState, VIRTUAL_KEY}, WindowsAndMessaging::{ WHEEL_DELTA, WM_KEYDOWN, WM_KEYUP, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_XBUTTONDOWN, WM_XBUTTONUP, }, }, }; use crate::{hiword, loword}; use super::Platform; pub struct WinEvent<'a>(pub &'a (), pub u32, pub WPARAM, pub LPARAM); impl<'a> types::IntoEvt for WinEvent<'a> { fn to_evt(&self, _win: ::WinRef<'_>) -> Option { fn other(wparam: usize) -> types::Button { let id = hiword(wparam as u32); let id = id % 255; let id = id as u8; types::Button::Mouse(id) } let msg = self.1; let wparam = self.2 .0; let lparam = self.3 .0; let (button, phase) = match msg { WM_LBUTTONDOWN => (types::Button::Left, types::Phase::Start), WM_LBUTTONUP => (types::Button::Left, types::Phase::End), WM_RBUTTONDOWN => (types::Button::Right, types::Phase::Start), WM_RBUTTONUP => (types::Button::Right, types::Phase::End), WM_MBUTTONDOWN => (types::Button::Middle, types::Phase::Start), WM_MBUTTONUP => (types::Button::Middle, types::Phase::End), WM_XBUTTONDOWN => (other(wparam), types::Phase::Start), WM_XBUTTONUP => (other(wparam), types::Phase::End), WM_MOUSEMOVE => (types::Button::Left, types::Phase::Update), _ => return None, }; let point = (loword(lparam as _) as _, hiword(lparam as _) as _); let metas = conv_metas(); Some(types::EvtMouse::new(button, phase, point, metas)) } } impl<'a> types::IntoEvt for WinEvent<'a> { fn to_evt(&self, _win: ::WinRef<'_>) -> Option { let msg = self.1; let wparam = self.2 .0; let value = (wparam >> 16) as i16; let value = value as f32 / WHEEL_DELTA as f32; match msg { WM_MOUSEWHEEL => types::EvtWheel::Line(0., value, 0.).into(), WM_MOUSEHWHEEL => types::EvtWheel::Line(value, 0., 0.).into(), _ => None, } } } impl<'a> types::IntoEvt for WinEvent<'a> { fn to_evt(&self, _win: ::WinRef<'_>) -> Option { let msg = self.1; let wparam = self.2 .0; let lparam = self.3 .0; let state = match msg { WM_KEYDOWN => types::State::Down, WM_KEYUP => types::State::Up, WM_SYSKEYDOWN => types::State::Down, WM_SYSKEYUP => types::State::Up, _ => return None, }; // https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-keydown // https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input let vkey = loword(wparam as _); let _repeat = (lparam & 0xFFFF) as u16; let mut scancode = ((lparam >> 16) & 0xff) as u16; // The extended-key flag indicates whether the keystroke message originated from one of the additional keys on the Enhanced 101/102-key keyboard. // The extended keys consist of the ALT and CTRL keys on the right-hand side of the keyboard; // the INS, DEL, HOME, END, PAGE UP, PAGE DOWN, and arrow keys in the clusters to the left of the numeric keypad; // the NUM LOCK key; the BREAK (CTRL+PAUSE) key; // the PRINT SCRN key; // and the divide (/) and ENTER keys in the numeric keypad. // The right-hand SHIFT key is not considered an extended-key, it has a separate scan code instead. // // If specified, the scan code consists of a sequence of two bytes, where the first byte has a value of 0xE0. let extended = ((lparam >> 24) & 0x01) != 0; if extended { scancode = 0xE000 | scancode; } // The context code indicates whether the ALT key was down when the keystroke message was generated. // The code is 1 if the ALT key was down and 0 if it was up. let _context_code = (lparam >> 29) & 0x01 != 0; // The previous key-state flag indicates whether the key that generated the keystroke message was previously up or down. // It is 1 if the key was previously down and 0 if the key was previously up. // You can use this flag to identify keystroke messages generated by the keyboard's automatic repeat feature. // This flag is set to 1 for WM_KEYDOWN and WM_SYSKEYDOWN keystroke messages generated by the automatic repeat feature. // It is always set to 1 for WM_KEYUP and WM_SYSKEYUP messages. let previous_state = (lparam >> 30) & 0x01 != 0; // The transition-state flag indicates whether pressing a key or releasing a key generated the keystroke message. // This flag is always set to 0 for WM_KEYDOWN and WM_SYSKEYDOWN messages; // it is always set to 1 for WM_KEYUP and WM_SYSKEYUP messages. let _transition_state = (lparam >> 31) & 0x01 != 0; let code = conv_code(scancode); let key = conv_key(vkey); let location = code.into(); let metas = conv_metas(); let repeat = match msg { WM_KEYDOWN => previous_state, WM_SYSKEYDOWN => previous_state, _ => false, }; let composing = false; Some(types::EvtKey::new(key, code, state, location, metas, repeat, composing)) } } impl<'a> types::IntoEvt for WinEvent<'a> { fn to_evt(&self, _win: ::WinRef<'_>) -> Option { // TODO None } } fn conv_metas() -> types::Metas { use windows::Win32::UI::Input::KeyboardAndMouse as VK; fn key_pressed(vkey: VIRTUAL_KEY) -> bool { unsafe { (GetKeyState(vkey.0 as i32) & (1 << 15)) == (1 << 15) } } let mut metas = types::Metas::EMPTY; if key_pressed(VK::VK_SHIFT) { metas.insert(types::Metas::SHIFT) } if key_pressed(VK::VK_CONTROL) { metas.insert(types::Metas::CONTROL); } if key_pressed(VK::VK_MENU) { metas.insert(types::Metas::ALT); } if key_pressed(VK::VK_LWIN) || key_pressed(VK::VK_RWIN) { metas.insert(types::Metas::META); } metas } fn conv_code(code: u16) -> types::Code { // See: https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html // and: https://www.w3.org/TR/uievents-code/ // and: The widget/NativeKeyToDOMCodeName.h file in the firefox source use types::Code as KeyCode; match code { 0x0029 => KeyCode::Backquote, 0x002b => KeyCode::Backslash, 0x000e => KeyCode::Backspace, 0x001a => KeyCode::BracketLeft, 0x001b => KeyCode::BracketRight, 0x0033 => KeyCode::Comma, 0x000b => KeyCode::Digit0, 0x0002 => KeyCode::Digit1, 0x0003 => KeyCode::Digit2, 0x0004 => KeyCode::Digit3, 0x0005 => KeyCode::Digit4, 0x0006 => KeyCode::Digit5, 0x0007 => KeyCode::Digit6, 0x0008 => KeyCode::Digit7, 0x0009 => KeyCode::Digit8, 0x000a => KeyCode::Digit9, 0x000d => KeyCode::Equal, 0x0056 => KeyCode::IntlBackslash, 0x0073 => KeyCode::IntlRo, 0x007d => KeyCode::IntlYen, 0x001e => KeyCode::KeyA, 0x0030 => KeyCode::KeyB, 0x002e => KeyCode::KeyC, 0x0020 => KeyCode::KeyD, 0x0012 => KeyCode::KeyE, 0x0021 => KeyCode::KeyF, 0x0022 => KeyCode::KeyG, 0x0023 => KeyCode::KeyH, 0x0017 => KeyCode::KeyI, 0x0024 => KeyCode::KeyJ, 0x0025 => KeyCode::KeyK, 0x0026 => KeyCode::KeyL, 0x0032 => KeyCode::KeyM, 0x0031 => KeyCode::KeyN, 0x0018 => KeyCode::KeyO, 0x0019 => KeyCode::KeyP, 0x0010 => KeyCode::KeyQ, 0x0013 => KeyCode::KeyR, 0x001f => KeyCode::KeyS, 0x0014 => KeyCode::KeyT, 0x0016 => KeyCode::KeyU, 0x002f => KeyCode::KeyV, 0x0011 => KeyCode::KeyW, 0x002d => KeyCode::KeyX, 0x0015 => KeyCode::KeyY, 0x002c => KeyCode::KeyZ, 0x000c => KeyCode::Minus, 0x0034 => KeyCode::Period, 0x0028 => KeyCode::Quote, 0x0027 => KeyCode::Semicolon, 0x0035 => KeyCode::Slash, 0x0038 => KeyCode::AltLeft, 0xe038 => KeyCode::AltRight, 0x003a => KeyCode::CapsLock, 0xe05d => KeyCode::ContextMenu, 0x001d => KeyCode::ControlLeft, 0xe01d => KeyCode::ControlRight, 0x001c => KeyCode::Enter, 0xe05b => KeyCode::MetaLeft, 0xe05c => KeyCode::MetaRight, 0x002a => KeyCode::ShiftLeft, 0x0036 => KeyCode::ShiftRight, 0x0039 => KeyCode::Space, 0x000f => KeyCode::Tab, 0x0079 => KeyCode::Convert, 0x0072 => KeyCode::Lang1, // for non-Korean layout 0xe0f2 => KeyCode::Lang1, // for Korean layout 0x0071 => KeyCode::Lang2, // for non-Korean layout 0xe0f1 => KeyCode::Lang2, // for Korean layout 0x0070 => KeyCode::KanaMode, 0x007b => KeyCode::NonConvert, 0xe053 => KeyCode::Delete, 0xe04f => KeyCode::End, 0xe047 => KeyCode::Home, 0xe052 => KeyCode::Insert, 0xe051 => KeyCode::PageDown, 0xe049 => KeyCode::PageUp, 0xe050 => KeyCode::ArrowDown, 0xe04b => KeyCode::ArrowLeft, 0xe04d => KeyCode::ArrowRight, 0xe048 => KeyCode::ArrowUp, 0xe045 => KeyCode::NumLock, 0x0052 => KeyCode::Numpad0, 0x004f => KeyCode::Numpad1, 0x0050 => KeyCode::Numpad2, 0x0051 => KeyCode::Numpad3, 0x004b => KeyCode::Numpad4, 0x004c => KeyCode::Numpad5, 0x004d => KeyCode::Numpad6, 0x0047 => KeyCode::Numpad7, 0x0048 => KeyCode::Numpad8, 0x0049 => KeyCode::Numpad9, 0x004e => KeyCode::NumpadAdd, 0x007e => KeyCode::NumpadComma, 0x0053 => KeyCode::NumpadDecimal, 0xe035 => KeyCode::NumpadDivide, 0xe01c => KeyCode::NumpadEnter, 0x0059 => KeyCode::NumpadEqual, 0x0037 => KeyCode::NumpadMultiply, 0x004a => KeyCode::NumpadSubtract, 0x0001 => KeyCode::Escape, 0x003b => KeyCode::F1, 0x003c => KeyCode::F2, 0x003d => KeyCode::F3, 0x003e => KeyCode::F4, 0x003f => KeyCode::F5, 0x0040 => KeyCode::F6, 0x0041 => KeyCode::F7, 0x0042 => KeyCode::F8, 0x0043 => KeyCode::F9, 0x0044 => KeyCode::F10, 0x0057 => KeyCode::F11, 0x0058 => KeyCode::F12, 0x0064 => KeyCode::F13, 0x0065 => KeyCode::F14, 0x0066 => KeyCode::F15, 0x0067 => KeyCode::F16, 0x0068 => KeyCode::F17, 0x0069 => KeyCode::F18, 0x006a => KeyCode::F19, 0x006b => KeyCode::F20, 0x006c => KeyCode::F21, 0x006d => KeyCode::F22, 0x006e => KeyCode::F23, 0x0076 => KeyCode::F24, 0xe037 => KeyCode::PrintScreen, 0x0054 => KeyCode::PrintScreen, // Alt + PrintScreen 0x0046 => KeyCode::ScrollLock, 0x0045 => KeyCode::Pause, 0xe046 => KeyCode::Pause, // Ctrl + Pause 0xe06a => KeyCode::BrowserBack, 0xe066 => KeyCode::BrowserFavorites, 0xe069 => KeyCode::BrowserForward, 0xe032 => KeyCode::BrowserHome, 0xe067 => KeyCode::BrowserRefresh, 0xe065 => KeyCode::BrowserSearch, 0xe068 => KeyCode::BrowserStop, 0xe06b => KeyCode::LaunchApp1, 0xe021 => KeyCode::LaunchApp2, 0xe06c => KeyCode::LaunchMail, 0xe022 => KeyCode::MediaPlayPause, 0xe06d => KeyCode::MediaSelect, 0xe024 => KeyCode::MediaStop, 0xe019 => KeyCode::MediaTrackNext, 0xe010 => KeyCode::MediaTrackPrevious, 0xe05e => KeyCode::Power, 0xe02e => KeyCode::AudioVolumeDown, 0xe020 => KeyCode::AudioVolumeMute, 0xe030 => KeyCode::AudioVolumeUp, _ => KeyCode::Unidentified(code), } } mod conv_key { use windows::Win32::{ System::SystemServices::{LANG_JAPANESE, LANG_KOREAN}, UI::Input::KeyboardAndMouse::{self as VK, GetKeyboardLayout}, }; use crate::loword; pub fn conv_key(vkey: u16) -> types::Key { let locale_id = unsafe { GetKeyboardLayout(0) }.0 as u64; let primary_lang_id = loword(locale_id as _) & 0x3ff; let is_korean = primary_lang_id as u32 == LANG_KOREAN; let is_japanese = primary_lang_id as u32 == LANG_JAPANESE; use types::Key; match VK::VIRTUAL_KEY(vkey) { VK::VK_LBUTTON => Key::Unidentified(vkey), // Mouse VK::VK_RBUTTON => Key::Unidentified(vkey), // Mouse // I don't think this can be represented with a Key VK::VK_CANCEL => Key::Unidentified(vkey), VK::VK_MBUTTON => Key::Unidentified(vkey), // Mouse VK::VK_XBUTTON1 => Key::Unidentified(vkey), // Mouse VK::VK_XBUTTON2 => Key::Unidentified(vkey), // Mouse VK::VK_BACK => Key::Backspace, VK::VK_TAB => Key::Tab, VK::VK_CLEAR => Key::Clear, VK::VK_RETURN => Key::Enter, VK::VK_SHIFT => Key::Shift, VK::VK_CONTROL => Key::Control, VK::VK_MENU => Key::Alt, VK::VK_PAUSE => Key::Pause, VK::VK_CAPITAL => Key::CapsLock, // VK::VK_HANGEUL => Key::HangulMode, // Deprecated in favour of VK::VK_HANGUL // VK::VK_HANGUL and VK::VK_KANA are defined as the same constant, therefore // we use appropriate conditions to differentiate between them VK::VK_HANGUL if is_korean => Key::HangulMode, VK::VK_KANA if is_japanese => Key::KanaMode, VK::VK_JUNJA => Key::JunjaMode, VK::VK_FINAL => Key::FinalMode, // VK::VK_HANJA and VK::VK_KANJI are defined as the same constant, therefore // we use appropriate conditions to differentiate between them VK::VK_HANJA if is_korean => Key::HanjaMode, VK::VK_KANJI if is_japanese => Key::KanjiMode, VK::VK_ESCAPE => Key::Escape, VK::VK_CONVERT => Key::Convert, VK::VK_NONCONVERT => Key::NonConvert, VK::VK_ACCEPT => Key::Accept, VK::VK_MODECHANGE => Key::ModeChange, VK::VK_SPACE => Key::Character(" ".into()), VK::VK_PRIOR => Key::PageUp, VK::VK_NEXT => Key::PageDown, VK::VK_END => Key::End, VK::VK_HOME => Key::Home, VK::VK_LEFT => Key::ArrowLeft, VK::VK_UP => Key::ArrowUp, VK::VK_RIGHT => Key::ArrowRight, VK::VK_DOWN => Key::ArrowDown, VK::VK_SELECT => Key::Select, VK::VK_PRINT => Key::Print, VK::VK_EXECUTE => Key::Execute, VK::VK_SNAPSHOT => Key::PrintScreen, VK::VK_INSERT => Key::Insert, VK::VK_DELETE => Key::Delete, VK::VK_HELP => Key::Help, VK::VK_0 => Key::Character("0".into()), VK::VK_1 => Key::Character("1".into()), VK::VK_2 => Key::Character("2".into()), VK::VK_3 => Key::Character("3".into()), VK::VK_4 => Key::Character("4".into()), VK::VK_5 => Key::Character("5".into()), VK::VK_6 => Key::Character("6".into()), VK::VK_7 => Key::Character("7".into()), VK::VK_8 => Key::Character("8".into()), VK::VK_9 => Key::Character("9".into()), VK::VK_A => Key::Character("a".into()), VK::VK_B => Key::Character("b".into()), VK::VK_C => Key::Character("c".into()), VK::VK_D => Key::Character("d".into()), VK::VK_E => Key::Character("e".into()), VK::VK_F => Key::Character("f".into()), VK::VK_G => Key::Character("g".into()), VK::VK_H => Key::Character("h".into()), VK::VK_I => Key::Character("i".into()), VK::VK_J => Key::Character("j".into()), VK::VK_K => Key::Character("k".into()), VK::VK_L => Key::Character("l".into()), VK::VK_M => Key::Character("m".into()), VK::VK_N => Key::Character("n".into()), VK::VK_O => Key::Character("o".into()), VK::VK_P => Key::Character("p".into()), VK::VK_Q => Key::Character("q".into()), VK::VK_R => Key::Character("r".into()), VK::VK_S => Key::Character("s".into()), VK::VK_T => Key::Character("t".into()), VK::VK_U => Key::Character("u".into()), VK::VK_V => Key::Character("v".into()), VK::VK_W => Key::Character("w".into()), VK::VK_X => Key::Character("x".into()), VK::VK_Y => Key::Character("y".into()), VK::VK_Z => Key::Character("z".into()), VK::VK_LWIN => Key::Super, VK::VK_RWIN => Key::Super, VK::VK_APPS => Key::ContextMenu, VK::VK_SLEEP => Key::Standby, // Numpad keys produce characters VK::VK_NUMPAD0 => Key::Character("0".into()), VK::VK_NUMPAD1 => Key::Character("1".into()), VK::VK_NUMPAD2 => Key::Character("2".into()), VK::VK_NUMPAD3 => Key::Character("3".into()), VK::VK_NUMPAD4 => Key::Character("4".into()), VK::VK_NUMPAD5 => Key::Character("5".into()), VK::VK_NUMPAD6 => Key::Character("6".into()), VK::VK_NUMPAD7 => Key::Character("7".into()), VK::VK_NUMPAD8 => Key::Character("8".into()), VK::VK_NUMPAD9 => Key::Character("9".into()), VK::VK_MULTIPLY => Key::Character("*".into()), VK::VK_ADD => Key::Character("+".into()), VK::VK_SEPARATOR => Key::Character("|".into()), VK::VK_SUBTRACT => Key::Character("-".into()), VK::VK_DECIMAL => Key::Character(".".into()), VK::VK_DIVIDE => Key::Character("/".into()), VK::VK_F1 => Key::F1, VK::VK_F2 => Key::F2, VK::VK_F3 => Key::F3, VK::VK_F4 => Key::F4, VK::VK_F5 => Key::F5, VK::VK_F6 => Key::F6, VK::VK_F7 => Key::F7, VK::VK_F8 => Key::F8, VK::VK_F9 => Key::F9, VK::VK_F10 => Key::F10, VK::VK_F11 => Key::F11, VK::VK_F12 => Key::F12, VK::VK_F13 => Key::F13, VK::VK_F14 => Key::F14, VK::VK_F15 => Key::F15, VK::VK_F16 => Key::F16, VK::VK_F17 => Key::F17, VK::VK_F18 => Key::F18, VK::VK_F19 => Key::F19, VK::VK_F20 => Key::F20, VK::VK_F21 => Key::F21, VK::VK_F22 => Key::F22, VK::VK_F23 => Key::F23, VK::VK_F24 => Key::F24, VK::VK_NAVIGATION_VIEW => Key::Unidentified(vkey), VK::VK_NAVIGATION_MENU => Key::Unidentified(vkey), VK::VK_NAVIGATION_UP => Key::Unidentified(vkey), VK::VK_NAVIGATION_DOWN => Key::Unidentified(vkey), VK::VK_NAVIGATION_LEFT => Key::Unidentified(vkey), VK::VK_NAVIGATION_RIGHT => Key::Unidentified(vkey), VK::VK_NAVIGATION_ACCEPT => Key::Unidentified(vkey), VK::VK_NAVIGATION_CANCEL => Key::Unidentified(vkey), VK::VK_NUMLOCK => Key::NumLock, VK::VK_SCROLL => Key::ScrollLock, VK::VK_OEM_NEC_EQUAL => Key::Unidentified(vkey), // VK::VK_OEM_FJ_JISHO => Key::Unidentified(vkey), // Conflicts with `VK::VK_OEM_NEC_EQUAL` VK::VK_OEM_FJ_MASSHOU => Key::Unidentified(vkey), VK::VK_OEM_FJ_TOUROKU => Key::Unidentified(vkey), VK::VK_OEM_FJ_LOYA => Key::Unidentified(vkey), VK::VK_OEM_FJ_ROYA => Key::Unidentified(vkey), VK::VK_LSHIFT => Key::Shift, VK::VK_RSHIFT => Key::Shift, VK::VK_LCONTROL => Key::Control, VK::VK_RCONTROL => Key::Control, VK::VK_LMENU => Key::Alt, VK::VK_RMENU => Key::Alt, VK::VK_BROWSER_BACK => Key::BrowserBack, VK::VK_BROWSER_FORWARD => Key::BrowserForward, VK::VK_BROWSER_REFRESH => Key::BrowserRefresh, VK::VK_BROWSER_STOP => Key::BrowserStop, VK::VK_BROWSER_SEARCH => Key::BrowserSearch, VK::VK_BROWSER_FAVORITES => Key::BrowserFavorites, VK::VK_BROWSER_HOME => Key::BrowserHome, VK::VK_VOLUME_MUTE => Key::AudioVolumeMute, VK::VK_VOLUME_DOWN => Key::AudioVolumeDown, VK::VK_VOLUME_UP => Key::AudioVolumeUp, VK::VK_MEDIA_NEXT_TRACK => Key::MediaTrackNext, VK::VK_MEDIA_PREV_TRACK => Key::MediaTrackPrevious, VK::VK_MEDIA_STOP => Key::MediaStop, VK::VK_MEDIA_PLAY_PAUSE => Key::MediaPlayPause, VK::VK_LAUNCH_MAIL => Key::LaunchMail, VK::VK_LAUNCH_MEDIA_SELECT => Key::LaunchMediaPlayer, VK::VK_LAUNCH_APP1 => Key::LaunchApplication1, VK::VK_LAUNCH_APP2 => Key::LaunchApplication2, // This function only converts "non-printable" VK::VK_OEM_1 => Key::Unidentified(vkey), VK::VK_OEM_PLUS => Key::Unidentified(vkey), VK::VK_OEM_COMMA => Key::Unidentified(vkey), VK::VK_OEM_MINUS => Key::Unidentified(vkey), VK::VK_OEM_PERIOD => Key::Unidentified(vkey), VK::VK_OEM_2 => Key::Unidentified(vkey), VK::VK_OEM_3 => Key::Unidentified(vkey), VK::VK_GAMEPAD_A => Key::Unidentified(vkey), VK::VK_GAMEPAD_B => Key::Unidentified(vkey), VK::VK_GAMEPAD_X => Key::Unidentified(vkey), VK::VK_GAMEPAD_Y => Key::Unidentified(vkey), VK::VK_GAMEPAD_RIGHT_SHOULDER => Key::Unidentified(vkey), VK::VK_GAMEPAD_LEFT_SHOULDER => Key::Unidentified(vkey), VK::VK_GAMEPAD_LEFT_TRIGGER => Key::Unidentified(vkey), VK::VK_GAMEPAD_RIGHT_TRIGGER => Key::Unidentified(vkey), VK::VK_GAMEPAD_DPAD_UP => Key::Unidentified(vkey), VK::VK_GAMEPAD_DPAD_DOWN => Key::Unidentified(vkey), VK::VK_GAMEPAD_DPAD_LEFT => Key::Unidentified(vkey), VK::VK_GAMEPAD_DPAD_RIGHT => Key::Unidentified(vkey), VK::VK_GAMEPAD_MENU => Key::Unidentified(vkey), VK::VK_GAMEPAD_VIEW => Key::Unidentified(vkey), VK::VK_GAMEPAD_LEFT_THUMBSTICK_BUTTON => Key::Unidentified(vkey), VK::VK_GAMEPAD_RIGHT_THUMBSTICK_BUTTON => Key::Unidentified(vkey), VK::VK_GAMEPAD_LEFT_THUMBSTICK_UP => Key::Unidentified(vkey), VK::VK_GAMEPAD_LEFT_THUMBSTICK_DOWN => Key::Unidentified(vkey), VK::VK_GAMEPAD_LEFT_THUMBSTICK_RIGHT => Key::Unidentified(vkey), VK::VK_GAMEPAD_LEFT_THUMBSTICK_LEFT => Key::Unidentified(vkey), VK::VK_GAMEPAD_RIGHT_THUMBSTICK_UP => Key::Unidentified(vkey), VK::VK_GAMEPAD_RIGHT_THUMBSTICK_DOWN => Key::Unidentified(vkey), VK::VK_GAMEPAD_RIGHT_THUMBSTICK_RIGHT => Key::Unidentified(vkey), VK::VK_GAMEPAD_RIGHT_THUMBSTICK_LEFT => Key::Unidentified(vkey), // This function only converts "non-printable" VK::VK_OEM_4 => Key::Unidentified(vkey), VK::VK_OEM_5 => Key::Unidentified(vkey), VK::VK_OEM_6 => Key::Unidentified(vkey), VK::VK_OEM_7 => Key::Unidentified(vkey), VK::VK_OEM_8 => Key::Unidentified(vkey), VK::VK_OEM_AX => Key::Unidentified(vkey), VK::VK_OEM_102 => Key::Unidentified(vkey), VK::VK_ICO_HELP => Key::Unidentified(vkey), VK::VK_ICO_00 => Key::Unidentified(vkey), VK::VK_PROCESSKEY => Key::Process, VK::VK_ICO_CLEAR => Key::Unidentified(vkey), VK::VK_PACKET => Key::Unidentified(vkey), VK::VK_OEM_RESET => Key::Unidentified(vkey), VK::VK_OEM_JUMP => Key::Unidentified(vkey), VK::VK_OEM_PA1 => Key::Unidentified(vkey), VK::VK_OEM_PA2 => Key::Unidentified(vkey), VK::VK_OEM_PA3 => Key::Unidentified(vkey), VK::VK_OEM_WSCTRL => Key::Unidentified(vkey), VK::VK_OEM_CUSEL => Key::Unidentified(vkey), VK::VK_OEM_ATTN => Key::Attn, VK::VK_OEM_FINISH => { if is_japanese { Key::Katakana } else { // This matches IE and Firefox behaviour according to // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values // At the time of writing, there is no `NamedKey::Finish` variant as // Finish is not mentioned at https://w3c.github.io/uievents-key/ // Also see: https://github.com/pyfisch/keyboard-types/issues/9 Key::Unidentified(vkey) } } VK::VK_OEM_COPY => Key::Copy, VK::VK_OEM_AUTO => Key::Hankaku, VK::VK_OEM_ENLW => Key::Zenkaku, VK::VK_OEM_BACKTAB => Key::Romaji, VK::VK_ATTN => Key::KanaMode, VK::VK_CRSEL => Key::CrSel, VK::VK_EXSEL => Key::ExSel, VK::VK_EREOF => Key::EraseEof, VK::VK_PLAY => Key::Play, VK::VK_ZOOM => Key::ZoomToggle, VK::VK_NONAME => Key::Unidentified(vkey), VK::VK_PA1 => Key::Unidentified(vkey), VK::VK_OEM_CLEAR => Key::Clear, _ => Key::Unidentified(vkey), } // types::Key::Unidentified } } use conv_key::*;