From ed77661d78522a0ba6ea931b93ff372e98cfa58d Mon Sep 17 00:00:00 2001 From: Diggory Hardy Date: Thu, 19 Oct 2023 15:27:49 +0100 Subject: [PATCH] Revise Key and KeyCode enums Split `Key` into clear categories, like `Named`, `Dead`, Character`, `Unidentified` removing the `#[non_exhaustive]` from the `Key` itself. Similar action was done for the `KeyCode`. Fixes: #2995 Co-authored-by: Kirill Chibisov --- examples/control_flow.rs | 4 +- examples/cursor_grab.rs | 4 +- examples/fullscreen.rs | 4 +- examples/ime.rs | 6 +- examples/multithreaded.rs | 18 +- examples/multiwindow.rs | 25 +- examples/resizable.rs | 4 +- examples/startup_notification.rs | 3 +- examples/web.rs | 6 +- examples/window_debug.rs | 6 +- examples/window_resize_increments.rs | 17 +- examples/window_tabbing.rs | 6 +- src/event.rs | 6 +- src/keyboard.rs | 326 ++++++--- src/platform/scancode.rs | 29 +- src/platform_impl/android/keycodes.rs | 338 ++++----- src/platform_impl/android/mod.rs | 2 +- src/platform_impl/linux/common/keymap.rs | 671 +++++++++--------- src/platform_impl/linux/common/xkb_state.rs | 8 +- src/platform_impl/linux/mod.rs | 10 +- .../linux/x11/event_processor.rs | 2 +- src/platform_impl/macos/event.rs | 165 +++-- src/platform_impl/macos/view.rs | 42 +- src/platform_impl/orbital/event_loop.rs | 22 +- src/platform_impl/web/keyboard.rs | 630 ++++++++-------- src/platform_impl/web/web_sys/canvas.rs | 6 +- src/platform_impl/web/web_sys/event.rs | 12 +- src/platform_impl/windows/event_loop.rs | 72 +- src/platform_impl/windows/keyboard.rs | 64 +- src/platform_impl/windows/keyboard_layout.rs | 247 +++---- tests/serde_objects.rs | 4 +- 31 files changed, 1469 insertions(+), 1290 deletions(-) diff --git a/examples/control_flow.rs b/examples/control_flow.rs index b7537af048..5032d0bffc 100644 --- a/examples/control_flow.rs +++ b/examples/control_flow.rs @@ -10,7 +10,7 @@ use simple_logger::SimpleLogger; use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::{ControlFlow, EventLoop}, - keyboard::Key, + keyboard::{Key, NamedKey}, window::WindowBuilder, }; @@ -88,7 +88,7 @@ fn main() -> Result<(), impl std::error::Error> { request_redraw = !request_redraw; println!("\nrequest_redraw: {request_redraw}\n"); } - Key::Escape => { + Key::Named(NamedKey::Escape) => { close_requested = true; } _ => (), diff --git a/examples/cursor_grab.rs b/examples/cursor_grab.rs index 4bbfea0b1f..27f8edfe8d 100644 --- a/examples/cursor_grab.rs +++ b/examples/cursor_grab.rs @@ -4,7 +4,7 @@ use simple_logger::SimpleLogger; use winit::{ event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, - keyboard::{Key, ModifiersState}, + keyboard::{Key, ModifiersState, NamedKey}, window::{CursorGrabMode, WindowBuilder}, }; @@ -35,7 +35,7 @@ fn main() -> Result<(), impl std::error::Error> { .. } => { let result = match key { - Key::Escape => { + Key::Named(NamedKey::Escape) => { elwt.exit(); Ok(()) } diff --git a/examples/fullscreen.rs b/examples/fullscreen.rs index 4195e99e56..fca98401c9 100644 --- a/examples/fullscreen.rs +++ b/examples/fullscreen.rs @@ -4,7 +4,7 @@ use simple_logger::SimpleLogger; use winit::dpi::PhysicalSize; use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; use winit::event_loop::EventLoop; -use winit::keyboard::Key; +use winit::keyboard::{Key, NamedKey}; use winit::window::{Fullscreen, WindowBuilder}; #[cfg(target_os = "macos")] @@ -65,7 +65,7 @@ fn main() -> Result<(), impl std::error::Error> { }, .. } => match key { - Key::Escape => elwt.exit(), + Key::Named(NamedKey::Escape) => elwt.exit(), // WARNING: Consider using `key_without_modifers()` if available on your platform. // See the `key_binding` example Key::Character(ch) => match ch.to_lowercase().as_str() { diff --git a/examples/ime.rs b/examples/ime.rs index 9e088d6575..79c2416411 100644 --- a/examples/ime.rs +++ b/examples/ime.rs @@ -6,7 +6,7 @@ use winit::{ dpi::{PhysicalPosition, PhysicalSize}, event::{ElementState, Event, Ime, WindowEvent}, event_loop::EventLoop, - keyboard::{Key, KeyCode}, + keyboard::NamedKey, window::{ImePurpose, WindowBuilder}, }; @@ -69,12 +69,12 @@ fn main() -> Result<(), impl std::error::Error> { WindowEvent::KeyboardInput { event, .. } => { println!("key: {event:?}"); - if event.state == ElementState::Pressed && event.physical_key == KeyCode::F2 { + if event.state == ElementState::Pressed && event.logical_key == NamedKey::F2 { ime_allowed = !ime_allowed; window.set_ime_allowed(ime_allowed); println!("\nIME allowed: {ime_allowed}\n"); } - if event.state == ElementState::Pressed && event.logical_key == Key::F3 { + if event.state == ElementState::Pressed && event.logical_key == NamedKey::F3 { ime_purpose = match ime_purpose { ImePurpose::Normal => ImePurpose::Password, ImePurpose::Password => ImePurpose::Terminal, diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index 49ddb50a55..2b02d8fd3c 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -9,7 +9,7 @@ fn main() -> Result<(), impl std::error::Error> { dpi::{PhysicalPosition, PhysicalSize, Position, Size}, event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, - keyboard::{Key, ModifiersState}, + keyboard::{Key, ModifiersState, NamedKey}, window::{CursorGrabMode, CursorIcon, Fullscreen, WindowBuilder, WindowLevel}, }; @@ -65,17 +65,17 @@ fn main() -> Result<(), impl std::error::Error> { }, .. } => { - use Key::{ArrowLeft, ArrowRight}; + use NamedKey::{ArrowLeft, ArrowRight}; window.set_title(&format!("{key:?}")); let state = !modifiers.shift_key(); match key { // Cycle through video modes - Key::ArrowRight | Key::ArrowLeft => { - video_mode_id = match key { - ArrowLeft => video_mode_id.saturating_sub(1), - ArrowRight => (video_modes.len() - 1).min(video_mode_id + 1), - _ => unreachable!(), - }; + Key::Named(ArrowRight) | Key::Named(ArrowLeft) => { + if key == ArrowLeft { + video_mode_id = video_mode_id.saturating_sub(1); + } else if key == ArrowRight { + video_mode_id = (video_modes.len() - 1).min(video_mode_id + 1); + } println!("Picking video mode: {}", video_modes[video_mode_id]); } // WARNING: Consider using `key_without_modifers()` if available on your platform. @@ -185,7 +185,7 @@ fn main() -> Result<(), impl std::error::Error> { event: KeyEvent { state: ElementState::Released, - logical_key: Key::Escape, + logical_key: Key::Named(NamedKey::Escape), .. }, .. diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 3c9def2ba9..07a9b84eef 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -4,9 +4,9 @@ use std::collections::HashMap; use simple_logger::SimpleLogger; use winit::{ - event::{ElementState, Event, KeyEvent, WindowEvent}, + event::{ElementState, Event, WindowEvent}, event_loop::EventLoop, - keyboard::Key, + keyboard::{Key, NamedKey}, window::Window, }; @@ -40,19 +40,18 @@ fn main() -> Result<(), impl std::error::Error> { } } WindowEvent::KeyboardInput { - event: - KeyEvent { - state: ElementState::Pressed, - logical_key: Key::Character(c), - .. - }, + event, is_synthetic: false, .. - } if matches!(c.as_ref(), "n" | "N") => { - let window = Window::new(elwt).unwrap(); - println!("Opened a new window: {:?}", window.id()); - windows.insert(window.id(), window); - } + } if event.state == ElementState::Pressed => match event.logical_key { + Key::Named(NamedKey::Escape) => elwt.exit(), + Key::Character(c) if c == "n" || c == "N" => { + let window = Window::new(elwt).unwrap(); + println!("Opened a new window: {:?}", window.id()); + windows.insert(window.id(), window); + } + _ => (), + }, WindowEvent::RedrawRequested => { if let Some(window) = windows.get(&window_id) { fill::fill_window(window); diff --git a/examples/resizable.rs b/examples/resizable.rs index a0b0df7140..134c34388d 100644 --- a/examples/resizable.rs +++ b/examples/resizable.rs @@ -5,7 +5,7 @@ use winit::{ dpi::LogicalSize, event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, - keyboard::KeyCode, + keyboard::{KeyCode, PhysicalKey}, window::WindowBuilder, }; @@ -34,7 +34,7 @@ fn main() -> Result<(), impl std::error::Error> { WindowEvent::KeyboardInput { event: KeyEvent { - physical_key: KeyCode::Space, + physical_key: PhysicalKey::Code(KeyCode::Space), state: ElementState::Released, .. }, diff --git a/examples/startup_notification.rs b/examples/startup_notification.rs index 5d191e94d2..0cbf4d3652 100644 --- a/examples/startup_notification.rs +++ b/examples/startup_notification.rs @@ -11,7 +11,6 @@ mod example { use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; use winit::event_loop::EventLoop; - use winit::keyboard::Key; use winit::platform::startup_notify::{ EventLoopExtStartupNotify, WindowBuilderExtStartupNotify, WindowExtStartupNotify, }; @@ -46,7 +45,7 @@ mod example { }, .. } => { - if logical_key == Key::Character("n".into()) { + if logical_key == "n" { if let Some(window) = windows.get(&window_id) { // Request a new activation token on this window. // Once we get it we will use it to create a window. diff --git a/examples/web.rs b/examples/web.rs index 7adb18fede..febc903a38 100644 --- a/examples/web.rs +++ b/examples/web.rs @@ -3,7 +3,7 @@ use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, - keyboard::KeyCode, + keyboard::Key, window::{Fullscreen, WindowBuilder}, }; @@ -39,13 +39,13 @@ pub fn main() -> Result<(), impl std::error::Error> { WindowEvent::KeyboardInput { event: KeyEvent { - physical_key: KeyCode::KeyF, + logical_key: Key::Character(c), state: ElementState::Released, .. }, .. }, - } if window_id == window.id() => { + } if window_id == window.id() && c == "f" => { if window.fullscreen().is_some() { window.set_fullscreen(None); } else { diff --git a/examples/window_debug.rs b/examples/window_debug.rs index f170c713f1..c6bf5b9053 100644 --- a/examples/window_debug.rs +++ b/examples/window_debug.rs @@ -7,7 +7,7 @@ use winit::{ dpi::{LogicalSize, PhysicalSize}, event::{DeviceEvent, ElementState, Event, KeyEvent, RawKeyEvent, WindowEvent}, event_loop::{DeviceEvents, EventLoop}, - keyboard::{Key, KeyCode}, + keyboard::{Key, KeyCode, PhysicalKey}, window::{Fullscreen, WindowBuilder}, }; @@ -51,14 +51,14 @@ fn main() -> Result<(), impl std::error::Error> { }), .. } => match physical_key { - KeyCode::KeyM => { + PhysicalKey::Code(KeyCode::KeyM) => { if minimized { minimized = !minimized; window.set_minimized(minimized); window.focus_window(); } } - KeyCode::KeyV => { + PhysicalKey::Code(KeyCode::KeyV) => { if !visible { visible = !visible; window.set_visible(visible); diff --git a/examples/window_resize_increments.rs b/examples/window_resize_increments.rs index 6eba170cda..834050585a 100644 --- a/examples/window_resize_increments.rs +++ b/examples/window_resize_increments.rs @@ -2,9 +2,9 @@ use log::debug; use simple_logger::SimpleLogger; use winit::{ dpi::LogicalSize, - event::{ElementState, Event, KeyEvent, WindowEvent}, + event::{ElementState, Event, WindowEvent}, event_loop::EventLoop, - keyboard::Key, + keyboard::NamedKey, window::WindowBuilder, }; @@ -27,15 +27,10 @@ fn main() -> Result<(), impl std::error::Error> { event_loop.run(move |event, elwt| match event { Event::WindowEvent { event, window_id } if window_id == window.id() => match event { WindowEvent::CloseRequested => elwt.exit(), - WindowEvent::KeyboardInput { - event: - KeyEvent { - logical_key: Key::Space, - state: ElementState::Released, - .. - }, - .. - } => { + WindowEvent::KeyboardInput { event, .. } + if event.logical_key == NamedKey::Space + && event.state == ElementState::Released => + { has_increments = !has_increments; let new_increments = match window.resize_increments() { diff --git a/examples/window_tabbing.rs b/examples/window_tabbing.rs index a99683236b..9413ae9a39 100644 --- a/examples/window_tabbing.rs +++ b/examples/window_tabbing.rs @@ -9,7 +9,7 @@ use simple_logger::SimpleLogger; use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, event_loop::EventLoop, - keyboard::Key, + keyboard::{Key, NamedKey}, platform::macos::{WindowBuilderExtMacOS, WindowExtMacOS}, window::{Window, WindowBuilder}, }; @@ -70,10 +70,10 @@ fn main() -> Result<(), impl std::error::Error> { Key::Character("w") => { let _ = windows.remove(&window_id); } - Key::ArrowRight => { + Key::Named(NamedKey::ArrowRight) => { windows.get(&window_id).unwrap().select_next_tab(); } - Key::ArrowLeft => { + Key::Named(NamedKey::ArrowLeft) => { windows.get(&window_id).unwrap().select_previous_tab(); } Key::Character(ch) => { diff --git a/src/event.rs b/src/event.rs index 5a3998c537..6a4b33cf7f 100644 --- a/src/event.rs +++ b/src/event.rs @@ -671,7 +671,7 @@ pub enum DeviceEvent { #[derive(Debug, Clone, Eq, PartialEq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct RawKeyEvent { - pub physical_key: keyboard::KeyCode, + pub physical_key: keyboard::PhysicalKey, pub state: ElementState, } @@ -703,7 +703,7 @@ pub struct KeyEvent { /// `Fn` and `FnLock` key events are *exceedingly unlikely* to be emitted by Winit. These keys /// are usually handled at the hardware or OS level, and aren't surfaced to applications. If /// you somehow see this in the wild, we'd like to know :) - pub physical_key: keyboard::KeyCode, + pub physical_key: keyboard::PhysicalKey, // Allowing `broken_intra_doc_links` for `logical_key`, because // `key_without_modifiers` is not available on all platforms @@ -743,7 +743,7 @@ pub struct KeyEvent { /// An additional difference from `logical_key` is that /// this field stores the text representation of any key /// that has such a representation. For example when - /// `logical_key` is `Key::Enter`, this field is `Some("\r")`. + /// `logical_key` is `Key::Named(NamedKey::Enter)`, this field is `Some("\r")`. /// /// This is `None` if the current keypress cannot /// be interpreted as text. diff --git a/src/keyboard.rs b/src/keyboard.rs index 40caa476b3..ac6f19c872 100644 --- a/src/keyboard.rs +++ b/src/keyboard.rs @@ -185,26 +185,112 @@ impl std::fmt::Debug for NativeKey { } } +impl From for NativeKey { + #[inline] + fn from(code: NativeKeyCode) -> Self { + match code { + NativeKeyCode::Unidentified => NativeKey::Unidentified, + NativeKeyCode::Android(x) => NativeKey::Android(x), + NativeKeyCode::MacOS(x) => NativeKey::MacOS(x), + NativeKeyCode::Windows(x) => NativeKey::Windows(x), + NativeKeyCode::Xkb(x) => NativeKey::Xkb(x), + } + } +} + +impl PartialEq for NativeKeyCode { + #[allow(clippy::cmp_owned)] // uses less code than direct match; target is stack allocated + #[inline] + fn eq(&self, rhs: &NativeKey) -> bool { + NativeKey::from(*self) == *rhs + } +} + +impl PartialEq for NativeKey { + #[inline] + fn eq(&self, rhs: &NativeKeyCode) -> bool { + rhs == self + } +} + /// Represents the location of a physical key. /// +/// This type is a superset of [`KeyCode`], including an [`Unidentified`](Self::Unidentified) +/// variant. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum PhysicalKey { + /// A known key code + Code(KeyCode), + /// This variant is used when the key cannot be translated to a [`KeyCode`] + /// + /// The native keycode is provided (if available) so you're able to more reliably match + /// key-press and key-release events by hashing the [`PhysicalKey`]. It is also possible to use + /// this for keybinds for non-standard keys, but such keybinds are tied to a given platform. + Unidentified(NativeKeyCode), +} + +impl From for PhysicalKey { + #[inline] + fn from(code: KeyCode) -> Self { + PhysicalKey::Code(code) + } +} + +impl From for PhysicalKey { + #[inline] + fn from(code: NativeKeyCode) -> Self { + PhysicalKey::Unidentified(code) + } +} + +impl PartialEq for PhysicalKey { + #[inline] + fn eq(&self, rhs: &KeyCode) -> bool { + match self { + PhysicalKey::Code(ref code) => code == rhs, + _ => false, + } + } +} + +impl PartialEq for KeyCode { + #[inline] + fn eq(&self, rhs: &PhysicalKey) -> bool { + rhs == self + } +} + +impl PartialEq for PhysicalKey { + #[inline] + fn eq(&self, rhs: &NativeKeyCode) -> bool { + match self { + PhysicalKey::Unidentified(ref code) => code == rhs, + _ => false, + } + } +} + +impl PartialEq for NativeKeyCode { + #[inline] + fn eq(&self, rhs: &PhysicalKey) -> bool { + rhs == self + } +} + +/// Code representing the location of a physical key +/// /// This mostly conforms to the UI Events Specification's [`KeyboardEvent.code`] with a few /// exceptions: /// - The keys that the specification calls "MetaLeft" and "MetaRight" are named "SuperLeft" and /// "SuperRight" here. /// - The key that the specification calls "Super" is reported as `Unidentified` here. -/// - The `Unidentified` variant here, can still identify a key through it's `NativeKeyCode`. /// /// [`KeyboardEvent.code`]: https://w3c.github.io/uievents-code/#code-value-tables #[non_exhaustive] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum KeyCode { - /// This variant is used when the key cannot be translated to any other variant. - /// - /// The native keycode is provided (if available) so you're able to more reliably match - /// key-press and key-release events by hashing the [`KeyCode`]. It is also possible to use - /// this for keybinds for non-standard keys, but such keybinds are tied to a given platform. - Unidentified(NativeKeyCode), /// ` on a US keyboard. This is also called a backtick or grave. /// This is the 半角/全角/漢字 /// (hankaku/zenkaku/kanji) key on Japanese keyboards @@ -648,7 +734,7 @@ pub enum KeyCode { F35, } -/// Key represents the meaning of a keypress. +/// A [`Key::Named`] value /// /// This mostly conforms to the UI Events Specification's [`KeyboardEvent.key`] with a few /// exceptions: @@ -656,32 +742,12 @@ pub enum KeyCode { /// another key which the specification calls `Super`. That does not exist here.) /// - The `Space` variant here, can be identified by the character it generates in the /// specificaiton. -/// - The `Unidentified` variant here, can still identifiy a key through it's `NativeKeyCode`. -/// - The `Dead` variant here, can specify the character which is inserted when pressing the -/// dead-key twice. /// /// [`KeyboardEvent.key`]: https://w3c.github.io/uievents-key/ #[non_exhaustive] -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub enum Key { - /// A key string that corresponds to the character typed by the user, taking into account the - /// user’s current locale setting, and any system-level keyboard mapping overrides that are in - /// effect. - Character(Str), - - /// This variant is used when the key cannot be translated to any other variant. - /// - /// The native key is provided (if available) in order to allow the user to specify keybindings - /// for keys which are not defined by this API, mainly through some sort of UI. - Unidentified(NativeKey), - - /// Contains the text representation of the dead-key when available. - /// - /// ## Platform-specific - /// - **Web:** Always contains `None` - Dead(Option), - +pub enum NamedKey { /// The `Alt` (Alternative) key. /// /// This key enables the alternate modifier function for interpreting concurrent or subsequent @@ -1385,83 +1451,131 @@ pub enum Key { F35, } -macro_rules! map_match { - ( - $to_match:expr, - // Custom match arms - { $( $from:pat => $to:expr ),* }, - // The enum's name - $prefix:path, - // Trivial match arms for unit variants - { $( $t:tt ),* }) => { - match $to_match { - $( $from => $to, )* - $( Key::$t => Key::$t, )* +/// Key represents the meaning of a keypress. +/// +/// This is a superset of the UI Events Specification's [`KeyboardEvent.key`] with +/// additions: +/// - All simple variants are wrapped under the `Named` variant +/// - The `Unidentified` variant here, can still identifiy a key through it's `NativeKeyCode`. +/// - The `Dead` variant here, can specify the character which is inserted when pressing the +/// dead-key twice. +/// +/// [`KeyboardEvent.key`]: https://w3c.github.io/uievents-key/ +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub enum Key { + /// A simple (unparameterised) action + Named(NamedKey), + + /// A key string that corresponds to the character typed by the user, taking into account the + /// user’s current locale setting, and any system-level keyboard mapping overrides that are in + /// effect. + Character(Str), + + /// This variant is used when the key cannot be translated to any other variant. + /// + /// The native key is provided (if available) in order to allow the user to specify keybindings + /// for keys which are not defined by this API, mainly through some sort of UI. + Unidentified(NativeKey), + + /// Contains the text representation of the dead-key when available. + /// + /// ## Platform-specific + /// - **Web:** Always contains `None` + Dead(Option), +} + +impl From for Key { + #[inline] + fn from(action: NamedKey) -> Self { + Key::Named(action) + } +} + +impl From for Key { + #[inline] + fn from(code: NativeKey) -> Self { + Key::Unidentified(code) + } +} + +impl PartialEq for Key { + #[inline] + fn eq(&self, rhs: &NamedKey) -> bool { + match self { + Key::Named(ref a) => a == rhs, + _ => false, } - }; + } +} + +impl> PartialEq for Key { + #[inline] + fn eq(&self, rhs: &str) -> bool { + match self { + Key::Character(ref s) => s == rhs, + _ => false, + } + } +} + +impl> PartialEq<&str> for Key { + #[inline] + fn eq(&self, rhs: &&str) -> bool { + self == *rhs + } +} + +impl PartialEq for Key { + #[inline] + fn eq(&self, rhs: &NativeKey) -> bool { + match self { + Key::Unidentified(ref code) => code == rhs, + _ => false, + } + } +} + +impl PartialEq> for NativeKey { + #[inline] + fn eq(&self, rhs: &Key) -> bool { + rhs == self + } } impl Key { /// Convert `Key::Character(SmolStr)` to `Key::Character(&str)` so you can more easily match on /// `Key`. All other variants remain unchanged. pub fn as_ref(&self) -> Key<&str> { - map_match!( - self, - { - Key::Character(ch) => Key::Character(ch.as_str()), - Key::Dead(d) => Key::Dead(*d), - Key::Unidentified(u) => Key::Unidentified(u.clone()) - }, - Key, - { - Alt, AltGraph, CapsLock, Control, Fn, FnLock, NumLock, ScrollLock, Shift, Symbol, - SymbolLock, Meta, Hyper, Super, Enter, Tab, Space, ArrowDown, ArrowLeft, - ArrowRight, ArrowUp, End, Home, PageDown, PageUp, Backspace, Clear, Copy, CrSel, - Cut, Delete, EraseEof, ExSel, Insert, Paste, Redo, Undo, Accept, Again, Attn, - Cancel, ContextMenu, Escape, Execute, Find, Help, Pause, Play, Props, Select, - ZoomIn, ZoomOut, BrightnessDown, BrightnessUp, Eject, LogOff, Power, PowerOff, - PrintScreen, Hibernate, Standby, WakeUp, AllCandidates, Alphanumeric, CodeInput, - Compose, Convert, FinalMode, GroupFirst, GroupLast, GroupNext, GroupPrevious, - ModeChange, NextCandidate, NonConvert, PreviousCandidate, Process, SingleCandidate, - HangulMode, HanjaMode, JunjaMode, Eisu, Hankaku, Hiragana, HiraganaKatakana, - KanaMode, KanjiMode, Katakana, Romaji, Zenkaku, ZenkakuHankaku, Soft1, Soft2, - Soft3, Soft4, ChannelDown, ChannelUp, Close, MailForward, MailReply, MailSend, - MediaClose, MediaFastForward, MediaPause, MediaPlay, MediaPlayPause, MediaRecord, - MediaRewind, MediaStop, MediaTrackNext, MediaTrackPrevious, New, Open, Print, Save, - SpellCheck, Key11, Key12, AudioBalanceLeft, AudioBalanceRight, AudioBassBoostDown, - AudioBassBoostToggle, AudioBassBoostUp, AudioFaderFront, AudioFaderRear, - AudioSurroundModeNext, AudioTrebleDown, AudioTrebleUp, AudioVolumeDown, - AudioVolumeUp, AudioVolumeMute, MicrophoneToggle, MicrophoneVolumeDown, - MicrophoneVolumeUp, MicrophoneVolumeMute, SpeechCorrectionList, SpeechInputToggle, - LaunchApplication1, LaunchApplication2, LaunchCalendar, LaunchContacts, LaunchMail, - LaunchMediaPlayer, LaunchMusicPlayer, LaunchPhone, LaunchScreenSaver, - LaunchSpreadsheet, LaunchWebBrowser, LaunchWebCam, LaunchWordProcessor, - BrowserBack, BrowserFavorites, BrowserForward, BrowserHome, BrowserRefresh, - BrowserSearch, BrowserStop, AppSwitch, Call, Camera, CameraFocus, EndCall, GoBack, - GoHome, HeadsetHook, LastNumberRedial, Notification, MannerMode, VoiceDial, TV, - TV3DMode, TVAntennaCable, TVAudioDescription, TVAudioDescriptionMixDown, - TVAudioDescriptionMixUp, TVContentsMenu, TVDataService, TVInput, TVInputComponent1, - TVInputComponent2, TVInputComposite1, TVInputComposite2, TVInputHDMI1, - TVInputHDMI2, TVInputHDMI3, TVInputHDMI4, TVInputVGA1, TVMediaContext, TVNetwork, - TVNumberEntry, TVPower, TVRadioService, TVSatellite, TVSatelliteBS, TVSatelliteCS, - TVSatelliteToggle, TVTerrestrialAnalog, TVTerrestrialDigital, TVTimer, AVRInput, - AVRPower, ColorF0Red, ColorF1Green, ColorF2Yellow, ColorF3Blue, ColorF4Grey, - ColorF5Brown, ClosedCaptionToggle, Dimmer, DisplaySwap, DVR, Exit, FavoriteClear0, - FavoriteClear1, FavoriteClear2, FavoriteClear3, FavoriteRecall0, FavoriteRecall1, - FavoriteRecall2, FavoriteRecall3, FavoriteStore0, FavoriteStore1, FavoriteStore2, - FavoriteStore3, Guide, GuideNextDay, GuidePreviousDay, Info, InstantReplay, Link, - ListProgram, LiveContent, Lock, MediaApps, MediaAudioTrack, MediaLast, - MediaSkipBackward, MediaSkipForward, MediaStepBackward, MediaStepForward, - MediaTopMenu, NavigateIn, NavigateNext, NavigateOut, NavigatePrevious, - NextFavoriteChannel, NextUserProfile, OnDemand, Pairing, PinPDown, PinPMove, - PinPToggle, PinPUp, PlaySpeedDown, PlaySpeedReset, PlaySpeedUp, RandomToggle, - RcLowBattery, RecordSpeedNext, RfBypass, ScanChannelsToggle, ScreenModeNext, - Settings, SplitScreenToggle, STBInput, STBPower, Subtitle, Teletext, VideoModeNext, - Wink, ZoomToggle, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, - F16, F17, F18, F19, F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31, - F32, F33, F34, F35 - } - ) + match self { + Key::Named(a) => Key::Named(*a), + Key::Character(ch) => Key::Character(ch.as_str()), + Key::Dead(d) => Key::Dead(*d), + Key::Unidentified(u) => Key::Unidentified(u.clone()), + } + } +} + +impl NamedKey { + /// Convert an action to its approximate textual equivalent. + /// + /// # Examples + /// + /// ``` + /// use winit::keyboard::NamedKey; + /// + /// assert_eq!(NamedKey::Enter.to_text(), Some("\r")); + /// assert_eq!(NamedKey::F20.to_text(), None); + /// ``` + pub fn to_text(&self) -> Option<&str> { + match self { + NamedKey::Enter => Some("\r"), + NamedKey::Backspace => Some("\x08"), + NamedKey::Tab => Some("\t"), + NamedKey::Space => Some(" "), + NamedKey::Escape => Some("\x1b"), + _ => None, + } } } @@ -1471,20 +1585,16 @@ impl Key { /// # Examples /// /// ``` - /// use winit::keyboard::Key; + /// use winit::keyboard::{NamedKey, Key}; /// /// assert_eq!(Key::Character("a".into()).to_text(), Some("a")); - /// assert_eq!(Key::Enter.to_text(), Some("\r")); - /// assert_eq!(Key::F20.to_text(), None); + /// assert_eq!(Key::Named(NamedKey::Enter).to_text(), Some("\r")); + /// assert_eq!(Key::Named(NamedKey::F20).to_text(), None); /// ``` pub fn to_text(&self) -> Option<&str> { match self { + Key::Named(action) => action.to_text(), Key::Character(ch) => Some(ch.as_str()), - Key::Enter => Some("\r"), - Key::Backspace => Some("\x08"), - Key::Tab => Some("\t"), - Key::Space => Some(" "), - Key::Escape => Some("\x1b"), _ => None, } } diff --git a/src/platform/scancode.rs b/src/platform/scancode.rs index 3b4c6804e5..1173d98b5a 100644 --- a/src/platform/scancode.rs +++ b/src/platform/scancode.rs @@ -1,14 +1,14 @@ #![cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform))] -use crate::keyboard::KeyCode; +use crate::keyboard::{KeyCode, PhysicalKey}; // TODO: Describe what this value contains for each platform -/// Additional methods for the [`KeyCode`] type that allow the user to access the platform-specific +/// Additional methods for the [`PhysicalKey`] type that allow the user to access the platform-specific /// scancode. /// -/// [`KeyCode`]: crate::keyboard::KeyCode -pub trait KeyCodeExtScancode { +/// [`PhysicalKey`]: crate::keyboard::PhysicalKey +pub trait PhysicalKeyExtScancode { /// The raw value of the platform-specific physical key identifier. /// /// Returns `Some(key_id)` if the conversion was succesful; returns `None` otherwise. @@ -18,13 +18,28 @@ pub trait KeyCodeExtScancode { /// - **Wayland/X11**: A 32-bit linux scancode, which is X11/Wayland keycode subtracted by 8. fn to_scancode(self) -> Option; - /// Constructs a `KeyCode` from a platform-specific physical key identifier. + /// Constructs a `PhysicalKey` from a platform-specific physical key identifier. /// - /// Note that this conversion may be lossy, i.e. converting the returned `KeyCode` back + /// Note that this conversion may be lossy, i.e. converting the returned `PhysicalKey` back /// using `to_scancode` might not yield the original value. /// /// ## Platform-specific /// - **Wayland/X11**: A 32-bit linux scancode. When building from X11/Wayland keycode subtract /// `8` to get the value you wanted. - fn from_scancode(scancode: u32) -> KeyCode; + fn from_scancode(scancode: u32) -> PhysicalKey; +} + +impl PhysicalKeyExtScancode for KeyCode +where + PhysicalKey: PhysicalKeyExtScancode, +{ + #[inline] + fn from_scancode(scancode: u32) -> PhysicalKey { + ::from_scancode(scancode) + } + + #[inline] + fn to_scancode(self) -> Option { + ::to_scancode(PhysicalKey::Code(self)) + } } diff --git a/src/platform_impl/android/keycodes.rs b/src/platform_impl/android/keycodes.rs index b9731d60ad..b1b60089c0 100644 --- a/src/platform_impl/android/keycodes.rs +++ b/src/platform_impl/android/keycodes.rs @@ -3,10 +3,10 @@ use android_activity::{ AndroidApp, }; -use crate::keyboard::{Key, KeyCode, KeyLocation, NativeKey, NativeKeyCode}; +use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey}; -pub fn to_physical_keycode(keycode: Keycode) -> KeyCode { - match keycode { +pub fn to_physical_key(keycode: Keycode) -> PhysicalKey { + PhysicalKey::Code(match keycode { Keycode::A => KeyCode::KeyA, Keycode::B => KeyCode::KeyB, Keycode::C => KeyCode::KeyC, @@ -155,8 +155,8 @@ pub fn to_physical_keycode(keycode: Keycode) -> KeyCode { Keycode::Sleep => KeyCode::Sleep, // what about SoftSleep? Keycode::Wakeup => KeyCode::WakeUp, - keycode => KeyCode::Unidentified(NativeKeyCode::Android(keycode.into())), - } + keycode => return PhysicalKey::Unidentified(NativeKeyCode::Android(keycode.into())), + }) } /// Tries to map the `key_event` to a `KeyMapChar` containing a unicode character or dead key accent @@ -231,10 +231,10 @@ pub fn to_logical(key_char: Option, keycode: Keycode) -> Key { None | Some(KeyMapChar::None) => match keycode { // Using `BrowserHome` instead of `GoHome` according to // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values - Home => Key::BrowserHome, - Back => Key::BrowserBack, - Call => Key::Call, - Endcall => Key::EndCall, + Home => Key::Named(NamedKey::BrowserHome), + Back => Key::Named(NamedKey::BrowserBack), + Call => Key::Named(NamedKey::Call), + Endcall => Key::Named(NamedKey::EndCall), //------------------------------------------------------------------------------- // These should be redundant because they should have already been matched @@ -291,81 +291,81 @@ pub fn to_logical(key_char: Option, keycode: Keycode) -> Key { At => Key::Character("@".into()), Plus => Key::Character("+".into()), //------------------------------------------------------------------------------- - DpadUp => Key::ArrowUp, - DpadDown => Key::ArrowDown, - DpadLeft => Key::ArrowLeft, - DpadRight => Key::ArrowRight, - DpadCenter => Key::Enter, - - VolumeUp => Key::AudioVolumeUp, - VolumeDown => Key::AudioVolumeDown, - Power => Key::Power, - Camera => Key::Camera, - Clear => Key::Clear, - - AltLeft => Key::Alt, - AltRight => Key::Alt, - ShiftLeft => Key::Shift, - ShiftRight => Key::Shift, - Tab => Key::Tab, - Space => Key::Space, - Sym => Key::Symbol, - Explorer => Key::LaunchWebBrowser, - Envelope => Key::LaunchMail, - Enter => Key::Enter, - Del => Key::Backspace, + DpadUp => Key::Named(NamedKey::ArrowUp), + DpadDown => Key::Named(NamedKey::ArrowDown), + DpadLeft => Key::Named(NamedKey::ArrowLeft), + DpadRight => Key::Named(NamedKey::ArrowRight), + DpadCenter => Key::Named(NamedKey::Enter), + + VolumeUp => Key::Named(NamedKey::AudioVolumeUp), + VolumeDown => Key::Named(NamedKey::AudioVolumeDown), + Power => Key::Named(NamedKey::Power), + Camera => Key::Named(NamedKey::Camera), + Clear => Key::Named(NamedKey::Clear), + + AltLeft => Key::Named(NamedKey::Alt), + AltRight => Key::Named(NamedKey::Alt), + ShiftLeft => Key::Named(NamedKey::Shift), + ShiftRight => Key::Named(NamedKey::Shift), + Tab => Key::Named(NamedKey::Tab), + Space => Key::Named(NamedKey::Space), + Sym => Key::Named(NamedKey::Symbol), + Explorer => Key::Named(NamedKey::LaunchWebBrowser), + Envelope => Key::Named(NamedKey::LaunchMail), + Enter => Key::Named(NamedKey::Enter), + Del => Key::Named(NamedKey::Backspace), // According to https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_NUM - Num => Key::Alt, - - Headsethook => Key::HeadsetHook, - Focus => Key::CameraFocus, - - Notification => Key::Notification, - Search => Key::BrowserSearch, - MediaPlayPause => Key::MediaPlayPause, - MediaStop => Key::MediaStop, - MediaNext => Key::MediaTrackNext, - MediaPrevious => Key::MediaTrackPrevious, - MediaRewind => Key::MediaRewind, - MediaFastForward => Key::MediaFastForward, - Mute => Key::MicrophoneVolumeMute, - PageUp => Key::PageUp, - PageDown => Key::PageDown, - - Escape => Key::Escape, - ForwardDel => Key::Delete, - CtrlLeft => Key::Control, - CtrlRight => Key::Control, - CapsLock => Key::CapsLock, - ScrollLock => Key::ScrollLock, - MetaLeft => Key::Super, - MetaRight => Key::Super, - Function => Key::Fn, - Sysrq => Key::PrintScreen, - Break => Key::Pause, - MoveHome => Key::Home, - MoveEnd => Key::End, - Insert => Key::Insert, - Forward => Key::BrowserForward, - MediaPlay => Key::MediaPlay, - MediaPause => Key::MediaPause, - MediaClose => Key::MediaClose, - MediaEject => Key::Eject, - MediaRecord => Key::MediaRecord, - F1 => Key::F1, - F2 => Key::F2, - F3 => Key::F3, - F4 => Key::F4, - F5 => Key::F5, - F6 => Key::F6, - F7 => Key::F7, - F8 => Key::F8, - F9 => Key::F9, - F10 => Key::F10, - F11 => Key::F11, - F12 => Key::F12, - NumLock => Key::NumLock, + Num => Key::Named(NamedKey::Alt), + + Headsethook => Key::Named(NamedKey::HeadsetHook), + Focus => Key::Named(NamedKey::CameraFocus), + + Notification => Key::Named(NamedKey::Notification), + Search => Key::Named(NamedKey::BrowserSearch), + MediaPlayPause => Key::Named(NamedKey::MediaPlayPause), + MediaStop => Key::Named(NamedKey::MediaStop), + MediaNext => Key::Named(NamedKey::MediaTrackNext), + MediaPrevious => Key::Named(NamedKey::MediaTrackPrevious), + MediaRewind => Key::Named(NamedKey::MediaRewind), + MediaFastForward => Key::Named(NamedKey::MediaFastForward), + Mute => Key::Named(NamedKey::MicrophoneVolumeMute), + PageUp => Key::Named(NamedKey::PageUp), + PageDown => Key::Named(NamedKey::PageDown), + + Escape => Key::Named(NamedKey::Escape), + ForwardDel => Key::Named(NamedKey::Delete), + CtrlLeft => Key::Named(NamedKey::Control), + CtrlRight => Key::Named(NamedKey::Control), + CapsLock => Key::Named(NamedKey::CapsLock), + ScrollLock => Key::Named(NamedKey::ScrollLock), + MetaLeft => Key::Named(NamedKey::Super), + MetaRight => Key::Named(NamedKey::Super), + Function => Key::Named(NamedKey::Fn), + Sysrq => Key::Named(NamedKey::PrintScreen), + Break => Key::Named(NamedKey::Pause), + MoveHome => Key::Named(NamedKey::Home), + MoveEnd => Key::Named(NamedKey::End), + Insert => Key::Named(NamedKey::Insert), + Forward => Key::Named(NamedKey::BrowserForward), + MediaPlay => Key::Named(NamedKey::MediaPlay), + MediaPause => Key::Named(NamedKey::MediaPause), + MediaClose => Key::Named(NamedKey::MediaClose), + MediaEject => Key::Named(NamedKey::Eject), + MediaRecord => Key::Named(NamedKey::MediaRecord), + F1 => Key::Named(NamedKey::F1), + F2 => Key::Named(NamedKey::F2), + F3 => Key::Named(NamedKey::F3), + F4 => Key::Named(NamedKey::F4), + F5 => Key::Named(NamedKey::F5), + F6 => Key::Named(NamedKey::F6), + F7 => Key::Named(NamedKey::F7), + F8 => Key::Named(NamedKey::F8), + F9 => Key::Named(NamedKey::F9), + F10 => Key::Named(NamedKey::F10), + F11 => Key::Named(NamedKey::F11), + F12 => Key::Named(NamedKey::F12), + NumLock => Key::Named(NamedKey::NumLock), Numpad0 => Key::Character("0".into()), Numpad1 => Key::Character("1".into()), Numpad2 => Key::Character("2".into()), @@ -382,97 +382,97 @@ pub fn to_logical(key_char: Option, keycode: Keycode) -> Key { NumpadAdd => Key::Character("+".into()), NumpadDot => Key::Character(".".into()), NumpadComma => Key::Character(",".into()), - NumpadEnter => Key::Enter, + NumpadEnter => Key::Named(NamedKey::Enter), NumpadEquals => Key::Character("=".into()), NumpadLeftParen => Key::Character("(".into()), NumpadRightParen => Key::Character(")".into()), - VolumeMute => Key::AudioVolumeMute, - Info => Key::Info, - ChannelUp => Key::ChannelUp, - ChannelDown => Key::ChannelDown, - ZoomIn => Key::ZoomIn, - ZoomOut => Key::ZoomOut, - Tv => Key::TV, - Guide => Key::Guide, - Dvr => Key::DVR, - Bookmark => Key::BrowserFavorites, - Captions => Key::ClosedCaptionToggle, - Settings => Key::Settings, - TvPower => Key::TVPower, - TvInput => Key::TVInput, - StbPower => Key::STBPower, - StbInput => Key::STBInput, - AvrPower => Key::AVRPower, - AvrInput => Key::AVRInput, - ProgRed => Key::ColorF0Red, - ProgGreen => Key::ColorF1Green, - ProgYellow => Key::ColorF2Yellow, - ProgBlue => Key::ColorF3Blue, - AppSwitch => Key::AppSwitch, - LanguageSwitch => Key::GroupNext, - MannerMode => Key::MannerMode, - Keycode3dMode => Key::TV3DMode, - Contacts => Key::LaunchContacts, - Calendar => Key::LaunchCalendar, - Music => Key::LaunchMusicPlayer, - Calculator => Key::LaunchApplication2, - ZenkakuHankaku => Key::ZenkakuHankaku, - Eisu => Key::Eisu, - Muhenkan => Key::NonConvert, - Henkan => Key::Convert, - KatakanaHiragana => Key::HiraganaKatakana, - Kana => Key::KanjiMode, - BrightnessDown => Key::BrightnessDown, - BrightnessUp => Key::BrightnessUp, - MediaAudioTrack => Key::MediaAudioTrack, - Sleep => Key::Standby, - Wakeup => Key::WakeUp, - Pairing => Key::Pairing, - MediaTopMenu => Key::MediaTopMenu, - LastChannel => Key::MediaLast, - TvDataService => Key::TVDataService, - VoiceAssist => Key::VoiceDial, - TvRadioService => Key::TVRadioService, - TvTeletext => Key::Teletext, - TvNumberEntry => Key::TVNumberEntry, - TvTerrestrialAnalog => Key::TVTerrestrialAnalog, - TvTerrestrialDigital => Key::TVTerrestrialDigital, - TvSatellite => Key::TVSatellite, - TvSatelliteBs => Key::TVSatelliteBS, - TvSatelliteCs => Key::TVSatelliteCS, - TvSatelliteService => Key::TVSatelliteToggle, - TvNetwork => Key::TVNetwork, - TvAntennaCable => Key::TVAntennaCable, - TvInputHdmi1 => Key::TVInputHDMI1, - TvInputHdmi2 => Key::TVInputHDMI2, - TvInputHdmi3 => Key::TVInputHDMI3, - TvInputHdmi4 => Key::TVInputHDMI4, - TvInputComposite1 => Key::TVInputComposite1, - TvInputComposite2 => Key::TVInputComposite2, - TvInputComponent1 => Key::TVInputComponent1, - TvInputComponent2 => Key::TVInputComponent2, - TvInputVga1 => Key::TVInputVGA1, - TvAudioDescription => Key::TVAudioDescription, - TvAudioDescriptionMixUp => Key::TVAudioDescriptionMixUp, - TvAudioDescriptionMixDown => Key::TVAudioDescriptionMixDown, - TvZoomMode => Key::ZoomToggle, - TvContentsMenu => Key::TVContentsMenu, - TvMediaContextMenu => Key::TVMediaContext, - TvTimerProgramming => Key::TVTimer, - Help => Key::Help, - NavigatePrevious => Key::NavigatePrevious, - NavigateNext => Key::NavigateNext, - NavigateIn => Key::NavigateIn, - NavigateOut => Key::NavigateOut, - MediaSkipForward => Key::MediaSkipForward, - MediaSkipBackward => Key::MediaSkipBackward, - MediaStepForward => Key::MediaStepForward, - MediaStepBackward => Key::MediaStepBackward, - Cut => Key::Cut, - Copy => Key::Copy, - Paste => Key::Paste, - Refresh => Key::BrowserRefresh, + VolumeMute => Key::Named(NamedKey::AudioVolumeMute), + Info => Key::Named(NamedKey::Info), + ChannelUp => Key::Named(NamedKey::ChannelUp), + ChannelDown => Key::Named(NamedKey::ChannelDown), + ZoomIn => Key::Named(NamedKey::ZoomIn), + ZoomOut => Key::Named(NamedKey::ZoomOut), + Tv => Key::Named(NamedKey::TV), + Guide => Key::Named(NamedKey::Guide), + Dvr => Key::Named(NamedKey::DVR), + Bookmark => Key::Named(NamedKey::BrowserFavorites), + Captions => Key::Named(NamedKey::ClosedCaptionToggle), + Settings => Key::Named(NamedKey::Settings), + TvPower => Key::Named(NamedKey::TVPower), + TvInput => Key::Named(NamedKey::TVInput), + StbPower => Key::Named(NamedKey::STBPower), + StbInput => Key::Named(NamedKey::STBInput), + AvrPower => Key::Named(NamedKey::AVRPower), + AvrInput => Key::Named(NamedKey::AVRInput), + ProgRed => Key::Named(NamedKey::ColorF0Red), + ProgGreen => Key::Named(NamedKey::ColorF1Green), + ProgYellow => Key::Named(NamedKey::ColorF2Yellow), + ProgBlue => Key::Named(NamedKey::ColorF3Blue), + AppSwitch => Key::Named(NamedKey::AppSwitch), + LanguageSwitch => Key::Named(NamedKey::GroupNext), + MannerMode => Key::Named(NamedKey::MannerMode), + Keycode3dMode => Key::Named(NamedKey::TV3DMode), + Contacts => Key::Named(NamedKey::LaunchContacts), + Calendar => Key::Named(NamedKey::LaunchCalendar), + Music => Key::Named(NamedKey::LaunchMusicPlayer), + Calculator => Key::Named(NamedKey::LaunchApplication2), + ZenkakuHankaku => Key::Named(NamedKey::ZenkakuHankaku), + Eisu => Key::Named(NamedKey::Eisu), + Muhenkan => Key::Named(NamedKey::NonConvert), + Henkan => Key::Named(NamedKey::Convert), + KatakanaHiragana => Key::Named(NamedKey::HiraganaKatakana), + Kana => Key::Named(NamedKey::KanjiMode), + BrightnessDown => Key::Named(NamedKey::BrightnessDown), + BrightnessUp => Key::Named(NamedKey::BrightnessUp), + MediaAudioTrack => Key::Named(NamedKey::MediaAudioTrack), + Sleep => Key::Named(NamedKey::Standby), + Wakeup => Key::Named(NamedKey::WakeUp), + Pairing => Key::Named(NamedKey::Pairing), + MediaTopMenu => Key::Named(NamedKey::MediaTopMenu), + LastChannel => Key::Named(NamedKey::MediaLast), + TvDataService => Key::Named(NamedKey::TVDataService), + VoiceAssist => Key::Named(NamedKey::VoiceDial), + TvRadioService => Key::Named(NamedKey::TVRadioService), + TvTeletext => Key::Named(NamedKey::Teletext), + TvNumberEntry => Key::Named(NamedKey::TVNumberEntry), + TvTerrestrialAnalog => Key::Named(NamedKey::TVTerrestrialAnalog), + TvTerrestrialDigital => Key::Named(NamedKey::TVTerrestrialDigital), + TvSatellite => Key::Named(NamedKey::TVSatellite), + TvSatelliteBs => Key::Named(NamedKey::TVSatelliteBS), + TvSatelliteCs => Key::Named(NamedKey::TVSatelliteCS), + TvSatelliteService => Key::Named(NamedKey::TVSatelliteToggle), + TvNetwork => Key::Named(NamedKey::TVNetwork), + TvAntennaCable => Key::Named(NamedKey::TVAntennaCable), + TvInputHdmi1 => Key::Named(NamedKey::TVInputHDMI1), + TvInputHdmi2 => Key::Named(NamedKey::TVInputHDMI2), + TvInputHdmi3 => Key::Named(NamedKey::TVInputHDMI3), + TvInputHdmi4 => Key::Named(NamedKey::TVInputHDMI4), + TvInputComposite1 => Key::Named(NamedKey::TVInputComposite1), + TvInputComposite2 => Key::Named(NamedKey::TVInputComposite2), + TvInputComponent1 => Key::Named(NamedKey::TVInputComponent1), + TvInputComponent2 => Key::Named(NamedKey::TVInputComponent2), + TvInputVga1 => Key::Named(NamedKey::TVInputVGA1), + TvAudioDescription => Key::Named(NamedKey::TVAudioDescription), + TvAudioDescriptionMixUp => Key::Named(NamedKey::TVAudioDescriptionMixUp), + TvAudioDescriptionMixDown => Key::Named(NamedKey::TVAudioDescriptionMixDown), + TvZoomMode => Key::Named(NamedKey::ZoomToggle), + TvContentsMenu => Key::Named(NamedKey::TVContentsMenu), + TvMediaContextMenu => Key::Named(NamedKey::TVMediaContext), + TvTimerProgramming => Key::Named(NamedKey::TVTimer), + Help => Key::Named(NamedKey::Help), + NavigatePrevious => Key::Named(NamedKey::NavigatePrevious), + NavigateNext => Key::Named(NamedKey::NavigateNext), + NavigateIn => Key::Named(NamedKey::NavigateIn), + NavigateOut => Key::Named(NamedKey::NavigateOut), + MediaSkipForward => Key::Named(NamedKey::MediaSkipForward), + MediaSkipBackward => Key::Named(NamedKey::MediaSkipBackward), + MediaStepForward => Key::Named(NamedKey::MediaStepForward), + MediaStepBackward => Key::Named(NamedKey::MediaStepBackward), + Cut => Key::Named(NamedKey::Cut), + Copy => Key::Named(NamedKey::Copy), + Paste => Key::Named(NamedKey::Paste), + Refresh => Key::Named(NamedKey::BrowserRefresh), // ----------------------------------------------------------------- // Keycodes that don't have a logical Key mapping diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index a6596ef297..72570c4984 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -456,7 +456,7 @@ impl EventLoop { device_id: event::DeviceId(DeviceId(key.device_id())), event: event::KeyEvent { state, - physical_key: keycodes::to_physical_keycode(keycode), + physical_key: keycodes::to_physical_key(keycode), logical_key: keycodes::to_logical(key_char, keycode), location: keycodes::to_location(keycode), repeat: key.repeat_count() > 0, diff --git a/src/platform_impl/linux/common/keymap.rs b/src/platform_impl/linux/common/keymap.rs index 1527ddc473..c226c0893e 100644 --- a/src/platform_impl/linux/common/keymap.rs +++ b/src/platform_impl/linux/common/keymap.rs @@ -1,18 +1,18 @@ //! Convert XKB keys to Winit keys. -use crate::keyboard::{Key, KeyCode, KeyLocation, NativeKey, NativeKeyCode}; +use crate::keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey}; /// Map the raw X11-style keycode to the `KeyCode` enum. /// /// X11-style keycodes are offset by 8 from the keycodes the Linux kernel uses. -pub fn raw_keycode_to_keycode(keycode: u32) -> KeyCode { +pub fn raw_keycode_to_physicalkey(keycode: u32) -> PhysicalKey { scancode_to_keycode(keycode.saturating_sub(8)) } /// Map the linux scancode to Keycode. /// /// Both X11 and Wayland use keys with `+ 8` offset to linux scancode. -pub fn scancode_to_keycode(scancode: u32) -> KeyCode { +pub fn scancode_to_keycode(scancode: u32) -> PhysicalKey { // The keycode values are taken from linux/include/uapi/linux/input-event-codes.h, as // libxkbcommon's documentation seems to suggest that the keycode values we're interested in // are defined by the Linux kernel. If Winit programs end up being run on other Unix-likes, @@ -21,8 +21,8 @@ pub fn scancode_to_keycode(scancode: u32) -> KeyCode { // Some of the keycodes are likely superfluous for our purposes, and some are ones which are // difficult to test the correctness of, or discover the purpose of. Because of this, they've // either been commented out here, or not included at all. - match scancode { - 0 => KeyCode::Unidentified(NativeKeyCode::Xkb(0)), + PhysicalKey::Code(match scancode { + 0 => return PhysicalKey::Unidentified(NativeKeyCode::Xkb(0)), 1 => KeyCode::Escape, 2 => KeyCode::Digit1, 3 => KeyCode::Digit2, @@ -256,7 +256,7 @@ pub fn scancode_to_keycode(scancode: u32) -> KeyCode { // 237 => KeyCode::BLUETOOTH, // 238 => KeyCode::WLAN, // 239 => KeyCode::UWB, - 240 => KeyCode::Unidentified(NativeKeyCode::Unidentified), + 240 => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified), // 241 => KeyCode::VIDEO_NEXT, // 242 => KeyCode::VIDEO_PREV, // 243 => KeyCode::BRIGHTNESS_CYCLE, @@ -265,14 +265,23 @@ pub fn scancode_to_keycode(scancode: u32) -> KeyCode { // 246 => KeyCode::WWAN, // 247 => KeyCode::RFKILL, // 248 => KeyCode::KEY_MICMUTE, - _ => KeyCode::Unidentified(NativeKeyCode::Xkb(scancode)), - } + _ => return PhysicalKey::Unidentified(NativeKeyCode::Xkb(scancode)), + }) } -pub fn keycode_to_scancode(keycode: KeyCode) -> Option { - match keycode { - KeyCode::Unidentified(NativeKeyCode::Unidentified) => Some(240), - KeyCode::Unidentified(NativeKeyCode::Xkb(raw)) => Some(raw), +pub fn physicalkey_to_scancode(key: PhysicalKey) -> Option { + let code = match key { + PhysicalKey::Code(code) => code, + PhysicalKey::Unidentified(code) => { + return match code { + NativeKeyCode::Unidentified => Some(240), + NativeKeyCode::Xkb(raw) => Some(raw), + _ => None, + }; + } + }; + + match code { KeyCode::Escape => Some(1), KeyCode::Digit1 => Some(2), KeyCode::Digit2 => Some(3), @@ -415,213 +424,213 @@ pub fn keycode_to_scancode(keycode: KeyCode) -> Option { pub fn keysym_to_key(keysym: u32) -> Key { use xkbcommon_dl::keysyms; - match keysym { + Key::Named(match keysym { // TTY function keys - keysyms::BackSpace => Key::Backspace, - keysyms::Tab => Key::Tab, - // keysyms::Linefeed => Key::Linefeed, - keysyms::Clear => Key::Clear, - keysyms::Return => Key::Enter, - keysyms::Pause => Key::Pause, - keysyms::Scroll_Lock => Key::ScrollLock, - keysyms::Sys_Req => Key::PrintScreen, - keysyms::Escape => Key::Escape, - keysyms::Delete => Key::Delete, + keysyms::BackSpace => NamedKey::Backspace, + keysyms::Tab => NamedKey::Tab, + // keysyms::Linefeed => NamedKey::Linefeed, + keysyms::Clear => NamedKey::Clear, + keysyms::Return => NamedKey::Enter, + keysyms::Pause => NamedKey::Pause, + keysyms::Scroll_Lock => NamedKey::ScrollLock, + keysyms::Sys_Req => NamedKey::PrintScreen, + keysyms::Escape => NamedKey::Escape, + keysyms::Delete => NamedKey::Delete, // IME keys - keysyms::Multi_key => Key::Compose, - keysyms::Codeinput => Key::CodeInput, - keysyms::SingleCandidate => Key::SingleCandidate, - keysyms::MultipleCandidate => Key::AllCandidates, - keysyms::PreviousCandidate => Key::PreviousCandidate, + keysyms::Multi_key => NamedKey::Compose, + keysyms::Codeinput => NamedKey::CodeInput, + keysyms::SingleCandidate => NamedKey::SingleCandidate, + keysyms::MultipleCandidate => NamedKey::AllCandidates, + keysyms::PreviousCandidate => NamedKey::PreviousCandidate, // Japanese keys - keysyms::Kanji => Key::KanjiMode, - keysyms::Muhenkan => Key::NonConvert, - keysyms::Henkan_Mode => Key::Convert, - keysyms::Romaji => Key::Romaji, - keysyms::Hiragana => Key::Hiragana, - keysyms::Hiragana_Katakana => Key::HiraganaKatakana, - keysyms::Zenkaku => Key::Zenkaku, - keysyms::Hankaku => Key::Hankaku, - keysyms::Zenkaku_Hankaku => Key::ZenkakuHankaku, - // keysyms::Touroku => Key::Touroku, - // keysyms::Massyo => Key::Massyo, - keysyms::Kana_Lock => Key::KanaMode, - keysyms::Kana_Shift => Key::KanaMode, - keysyms::Eisu_Shift => Key::Alphanumeric, - keysyms::Eisu_toggle => Key::Alphanumeric, + keysyms::Kanji => NamedKey::KanjiMode, + keysyms::Muhenkan => NamedKey::NonConvert, + keysyms::Henkan_Mode => NamedKey::Convert, + keysyms::Romaji => NamedKey::Romaji, + keysyms::Hiragana => NamedKey::Hiragana, + keysyms::Hiragana_Katakana => NamedKey::HiraganaKatakana, + keysyms::Zenkaku => NamedKey::Zenkaku, + keysyms::Hankaku => NamedKey::Hankaku, + keysyms::Zenkaku_Hankaku => NamedKey::ZenkakuHankaku, + // keysyms::Touroku => NamedKey::Touroku, + // keysyms::Massyo => NamedKey::Massyo, + keysyms::Kana_Lock => NamedKey::KanaMode, + keysyms::Kana_Shift => NamedKey::KanaMode, + keysyms::Eisu_Shift => NamedKey::Alphanumeric, + keysyms::Eisu_toggle => NamedKey::Alphanumeric, // NOTE: The next three items are aliases for values we've already mapped. - // keysyms::Kanji_Bangou => Key::CodeInput, - // keysyms::Zen_Koho => Key::AllCandidates, - // keysyms::Mae_Koho => Key::PreviousCandidate, + // keysyms::Kanji_Bangou => NamedKey::CodeInput, + // keysyms::Zen_Koho => NamedKey::AllCandidates, + // keysyms::Mae_Koho => NamedKey::PreviousCandidate, // Cursor control & motion - keysyms::Home => Key::Home, - keysyms::Left => Key::ArrowLeft, - keysyms::Up => Key::ArrowUp, - keysyms::Right => Key::ArrowRight, - keysyms::Down => Key::ArrowDown, - // keysyms::Prior => Key::PageUp, - keysyms::Page_Up => Key::PageUp, - // keysyms::Next => Key::PageDown, - keysyms::Page_Down => Key::PageDown, - keysyms::End => Key::End, - // keysyms::Begin => Key::Begin, + keysyms::Home => NamedKey::Home, + keysyms::Left => NamedKey::ArrowLeft, + keysyms::Up => NamedKey::ArrowUp, + keysyms::Right => NamedKey::ArrowRight, + keysyms::Down => NamedKey::ArrowDown, + // keysyms::Prior => NamedKey::PageUp, + keysyms::Page_Up => NamedKey::PageUp, + // keysyms::Next => NamedKey::PageDown, + keysyms::Page_Down => NamedKey::PageDown, + keysyms::End => NamedKey::End, + // keysyms::Begin => NamedKey::Begin, // Misc. functions - keysyms::Select => Key::Select, - keysyms::Print => Key::PrintScreen, - keysyms::Execute => Key::Execute, - keysyms::Insert => Key::Insert, - keysyms::Undo => Key::Undo, - keysyms::Redo => Key::Redo, - keysyms::Menu => Key::ContextMenu, - keysyms::Find => Key::Find, - keysyms::Cancel => Key::Cancel, - keysyms::Help => Key::Help, - keysyms::Break => Key::Pause, - keysyms::Mode_switch => Key::ModeChange, - // keysyms::script_switch => Key::ModeChange, - keysyms::Num_Lock => Key::NumLock, + keysyms::Select => NamedKey::Select, + keysyms::Print => NamedKey::PrintScreen, + keysyms::Execute => NamedKey::Execute, + keysyms::Insert => NamedKey::Insert, + keysyms::Undo => NamedKey::Undo, + keysyms::Redo => NamedKey::Redo, + keysyms::Menu => NamedKey::ContextMenu, + keysyms::Find => NamedKey::Find, + keysyms::Cancel => NamedKey::Cancel, + keysyms::Help => NamedKey::Help, + keysyms::Break => NamedKey::Pause, + keysyms::Mode_switch => NamedKey::ModeChange, + // keysyms::script_switch => NamedKey::ModeChange, + keysyms::Num_Lock => NamedKey::NumLock, // Keypad keys - // keysyms::KP_Space => Key::Character(" "), - keysyms::KP_Tab => Key::Tab, - keysyms::KP_Enter => Key::Enter, - keysyms::KP_F1 => Key::F1, - keysyms::KP_F2 => Key::F2, - keysyms::KP_F3 => Key::F3, - keysyms::KP_F4 => Key::F4, - keysyms::KP_Home => Key::Home, - keysyms::KP_Left => Key::ArrowLeft, - keysyms::KP_Up => Key::ArrowLeft, - keysyms::KP_Right => Key::ArrowRight, - keysyms::KP_Down => Key::ArrowDown, - // keysyms::KP_Prior => Key::PageUp, - keysyms::KP_Page_Up => Key::PageUp, - // keysyms::KP_Next => Key::PageDown, - keysyms::KP_Page_Down => Key::PageDown, - keysyms::KP_End => Key::End, + // keysyms::KP_Space => return Key::Character(" "), + keysyms::KP_Tab => NamedKey::Tab, + keysyms::KP_Enter => NamedKey::Enter, + keysyms::KP_F1 => NamedKey::F1, + keysyms::KP_F2 => NamedKey::F2, + keysyms::KP_F3 => NamedKey::F3, + keysyms::KP_F4 => NamedKey::F4, + keysyms::KP_Home => NamedKey::Home, + keysyms::KP_Left => NamedKey::ArrowLeft, + keysyms::KP_Up => NamedKey::ArrowLeft, + keysyms::KP_Right => NamedKey::ArrowRight, + keysyms::KP_Down => NamedKey::ArrowDown, + // keysyms::KP_Prior => NamedKey::PageUp, + keysyms::KP_Page_Up => NamedKey::PageUp, + // keysyms::KP_Next => NamedKey::PageDown, + keysyms::KP_Page_Down => NamedKey::PageDown, + keysyms::KP_End => NamedKey::End, // This is the key labeled "5" on the numpad when NumLock is off. - // keysyms::KP_Begin => Key::Begin, - keysyms::KP_Insert => Key::Insert, - keysyms::KP_Delete => Key::Delete, - // keysyms::KP_Equal => Key::Equal, - // keysyms::KP_Multiply => Key::Multiply, - // keysyms::KP_Add => Key::Add, - // keysyms::KP_Separator => Key::Separator, - // keysyms::KP_Subtract => Key::Subtract, - // keysyms::KP_Decimal => Key::Decimal, - // keysyms::KP_Divide => Key::Divide, - - // keysyms::KP_0 => Key::Character("0"), - // keysyms::KP_1 => Key::Character("1"), - // keysyms::KP_2 => Key::Character("2"), - // keysyms::KP_3 => Key::Character("3"), - // keysyms::KP_4 => Key::Character("4"), - // keysyms::KP_5 => Key::Character("5"), - // keysyms::KP_6 => Key::Character("6"), - // keysyms::KP_7 => Key::Character("7"), - // keysyms::KP_8 => Key::Character("8"), - // keysyms::KP_9 => Key::Character("9"), + // keysyms::KP_Begin => NamedKey::Begin, + keysyms::KP_Insert => NamedKey::Insert, + keysyms::KP_Delete => NamedKey::Delete, + // keysyms::KP_Equal => NamedKey::Equal, + // keysyms::KP_Multiply => NamedKey::Multiply, + // keysyms::KP_Add => NamedKey::Add, + // keysyms::KP_Separator => NamedKey::Separator, + // keysyms::KP_Subtract => NamedKey::Subtract, + // keysyms::KP_Decimal => NamedKey::Decimal, + // keysyms::KP_Divide => NamedKey::Divide, + + // keysyms::KP_0 => return Key::Character("0"), + // keysyms::KP_1 => return Key::Character("1"), + // keysyms::KP_2 => return Key::Character("2"), + // keysyms::KP_3 => return Key::Character("3"), + // keysyms::KP_4 => return Key::Character("4"), + // keysyms::KP_5 => return Key::Character("5"), + // keysyms::KP_6 => return Key::Character("6"), + // keysyms::KP_7 => return Key::Character("7"), + // keysyms::KP_8 => return Key::Character("8"), + // keysyms::KP_9 => return Key::Character("9"), // Function keys - keysyms::F1 => Key::F1, - keysyms::F2 => Key::F2, - keysyms::F3 => Key::F3, - keysyms::F4 => Key::F4, - keysyms::F5 => Key::F5, - keysyms::F6 => Key::F6, - keysyms::F7 => Key::F7, - keysyms::F8 => Key::F8, - keysyms::F9 => Key::F9, - keysyms::F10 => Key::F10, - keysyms::F11 => Key::F11, - keysyms::F12 => Key::F12, - keysyms::F13 => Key::F13, - keysyms::F14 => Key::F14, - keysyms::F15 => Key::F15, - keysyms::F16 => Key::F16, - keysyms::F17 => Key::F17, - keysyms::F18 => Key::F18, - keysyms::F19 => Key::F19, - keysyms::F20 => Key::F20, - keysyms::F21 => Key::F21, - keysyms::F22 => Key::F22, - keysyms::F23 => Key::F23, - keysyms::F24 => Key::F24, - keysyms::F25 => Key::F25, - keysyms::F26 => Key::F26, - keysyms::F27 => Key::F27, - keysyms::F28 => Key::F28, - keysyms::F29 => Key::F29, - keysyms::F30 => Key::F30, - keysyms::F31 => Key::F31, - keysyms::F32 => Key::F32, - keysyms::F33 => Key::F33, - keysyms::F34 => Key::F34, - keysyms::F35 => Key::F35, + keysyms::F1 => NamedKey::F1, + keysyms::F2 => NamedKey::F2, + keysyms::F3 => NamedKey::F3, + keysyms::F4 => NamedKey::F4, + keysyms::F5 => NamedKey::F5, + keysyms::F6 => NamedKey::F6, + keysyms::F7 => NamedKey::F7, + keysyms::F8 => NamedKey::F8, + keysyms::F9 => NamedKey::F9, + keysyms::F10 => NamedKey::F10, + keysyms::F11 => NamedKey::F11, + keysyms::F12 => NamedKey::F12, + keysyms::F13 => NamedKey::F13, + keysyms::F14 => NamedKey::F14, + keysyms::F15 => NamedKey::F15, + keysyms::F16 => NamedKey::F16, + keysyms::F17 => NamedKey::F17, + keysyms::F18 => NamedKey::F18, + keysyms::F19 => NamedKey::F19, + keysyms::F20 => NamedKey::F20, + keysyms::F21 => NamedKey::F21, + keysyms::F22 => NamedKey::F22, + keysyms::F23 => NamedKey::F23, + keysyms::F24 => NamedKey::F24, + keysyms::F25 => NamedKey::F25, + keysyms::F26 => NamedKey::F26, + keysyms::F27 => NamedKey::F27, + keysyms::F28 => NamedKey::F28, + keysyms::F29 => NamedKey::F29, + keysyms::F30 => NamedKey::F30, + keysyms::F31 => NamedKey::F31, + keysyms::F32 => NamedKey::F32, + keysyms::F33 => NamedKey::F33, + keysyms::F34 => NamedKey::F34, + keysyms::F35 => NamedKey::F35, // Modifiers - keysyms::Shift_L => Key::Shift, - keysyms::Shift_R => Key::Shift, - keysyms::Control_L => Key::Control, - keysyms::Control_R => Key::Control, - keysyms::Caps_Lock => Key::CapsLock, - // keysyms::Shift_Lock => Key::ShiftLock, - - // keysyms::Meta_L => Key::Meta, - // keysyms::Meta_R => Key::Meta, - keysyms::Alt_L => Key::Alt, - keysyms::Alt_R => Key::Alt, - keysyms::Super_L => Key::Super, - keysyms::Super_R => Key::Super, - keysyms::Hyper_L => Key::Hyper, - keysyms::Hyper_R => Key::Hyper, + keysyms::Shift_L => NamedKey::Shift, + keysyms::Shift_R => NamedKey::Shift, + keysyms::Control_L => NamedKey::Control, + keysyms::Control_R => NamedKey::Control, + keysyms::Caps_Lock => NamedKey::CapsLock, + // keysyms::Shift_Lock => NamedKey::ShiftLock, + + // keysyms::Meta_L => NamedKey::Meta, + // keysyms::Meta_R => NamedKey::Meta, + keysyms::Alt_L => NamedKey::Alt, + keysyms::Alt_R => NamedKey::Alt, + keysyms::Super_L => NamedKey::Super, + keysyms::Super_R => NamedKey::Super, + keysyms::Hyper_L => NamedKey::Hyper, + keysyms::Hyper_R => NamedKey::Hyper, // XKB function and modifier keys - // keysyms::ISO_Lock => Key::IsoLock, - // keysyms::ISO_Level2_Latch => Key::IsoLevel2Latch, - keysyms::ISO_Level3_Shift => Key::AltGraph, - keysyms::ISO_Level3_Latch => Key::AltGraph, - keysyms::ISO_Level3_Lock => Key::AltGraph, - // keysyms::ISO_Level5_Shift => Key::IsoLevel5Shift, - // keysyms::ISO_Level5_Latch => Key::IsoLevel5Latch, - // keysyms::ISO_Level5_Lock => Key::IsoLevel5Lock, - // keysyms::ISO_Group_Shift => Key::IsoGroupShift, - // keysyms::ISO_Group_Latch => Key::IsoGroupLatch, - // keysyms::ISO_Group_Lock => Key::IsoGroupLock, - keysyms::ISO_Next_Group => Key::GroupNext, - // keysyms::ISO_Next_Group_Lock => Key::GroupNextLock, - keysyms::ISO_Prev_Group => Key::GroupPrevious, - // keysyms::ISO_Prev_Group_Lock => Key::GroupPreviousLock, - keysyms::ISO_First_Group => Key::GroupFirst, - // keysyms::ISO_First_Group_Lock => Key::GroupFirstLock, - keysyms::ISO_Last_Group => Key::GroupLast, - // keysyms::ISO_Last_Group_Lock => Key::GroupLastLock, + // keysyms::ISO_Lock => NamedKey::IsoLock, + // keysyms::ISO_Level2_Latch => NamedKey::IsoLevel2Latch, + keysyms::ISO_Level3_Shift => NamedKey::AltGraph, + keysyms::ISO_Level3_Latch => NamedKey::AltGraph, + keysyms::ISO_Level3_Lock => NamedKey::AltGraph, + // keysyms::ISO_Level5_Shift => NamedKey::IsoLevel5Shift, + // keysyms::ISO_Level5_Latch => NamedKey::IsoLevel5Latch, + // keysyms::ISO_Level5_Lock => NamedKey::IsoLevel5Lock, + // keysyms::ISO_Group_Shift => NamedKey::IsoGroupShift, + // keysyms::ISO_Group_Latch => NamedKey::IsoGroupLatch, + // keysyms::ISO_Group_Lock => NamedKey::IsoGroupLock, + keysyms::ISO_Next_Group => NamedKey::GroupNext, + // keysyms::ISO_Next_Group_Lock => NamedKey::GroupNextLock, + keysyms::ISO_Prev_Group => NamedKey::GroupPrevious, + // keysyms::ISO_Prev_Group_Lock => NamedKey::GroupPreviousLock, + keysyms::ISO_First_Group => NamedKey::GroupFirst, + // keysyms::ISO_First_Group_Lock => NamedKey::GroupFirstLock, + keysyms::ISO_Last_Group => NamedKey::GroupLast, + // keysyms::ISO_Last_Group_Lock => NamedKey::GroupLastLock, // - keysyms::ISO_Left_Tab => Key::Tab, - // keysyms::ISO_Move_Line_Up => Key::IsoMoveLineUp, - // keysyms::ISO_Move_Line_Down => Key::IsoMoveLineDown, - // keysyms::ISO_Partial_Line_Up => Key::IsoPartialLineUp, - // keysyms::ISO_Partial_Line_Down => Key::IsoPartialLineDown, - // keysyms::ISO_Partial_Space_Left => Key::IsoPartialSpaceLeft, - // keysyms::ISO_Partial_Space_Right => Key::IsoPartialSpaceRight, - // keysyms::ISO_Set_Margin_Left => Key::IsoSetMarginLeft, - // keysyms::ISO_Set_Margin_Right => Key::IsoSetMarginRight, - // keysyms::ISO_Release_Margin_Left => Key::IsoReleaseMarginLeft, - // keysyms::ISO_Release_Margin_Right => Key::IsoReleaseMarginRight, - // keysyms::ISO_Release_Both_Margins => Key::IsoReleaseBothMargins, - // keysyms::ISO_Fast_Cursor_Left => Key::IsoFastCursorLeft, - // keysyms::ISO_Fast_Cursor_Right => Key::IsoFastCursorRight, - // keysyms::ISO_Fast_Cursor_Up => Key::IsoFastCursorUp, - // keysyms::ISO_Fast_Cursor_Down => Key::IsoFastCursorDown, - // keysyms::ISO_Continuous_Underline => Key::IsoContinuousUnderline, - // keysyms::ISO_Discontinuous_Underline => Key::IsoDiscontinuousUnderline, - // keysyms::ISO_Emphasize => Key::IsoEmphasize, - // keysyms::ISO_Center_Object => Key::IsoCenterObject, - keysyms::ISO_Enter => Key::Enter, + keysyms::ISO_Left_Tab => NamedKey::Tab, + // keysyms::ISO_Move_Line_Up => NamedKey::IsoMoveLineUp, + // keysyms::ISO_Move_Line_Down => NamedKey::IsoMoveLineDown, + // keysyms::ISO_Partial_Line_Up => NamedKey::IsoPartialLineUp, + // keysyms::ISO_Partial_Line_Down => NamedKey::IsoPartialLineDown, + // keysyms::ISO_Partial_Space_Left => NamedKey::IsoPartialSpaceLeft, + // keysyms::ISO_Partial_Space_Right => NamedKey::IsoPartialSpaceRight, + // keysyms::ISO_Set_Margin_Left => NamedKey::IsoSetMarginLeft, + // keysyms::ISO_Set_Margin_Right => NamedKey::IsoSetMarginRight, + // keysyms::ISO_Release_Margin_Left => NamedKey::IsoReleaseMarginLeft, + // keysyms::ISO_Release_Margin_Right => NamedKey::IsoReleaseMarginRight, + // keysyms::ISO_Release_Both_Margins => NamedKey::IsoReleaseBothMargins, + // keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastCursorLeft, + // keysyms::ISO_Fast_Cursor_Right => NamedKey::IsoFastCursorRight, + // keysyms::ISO_Fast_Cursor_Up => NamedKey::IsoFastCursorUp, + // keysyms::ISO_Fast_Cursor_Down => NamedKey::IsoFastCursorDown, + // keysyms::ISO_Continuous_Underline => NamedKey::IsoContinuousUnderline, + // keysyms::ISO_Discontinuous_Underline => NamedKey::IsoDiscontinuousUnderline, + // keysyms::ISO_Emphasize => NamedKey::IsoEmphasize, + // keysyms::ISO_Center_Object => NamedKey::IsoCenterObject, + keysyms::ISO_Enter => NamedKey::Enter, // dead_grave..dead_currency @@ -642,194 +651,194 @@ pub fn keysym_to_key(keysym: u32) -> Key { // ch..C_H // 3270 terminal keys - // keysyms::3270_Duplicate => Key::Duplicate, - // keysyms::3270_FieldMark => Key::FieldMark, - // keysyms::3270_Right2 => Key::Right2, - // keysyms::3270_Left2 => Key::Left2, - // keysyms::3270_BackTab => Key::BackTab, - keysyms::_3270_EraseEOF => Key::EraseEof, - // keysyms::3270_EraseInput => Key::EraseInput, - // keysyms::3270_Reset => Key::Reset, - // keysyms::3270_Quit => Key::Quit, - // keysyms::3270_PA1 => Key::Pa1, - // keysyms::3270_PA2 => Key::Pa2, - // keysyms::3270_PA3 => Key::Pa3, - // keysyms::3270_Test => Key::Test, - keysyms::_3270_Attn => Key::Attn, - // keysyms::3270_CursorBlink => Key::CursorBlink, - // keysyms::3270_AltCursor => Key::AltCursor, - // keysyms::3270_KeyClick => Key::KeyClick, - // keysyms::3270_Jump => Key::Jump, - // keysyms::3270_Ident => Key::Ident, - // keysyms::3270_Rule => Key::Rule, - // keysyms::3270_Copy => Key::Copy, - keysyms::_3270_Play => Key::Play, - // keysyms::3270_Setup => Key::Setup, - // keysyms::3270_Record => Key::Record, - // keysyms::3270_ChangeScreen => Key::ChangeScreen, - // keysyms::3270_DeleteWord => Key::DeleteWord, - keysyms::_3270_ExSelect => Key::ExSel, - keysyms::_3270_CursorSelect => Key::CrSel, - keysyms::_3270_PrintScreen => Key::PrintScreen, - keysyms::_3270_Enter => Key::Enter, - - keysyms::space => Key::Space, + // keysyms::3270_Duplicate => NamedKey::Duplicate, + // keysyms::3270_FieldMark => NamedKey::FieldMark, + // keysyms::3270_Right2 => NamedKey::Right2, + // keysyms::3270_Left2 => NamedKey::Left2, + // keysyms::3270_BackTab => NamedKey::BackTab, + keysyms::_3270_EraseEOF => NamedKey::EraseEof, + // keysyms::3270_EraseInput => NamedKey::EraseInput, + // keysyms::3270_Reset => NamedKey::Reset, + // keysyms::3270_Quit => NamedKey::Quit, + // keysyms::3270_PA1 => NamedKey::Pa1, + // keysyms::3270_PA2 => NamedKey::Pa2, + // keysyms::3270_PA3 => NamedKey::Pa3, + // keysyms::3270_Test => NamedKey::Test, + keysyms::_3270_Attn => NamedKey::Attn, + // keysyms::3270_CursorBlink => NamedKey::CursorBlink, + // keysyms::3270_AltCursor => NamedKey::AltCursor, + // keysyms::3270_KeyClick => NamedKey::KeyClick, + // keysyms::3270_Jump => NamedKey::Jump, + // keysyms::3270_Ident => NamedKey::Ident, + // keysyms::3270_Rule => NamedKey::Rule, + // keysyms::3270_Copy => NamedKey::Copy, + keysyms::_3270_Play => NamedKey::Play, + // keysyms::3270_Setup => NamedKey::Setup, + // keysyms::3270_Record => NamedKey::Record, + // keysyms::3270_ChangeScreen => NamedKey::ChangeScreen, + // keysyms::3270_DeleteWord => NamedKey::DeleteWord, + keysyms::_3270_ExSelect => NamedKey::ExSel, + keysyms::_3270_CursorSelect => NamedKey::CrSel, + keysyms::_3270_PrintScreen => NamedKey::PrintScreen, + keysyms::_3270_Enter => NamedKey::Enter, + + keysyms::space => NamedKey::Space, // exclam..Sinh_kunddaliya // XFree86 - // keysyms::XF86_ModeLock => Key::ModeLock, + // keysyms::XF86_ModeLock => NamedKey::ModeLock, // XFree86 - Backlight controls - keysyms::XF86_MonBrightnessUp => Key::BrightnessUp, - keysyms::XF86_MonBrightnessDown => Key::BrightnessDown, - // keysyms::XF86_KbdLightOnOff => Key::LightOnOff, - // keysyms::XF86_KbdBrightnessUp => Key::KeyboardBrightnessUp, - // keysyms::XF86_KbdBrightnessDown => Key::KeyboardBrightnessDown, + keysyms::XF86_MonBrightnessUp => NamedKey::BrightnessUp, + keysyms::XF86_MonBrightnessDown => NamedKey::BrightnessDown, + // keysyms::XF86_KbdLightOnOff => NamedKey::LightOnOff, + // keysyms::XF86_KbdBrightnessUp => NamedKey::KeyboardBrightnessUp, + // keysyms::XF86_KbdBrightnessDown => NamedKey::KeyboardBrightnessDown, // XFree86 - "Internet" - keysyms::XF86_Standby => Key::Standby, - keysyms::XF86_AudioLowerVolume => Key::AudioVolumeDown, - keysyms::XF86_AudioRaiseVolume => Key::AudioVolumeUp, - keysyms::XF86_AudioPlay => Key::MediaPlay, - keysyms::XF86_AudioStop => Key::MediaStop, - keysyms::XF86_AudioPrev => Key::MediaTrackPrevious, - keysyms::XF86_AudioNext => Key::MediaTrackNext, - keysyms::XF86_HomePage => Key::BrowserHome, - keysyms::XF86_Mail => Key::LaunchMail, - // keysyms::XF86_Start => Key::Start, - keysyms::XF86_Search => Key::BrowserSearch, - keysyms::XF86_AudioRecord => Key::MediaRecord, + keysyms::XF86_Standby => NamedKey::Standby, + keysyms::XF86_AudioLowerVolume => NamedKey::AudioVolumeDown, + keysyms::XF86_AudioRaiseVolume => NamedKey::AudioVolumeUp, + keysyms::XF86_AudioPlay => NamedKey::MediaPlay, + keysyms::XF86_AudioStop => NamedKey::MediaStop, + keysyms::XF86_AudioPrev => NamedKey::MediaTrackPrevious, + keysyms::XF86_AudioNext => NamedKey::MediaTrackNext, + keysyms::XF86_HomePage => NamedKey::BrowserHome, + keysyms::XF86_Mail => NamedKey::LaunchMail, + // keysyms::XF86_Start => NamedKey::Start, + keysyms::XF86_Search => NamedKey::BrowserSearch, + keysyms::XF86_AudioRecord => NamedKey::MediaRecord, // XFree86 - PDA - keysyms::XF86_Calculator => Key::LaunchApplication2, - // keysyms::XF86_Memo => Key::Memo, - // keysyms::XF86_ToDoList => Key::ToDoList, - keysyms::XF86_Calendar => Key::LaunchCalendar, - keysyms::XF86_PowerDown => Key::Power, - // keysyms::XF86_ContrastAdjust => Key::AdjustContrast, - // keysyms::XF86_RockerUp => Key::RockerUp, - // keysyms::XF86_RockerDown => Key::RockerDown, - // keysyms::XF86_RockerEnter => Key::RockerEnter, + keysyms::XF86_Calculator => NamedKey::LaunchApplication2, + // keysyms::XF86_Memo => NamedKey::Memo, + // keysyms::XF86_ToDoList => NamedKey::ToDoList, + keysyms::XF86_Calendar => NamedKey::LaunchCalendar, + keysyms::XF86_PowerDown => NamedKey::Power, + // keysyms::XF86_ContrastAdjust => NamedKey::AdjustContrast, + // keysyms::XF86_RockerUp => NamedKey::RockerUp, + // keysyms::XF86_RockerDown => NamedKey::RockerDown, + // keysyms::XF86_RockerEnter => NamedKey::RockerEnter, // XFree86 - More "Internet" - keysyms::XF86_Back => Key::BrowserBack, - keysyms::XF86_Forward => Key::BrowserForward, - // keysyms::XF86_Stop => Key::Stop, - keysyms::XF86_Refresh => Key::BrowserRefresh, - keysyms::XF86_PowerOff => Key::Power, - keysyms::XF86_WakeUp => Key::WakeUp, - keysyms::XF86_Eject => Key::Eject, - keysyms::XF86_ScreenSaver => Key::LaunchScreenSaver, - keysyms::XF86_WWW => Key::LaunchWebBrowser, - keysyms::XF86_Sleep => Key::Standby, - keysyms::XF86_Favorites => Key::BrowserFavorites, - keysyms::XF86_AudioPause => Key::MediaPause, - // keysyms::XF86_AudioMedia => Key::AudioMedia, - keysyms::XF86_MyComputer => Key::LaunchApplication1, - // keysyms::XF86_VendorHome => Key::VendorHome, - // keysyms::XF86_LightBulb => Key::LightBulb, - // keysyms::XF86_Shop => Key::BrowserShop, - // keysyms::XF86_History => Key::BrowserHistory, - // keysyms::XF86_OpenURL => Key::OpenUrl, - // keysyms::XF86_AddFavorite => Key::AddFavorite, - // keysyms::XF86_HotLinks => Key::HotLinks, - // keysyms::XF86_BrightnessAdjust => Key::BrightnessAdjust, - // keysyms::XF86_Finance => Key::BrowserFinance, - // keysyms::XF86_Community => Key::BrowserCommunity, - keysyms::XF86_AudioRewind => Key::MediaRewind, + keysyms::XF86_Back => NamedKey::BrowserBack, + keysyms::XF86_Forward => NamedKey::BrowserForward, + // keysyms::XF86_Stop => NamedKey::Stop, + keysyms::XF86_Refresh => NamedKey::BrowserRefresh, + keysyms::XF86_PowerOff => NamedKey::Power, + keysyms::XF86_WakeUp => NamedKey::WakeUp, + keysyms::XF86_Eject => NamedKey::Eject, + keysyms::XF86_ScreenSaver => NamedKey::LaunchScreenSaver, + keysyms::XF86_WWW => NamedKey::LaunchWebBrowser, + keysyms::XF86_Sleep => NamedKey::Standby, + keysyms::XF86_Favorites => NamedKey::BrowserFavorites, + keysyms::XF86_AudioPause => NamedKey::MediaPause, + // keysyms::XF86_AudioMedia => NamedKey::AudioMedia, + keysyms::XF86_MyComputer => NamedKey::LaunchApplication1, + // keysyms::XF86_VendorHome => NamedKey::VendorHome, + // keysyms::XF86_LightBulb => NamedKey::LightBulb, + // keysyms::XF86_Shop => NamedKey::BrowserShop, + // keysyms::XF86_History => NamedKey::BrowserHistory, + // keysyms::XF86_OpenURL => NamedKey::OpenUrl, + // keysyms::XF86_AddFavorite => NamedKey::AddFavorite, + // keysyms::XF86_HotLinks => NamedKey::HotLinks, + // keysyms::XF86_BrightnessAdjust => NamedKey::BrightnessAdjust, + // keysyms::XF86_Finance => NamedKey::BrowserFinance, + // keysyms::XF86_Community => NamedKey::BrowserCommunity, + keysyms::XF86_AudioRewind => NamedKey::MediaRewind, // keysyms::XF86_BackForward => Key::???, // XF86_Launch0..XF86_LaunchF // XF86_ApplicationLeft..XF86_CD - keysyms::XF86_Calculater => Key::LaunchApplication2, // Nice typo, libxkbcommon :) + keysyms::XF86_Calculater => NamedKey::LaunchApplication2, // Nice typo, libxkbcommon :) // XF86_Clear - keysyms::XF86_Close => Key::Close, - keysyms::XF86_Copy => Key::Copy, - keysyms::XF86_Cut => Key::Cut, + keysyms::XF86_Close => NamedKey::Close, + keysyms::XF86_Copy => NamedKey::Copy, + keysyms::XF86_Cut => NamedKey::Cut, // XF86_Display..XF86_Documents - keysyms::XF86_Excel => Key::LaunchSpreadsheet, + keysyms::XF86_Excel => NamedKey::LaunchSpreadsheet, // XF86_Explorer..XF86iTouch - keysyms::XF86_LogOff => Key::LogOff, + keysyms::XF86_LogOff => NamedKey::LogOff, // XF86_Market..XF86_MenuPB - keysyms::XF86_MySites => Key::BrowserFavorites, - keysyms::XF86_New => Key::New, + keysyms::XF86_MySites => NamedKey::BrowserFavorites, + keysyms::XF86_New => NamedKey::New, // XF86_News..XF86_OfficeHome - keysyms::XF86_Open => Key::Open, + keysyms::XF86_Open => NamedKey::Open, // XF86_Option - keysyms::XF86_Paste => Key::Paste, - keysyms::XF86_Phone => Key::LaunchPhone, + keysyms::XF86_Paste => NamedKey::Paste, + keysyms::XF86_Phone => NamedKey::LaunchPhone, // XF86_Q - keysyms::XF86_Reply => Key::MailReply, - keysyms::XF86_Reload => Key::BrowserRefresh, + keysyms::XF86_Reply => NamedKey::MailReply, + keysyms::XF86_Reload => NamedKey::BrowserRefresh, // XF86_RotateWindows..XF86_RotationKB - keysyms::XF86_Save => Key::Save, + keysyms::XF86_Save => NamedKey::Save, // XF86_ScrollUp..XF86_ScrollClick - keysyms::XF86_Send => Key::MailSend, - keysyms::XF86_Spell => Key::SpellCheck, - keysyms::XF86_SplitScreen => Key::SplitScreenToggle, + keysyms::XF86_Send => NamedKey::MailSend, + keysyms::XF86_Spell => NamedKey::SpellCheck, + keysyms::XF86_SplitScreen => NamedKey::SplitScreenToggle, // XF86_Support..XF86_User2KB - keysyms::XF86_Video => Key::LaunchMediaPlayer, + keysyms::XF86_Video => NamedKey::LaunchMediaPlayer, // XF86_WheelButton - keysyms::XF86_Word => Key::LaunchWordProcessor, + keysyms::XF86_Word => NamedKey::LaunchWordProcessor, // XF86_Xfer - keysyms::XF86_ZoomIn => Key::ZoomIn, - keysyms::XF86_ZoomOut => Key::ZoomOut, + keysyms::XF86_ZoomIn => NamedKey::ZoomIn, + keysyms::XF86_ZoomOut => NamedKey::ZoomOut, // XF86_Away..XF86_Messenger - keysyms::XF86_WebCam => Key::LaunchWebCam, - keysyms::XF86_MailForward => Key::MailForward, + keysyms::XF86_WebCam => NamedKey::LaunchWebCam, + keysyms::XF86_MailForward => NamedKey::MailForward, // XF86_Pictures - keysyms::XF86_Music => Key::LaunchMusicPlayer, + keysyms::XF86_Music => NamedKey::LaunchMusicPlayer, // XF86_Battery..XF86_UWB // - keysyms::XF86_AudioForward => Key::MediaFastForward, + keysyms::XF86_AudioForward => NamedKey::MediaFastForward, // XF86_AudioRepeat - keysyms::XF86_AudioRandomPlay => Key::RandomToggle, - keysyms::XF86_Subtitle => Key::Subtitle, - keysyms::XF86_AudioCycleTrack => Key::MediaAudioTrack, + keysyms::XF86_AudioRandomPlay => NamedKey::RandomToggle, + keysyms::XF86_Subtitle => NamedKey::Subtitle, + keysyms::XF86_AudioCycleTrack => NamedKey::MediaAudioTrack, // XF86_CycleAngle..XF86_Blue // - keysyms::XF86_Suspend => Key::Standby, - keysyms::XF86_Hibernate => Key::Hibernate, + keysyms::XF86_Suspend => NamedKey::Standby, + keysyms::XF86_Hibernate => NamedKey::Hibernate, // XF86_TouchpadToggle..XF86_TouchpadOff // - keysyms::XF86_AudioMute => Key::AudioVolumeMute, + keysyms::XF86_AudioMute => NamedKey::AudioVolumeMute, // XF86_Switch_VT_1..XF86_Switch_VT_12 // XF86_Ungrab..XF86_ClearGrab - keysyms::XF86_Next_VMode => Key::VideoModeNext, - // keysyms::XF86_Prev_VMode => Key::VideoModePrevious, + keysyms::XF86_Next_VMode => NamedKey::VideoModeNext, + // keysyms::XF86_Prev_VMode => NamedKey::VideoModePrevious, // XF86_LogWindowTree..XF86_LogGrabInfo // SunFA_Grave..SunFA_Cedilla - // keysyms::SunF36 => Key::F36 | Key::F11, - // keysyms::SunF37 => Key::F37 | Key::F12, + // keysyms::SunF36 => NamedKey::F36 | NamedKey::F11, + // keysyms::SunF37 => NamedKey::F37 | NamedKey::F12, - // keysyms::SunSys_Req => Key::PrintScreen, + // keysyms::SunSys_Req => NamedKey::PrintScreen, // The next couple of xkb (until SunStop) are already handled. // SunPrint_Screen..SunPageDown // SunUndo..SunFront - keysyms::SUN_Copy => Key::Copy, - keysyms::SUN_Open => Key::Open, - keysyms::SUN_Paste => Key::Paste, - keysyms::SUN_Cut => Key::Cut, + keysyms::SUN_Copy => NamedKey::Copy, + keysyms::SUN_Open => NamedKey::Open, + keysyms::SUN_Paste => NamedKey::Paste, + keysyms::SUN_Cut => NamedKey::Cut, // SunPowerSwitch - keysyms::SUN_AudioLowerVolume => Key::AudioVolumeDown, - keysyms::SUN_AudioMute => Key::AudioVolumeMute, - keysyms::SUN_AudioRaiseVolume => Key::AudioVolumeUp, + keysyms::SUN_AudioLowerVolume => NamedKey::AudioVolumeDown, + keysyms::SUN_AudioMute => NamedKey::AudioVolumeMute, + keysyms::SUN_AudioRaiseVolume => NamedKey::AudioVolumeUp, // SUN_VideoDegauss - keysyms::SUN_VideoLowerBrightness => Key::BrightnessDown, - keysyms::SUN_VideoRaiseBrightness => Key::BrightnessUp, + keysyms::SUN_VideoLowerBrightness => NamedKey::BrightnessDown, + keysyms::SUN_VideoRaiseBrightness => NamedKey::BrightnessUp, // SunPowerSwitchShift // - 0 => Key::Unidentified(NativeKey::Unidentified), - _ => Key::Unidentified(NativeKey::Xkb(keysym)), - } + 0 => return Key::Unidentified(NativeKey::Unidentified), + _ => return Key::Unidentified(NativeKey::Xkb(keysym)), + }) } pub fn keysym_location(keysym: u32) -> KeyLocation { diff --git a/src/platform_impl/linux/common/xkb_state.rs b/src/platform_impl/linux/common/xkb_state.rs index 7c4449af62..c1a912306c 100644 --- a/src/platform_impl/linux/common/xkb_state.rs +++ b/src/platform_impl/linux/common/xkb_state.rs @@ -22,7 +22,7 @@ use crate::platform_impl::common::keymap; use crate::platform_impl::KeyEventExtra; use crate::{ event::ElementState, - keyboard::{Key, KeyCode, KeyLocation}, + keyboard::{Key, KeyLocation, PhysicalKey}, }; // TODO: Wire this up without using a static `AtomicBool`. @@ -391,7 +391,7 @@ impl KbdState { ) -> KeyEvent { let mut event = KeyEventResults::new(self, keycode, !repeat && state == ElementState::Pressed); - let physical_key = event.keycode(); + let physical_key = event.physical_key(); let (logical_key, location) = event.key(); let text = event.text(); let (key_without_modifiers, _) = event.key_without_modifiers(); @@ -498,8 +498,8 @@ impl<'a> KeyEventResults<'a> { } } - fn keycode(&mut self) -> KeyCode { - keymap::raw_keycode_to_keycode(self.keycode) + fn physical_key(&mut self) -> PhysicalKey { + keymap::raw_keycode_to_physicalkey(self.keycode) } pub fn key(&mut self) -> (Key, KeyLocation) { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index f5de3f7c7e..a6068bc762 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -25,10 +25,10 @@ use crate::{ EventLoopWindowTarget as RootELW, }, icon::Icon, - keyboard::{Key, KeyCode}, + keyboard::{Key, PhysicalKey}, platform::{ modifier_supplement::KeyEventExtModifierSupplement, pump_events::PumpStatus, - scancode::KeyCodeExtScancode, + scancode::PhysicalKeyExtScancode, }, window::{ ActivationToken, CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, @@ -657,13 +657,13 @@ impl KeyEventExtModifierSupplement for KeyEvent { } } -impl KeyCodeExtScancode for KeyCode { - fn from_scancode(scancode: u32) -> KeyCode { +impl PhysicalKeyExtScancode for PhysicalKey { + fn from_scancode(scancode: u32) -> PhysicalKey { common::keymap::scancode_to_keycode(scancode) } fn to_scancode(self) -> Option { - common::keymap::keycode_to_scancode(self) + common::keymap::physicalkey_to_scancode(self) } } diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index f23c1700b8..8aaabca531 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -1201,7 +1201,7 @@ impl EventProcessor { if keycode < KEYCODE_OFFSET as u32 { return; } - let physical_key = keymap::raw_keycode_to_keycode(keycode); + let physical_key = keymap::raw_keycode_to_physicalkey(keycode); callback(Event::DeviceEvent { device_id, diff --git a/src/platform_impl/macos/event.rs b/src/platform_impl/macos/event.rs index 185edbf4c8..af5af175a7 100644 --- a/src/platform_impl/macos/event.rs +++ b/src/platform_impl/macos/event.rs @@ -11,9 +11,12 @@ use super::appkit::{NSEvent, NSEventModifierFlags}; use crate::{ event::{ElementState, KeyEvent, Modifiers}, keyboard::{ - Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NativeKey, NativeKeyCode, + Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, + NativeKeyCode, PhysicalKey, + }, + platform::{ + modifier_supplement::KeyEventExtModifierSupplement, scancode::PhysicalKeyExtScancode, }, - platform::{modifier_supplement::KeyEventExtModifierSupplement, scancode::KeyCodeExtScancode}, platform_impl::platform::ffi, }; @@ -112,13 +115,14 @@ pub(crate) fn create_key_event( ns_event: &NSEvent, is_press: bool, is_repeat: bool, - key_override: Option, + key_override: Option, ) -> KeyEvent { use ElementState::{Pressed, Released}; let state = if is_press { Pressed } else { Released }; let scancode = ns_event.key_code(); - let mut physical_key = key_override.unwrap_or_else(|| KeyCode::from_scancode(scancode as u32)); + let mut physical_key = + key_override.unwrap_or_else(|| PhysicalKey::from_scancode(scancode as u32)); let text_with_all_modifiers: Option = if key_override.is_some() { None @@ -130,7 +134,7 @@ pub(crate) fn create_key_event( if characters.is_empty() { None } else { - if matches!(physical_key, KeyCode::Unidentified(_)) { + if matches!(physical_key, PhysicalKey::Unidentified(_)) { // The key may be one of the funky function keys physical_key = extra_function_key_to_code(scancode, &characters); } @@ -188,65 +192,75 @@ pub(crate) fn create_key_event( } } -pub fn code_to_key(code: KeyCode, scancode: u16) -> Key { - match code { - KeyCode::Enter => Key::Enter, - KeyCode::Tab => Key::Tab, - KeyCode::Space => Key::Space, - KeyCode::Backspace => Key::Backspace, - KeyCode::Escape => Key::Escape, - KeyCode::SuperRight => Key::Super, - KeyCode::SuperLeft => Key::Super, - KeyCode::ShiftLeft => Key::Shift, - KeyCode::AltLeft => Key::Alt, - KeyCode::ControlLeft => Key::Control, - KeyCode::ShiftRight => Key::Shift, - KeyCode::AltRight => Key::Alt, - KeyCode::ControlRight => Key::Control, - - KeyCode::NumLock => Key::NumLock, - KeyCode::AudioVolumeUp => Key::AudioVolumeUp, - KeyCode::AudioVolumeDown => Key::AudioVolumeDown, +pub fn code_to_key(key: PhysicalKey, scancode: u16) -> Key { + let code = match key { + PhysicalKey::Code(code) => code, + PhysicalKey::Unidentified(code) => return Key::Unidentified(code.into()), + }; + + Key::Named(match code { + KeyCode::Enter => NamedKey::Enter, + KeyCode::Tab => NamedKey::Tab, + KeyCode::Space => NamedKey::Space, + KeyCode::Backspace => NamedKey::Backspace, + KeyCode::Escape => NamedKey::Escape, + KeyCode::SuperRight => NamedKey::Super, + KeyCode::SuperLeft => NamedKey::Super, + KeyCode::ShiftLeft => NamedKey::Shift, + KeyCode::AltLeft => NamedKey::Alt, + KeyCode::ControlLeft => NamedKey::Control, + KeyCode::ShiftRight => NamedKey::Shift, + KeyCode::AltRight => NamedKey::Alt, + KeyCode::ControlRight => NamedKey::Control, + + KeyCode::NumLock => NamedKey::NumLock, + KeyCode::AudioVolumeUp => NamedKey::AudioVolumeUp, + KeyCode::AudioVolumeDown => NamedKey::AudioVolumeDown, // Other numpad keys all generate text on macOS (if I understand correctly) - KeyCode::NumpadEnter => Key::Enter, - - KeyCode::F1 => Key::F1, - KeyCode::F2 => Key::F2, - KeyCode::F3 => Key::F3, - KeyCode::F4 => Key::F4, - KeyCode::F5 => Key::F5, - KeyCode::F6 => Key::F6, - KeyCode::F7 => Key::F7, - KeyCode::F8 => Key::F8, - KeyCode::F9 => Key::F9, - KeyCode::F10 => Key::F10, - KeyCode::F11 => Key::F11, - KeyCode::F12 => Key::F12, - KeyCode::F13 => Key::F13, - KeyCode::F14 => Key::F14, - KeyCode::F15 => Key::F15, - KeyCode::F16 => Key::F16, - KeyCode::F17 => Key::F17, - KeyCode::F18 => Key::F18, - KeyCode::F19 => Key::F19, - KeyCode::F20 => Key::F20, - - KeyCode::Insert => Key::Insert, - KeyCode::Home => Key::Home, - KeyCode::PageUp => Key::PageUp, - KeyCode::Delete => Key::Delete, - KeyCode::End => Key::End, - KeyCode::PageDown => Key::PageDown, - KeyCode::ArrowLeft => Key::ArrowLeft, - KeyCode::ArrowRight => Key::ArrowRight, - KeyCode::ArrowDown => Key::ArrowDown, - KeyCode::ArrowUp => Key::ArrowUp, - _ => Key::Unidentified(NativeKey::MacOS(scancode)), - } + KeyCode::NumpadEnter => NamedKey::Enter, + + KeyCode::F1 => NamedKey::F1, + KeyCode::F2 => NamedKey::F2, + KeyCode::F3 => NamedKey::F3, + KeyCode::F4 => NamedKey::F4, + KeyCode::F5 => NamedKey::F5, + KeyCode::F6 => NamedKey::F6, + KeyCode::F7 => NamedKey::F7, + KeyCode::F8 => NamedKey::F8, + KeyCode::F9 => NamedKey::F9, + KeyCode::F10 => NamedKey::F10, + KeyCode::F11 => NamedKey::F11, + KeyCode::F12 => NamedKey::F12, + KeyCode::F13 => NamedKey::F13, + KeyCode::F14 => NamedKey::F14, + KeyCode::F15 => NamedKey::F15, + KeyCode::F16 => NamedKey::F16, + KeyCode::F17 => NamedKey::F17, + KeyCode::F18 => NamedKey::F18, + KeyCode::F19 => NamedKey::F19, + KeyCode::F20 => NamedKey::F20, + + KeyCode::Insert => NamedKey::Insert, + KeyCode::Home => NamedKey::Home, + KeyCode::PageUp => NamedKey::PageUp, + KeyCode::Delete => NamedKey::Delete, + KeyCode::End => NamedKey::End, + KeyCode::PageDown => NamedKey::PageDown, + KeyCode::ArrowLeft => NamedKey::ArrowLeft, + KeyCode::ArrowRight => NamedKey::ArrowRight, + KeyCode::ArrowDown => NamedKey::ArrowDown, + KeyCode::ArrowUp => NamedKey::ArrowUp, + _ => return Key::Unidentified(NativeKey::MacOS(scancode)), + }) } -pub fn code_to_location(code: KeyCode) -> KeyLocation { +pub fn code_to_location(key: PhysicalKey) -> KeyLocation { + let code = match key { + PhysicalKey::Code(code) => code, + PhysicalKey::Unidentified(_) => return KeyLocation::Standard, + }; + match code { KeyCode::SuperRight => KeyLocation::Right, KeyCode::SuperLeft => KeyLocation::Left, @@ -283,17 +297,17 @@ pub fn code_to_location(code: KeyCode) -> KeyLocation { // While F1-F20 have scancodes we can match on, we have to check against UTF-16 // constants for the rest. // https://developer.apple.com/documentation/appkit/1535851-function-key_unicodes?preferredLanguage=occ -pub fn extra_function_key_to_code(scancode: u16, string: &str) -> KeyCode { +pub fn extra_function_key_to_code(scancode: u16, string: &str) -> PhysicalKey { if let Some(ch) = string.encode_utf16().next() { match ch { - 0xf718 => KeyCode::F21, - 0xf719 => KeyCode::F22, - 0xf71a => KeyCode::F23, - 0xf71b => KeyCode::F24, - _ => KeyCode::Unidentified(NativeKeyCode::MacOS(scancode)), + 0xf718 => PhysicalKey::Code(KeyCode::F21), + 0xf719 => PhysicalKey::Code(KeyCode::F22), + 0xf71a => PhysicalKey::Code(KeyCode::F23), + 0xf71b => PhysicalKey::Code(KeyCode::F24), + _ => PhysicalKey::Unidentified(NativeKeyCode::MacOS(scancode)), } } else { - KeyCode::Unidentified(NativeKeyCode::MacOS(scancode)) + PhysicalKey::Unidentified(NativeKeyCode::MacOS(scancode)) } } @@ -340,9 +354,14 @@ pub(super) fn event_mods(event: &NSEvent) -> Modifiers { } } -impl KeyCodeExtScancode for KeyCode { +impl PhysicalKeyExtScancode for PhysicalKey { fn to_scancode(self) -> Option { - match self { + let code = match self { + PhysicalKey::Code(code) => code, + PhysicalKey::Unidentified(_) => return None, + }; + + match code { KeyCode::KeyA => Some(0x00), KeyCode::KeyS => Some(0x01), KeyCode::KeyD => Some(0x02), @@ -458,8 +477,8 @@ impl KeyCodeExtScancode for KeyCode { } } - fn from_scancode(scancode: u32) -> KeyCode { - match scancode { + fn from_scancode(scancode: u32) -> PhysicalKey { + PhysicalKey::Code(match scancode { 0x00 => KeyCode::KeyA, 0x01 => KeyCode::KeyS, 0x02 => KeyCode::KeyD, @@ -596,7 +615,7 @@ impl KeyCodeExtScancode for KeyCode { // 0xA is the caret (^) an macOS's German QERTZ layout. This key is at the same location as // backquote (`) on Windows' US layout. 0xa => KeyCode::Backquote, - _ => KeyCode::Unidentified(NativeKeyCode::MacOS(scancode as u16)), - } + _ => return PhysicalKey::Unidentified(NativeKeyCode::MacOS(scancode as u16)), + }) } } diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index 414ea1ba89..c5b5655761 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -26,9 +26,9 @@ use crate::{ DeviceEvent, ElementState, Event, Ime, Modifiers, MouseButton, MouseScrollDelta, TouchPhase, WindowEvent, }, - keyboard::{Key, KeyCode, KeyLocation, ModifiersState}, + keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey, PhysicalKey}, platform::macos::{OptionAsAlt, WindowExtMacOS}, - platform::scancode::KeyCodeExtScancode, + platform::scancode::PhysicalKeyExtScancode, platform_impl::platform::{ app_state::AppState, event::{create_key_event, event_mods}, @@ -90,30 +90,30 @@ impl ModLocationMask { fn key_to_modifier(key: &Key) -> ModifiersState { match key { - Key::Alt => ModifiersState::ALT, - Key::Control => ModifiersState::CONTROL, - Key::Super => ModifiersState::SUPER, - Key::Shift => ModifiersState::SHIFT, + Key::Named(NamedKey::Alt) => ModifiersState::ALT, + Key::Named(NamedKey::Control) => ModifiersState::CONTROL, + Key::Named(NamedKey::Super) => ModifiersState::SUPER, + Key::Named(NamedKey::Shift) => ModifiersState::SHIFT, _ => unreachable!(), } } fn get_right_modifier_code(key: &Key) -> KeyCode { match key { - Key::Alt => KeyCode::AltRight, - Key::Control => KeyCode::ControlRight, - Key::Shift => KeyCode::ShiftRight, - Key::Super => KeyCode::SuperRight, + Key::Named(NamedKey::Alt) => KeyCode::AltRight, + Key::Named(NamedKey::Control) => KeyCode::ControlRight, + Key::Named(NamedKey::Shift) => KeyCode::ShiftRight, + Key::Named(NamedKey::Super) => KeyCode::SuperRight, _ => unreachable!(), } } fn get_left_modifier_code(key: &Key) -> KeyCode { match key { - Key::Alt => KeyCode::AltLeft, - Key::Control => KeyCode::ControlLeft, - Key::Shift => KeyCode::ShiftLeft, - Key::Super => KeyCode::SuperLeft, + Key::Named(NamedKey::Alt) => KeyCode::AltLeft, + Key::Named(NamedKey::Control) => KeyCode::ControlLeft, + Key::Named(NamedKey::Shift) => KeyCode::ShiftLeft, + Key::Named(NamedKey::Super) => KeyCode::SuperLeft, _ => unreachable!(), } } @@ -926,16 +926,16 @@ impl WinitView { // information. if is_flags_changed_event && ns_event.key_code() != 0 { let scancode = ns_event.key_code(); - let keycode = KeyCode::from_scancode(scancode as u32); + let physical_key = PhysicalKey::from_scancode(scancode as u32); // We'll correct the `is_press` later. - let mut event = create_key_event(ns_event, false, false, Some(keycode)); + let mut event = create_key_event(ns_event, false, false, Some(physical_key)); - let key = code_to_key(keycode, scancode); + let key = code_to_key(physical_key, scancode); let event_modifier = key_to_modifier(&key); - event.physical_key = keycode; + event.physical_key = physical_key; event.logical_key = key.clone(); - event.location = code_to_location(keycode); + event.location = code_to_location(physical_key); let location_mask = ModLocationMask::from_location(event.location); let mut phys_mod_state = self.state.phys_modifiers.borrow_mut(); @@ -956,7 +956,7 @@ impl WinitView { if phys_mod.contains(ModLocationMask::LEFT) { let mut event = event.clone(); event.location = KeyLocation::Left; - event.physical_key = get_left_modifier_code(&event.logical_key); + event.physical_key = get_left_modifier_code(&event.logical_key).into(); events.push_back(WindowEvent::KeyboardInput { device_id: DEVICE_ID, event, @@ -965,7 +965,7 @@ impl WinitView { } if phys_mod.contains(ModLocationMask::RIGHT) { event.location = KeyLocation::Right; - event.physical_key = get_right_modifier_code(&event.logical_key); + event.physical_key = get_right_modifier_code(&event.logical_key).into(); events.push_back(WindowEvent::KeyboardInput { device_id: DEVICE_ID, event, diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index 954a2142a1..6dd06c3a9c 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -18,6 +18,7 @@ use crate::{ event_loop::{self, ControlFlow, DeviceEvents}, keyboard::{ Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NativeKey, NativeKeyCode, + PhysicalKey, }, window::WindowId as RootWindowId, }; @@ -27,8 +28,8 @@ use super::{ RedoxSocket, TimeSocket, WindowId, WindowProperties, }; -fn convert_scancode(scancode: u8) -> KeyCode { - match scancode { +fn convert_scancode(scancode: u8) -> PhysicalKey { + PhysicalKey::Code(match scancode { orbclient::K_A => KeyCode::KeyA, orbclient::K_B => KeyCode::KeyB, orbclient::K_C => KeyCode::KeyC, @@ -109,8 +110,8 @@ fn convert_scancode(scancode: u8) -> KeyCode { orbclient::K_F11 => KeyCode::F11, orbclient::K_F12 => KeyCode::F12, - _ => KeyCode::Unidentified(NativeKeyCode::Unidentified), - } + _ => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified), + }) } fn element_state(pressed: bool) -> event::ElementState { @@ -152,7 +153,12 @@ struct EventState { } impl EventState { - fn key(&mut self, code: KeyCode, pressed: bool) { + fn key(&mut self, key: PhysicalKey, pressed: bool) { + let code = match key { + PhysicalKey::Code(code) => code, + _ => return, + }; + match code { KeyCode::ShiftLeft => self.keyboard.set(KeyboardModifierState::LSHIFT, pressed), KeyCode::ShiftRight => self.keyboard.set(KeyboardModifierState::RSHIFT, pressed), @@ -332,16 +338,16 @@ impl EventLoop { pressed, }) => { if scancode != 0 { - let code = convert_scancode(scancode); + let physical_key = convert_scancode(scancode); let modifiers_before = event_state.keyboard; - event_state.key(code, pressed); + event_state.key(physical_key, pressed); event_handler(event::Event::WindowEvent { window_id: RootWindowId(window_id), event: event::WindowEvent::KeyboardInput { device_id: event::DeviceId(DeviceId), event: event::KeyEvent { logical_key: Key::Unidentified(NativeKey::Unidentified), - physical_key: code, + physical_key, location: KeyLocation::Standard, state: element_state(pressed), repeat: false, diff --git a/src/platform_impl/web/keyboard.rs b/src/platform_impl/web/keyboard.rs index 84c0003975..6f8d69c760 100644 --- a/src/platform_impl/web/keyboard.rs +++ b/src/platform_impl/web/keyboard.rs @@ -1,328 +1,328 @@ use smol_str::SmolStr; -use crate::keyboard::{Key, KeyCode, NativeKey, NativeKeyCode}; +use crate::keyboard::{Key, KeyCode, NamedKey, NativeKey, NativeKeyCode, PhysicalKey}; #[derive(Debug, Clone, Eq, PartialEq, Hash)] pub(crate) struct KeyEventExtra; impl Key { pub(crate) fn from_key_attribute_value(kav: &str) -> Self { - match kav { - "Unidentified" => Key::Unidentified(NativeKey::Web(SmolStr::new(kav))), - "Dead" => Key::Dead(None), - "Alt" => Key::Alt, - "AltGraph" => Key::AltGraph, - "CapsLock" => Key::CapsLock, - "Control" => Key::Control, - "Fn" => Key::Fn, - "FnLock" => Key::FnLock, - "NumLock" => Key::NumLock, - "ScrollLock" => Key::ScrollLock, - "Shift" => Key::Shift, - "Symbol" => Key::Symbol, - "SymbolLock" => Key::SymbolLock, - "Hyper" => Key::Hyper, - "Meta" => Key::Super, - "Enter" => Key::Enter, - "Tab" => Key::Tab, - " " => Key::Space, - "ArrowDown" => Key::ArrowDown, - "ArrowLeft" => Key::ArrowLeft, - "ArrowRight" => Key::ArrowRight, - "ArrowUp" => Key::ArrowUp, - "End" => Key::End, - "Home" => Key::Home, - "PageDown" => Key::PageDown, - "PageUp" => Key::PageUp, - "Backspace" => Key::Backspace, - "Clear" => Key::Clear, - "Copy" => Key::Copy, - "CrSel" => Key::CrSel, - "Cut" => Key::Cut, - "Delete" => Key::Delete, - "EraseEof" => Key::EraseEof, - "ExSel" => Key::ExSel, - "Insert" => Key::Insert, - "Paste" => Key::Paste, - "Redo" => Key::Redo, - "Undo" => Key::Undo, - "Accept" => Key::Accept, - "Again" => Key::Again, - "Attn" => Key::Attn, - "Cancel" => Key::Cancel, - "ContextMenu" => Key::ContextMenu, - "Escape" => Key::Escape, - "Execute" => Key::Execute, - "Find" => Key::Find, - "Help" => Key::Help, - "Pause" => Key::Pause, - "Play" => Key::Play, - "Props" => Key::Props, - "Select" => Key::Select, - "ZoomIn" => Key::ZoomIn, - "ZoomOut" => Key::ZoomOut, - "BrightnessDown" => Key::BrightnessDown, - "BrightnessUp" => Key::BrightnessUp, - "Eject" => Key::Eject, - "LogOff" => Key::LogOff, - "Power" => Key::Power, - "PowerOff" => Key::PowerOff, - "PrintScreen" => Key::PrintScreen, - "Hibernate" => Key::Hibernate, - "Standby" => Key::Standby, - "WakeUp" => Key::WakeUp, - "AllCandidates" => Key::AllCandidates, - "Alphanumeric" => Key::Alphanumeric, - "CodeInput" => Key::CodeInput, - "Compose" => Key::Compose, - "Convert" => Key::Convert, - "FinalMode" => Key::FinalMode, - "GroupFirst" => Key::GroupFirst, - "GroupLast" => Key::GroupLast, - "GroupNext" => Key::GroupNext, - "GroupPrevious" => Key::GroupPrevious, - "ModeChange" => Key::ModeChange, - "NextCandidate" => Key::NextCandidate, - "NonConvert" => Key::NonConvert, - "PreviousCandidate" => Key::PreviousCandidate, - "Process" => Key::Process, - "SingleCandidate" => Key::SingleCandidate, - "HangulMode" => Key::HangulMode, - "HanjaMode" => Key::HanjaMode, - "JunjaMode" => Key::JunjaMode, - "Eisu" => Key::Eisu, - "Hankaku" => Key::Hankaku, - "Hiragana" => Key::Hiragana, - "HiraganaKatakana" => Key::HiraganaKatakana, - "KanaMode" => Key::KanaMode, - "KanjiMode" => Key::KanjiMode, - "Katakana" => Key::Katakana, - "Romaji" => Key::Romaji, - "Zenkaku" => Key::Zenkaku, - "ZenkakuHankaku" => Key::ZenkakuHankaku, - "Soft1" => Key::Soft1, - "Soft2" => Key::Soft2, - "Soft3" => Key::Soft3, - "Soft4" => Key::Soft4, - "ChannelDown" => Key::ChannelDown, - "ChannelUp" => Key::ChannelUp, - "Close" => Key::Close, - "MailForward" => Key::MailForward, - "MailReply" => Key::MailReply, - "MailSend" => Key::MailSend, - "MediaClose" => Key::MediaClose, - "MediaFastForward" => Key::MediaFastForward, - "MediaPause" => Key::MediaPause, - "MediaPlay" => Key::MediaPlay, - "MediaPlayPause" => Key::MediaPlayPause, - "MediaRecord" => Key::MediaRecord, - "MediaRewind" => Key::MediaRewind, - "MediaStop" => Key::MediaStop, - "MediaTrackNext" => Key::MediaTrackNext, - "MediaTrackPrevious" => Key::MediaTrackPrevious, - "New" => Key::New, - "Open" => Key::Open, - "Print" => Key::Print, - "Save" => Key::Save, - "SpellCheck" => Key::SpellCheck, - "Key11" => Key::Key11, - "Key12" => Key::Key12, - "AudioBalanceLeft" => Key::AudioBalanceLeft, - "AudioBalanceRight" => Key::AudioBalanceRight, - "AudioBassBoostDown" => Key::AudioBassBoostDown, - "AudioBassBoostToggle" => Key::AudioBassBoostToggle, - "AudioBassBoostUp" => Key::AudioBassBoostUp, - "AudioFaderFront" => Key::AudioFaderFront, - "AudioFaderRear" => Key::AudioFaderRear, - "AudioSurroundModeNext" => Key::AudioSurroundModeNext, - "AudioTrebleDown" => Key::AudioTrebleDown, - "AudioTrebleUp" => Key::AudioTrebleUp, - "AudioVolumeDown" => Key::AudioVolumeDown, - "AudioVolumeUp" => Key::AudioVolumeUp, - "AudioVolumeMute" => Key::AudioVolumeMute, - "MicrophoneToggle" => Key::MicrophoneToggle, - "MicrophoneVolumeDown" => Key::MicrophoneVolumeDown, - "MicrophoneVolumeUp" => Key::MicrophoneVolumeUp, - "MicrophoneVolumeMute" => Key::MicrophoneVolumeMute, - "SpeechCorrectionList" => Key::SpeechCorrectionList, - "SpeechInputToggle" => Key::SpeechInputToggle, - "LaunchApplication1" => Key::LaunchApplication1, - "LaunchApplication2" => Key::LaunchApplication2, - "LaunchCalendar" => Key::LaunchCalendar, - "LaunchContacts" => Key::LaunchContacts, - "LaunchMail" => Key::LaunchMail, - "LaunchMediaPlayer" => Key::LaunchMediaPlayer, - "LaunchMusicPlayer" => Key::LaunchMusicPlayer, - "LaunchPhone" => Key::LaunchPhone, - "LaunchScreenSaver" => Key::LaunchScreenSaver, - "LaunchSpreadsheet" => Key::LaunchSpreadsheet, - "LaunchWebBrowser" => Key::LaunchWebBrowser, - "LaunchWebCam" => Key::LaunchWebCam, - "LaunchWordProcessor" => Key::LaunchWordProcessor, - "BrowserBack" => Key::BrowserBack, - "BrowserFavorites" => Key::BrowserFavorites, - "BrowserForward" => Key::BrowserForward, - "BrowserHome" => Key::BrowserHome, - "BrowserRefresh" => Key::BrowserRefresh, - "BrowserSearch" => Key::BrowserSearch, - "BrowserStop" => Key::BrowserStop, - "AppSwitch" => Key::AppSwitch, - "Call" => Key::Call, - "Camera" => Key::Camera, - "CameraFocus" => Key::CameraFocus, - "EndCall" => Key::EndCall, - "GoBack" => Key::GoBack, - "GoHome" => Key::GoHome, - "HeadsetHook" => Key::HeadsetHook, - "LastNumberRedial" => Key::LastNumberRedial, - "Notification" => Key::Notification, - "MannerMode" => Key::MannerMode, - "VoiceDial" => Key::VoiceDial, - "TV" => Key::TV, - "TV3DMode" => Key::TV3DMode, - "TVAntennaCable" => Key::TVAntennaCable, - "TVAudioDescription" => Key::TVAudioDescription, - "TVAudioDescriptionMixDown" => Key::TVAudioDescriptionMixDown, - "TVAudioDescriptionMixUp" => Key::TVAudioDescriptionMixUp, - "TVContentsMenu" => Key::TVContentsMenu, - "TVDataService" => Key::TVDataService, - "TVInput" => Key::TVInput, - "TVInputComponent1" => Key::TVInputComponent1, - "TVInputComponent2" => Key::TVInputComponent2, - "TVInputComposite1" => Key::TVInputComposite1, - "TVInputComposite2" => Key::TVInputComposite2, - "TVInputHDMI1" => Key::TVInputHDMI1, - "TVInputHDMI2" => Key::TVInputHDMI2, - "TVInputHDMI3" => Key::TVInputHDMI3, - "TVInputHDMI4" => Key::TVInputHDMI4, - "TVInputVGA1" => Key::TVInputVGA1, - "TVMediaContext" => Key::TVMediaContext, - "TVNetwork" => Key::TVNetwork, - "TVNumberEntry" => Key::TVNumberEntry, - "TVPower" => Key::TVPower, - "TVRadioService" => Key::TVRadioService, - "TVSatellite" => Key::TVSatellite, - "TVSatelliteBS" => Key::TVSatelliteBS, - "TVSatelliteCS" => Key::TVSatelliteCS, - "TVSatelliteToggle" => Key::TVSatelliteToggle, - "TVTerrestrialAnalog" => Key::TVTerrestrialAnalog, - "TVTerrestrialDigital" => Key::TVTerrestrialDigital, - "TVTimer" => Key::TVTimer, - "AVRInput" => Key::AVRInput, - "AVRPower" => Key::AVRPower, - "ColorF0Red" => Key::ColorF0Red, - "ColorF1Green" => Key::ColorF1Green, - "ColorF2Yellow" => Key::ColorF2Yellow, - "ColorF3Blue" => Key::ColorF3Blue, - "ColorF4Grey" => Key::ColorF4Grey, - "ColorF5Brown" => Key::ColorF5Brown, - "ClosedCaptionToggle" => Key::ClosedCaptionToggle, - "Dimmer" => Key::Dimmer, - "DisplaySwap" => Key::DisplaySwap, - "DVR" => Key::DVR, - "Exit" => Key::Exit, - "FavoriteClear0" => Key::FavoriteClear0, - "FavoriteClear1" => Key::FavoriteClear1, - "FavoriteClear2" => Key::FavoriteClear2, - "FavoriteClear3" => Key::FavoriteClear3, - "FavoriteRecall0" => Key::FavoriteRecall0, - "FavoriteRecall1" => Key::FavoriteRecall1, - "FavoriteRecall2" => Key::FavoriteRecall2, - "FavoriteRecall3" => Key::FavoriteRecall3, - "FavoriteStore0" => Key::FavoriteStore0, - "FavoriteStore1" => Key::FavoriteStore1, - "FavoriteStore2" => Key::FavoriteStore2, - "FavoriteStore3" => Key::FavoriteStore3, - "Guide" => Key::Guide, - "GuideNextDay" => Key::GuideNextDay, - "GuidePreviousDay" => Key::GuidePreviousDay, - "Info" => Key::Info, - "InstantReplay" => Key::InstantReplay, - "Link" => Key::Link, - "ListProgram" => Key::ListProgram, - "LiveContent" => Key::LiveContent, - "Lock" => Key::Lock, - "MediaApps" => Key::MediaApps, - "MediaAudioTrack" => Key::MediaAudioTrack, - "MediaLast" => Key::MediaLast, - "MediaSkipBackward" => Key::MediaSkipBackward, - "MediaSkipForward" => Key::MediaSkipForward, - "MediaStepBackward" => Key::MediaStepBackward, - "MediaStepForward" => Key::MediaStepForward, - "MediaTopMenu" => Key::MediaTopMenu, - "NavigateIn" => Key::NavigateIn, - "NavigateNext" => Key::NavigateNext, - "NavigateOut" => Key::NavigateOut, - "NavigatePrevious" => Key::NavigatePrevious, - "NextFavoriteChannel" => Key::NextFavoriteChannel, - "NextUserProfile" => Key::NextUserProfile, - "OnDemand" => Key::OnDemand, - "Pairing" => Key::Pairing, - "PinPDown" => Key::PinPDown, - "PinPMove" => Key::PinPMove, - "PinPToggle" => Key::PinPToggle, - "PinPUp" => Key::PinPUp, - "PlaySpeedDown" => Key::PlaySpeedDown, - "PlaySpeedReset" => Key::PlaySpeedReset, - "PlaySpeedUp" => Key::PlaySpeedUp, - "RandomToggle" => Key::RandomToggle, - "RcLowBattery" => Key::RcLowBattery, - "RecordSpeedNext" => Key::RecordSpeedNext, - "RfBypass" => Key::RfBypass, - "ScanChannelsToggle" => Key::ScanChannelsToggle, - "ScreenModeNext" => Key::ScreenModeNext, - "Settings" => Key::Settings, - "SplitScreenToggle" => Key::SplitScreenToggle, - "STBInput" => Key::STBInput, - "STBPower" => Key::STBPower, - "Subtitle" => Key::Subtitle, - "Teletext" => Key::Teletext, - "VideoModeNext" => Key::VideoModeNext, - "Wink" => Key::Wink, - "ZoomToggle" => Key::ZoomToggle, - "F1" => Key::F1, - "F2" => Key::F2, - "F3" => Key::F3, - "F4" => Key::F4, - "F5" => Key::F5, - "F6" => Key::F6, - "F7" => Key::F7, - "F8" => Key::F8, - "F9" => Key::F9, - "F10" => Key::F10, - "F11" => Key::F11, - "F12" => Key::F12, - "F13" => Key::F13, - "F14" => Key::F14, - "F15" => Key::F15, - "F16" => Key::F16, - "F17" => Key::F17, - "F18" => Key::F18, - "F19" => Key::F19, - "F20" => Key::F20, - "F21" => Key::F21, - "F22" => Key::F22, - "F23" => Key::F23, - "F24" => Key::F24, - "F25" => Key::F25, - "F26" => Key::F26, - "F27" => Key::F27, - "F28" => Key::F28, - "F29" => Key::F29, - "F30" => Key::F30, - "F31" => Key::F31, - "F32" => Key::F32, - "F33" => Key::F33, - "F34" => Key::F34, - "F35" => Key::F35, - string => Key::Character(SmolStr::new(string)), - } + Key::Named(match kav { + "Unidentified" => return Key::Unidentified(NativeKey::Web(SmolStr::new(kav))), + "Dead" => return Key::Dead(None), + "Alt" => NamedKey::Alt, + "AltGraph" => NamedKey::AltGraph, + "CapsLock" => NamedKey::CapsLock, + "Control" => NamedKey::Control, + "Fn" => NamedKey::Fn, + "FnLock" => NamedKey::FnLock, + "NumLock" => NamedKey::NumLock, + "ScrollLock" => NamedKey::ScrollLock, + "Shift" => NamedKey::Shift, + "Symbol" => NamedKey::Symbol, + "SymbolLock" => NamedKey::SymbolLock, + "Hyper" => NamedKey::Hyper, + "Meta" => NamedKey::Super, + "Enter" => NamedKey::Enter, + "Tab" => NamedKey::Tab, + " " => NamedKey::Space, + "ArrowDown" => NamedKey::ArrowDown, + "ArrowLeft" => NamedKey::ArrowLeft, + "ArrowRight" => NamedKey::ArrowRight, + "ArrowUp" => NamedKey::ArrowUp, + "End" => NamedKey::End, + "Home" => NamedKey::Home, + "PageDown" => NamedKey::PageDown, + "PageUp" => NamedKey::PageUp, + "Backspace" => NamedKey::Backspace, + "Clear" => NamedKey::Clear, + "Copy" => NamedKey::Copy, + "CrSel" => NamedKey::CrSel, + "Cut" => NamedKey::Cut, + "Delete" => NamedKey::Delete, + "EraseEof" => NamedKey::EraseEof, + "ExSel" => NamedKey::ExSel, + "Insert" => NamedKey::Insert, + "Paste" => NamedKey::Paste, + "Redo" => NamedKey::Redo, + "Undo" => NamedKey::Undo, + "Accept" => NamedKey::Accept, + "Again" => NamedKey::Again, + "Attn" => NamedKey::Attn, + "Cancel" => NamedKey::Cancel, + "ContextMenu" => NamedKey::ContextMenu, + "Escape" => NamedKey::Escape, + "Execute" => NamedKey::Execute, + "Find" => NamedKey::Find, + "Help" => NamedKey::Help, + "Pause" => NamedKey::Pause, + "Play" => NamedKey::Play, + "Props" => NamedKey::Props, + "Select" => NamedKey::Select, + "ZoomIn" => NamedKey::ZoomIn, + "ZoomOut" => NamedKey::ZoomOut, + "BrightnessDown" => NamedKey::BrightnessDown, + "BrightnessUp" => NamedKey::BrightnessUp, + "Eject" => NamedKey::Eject, + "LogOff" => NamedKey::LogOff, + "Power" => NamedKey::Power, + "PowerOff" => NamedKey::PowerOff, + "PrintScreen" => NamedKey::PrintScreen, + "Hibernate" => NamedKey::Hibernate, + "Standby" => NamedKey::Standby, + "WakeUp" => NamedKey::WakeUp, + "AllCandidates" => NamedKey::AllCandidates, + "Alphanumeric" => NamedKey::Alphanumeric, + "CodeInput" => NamedKey::CodeInput, + "Compose" => NamedKey::Compose, + "Convert" => NamedKey::Convert, + "FinalMode" => NamedKey::FinalMode, + "GroupFirst" => NamedKey::GroupFirst, + "GroupLast" => NamedKey::GroupLast, + "GroupNext" => NamedKey::GroupNext, + "GroupPrevious" => NamedKey::GroupPrevious, + "ModeChange" => NamedKey::ModeChange, + "NextCandidate" => NamedKey::NextCandidate, + "NonConvert" => NamedKey::NonConvert, + "PreviousCandidate" => NamedKey::PreviousCandidate, + "Process" => NamedKey::Process, + "SingleCandidate" => NamedKey::SingleCandidate, + "HangulMode" => NamedKey::HangulMode, + "HanjaMode" => NamedKey::HanjaMode, + "JunjaMode" => NamedKey::JunjaMode, + "Eisu" => NamedKey::Eisu, + "Hankaku" => NamedKey::Hankaku, + "Hiragana" => NamedKey::Hiragana, + "HiraganaKatakana" => NamedKey::HiraganaKatakana, + "KanaMode" => NamedKey::KanaMode, + "KanjiMode" => NamedKey::KanjiMode, + "Katakana" => NamedKey::Katakana, + "Romaji" => NamedKey::Romaji, + "Zenkaku" => NamedKey::Zenkaku, + "ZenkakuHankaku" => NamedKey::ZenkakuHankaku, + "Soft1" => NamedKey::Soft1, + "Soft2" => NamedKey::Soft2, + "Soft3" => NamedKey::Soft3, + "Soft4" => NamedKey::Soft4, + "ChannelDown" => NamedKey::ChannelDown, + "ChannelUp" => NamedKey::ChannelUp, + "Close" => NamedKey::Close, + "MailForward" => NamedKey::MailForward, + "MailReply" => NamedKey::MailReply, + "MailSend" => NamedKey::MailSend, + "MediaClose" => NamedKey::MediaClose, + "MediaFastForward" => NamedKey::MediaFastForward, + "MediaPause" => NamedKey::MediaPause, + "MediaPlay" => NamedKey::MediaPlay, + "MediaPlayPause" => NamedKey::MediaPlayPause, + "MediaRecord" => NamedKey::MediaRecord, + "MediaRewind" => NamedKey::MediaRewind, + "MediaStop" => NamedKey::MediaStop, + "MediaTrackNext" => NamedKey::MediaTrackNext, + "MediaTrackPrevious" => NamedKey::MediaTrackPrevious, + "New" => NamedKey::New, + "Open" => NamedKey::Open, + "Print" => NamedKey::Print, + "Save" => NamedKey::Save, + "SpellCheck" => NamedKey::SpellCheck, + "Key11" => NamedKey::Key11, + "Key12" => NamedKey::Key12, + "AudioBalanceLeft" => NamedKey::AudioBalanceLeft, + "AudioBalanceRight" => NamedKey::AudioBalanceRight, + "AudioBassBoostDown" => NamedKey::AudioBassBoostDown, + "AudioBassBoostToggle" => NamedKey::AudioBassBoostToggle, + "AudioBassBoostUp" => NamedKey::AudioBassBoostUp, + "AudioFaderFront" => NamedKey::AudioFaderFront, + "AudioFaderRear" => NamedKey::AudioFaderRear, + "AudioSurroundModeNext" => NamedKey::AudioSurroundModeNext, + "AudioTrebleDown" => NamedKey::AudioTrebleDown, + "AudioTrebleUp" => NamedKey::AudioTrebleUp, + "AudioVolumeDown" => NamedKey::AudioVolumeDown, + "AudioVolumeUp" => NamedKey::AudioVolumeUp, + "AudioVolumeMute" => NamedKey::AudioVolumeMute, + "MicrophoneToggle" => NamedKey::MicrophoneToggle, + "MicrophoneVolumeDown" => NamedKey::MicrophoneVolumeDown, + "MicrophoneVolumeUp" => NamedKey::MicrophoneVolumeUp, + "MicrophoneVolumeMute" => NamedKey::MicrophoneVolumeMute, + "SpeechCorrectionList" => NamedKey::SpeechCorrectionList, + "SpeechInputToggle" => NamedKey::SpeechInputToggle, + "LaunchApplication1" => NamedKey::LaunchApplication1, + "LaunchApplication2" => NamedKey::LaunchApplication2, + "LaunchCalendar" => NamedKey::LaunchCalendar, + "LaunchContacts" => NamedKey::LaunchContacts, + "LaunchMail" => NamedKey::LaunchMail, + "LaunchMediaPlayer" => NamedKey::LaunchMediaPlayer, + "LaunchMusicPlayer" => NamedKey::LaunchMusicPlayer, + "LaunchPhone" => NamedKey::LaunchPhone, + "LaunchScreenSaver" => NamedKey::LaunchScreenSaver, + "LaunchSpreadsheet" => NamedKey::LaunchSpreadsheet, + "LaunchWebBrowser" => NamedKey::LaunchWebBrowser, + "LaunchWebCam" => NamedKey::LaunchWebCam, + "LaunchWordProcessor" => NamedKey::LaunchWordProcessor, + "BrowserBack" => NamedKey::BrowserBack, + "BrowserFavorites" => NamedKey::BrowserFavorites, + "BrowserForward" => NamedKey::BrowserForward, + "BrowserHome" => NamedKey::BrowserHome, + "BrowserRefresh" => NamedKey::BrowserRefresh, + "BrowserSearch" => NamedKey::BrowserSearch, + "BrowserStop" => NamedKey::BrowserStop, + "AppSwitch" => NamedKey::AppSwitch, + "Call" => NamedKey::Call, + "Camera" => NamedKey::Camera, + "CameraFocus" => NamedKey::CameraFocus, + "EndCall" => NamedKey::EndCall, + "GoBack" => NamedKey::GoBack, + "GoHome" => NamedKey::GoHome, + "HeadsetHook" => NamedKey::HeadsetHook, + "LastNumberRedial" => NamedKey::LastNumberRedial, + "Notification" => NamedKey::Notification, + "MannerMode" => NamedKey::MannerMode, + "VoiceDial" => NamedKey::VoiceDial, + "TV" => NamedKey::TV, + "TV3DMode" => NamedKey::TV3DMode, + "TVAntennaCable" => NamedKey::TVAntennaCable, + "TVAudioDescription" => NamedKey::TVAudioDescription, + "TVAudioDescriptionMixDown" => NamedKey::TVAudioDescriptionMixDown, + "TVAudioDescriptionMixUp" => NamedKey::TVAudioDescriptionMixUp, + "TVContentsMenu" => NamedKey::TVContentsMenu, + "TVDataService" => NamedKey::TVDataService, + "TVInput" => NamedKey::TVInput, + "TVInputComponent1" => NamedKey::TVInputComponent1, + "TVInputComponent2" => NamedKey::TVInputComponent2, + "TVInputComposite1" => NamedKey::TVInputComposite1, + "TVInputComposite2" => NamedKey::TVInputComposite2, + "TVInputHDMI1" => NamedKey::TVInputHDMI1, + "TVInputHDMI2" => NamedKey::TVInputHDMI2, + "TVInputHDMI3" => NamedKey::TVInputHDMI3, + "TVInputHDMI4" => NamedKey::TVInputHDMI4, + "TVInputVGA1" => NamedKey::TVInputVGA1, + "TVMediaContext" => NamedKey::TVMediaContext, + "TVNetwork" => NamedKey::TVNetwork, + "TVNumberEntry" => NamedKey::TVNumberEntry, + "TVPower" => NamedKey::TVPower, + "TVRadioService" => NamedKey::TVRadioService, + "TVSatellite" => NamedKey::TVSatellite, + "TVSatelliteBS" => NamedKey::TVSatelliteBS, + "TVSatelliteCS" => NamedKey::TVSatelliteCS, + "TVSatelliteToggle" => NamedKey::TVSatelliteToggle, + "TVTerrestrialAnalog" => NamedKey::TVTerrestrialAnalog, + "TVTerrestrialDigital" => NamedKey::TVTerrestrialDigital, + "TVTimer" => NamedKey::TVTimer, + "AVRInput" => NamedKey::AVRInput, + "AVRPower" => NamedKey::AVRPower, + "ColorF0Red" => NamedKey::ColorF0Red, + "ColorF1Green" => NamedKey::ColorF1Green, + "ColorF2Yellow" => NamedKey::ColorF2Yellow, + "ColorF3Blue" => NamedKey::ColorF3Blue, + "ColorF4Grey" => NamedKey::ColorF4Grey, + "ColorF5Brown" => NamedKey::ColorF5Brown, + "ClosedCaptionToggle" => NamedKey::ClosedCaptionToggle, + "Dimmer" => NamedKey::Dimmer, + "DisplaySwap" => NamedKey::DisplaySwap, + "DVR" => NamedKey::DVR, + "Exit" => NamedKey::Exit, + "FavoriteClear0" => NamedKey::FavoriteClear0, + "FavoriteClear1" => NamedKey::FavoriteClear1, + "FavoriteClear2" => NamedKey::FavoriteClear2, + "FavoriteClear3" => NamedKey::FavoriteClear3, + "FavoriteRecall0" => NamedKey::FavoriteRecall0, + "FavoriteRecall1" => NamedKey::FavoriteRecall1, + "FavoriteRecall2" => NamedKey::FavoriteRecall2, + "FavoriteRecall3" => NamedKey::FavoriteRecall3, + "FavoriteStore0" => NamedKey::FavoriteStore0, + "FavoriteStore1" => NamedKey::FavoriteStore1, + "FavoriteStore2" => NamedKey::FavoriteStore2, + "FavoriteStore3" => NamedKey::FavoriteStore3, + "Guide" => NamedKey::Guide, + "GuideNextDay" => NamedKey::GuideNextDay, + "GuidePreviousDay" => NamedKey::GuidePreviousDay, + "Info" => NamedKey::Info, + "InstantReplay" => NamedKey::InstantReplay, + "Link" => NamedKey::Link, + "ListProgram" => NamedKey::ListProgram, + "LiveContent" => NamedKey::LiveContent, + "Lock" => NamedKey::Lock, + "MediaApps" => NamedKey::MediaApps, + "MediaAudioTrack" => NamedKey::MediaAudioTrack, + "MediaLast" => NamedKey::MediaLast, + "MediaSkipBackward" => NamedKey::MediaSkipBackward, + "MediaSkipForward" => NamedKey::MediaSkipForward, + "MediaStepBackward" => NamedKey::MediaStepBackward, + "MediaStepForward" => NamedKey::MediaStepForward, + "MediaTopMenu" => NamedKey::MediaTopMenu, + "NavigateIn" => NamedKey::NavigateIn, + "NavigateNext" => NamedKey::NavigateNext, + "NavigateOut" => NamedKey::NavigateOut, + "NavigatePrevious" => NamedKey::NavigatePrevious, + "NextFavoriteChannel" => NamedKey::NextFavoriteChannel, + "NextUserProfile" => NamedKey::NextUserProfile, + "OnDemand" => NamedKey::OnDemand, + "Pairing" => NamedKey::Pairing, + "PinPDown" => NamedKey::PinPDown, + "PinPMove" => NamedKey::PinPMove, + "PinPToggle" => NamedKey::PinPToggle, + "PinPUp" => NamedKey::PinPUp, + "PlaySpeedDown" => NamedKey::PlaySpeedDown, + "PlaySpeedReset" => NamedKey::PlaySpeedReset, + "PlaySpeedUp" => NamedKey::PlaySpeedUp, + "RandomToggle" => NamedKey::RandomToggle, + "RcLowBattery" => NamedKey::RcLowBattery, + "RecordSpeedNext" => NamedKey::RecordSpeedNext, + "RfBypass" => NamedKey::RfBypass, + "ScanChannelsToggle" => NamedKey::ScanChannelsToggle, + "ScreenModeNext" => NamedKey::ScreenModeNext, + "Settings" => NamedKey::Settings, + "SplitScreenToggle" => NamedKey::SplitScreenToggle, + "STBInput" => NamedKey::STBInput, + "STBPower" => NamedKey::STBPower, + "Subtitle" => NamedKey::Subtitle, + "Teletext" => NamedKey::Teletext, + "VideoModeNext" => NamedKey::VideoModeNext, + "Wink" => NamedKey::Wink, + "ZoomToggle" => NamedKey::ZoomToggle, + "F1" => NamedKey::F1, + "F2" => NamedKey::F2, + "F3" => NamedKey::F3, + "F4" => NamedKey::F4, + "F5" => NamedKey::F5, + "F6" => NamedKey::F6, + "F7" => NamedKey::F7, + "F8" => NamedKey::F8, + "F9" => NamedKey::F9, + "F10" => NamedKey::F10, + "F11" => NamedKey::F11, + "F12" => NamedKey::F12, + "F13" => NamedKey::F13, + "F14" => NamedKey::F14, + "F15" => NamedKey::F15, + "F16" => NamedKey::F16, + "F17" => NamedKey::F17, + "F18" => NamedKey::F18, + "F19" => NamedKey::F19, + "F20" => NamedKey::F20, + "F21" => NamedKey::F21, + "F22" => NamedKey::F22, + "F23" => NamedKey::F23, + "F24" => NamedKey::F24, + "F25" => NamedKey::F25, + "F26" => NamedKey::F26, + "F27" => NamedKey::F27, + "F28" => NamedKey::F28, + "F29" => NamedKey::F29, + "F30" => NamedKey::F30, + "F31" => NamedKey::F31, + "F32" => NamedKey::F32, + "F33" => NamedKey::F33, + "F34" => NamedKey::F34, + "F35" => NamedKey::F35, + string => return Key::Character(SmolStr::new(string)), + }) } } -impl KeyCode { +impl PhysicalKey { pub fn from_key_code_attribute_value(kcav: &str) -> Self { - match kcav { + PhysicalKey::Code(match kcav { "Backquote" => KeyCode::Backquote, "Backslash" => KeyCode::Backslash, "BracketLeft" => KeyCode::BracketLeft, @@ -516,7 +516,7 @@ impl KeyCode { "F33" => KeyCode::F33, "F34" => KeyCode::F34, "F35" => KeyCode::F35, - _ => KeyCode::Unidentified(NativeKeyCode::Unidentified), - } + _ => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified), + }) } } diff --git a/src/platform_impl/web/web_sys/canvas.rs b/src/platform_impl/web/web_sys/canvas.rs index b2dc6536da..cc7e4b054e 100644 --- a/src/platform_impl/web/web_sys/canvas.rs +++ b/src/platform_impl/web/web_sys/canvas.rs @@ -11,7 +11,7 @@ use web_sys::{ use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; use crate::error::OsError as RootOE; use crate::event::{Force, InnerSizeWriter, MouseButton, MouseScrollDelta}; -use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState}; +use crate::keyboard::{Key, KeyLocation, ModifiersState, PhysicalKey}; use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes}; use crate::window::{WindowAttributes, WindowId as RootWindowId}; @@ -258,7 +258,7 @@ impl Canvas { pub fn on_keyboard_release(&mut self, mut handler: F, prevent_default: bool) where - F: 'static + FnMut(KeyCode, Key, Option, KeyLocation, bool, ModifiersState), + F: 'static + FnMut(PhysicalKey, Key, Option, KeyLocation, bool, ModifiersState), { self.on_keyboard_release = Some(self.common.add_event("keyup", move |event: KeyboardEvent| { @@ -280,7 +280,7 @@ impl Canvas { pub fn on_keyboard_press(&mut self, mut handler: F, prevent_default: bool) where - F: 'static + FnMut(KeyCode, Key, Option, KeyLocation, bool, ModifiersState), + F: 'static + FnMut(PhysicalKey, Key, Option, KeyLocation, bool, ModifiersState), { self.on_keyboard_press = Some(self.common.add_transient_event( "keydown", diff --git a/src/platform_impl/web/web_sys/event.rs b/src/platform_impl/web/web_sys/event.rs index b3678f125b..c81ed1c4a1 100644 --- a/src/platform_impl/web/web_sys/event.rs +++ b/src/platform_impl/web/web_sys/event.rs @@ -1,6 +1,6 @@ use crate::dpi::LogicalPosition; use crate::event::{MouseButton, MouseScrollDelta}; -use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState}; +use crate::keyboard::{Key, KeyLocation, ModifiersState, NamedKey, PhysicalKey}; use once_cell::unsync::OnceCell; use smol_str::SmolStr; @@ -149,9 +149,9 @@ pub fn mouse_scroll_delta( } } -pub fn key_code(event: &KeyboardEvent) -> KeyCode { +pub fn key_code(event: &KeyboardEvent) -> PhysicalKey { let code = event.code(); - KeyCode::from_key_code_attribute_value(&code) + PhysicalKey::from_key_code_attribute_value(&code) } pub fn key(event: &KeyboardEvent) -> Key { @@ -163,9 +163,9 @@ pub fn key_text(event: &KeyboardEvent) -> Option { let key = Key::from_key_attribute_value(&key); match &key { Key::Character(text) => Some(text.clone()), - Key::Tab => Some(SmolStr::new("\t")), - Key::Enter => Some(SmolStr::new("\r")), - Key::Space => Some(SmolStr::new(" ")), + Key::Named(NamedKey::Tab) => Some(SmolStr::new("\t")), + Key::Named(NamedKey::Enter) => Some(SmolStr::new("\r")), + Key::Named(NamedKey::Space) => Some(SmolStr::new(" ")), _ => None, } .map(SmolStr::new) diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 43b162afae..c29997c241 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -80,8 +80,8 @@ use crate::{ WindowEvent, }, event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, - keyboard::{KeyCode, ModifiersState}, - platform::{pump_events::PumpStatus, scancode::KeyCodeExtScancode}, + keyboard::{KeyCode, ModifiersState, PhysicalKey}, + platform::{pump_events::PumpStatus, scancode::PhysicalKeyExtScancode}, platform_impl::platform::{ dark_mode::try_theme, dpi::{become_dpi_aware, dpi_to_scale_factor}, @@ -2518,7 +2518,7 @@ unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: // https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503 return; } - let code = if keyboard.VKey == VK_NUMLOCK { + let physical_key = if keyboard.VKey == VK_NUMLOCK { // Historically, the NumLock and the Pause key were one and the same physical key. // The user could trigger Pause by pressing Ctrl+NumLock. // Now these are often physically separate and the two keys can be differentiated by @@ -2531,47 +2531,49 @@ unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: // For more on this, read the article by Raymond Chen, titled: // "Why does Ctrl+ScrollLock cancel dialogs?" // https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503 - KeyCode::NumLock + PhysicalKey::Code(KeyCode::NumLock) } else { - KeyCode::from_scancode(scancode as u32) + PhysicalKey::from_scancode(scancode as u32) }; if keyboard.VKey == VK_SHIFT { - match code { - KeyCode::NumpadDecimal - | KeyCode::Numpad0 - | KeyCode::Numpad1 - | KeyCode::Numpad2 - | KeyCode::Numpad3 - | KeyCode::Numpad4 - | KeyCode::Numpad5 - | KeyCode::Numpad6 - | KeyCode::Numpad7 - | KeyCode::Numpad8 - | KeyCode::Numpad9 => { - // On Windows, holding the Shift key makes numpad keys behave as if NumLock - // wasn't active. The way this is exposed to applications by the system is that - // the application receives a fake key release event for the shift key at the - // moment when the numpad key is pressed, just before receiving the numpad key - // as well. - // - // The issue is that in the raw device event (here), the fake shift release - // event reports the numpad key as the scancode. Unfortunately, the event doesn't - // have any information to tell whether it's the left shift or the right shift - // that needs to get the fake release (or press) event so we don't forward this - // event to the application at all. - // - // For more on this, read the article by Raymond Chen, titled: - // "The shift key overrides NumLock" - // https://devblogs.microsoft.com/oldnewthing/20040906-00/?p=37953 - return; + if let PhysicalKey::Code(code) = physical_key { + match code { + KeyCode::NumpadDecimal + | KeyCode::Numpad0 + | KeyCode::Numpad1 + | KeyCode::Numpad2 + | KeyCode::Numpad3 + | KeyCode::Numpad4 + | KeyCode::Numpad5 + | KeyCode::Numpad6 + | KeyCode::Numpad7 + | KeyCode::Numpad8 + | KeyCode::Numpad9 => { + // On Windows, holding the Shift key makes numpad keys behave as if NumLock + // wasn't active. The way this is exposed to applications by the system is that + // the application receives a fake key release event for the shift key at the + // moment when the numpad key is pressed, just before receiving the numpad key + // as well. + // + // The issue is that in the raw device event (here), the fake shift release + // event reports the numpad key as the scancode. Unfortunately, the event doesn't + // have any information to tell whether it's the left shift or the right shift + // that needs to get the fake release (or press) event so we don't forward this + // event to the application at all. + // + // For more on this, read the article by Raymond Chen, titled: + // "The shift key overrides NumLock" + // https://devblogs.microsoft.com/oldnewthing/20040906-00/?p=37953 + return; + } + _ => (), } - _ => (), } } userdata.send_event(Event::DeviceEvent { device_id, event: Key(RawKeyEvent { - physical_key: code, + physical_key, state, }), }); diff --git a/src/platform_impl/windows/keyboard.rs b/src/platform_impl/windows/keyboard.rs index 595cd4c51e..c46136bb3c 100644 --- a/src/platform_impl/windows/keyboard.rs +++ b/src/platform_impl/windows/keyboard.rs @@ -37,8 +37,8 @@ use unicode_segmentation::UnicodeSegmentation; use crate::{ event::{ElementState, KeyEvent}, - keyboard::{Key, KeyCode, KeyLocation, NativeKey, NativeKeyCode}, - platform::scancode::KeyCodeExtScancode, + keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey}, + platform::scancode::PhysicalKeyExtScancode, platform_impl::platform::{ event_loop::ProcResult, keyboard_layout::{Layout, LayoutCache, WindowsModifiers, LAYOUT_CACHE}, @@ -264,8 +264,8 @@ impl KeyEventBuilder { let mod_no_ctrl = mod_state.remove_only_ctrl(); let num_lock_on = kbd_state[VK_NUMLOCK as usize] & 1 != 0; let vkey = event_info.vkey; - let keycode = &event_info.code; - let key = layout.get_key(mod_no_ctrl, num_lock_on, vkey, keycode); + let physical_key = &event_info.physical_key; + let key = layout.get_key(mod_no_ctrl, num_lock_on, vkey, physical_key); event_info.text = PartialText::Text(key.to_text().map(SmolStr::new)); } let ev = event_info.finalize(); @@ -454,15 +454,16 @@ impl KeyEventBuilder { return None; } let scancode = scancode as ExScancode; - let code = KeyCode::from_scancode(scancode as u32); + let physical_key = PhysicalKey::from_scancode(scancode as u32); let mods = if caps_lock_on { WindowsModifiers::CAPS_LOCK } else { WindowsModifiers::empty() }; let layout = layouts.layouts.get(&(locale_id as u64)).unwrap(); - let logical_key = layout.get_key(mods, num_lock_on, vk, &code); - let key_without_modifiers = layout.get_key(WindowsModifiers::empty(), false, vk, &code); + let logical_key = layout.get_key(mods, num_lock_on, vk, &physical_key); + let key_without_modifiers = + layout.get_key(WindowsModifiers::empty(), false, vk, &physical_key); let text = if key_state == ElementState::Pressed { logical_key.to_text().map(SmolStr::new) } else { @@ -474,7 +475,7 @@ impl KeyEventBuilder { key_without_modifiers, key_state, is_repeat: false, - code, + physical_key, location: get_location(scancode, locale_id), utf16parts: Vec::with_capacity(8), text: PartialText::Text(text.clone()), @@ -511,7 +512,7 @@ struct PartialKeyEventInfo { vkey: VIRTUAL_KEY, key_state: ElementState, is_repeat: bool, - code: KeyCode, + physical_key: PhysicalKey, location: KeyLocation, logical_key: PartialLogicalKey, @@ -543,7 +544,7 @@ impl PartialKeyEventInfo { } else { new_ex_scancode(lparam_struct.scancode, lparam_struct.extended) }; - let code = KeyCode::from_scancode(scancode as u32); + let physical_key = PhysicalKey::from_scancode(scancode as u32); let location = get_location(scancode, layout.hkl as HKL); let kbd_state = get_kbd_state(); @@ -558,16 +559,17 @@ impl PartialKeyEventInfo { // "Why does Ctrl+ScrollLock cancel dialogs?" // https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503 let code_as_key = if mods.contains(WindowsModifiers::CONTROL) { - match code { - KeyCode::NumLock => Some(Key::NumLock), - KeyCode::Pause => Some(Key::Pause), + match physical_key { + PhysicalKey::Code(KeyCode::NumLock) => Some(Key::Named(NamedKey::NumLock)), + PhysicalKey::Code(KeyCode::Pause) => Some(Key::Named(NamedKey::Pause)), _ => None, } } else { None }; - let preliminary_logical_key = layout.get_key(mods_without_ctrl, num_lock_on, vkey, &code); + let preliminary_logical_key = + layout.get_key(mods_without_ctrl, num_lock_on, vkey, &physical_key); let key_is_char = matches!(preliminary_logical_key, Key::Character(_)); let is_pressed = state == ElementState::Pressed; @@ -583,7 +585,7 @@ impl PartialKeyEventInfo { let key_without_modifiers = if let Some(key) = code_as_key { key } else { - match layout.get_key(NO_MODS, false, vkey, &code) { + match layout.get_key(NO_MODS, false, vkey, &physical_key) { // We convert dead keys into their character. // The reason for this is that `key_without_modifiers` is designed for key-bindings, // but the US International layout treats `'` (apostrophe) as a dead key and the @@ -609,7 +611,7 @@ impl PartialKeyEventInfo { logical_key, key_without_modifiers, is_repeat: lparam_struct.is_repeat, - code, + physical_key, location, utf16parts: Vec::with_capacity(8), text: PartialText::System(Vec::new()), @@ -656,7 +658,7 @@ impl PartialKeyEventInfo { }; KeyEvent { - physical_key: self.code, + physical_key: self.physical_key, logical_key, text, location: self.location, @@ -740,7 +742,10 @@ fn get_async_kbd_state() -> [u8; 256] { /// the next event is a right Alt (AltGr) event. If this is the case, the current event must be the /// fake Ctrl event. fn is_current_fake(curr_info: &PartialKeyEventInfo, next_msg: MSG, layout: &Layout) -> bool { - let curr_is_ctrl = matches!(curr_info.logical_key, PartialLogicalKey::This(Key::Control)); + let curr_is_ctrl = matches!( + curr_info.logical_key, + PartialLogicalKey::This(Key::Named(NamedKey::Control)) + ); if layout.has_alt_graph { let next_code = ex_scancode_from_lparam(next_msg.lParam); let next_is_altgr = next_code == 0xE038; // 0xE038 is right alt @@ -937,7 +942,7 @@ fn get_location(scancode: ExScancode, hkl: HKL) -> KeyLocation { } } -impl KeyCodeExtScancode for KeyCode { +impl PhysicalKeyExtScancode for PhysicalKey { fn to_scancode(self) -> Option { // See `from_scancode` for more info @@ -946,7 +951,17 @@ impl KeyCodeExtScancode for KeyCode { let primary_lang_id = primarylangid(loword(hkl as u32)); let is_korean = primary_lang_id as u32 == LANG_KOREAN; - match self { + let code = match self { + PhysicalKey::Code(code) => code, + PhysicalKey::Unidentified(code) => { + return match code { + NativeKeyCode::Windows(scancode) => Some(scancode as u32), + _ => None, + }; + } + }; + + match code { KeyCode::Backquote => Some(0x0029), KeyCode::Backslash => Some(0x002B), KeyCode::Backspace => Some(0x000E), @@ -1106,17 +1121,16 @@ impl KeyCodeExtScancode for KeyCode { KeyCode::AudioVolumeDown => Some(0xE02E), KeyCode::AudioVolumeMute => Some(0xE020), KeyCode::AudioVolumeUp => Some(0xE030), - KeyCode::Unidentified(NativeKeyCode::Windows(scancode)) => Some(scancode as u32), _ => None, } } - fn from_scancode(scancode: u32) -> KeyCode { + fn from_scancode(scancode: u32) -> PhysicalKey { // 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 - match scancode { + PhysicalKey::Code(match scancode { 0x0029 => KeyCode::Backquote, 0x002B => KeyCode::Backslash, 0x000E => KeyCode::Backspace, @@ -1266,7 +1280,7 @@ impl KeyCodeExtScancode for KeyCode { 0xE02E => KeyCode::AudioVolumeDown, 0xE020 => KeyCode::AudioVolumeMute, 0xE030 => KeyCode::AudioVolumeUp, - _ => KeyCode::Unidentified(NativeKeyCode::Windows(scancode as u16)), - } + _ => return PhysicalKey::Unidentified(NativeKeyCode::Windows(scancode as u16)), + }) } } diff --git a/src/platform_impl/windows/keyboard_layout.rs b/src/platform_impl/windows/keyboard_layout.rs index 1064cec125..d80267637a 100644 --- a/src/platform_impl/windows/keyboard_layout.rs +++ b/src/platform_impl/windows/keyboard_layout.rs @@ -52,8 +52,8 @@ use windows_sys::Win32::{ }; use crate::{ - keyboard::{Key, KeyCode, ModifiersState, NativeKey}, - platform::scancode::KeyCodeExtScancode, + keyboard::{Key, KeyCode, ModifiersState, NamedKey, NativeKey, PhysicalKey}, + platform::scancode::PhysicalKeyExtScancode, platform_impl::{loword, primarylangid}, }; @@ -224,7 +224,7 @@ impl Layout { mods: WindowsModifiers, num_lock_on: bool, vkey: VIRTUAL_KEY, - keycode: &KeyCode, + physical_key: &PhysicalKey, ) -> Key { let native_code = NativeKey::Windows(vkey); @@ -252,9 +252,11 @@ impl Layout { } else if let Some(key) = self.numlock_off_keys.get(&vkey) { return key.clone(); } - if let Some(keys) = self.keys.get(&mods) { - if let Some(key) = keys.get(keycode) { - return key.clone(); + if let PhysicalKey::Code(code) = physical_key { + if let Some(keys) = self.keys.get(&mods) { + if let Some(key) = keys.get(code) { + return key.clone(); + } } } Key::Unidentified(native_code) @@ -334,7 +336,11 @@ impl LayoutCache { if scancode == 0 { continue; } - let keycode = KeyCode::from_scancode(scancode); + let keycode = match PhysicalKey::from_scancode(scancode) { + PhysicalKey::Code(code) => code, + // TODO: validate that we can skip on unidentified keys (probably never occurs?) + _ => continue, + }; if !is_numpad_specific(vk as VIRTUAL_KEY) && NUMPAD_KEYCODES.contains(&keycode) { let native_code = NativeKey::Windows(vk as VIRTUAL_KEY); let map_vkey = keycode_to_vkey(keycode, locale_id); @@ -382,7 +388,11 @@ impl LayoutCache { } let native_code = NativeKey::Windows(vk as VIRTUAL_KEY); - let key_code = KeyCode::from_scancode(scancode); + let key_code = match PhysicalKey::from_scancode(scancode) { + PhysicalKey::Code(code) => code, + // TODO: validate that we can skip on unidentified keys (probably never occurs?) + _ => continue, + }; // Let's try to get the key from just the scancode and vk // We don't necessarily know yet if AltGraph is present on this layout so we'll // assume it isn't. Then we'll do a second pass where we set the "AltRight" keys to @@ -446,7 +456,7 @@ impl LayoutCache { let mod_state = WindowsModifiers::from_bits_retain(mod_state); if let Some(keys) = layout.keys.get_mut(&mod_state) { if let Some(key) = keys.get_mut(&KeyCode::AltRight) { - *key = Key::AltGraph; + *key = Key::Named(NamedKey::AltGraph); } } } @@ -733,7 +743,6 @@ fn keycode_to_vkey(keycode: KeyCode, hkl: u64) -> VIRTUAL_KEY { KeyCode::F33 => 0, KeyCode::F34 => 0, KeyCode::F35 => 0, - KeyCode::Unidentified(_) => 0, _ => 0, } } @@ -769,56 +778,56 @@ fn vkey_to_non_char_key( VK_MBUTTON => Key::Unidentified(NativeKey::Unidentified), // Mouse VK_XBUTTON1 => Key::Unidentified(NativeKey::Unidentified), // Mouse VK_XBUTTON2 => Key::Unidentified(NativeKey::Unidentified), // Mouse - VK_BACK => Key::Backspace, - VK_TAB => Key::Tab, - VK_CLEAR => Key::Clear, - VK_RETURN => Key::Enter, - VK_SHIFT => Key::Shift, - VK_CONTROL => Key::Control, - VK_MENU => Key::Alt, - VK_PAUSE => Key::Pause, - VK_CAPITAL => Key::CapsLock, - - //VK_HANGEUL => Key::HangulMode, // Deprecated in favour of VK_HANGUL + VK_BACK => Key::Named(NamedKey::Backspace), + VK_TAB => Key::Named(NamedKey::Tab), + VK_CLEAR => Key::Named(NamedKey::Clear), + VK_RETURN => Key::Named(NamedKey::Enter), + VK_SHIFT => Key::Named(NamedKey::Shift), + VK_CONTROL => Key::Named(NamedKey::Control), + VK_MENU => Key::Named(NamedKey::Alt), + VK_PAUSE => Key::Named(NamedKey::Pause), + VK_CAPITAL => Key::Named(NamedKey::CapsLock), + + //VK_HANGEUL => Key::Named(NamedKey::HangulMode), // Deprecated in favour of VK_HANGUL // VK_HANGUL and VK_KANA are defined as the same constant, therefore // we use appropriate conditions to differentate between them - VK_HANGUL if is_korean => Key::HangulMode, - VK_KANA if is_japanese => Key::KanaMode, + VK_HANGUL if is_korean => Key::Named(NamedKey::HangulMode), + VK_KANA if is_japanese => Key::Named(NamedKey::KanaMode), - VK_JUNJA => Key::JunjaMode, - VK_FINAL => Key::FinalMode, + VK_JUNJA => Key::Named(NamedKey::JunjaMode), + VK_FINAL => Key::Named(NamedKey::FinalMode), // VK_HANJA and VK_KANJI are defined as the same constant, therefore // we use appropriate conditions to differentate between them - VK_HANJA if is_korean => Key::HanjaMode, - VK_KANJI if is_japanese => Key::KanjiMode, - - VK_ESCAPE => Key::Escape, - VK_CONVERT => Key::Convert, - VK_NONCONVERT => Key::NonConvert, - VK_ACCEPT => Key::Accept, - VK_MODECHANGE => Key::ModeChange, - VK_SPACE => Key::Space, - VK_PRIOR => Key::PageUp, - VK_NEXT => Key::PageDown, - VK_END => Key::End, - VK_HOME => Key::Home, - VK_LEFT => Key::ArrowLeft, - VK_UP => Key::ArrowUp, - VK_RIGHT => Key::ArrowRight, - VK_DOWN => Key::ArrowDown, - VK_SELECT => Key::Select, - VK_PRINT => Key::Print, - VK_EXECUTE => Key::Execute, - VK_SNAPSHOT => Key::PrintScreen, - VK_INSERT => Key::Insert, - VK_DELETE => Key::Delete, - VK_HELP => Key::Help, - VK_LWIN => Key::Super, - VK_RWIN => Key::Super, - VK_APPS => Key::ContextMenu, - VK_SLEEP => Key::Standby, + VK_HANJA if is_korean => Key::Named(NamedKey::HanjaMode), + VK_KANJI if is_japanese => Key::Named(NamedKey::KanjiMode), + + VK_ESCAPE => Key::Named(NamedKey::Escape), + VK_CONVERT => Key::Named(NamedKey::Convert), + VK_NONCONVERT => Key::Named(NamedKey::NonConvert), + VK_ACCEPT => Key::Named(NamedKey::Accept), + VK_MODECHANGE => Key::Named(NamedKey::ModeChange), + VK_SPACE => Key::Named(NamedKey::Space), + VK_PRIOR => Key::Named(NamedKey::PageUp), + VK_NEXT => Key::Named(NamedKey::PageDown), + VK_END => Key::Named(NamedKey::End), + VK_HOME => Key::Named(NamedKey::Home), + VK_LEFT => Key::Named(NamedKey::ArrowLeft), + VK_UP => Key::Named(NamedKey::ArrowUp), + VK_RIGHT => Key::Named(NamedKey::ArrowRight), + VK_DOWN => Key::Named(NamedKey::ArrowDown), + VK_SELECT => Key::Named(NamedKey::Select), + VK_PRINT => Key::Named(NamedKey::Print), + VK_EXECUTE => Key::Named(NamedKey::Execute), + VK_SNAPSHOT => Key::Named(NamedKey::PrintScreen), + VK_INSERT => Key::Named(NamedKey::Insert), + VK_DELETE => Key::Named(NamedKey::Delete), + VK_HELP => Key::Named(NamedKey::Help), + VK_LWIN => Key::Named(NamedKey::Super), + VK_RWIN => Key::Named(NamedKey::Super), + VK_APPS => Key::Named(NamedKey::ContextMenu), + VK_SLEEP => Key::Named(NamedKey::Standby), // Numpad keys produce characters VK_NUMPAD0 => Key::Unidentified(native_code), @@ -838,30 +847,30 @@ fn vkey_to_non_char_key( VK_DECIMAL => Key::Unidentified(native_code), VK_DIVIDE => Key::Unidentified(native_code), - VK_F1 => Key::F1, - VK_F2 => Key::F2, - VK_F3 => Key::F3, - VK_F4 => Key::F4, - VK_F5 => Key::F5, - VK_F6 => Key::F6, - VK_F7 => Key::F7, - VK_F8 => Key::F8, - VK_F9 => Key::F9, - VK_F10 => Key::F10, - VK_F11 => Key::F11, - VK_F12 => Key::F12, - VK_F13 => Key::F13, - VK_F14 => Key::F14, - VK_F15 => Key::F15, - VK_F16 => Key::F16, - VK_F17 => Key::F17, - VK_F18 => Key::F18, - VK_F19 => Key::F19, - VK_F20 => Key::F20, - VK_F21 => Key::F21, - VK_F22 => Key::F22, - VK_F23 => Key::F23, - VK_F24 => Key::F24, + VK_F1 => Key::Named(NamedKey::F1), + VK_F2 => Key::Named(NamedKey::F2), + VK_F3 => Key::Named(NamedKey::F3), + VK_F4 => Key::Named(NamedKey::F4), + VK_F5 => Key::Named(NamedKey::F5), + VK_F6 => Key::Named(NamedKey::F6), + VK_F7 => Key::Named(NamedKey::F7), + VK_F8 => Key::Named(NamedKey::F8), + VK_F9 => Key::Named(NamedKey::F9), + VK_F10 => Key::Named(NamedKey::F10), + VK_F11 => Key::Named(NamedKey::F11), + VK_F12 => Key::Named(NamedKey::F12), + VK_F13 => Key::Named(NamedKey::F13), + VK_F14 => Key::Named(NamedKey::F14), + VK_F15 => Key::Named(NamedKey::F15), + VK_F16 => Key::Named(NamedKey::F16), + VK_F17 => Key::Named(NamedKey::F17), + VK_F18 => Key::Named(NamedKey::F18), + VK_F19 => Key::Named(NamedKey::F19), + VK_F20 => Key::Named(NamedKey::F20), + VK_F21 => Key::Named(NamedKey::F21), + VK_F22 => Key::Named(NamedKey::F22), + VK_F23 => Key::Named(NamedKey::F23), + VK_F24 => Key::Named(NamedKey::F24), VK_NAVIGATION_VIEW => Key::Unidentified(native_code), VK_NAVIGATION_MENU => Key::Unidentified(native_code), VK_NAVIGATION_UP => Key::Unidentified(native_code), @@ -870,44 +879,44 @@ fn vkey_to_non_char_key( VK_NAVIGATION_RIGHT => Key::Unidentified(native_code), VK_NAVIGATION_ACCEPT => Key::Unidentified(native_code), VK_NAVIGATION_CANCEL => Key::Unidentified(native_code), - VK_NUMLOCK => Key::NumLock, - VK_SCROLL => Key::ScrollLock, + VK_NUMLOCK => Key::Named(NamedKey::NumLock), + VK_SCROLL => Key::Named(NamedKey::ScrollLock), VK_OEM_NEC_EQUAL => Key::Unidentified(native_code), //VK_OEM_FJ_JISHO => Key::Unidentified(native_code), // Conflicts with `VK_OEM_NEC_EQUAL` VK_OEM_FJ_MASSHOU => Key::Unidentified(native_code), VK_OEM_FJ_TOUROKU => Key::Unidentified(native_code), VK_OEM_FJ_LOYA => Key::Unidentified(native_code), VK_OEM_FJ_ROYA => Key::Unidentified(native_code), - VK_LSHIFT => Key::Shift, - VK_RSHIFT => Key::Shift, - VK_LCONTROL => Key::Control, - VK_RCONTROL => Key::Control, - VK_LMENU => Key::Alt, + VK_LSHIFT => Key::Named(NamedKey::Shift), + VK_RSHIFT => Key::Named(NamedKey::Shift), + VK_LCONTROL => Key::Named(NamedKey::Control), + VK_RCONTROL => Key::Named(NamedKey::Control), + VK_LMENU => Key::Named(NamedKey::Alt), VK_RMENU => { if has_alt_graph { - Key::AltGraph + Key::Named(NamedKey::AltGraph) } else { - Key::Alt + Key::Named(NamedKey::Alt) } } - VK_BROWSER_BACK => Key::BrowserBack, - VK_BROWSER_FORWARD => Key::BrowserForward, - VK_BROWSER_REFRESH => Key::BrowserRefresh, - VK_BROWSER_STOP => Key::BrowserStop, - VK_BROWSER_SEARCH => Key::BrowserSearch, - VK_BROWSER_FAVORITES => Key::BrowserFavorites, - VK_BROWSER_HOME => Key::BrowserHome, - VK_VOLUME_MUTE => Key::AudioVolumeMute, - VK_VOLUME_DOWN => Key::AudioVolumeDown, - VK_VOLUME_UP => Key::AudioVolumeUp, - VK_MEDIA_NEXT_TRACK => Key::MediaTrackNext, - VK_MEDIA_PREV_TRACK => Key::MediaTrackPrevious, - VK_MEDIA_STOP => Key::MediaStop, - VK_MEDIA_PLAY_PAUSE => Key::MediaPlayPause, - VK_LAUNCH_MAIL => Key::LaunchMail, - VK_LAUNCH_MEDIA_SELECT => Key::LaunchMediaPlayer, - VK_LAUNCH_APP1 => Key::LaunchApplication1, - VK_LAUNCH_APP2 => Key::LaunchApplication2, + VK_BROWSER_BACK => Key::Named(NamedKey::BrowserBack), + VK_BROWSER_FORWARD => Key::Named(NamedKey::BrowserForward), + VK_BROWSER_REFRESH => Key::Named(NamedKey::BrowserRefresh), + VK_BROWSER_STOP => Key::Named(NamedKey::BrowserStop), + VK_BROWSER_SEARCH => Key::Named(NamedKey::BrowserSearch), + VK_BROWSER_FAVORITES => Key::Named(NamedKey::BrowserFavorites), + VK_BROWSER_HOME => Key::Named(NamedKey::BrowserHome), + VK_VOLUME_MUTE => Key::Named(NamedKey::AudioVolumeMute), + VK_VOLUME_DOWN => Key::Named(NamedKey::AudioVolumeDown), + VK_VOLUME_UP => Key::Named(NamedKey::AudioVolumeUp), + VK_MEDIA_NEXT_TRACK => Key::Named(NamedKey::MediaTrackNext), + VK_MEDIA_PREV_TRACK => Key::Named(NamedKey::MediaTrackPrevious), + VK_MEDIA_STOP => Key::Named(NamedKey::MediaStop), + VK_MEDIA_PLAY_PAUSE => Key::Named(NamedKey::MediaPlayPause), + VK_LAUNCH_MAIL => Key::Named(NamedKey::LaunchMail), + VK_LAUNCH_MEDIA_SELECT => Key::Named(NamedKey::LaunchMediaPlayer), + VK_LAUNCH_APP1 => Key::Named(NamedKey::LaunchApplication1), + VK_LAUNCH_APP2 => Key::Named(NamedKey::LaunchApplication2), // This function only converts "non-printable" VK_OEM_1 => Key::Unidentified(native_code), @@ -955,7 +964,7 @@ fn vkey_to_non_char_key( VK_ICO_HELP => Key::Unidentified(native_code), VK_ICO_00 => Key::Unidentified(native_code), - VK_PROCESSKEY => Key::Process, + VK_PROCESSKEY => Key::Named(NamedKey::Process), VK_ICO_CLEAR => Key::Unidentified(native_code), VK_PACKET => Key::Unidentified(native_code), @@ -967,32 +976,32 @@ fn vkey_to_non_char_key( VK_OEM_WSCTRL => Key::Unidentified(native_code), VK_OEM_CUSEL => Key::Unidentified(native_code), - VK_OEM_ATTN => Key::Attn, + VK_OEM_ATTN => Key::Named(NamedKey::Attn), VK_OEM_FINISH => { if is_japanese { - Key::Katakana + Key::Named(NamedKey::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 `Key::Finish` variant as + // At the time of writing, there is no `NamedKey::Finish` variant as // Finish is not mentionned at https://w3c.github.io/uievents-key/ // Also see: https://github.com/pyfisch/keyboard-types/issues/9 Key::Unidentified(native_code) } } - VK_OEM_COPY => Key::Copy, - VK_OEM_AUTO => Key::Hankaku, - VK_OEM_ENLW => Key::Zenkaku, - VK_OEM_BACKTAB => Key::Romaji, - VK_ATTN => Key::KanaMode, - VK_CRSEL => Key::CrSel, - VK_EXSEL => Key::ExSel, - VK_EREOF => Key::EraseEof, - VK_PLAY => Key::Play, - VK_ZOOM => Key::ZoomToggle, + VK_OEM_COPY => Key::Named(NamedKey::Copy), + VK_OEM_AUTO => Key::Named(NamedKey::Hankaku), + VK_OEM_ENLW => Key::Named(NamedKey::Zenkaku), + VK_OEM_BACKTAB => Key::Named(NamedKey::Romaji), + VK_ATTN => Key::Named(NamedKey::KanaMode), + VK_CRSEL => Key::Named(NamedKey::CrSel), + VK_EXSEL => Key::Named(NamedKey::ExSel), + VK_EREOF => Key::Named(NamedKey::EraseEof), + VK_PLAY => Key::Named(NamedKey::Play), + VK_ZOOM => Key::Named(NamedKey::ZoomToggle), VK_NONAME => Key::Unidentified(native_code), VK_PA1 => Key::Unidentified(native_code), - VK_OEM_CLEAR => Key::Clear, + VK_OEM_CLEAR => Key::Named(NamedKey::Clear), _ => Key::Unidentified(native_code), } } diff --git a/tests/serde_objects.rs b/tests/serde_objects.rs index fccc202b1e..02b249b555 100644 --- a/tests/serde_objects.rs +++ b/tests/serde_objects.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use winit::{ dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}, event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase}, - keyboard::{Key, KeyCode, KeyLocation, ModifiersState}, + keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey, PhysicalKey}, window::CursorIcon, }; @@ -23,7 +23,9 @@ fn events_serde() { needs_serde::(); needs_serde::(); needs_serde::(); + needs_serde::(); needs_serde::(); + needs_serde::(); needs_serde::(); needs_serde::(); }