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 <contact@kchibisov.com>
This commit is contained in:
Diggory Hardy 2023-10-19 15:27:49 +01:00 committed by GitHub
parent b9e1e96eaa
commit acfeff5327
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 1456 additions and 1277 deletions

View file

@ -10,7 +10,7 @@ use simple_logger::SimpleLogger;
use winit::{ use winit::{
event::{ElementState, Event, KeyEvent, WindowEvent}, event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
keyboard::Key, keyboard::{Key, NamedKey},
window::WindowBuilder, window::WindowBuilder,
}; };
@ -88,7 +88,7 @@ fn main() -> Result<(), impl std::error::Error> {
request_redraw = !request_redraw; request_redraw = !request_redraw;
println!("\nrequest_redraw: {request_redraw}\n"); println!("\nrequest_redraw: {request_redraw}\n");
} }
Key::Escape => { Key::Named(NamedKey::Escape) => {
close_requested = true; close_requested = true;
} }
_ => (), _ => (),

View file

@ -4,7 +4,7 @@ use simple_logger::SimpleLogger;
use winit::{ use winit::{
event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent}, event::{DeviceEvent, ElementState, Event, KeyEvent, WindowEvent},
event_loop::EventLoop, event_loop::EventLoop,
keyboard::{Key, ModifiersState}, keyboard::{Key, ModifiersState, NamedKey},
window::{CursorGrabMode, WindowBuilder}, window::{CursorGrabMode, WindowBuilder},
}; };
@ -35,7 +35,7 @@ fn main() -> Result<(), impl std::error::Error> {
.. ..
} => { } => {
let result = match key { let result = match key {
Key::Escape => { Key::Named(NamedKey::Escape) => {
elwt.exit(); elwt.exit();
Ok(()) Ok(())
} }

View file

@ -4,7 +4,7 @@ use simple_logger::SimpleLogger;
use winit::dpi::PhysicalSize; use winit::dpi::PhysicalSize;
use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; use winit::event::{ElementState, Event, KeyEvent, WindowEvent};
use winit::event_loop::EventLoop; use winit::event_loop::EventLoop;
use winit::keyboard::Key; use winit::keyboard::{Key, NamedKey};
use winit::window::{Fullscreen, WindowBuilder}; use winit::window::{Fullscreen, WindowBuilder};
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@ -65,7 +65,7 @@ fn main() -> Result<(), impl std::error::Error> {
}, },
.. ..
} => match key { } => match key {
Key::Escape => elwt.exit(), Key::Named(NamedKey::Escape) => elwt.exit(),
// WARNING: Consider using `key_without_modifers()` if available on your platform. // WARNING: Consider using `key_without_modifers()` if available on your platform.
// See the `key_binding` example // See the `key_binding` example
Key::Character(ch) => match ch.to_lowercase().as_str() { Key::Character(ch) => match ch.to_lowercase().as_str() {

View file

@ -6,7 +6,7 @@ use winit::{
dpi::{PhysicalPosition, PhysicalSize}, dpi::{PhysicalPosition, PhysicalSize},
event::{ElementState, Event, Ime, WindowEvent}, event::{ElementState, Event, Ime, WindowEvent},
event_loop::EventLoop, event_loop::EventLoop,
keyboard::{Key, KeyCode}, keyboard::NamedKey,
window::{ImePurpose, WindowBuilder}, window::{ImePurpose, WindowBuilder},
}; };
@ -69,12 +69,12 @@ fn main() -> Result<(), impl std::error::Error> {
WindowEvent::KeyboardInput { event, .. } => { WindowEvent::KeyboardInput { event, .. } => {
println!("key: {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; ime_allowed = !ime_allowed;
window.set_ime_allowed(ime_allowed); window.set_ime_allowed(ime_allowed);
println!("\nIME allowed: {ime_allowed}\n"); 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 { ime_purpose = match ime_purpose {
ImePurpose::Normal => ImePurpose::Password, ImePurpose::Normal => ImePurpose::Password,
ImePurpose::Password => ImePurpose::Terminal, ImePurpose::Password => ImePurpose::Terminal,

View file

@ -9,7 +9,7 @@ fn main() -> Result<(), impl std::error::Error> {
dpi::{PhysicalPosition, PhysicalSize, Position, Size}, dpi::{PhysicalPosition, PhysicalSize, Position, Size},
event::{ElementState, Event, KeyEvent, WindowEvent}, event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::EventLoop, event_loop::EventLoop,
keyboard::{Key, ModifiersState}, keyboard::{Key, ModifiersState, NamedKey},
window::{CursorGrabMode, CursorIcon, Fullscreen, WindowBuilder, WindowLevel}, 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:?}")); window.set_title(&format!("{key:?}"));
let state = !modifiers.shift_key(); let state = !modifiers.shift_key();
match key { match key {
// Cycle through video modes // Cycle through video modes
Key::ArrowRight | Key::ArrowLeft => { Key::Named(ArrowRight) | Key::Named(ArrowLeft) => {
video_mode_id = match key { if key == ArrowLeft {
ArrowLeft => video_mode_id.saturating_sub(1), video_mode_id = video_mode_id.saturating_sub(1);
ArrowRight => (video_modes.len() - 1).min(video_mode_id + 1), } else if key == ArrowRight {
_ => unreachable!(), video_mode_id = (video_modes.len() - 1).min(video_mode_id + 1);
}; }
println!("Picking video mode: {}", video_modes[video_mode_id]); println!("Picking video mode: {}", video_modes[video_mode_id]);
} }
// WARNING: Consider using `key_without_modifers()` if available on your platform. // WARNING: Consider using `key_without_modifers()` if available on your platform.
@ -185,7 +185,7 @@ fn main() -> Result<(), impl std::error::Error> {
event: event:
KeyEvent { KeyEvent {
state: ElementState::Released, state: ElementState::Released,
logical_key: Key::Escape, logical_key: Key::Named(NamedKey::Escape),
.. ..
}, },
.. ..

View file

@ -4,9 +4,9 @@ use std::collections::HashMap;
use simple_logger::SimpleLogger; use simple_logger::SimpleLogger;
use winit::{ use winit::{
event::{ElementState, Event, KeyEvent, WindowEvent}, event::{ElementState, Event, WindowEvent},
event_loop::EventLoop, event_loop::EventLoop,
keyboard::Key, keyboard::{Key, NamedKey},
window::Window, window::Window,
}; };
@ -40,19 +40,18 @@ fn main() -> Result<(), impl std::error::Error> {
} }
} }
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
event: event,
KeyEvent {
state: ElementState::Pressed,
logical_key: Key::Character(c),
..
},
is_synthetic: false, is_synthetic: false,
.. ..
} if matches!(c.as_ref(), "n" | "N") => { } if event.state == ElementState::Pressed => match event.logical_key {
let window = Window::new(elwt).unwrap(); Key::Named(NamedKey::Escape) => elwt.exit(),
println!("Opened a new window: {:?}", window.id()); Key::Character(c) if c == "n" || c == "N" => {
windows.insert(window.id(), window); let window = Window::new(elwt).unwrap();
} println!("Opened a new window: {:?}", window.id());
windows.insert(window.id(), window);
}
_ => (),
},
WindowEvent::RedrawRequested => { WindowEvent::RedrawRequested => {
if let Some(window) = windows.get(&window_id) { if let Some(window) = windows.get(&window_id) {
fill::fill_window(window); fill::fill_window(window);

View file

@ -5,7 +5,7 @@ use winit::{
dpi::LogicalSize, dpi::LogicalSize,
event::{ElementState, Event, KeyEvent, WindowEvent}, event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::EventLoop, event_loop::EventLoop,
keyboard::KeyCode, keyboard::{KeyCode, PhysicalKey},
window::WindowBuilder, window::WindowBuilder,
}; };
@ -34,7 +34,7 @@ fn main() -> Result<(), impl std::error::Error> {
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
event: event:
KeyEvent { KeyEvent {
physical_key: KeyCode::Space, physical_key: PhysicalKey::Code(KeyCode::Space),
state: ElementState::Released, state: ElementState::Released,
.. ..
}, },

View file

@ -11,7 +11,6 @@ mod example {
use winit::event::{ElementState, Event, KeyEvent, WindowEvent}; use winit::event::{ElementState, Event, KeyEvent, WindowEvent};
use winit::event_loop::EventLoop; use winit::event_loop::EventLoop;
use winit::keyboard::Key;
use winit::platform::startup_notify::{ use winit::platform::startup_notify::{
EventLoopExtStartupNotify, WindowBuilderExtStartupNotify, WindowExtStartupNotify, 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) { if let Some(window) = windows.get(&window_id) {
// Request a new activation token on this window. // Request a new activation token on this window.
// Once we get it we will use it to create a window. // Once we get it we will use it to create a window.

View file

@ -3,7 +3,7 @@
use winit::{ use winit::{
event::{ElementState, Event, KeyEvent, WindowEvent}, event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::EventLoop, event_loop::EventLoop,
keyboard::KeyCode, keyboard::Key,
window::{Fullscreen, WindowBuilder}, window::{Fullscreen, WindowBuilder},
}; };
@ -39,13 +39,13 @@ pub fn main() -> Result<(), impl std::error::Error> {
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput {
event: event:
KeyEvent { KeyEvent {
physical_key: KeyCode::KeyF, logical_key: Key::Character(c),
state: ElementState::Released, state: ElementState::Released,
.. ..
}, },
.. ..
}, },
} if window_id == window.id() => { } if window_id == window.id() && c == "f" => {
if window.fullscreen().is_some() { if window.fullscreen().is_some() {
window.set_fullscreen(None); window.set_fullscreen(None);
} else { } else {

View file

@ -7,7 +7,7 @@ use winit::{
dpi::{LogicalSize, PhysicalSize}, dpi::{LogicalSize, PhysicalSize},
event::{DeviceEvent, ElementState, Event, KeyEvent, RawKeyEvent, WindowEvent}, event::{DeviceEvent, ElementState, Event, KeyEvent, RawKeyEvent, WindowEvent},
event_loop::{DeviceEvents, EventLoop}, event_loop::{DeviceEvents, EventLoop},
keyboard::{Key, KeyCode}, keyboard::{Key, KeyCode, PhysicalKey},
window::{Fullscreen, WindowBuilder}, window::{Fullscreen, WindowBuilder},
}; };
@ -51,14 +51,14 @@ fn main() -> Result<(), impl std::error::Error> {
}), }),
.. ..
} => match physical_key { } => match physical_key {
KeyCode::KeyM => { PhysicalKey::Code(KeyCode::KeyM) => {
if minimized { if minimized {
minimized = !minimized; minimized = !minimized;
window.set_minimized(minimized); window.set_minimized(minimized);
window.focus_window(); window.focus_window();
} }
} }
KeyCode::KeyV => { PhysicalKey::Code(KeyCode::KeyV) => {
if !visible { if !visible {
visible = !visible; visible = !visible;
window.set_visible(visible); window.set_visible(visible);

View file

@ -2,9 +2,9 @@ use log::debug;
use simple_logger::SimpleLogger; use simple_logger::SimpleLogger;
use winit::{ use winit::{
dpi::LogicalSize, dpi::LogicalSize,
event::{ElementState, Event, KeyEvent, WindowEvent}, event::{ElementState, Event, WindowEvent},
event_loop::EventLoop, event_loop::EventLoop,
keyboard::Key, keyboard::NamedKey,
window::WindowBuilder, window::WindowBuilder,
}; };
@ -27,15 +27,10 @@ fn main() -> Result<(), impl std::error::Error> {
event_loop.run(move |event, elwt| match event { event_loop.run(move |event, elwt| match event {
Event::WindowEvent { event, window_id } if window_id == window.id() => match event { Event::WindowEvent { event, window_id } if window_id == window.id() => match event {
WindowEvent::CloseRequested => elwt.exit(), WindowEvent::CloseRequested => elwt.exit(),
WindowEvent::KeyboardInput { WindowEvent::KeyboardInput { event, .. }
event: if event.logical_key == NamedKey::Space
KeyEvent { && event.state == ElementState::Released =>
logical_key: Key::Space, {
state: ElementState::Released,
..
},
..
} => {
has_increments = !has_increments; has_increments = !has_increments;
let new_increments = match window.resize_increments() { let new_increments = match window.resize_increments() {

View file

@ -9,7 +9,7 @@ use simple_logger::SimpleLogger;
use winit::{ use winit::{
event::{ElementState, Event, KeyEvent, WindowEvent}, event::{ElementState, Event, KeyEvent, WindowEvent},
event_loop::EventLoop, event_loop::EventLoop,
keyboard::Key, keyboard::{Key, NamedKey},
platform::macos::{WindowBuilderExtMacOS, WindowExtMacOS}, platform::macos::{WindowBuilderExtMacOS, WindowExtMacOS},
window::{Window, WindowBuilder}, window::{Window, WindowBuilder},
}; };
@ -70,10 +70,10 @@ fn main() -> Result<(), impl std::error::Error> {
Key::Character("w") => { Key::Character("w") => {
let _ = windows.remove(&window_id); let _ = windows.remove(&window_id);
} }
Key::ArrowRight => { Key::Named(NamedKey::ArrowRight) => {
windows.get(&window_id).unwrap().select_next_tab(); windows.get(&window_id).unwrap().select_next_tab();
} }
Key::ArrowLeft => { Key::Named(NamedKey::ArrowLeft) => {
windows.get(&window_id).unwrap().select_previous_tab(); windows.get(&window_id).unwrap().select_previous_tab();
} }
Key::Character(ch) => { Key::Character(ch) => {

View file

@ -671,7 +671,7 @@ pub enum DeviceEvent {
#[derive(Debug, Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct RawKeyEvent { pub struct RawKeyEvent {
pub physical_key: keyboard::KeyCode, pub physical_key: keyboard::PhysicalKey,
pub state: ElementState, 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 /// `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 /// 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 :) /// 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 // Allowing `broken_intra_doc_links` for `logical_key`, because
// `key_without_modifiers` is not available on all platforms // `key_without_modifiers` is not available on all platforms
@ -743,7 +743,7 @@ pub struct KeyEvent {
/// An additional difference from `logical_key` is that /// An additional difference from `logical_key` is that
/// this field stores the text representation of any key /// this field stores the text representation of any key
/// that has such a representation. For example when /// 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 /// This is `None` if the current keypress cannot
/// be interpreted as text. /// be interpreted as text.

View file

@ -185,26 +185,112 @@ impl std::fmt::Debug for NativeKey {
} }
} }
impl From<NativeKeyCode> 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<NativeKey> 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<NativeKeyCode> for NativeKey {
#[inline]
fn eq(&self, rhs: &NativeKeyCode) -> bool {
rhs == self
}
}
/// Represents the location of a physical key. /// 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<KeyCode> for PhysicalKey {
#[inline]
fn from(code: KeyCode) -> Self {
PhysicalKey::Code(code)
}
}
impl From<NativeKeyCode> for PhysicalKey {
#[inline]
fn from(code: NativeKeyCode) -> Self {
PhysicalKey::Unidentified(code)
}
}
impl PartialEq<KeyCode> for PhysicalKey {
#[inline]
fn eq(&self, rhs: &KeyCode) -> bool {
match self {
PhysicalKey::Code(ref code) => code == rhs,
_ => false,
}
}
}
impl PartialEq<PhysicalKey> for KeyCode {
#[inline]
fn eq(&self, rhs: &PhysicalKey) -> bool {
rhs == self
}
}
impl PartialEq<NativeKeyCode> for PhysicalKey {
#[inline]
fn eq(&self, rhs: &NativeKeyCode) -> bool {
match self {
PhysicalKey::Unidentified(ref code) => code == rhs,
_ => false,
}
}
}
impl PartialEq<PhysicalKey> 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 /// This mostly conforms to the UI Events Specification's [`KeyboardEvent.code`] with a few
/// exceptions: /// exceptions:
/// - The keys that the specification calls "MetaLeft" and "MetaRight" are named "SuperLeft" and /// - The keys that the specification calls "MetaLeft" and "MetaRight" are named "SuperLeft" and
/// "SuperRight" here. /// "SuperRight" here.
/// - The key that the specification calls "Super" is reported as `Unidentified` 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 /// [`KeyboardEvent.code`]: https://w3c.github.io/uievents-code/#code-value-tables
#[non_exhaustive] #[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum KeyCode { 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),
/// <kbd>`</kbd> on a US keyboard. This is also called a backtick or grave. /// <kbd>`</kbd> on a US keyboard. This is also called a backtick or grave.
/// This is the <kbd>半角</kbd>/<kbd>全角</kbd>/<kbd>漢字</kbd> /// This is the <kbd>半角</kbd>/<kbd>全角</kbd>/<kbd>漢字</kbd>
/// (hankaku/zenkaku/kanji) key on Japanese keyboards /// (hankaku/zenkaku/kanji) key on Japanese keyboards
@ -648,7 +734,7 @@ pub enum KeyCode {
F35, 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 /// This mostly conforms to the UI Events Specification's [`KeyboardEvent.key`] with a few
/// exceptions: /// exceptions:
@ -656,32 +742,12 @@ pub enum KeyCode {
/// another key which the specification calls `Super`. That does not exist here.) /// 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 /// - The `Space` variant here, can be identified by the character it generates in the
/// specificaiton. /// 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/ /// [`KeyboardEvent.key`]: https://w3c.github.io/uievents-key/
#[non_exhaustive] #[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))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Key<Str = SmolStr> { pub enum NamedKey {
/// A key string that corresponds to the character typed by the user, taking into account the
/// users 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<char>),
/// The `Alt` (Alternative) key. /// The `Alt` (Alternative) key.
/// ///
/// This key enables the alternate modifier function for interpreting concurrent or subsequent /// This key enables the alternate modifier function for interpreting concurrent or subsequent
@ -1385,83 +1451,131 @@ pub enum Key<Str = SmolStr> {
F35, F35,
} }
macro_rules! map_match { /// Key represents the meaning of a keypress.
( ///
$to_match:expr, /// This is a superset of the UI Events Specification's [`KeyboardEvent.key`] with
// Custom match arms /// additions:
{ $( $from:pat => $to:expr ),* }, /// - All simple variants are wrapped under the `Named` variant
// The enum's name /// - The `Unidentified` variant here, can still identifiy a key through it's `NativeKeyCode`.
$prefix:path, /// - The `Dead` variant here, can specify the character which is inserted when pressing the
// Trivial match arms for unit variants /// dead-key twice.
{ $( $t:tt ),* }) => { ///
match $to_match { /// [`KeyboardEvent.key`]: https://w3c.github.io/uievents-key/
$( $from => $to, )* #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
$( Key::$t => Key::$t, )* #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Key<Str = SmolStr> {
/// A simple (unparameterised) action
Named(NamedKey),
/// A key string that corresponds to the character typed by the user, taking into account the
/// users 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<char>),
}
impl From<NamedKey> for Key {
#[inline]
fn from(action: NamedKey) -> Self {
Key::Named(action)
}
}
impl From<NativeKey> for Key {
#[inline]
fn from(code: NativeKey) -> Self {
Key::Unidentified(code)
}
}
impl<Str> PartialEq<NamedKey> for Key<Str> {
#[inline]
fn eq(&self, rhs: &NamedKey) -> bool {
match self {
Key::Named(ref a) => a == rhs,
_ => false,
} }
}; }
}
impl<Str: PartialEq<str>> PartialEq<str> for Key<Str> {
#[inline]
fn eq(&self, rhs: &str) -> bool {
match self {
Key::Character(ref s) => s == rhs,
_ => false,
}
}
}
impl<Str: PartialEq<str>> PartialEq<&str> for Key<Str> {
#[inline]
fn eq(&self, rhs: &&str) -> bool {
self == *rhs
}
}
impl<Str> PartialEq<NativeKey> for Key<Str> {
#[inline]
fn eq(&self, rhs: &NativeKey) -> bool {
match self {
Key::Unidentified(ref code) => code == rhs,
_ => false,
}
}
}
impl<Str> PartialEq<Key<Str>> for NativeKey {
#[inline]
fn eq(&self, rhs: &Key<Str>) -> bool {
rhs == self
}
} }
impl Key<SmolStr> { impl Key<SmolStr> {
/// Convert `Key::Character(SmolStr)` to `Key::Character(&str)` so you can more easily match on /// Convert `Key::Character(SmolStr)` to `Key::Character(&str)` so you can more easily match on
/// `Key`. All other variants remain unchanged. /// `Key`. All other variants remain unchanged.
pub fn as_ref(&self) -> Key<&str> { pub fn as_ref(&self) -> Key<&str> {
map_match!( match self {
self, Key::Named(a) => Key::Named(*a),
{ Key::Character(ch) => Key::Character(ch.as_str()),
Key::Character(ch) => Key::Character(ch.as_str()), Key::Dead(d) => Key::Dead(*d),
Key::Dead(d) => Key::Dead(*d), Key::Unidentified(u) => Key::Unidentified(u.clone()),
Key::Unidentified(u) => Key::Unidentified(u.clone()) }
}, }
Key, }
{
Alt, AltGraph, CapsLock, Control, Fn, FnLock, NumLock, ScrollLock, Shift, Symbol, impl NamedKey {
SymbolLock, Meta, Hyper, Super, Enter, Tab, Space, ArrowDown, ArrowLeft, /// Convert an action to its approximate textual equivalent.
ArrowRight, ArrowUp, End, Home, PageDown, PageUp, Backspace, Clear, Copy, CrSel, ///
Cut, Delete, EraseEof, ExSel, Insert, Paste, Redo, Undo, Accept, Again, Attn, /// # Examples
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, /// use winit::keyboard::NamedKey;
Compose, Convert, FinalMode, GroupFirst, GroupLast, GroupNext, GroupPrevious, ///
ModeChange, NextCandidate, NonConvert, PreviousCandidate, Process, SingleCandidate, /// assert_eq!(NamedKey::Enter.to_text(), Some("\r"));
HangulMode, HanjaMode, JunjaMode, Eisu, Hankaku, Hiragana, HiraganaKatakana, /// assert_eq!(NamedKey::F20.to_text(), None);
KanaMode, KanjiMode, Katakana, Romaji, Zenkaku, ZenkakuHankaku, Soft1, Soft2, /// ```
Soft3, Soft4, ChannelDown, ChannelUp, Close, MailForward, MailReply, MailSend, pub fn to_text(&self) -> Option<&str> {
MediaClose, MediaFastForward, MediaPause, MediaPlay, MediaPlayPause, MediaRecord, match self {
MediaRewind, MediaStop, MediaTrackNext, MediaTrackPrevious, New, Open, Print, Save, NamedKey::Enter => Some("\r"),
SpellCheck, Key11, Key12, AudioBalanceLeft, AudioBalanceRight, AudioBassBoostDown, NamedKey::Backspace => Some("\x08"),
AudioBassBoostToggle, AudioBassBoostUp, AudioFaderFront, AudioFaderRear, NamedKey::Tab => Some("\t"),
AudioSurroundModeNext, AudioTrebleDown, AudioTrebleUp, AudioVolumeDown, NamedKey::Space => Some(" "),
AudioVolumeUp, AudioVolumeMute, MicrophoneToggle, MicrophoneVolumeDown, NamedKey::Escape => Some("\x1b"),
MicrophoneVolumeUp, MicrophoneVolumeMute, SpeechCorrectionList, SpeechInputToggle, _ => None,
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
}
)
} }
} }
@ -1471,20 +1585,16 @@ impl Key {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use winit::keyboard::Key; /// use winit::keyboard::{NamedKey, Key};
/// ///
/// assert_eq!(Key::Character("a".into()).to_text(), Some("a")); /// assert_eq!(Key::Character("a".into()).to_text(), Some("a"));
/// assert_eq!(Key::Enter.to_text(), Some("\r")); /// assert_eq!(Key::Named(NamedKey::Enter).to_text(), Some("\r"));
/// assert_eq!(Key::F20.to_text(), None); /// assert_eq!(Key::Named(NamedKey::F20).to_text(), None);
/// ``` /// ```
pub fn to_text(&self) -> Option<&str> { pub fn to_text(&self) -> Option<&str> {
match self { match self {
Key::Named(action) => action.to_text(),
Key::Character(ch) => Some(ch.as_str()), 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, _ => None,
} }
} }

View file

@ -1,14 +1,14 @@
#![cfg(any(windows_platform, macos_platform, x11_platform, wayland_platform))] #![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 // 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. /// scancode.
/// ///
/// [`KeyCode`]: crate::keyboard::KeyCode /// [`PhysicalKey`]: crate::keyboard::PhysicalKey
pub trait KeyCodeExtScancode { pub trait PhysicalKeyExtScancode {
/// The raw value of the platform-specific physical key identifier. /// The raw value of the platform-specific physical key identifier.
/// ///
/// Returns `Some(key_id)` if the conversion was succesful; returns `None` otherwise. /// 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. /// - **Wayland/X11**: A 32-bit linux scancode, which is X11/Wayland keycode subtracted by 8.
fn to_scancode(self) -> Option<u32>; fn to_scancode(self) -> Option<u32>;
/// 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. /// using `to_scancode` might not yield the original value.
/// ///
/// ## Platform-specific /// ## Platform-specific
/// - **Wayland/X11**: A 32-bit linux scancode. When building from X11/Wayland keycode subtract /// - **Wayland/X11**: A 32-bit linux scancode. When building from X11/Wayland keycode subtract
/// `8` to get the value you wanted. /// `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 {
<PhysicalKey as PhysicalKeyExtScancode>::from_scancode(scancode)
}
#[inline]
fn to_scancode(self) -> Option<u32> {
<PhysicalKey as PhysicalKeyExtScancode>::to_scancode(PhysicalKey::Code(self))
}
} }

View file

@ -3,10 +3,10 @@ use android_activity::{
AndroidApp, 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 { pub fn to_physical_key(keycode: Keycode) -> PhysicalKey {
match keycode { PhysicalKey::Code(match keycode {
Keycode::A => KeyCode::KeyA, Keycode::A => KeyCode::KeyA,
Keycode::B => KeyCode::KeyB, Keycode::B => KeyCode::KeyB,
Keycode::C => KeyCode::KeyC, Keycode::C => KeyCode::KeyC,
@ -155,8 +155,8 @@ pub fn to_physical_keycode(keycode: Keycode) -> KeyCode {
Keycode::Sleep => KeyCode::Sleep, // what about SoftSleep? Keycode::Sleep => KeyCode::Sleep, // what about SoftSleep?
Keycode::Wakeup => KeyCode::WakeUp, 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 /// 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<KeyMapChar>, keycode: Keycode) -> Key {
None | Some(KeyMapChar::None) => match keycode { None | Some(KeyMapChar::None) => match keycode {
// Using `BrowserHome` instead of `GoHome` according to // Using `BrowserHome` instead of `GoHome` according to
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
Home => Key::BrowserHome, Home => Key::Named(NamedKey::BrowserHome),
Back => Key::BrowserBack, Back => Key::Named(NamedKey::BrowserBack),
Call => Key::Call, Call => Key::Named(NamedKey::Call),
Endcall => Key::EndCall, Endcall => Key::Named(NamedKey::EndCall),
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
// These should be redundant because they should have already been matched // These should be redundant because they should have already been matched
@ -291,81 +291,81 @@ pub fn to_logical(key_char: Option<KeyMapChar>, keycode: Keycode) -> Key {
At => Key::Character("@".into()), At => Key::Character("@".into()),
Plus => Key::Character("+".into()), Plus => Key::Character("+".into()),
//------------------------------------------------------------------------------- //-------------------------------------------------------------------------------
DpadUp => Key::ArrowUp, DpadUp => Key::Named(NamedKey::ArrowUp),
DpadDown => Key::ArrowDown, DpadDown => Key::Named(NamedKey::ArrowDown),
DpadLeft => Key::ArrowLeft, DpadLeft => Key::Named(NamedKey::ArrowLeft),
DpadRight => Key::ArrowRight, DpadRight => Key::Named(NamedKey::ArrowRight),
DpadCenter => Key::Enter, DpadCenter => Key::Named(NamedKey::Enter),
VolumeUp => Key::AudioVolumeUp, VolumeUp => Key::Named(NamedKey::AudioVolumeUp),
VolumeDown => Key::AudioVolumeDown, VolumeDown => Key::Named(NamedKey::AudioVolumeDown),
Power => Key::Power, Power => Key::Named(NamedKey::Power),
Camera => Key::Camera, Camera => Key::Named(NamedKey::Camera),
Clear => Key::Clear, Clear => Key::Named(NamedKey::Clear),
AltLeft => Key::Alt, AltLeft => Key::Named(NamedKey::Alt),
AltRight => Key::Alt, AltRight => Key::Named(NamedKey::Alt),
ShiftLeft => Key::Shift, ShiftLeft => Key::Named(NamedKey::Shift),
ShiftRight => Key::Shift, ShiftRight => Key::Named(NamedKey::Shift),
Tab => Key::Tab, Tab => Key::Named(NamedKey::Tab),
Space => Key::Space, Space => Key::Named(NamedKey::Space),
Sym => Key::Symbol, Sym => Key::Named(NamedKey::Symbol),
Explorer => Key::LaunchWebBrowser, Explorer => Key::Named(NamedKey::LaunchWebBrowser),
Envelope => Key::LaunchMail, Envelope => Key::Named(NamedKey::LaunchMail),
Enter => Key::Enter, Enter => Key::Named(NamedKey::Enter),
Del => Key::Backspace, Del => Key::Named(NamedKey::Backspace),
// According to https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_NUM // According to https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_NUM
Num => Key::Alt, Num => Key::Named(NamedKey::Alt),
Headsethook => Key::HeadsetHook, Headsethook => Key::Named(NamedKey::HeadsetHook),
Focus => Key::CameraFocus, Focus => Key::Named(NamedKey::CameraFocus),
Notification => Key::Notification, Notification => Key::Named(NamedKey::Notification),
Search => Key::BrowserSearch, Search => Key::Named(NamedKey::BrowserSearch),
MediaPlayPause => Key::MediaPlayPause, MediaPlayPause => Key::Named(NamedKey::MediaPlayPause),
MediaStop => Key::MediaStop, MediaStop => Key::Named(NamedKey::MediaStop),
MediaNext => Key::MediaTrackNext, MediaNext => Key::Named(NamedKey::MediaTrackNext),
MediaPrevious => Key::MediaTrackPrevious, MediaPrevious => Key::Named(NamedKey::MediaTrackPrevious),
MediaRewind => Key::MediaRewind, MediaRewind => Key::Named(NamedKey::MediaRewind),
MediaFastForward => Key::MediaFastForward, MediaFastForward => Key::Named(NamedKey::MediaFastForward),
Mute => Key::MicrophoneVolumeMute, Mute => Key::Named(NamedKey::MicrophoneVolumeMute),
PageUp => Key::PageUp, PageUp => Key::Named(NamedKey::PageUp),
PageDown => Key::PageDown, PageDown => Key::Named(NamedKey::PageDown),
Escape => Key::Escape, Escape => Key::Named(NamedKey::Escape),
ForwardDel => Key::Delete, ForwardDel => Key::Named(NamedKey::Delete),
CtrlLeft => Key::Control, CtrlLeft => Key::Named(NamedKey::Control),
CtrlRight => Key::Control, CtrlRight => Key::Named(NamedKey::Control),
CapsLock => Key::CapsLock, CapsLock => Key::Named(NamedKey::CapsLock),
ScrollLock => Key::ScrollLock, ScrollLock => Key::Named(NamedKey::ScrollLock),
MetaLeft => Key::Super, MetaLeft => Key::Named(NamedKey::Super),
MetaRight => Key::Super, MetaRight => Key::Named(NamedKey::Super),
Function => Key::Fn, Function => Key::Named(NamedKey::Fn),
Sysrq => Key::PrintScreen, Sysrq => Key::Named(NamedKey::PrintScreen),
Break => Key::Pause, Break => Key::Named(NamedKey::Pause),
MoveHome => Key::Home, MoveHome => Key::Named(NamedKey::Home),
MoveEnd => Key::End, MoveEnd => Key::Named(NamedKey::End),
Insert => Key::Insert, Insert => Key::Named(NamedKey::Insert),
Forward => Key::BrowserForward, Forward => Key::Named(NamedKey::BrowserForward),
MediaPlay => Key::MediaPlay, MediaPlay => Key::Named(NamedKey::MediaPlay),
MediaPause => Key::MediaPause, MediaPause => Key::Named(NamedKey::MediaPause),
MediaClose => Key::MediaClose, MediaClose => Key::Named(NamedKey::MediaClose),
MediaEject => Key::Eject, MediaEject => Key::Named(NamedKey::Eject),
MediaRecord => Key::MediaRecord, MediaRecord => Key::Named(NamedKey::MediaRecord),
F1 => Key::F1, F1 => Key::Named(NamedKey::F1),
F2 => Key::F2, F2 => Key::Named(NamedKey::F2),
F3 => Key::F3, F3 => Key::Named(NamedKey::F3),
F4 => Key::F4, F4 => Key::Named(NamedKey::F4),
F5 => Key::F5, F5 => Key::Named(NamedKey::F5),
F6 => Key::F6, F6 => Key::Named(NamedKey::F6),
F7 => Key::F7, F7 => Key::Named(NamedKey::F7),
F8 => Key::F8, F8 => Key::Named(NamedKey::F8),
F9 => Key::F9, F9 => Key::Named(NamedKey::F9),
F10 => Key::F10, F10 => Key::Named(NamedKey::F10),
F11 => Key::F11, F11 => Key::Named(NamedKey::F11),
F12 => Key::F12, F12 => Key::Named(NamedKey::F12),
NumLock => Key::NumLock, NumLock => Key::Named(NamedKey::NumLock),
Numpad0 => Key::Character("0".into()), Numpad0 => Key::Character("0".into()),
Numpad1 => Key::Character("1".into()), Numpad1 => Key::Character("1".into()),
Numpad2 => Key::Character("2".into()), Numpad2 => Key::Character("2".into()),
@ -382,97 +382,97 @@ pub fn to_logical(key_char: Option<KeyMapChar>, keycode: Keycode) -> Key {
NumpadAdd => Key::Character("+".into()), NumpadAdd => Key::Character("+".into()),
NumpadDot => Key::Character(".".into()), NumpadDot => Key::Character(".".into()),
NumpadComma => Key::Character(",".into()), NumpadComma => Key::Character(",".into()),
NumpadEnter => Key::Enter, NumpadEnter => Key::Named(NamedKey::Enter),
NumpadEquals => Key::Character("=".into()), NumpadEquals => Key::Character("=".into()),
NumpadLeftParen => Key::Character("(".into()), NumpadLeftParen => Key::Character("(".into()),
NumpadRightParen => Key::Character(")".into()), NumpadRightParen => Key::Character(")".into()),
VolumeMute => Key::AudioVolumeMute, VolumeMute => Key::Named(NamedKey::AudioVolumeMute),
Info => Key::Info, Info => Key::Named(NamedKey::Info),
ChannelUp => Key::ChannelUp, ChannelUp => Key::Named(NamedKey::ChannelUp),
ChannelDown => Key::ChannelDown, ChannelDown => Key::Named(NamedKey::ChannelDown),
ZoomIn => Key::ZoomIn, ZoomIn => Key::Named(NamedKey::ZoomIn),
ZoomOut => Key::ZoomOut, ZoomOut => Key::Named(NamedKey::ZoomOut),
Tv => Key::TV, Tv => Key::Named(NamedKey::TV),
Guide => Key::Guide, Guide => Key::Named(NamedKey::Guide),
Dvr => Key::DVR, Dvr => Key::Named(NamedKey::DVR),
Bookmark => Key::BrowserFavorites, Bookmark => Key::Named(NamedKey::BrowserFavorites),
Captions => Key::ClosedCaptionToggle, Captions => Key::Named(NamedKey::ClosedCaptionToggle),
Settings => Key::Settings, Settings => Key::Named(NamedKey::Settings),
TvPower => Key::TVPower, TvPower => Key::Named(NamedKey::TVPower),
TvInput => Key::TVInput, TvInput => Key::Named(NamedKey::TVInput),
StbPower => Key::STBPower, StbPower => Key::Named(NamedKey::STBPower),
StbInput => Key::STBInput, StbInput => Key::Named(NamedKey::STBInput),
AvrPower => Key::AVRPower, AvrPower => Key::Named(NamedKey::AVRPower),
AvrInput => Key::AVRInput, AvrInput => Key::Named(NamedKey::AVRInput),
ProgRed => Key::ColorF0Red, ProgRed => Key::Named(NamedKey::ColorF0Red),
ProgGreen => Key::ColorF1Green, ProgGreen => Key::Named(NamedKey::ColorF1Green),
ProgYellow => Key::ColorF2Yellow, ProgYellow => Key::Named(NamedKey::ColorF2Yellow),
ProgBlue => Key::ColorF3Blue, ProgBlue => Key::Named(NamedKey::ColorF3Blue),
AppSwitch => Key::AppSwitch, AppSwitch => Key::Named(NamedKey::AppSwitch),
LanguageSwitch => Key::GroupNext, LanguageSwitch => Key::Named(NamedKey::GroupNext),
MannerMode => Key::MannerMode, MannerMode => Key::Named(NamedKey::MannerMode),
Keycode3dMode => Key::TV3DMode, Keycode3dMode => Key::Named(NamedKey::TV3DMode),
Contacts => Key::LaunchContacts, Contacts => Key::Named(NamedKey::LaunchContacts),
Calendar => Key::LaunchCalendar, Calendar => Key::Named(NamedKey::LaunchCalendar),
Music => Key::LaunchMusicPlayer, Music => Key::Named(NamedKey::LaunchMusicPlayer),
Calculator => Key::LaunchApplication2, Calculator => Key::Named(NamedKey::LaunchApplication2),
ZenkakuHankaku => Key::ZenkakuHankaku, ZenkakuHankaku => Key::Named(NamedKey::ZenkakuHankaku),
Eisu => Key::Eisu, Eisu => Key::Named(NamedKey::Eisu),
Muhenkan => Key::NonConvert, Muhenkan => Key::Named(NamedKey::NonConvert),
Henkan => Key::Convert, Henkan => Key::Named(NamedKey::Convert),
KatakanaHiragana => Key::HiraganaKatakana, KatakanaHiragana => Key::Named(NamedKey::HiraganaKatakana),
Kana => Key::KanjiMode, Kana => Key::Named(NamedKey::KanjiMode),
BrightnessDown => Key::BrightnessDown, BrightnessDown => Key::Named(NamedKey::BrightnessDown),
BrightnessUp => Key::BrightnessUp, BrightnessUp => Key::Named(NamedKey::BrightnessUp),
MediaAudioTrack => Key::MediaAudioTrack, MediaAudioTrack => Key::Named(NamedKey::MediaAudioTrack),
Sleep => Key::Standby, Sleep => Key::Named(NamedKey::Standby),
Wakeup => Key::WakeUp, Wakeup => Key::Named(NamedKey::WakeUp),
Pairing => Key::Pairing, Pairing => Key::Named(NamedKey::Pairing),
MediaTopMenu => Key::MediaTopMenu, MediaTopMenu => Key::Named(NamedKey::MediaTopMenu),
LastChannel => Key::MediaLast, LastChannel => Key::Named(NamedKey::MediaLast),
TvDataService => Key::TVDataService, TvDataService => Key::Named(NamedKey::TVDataService),
VoiceAssist => Key::VoiceDial, VoiceAssist => Key::Named(NamedKey::VoiceDial),
TvRadioService => Key::TVRadioService, TvRadioService => Key::Named(NamedKey::TVRadioService),
TvTeletext => Key::Teletext, TvTeletext => Key::Named(NamedKey::Teletext),
TvNumberEntry => Key::TVNumberEntry, TvNumberEntry => Key::Named(NamedKey::TVNumberEntry),
TvTerrestrialAnalog => Key::TVTerrestrialAnalog, TvTerrestrialAnalog => Key::Named(NamedKey::TVTerrestrialAnalog),
TvTerrestrialDigital => Key::TVTerrestrialDigital, TvTerrestrialDigital => Key::Named(NamedKey::TVTerrestrialDigital),
TvSatellite => Key::TVSatellite, TvSatellite => Key::Named(NamedKey::TVSatellite),
TvSatelliteBs => Key::TVSatelliteBS, TvSatelliteBs => Key::Named(NamedKey::TVSatelliteBS),
TvSatelliteCs => Key::TVSatelliteCS, TvSatelliteCs => Key::Named(NamedKey::TVSatelliteCS),
TvSatelliteService => Key::TVSatelliteToggle, TvSatelliteService => Key::Named(NamedKey::TVSatelliteToggle),
TvNetwork => Key::TVNetwork, TvNetwork => Key::Named(NamedKey::TVNetwork),
TvAntennaCable => Key::TVAntennaCable, TvAntennaCable => Key::Named(NamedKey::TVAntennaCable),
TvInputHdmi1 => Key::TVInputHDMI1, TvInputHdmi1 => Key::Named(NamedKey::TVInputHDMI1),
TvInputHdmi2 => Key::TVInputHDMI2, TvInputHdmi2 => Key::Named(NamedKey::TVInputHDMI2),
TvInputHdmi3 => Key::TVInputHDMI3, TvInputHdmi3 => Key::Named(NamedKey::TVInputHDMI3),
TvInputHdmi4 => Key::TVInputHDMI4, TvInputHdmi4 => Key::Named(NamedKey::TVInputHDMI4),
TvInputComposite1 => Key::TVInputComposite1, TvInputComposite1 => Key::Named(NamedKey::TVInputComposite1),
TvInputComposite2 => Key::TVInputComposite2, TvInputComposite2 => Key::Named(NamedKey::TVInputComposite2),
TvInputComponent1 => Key::TVInputComponent1, TvInputComponent1 => Key::Named(NamedKey::TVInputComponent1),
TvInputComponent2 => Key::TVInputComponent2, TvInputComponent2 => Key::Named(NamedKey::TVInputComponent2),
TvInputVga1 => Key::TVInputVGA1, TvInputVga1 => Key::Named(NamedKey::TVInputVGA1),
TvAudioDescription => Key::TVAudioDescription, TvAudioDescription => Key::Named(NamedKey::TVAudioDescription),
TvAudioDescriptionMixUp => Key::TVAudioDescriptionMixUp, TvAudioDescriptionMixUp => Key::Named(NamedKey::TVAudioDescriptionMixUp),
TvAudioDescriptionMixDown => Key::TVAudioDescriptionMixDown, TvAudioDescriptionMixDown => Key::Named(NamedKey::TVAudioDescriptionMixDown),
TvZoomMode => Key::ZoomToggle, TvZoomMode => Key::Named(NamedKey::ZoomToggle),
TvContentsMenu => Key::TVContentsMenu, TvContentsMenu => Key::Named(NamedKey::TVContentsMenu),
TvMediaContextMenu => Key::TVMediaContext, TvMediaContextMenu => Key::Named(NamedKey::TVMediaContext),
TvTimerProgramming => Key::TVTimer, TvTimerProgramming => Key::Named(NamedKey::TVTimer),
Help => Key::Help, Help => Key::Named(NamedKey::Help),
NavigatePrevious => Key::NavigatePrevious, NavigatePrevious => Key::Named(NamedKey::NavigatePrevious),
NavigateNext => Key::NavigateNext, NavigateNext => Key::Named(NamedKey::NavigateNext),
NavigateIn => Key::NavigateIn, NavigateIn => Key::Named(NamedKey::NavigateIn),
NavigateOut => Key::NavigateOut, NavigateOut => Key::Named(NamedKey::NavigateOut),
MediaSkipForward => Key::MediaSkipForward, MediaSkipForward => Key::Named(NamedKey::MediaSkipForward),
MediaSkipBackward => Key::MediaSkipBackward, MediaSkipBackward => Key::Named(NamedKey::MediaSkipBackward),
MediaStepForward => Key::MediaStepForward, MediaStepForward => Key::Named(NamedKey::MediaStepForward),
MediaStepBackward => Key::MediaStepBackward, MediaStepBackward => Key::Named(NamedKey::MediaStepBackward),
Cut => Key::Cut, Cut => Key::Named(NamedKey::Cut),
Copy => Key::Copy, Copy => Key::Named(NamedKey::Copy),
Paste => Key::Paste, Paste => Key::Named(NamedKey::Paste),
Refresh => Key::BrowserRefresh, Refresh => Key::Named(NamedKey::BrowserRefresh),
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// Keycodes that don't have a logical Key mapping // Keycodes that don't have a logical Key mapping

View file

@ -456,7 +456,7 @@ impl<T: 'static> EventLoop<T> {
device_id: event::DeviceId(DeviceId(key.device_id())), device_id: event::DeviceId(DeviceId(key.device_id())),
event: event::KeyEvent { event: event::KeyEvent {
state, state,
physical_key: keycodes::to_physical_keycode(keycode), physical_key: keycodes::to_physical_key(keycode),
logical_key: keycodes::to_logical(key_char, keycode), logical_key: keycodes::to_logical(key_char, keycode),
location: keycodes::to_location(keycode), location: keycodes::to_location(keycode),
repeat: key.repeat_count() > 0, repeat: key.repeat_count() > 0,

View file

@ -1,18 +1,18 @@
//! Convert XKB keys to Winit keys. //! 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. /// Map the raw X11-style keycode to the `KeyCode` enum.
/// ///
/// X11-style keycodes are offset by 8 from the keycodes the Linux kernel uses. /// 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)) scancode_to_keycode(keycode.saturating_sub(8))
} }
/// Map the linux scancode to Keycode. /// Map the linux scancode to Keycode.
/// ///
/// Both X11 and Wayland use keys with `+ 8` offset to linux scancode. /// 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 // 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 // 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, // 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 // 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 // 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. // either been commented out here, or not included at all.
match scancode { PhysicalKey::Code(match scancode {
0 => KeyCode::Unidentified(NativeKeyCode::Xkb(0)), 0 => return PhysicalKey::Unidentified(NativeKeyCode::Xkb(0)),
1 => KeyCode::Escape, 1 => KeyCode::Escape,
2 => KeyCode::Digit1, 2 => KeyCode::Digit1,
3 => KeyCode::Digit2, 3 => KeyCode::Digit2,
@ -256,7 +256,7 @@ pub fn scancode_to_keycode(scancode: u32) -> KeyCode {
// 237 => KeyCode::BLUETOOTH, // 237 => KeyCode::BLUETOOTH,
// 238 => KeyCode::WLAN, // 238 => KeyCode::WLAN,
// 239 => KeyCode::UWB, // 239 => KeyCode::UWB,
240 => KeyCode::Unidentified(NativeKeyCode::Unidentified), 240 => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified),
// 241 => KeyCode::VIDEO_NEXT, // 241 => KeyCode::VIDEO_NEXT,
// 242 => KeyCode::VIDEO_PREV, // 242 => KeyCode::VIDEO_PREV,
// 243 => KeyCode::BRIGHTNESS_CYCLE, // 243 => KeyCode::BRIGHTNESS_CYCLE,
@ -265,14 +265,23 @@ pub fn scancode_to_keycode(scancode: u32) -> KeyCode {
// 246 => KeyCode::WWAN, // 246 => KeyCode::WWAN,
// 247 => KeyCode::RFKILL, // 247 => KeyCode::RFKILL,
// 248 => KeyCode::KEY_MICMUTE, // 248 => KeyCode::KEY_MICMUTE,
_ => KeyCode::Unidentified(NativeKeyCode::Xkb(scancode)), _ => return PhysicalKey::Unidentified(NativeKeyCode::Xkb(scancode)),
} })
} }
pub fn keycode_to_scancode(keycode: KeyCode) -> Option<u32> { pub fn physicalkey_to_scancode(key: PhysicalKey) -> Option<u32> {
match keycode { let code = match key {
KeyCode::Unidentified(NativeKeyCode::Unidentified) => Some(240), PhysicalKey::Code(code) => code,
KeyCode::Unidentified(NativeKeyCode::Xkb(raw)) => Some(raw), PhysicalKey::Unidentified(code) => {
return match code {
NativeKeyCode::Unidentified => Some(240),
NativeKeyCode::Xkb(raw) => Some(raw),
_ => None,
};
}
};
match code {
KeyCode::Escape => Some(1), KeyCode::Escape => Some(1),
KeyCode::Digit1 => Some(2), KeyCode::Digit1 => Some(2),
KeyCode::Digit2 => Some(3), KeyCode::Digit2 => Some(3),
@ -415,213 +424,213 @@ pub fn keycode_to_scancode(keycode: KeyCode) -> Option<u32> {
pub fn keysym_to_key(keysym: u32) -> Key { pub fn keysym_to_key(keysym: u32) -> Key {
use xkbcommon_dl::keysyms; use xkbcommon_dl::keysyms;
match keysym { Key::Named(match keysym {
// TTY function keys // TTY function keys
keysyms::BackSpace => Key::Backspace, keysyms::BackSpace => NamedKey::Backspace,
keysyms::Tab => Key::Tab, keysyms::Tab => NamedKey::Tab,
// keysyms::Linefeed => Key::Linefeed, // keysyms::Linefeed => NamedKey::Linefeed,
keysyms::Clear => Key::Clear, keysyms::Clear => NamedKey::Clear,
keysyms::Return => Key::Enter, keysyms::Return => NamedKey::Enter,
keysyms::Pause => Key::Pause, keysyms::Pause => NamedKey::Pause,
keysyms::Scroll_Lock => Key::ScrollLock, keysyms::Scroll_Lock => NamedKey::ScrollLock,
keysyms::Sys_Req => Key::PrintScreen, keysyms::Sys_Req => NamedKey::PrintScreen,
keysyms::Escape => Key::Escape, keysyms::Escape => NamedKey::Escape,
keysyms::Delete => Key::Delete, keysyms::Delete => NamedKey::Delete,
// IME keys // IME keys
keysyms::Multi_key => Key::Compose, keysyms::Multi_key => NamedKey::Compose,
keysyms::Codeinput => Key::CodeInput, keysyms::Codeinput => NamedKey::CodeInput,
keysyms::SingleCandidate => Key::SingleCandidate, keysyms::SingleCandidate => NamedKey::SingleCandidate,
keysyms::MultipleCandidate => Key::AllCandidates, keysyms::MultipleCandidate => NamedKey::AllCandidates,
keysyms::PreviousCandidate => Key::PreviousCandidate, keysyms::PreviousCandidate => NamedKey::PreviousCandidate,
// Japanese keys // Japanese keys
keysyms::Kanji => Key::KanjiMode, keysyms::Kanji => NamedKey::KanjiMode,
keysyms::Muhenkan => Key::NonConvert, keysyms::Muhenkan => NamedKey::NonConvert,
keysyms::Henkan_Mode => Key::Convert, keysyms::Henkan_Mode => NamedKey::Convert,
keysyms::Romaji => Key::Romaji, keysyms::Romaji => NamedKey::Romaji,
keysyms::Hiragana => Key::Hiragana, keysyms::Hiragana => NamedKey::Hiragana,
keysyms::Hiragana_Katakana => Key::HiraganaKatakana, keysyms::Hiragana_Katakana => NamedKey::HiraganaKatakana,
keysyms::Zenkaku => Key::Zenkaku, keysyms::Zenkaku => NamedKey::Zenkaku,
keysyms::Hankaku => Key::Hankaku, keysyms::Hankaku => NamedKey::Hankaku,
keysyms::Zenkaku_Hankaku => Key::ZenkakuHankaku, keysyms::Zenkaku_Hankaku => NamedKey::ZenkakuHankaku,
// keysyms::Touroku => Key::Touroku, // keysyms::Touroku => NamedKey::Touroku,
// keysyms::Massyo => Key::Massyo, // keysyms::Massyo => NamedKey::Massyo,
keysyms::Kana_Lock => Key::KanaMode, keysyms::Kana_Lock => NamedKey::KanaMode,
keysyms::Kana_Shift => Key::KanaMode, keysyms::Kana_Shift => NamedKey::KanaMode,
keysyms::Eisu_Shift => Key::Alphanumeric, keysyms::Eisu_Shift => NamedKey::Alphanumeric,
keysyms::Eisu_toggle => Key::Alphanumeric, keysyms::Eisu_toggle => NamedKey::Alphanumeric,
// NOTE: The next three items are aliases for values we've already mapped. // NOTE: The next three items are aliases for values we've already mapped.
// keysyms::Kanji_Bangou => Key::CodeInput, // keysyms::Kanji_Bangou => NamedKey::CodeInput,
// keysyms::Zen_Koho => Key::AllCandidates, // keysyms::Zen_Koho => NamedKey::AllCandidates,
// keysyms::Mae_Koho => Key::PreviousCandidate, // keysyms::Mae_Koho => NamedKey::PreviousCandidate,
// Cursor control & motion // Cursor control & motion
keysyms::Home => Key::Home, keysyms::Home => NamedKey::Home,
keysyms::Left => Key::ArrowLeft, keysyms::Left => NamedKey::ArrowLeft,
keysyms::Up => Key::ArrowUp, keysyms::Up => NamedKey::ArrowUp,
keysyms::Right => Key::ArrowRight, keysyms::Right => NamedKey::ArrowRight,
keysyms::Down => Key::ArrowDown, keysyms::Down => NamedKey::ArrowDown,
// keysyms::Prior => Key::PageUp, // keysyms::Prior => NamedKey::PageUp,
keysyms::Page_Up => Key::PageUp, keysyms::Page_Up => NamedKey::PageUp,
// keysyms::Next => Key::PageDown, // keysyms::Next => NamedKey::PageDown,
keysyms::Page_Down => Key::PageDown, keysyms::Page_Down => NamedKey::PageDown,
keysyms::End => Key::End, keysyms::End => NamedKey::End,
// keysyms::Begin => Key::Begin, // keysyms::Begin => NamedKey::Begin,
// Misc. functions // Misc. functions
keysyms::Select => Key::Select, keysyms::Select => NamedKey::Select,
keysyms::Print => Key::PrintScreen, keysyms::Print => NamedKey::PrintScreen,
keysyms::Execute => Key::Execute, keysyms::Execute => NamedKey::Execute,
keysyms::Insert => Key::Insert, keysyms::Insert => NamedKey::Insert,
keysyms::Undo => Key::Undo, keysyms::Undo => NamedKey::Undo,
keysyms::Redo => Key::Redo, keysyms::Redo => NamedKey::Redo,
keysyms::Menu => Key::ContextMenu, keysyms::Menu => NamedKey::ContextMenu,
keysyms::Find => Key::Find, keysyms::Find => NamedKey::Find,
keysyms::Cancel => Key::Cancel, keysyms::Cancel => NamedKey::Cancel,
keysyms::Help => Key::Help, keysyms::Help => NamedKey::Help,
keysyms::Break => Key::Pause, keysyms::Break => NamedKey::Pause,
keysyms::Mode_switch => Key::ModeChange, keysyms::Mode_switch => NamedKey::ModeChange,
// keysyms::script_switch => Key::ModeChange, // keysyms::script_switch => NamedKey::ModeChange,
keysyms::Num_Lock => Key::NumLock, keysyms::Num_Lock => NamedKey::NumLock,
// Keypad keys // Keypad keys
// keysyms::KP_Space => Key::Character(" "), // keysyms::KP_Space => return Key::Character(" "),
keysyms::KP_Tab => Key::Tab, keysyms::KP_Tab => NamedKey::Tab,
keysyms::KP_Enter => Key::Enter, keysyms::KP_Enter => NamedKey::Enter,
keysyms::KP_F1 => Key::F1, keysyms::KP_F1 => NamedKey::F1,
keysyms::KP_F2 => Key::F2, keysyms::KP_F2 => NamedKey::F2,
keysyms::KP_F3 => Key::F3, keysyms::KP_F3 => NamedKey::F3,
keysyms::KP_F4 => Key::F4, keysyms::KP_F4 => NamedKey::F4,
keysyms::KP_Home => Key::Home, keysyms::KP_Home => NamedKey::Home,
keysyms::KP_Left => Key::ArrowLeft, keysyms::KP_Left => NamedKey::ArrowLeft,
keysyms::KP_Up => Key::ArrowLeft, keysyms::KP_Up => NamedKey::ArrowLeft,
keysyms::KP_Right => Key::ArrowRight, keysyms::KP_Right => NamedKey::ArrowRight,
keysyms::KP_Down => Key::ArrowDown, keysyms::KP_Down => NamedKey::ArrowDown,
// keysyms::KP_Prior => Key::PageUp, // keysyms::KP_Prior => NamedKey::PageUp,
keysyms::KP_Page_Up => Key::PageUp, keysyms::KP_Page_Up => NamedKey::PageUp,
// keysyms::KP_Next => Key::PageDown, // keysyms::KP_Next => NamedKey::PageDown,
keysyms::KP_Page_Down => Key::PageDown, keysyms::KP_Page_Down => NamedKey::PageDown,
keysyms::KP_End => Key::End, keysyms::KP_End => NamedKey::End,
// This is the key labeled "5" on the numpad when NumLock is off. // This is the key labeled "5" on the numpad when NumLock is off.
// keysyms::KP_Begin => Key::Begin, // keysyms::KP_Begin => NamedKey::Begin,
keysyms::KP_Insert => Key::Insert, keysyms::KP_Insert => NamedKey::Insert,
keysyms::KP_Delete => Key::Delete, keysyms::KP_Delete => NamedKey::Delete,
// keysyms::KP_Equal => Key::Equal, // keysyms::KP_Equal => NamedKey::Equal,
// keysyms::KP_Multiply => Key::Multiply, // keysyms::KP_Multiply => NamedKey::Multiply,
// keysyms::KP_Add => Key::Add, // keysyms::KP_Add => NamedKey::Add,
// keysyms::KP_Separator => Key::Separator, // keysyms::KP_Separator => NamedKey::Separator,
// keysyms::KP_Subtract => Key::Subtract, // keysyms::KP_Subtract => NamedKey::Subtract,
// keysyms::KP_Decimal => Key::Decimal, // keysyms::KP_Decimal => NamedKey::Decimal,
// keysyms::KP_Divide => Key::Divide, // keysyms::KP_Divide => NamedKey::Divide,
// keysyms::KP_0 => Key::Character("0"), // keysyms::KP_0 => return Key::Character("0"),
// keysyms::KP_1 => Key::Character("1"), // keysyms::KP_1 => return Key::Character("1"),
// keysyms::KP_2 => Key::Character("2"), // keysyms::KP_2 => return Key::Character("2"),
// keysyms::KP_3 => Key::Character("3"), // keysyms::KP_3 => return Key::Character("3"),
// keysyms::KP_4 => Key::Character("4"), // keysyms::KP_4 => return Key::Character("4"),
// keysyms::KP_5 => Key::Character("5"), // keysyms::KP_5 => return Key::Character("5"),
// keysyms::KP_6 => Key::Character("6"), // keysyms::KP_6 => return Key::Character("6"),
// keysyms::KP_7 => Key::Character("7"), // keysyms::KP_7 => return Key::Character("7"),
// keysyms::KP_8 => Key::Character("8"), // keysyms::KP_8 => return Key::Character("8"),
// keysyms::KP_9 => Key::Character("9"), // keysyms::KP_9 => return Key::Character("9"),
// Function keys // Function keys
keysyms::F1 => Key::F1, keysyms::F1 => NamedKey::F1,
keysyms::F2 => Key::F2, keysyms::F2 => NamedKey::F2,
keysyms::F3 => Key::F3, keysyms::F3 => NamedKey::F3,
keysyms::F4 => Key::F4, keysyms::F4 => NamedKey::F4,
keysyms::F5 => Key::F5, keysyms::F5 => NamedKey::F5,
keysyms::F6 => Key::F6, keysyms::F6 => NamedKey::F6,
keysyms::F7 => Key::F7, keysyms::F7 => NamedKey::F7,
keysyms::F8 => Key::F8, keysyms::F8 => NamedKey::F8,
keysyms::F9 => Key::F9, keysyms::F9 => NamedKey::F9,
keysyms::F10 => Key::F10, keysyms::F10 => NamedKey::F10,
keysyms::F11 => Key::F11, keysyms::F11 => NamedKey::F11,
keysyms::F12 => Key::F12, keysyms::F12 => NamedKey::F12,
keysyms::F13 => Key::F13, keysyms::F13 => NamedKey::F13,
keysyms::F14 => Key::F14, keysyms::F14 => NamedKey::F14,
keysyms::F15 => Key::F15, keysyms::F15 => NamedKey::F15,
keysyms::F16 => Key::F16, keysyms::F16 => NamedKey::F16,
keysyms::F17 => Key::F17, keysyms::F17 => NamedKey::F17,
keysyms::F18 => Key::F18, keysyms::F18 => NamedKey::F18,
keysyms::F19 => Key::F19, keysyms::F19 => NamedKey::F19,
keysyms::F20 => Key::F20, keysyms::F20 => NamedKey::F20,
keysyms::F21 => Key::F21, keysyms::F21 => NamedKey::F21,
keysyms::F22 => Key::F22, keysyms::F22 => NamedKey::F22,
keysyms::F23 => Key::F23, keysyms::F23 => NamedKey::F23,
keysyms::F24 => Key::F24, keysyms::F24 => NamedKey::F24,
keysyms::F25 => Key::F25, keysyms::F25 => NamedKey::F25,
keysyms::F26 => Key::F26, keysyms::F26 => NamedKey::F26,
keysyms::F27 => Key::F27, keysyms::F27 => NamedKey::F27,
keysyms::F28 => Key::F28, keysyms::F28 => NamedKey::F28,
keysyms::F29 => Key::F29, keysyms::F29 => NamedKey::F29,
keysyms::F30 => Key::F30, keysyms::F30 => NamedKey::F30,
keysyms::F31 => Key::F31, keysyms::F31 => NamedKey::F31,
keysyms::F32 => Key::F32, keysyms::F32 => NamedKey::F32,
keysyms::F33 => Key::F33, keysyms::F33 => NamedKey::F33,
keysyms::F34 => Key::F34, keysyms::F34 => NamedKey::F34,
keysyms::F35 => Key::F35, keysyms::F35 => NamedKey::F35,
// Modifiers // Modifiers
keysyms::Shift_L => Key::Shift, keysyms::Shift_L => NamedKey::Shift,
keysyms::Shift_R => Key::Shift, keysyms::Shift_R => NamedKey::Shift,
keysyms::Control_L => Key::Control, keysyms::Control_L => NamedKey::Control,
keysyms::Control_R => Key::Control, keysyms::Control_R => NamedKey::Control,
keysyms::Caps_Lock => Key::CapsLock, keysyms::Caps_Lock => NamedKey::CapsLock,
// keysyms::Shift_Lock => Key::ShiftLock, // keysyms::Shift_Lock => NamedKey::ShiftLock,
// keysyms::Meta_L => Key::Meta, // keysyms::Meta_L => NamedKey::Meta,
// keysyms::Meta_R => Key::Meta, // keysyms::Meta_R => NamedKey::Meta,
keysyms::Alt_L => Key::Alt, keysyms::Alt_L => NamedKey::Alt,
keysyms::Alt_R => Key::Alt, keysyms::Alt_R => NamedKey::Alt,
keysyms::Super_L => Key::Super, keysyms::Super_L => NamedKey::Super,
keysyms::Super_R => Key::Super, keysyms::Super_R => NamedKey::Super,
keysyms::Hyper_L => Key::Hyper, keysyms::Hyper_L => NamedKey::Hyper,
keysyms::Hyper_R => Key::Hyper, keysyms::Hyper_R => NamedKey::Hyper,
// XKB function and modifier keys // XKB function and modifier keys
// keysyms::ISO_Lock => Key::IsoLock, // keysyms::ISO_Lock => NamedKey::IsoLock,
// keysyms::ISO_Level2_Latch => Key::IsoLevel2Latch, // keysyms::ISO_Level2_Latch => NamedKey::IsoLevel2Latch,
keysyms::ISO_Level3_Shift => Key::AltGraph, keysyms::ISO_Level3_Shift => NamedKey::AltGraph,
keysyms::ISO_Level3_Latch => Key::AltGraph, keysyms::ISO_Level3_Latch => NamedKey::AltGraph,
keysyms::ISO_Level3_Lock => Key::AltGraph, keysyms::ISO_Level3_Lock => NamedKey::AltGraph,
// keysyms::ISO_Level5_Shift => Key::IsoLevel5Shift, // keysyms::ISO_Level5_Shift => NamedKey::IsoLevel5Shift,
// keysyms::ISO_Level5_Latch => Key::IsoLevel5Latch, // keysyms::ISO_Level5_Latch => NamedKey::IsoLevel5Latch,
// keysyms::ISO_Level5_Lock => Key::IsoLevel5Lock, // keysyms::ISO_Level5_Lock => NamedKey::IsoLevel5Lock,
// keysyms::ISO_Group_Shift => Key::IsoGroupShift, // keysyms::ISO_Group_Shift => NamedKey::IsoGroupShift,
// keysyms::ISO_Group_Latch => Key::IsoGroupLatch, // keysyms::ISO_Group_Latch => NamedKey::IsoGroupLatch,
// keysyms::ISO_Group_Lock => Key::IsoGroupLock, // keysyms::ISO_Group_Lock => NamedKey::IsoGroupLock,
keysyms::ISO_Next_Group => Key::GroupNext, keysyms::ISO_Next_Group => NamedKey::GroupNext,
// keysyms::ISO_Next_Group_Lock => Key::GroupNextLock, // keysyms::ISO_Next_Group_Lock => NamedKey::GroupNextLock,
keysyms::ISO_Prev_Group => Key::GroupPrevious, keysyms::ISO_Prev_Group => NamedKey::GroupPrevious,
// keysyms::ISO_Prev_Group_Lock => Key::GroupPreviousLock, // keysyms::ISO_Prev_Group_Lock => NamedKey::GroupPreviousLock,
keysyms::ISO_First_Group => Key::GroupFirst, keysyms::ISO_First_Group => NamedKey::GroupFirst,
// keysyms::ISO_First_Group_Lock => Key::GroupFirstLock, // keysyms::ISO_First_Group_Lock => NamedKey::GroupFirstLock,
keysyms::ISO_Last_Group => Key::GroupLast, keysyms::ISO_Last_Group => NamedKey::GroupLast,
// keysyms::ISO_Last_Group_Lock => Key::GroupLastLock, // keysyms::ISO_Last_Group_Lock => NamedKey::GroupLastLock,
// //
keysyms::ISO_Left_Tab => Key::Tab, keysyms::ISO_Left_Tab => NamedKey::Tab,
// keysyms::ISO_Move_Line_Up => Key::IsoMoveLineUp, // keysyms::ISO_Move_Line_Up => NamedKey::IsoMoveLineUp,
// keysyms::ISO_Move_Line_Down => Key::IsoMoveLineDown, // keysyms::ISO_Move_Line_Down => NamedKey::IsoMoveLineDown,
// keysyms::ISO_Partial_Line_Up => Key::IsoPartialLineUp, // keysyms::ISO_Partial_Line_Up => NamedKey::IsoPartialLineUp,
// keysyms::ISO_Partial_Line_Down => Key::IsoPartialLineDown, // keysyms::ISO_Partial_Line_Down => NamedKey::IsoPartialLineDown,
// keysyms::ISO_Partial_Space_Left => Key::IsoPartialSpaceLeft, // keysyms::ISO_Partial_Space_Left => NamedKey::IsoPartialSpaceLeft,
// keysyms::ISO_Partial_Space_Right => Key::IsoPartialSpaceRight, // keysyms::ISO_Partial_Space_Right => NamedKey::IsoPartialSpaceRight,
// keysyms::ISO_Set_Margin_Left => Key::IsoSetMarginLeft, // keysyms::ISO_Set_Margin_Left => NamedKey::IsoSetMarginLeft,
// keysyms::ISO_Set_Margin_Right => Key::IsoSetMarginRight, // keysyms::ISO_Set_Margin_Right => NamedKey::IsoSetMarginRight,
// keysyms::ISO_Release_Margin_Left => Key::IsoReleaseMarginLeft, // keysyms::ISO_Release_Margin_Left => NamedKey::IsoReleaseMarginLeft,
// keysyms::ISO_Release_Margin_Right => Key::IsoReleaseMarginRight, // keysyms::ISO_Release_Margin_Right => NamedKey::IsoReleaseMarginRight,
// keysyms::ISO_Release_Both_Margins => Key::IsoReleaseBothMargins, // keysyms::ISO_Release_Both_Margins => NamedKey::IsoReleaseBothMargins,
// keysyms::ISO_Fast_Cursor_Left => Key::IsoFastCursorLeft, // keysyms::ISO_Fast_Cursor_Left => NamedKey::IsoFastCursorLeft,
// keysyms::ISO_Fast_Cursor_Right => Key::IsoFastCursorRight, // keysyms::ISO_Fast_Cursor_Right => NamedKey::IsoFastCursorRight,
// keysyms::ISO_Fast_Cursor_Up => Key::IsoFastCursorUp, // keysyms::ISO_Fast_Cursor_Up => NamedKey::IsoFastCursorUp,
// keysyms::ISO_Fast_Cursor_Down => Key::IsoFastCursorDown, // keysyms::ISO_Fast_Cursor_Down => NamedKey::IsoFastCursorDown,
// keysyms::ISO_Continuous_Underline => Key::IsoContinuousUnderline, // keysyms::ISO_Continuous_Underline => NamedKey::IsoContinuousUnderline,
// keysyms::ISO_Discontinuous_Underline => Key::IsoDiscontinuousUnderline, // keysyms::ISO_Discontinuous_Underline => NamedKey::IsoDiscontinuousUnderline,
// keysyms::ISO_Emphasize => Key::IsoEmphasize, // keysyms::ISO_Emphasize => NamedKey::IsoEmphasize,
// keysyms::ISO_Center_Object => Key::IsoCenterObject, // keysyms::ISO_Center_Object => NamedKey::IsoCenterObject,
keysyms::ISO_Enter => Key::Enter, keysyms::ISO_Enter => NamedKey::Enter,
// dead_grave..dead_currency // dead_grave..dead_currency
@ -642,194 +651,194 @@ pub fn keysym_to_key(keysym: u32) -> Key {
// ch..C_H // ch..C_H
// 3270 terminal keys // 3270 terminal keys
// keysyms::3270_Duplicate => Key::Duplicate, // keysyms::3270_Duplicate => NamedKey::Duplicate,
// keysyms::3270_FieldMark => Key::FieldMark, // keysyms::3270_FieldMark => NamedKey::FieldMark,
// keysyms::3270_Right2 => Key::Right2, // keysyms::3270_Right2 => NamedKey::Right2,
// keysyms::3270_Left2 => Key::Left2, // keysyms::3270_Left2 => NamedKey::Left2,
// keysyms::3270_BackTab => Key::BackTab, // keysyms::3270_BackTab => NamedKey::BackTab,
keysyms::_3270_EraseEOF => Key::EraseEof, keysyms::_3270_EraseEOF => NamedKey::EraseEof,
// keysyms::3270_EraseInput => Key::EraseInput, // keysyms::3270_EraseInput => NamedKey::EraseInput,
// keysyms::3270_Reset => Key::Reset, // keysyms::3270_Reset => NamedKey::Reset,
// keysyms::3270_Quit => Key::Quit, // keysyms::3270_Quit => NamedKey::Quit,
// keysyms::3270_PA1 => Key::Pa1, // keysyms::3270_PA1 => NamedKey::Pa1,
// keysyms::3270_PA2 => Key::Pa2, // keysyms::3270_PA2 => NamedKey::Pa2,
// keysyms::3270_PA3 => Key::Pa3, // keysyms::3270_PA3 => NamedKey::Pa3,
// keysyms::3270_Test => Key::Test, // keysyms::3270_Test => NamedKey::Test,
keysyms::_3270_Attn => Key::Attn, keysyms::_3270_Attn => NamedKey::Attn,
// keysyms::3270_CursorBlink => Key::CursorBlink, // keysyms::3270_CursorBlink => NamedKey::CursorBlink,
// keysyms::3270_AltCursor => Key::AltCursor, // keysyms::3270_AltCursor => NamedKey::AltCursor,
// keysyms::3270_KeyClick => Key::KeyClick, // keysyms::3270_KeyClick => NamedKey::KeyClick,
// keysyms::3270_Jump => Key::Jump, // keysyms::3270_Jump => NamedKey::Jump,
// keysyms::3270_Ident => Key::Ident, // keysyms::3270_Ident => NamedKey::Ident,
// keysyms::3270_Rule => Key::Rule, // keysyms::3270_Rule => NamedKey::Rule,
// keysyms::3270_Copy => Key::Copy, // keysyms::3270_Copy => NamedKey::Copy,
keysyms::_3270_Play => Key::Play, keysyms::_3270_Play => NamedKey::Play,
// keysyms::3270_Setup => Key::Setup, // keysyms::3270_Setup => NamedKey::Setup,
// keysyms::3270_Record => Key::Record, // keysyms::3270_Record => NamedKey::Record,
// keysyms::3270_ChangeScreen => Key::ChangeScreen, // keysyms::3270_ChangeScreen => NamedKey::ChangeScreen,
// keysyms::3270_DeleteWord => Key::DeleteWord, // keysyms::3270_DeleteWord => NamedKey::DeleteWord,
keysyms::_3270_ExSelect => Key::ExSel, keysyms::_3270_ExSelect => NamedKey::ExSel,
keysyms::_3270_CursorSelect => Key::CrSel, keysyms::_3270_CursorSelect => NamedKey::CrSel,
keysyms::_3270_PrintScreen => Key::PrintScreen, keysyms::_3270_PrintScreen => NamedKey::PrintScreen,
keysyms::_3270_Enter => Key::Enter, keysyms::_3270_Enter => NamedKey::Enter,
keysyms::space => Key::Space, keysyms::space => NamedKey::Space,
// exclam..Sinh_kunddaliya // exclam..Sinh_kunddaliya
// XFree86 // XFree86
// keysyms::XF86_ModeLock => Key::ModeLock, // keysyms::XF86_ModeLock => NamedKey::ModeLock,
// XFree86 - Backlight controls // XFree86 - Backlight controls
keysyms::XF86_MonBrightnessUp => Key::BrightnessUp, keysyms::XF86_MonBrightnessUp => NamedKey::BrightnessUp,
keysyms::XF86_MonBrightnessDown => Key::BrightnessDown, keysyms::XF86_MonBrightnessDown => NamedKey::BrightnessDown,
// keysyms::XF86_KbdLightOnOff => Key::LightOnOff, // keysyms::XF86_KbdLightOnOff => NamedKey::LightOnOff,
// keysyms::XF86_KbdBrightnessUp => Key::KeyboardBrightnessUp, // keysyms::XF86_KbdBrightnessUp => NamedKey::KeyboardBrightnessUp,
// keysyms::XF86_KbdBrightnessDown => Key::KeyboardBrightnessDown, // keysyms::XF86_KbdBrightnessDown => NamedKey::KeyboardBrightnessDown,
// XFree86 - "Internet" // XFree86 - "Internet"
keysyms::XF86_Standby => Key::Standby, keysyms::XF86_Standby => NamedKey::Standby,
keysyms::XF86_AudioLowerVolume => Key::AudioVolumeDown, keysyms::XF86_AudioLowerVolume => NamedKey::AudioVolumeDown,
keysyms::XF86_AudioRaiseVolume => Key::AudioVolumeUp, keysyms::XF86_AudioRaiseVolume => NamedKey::AudioVolumeUp,
keysyms::XF86_AudioPlay => Key::MediaPlay, keysyms::XF86_AudioPlay => NamedKey::MediaPlay,
keysyms::XF86_AudioStop => Key::MediaStop, keysyms::XF86_AudioStop => NamedKey::MediaStop,
keysyms::XF86_AudioPrev => Key::MediaTrackPrevious, keysyms::XF86_AudioPrev => NamedKey::MediaTrackPrevious,
keysyms::XF86_AudioNext => Key::MediaTrackNext, keysyms::XF86_AudioNext => NamedKey::MediaTrackNext,
keysyms::XF86_HomePage => Key::BrowserHome, keysyms::XF86_HomePage => NamedKey::BrowserHome,
keysyms::XF86_Mail => Key::LaunchMail, keysyms::XF86_Mail => NamedKey::LaunchMail,
// keysyms::XF86_Start => Key::Start, // keysyms::XF86_Start => NamedKey::Start,
keysyms::XF86_Search => Key::BrowserSearch, keysyms::XF86_Search => NamedKey::BrowserSearch,
keysyms::XF86_AudioRecord => Key::MediaRecord, keysyms::XF86_AudioRecord => NamedKey::MediaRecord,
// XFree86 - PDA // XFree86 - PDA
keysyms::XF86_Calculator => Key::LaunchApplication2, keysyms::XF86_Calculator => NamedKey::LaunchApplication2,
// keysyms::XF86_Memo => Key::Memo, // keysyms::XF86_Memo => NamedKey::Memo,
// keysyms::XF86_ToDoList => Key::ToDoList, // keysyms::XF86_ToDoList => NamedKey::ToDoList,
keysyms::XF86_Calendar => Key::LaunchCalendar, keysyms::XF86_Calendar => NamedKey::LaunchCalendar,
keysyms::XF86_PowerDown => Key::Power, keysyms::XF86_PowerDown => NamedKey::Power,
// keysyms::XF86_ContrastAdjust => Key::AdjustContrast, // keysyms::XF86_ContrastAdjust => NamedKey::AdjustContrast,
// keysyms::XF86_RockerUp => Key::RockerUp, // keysyms::XF86_RockerUp => NamedKey::RockerUp,
// keysyms::XF86_RockerDown => Key::RockerDown, // keysyms::XF86_RockerDown => NamedKey::RockerDown,
// keysyms::XF86_RockerEnter => Key::RockerEnter, // keysyms::XF86_RockerEnter => NamedKey::RockerEnter,
// XFree86 - More "Internet" // XFree86 - More "Internet"
keysyms::XF86_Back => Key::BrowserBack, keysyms::XF86_Back => NamedKey::BrowserBack,
keysyms::XF86_Forward => Key::BrowserForward, keysyms::XF86_Forward => NamedKey::BrowserForward,
// keysyms::XF86_Stop => Key::Stop, // keysyms::XF86_Stop => NamedKey::Stop,
keysyms::XF86_Refresh => Key::BrowserRefresh, keysyms::XF86_Refresh => NamedKey::BrowserRefresh,
keysyms::XF86_PowerOff => Key::Power, keysyms::XF86_PowerOff => NamedKey::Power,
keysyms::XF86_WakeUp => Key::WakeUp, keysyms::XF86_WakeUp => NamedKey::WakeUp,
keysyms::XF86_Eject => Key::Eject, keysyms::XF86_Eject => NamedKey::Eject,
keysyms::XF86_ScreenSaver => Key::LaunchScreenSaver, keysyms::XF86_ScreenSaver => NamedKey::LaunchScreenSaver,
keysyms::XF86_WWW => Key::LaunchWebBrowser, keysyms::XF86_WWW => NamedKey::LaunchWebBrowser,
keysyms::XF86_Sleep => Key::Standby, keysyms::XF86_Sleep => NamedKey::Standby,
keysyms::XF86_Favorites => Key::BrowserFavorites, keysyms::XF86_Favorites => NamedKey::BrowserFavorites,
keysyms::XF86_AudioPause => Key::MediaPause, keysyms::XF86_AudioPause => NamedKey::MediaPause,
// keysyms::XF86_AudioMedia => Key::AudioMedia, // keysyms::XF86_AudioMedia => NamedKey::AudioMedia,
keysyms::XF86_MyComputer => Key::LaunchApplication1, keysyms::XF86_MyComputer => NamedKey::LaunchApplication1,
// keysyms::XF86_VendorHome => Key::VendorHome, // keysyms::XF86_VendorHome => NamedKey::VendorHome,
// keysyms::XF86_LightBulb => Key::LightBulb, // keysyms::XF86_LightBulb => NamedKey::LightBulb,
// keysyms::XF86_Shop => Key::BrowserShop, // keysyms::XF86_Shop => NamedKey::BrowserShop,
// keysyms::XF86_History => Key::BrowserHistory, // keysyms::XF86_History => NamedKey::BrowserHistory,
// keysyms::XF86_OpenURL => Key::OpenUrl, // keysyms::XF86_OpenURL => NamedKey::OpenUrl,
// keysyms::XF86_AddFavorite => Key::AddFavorite, // keysyms::XF86_AddFavorite => NamedKey::AddFavorite,
// keysyms::XF86_HotLinks => Key::HotLinks, // keysyms::XF86_HotLinks => NamedKey::HotLinks,
// keysyms::XF86_BrightnessAdjust => Key::BrightnessAdjust, // keysyms::XF86_BrightnessAdjust => NamedKey::BrightnessAdjust,
// keysyms::XF86_Finance => Key::BrowserFinance, // keysyms::XF86_Finance => NamedKey::BrowserFinance,
// keysyms::XF86_Community => Key::BrowserCommunity, // keysyms::XF86_Community => NamedKey::BrowserCommunity,
keysyms::XF86_AudioRewind => Key::MediaRewind, keysyms::XF86_AudioRewind => NamedKey::MediaRewind,
// keysyms::XF86_BackForward => Key::???, // keysyms::XF86_BackForward => Key::???,
// XF86_Launch0..XF86_LaunchF // XF86_Launch0..XF86_LaunchF
// XF86_ApplicationLeft..XF86_CD // XF86_ApplicationLeft..XF86_CD
keysyms::XF86_Calculater => Key::LaunchApplication2, // Nice typo, libxkbcommon :) keysyms::XF86_Calculater => NamedKey::LaunchApplication2, // Nice typo, libxkbcommon :)
// XF86_Clear // XF86_Clear
keysyms::XF86_Close => Key::Close, keysyms::XF86_Close => NamedKey::Close,
keysyms::XF86_Copy => Key::Copy, keysyms::XF86_Copy => NamedKey::Copy,
keysyms::XF86_Cut => Key::Cut, keysyms::XF86_Cut => NamedKey::Cut,
// XF86_Display..XF86_Documents // XF86_Display..XF86_Documents
keysyms::XF86_Excel => Key::LaunchSpreadsheet, keysyms::XF86_Excel => NamedKey::LaunchSpreadsheet,
// XF86_Explorer..XF86iTouch // XF86_Explorer..XF86iTouch
keysyms::XF86_LogOff => Key::LogOff, keysyms::XF86_LogOff => NamedKey::LogOff,
// XF86_Market..XF86_MenuPB // XF86_Market..XF86_MenuPB
keysyms::XF86_MySites => Key::BrowserFavorites, keysyms::XF86_MySites => NamedKey::BrowserFavorites,
keysyms::XF86_New => Key::New, keysyms::XF86_New => NamedKey::New,
// XF86_News..XF86_OfficeHome // XF86_News..XF86_OfficeHome
keysyms::XF86_Open => Key::Open, keysyms::XF86_Open => NamedKey::Open,
// XF86_Option // XF86_Option
keysyms::XF86_Paste => Key::Paste, keysyms::XF86_Paste => NamedKey::Paste,
keysyms::XF86_Phone => Key::LaunchPhone, keysyms::XF86_Phone => NamedKey::LaunchPhone,
// XF86_Q // XF86_Q
keysyms::XF86_Reply => Key::MailReply, keysyms::XF86_Reply => NamedKey::MailReply,
keysyms::XF86_Reload => Key::BrowserRefresh, keysyms::XF86_Reload => NamedKey::BrowserRefresh,
// XF86_RotateWindows..XF86_RotationKB // XF86_RotateWindows..XF86_RotationKB
keysyms::XF86_Save => Key::Save, keysyms::XF86_Save => NamedKey::Save,
// XF86_ScrollUp..XF86_ScrollClick // XF86_ScrollUp..XF86_ScrollClick
keysyms::XF86_Send => Key::MailSend, keysyms::XF86_Send => NamedKey::MailSend,
keysyms::XF86_Spell => Key::SpellCheck, keysyms::XF86_Spell => NamedKey::SpellCheck,
keysyms::XF86_SplitScreen => Key::SplitScreenToggle, keysyms::XF86_SplitScreen => NamedKey::SplitScreenToggle,
// XF86_Support..XF86_User2KB // XF86_Support..XF86_User2KB
keysyms::XF86_Video => Key::LaunchMediaPlayer, keysyms::XF86_Video => NamedKey::LaunchMediaPlayer,
// XF86_WheelButton // XF86_WheelButton
keysyms::XF86_Word => Key::LaunchWordProcessor, keysyms::XF86_Word => NamedKey::LaunchWordProcessor,
// XF86_Xfer // XF86_Xfer
keysyms::XF86_ZoomIn => Key::ZoomIn, keysyms::XF86_ZoomIn => NamedKey::ZoomIn,
keysyms::XF86_ZoomOut => Key::ZoomOut, keysyms::XF86_ZoomOut => NamedKey::ZoomOut,
// XF86_Away..XF86_Messenger // XF86_Away..XF86_Messenger
keysyms::XF86_WebCam => Key::LaunchWebCam, keysyms::XF86_WebCam => NamedKey::LaunchWebCam,
keysyms::XF86_MailForward => Key::MailForward, keysyms::XF86_MailForward => NamedKey::MailForward,
// XF86_Pictures // XF86_Pictures
keysyms::XF86_Music => Key::LaunchMusicPlayer, keysyms::XF86_Music => NamedKey::LaunchMusicPlayer,
// XF86_Battery..XF86_UWB // XF86_Battery..XF86_UWB
// //
keysyms::XF86_AudioForward => Key::MediaFastForward, keysyms::XF86_AudioForward => NamedKey::MediaFastForward,
// XF86_AudioRepeat // XF86_AudioRepeat
keysyms::XF86_AudioRandomPlay => Key::RandomToggle, keysyms::XF86_AudioRandomPlay => NamedKey::RandomToggle,
keysyms::XF86_Subtitle => Key::Subtitle, keysyms::XF86_Subtitle => NamedKey::Subtitle,
keysyms::XF86_AudioCycleTrack => Key::MediaAudioTrack, keysyms::XF86_AudioCycleTrack => NamedKey::MediaAudioTrack,
// XF86_CycleAngle..XF86_Blue // XF86_CycleAngle..XF86_Blue
// //
keysyms::XF86_Suspend => Key::Standby, keysyms::XF86_Suspend => NamedKey::Standby,
keysyms::XF86_Hibernate => Key::Hibernate, keysyms::XF86_Hibernate => NamedKey::Hibernate,
// XF86_TouchpadToggle..XF86_TouchpadOff // XF86_TouchpadToggle..XF86_TouchpadOff
// //
keysyms::XF86_AudioMute => Key::AudioVolumeMute, keysyms::XF86_AudioMute => NamedKey::AudioVolumeMute,
// XF86_Switch_VT_1..XF86_Switch_VT_12 // XF86_Switch_VT_1..XF86_Switch_VT_12
// XF86_Ungrab..XF86_ClearGrab // XF86_Ungrab..XF86_ClearGrab
keysyms::XF86_Next_VMode => Key::VideoModeNext, keysyms::XF86_Next_VMode => NamedKey::VideoModeNext,
// keysyms::XF86_Prev_VMode => Key::VideoModePrevious, // keysyms::XF86_Prev_VMode => NamedKey::VideoModePrevious,
// XF86_LogWindowTree..XF86_LogGrabInfo // XF86_LogWindowTree..XF86_LogGrabInfo
// SunFA_Grave..SunFA_Cedilla // SunFA_Grave..SunFA_Cedilla
// keysyms::SunF36 => Key::F36 | Key::F11, // keysyms::SunF36 => NamedKey::F36 | NamedKey::F11,
// keysyms::SunF37 => Key::F37 | Key::F12, // 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. // The next couple of xkb (until SunStop) are already handled.
// SunPrint_Screen..SunPageDown // SunPrint_Screen..SunPageDown
// SunUndo..SunFront // SunUndo..SunFront
keysyms::SUN_Copy => Key::Copy, keysyms::SUN_Copy => NamedKey::Copy,
keysyms::SUN_Open => Key::Open, keysyms::SUN_Open => NamedKey::Open,
keysyms::SUN_Paste => Key::Paste, keysyms::SUN_Paste => NamedKey::Paste,
keysyms::SUN_Cut => Key::Cut, keysyms::SUN_Cut => NamedKey::Cut,
// SunPowerSwitch // SunPowerSwitch
keysyms::SUN_AudioLowerVolume => Key::AudioVolumeDown, keysyms::SUN_AudioLowerVolume => NamedKey::AudioVolumeDown,
keysyms::SUN_AudioMute => Key::AudioVolumeMute, keysyms::SUN_AudioMute => NamedKey::AudioVolumeMute,
keysyms::SUN_AudioRaiseVolume => Key::AudioVolumeUp, keysyms::SUN_AudioRaiseVolume => NamedKey::AudioVolumeUp,
// SUN_VideoDegauss // SUN_VideoDegauss
keysyms::SUN_VideoLowerBrightness => Key::BrightnessDown, keysyms::SUN_VideoLowerBrightness => NamedKey::BrightnessDown,
keysyms::SUN_VideoRaiseBrightness => Key::BrightnessUp, keysyms::SUN_VideoRaiseBrightness => NamedKey::BrightnessUp,
// SunPowerSwitchShift // SunPowerSwitchShift
// //
0 => Key::Unidentified(NativeKey::Unidentified), 0 => return Key::Unidentified(NativeKey::Unidentified),
_ => Key::Unidentified(NativeKey::Xkb(keysym)), _ => return Key::Unidentified(NativeKey::Xkb(keysym)),
} })
} }
pub fn keysym_location(keysym: u32) -> KeyLocation { pub fn keysym_location(keysym: u32) -> KeyLocation {

View file

@ -22,7 +22,7 @@ use crate::platform_impl::common::keymap;
use crate::platform_impl::KeyEventExtra; use crate::platform_impl::KeyEventExtra;
use crate::{ use crate::{
event::ElementState, event::ElementState,
keyboard::{Key, KeyCode, KeyLocation}, keyboard::{Key, KeyLocation, PhysicalKey},
}; };
// TODO: Wire this up without using a static `AtomicBool`. // TODO: Wire this up without using a static `AtomicBool`.
@ -391,7 +391,7 @@ impl KbdState {
) -> KeyEvent { ) -> KeyEvent {
let mut event = let mut event =
KeyEventResults::new(self, keycode, !repeat && state == ElementState::Pressed); 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 (logical_key, location) = event.key();
let text = event.text(); let text = event.text();
let (key_without_modifiers, _) = event.key_without_modifiers(); let (key_without_modifiers, _) = event.key_without_modifiers();
@ -498,8 +498,8 @@ impl<'a> KeyEventResults<'a> {
} }
} }
fn keycode(&mut self) -> KeyCode { fn physical_key(&mut self) -> PhysicalKey {
keymap::raw_keycode_to_keycode(self.keycode) keymap::raw_keycode_to_physicalkey(self.keycode)
} }
pub fn key(&mut self) -> (Key, KeyLocation) { pub fn key(&mut self) -> (Key, KeyLocation) {

View file

@ -25,10 +25,10 @@ use crate::{
EventLoopWindowTarget as RootELW, EventLoopWindowTarget as RootELW,
}, },
icon::Icon, icon::Icon,
keyboard::{Key, KeyCode}, keyboard::{Key, PhysicalKey},
platform::{ platform::{
modifier_supplement::KeyEventExtModifierSupplement, pump_events::PumpStatus, modifier_supplement::KeyEventExtModifierSupplement, pump_events::PumpStatus,
scancode::KeyCodeExtScancode, scancode::PhysicalKeyExtScancode,
}, },
window::{ window::{
ActivationToken, CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme, ActivationToken, CursorGrabMode, CursorIcon, ImePurpose, ResizeDirection, Theme,
@ -657,13 +657,13 @@ impl KeyEventExtModifierSupplement for KeyEvent {
} }
} }
impl KeyCodeExtScancode for KeyCode { impl PhysicalKeyExtScancode for PhysicalKey {
fn from_scancode(scancode: u32) -> KeyCode { fn from_scancode(scancode: u32) -> PhysicalKey {
common::keymap::scancode_to_keycode(scancode) common::keymap::scancode_to_keycode(scancode)
} }
fn to_scancode(self) -> Option<u32> { fn to_scancode(self) -> Option<u32> {
common::keymap::keycode_to_scancode(self) common::keymap::physicalkey_to_scancode(self)
} }
} }

View file

@ -1201,7 +1201,7 @@ impl<T: 'static> EventProcessor<T> {
if keycode < KEYCODE_OFFSET as u32 { if keycode < KEYCODE_OFFSET as u32 {
return; return;
} }
let physical_key = keymap::raw_keycode_to_keycode(keycode); let physical_key = keymap::raw_keycode_to_physicalkey(keycode);
callback(Event::DeviceEvent { callback(Event::DeviceEvent {
device_id, device_id,

View file

@ -11,9 +11,12 @@ use super::appkit::{NSEvent, NSEventModifierFlags};
use crate::{ use crate::{
event::{ElementState, KeyEvent, Modifiers}, event::{ElementState, KeyEvent, Modifiers},
keyboard::{ 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, platform_impl::platform::ffi,
}; };
@ -112,13 +115,14 @@ pub(crate) fn create_key_event(
ns_event: &NSEvent, ns_event: &NSEvent,
is_press: bool, is_press: bool,
is_repeat: bool, is_repeat: bool,
key_override: Option<KeyCode>, key_override: Option<PhysicalKey>,
) -> KeyEvent { ) -> KeyEvent {
use ElementState::{Pressed, Released}; use ElementState::{Pressed, Released};
let state = if is_press { Pressed } else { Released }; let state = if is_press { Pressed } else { Released };
let scancode = ns_event.key_code(); 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<SmolStr> = if key_override.is_some() { let text_with_all_modifiers: Option<SmolStr> = if key_override.is_some() {
None None
@ -130,7 +134,7 @@ pub(crate) fn create_key_event(
if characters.is_empty() { if characters.is_empty() {
None None
} else { } else {
if matches!(physical_key, KeyCode::Unidentified(_)) { if matches!(physical_key, PhysicalKey::Unidentified(_)) {
// The key may be one of the funky function keys // The key may be one of the funky function keys
physical_key = extra_function_key_to_code(scancode, &characters); 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 { pub fn code_to_key(key: PhysicalKey, scancode: u16) -> Key {
match code { let code = match key {
KeyCode::Enter => Key::Enter, PhysicalKey::Code(code) => code,
KeyCode::Tab => Key::Tab, PhysicalKey::Unidentified(code) => return Key::Unidentified(code.into()),
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, Key::Named(match code {
KeyCode::AudioVolumeUp => Key::AudioVolumeUp, KeyCode::Enter => NamedKey::Enter,
KeyCode::AudioVolumeDown => Key::AudioVolumeDown, 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) // Other numpad keys all generate text on macOS (if I understand correctly)
KeyCode::NumpadEnter => Key::Enter, KeyCode::NumpadEnter => NamedKey::Enter,
KeyCode::F1 => Key::F1, KeyCode::F1 => NamedKey::F1,
KeyCode::F2 => Key::F2, KeyCode::F2 => NamedKey::F2,
KeyCode::F3 => Key::F3, KeyCode::F3 => NamedKey::F3,
KeyCode::F4 => Key::F4, KeyCode::F4 => NamedKey::F4,
KeyCode::F5 => Key::F5, KeyCode::F5 => NamedKey::F5,
KeyCode::F6 => Key::F6, KeyCode::F6 => NamedKey::F6,
KeyCode::F7 => Key::F7, KeyCode::F7 => NamedKey::F7,
KeyCode::F8 => Key::F8, KeyCode::F8 => NamedKey::F8,
KeyCode::F9 => Key::F9, KeyCode::F9 => NamedKey::F9,
KeyCode::F10 => Key::F10, KeyCode::F10 => NamedKey::F10,
KeyCode::F11 => Key::F11, KeyCode::F11 => NamedKey::F11,
KeyCode::F12 => Key::F12, KeyCode::F12 => NamedKey::F12,
KeyCode::F13 => Key::F13, KeyCode::F13 => NamedKey::F13,
KeyCode::F14 => Key::F14, KeyCode::F14 => NamedKey::F14,
KeyCode::F15 => Key::F15, KeyCode::F15 => NamedKey::F15,
KeyCode::F16 => Key::F16, KeyCode::F16 => NamedKey::F16,
KeyCode::F17 => Key::F17, KeyCode::F17 => NamedKey::F17,
KeyCode::F18 => Key::F18, KeyCode::F18 => NamedKey::F18,
KeyCode::F19 => Key::F19, KeyCode::F19 => NamedKey::F19,
KeyCode::F20 => Key::F20, KeyCode::F20 => NamedKey::F20,
KeyCode::Insert => Key::Insert, KeyCode::Insert => NamedKey::Insert,
KeyCode::Home => Key::Home, KeyCode::Home => NamedKey::Home,
KeyCode::PageUp => Key::PageUp, KeyCode::PageUp => NamedKey::PageUp,
KeyCode::Delete => Key::Delete, KeyCode::Delete => NamedKey::Delete,
KeyCode::End => Key::End, KeyCode::End => NamedKey::End,
KeyCode::PageDown => Key::PageDown, KeyCode::PageDown => NamedKey::PageDown,
KeyCode::ArrowLeft => Key::ArrowLeft, KeyCode::ArrowLeft => NamedKey::ArrowLeft,
KeyCode::ArrowRight => Key::ArrowRight, KeyCode::ArrowRight => NamedKey::ArrowRight,
KeyCode::ArrowDown => Key::ArrowDown, KeyCode::ArrowDown => NamedKey::ArrowDown,
KeyCode::ArrowUp => Key::ArrowUp, KeyCode::ArrowUp => NamedKey::ArrowUp,
_ => Key::Unidentified(NativeKey::MacOS(scancode)), _ => 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 { match code {
KeyCode::SuperRight => KeyLocation::Right, KeyCode::SuperRight => KeyLocation::Right,
KeyCode::SuperLeft => KeyLocation::Left, 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 // While F1-F20 have scancodes we can match on, we have to check against UTF-16
// constants for the rest. // constants for the rest.
// https://developer.apple.com/documentation/appkit/1535851-function-key_unicodes?preferredLanguage=occ // 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() { if let Some(ch) = string.encode_utf16().next() {
match ch { match ch {
0xf718 => KeyCode::F21, 0xf718 => PhysicalKey::Code(KeyCode::F21),
0xf719 => KeyCode::F22, 0xf719 => PhysicalKey::Code(KeyCode::F22),
0xf71a => KeyCode::F23, 0xf71a => PhysicalKey::Code(KeyCode::F23),
0xf71b => KeyCode::F24, 0xf71b => PhysicalKey::Code(KeyCode::F24),
_ => KeyCode::Unidentified(NativeKeyCode::MacOS(scancode)), _ => PhysicalKey::Unidentified(NativeKeyCode::MacOS(scancode)),
} }
} else { } 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<u32> { fn to_scancode(self) -> Option<u32> {
match self { let code = match self {
PhysicalKey::Code(code) => code,
PhysicalKey::Unidentified(_) => return None,
};
match code {
KeyCode::KeyA => Some(0x00), KeyCode::KeyA => Some(0x00),
KeyCode::KeyS => Some(0x01), KeyCode::KeyS => Some(0x01),
KeyCode::KeyD => Some(0x02), KeyCode::KeyD => Some(0x02),
@ -458,8 +477,8 @@ impl KeyCodeExtScancode for KeyCode {
} }
} }
fn from_scancode(scancode: u32) -> KeyCode { fn from_scancode(scancode: u32) -> PhysicalKey {
match scancode { PhysicalKey::Code(match scancode {
0x00 => KeyCode::KeyA, 0x00 => KeyCode::KeyA,
0x01 => KeyCode::KeyS, 0x01 => KeyCode::KeyS,
0x02 => KeyCode::KeyD, 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 // 0xA is the caret (^) an macOS's German QERTZ layout. This key is at the same location as
// backquote (`) on Windows' US layout. // backquote (`) on Windows' US layout.
0xa => KeyCode::Backquote, 0xa => KeyCode::Backquote,
_ => KeyCode::Unidentified(NativeKeyCode::MacOS(scancode as u16)), _ => return PhysicalKey::Unidentified(NativeKeyCode::MacOS(scancode as u16)),
} })
} }
} }

View file

@ -26,9 +26,9 @@ use crate::{
DeviceEvent, ElementState, Event, Ime, Modifiers, MouseButton, MouseScrollDelta, DeviceEvent, ElementState, Event, Ime, Modifiers, MouseButton, MouseScrollDelta,
TouchPhase, WindowEvent, TouchPhase, WindowEvent,
}, },
keyboard::{Key, KeyCode, KeyLocation, ModifiersState}, keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey, PhysicalKey},
platform::macos::{OptionAsAlt, WindowExtMacOS}, platform::macos::{OptionAsAlt, WindowExtMacOS},
platform::scancode::KeyCodeExtScancode, platform::scancode::PhysicalKeyExtScancode,
platform_impl::platform::{ platform_impl::platform::{
app_state::AppState, app_state::AppState,
event::{create_key_event, event_mods}, event::{create_key_event, event_mods},
@ -90,30 +90,30 @@ impl ModLocationMask {
fn key_to_modifier(key: &Key) -> ModifiersState { fn key_to_modifier(key: &Key) -> ModifiersState {
match key { match key {
Key::Alt => ModifiersState::ALT, Key::Named(NamedKey::Alt) => ModifiersState::ALT,
Key::Control => ModifiersState::CONTROL, Key::Named(NamedKey::Control) => ModifiersState::CONTROL,
Key::Super => ModifiersState::SUPER, Key::Named(NamedKey::Super) => ModifiersState::SUPER,
Key::Shift => ModifiersState::SHIFT, Key::Named(NamedKey::Shift) => ModifiersState::SHIFT,
_ => unreachable!(), _ => unreachable!(),
} }
} }
fn get_right_modifier_code(key: &Key) -> KeyCode { fn get_right_modifier_code(key: &Key) -> KeyCode {
match key { match key {
Key::Alt => KeyCode::AltRight, Key::Named(NamedKey::Alt) => KeyCode::AltRight,
Key::Control => KeyCode::ControlRight, Key::Named(NamedKey::Control) => KeyCode::ControlRight,
Key::Shift => KeyCode::ShiftRight, Key::Named(NamedKey::Shift) => KeyCode::ShiftRight,
Key::Super => KeyCode::SuperRight, Key::Named(NamedKey::Super) => KeyCode::SuperRight,
_ => unreachable!(), _ => unreachable!(),
} }
} }
fn get_left_modifier_code(key: &Key) -> KeyCode { fn get_left_modifier_code(key: &Key) -> KeyCode {
match key { match key {
Key::Alt => KeyCode::AltLeft, Key::Named(NamedKey::Alt) => KeyCode::AltLeft,
Key::Control => KeyCode::ControlLeft, Key::Named(NamedKey::Control) => KeyCode::ControlLeft,
Key::Shift => KeyCode::ShiftLeft, Key::Named(NamedKey::Shift) => KeyCode::ShiftLeft,
Key::Super => KeyCode::SuperLeft, Key::Named(NamedKey::Super) => KeyCode::SuperLeft,
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -926,16 +926,16 @@ impl WinitView {
// information. // information.
if is_flags_changed_event && ns_event.key_code() != 0 { if is_flags_changed_event && ns_event.key_code() != 0 {
let scancode = ns_event.key_code(); 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. // 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); let event_modifier = key_to_modifier(&key);
event.physical_key = keycode; event.physical_key = physical_key;
event.logical_key = key.clone(); 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 location_mask = ModLocationMask::from_location(event.location);
let mut phys_mod_state = self.state.phys_modifiers.borrow_mut(); let mut phys_mod_state = self.state.phys_modifiers.borrow_mut();
@ -956,7 +956,7 @@ impl WinitView {
if phys_mod.contains(ModLocationMask::LEFT) { if phys_mod.contains(ModLocationMask::LEFT) {
let mut event = event.clone(); let mut event = event.clone();
event.location = KeyLocation::Left; 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 { events.push_back(WindowEvent::KeyboardInput {
device_id: DEVICE_ID, device_id: DEVICE_ID,
event, event,
@ -965,7 +965,7 @@ impl WinitView {
} }
if phys_mod.contains(ModLocationMask::RIGHT) { if phys_mod.contains(ModLocationMask::RIGHT) {
event.location = KeyLocation::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 { events.push_back(WindowEvent::KeyboardInput {
device_id: DEVICE_ID, device_id: DEVICE_ID,
event, event,

View file

@ -18,6 +18,7 @@ use crate::{
event_loop::{self, ControlFlow, DeviceEvents}, event_loop::{self, ControlFlow, DeviceEvents},
keyboard::{ keyboard::{
Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NativeKey, NativeKeyCode, Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NativeKey, NativeKeyCode,
PhysicalKey,
}, },
window::WindowId as RootWindowId, window::WindowId as RootWindowId,
}; };
@ -27,8 +28,8 @@ use super::{
RedoxSocket, TimeSocket, WindowId, WindowProperties, RedoxSocket, TimeSocket, WindowId, WindowProperties,
}; };
fn convert_scancode(scancode: u8) -> KeyCode { fn convert_scancode(scancode: u8) -> PhysicalKey {
match scancode { PhysicalKey::Code(match scancode {
orbclient::K_A => KeyCode::KeyA, orbclient::K_A => KeyCode::KeyA,
orbclient::K_B => KeyCode::KeyB, orbclient::K_B => KeyCode::KeyB,
orbclient::K_C => KeyCode::KeyC, orbclient::K_C => KeyCode::KeyC,
@ -109,8 +110,8 @@ fn convert_scancode(scancode: u8) -> KeyCode {
orbclient::K_F11 => KeyCode::F11, orbclient::K_F11 => KeyCode::F11,
orbclient::K_F12 => KeyCode::F12, orbclient::K_F12 => KeyCode::F12,
_ => KeyCode::Unidentified(NativeKeyCode::Unidentified), _ => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified),
} })
} }
fn element_state(pressed: bool) -> event::ElementState { fn element_state(pressed: bool) -> event::ElementState {
@ -152,7 +153,12 @@ struct EventState {
} }
impl 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 { match code {
KeyCode::ShiftLeft => self.keyboard.set(KeyboardModifierState::LSHIFT, pressed), KeyCode::ShiftLeft => self.keyboard.set(KeyboardModifierState::LSHIFT, pressed),
KeyCode::ShiftRight => self.keyboard.set(KeyboardModifierState::RSHIFT, pressed), KeyCode::ShiftRight => self.keyboard.set(KeyboardModifierState::RSHIFT, pressed),
@ -332,16 +338,16 @@ impl<T: 'static> EventLoop<T> {
pressed, pressed,
}) => { }) => {
if scancode != 0 { if scancode != 0 {
let code = convert_scancode(scancode); let physical_key = convert_scancode(scancode);
let modifiers_before = event_state.keyboard; let modifiers_before = event_state.keyboard;
event_state.key(code, pressed); event_state.key(physical_key, pressed);
event_handler(event::Event::WindowEvent { event_handler(event::Event::WindowEvent {
window_id: RootWindowId(window_id), window_id: RootWindowId(window_id),
event: event::WindowEvent::KeyboardInput { event: event::WindowEvent::KeyboardInput {
device_id: event::DeviceId(DeviceId), device_id: event::DeviceId(DeviceId),
event: event::KeyEvent { event: event::KeyEvent {
logical_key: Key::Unidentified(NativeKey::Unidentified), logical_key: Key::Unidentified(NativeKey::Unidentified),
physical_key: code, physical_key,
location: KeyLocation::Standard, location: KeyLocation::Standard,
state: element_state(pressed), state: element_state(pressed),
repeat: false, repeat: false,

View file

@ -1,328 +1,328 @@
use smol_str::SmolStr; 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)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub(crate) struct KeyEventExtra; pub(crate) struct KeyEventExtra;
impl Key { impl Key {
pub(crate) fn from_key_attribute_value(kav: &str) -> Self { pub(crate) fn from_key_attribute_value(kav: &str) -> Self {
match kav { Key::Named(match kav {
"Unidentified" => Key::Unidentified(NativeKey::Web(SmolStr::new(kav))), "Unidentified" => return Key::Unidentified(NativeKey::Web(SmolStr::new(kav))),
"Dead" => Key::Dead(None), "Dead" => return Key::Dead(None),
"Alt" => Key::Alt, "Alt" => NamedKey::Alt,
"AltGraph" => Key::AltGraph, "AltGraph" => NamedKey::AltGraph,
"CapsLock" => Key::CapsLock, "CapsLock" => NamedKey::CapsLock,
"Control" => Key::Control, "Control" => NamedKey::Control,
"Fn" => Key::Fn, "Fn" => NamedKey::Fn,
"FnLock" => Key::FnLock, "FnLock" => NamedKey::FnLock,
"NumLock" => Key::NumLock, "NumLock" => NamedKey::NumLock,
"ScrollLock" => Key::ScrollLock, "ScrollLock" => NamedKey::ScrollLock,
"Shift" => Key::Shift, "Shift" => NamedKey::Shift,
"Symbol" => Key::Symbol, "Symbol" => NamedKey::Symbol,
"SymbolLock" => Key::SymbolLock, "SymbolLock" => NamedKey::SymbolLock,
"Hyper" => Key::Hyper, "Hyper" => NamedKey::Hyper,
"Meta" => Key::Super, "Meta" => NamedKey::Super,
"Enter" => Key::Enter, "Enter" => NamedKey::Enter,
"Tab" => Key::Tab, "Tab" => NamedKey::Tab,
" " => Key::Space, " " => NamedKey::Space,
"ArrowDown" => Key::ArrowDown, "ArrowDown" => NamedKey::ArrowDown,
"ArrowLeft" => Key::ArrowLeft, "ArrowLeft" => NamedKey::ArrowLeft,
"ArrowRight" => Key::ArrowRight, "ArrowRight" => NamedKey::ArrowRight,
"ArrowUp" => Key::ArrowUp, "ArrowUp" => NamedKey::ArrowUp,
"End" => Key::End, "End" => NamedKey::End,
"Home" => Key::Home, "Home" => NamedKey::Home,
"PageDown" => Key::PageDown, "PageDown" => NamedKey::PageDown,
"PageUp" => Key::PageUp, "PageUp" => NamedKey::PageUp,
"Backspace" => Key::Backspace, "Backspace" => NamedKey::Backspace,
"Clear" => Key::Clear, "Clear" => NamedKey::Clear,
"Copy" => Key::Copy, "Copy" => NamedKey::Copy,
"CrSel" => Key::CrSel, "CrSel" => NamedKey::CrSel,
"Cut" => Key::Cut, "Cut" => NamedKey::Cut,
"Delete" => Key::Delete, "Delete" => NamedKey::Delete,
"EraseEof" => Key::EraseEof, "EraseEof" => NamedKey::EraseEof,
"ExSel" => Key::ExSel, "ExSel" => NamedKey::ExSel,
"Insert" => Key::Insert, "Insert" => NamedKey::Insert,
"Paste" => Key::Paste, "Paste" => NamedKey::Paste,
"Redo" => Key::Redo, "Redo" => NamedKey::Redo,
"Undo" => Key::Undo, "Undo" => NamedKey::Undo,
"Accept" => Key::Accept, "Accept" => NamedKey::Accept,
"Again" => Key::Again, "Again" => NamedKey::Again,
"Attn" => Key::Attn, "Attn" => NamedKey::Attn,
"Cancel" => Key::Cancel, "Cancel" => NamedKey::Cancel,
"ContextMenu" => Key::ContextMenu, "ContextMenu" => NamedKey::ContextMenu,
"Escape" => Key::Escape, "Escape" => NamedKey::Escape,
"Execute" => Key::Execute, "Execute" => NamedKey::Execute,
"Find" => Key::Find, "Find" => NamedKey::Find,
"Help" => Key::Help, "Help" => NamedKey::Help,
"Pause" => Key::Pause, "Pause" => NamedKey::Pause,
"Play" => Key::Play, "Play" => NamedKey::Play,
"Props" => Key::Props, "Props" => NamedKey::Props,
"Select" => Key::Select, "Select" => NamedKey::Select,
"ZoomIn" => Key::ZoomIn, "ZoomIn" => NamedKey::ZoomIn,
"ZoomOut" => Key::ZoomOut, "ZoomOut" => NamedKey::ZoomOut,
"BrightnessDown" => Key::BrightnessDown, "BrightnessDown" => NamedKey::BrightnessDown,
"BrightnessUp" => Key::BrightnessUp, "BrightnessUp" => NamedKey::BrightnessUp,
"Eject" => Key::Eject, "Eject" => NamedKey::Eject,
"LogOff" => Key::LogOff, "LogOff" => NamedKey::LogOff,
"Power" => Key::Power, "Power" => NamedKey::Power,
"PowerOff" => Key::PowerOff, "PowerOff" => NamedKey::PowerOff,
"PrintScreen" => Key::PrintScreen, "PrintScreen" => NamedKey::PrintScreen,
"Hibernate" => Key::Hibernate, "Hibernate" => NamedKey::Hibernate,
"Standby" => Key::Standby, "Standby" => NamedKey::Standby,
"WakeUp" => Key::WakeUp, "WakeUp" => NamedKey::WakeUp,
"AllCandidates" => Key::AllCandidates, "AllCandidates" => NamedKey::AllCandidates,
"Alphanumeric" => Key::Alphanumeric, "Alphanumeric" => NamedKey::Alphanumeric,
"CodeInput" => Key::CodeInput, "CodeInput" => NamedKey::CodeInput,
"Compose" => Key::Compose, "Compose" => NamedKey::Compose,
"Convert" => Key::Convert, "Convert" => NamedKey::Convert,
"FinalMode" => Key::FinalMode, "FinalMode" => NamedKey::FinalMode,
"GroupFirst" => Key::GroupFirst, "GroupFirst" => NamedKey::GroupFirst,
"GroupLast" => Key::GroupLast, "GroupLast" => NamedKey::GroupLast,
"GroupNext" => Key::GroupNext, "GroupNext" => NamedKey::GroupNext,
"GroupPrevious" => Key::GroupPrevious, "GroupPrevious" => NamedKey::GroupPrevious,
"ModeChange" => Key::ModeChange, "ModeChange" => NamedKey::ModeChange,
"NextCandidate" => Key::NextCandidate, "NextCandidate" => NamedKey::NextCandidate,
"NonConvert" => Key::NonConvert, "NonConvert" => NamedKey::NonConvert,
"PreviousCandidate" => Key::PreviousCandidate, "PreviousCandidate" => NamedKey::PreviousCandidate,
"Process" => Key::Process, "Process" => NamedKey::Process,
"SingleCandidate" => Key::SingleCandidate, "SingleCandidate" => NamedKey::SingleCandidate,
"HangulMode" => Key::HangulMode, "HangulMode" => NamedKey::HangulMode,
"HanjaMode" => Key::HanjaMode, "HanjaMode" => NamedKey::HanjaMode,
"JunjaMode" => Key::JunjaMode, "JunjaMode" => NamedKey::JunjaMode,
"Eisu" => Key::Eisu, "Eisu" => NamedKey::Eisu,
"Hankaku" => Key::Hankaku, "Hankaku" => NamedKey::Hankaku,
"Hiragana" => Key::Hiragana, "Hiragana" => NamedKey::Hiragana,
"HiraganaKatakana" => Key::HiraganaKatakana, "HiraganaKatakana" => NamedKey::HiraganaKatakana,
"KanaMode" => Key::KanaMode, "KanaMode" => NamedKey::KanaMode,
"KanjiMode" => Key::KanjiMode, "KanjiMode" => NamedKey::KanjiMode,
"Katakana" => Key::Katakana, "Katakana" => NamedKey::Katakana,
"Romaji" => Key::Romaji, "Romaji" => NamedKey::Romaji,
"Zenkaku" => Key::Zenkaku, "Zenkaku" => NamedKey::Zenkaku,
"ZenkakuHankaku" => Key::ZenkakuHankaku, "ZenkakuHankaku" => NamedKey::ZenkakuHankaku,
"Soft1" => Key::Soft1, "Soft1" => NamedKey::Soft1,
"Soft2" => Key::Soft2, "Soft2" => NamedKey::Soft2,
"Soft3" => Key::Soft3, "Soft3" => NamedKey::Soft3,
"Soft4" => Key::Soft4, "Soft4" => NamedKey::Soft4,
"ChannelDown" => Key::ChannelDown, "ChannelDown" => NamedKey::ChannelDown,
"ChannelUp" => Key::ChannelUp, "ChannelUp" => NamedKey::ChannelUp,
"Close" => Key::Close, "Close" => NamedKey::Close,
"MailForward" => Key::MailForward, "MailForward" => NamedKey::MailForward,
"MailReply" => Key::MailReply, "MailReply" => NamedKey::MailReply,
"MailSend" => Key::MailSend, "MailSend" => NamedKey::MailSend,
"MediaClose" => Key::MediaClose, "MediaClose" => NamedKey::MediaClose,
"MediaFastForward" => Key::MediaFastForward, "MediaFastForward" => NamedKey::MediaFastForward,
"MediaPause" => Key::MediaPause, "MediaPause" => NamedKey::MediaPause,
"MediaPlay" => Key::MediaPlay, "MediaPlay" => NamedKey::MediaPlay,
"MediaPlayPause" => Key::MediaPlayPause, "MediaPlayPause" => NamedKey::MediaPlayPause,
"MediaRecord" => Key::MediaRecord, "MediaRecord" => NamedKey::MediaRecord,
"MediaRewind" => Key::MediaRewind, "MediaRewind" => NamedKey::MediaRewind,
"MediaStop" => Key::MediaStop, "MediaStop" => NamedKey::MediaStop,
"MediaTrackNext" => Key::MediaTrackNext, "MediaTrackNext" => NamedKey::MediaTrackNext,
"MediaTrackPrevious" => Key::MediaTrackPrevious, "MediaTrackPrevious" => NamedKey::MediaTrackPrevious,
"New" => Key::New, "New" => NamedKey::New,
"Open" => Key::Open, "Open" => NamedKey::Open,
"Print" => Key::Print, "Print" => NamedKey::Print,
"Save" => Key::Save, "Save" => NamedKey::Save,
"SpellCheck" => Key::SpellCheck, "SpellCheck" => NamedKey::SpellCheck,
"Key11" => Key::Key11, "Key11" => NamedKey::Key11,
"Key12" => Key::Key12, "Key12" => NamedKey::Key12,
"AudioBalanceLeft" => Key::AudioBalanceLeft, "AudioBalanceLeft" => NamedKey::AudioBalanceLeft,
"AudioBalanceRight" => Key::AudioBalanceRight, "AudioBalanceRight" => NamedKey::AudioBalanceRight,
"AudioBassBoostDown" => Key::AudioBassBoostDown, "AudioBassBoostDown" => NamedKey::AudioBassBoostDown,
"AudioBassBoostToggle" => Key::AudioBassBoostToggle, "AudioBassBoostToggle" => NamedKey::AudioBassBoostToggle,
"AudioBassBoostUp" => Key::AudioBassBoostUp, "AudioBassBoostUp" => NamedKey::AudioBassBoostUp,
"AudioFaderFront" => Key::AudioFaderFront, "AudioFaderFront" => NamedKey::AudioFaderFront,
"AudioFaderRear" => Key::AudioFaderRear, "AudioFaderRear" => NamedKey::AudioFaderRear,
"AudioSurroundModeNext" => Key::AudioSurroundModeNext, "AudioSurroundModeNext" => NamedKey::AudioSurroundModeNext,
"AudioTrebleDown" => Key::AudioTrebleDown, "AudioTrebleDown" => NamedKey::AudioTrebleDown,
"AudioTrebleUp" => Key::AudioTrebleUp, "AudioTrebleUp" => NamedKey::AudioTrebleUp,
"AudioVolumeDown" => Key::AudioVolumeDown, "AudioVolumeDown" => NamedKey::AudioVolumeDown,
"AudioVolumeUp" => Key::AudioVolumeUp, "AudioVolumeUp" => NamedKey::AudioVolumeUp,
"AudioVolumeMute" => Key::AudioVolumeMute, "AudioVolumeMute" => NamedKey::AudioVolumeMute,
"MicrophoneToggle" => Key::MicrophoneToggle, "MicrophoneToggle" => NamedKey::MicrophoneToggle,
"MicrophoneVolumeDown" => Key::MicrophoneVolumeDown, "MicrophoneVolumeDown" => NamedKey::MicrophoneVolumeDown,
"MicrophoneVolumeUp" => Key::MicrophoneVolumeUp, "MicrophoneVolumeUp" => NamedKey::MicrophoneVolumeUp,
"MicrophoneVolumeMute" => Key::MicrophoneVolumeMute, "MicrophoneVolumeMute" => NamedKey::MicrophoneVolumeMute,
"SpeechCorrectionList" => Key::SpeechCorrectionList, "SpeechCorrectionList" => NamedKey::SpeechCorrectionList,
"SpeechInputToggle" => Key::SpeechInputToggle, "SpeechInputToggle" => NamedKey::SpeechInputToggle,
"LaunchApplication1" => Key::LaunchApplication1, "LaunchApplication1" => NamedKey::LaunchApplication1,
"LaunchApplication2" => Key::LaunchApplication2, "LaunchApplication2" => NamedKey::LaunchApplication2,
"LaunchCalendar" => Key::LaunchCalendar, "LaunchCalendar" => NamedKey::LaunchCalendar,
"LaunchContacts" => Key::LaunchContacts, "LaunchContacts" => NamedKey::LaunchContacts,
"LaunchMail" => Key::LaunchMail, "LaunchMail" => NamedKey::LaunchMail,
"LaunchMediaPlayer" => Key::LaunchMediaPlayer, "LaunchMediaPlayer" => NamedKey::LaunchMediaPlayer,
"LaunchMusicPlayer" => Key::LaunchMusicPlayer, "LaunchMusicPlayer" => NamedKey::LaunchMusicPlayer,
"LaunchPhone" => Key::LaunchPhone, "LaunchPhone" => NamedKey::LaunchPhone,
"LaunchScreenSaver" => Key::LaunchScreenSaver, "LaunchScreenSaver" => NamedKey::LaunchScreenSaver,
"LaunchSpreadsheet" => Key::LaunchSpreadsheet, "LaunchSpreadsheet" => NamedKey::LaunchSpreadsheet,
"LaunchWebBrowser" => Key::LaunchWebBrowser, "LaunchWebBrowser" => NamedKey::LaunchWebBrowser,
"LaunchWebCam" => Key::LaunchWebCam, "LaunchWebCam" => NamedKey::LaunchWebCam,
"LaunchWordProcessor" => Key::LaunchWordProcessor, "LaunchWordProcessor" => NamedKey::LaunchWordProcessor,
"BrowserBack" => Key::BrowserBack, "BrowserBack" => NamedKey::BrowserBack,
"BrowserFavorites" => Key::BrowserFavorites, "BrowserFavorites" => NamedKey::BrowserFavorites,
"BrowserForward" => Key::BrowserForward, "BrowserForward" => NamedKey::BrowserForward,
"BrowserHome" => Key::BrowserHome, "BrowserHome" => NamedKey::BrowserHome,
"BrowserRefresh" => Key::BrowserRefresh, "BrowserRefresh" => NamedKey::BrowserRefresh,
"BrowserSearch" => Key::BrowserSearch, "BrowserSearch" => NamedKey::BrowserSearch,
"BrowserStop" => Key::BrowserStop, "BrowserStop" => NamedKey::BrowserStop,
"AppSwitch" => Key::AppSwitch, "AppSwitch" => NamedKey::AppSwitch,
"Call" => Key::Call, "Call" => NamedKey::Call,
"Camera" => Key::Camera, "Camera" => NamedKey::Camera,
"CameraFocus" => Key::CameraFocus, "CameraFocus" => NamedKey::CameraFocus,
"EndCall" => Key::EndCall, "EndCall" => NamedKey::EndCall,
"GoBack" => Key::GoBack, "GoBack" => NamedKey::GoBack,
"GoHome" => Key::GoHome, "GoHome" => NamedKey::GoHome,
"HeadsetHook" => Key::HeadsetHook, "HeadsetHook" => NamedKey::HeadsetHook,
"LastNumberRedial" => Key::LastNumberRedial, "LastNumberRedial" => NamedKey::LastNumberRedial,
"Notification" => Key::Notification, "Notification" => NamedKey::Notification,
"MannerMode" => Key::MannerMode, "MannerMode" => NamedKey::MannerMode,
"VoiceDial" => Key::VoiceDial, "VoiceDial" => NamedKey::VoiceDial,
"TV" => Key::TV, "TV" => NamedKey::TV,
"TV3DMode" => Key::TV3DMode, "TV3DMode" => NamedKey::TV3DMode,
"TVAntennaCable" => Key::TVAntennaCable, "TVAntennaCable" => NamedKey::TVAntennaCable,
"TVAudioDescription" => Key::TVAudioDescription, "TVAudioDescription" => NamedKey::TVAudioDescription,
"TVAudioDescriptionMixDown" => Key::TVAudioDescriptionMixDown, "TVAudioDescriptionMixDown" => NamedKey::TVAudioDescriptionMixDown,
"TVAudioDescriptionMixUp" => Key::TVAudioDescriptionMixUp, "TVAudioDescriptionMixUp" => NamedKey::TVAudioDescriptionMixUp,
"TVContentsMenu" => Key::TVContentsMenu, "TVContentsMenu" => NamedKey::TVContentsMenu,
"TVDataService" => Key::TVDataService, "TVDataService" => NamedKey::TVDataService,
"TVInput" => Key::TVInput, "TVInput" => NamedKey::TVInput,
"TVInputComponent1" => Key::TVInputComponent1, "TVInputComponent1" => NamedKey::TVInputComponent1,
"TVInputComponent2" => Key::TVInputComponent2, "TVInputComponent2" => NamedKey::TVInputComponent2,
"TVInputComposite1" => Key::TVInputComposite1, "TVInputComposite1" => NamedKey::TVInputComposite1,
"TVInputComposite2" => Key::TVInputComposite2, "TVInputComposite2" => NamedKey::TVInputComposite2,
"TVInputHDMI1" => Key::TVInputHDMI1, "TVInputHDMI1" => NamedKey::TVInputHDMI1,
"TVInputHDMI2" => Key::TVInputHDMI2, "TVInputHDMI2" => NamedKey::TVInputHDMI2,
"TVInputHDMI3" => Key::TVInputHDMI3, "TVInputHDMI3" => NamedKey::TVInputHDMI3,
"TVInputHDMI4" => Key::TVInputHDMI4, "TVInputHDMI4" => NamedKey::TVInputHDMI4,
"TVInputVGA1" => Key::TVInputVGA1, "TVInputVGA1" => NamedKey::TVInputVGA1,
"TVMediaContext" => Key::TVMediaContext, "TVMediaContext" => NamedKey::TVMediaContext,
"TVNetwork" => Key::TVNetwork, "TVNetwork" => NamedKey::TVNetwork,
"TVNumberEntry" => Key::TVNumberEntry, "TVNumberEntry" => NamedKey::TVNumberEntry,
"TVPower" => Key::TVPower, "TVPower" => NamedKey::TVPower,
"TVRadioService" => Key::TVRadioService, "TVRadioService" => NamedKey::TVRadioService,
"TVSatellite" => Key::TVSatellite, "TVSatellite" => NamedKey::TVSatellite,
"TVSatelliteBS" => Key::TVSatelliteBS, "TVSatelliteBS" => NamedKey::TVSatelliteBS,
"TVSatelliteCS" => Key::TVSatelliteCS, "TVSatelliteCS" => NamedKey::TVSatelliteCS,
"TVSatelliteToggle" => Key::TVSatelliteToggle, "TVSatelliteToggle" => NamedKey::TVSatelliteToggle,
"TVTerrestrialAnalog" => Key::TVTerrestrialAnalog, "TVTerrestrialAnalog" => NamedKey::TVTerrestrialAnalog,
"TVTerrestrialDigital" => Key::TVTerrestrialDigital, "TVTerrestrialDigital" => NamedKey::TVTerrestrialDigital,
"TVTimer" => Key::TVTimer, "TVTimer" => NamedKey::TVTimer,
"AVRInput" => Key::AVRInput, "AVRInput" => NamedKey::AVRInput,
"AVRPower" => Key::AVRPower, "AVRPower" => NamedKey::AVRPower,
"ColorF0Red" => Key::ColorF0Red, "ColorF0Red" => NamedKey::ColorF0Red,
"ColorF1Green" => Key::ColorF1Green, "ColorF1Green" => NamedKey::ColorF1Green,
"ColorF2Yellow" => Key::ColorF2Yellow, "ColorF2Yellow" => NamedKey::ColorF2Yellow,
"ColorF3Blue" => Key::ColorF3Blue, "ColorF3Blue" => NamedKey::ColorF3Blue,
"ColorF4Grey" => Key::ColorF4Grey, "ColorF4Grey" => NamedKey::ColorF4Grey,
"ColorF5Brown" => Key::ColorF5Brown, "ColorF5Brown" => NamedKey::ColorF5Brown,
"ClosedCaptionToggle" => Key::ClosedCaptionToggle, "ClosedCaptionToggle" => NamedKey::ClosedCaptionToggle,
"Dimmer" => Key::Dimmer, "Dimmer" => NamedKey::Dimmer,
"DisplaySwap" => Key::DisplaySwap, "DisplaySwap" => NamedKey::DisplaySwap,
"DVR" => Key::DVR, "DVR" => NamedKey::DVR,
"Exit" => Key::Exit, "Exit" => NamedKey::Exit,
"FavoriteClear0" => Key::FavoriteClear0, "FavoriteClear0" => NamedKey::FavoriteClear0,
"FavoriteClear1" => Key::FavoriteClear1, "FavoriteClear1" => NamedKey::FavoriteClear1,
"FavoriteClear2" => Key::FavoriteClear2, "FavoriteClear2" => NamedKey::FavoriteClear2,
"FavoriteClear3" => Key::FavoriteClear3, "FavoriteClear3" => NamedKey::FavoriteClear3,
"FavoriteRecall0" => Key::FavoriteRecall0, "FavoriteRecall0" => NamedKey::FavoriteRecall0,
"FavoriteRecall1" => Key::FavoriteRecall1, "FavoriteRecall1" => NamedKey::FavoriteRecall1,
"FavoriteRecall2" => Key::FavoriteRecall2, "FavoriteRecall2" => NamedKey::FavoriteRecall2,
"FavoriteRecall3" => Key::FavoriteRecall3, "FavoriteRecall3" => NamedKey::FavoriteRecall3,
"FavoriteStore0" => Key::FavoriteStore0, "FavoriteStore0" => NamedKey::FavoriteStore0,
"FavoriteStore1" => Key::FavoriteStore1, "FavoriteStore1" => NamedKey::FavoriteStore1,
"FavoriteStore2" => Key::FavoriteStore2, "FavoriteStore2" => NamedKey::FavoriteStore2,
"FavoriteStore3" => Key::FavoriteStore3, "FavoriteStore3" => NamedKey::FavoriteStore3,
"Guide" => Key::Guide, "Guide" => NamedKey::Guide,
"GuideNextDay" => Key::GuideNextDay, "GuideNextDay" => NamedKey::GuideNextDay,
"GuidePreviousDay" => Key::GuidePreviousDay, "GuidePreviousDay" => NamedKey::GuidePreviousDay,
"Info" => Key::Info, "Info" => NamedKey::Info,
"InstantReplay" => Key::InstantReplay, "InstantReplay" => NamedKey::InstantReplay,
"Link" => Key::Link, "Link" => NamedKey::Link,
"ListProgram" => Key::ListProgram, "ListProgram" => NamedKey::ListProgram,
"LiveContent" => Key::LiveContent, "LiveContent" => NamedKey::LiveContent,
"Lock" => Key::Lock, "Lock" => NamedKey::Lock,
"MediaApps" => Key::MediaApps, "MediaApps" => NamedKey::MediaApps,
"MediaAudioTrack" => Key::MediaAudioTrack, "MediaAudioTrack" => NamedKey::MediaAudioTrack,
"MediaLast" => Key::MediaLast, "MediaLast" => NamedKey::MediaLast,
"MediaSkipBackward" => Key::MediaSkipBackward, "MediaSkipBackward" => NamedKey::MediaSkipBackward,
"MediaSkipForward" => Key::MediaSkipForward, "MediaSkipForward" => NamedKey::MediaSkipForward,
"MediaStepBackward" => Key::MediaStepBackward, "MediaStepBackward" => NamedKey::MediaStepBackward,
"MediaStepForward" => Key::MediaStepForward, "MediaStepForward" => NamedKey::MediaStepForward,
"MediaTopMenu" => Key::MediaTopMenu, "MediaTopMenu" => NamedKey::MediaTopMenu,
"NavigateIn" => Key::NavigateIn, "NavigateIn" => NamedKey::NavigateIn,
"NavigateNext" => Key::NavigateNext, "NavigateNext" => NamedKey::NavigateNext,
"NavigateOut" => Key::NavigateOut, "NavigateOut" => NamedKey::NavigateOut,
"NavigatePrevious" => Key::NavigatePrevious, "NavigatePrevious" => NamedKey::NavigatePrevious,
"NextFavoriteChannel" => Key::NextFavoriteChannel, "NextFavoriteChannel" => NamedKey::NextFavoriteChannel,
"NextUserProfile" => Key::NextUserProfile, "NextUserProfile" => NamedKey::NextUserProfile,
"OnDemand" => Key::OnDemand, "OnDemand" => NamedKey::OnDemand,
"Pairing" => Key::Pairing, "Pairing" => NamedKey::Pairing,
"PinPDown" => Key::PinPDown, "PinPDown" => NamedKey::PinPDown,
"PinPMove" => Key::PinPMove, "PinPMove" => NamedKey::PinPMove,
"PinPToggle" => Key::PinPToggle, "PinPToggle" => NamedKey::PinPToggle,
"PinPUp" => Key::PinPUp, "PinPUp" => NamedKey::PinPUp,
"PlaySpeedDown" => Key::PlaySpeedDown, "PlaySpeedDown" => NamedKey::PlaySpeedDown,
"PlaySpeedReset" => Key::PlaySpeedReset, "PlaySpeedReset" => NamedKey::PlaySpeedReset,
"PlaySpeedUp" => Key::PlaySpeedUp, "PlaySpeedUp" => NamedKey::PlaySpeedUp,
"RandomToggle" => Key::RandomToggle, "RandomToggle" => NamedKey::RandomToggle,
"RcLowBattery" => Key::RcLowBattery, "RcLowBattery" => NamedKey::RcLowBattery,
"RecordSpeedNext" => Key::RecordSpeedNext, "RecordSpeedNext" => NamedKey::RecordSpeedNext,
"RfBypass" => Key::RfBypass, "RfBypass" => NamedKey::RfBypass,
"ScanChannelsToggle" => Key::ScanChannelsToggle, "ScanChannelsToggle" => NamedKey::ScanChannelsToggle,
"ScreenModeNext" => Key::ScreenModeNext, "ScreenModeNext" => NamedKey::ScreenModeNext,
"Settings" => Key::Settings, "Settings" => NamedKey::Settings,
"SplitScreenToggle" => Key::SplitScreenToggle, "SplitScreenToggle" => NamedKey::SplitScreenToggle,
"STBInput" => Key::STBInput, "STBInput" => NamedKey::STBInput,
"STBPower" => Key::STBPower, "STBPower" => NamedKey::STBPower,
"Subtitle" => Key::Subtitle, "Subtitle" => NamedKey::Subtitle,
"Teletext" => Key::Teletext, "Teletext" => NamedKey::Teletext,
"VideoModeNext" => Key::VideoModeNext, "VideoModeNext" => NamedKey::VideoModeNext,
"Wink" => Key::Wink, "Wink" => NamedKey::Wink,
"ZoomToggle" => Key::ZoomToggle, "ZoomToggle" => NamedKey::ZoomToggle,
"F1" => Key::F1, "F1" => NamedKey::F1,
"F2" => Key::F2, "F2" => NamedKey::F2,
"F3" => Key::F3, "F3" => NamedKey::F3,
"F4" => Key::F4, "F4" => NamedKey::F4,
"F5" => Key::F5, "F5" => NamedKey::F5,
"F6" => Key::F6, "F6" => NamedKey::F6,
"F7" => Key::F7, "F7" => NamedKey::F7,
"F8" => Key::F8, "F8" => NamedKey::F8,
"F9" => Key::F9, "F9" => NamedKey::F9,
"F10" => Key::F10, "F10" => NamedKey::F10,
"F11" => Key::F11, "F11" => NamedKey::F11,
"F12" => Key::F12, "F12" => NamedKey::F12,
"F13" => Key::F13, "F13" => NamedKey::F13,
"F14" => Key::F14, "F14" => NamedKey::F14,
"F15" => Key::F15, "F15" => NamedKey::F15,
"F16" => Key::F16, "F16" => NamedKey::F16,
"F17" => Key::F17, "F17" => NamedKey::F17,
"F18" => Key::F18, "F18" => NamedKey::F18,
"F19" => Key::F19, "F19" => NamedKey::F19,
"F20" => Key::F20, "F20" => NamedKey::F20,
"F21" => Key::F21, "F21" => NamedKey::F21,
"F22" => Key::F22, "F22" => NamedKey::F22,
"F23" => Key::F23, "F23" => NamedKey::F23,
"F24" => Key::F24, "F24" => NamedKey::F24,
"F25" => Key::F25, "F25" => NamedKey::F25,
"F26" => Key::F26, "F26" => NamedKey::F26,
"F27" => Key::F27, "F27" => NamedKey::F27,
"F28" => Key::F28, "F28" => NamedKey::F28,
"F29" => Key::F29, "F29" => NamedKey::F29,
"F30" => Key::F30, "F30" => NamedKey::F30,
"F31" => Key::F31, "F31" => NamedKey::F31,
"F32" => Key::F32, "F32" => NamedKey::F32,
"F33" => Key::F33, "F33" => NamedKey::F33,
"F34" => Key::F34, "F34" => NamedKey::F34,
"F35" => Key::F35, "F35" => NamedKey::F35,
string => Key::Character(SmolStr::new(string)), string => return Key::Character(SmolStr::new(string)),
} })
} }
} }
impl KeyCode { impl PhysicalKey {
pub fn from_key_code_attribute_value(kcav: &str) -> Self { pub fn from_key_code_attribute_value(kcav: &str) -> Self {
match kcav { PhysicalKey::Code(match kcav {
"Backquote" => KeyCode::Backquote, "Backquote" => KeyCode::Backquote,
"Backslash" => KeyCode::Backslash, "Backslash" => KeyCode::Backslash,
"BracketLeft" => KeyCode::BracketLeft, "BracketLeft" => KeyCode::BracketLeft,
@ -516,7 +516,7 @@ impl KeyCode {
"F33" => KeyCode::F33, "F33" => KeyCode::F33,
"F34" => KeyCode::F34, "F34" => KeyCode::F34,
"F35" => KeyCode::F35, "F35" => KeyCode::F35,
_ => KeyCode::Unidentified(NativeKeyCode::Unidentified), _ => return PhysicalKey::Unidentified(NativeKeyCode::Unidentified),
} })
} }
} }

View file

@ -11,7 +11,7 @@ use web_sys::{
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
use crate::error::OsError as RootOE; use crate::error::OsError as RootOE;
use crate::event::{Force, InnerSizeWriter, MouseButton, MouseScrollDelta}; 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::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes};
use crate::window::{WindowAttributes, WindowId as RootWindowId}; use crate::window::{WindowAttributes, WindowId as RootWindowId};
@ -258,7 +258,7 @@ impl Canvas {
pub fn on_keyboard_release<F>(&mut self, mut handler: F, prevent_default: bool) pub fn on_keyboard_release<F>(&mut self, mut handler: F, prevent_default: bool)
where where
F: 'static + FnMut(KeyCode, Key, Option<SmolStr>, KeyLocation, bool, ModifiersState), F: 'static + FnMut(PhysicalKey, Key, Option<SmolStr>, KeyLocation, bool, ModifiersState),
{ {
self.on_keyboard_release = self.on_keyboard_release =
Some(self.common.add_event("keyup", move |event: KeyboardEvent| { Some(self.common.add_event("keyup", move |event: KeyboardEvent| {
@ -280,7 +280,7 @@ impl Canvas {
pub fn on_keyboard_press<F>(&mut self, mut handler: F, prevent_default: bool) pub fn on_keyboard_press<F>(&mut self, mut handler: F, prevent_default: bool)
where where
F: 'static + FnMut(KeyCode, Key, Option<SmolStr>, KeyLocation, bool, ModifiersState), F: 'static + FnMut(PhysicalKey, Key, Option<SmolStr>, KeyLocation, bool, ModifiersState),
{ {
self.on_keyboard_press = Some(self.common.add_transient_event( self.on_keyboard_press = Some(self.common.add_transient_event(
"keydown", "keydown",

View file

@ -1,6 +1,6 @@
use crate::dpi::LogicalPosition; use crate::dpi::LogicalPosition;
use crate::event::{MouseButton, MouseScrollDelta}; 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 once_cell::unsync::OnceCell;
use smol_str::SmolStr; 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(); let code = event.code();
KeyCode::from_key_code_attribute_value(&code) PhysicalKey::from_key_code_attribute_value(&code)
} }
pub fn key(event: &KeyboardEvent) -> Key { pub fn key(event: &KeyboardEvent) -> Key {
@ -163,9 +163,9 @@ pub fn key_text(event: &KeyboardEvent) -> Option<SmolStr> {
let key = Key::from_key_attribute_value(&key); let key = Key::from_key_attribute_value(&key);
match &key { match &key {
Key::Character(text) => Some(text.clone()), Key::Character(text) => Some(text.clone()),
Key::Tab => Some(SmolStr::new("\t")), Key::Named(NamedKey::Tab) => Some(SmolStr::new("\t")),
Key::Enter => Some(SmolStr::new("\r")), Key::Named(NamedKey::Enter) => Some(SmolStr::new("\r")),
Key::Space => Some(SmolStr::new(" ")), Key::Named(NamedKey::Space) => Some(SmolStr::new(" ")),
_ => None, _ => None,
} }
.map(SmolStr::new) .map(SmolStr::new)

View file

@ -80,8 +80,8 @@ use crate::{
WindowEvent, WindowEvent,
}, },
event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW},
keyboard::{KeyCode, ModifiersState}, keyboard::{KeyCode, ModifiersState, PhysicalKey},
platform::{pump_events::PumpStatus, scancode::KeyCodeExtScancode}, platform::{pump_events::PumpStatus, scancode::PhysicalKeyExtScancode},
platform_impl::platform::{ platform_impl::platform::{
dark_mode::try_theme, dark_mode::try_theme,
dpi::{become_dpi_aware, dpi_to_scale_factor}, dpi::{become_dpi_aware, dpi_to_scale_factor},
@ -2518,7 +2518,7 @@ unsafe fn handle_raw_input<T: 'static>(userdata: &ThreadMsgTargetData<T>, data:
// https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503 // https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
return; 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. // Historically, the NumLock and the Pause key were one and the same physical key.
// The user could trigger Pause by pressing Ctrl+NumLock. // The user could trigger Pause by pressing Ctrl+NumLock.
// Now these are often physically separate and the two keys can be differentiated by // Now these are often physically separate and the two keys can be differentiated by
@ -2531,47 +2531,49 @@ unsafe fn handle_raw_input<T: 'static>(userdata: &ThreadMsgTargetData<T>, data:
// For more on this, read the article by Raymond Chen, titled: // For more on this, read the article by Raymond Chen, titled:
// "Why does Ctrl+ScrollLock cancel dialogs?" // "Why does Ctrl+ScrollLock cancel dialogs?"
// https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503 // https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
KeyCode::NumLock PhysicalKey::Code(KeyCode::NumLock)
} else { } else {
KeyCode::from_scancode(scancode as u32) PhysicalKey::from_scancode(scancode as u32)
}; };
if keyboard.VKey == VK_SHIFT { if keyboard.VKey == VK_SHIFT {
match code { if let PhysicalKey::Code(code) = physical_key {
KeyCode::NumpadDecimal match code {
| KeyCode::Numpad0 KeyCode::NumpadDecimal
| KeyCode::Numpad1 | KeyCode::Numpad0
| KeyCode::Numpad2 | KeyCode::Numpad1
| KeyCode::Numpad3 | KeyCode::Numpad2
| KeyCode::Numpad4 | KeyCode::Numpad3
| KeyCode::Numpad5 | KeyCode::Numpad4
| KeyCode::Numpad6 | KeyCode::Numpad5
| KeyCode::Numpad7 | KeyCode::Numpad6
| KeyCode::Numpad8 | KeyCode::Numpad7
| KeyCode::Numpad9 => { | KeyCode::Numpad8
// On Windows, holding the Shift key makes numpad keys behave as if NumLock | KeyCode::Numpad9 => {
// wasn't active. The way this is exposed to applications by the system is that // On Windows, holding the Shift key makes numpad keys behave as if NumLock
// the application receives a fake key release event for the shift key at the // wasn't active. The way this is exposed to applications by the system is that
// moment when the numpad key is pressed, just before receiving the numpad key // the application receives a fake key release event for the shift key at the
// as well. // 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 // The issue is that in the raw device event (here), the fake shift release
// have any information to tell whether it's the left shift or the right shift // event reports the numpad key as the scancode. Unfortunately, the event doesn't
// that needs to get the fake release (or press) event so we don't forward this // have any information to tell whether it's the left shift or the right shift
// event to the application at all. // 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" // For more on this, read the article by Raymond Chen, titled:
// https://devblogs.microsoft.com/oldnewthing/20040906-00/?p=37953 // "The shift key overrides NumLock"
return; // https://devblogs.microsoft.com/oldnewthing/20040906-00/?p=37953
return;
}
_ => (),
} }
_ => (),
} }
} }
userdata.send_event(Event::DeviceEvent { userdata.send_event(Event::DeviceEvent {
device_id, device_id,
event: Key(RawKeyEvent { event: Key(RawKeyEvent {
physical_key: code, physical_key,
state, state,
}), }),
}); });

View file

@ -37,8 +37,8 @@ use unicode_segmentation::UnicodeSegmentation;
use crate::{ use crate::{
event::{ElementState, KeyEvent}, event::{ElementState, KeyEvent},
keyboard::{Key, KeyCode, KeyLocation, NativeKey, NativeKeyCode}, keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey},
platform::scancode::KeyCodeExtScancode, platform::scancode::PhysicalKeyExtScancode,
platform_impl::platform::{ platform_impl::platform::{
event_loop::ProcResult, event_loop::ProcResult,
keyboard_layout::{Layout, LayoutCache, WindowsModifiers, LAYOUT_CACHE}, keyboard_layout::{Layout, LayoutCache, WindowsModifiers, LAYOUT_CACHE},
@ -264,8 +264,8 @@ impl KeyEventBuilder {
let mod_no_ctrl = mod_state.remove_only_ctrl(); let mod_no_ctrl = mod_state.remove_only_ctrl();
let num_lock_on = kbd_state[VK_NUMLOCK as usize] & 1 != 0; let num_lock_on = kbd_state[VK_NUMLOCK as usize] & 1 != 0;
let vkey = event_info.vkey; let vkey = event_info.vkey;
let keycode = &event_info.code; let physical_key = &event_info.physical_key;
let key = layout.get_key(mod_no_ctrl, num_lock_on, vkey, keycode); 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)); event_info.text = PartialText::Text(key.to_text().map(SmolStr::new));
} }
let ev = event_info.finalize(); let ev = event_info.finalize();
@ -454,15 +454,16 @@ impl KeyEventBuilder {
return None; return None;
} }
let scancode = scancode as ExScancode; 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 { let mods = if caps_lock_on {
WindowsModifiers::CAPS_LOCK WindowsModifiers::CAPS_LOCK
} else { } else {
WindowsModifiers::empty() WindowsModifiers::empty()
}; };
let layout = layouts.layouts.get(&(locale_id as u64)).unwrap(); let layout = layouts.layouts.get(&(locale_id as u64)).unwrap();
let logical_key = layout.get_key(mods, num_lock_on, 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, &code); let key_without_modifiers =
layout.get_key(WindowsModifiers::empty(), false, vk, &physical_key);
let text = if key_state == ElementState::Pressed { let text = if key_state == ElementState::Pressed {
logical_key.to_text().map(SmolStr::new) logical_key.to_text().map(SmolStr::new)
} else { } else {
@ -474,7 +475,7 @@ impl KeyEventBuilder {
key_without_modifiers, key_without_modifiers,
key_state, key_state,
is_repeat: false, is_repeat: false,
code, physical_key,
location: get_location(scancode, locale_id), location: get_location(scancode, locale_id),
utf16parts: Vec::with_capacity(8), utf16parts: Vec::with_capacity(8),
text: PartialText::Text(text.clone()), text: PartialText::Text(text.clone()),
@ -511,7 +512,7 @@ struct PartialKeyEventInfo {
vkey: VIRTUAL_KEY, vkey: VIRTUAL_KEY,
key_state: ElementState, key_state: ElementState,
is_repeat: bool, is_repeat: bool,
code: KeyCode, physical_key: PhysicalKey,
location: KeyLocation, location: KeyLocation,
logical_key: PartialLogicalKey, logical_key: PartialLogicalKey,
@ -543,7 +544,7 @@ impl PartialKeyEventInfo {
} else { } else {
new_ex_scancode(lparam_struct.scancode, lparam_struct.extended) 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 location = get_location(scancode, layout.hkl as HKL);
let kbd_state = get_kbd_state(); let kbd_state = get_kbd_state();
@ -558,16 +559,17 @@ impl PartialKeyEventInfo {
// "Why does Ctrl+ScrollLock cancel dialogs?" // "Why does Ctrl+ScrollLock cancel dialogs?"
// https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503 // https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
let code_as_key = if mods.contains(WindowsModifiers::CONTROL) { let code_as_key = if mods.contains(WindowsModifiers::CONTROL) {
match code { match physical_key {
KeyCode::NumLock => Some(Key::NumLock), PhysicalKey::Code(KeyCode::NumLock) => Some(Key::Named(NamedKey::NumLock)),
KeyCode::Pause => Some(Key::Pause), PhysicalKey::Code(KeyCode::Pause) => Some(Key::Named(NamedKey::Pause)),
_ => None, _ => None,
} }
} else { } else {
None 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 key_is_char = matches!(preliminary_logical_key, Key::Character(_));
let is_pressed = state == ElementState::Pressed; let is_pressed = state == ElementState::Pressed;
@ -583,7 +585,7 @@ impl PartialKeyEventInfo {
let key_without_modifiers = if let Some(key) = code_as_key { let key_without_modifiers = if let Some(key) = code_as_key {
key key
} else { } 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. // We convert dead keys into their character.
// The reason for this is that `key_without_modifiers` is designed for key-bindings, // 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 // but the US International layout treats `'` (apostrophe) as a dead key and the
@ -609,7 +611,7 @@ impl PartialKeyEventInfo {
logical_key, logical_key,
key_without_modifiers, key_without_modifiers,
is_repeat: lparam_struct.is_repeat, is_repeat: lparam_struct.is_repeat,
code, physical_key,
location, location,
utf16parts: Vec::with_capacity(8), utf16parts: Vec::with_capacity(8),
text: PartialText::System(Vec::new()), text: PartialText::System(Vec::new()),
@ -656,7 +658,7 @@ impl PartialKeyEventInfo {
}; };
KeyEvent { KeyEvent {
physical_key: self.code, physical_key: self.physical_key,
logical_key, logical_key,
text, text,
location: self.location, 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 /// the next event is a right Alt (AltGr) event. If this is the case, the current event must be the
/// fake Ctrl event. /// fake Ctrl event.
fn is_current_fake(curr_info: &PartialKeyEventInfo, next_msg: MSG, layout: &Layout) -> bool { 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 { if layout.has_alt_graph {
let next_code = ex_scancode_from_lparam(next_msg.lParam); let next_code = ex_scancode_from_lparam(next_msg.lParam);
let next_is_altgr = next_code == 0xE038; // 0xE038 is right alt 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<u32> { fn to_scancode(self) -> Option<u32> {
// See `from_scancode` for more info // See `from_scancode` for more info
@ -946,7 +951,17 @@ impl KeyCodeExtScancode for KeyCode {
let primary_lang_id = primarylangid(loword(hkl as u32)); let primary_lang_id = primarylangid(loword(hkl as u32));
let is_korean = primary_lang_id as u32 == LANG_KOREAN; 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::Backquote => Some(0x0029),
KeyCode::Backslash => Some(0x002B), KeyCode::Backslash => Some(0x002B),
KeyCode::Backspace => Some(0x000E), KeyCode::Backspace => Some(0x000E),
@ -1106,17 +1121,16 @@ impl KeyCodeExtScancode for KeyCode {
KeyCode::AudioVolumeDown => Some(0xE02E), KeyCode::AudioVolumeDown => Some(0xE02E),
KeyCode::AudioVolumeMute => Some(0xE020), KeyCode::AudioVolumeMute => Some(0xE020),
KeyCode::AudioVolumeUp => Some(0xE030), KeyCode::AudioVolumeUp => Some(0xE030),
KeyCode::Unidentified(NativeKeyCode::Windows(scancode)) => Some(scancode as u32),
_ => None, _ => 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 // See: https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
// and: https://www.w3.org/TR/uievents-code/ // and: https://www.w3.org/TR/uievents-code/
// and: The widget/NativeKeyToDOMCodeName.h file in the firefox source // and: The widget/NativeKeyToDOMCodeName.h file in the firefox source
match scancode { PhysicalKey::Code(match scancode {
0x0029 => KeyCode::Backquote, 0x0029 => KeyCode::Backquote,
0x002B => KeyCode::Backslash, 0x002B => KeyCode::Backslash,
0x000E => KeyCode::Backspace, 0x000E => KeyCode::Backspace,
@ -1266,7 +1280,7 @@ impl KeyCodeExtScancode for KeyCode {
0xE02E => KeyCode::AudioVolumeDown, 0xE02E => KeyCode::AudioVolumeDown,
0xE020 => KeyCode::AudioVolumeMute, 0xE020 => KeyCode::AudioVolumeMute,
0xE030 => KeyCode::AudioVolumeUp, 0xE030 => KeyCode::AudioVolumeUp,
_ => KeyCode::Unidentified(NativeKeyCode::Windows(scancode as u16)), _ => return PhysicalKey::Unidentified(NativeKeyCode::Windows(scancode as u16)),
} })
} }
} }

View file

@ -52,8 +52,8 @@ use windows_sys::Win32::{
}; };
use crate::{ use crate::{
keyboard::{Key, KeyCode, ModifiersState, NativeKey}, keyboard::{Key, KeyCode, ModifiersState, NamedKey, NativeKey, PhysicalKey},
platform::scancode::KeyCodeExtScancode, platform::scancode::PhysicalKeyExtScancode,
platform_impl::{loword, primarylangid}, platform_impl::{loword, primarylangid},
}; };
@ -224,7 +224,7 @@ impl Layout {
mods: WindowsModifiers, mods: WindowsModifiers,
num_lock_on: bool, num_lock_on: bool,
vkey: VIRTUAL_KEY, vkey: VIRTUAL_KEY,
keycode: &KeyCode, physical_key: &PhysicalKey,
) -> Key { ) -> Key {
let native_code = NativeKey::Windows(vkey); let native_code = NativeKey::Windows(vkey);
@ -252,9 +252,11 @@ impl Layout {
} else if let Some(key) = self.numlock_off_keys.get(&vkey) { } else if let Some(key) = self.numlock_off_keys.get(&vkey) {
return key.clone(); return key.clone();
} }
if let Some(keys) = self.keys.get(&mods) { if let PhysicalKey::Code(code) = physical_key {
if let Some(key) = keys.get(keycode) { if let Some(keys) = self.keys.get(&mods) {
return key.clone(); if let Some(key) = keys.get(code) {
return key.clone();
}
} }
} }
Key::Unidentified(native_code) Key::Unidentified(native_code)
@ -334,7 +336,11 @@ impl LayoutCache {
if scancode == 0 { if scancode == 0 {
continue; 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) { if !is_numpad_specific(vk as VIRTUAL_KEY) && NUMPAD_KEYCODES.contains(&keycode) {
let native_code = NativeKey::Windows(vk as VIRTUAL_KEY); let native_code = NativeKey::Windows(vk as VIRTUAL_KEY);
let map_vkey = keycode_to_vkey(keycode, locale_id); 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 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 // 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 // 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 // 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); let mod_state = WindowsModifiers::from_bits_retain(mod_state);
if let Some(keys) = layout.keys.get_mut(&mod_state) { if let Some(keys) = layout.keys.get_mut(&mod_state) {
if let Some(key) = keys.get_mut(&KeyCode::AltRight) { 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::F33 => 0,
KeyCode::F34 => 0, KeyCode::F34 => 0,
KeyCode::F35 => 0, KeyCode::F35 => 0,
KeyCode::Unidentified(_) => 0,
_ => 0, _ => 0,
} }
} }
@ -769,56 +778,56 @@ fn vkey_to_non_char_key(
VK_MBUTTON => Key::Unidentified(NativeKey::Unidentified), // Mouse VK_MBUTTON => Key::Unidentified(NativeKey::Unidentified), // Mouse
VK_XBUTTON1 => Key::Unidentified(NativeKey::Unidentified), // Mouse VK_XBUTTON1 => Key::Unidentified(NativeKey::Unidentified), // Mouse
VK_XBUTTON2 => Key::Unidentified(NativeKey::Unidentified), // Mouse VK_XBUTTON2 => Key::Unidentified(NativeKey::Unidentified), // Mouse
VK_BACK => Key::Backspace, VK_BACK => Key::Named(NamedKey::Backspace),
VK_TAB => Key::Tab, VK_TAB => Key::Named(NamedKey::Tab),
VK_CLEAR => Key::Clear, VK_CLEAR => Key::Named(NamedKey::Clear),
VK_RETURN => Key::Enter, VK_RETURN => Key::Named(NamedKey::Enter),
VK_SHIFT => Key::Shift, VK_SHIFT => Key::Named(NamedKey::Shift),
VK_CONTROL => Key::Control, VK_CONTROL => Key::Named(NamedKey::Control),
VK_MENU => Key::Alt, VK_MENU => Key::Named(NamedKey::Alt),
VK_PAUSE => Key::Pause, VK_PAUSE => Key::Named(NamedKey::Pause),
VK_CAPITAL => Key::CapsLock, VK_CAPITAL => Key::Named(NamedKey::CapsLock),
//VK_HANGEUL => Key::HangulMode, // Deprecated in favour of VK_HANGUL //VK_HANGEUL => Key::Named(NamedKey::HangulMode), // Deprecated in favour of VK_HANGUL
// VK_HANGUL and VK_KANA are defined as the same constant, therefore // VK_HANGUL and VK_KANA are defined as the same constant, therefore
// we use appropriate conditions to differentate between them // we use appropriate conditions to differentate between them
VK_HANGUL if is_korean => Key::HangulMode, VK_HANGUL if is_korean => Key::Named(NamedKey::HangulMode),
VK_KANA if is_japanese => Key::KanaMode, VK_KANA if is_japanese => Key::Named(NamedKey::KanaMode),
VK_JUNJA => Key::JunjaMode, VK_JUNJA => Key::Named(NamedKey::JunjaMode),
VK_FINAL => Key::FinalMode, VK_FINAL => Key::Named(NamedKey::FinalMode),
// VK_HANJA and VK_KANJI are defined as the same constant, therefore // VK_HANJA and VK_KANJI are defined as the same constant, therefore
// we use appropriate conditions to differentate between them // we use appropriate conditions to differentate between them
VK_HANJA if is_korean => Key::HanjaMode, VK_HANJA if is_korean => Key::Named(NamedKey::HanjaMode),
VK_KANJI if is_japanese => Key::KanjiMode, VK_KANJI if is_japanese => Key::Named(NamedKey::KanjiMode),
VK_ESCAPE => Key::Escape, VK_ESCAPE => Key::Named(NamedKey::Escape),
VK_CONVERT => Key::Convert, VK_CONVERT => Key::Named(NamedKey::Convert),
VK_NONCONVERT => Key::NonConvert, VK_NONCONVERT => Key::Named(NamedKey::NonConvert),
VK_ACCEPT => Key::Accept, VK_ACCEPT => Key::Named(NamedKey::Accept),
VK_MODECHANGE => Key::ModeChange, VK_MODECHANGE => Key::Named(NamedKey::ModeChange),
VK_SPACE => Key::Space, VK_SPACE => Key::Named(NamedKey::Space),
VK_PRIOR => Key::PageUp, VK_PRIOR => Key::Named(NamedKey::PageUp),
VK_NEXT => Key::PageDown, VK_NEXT => Key::Named(NamedKey::PageDown),
VK_END => Key::End, VK_END => Key::Named(NamedKey::End),
VK_HOME => Key::Home, VK_HOME => Key::Named(NamedKey::Home),
VK_LEFT => Key::ArrowLeft, VK_LEFT => Key::Named(NamedKey::ArrowLeft),
VK_UP => Key::ArrowUp, VK_UP => Key::Named(NamedKey::ArrowUp),
VK_RIGHT => Key::ArrowRight, VK_RIGHT => Key::Named(NamedKey::ArrowRight),
VK_DOWN => Key::ArrowDown, VK_DOWN => Key::Named(NamedKey::ArrowDown),
VK_SELECT => Key::Select, VK_SELECT => Key::Named(NamedKey::Select),
VK_PRINT => Key::Print, VK_PRINT => Key::Named(NamedKey::Print),
VK_EXECUTE => Key::Execute, VK_EXECUTE => Key::Named(NamedKey::Execute),
VK_SNAPSHOT => Key::PrintScreen, VK_SNAPSHOT => Key::Named(NamedKey::PrintScreen),
VK_INSERT => Key::Insert, VK_INSERT => Key::Named(NamedKey::Insert),
VK_DELETE => Key::Delete, VK_DELETE => Key::Named(NamedKey::Delete),
VK_HELP => Key::Help, VK_HELP => Key::Named(NamedKey::Help),
VK_LWIN => Key::Super, VK_LWIN => Key::Named(NamedKey::Super),
VK_RWIN => Key::Super, VK_RWIN => Key::Named(NamedKey::Super),
VK_APPS => Key::ContextMenu, VK_APPS => Key::Named(NamedKey::ContextMenu),
VK_SLEEP => Key::Standby, VK_SLEEP => Key::Named(NamedKey::Standby),
// Numpad keys produce characters // Numpad keys produce characters
VK_NUMPAD0 => Key::Unidentified(native_code), VK_NUMPAD0 => Key::Unidentified(native_code),
@ -838,30 +847,30 @@ fn vkey_to_non_char_key(
VK_DECIMAL => Key::Unidentified(native_code), VK_DECIMAL => Key::Unidentified(native_code),
VK_DIVIDE => Key::Unidentified(native_code), VK_DIVIDE => Key::Unidentified(native_code),
VK_F1 => Key::F1, VK_F1 => Key::Named(NamedKey::F1),
VK_F2 => Key::F2, VK_F2 => Key::Named(NamedKey::F2),
VK_F3 => Key::F3, VK_F3 => Key::Named(NamedKey::F3),
VK_F4 => Key::F4, VK_F4 => Key::Named(NamedKey::F4),
VK_F5 => Key::F5, VK_F5 => Key::Named(NamedKey::F5),
VK_F6 => Key::F6, VK_F6 => Key::Named(NamedKey::F6),
VK_F7 => Key::F7, VK_F7 => Key::Named(NamedKey::F7),
VK_F8 => Key::F8, VK_F8 => Key::Named(NamedKey::F8),
VK_F9 => Key::F9, VK_F9 => Key::Named(NamedKey::F9),
VK_F10 => Key::F10, VK_F10 => Key::Named(NamedKey::F10),
VK_F11 => Key::F11, VK_F11 => Key::Named(NamedKey::F11),
VK_F12 => Key::F12, VK_F12 => Key::Named(NamedKey::F12),
VK_F13 => Key::F13, VK_F13 => Key::Named(NamedKey::F13),
VK_F14 => Key::F14, VK_F14 => Key::Named(NamedKey::F14),
VK_F15 => Key::F15, VK_F15 => Key::Named(NamedKey::F15),
VK_F16 => Key::F16, VK_F16 => Key::Named(NamedKey::F16),
VK_F17 => Key::F17, VK_F17 => Key::Named(NamedKey::F17),
VK_F18 => Key::F18, VK_F18 => Key::Named(NamedKey::F18),
VK_F19 => Key::F19, VK_F19 => Key::Named(NamedKey::F19),
VK_F20 => Key::F20, VK_F20 => Key::Named(NamedKey::F20),
VK_F21 => Key::F21, VK_F21 => Key::Named(NamedKey::F21),
VK_F22 => Key::F22, VK_F22 => Key::Named(NamedKey::F22),
VK_F23 => Key::F23, VK_F23 => Key::Named(NamedKey::F23),
VK_F24 => Key::F24, VK_F24 => Key::Named(NamedKey::F24),
VK_NAVIGATION_VIEW => Key::Unidentified(native_code), VK_NAVIGATION_VIEW => Key::Unidentified(native_code),
VK_NAVIGATION_MENU => Key::Unidentified(native_code), VK_NAVIGATION_MENU => Key::Unidentified(native_code),
VK_NAVIGATION_UP => 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_RIGHT => Key::Unidentified(native_code),
VK_NAVIGATION_ACCEPT => Key::Unidentified(native_code), VK_NAVIGATION_ACCEPT => Key::Unidentified(native_code),
VK_NAVIGATION_CANCEL => Key::Unidentified(native_code), VK_NAVIGATION_CANCEL => Key::Unidentified(native_code),
VK_NUMLOCK => Key::NumLock, VK_NUMLOCK => Key::Named(NamedKey::NumLock),
VK_SCROLL => Key::ScrollLock, VK_SCROLL => Key::Named(NamedKey::ScrollLock),
VK_OEM_NEC_EQUAL => Key::Unidentified(native_code), 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_JISHO => Key::Unidentified(native_code), // Conflicts with `VK_OEM_NEC_EQUAL`
VK_OEM_FJ_MASSHOU => Key::Unidentified(native_code), VK_OEM_FJ_MASSHOU => Key::Unidentified(native_code),
VK_OEM_FJ_TOUROKU => Key::Unidentified(native_code), VK_OEM_FJ_TOUROKU => Key::Unidentified(native_code),
VK_OEM_FJ_LOYA => Key::Unidentified(native_code), VK_OEM_FJ_LOYA => Key::Unidentified(native_code),
VK_OEM_FJ_ROYA => Key::Unidentified(native_code), VK_OEM_FJ_ROYA => Key::Unidentified(native_code),
VK_LSHIFT => Key::Shift, VK_LSHIFT => Key::Named(NamedKey::Shift),
VK_RSHIFT => Key::Shift, VK_RSHIFT => Key::Named(NamedKey::Shift),
VK_LCONTROL => Key::Control, VK_LCONTROL => Key::Named(NamedKey::Control),
VK_RCONTROL => Key::Control, VK_RCONTROL => Key::Named(NamedKey::Control),
VK_LMENU => Key::Alt, VK_LMENU => Key::Named(NamedKey::Alt),
VK_RMENU => { VK_RMENU => {
if has_alt_graph { if has_alt_graph {
Key::AltGraph Key::Named(NamedKey::AltGraph)
} else { } else {
Key::Alt Key::Named(NamedKey::Alt)
} }
} }
VK_BROWSER_BACK => Key::BrowserBack, VK_BROWSER_BACK => Key::Named(NamedKey::BrowserBack),
VK_BROWSER_FORWARD => Key::BrowserForward, VK_BROWSER_FORWARD => Key::Named(NamedKey::BrowserForward),
VK_BROWSER_REFRESH => Key::BrowserRefresh, VK_BROWSER_REFRESH => Key::Named(NamedKey::BrowserRefresh),
VK_BROWSER_STOP => Key::BrowserStop, VK_BROWSER_STOP => Key::Named(NamedKey::BrowserStop),
VK_BROWSER_SEARCH => Key::BrowserSearch, VK_BROWSER_SEARCH => Key::Named(NamedKey::BrowserSearch),
VK_BROWSER_FAVORITES => Key::BrowserFavorites, VK_BROWSER_FAVORITES => Key::Named(NamedKey::BrowserFavorites),
VK_BROWSER_HOME => Key::BrowserHome, VK_BROWSER_HOME => Key::Named(NamedKey::BrowserHome),
VK_VOLUME_MUTE => Key::AudioVolumeMute, VK_VOLUME_MUTE => Key::Named(NamedKey::AudioVolumeMute),
VK_VOLUME_DOWN => Key::AudioVolumeDown, VK_VOLUME_DOWN => Key::Named(NamedKey::AudioVolumeDown),
VK_VOLUME_UP => Key::AudioVolumeUp, VK_VOLUME_UP => Key::Named(NamedKey::AudioVolumeUp),
VK_MEDIA_NEXT_TRACK => Key::MediaTrackNext, VK_MEDIA_NEXT_TRACK => Key::Named(NamedKey::MediaTrackNext),
VK_MEDIA_PREV_TRACK => Key::MediaTrackPrevious, VK_MEDIA_PREV_TRACK => Key::Named(NamedKey::MediaTrackPrevious),
VK_MEDIA_STOP => Key::MediaStop, VK_MEDIA_STOP => Key::Named(NamedKey::MediaStop),
VK_MEDIA_PLAY_PAUSE => Key::MediaPlayPause, VK_MEDIA_PLAY_PAUSE => Key::Named(NamedKey::MediaPlayPause),
VK_LAUNCH_MAIL => Key::LaunchMail, VK_LAUNCH_MAIL => Key::Named(NamedKey::LaunchMail),
VK_LAUNCH_MEDIA_SELECT => Key::LaunchMediaPlayer, VK_LAUNCH_MEDIA_SELECT => Key::Named(NamedKey::LaunchMediaPlayer),
VK_LAUNCH_APP1 => Key::LaunchApplication1, VK_LAUNCH_APP1 => Key::Named(NamedKey::LaunchApplication1),
VK_LAUNCH_APP2 => Key::LaunchApplication2, VK_LAUNCH_APP2 => Key::Named(NamedKey::LaunchApplication2),
// This function only converts "non-printable" // This function only converts "non-printable"
VK_OEM_1 => Key::Unidentified(native_code), 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_HELP => Key::Unidentified(native_code),
VK_ICO_00 => 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_ICO_CLEAR => Key::Unidentified(native_code),
VK_PACKET => 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_WSCTRL => Key::Unidentified(native_code),
VK_OEM_CUSEL => 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 => { VK_OEM_FINISH => {
if is_japanese { if is_japanese {
Key::Katakana Key::Named(NamedKey::Katakana)
} else { } else {
// This matches IE and Firefox behaviour according to // This matches IE and Firefox behaviour according to
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values // 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/ // Finish is not mentionned at https://w3c.github.io/uievents-key/
// Also see: https://github.com/pyfisch/keyboard-types/issues/9 // Also see: https://github.com/pyfisch/keyboard-types/issues/9
Key::Unidentified(native_code) Key::Unidentified(native_code)
} }
} }
VK_OEM_COPY => Key::Copy, VK_OEM_COPY => Key::Named(NamedKey::Copy),
VK_OEM_AUTO => Key::Hankaku, VK_OEM_AUTO => Key::Named(NamedKey::Hankaku),
VK_OEM_ENLW => Key::Zenkaku, VK_OEM_ENLW => Key::Named(NamedKey::Zenkaku),
VK_OEM_BACKTAB => Key::Romaji, VK_OEM_BACKTAB => Key::Named(NamedKey::Romaji),
VK_ATTN => Key::KanaMode, VK_ATTN => Key::Named(NamedKey::KanaMode),
VK_CRSEL => Key::CrSel, VK_CRSEL => Key::Named(NamedKey::CrSel),
VK_EXSEL => Key::ExSel, VK_EXSEL => Key::Named(NamedKey::ExSel),
VK_EREOF => Key::EraseEof, VK_EREOF => Key::Named(NamedKey::EraseEof),
VK_PLAY => Key::Play, VK_PLAY => Key::Named(NamedKey::Play),
VK_ZOOM => Key::ZoomToggle, VK_ZOOM => Key::Named(NamedKey::ZoomToggle),
VK_NONAME => Key::Unidentified(native_code), VK_NONAME => Key::Unidentified(native_code),
VK_PA1 => 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), _ => Key::Unidentified(native_code),
} }
} }

View file

@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
use winit::{ use winit::{
dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}, dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize},
event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase}, event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase},
keyboard::{Key, KeyCode, KeyLocation, ModifiersState}, keyboard::{Key, KeyCode, KeyLocation, ModifiersState, NamedKey, PhysicalKey},
window::CursorIcon, window::CursorIcon,
}; };
@ -23,7 +23,9 @@ fn events_serde() {
needs_serde::<MouseButton>(); needs_serde::<MouseButton>();
needs_serde::<MouseScrollDelta>(); needs_serde::<MouseScrollDelta>();
needs_serde::<Key>(); needs_serde::<Key>();
needs_serde::<NamedKey>();
needs_serde::<KeyCode>(); needs_serde::<KeyCode>();
needs_serde::<PhysicalKey>();
needs_serde::<KeyLocation>(); needs_serde::<KeyLocation>();
needs_serde::<ModifiersState>(); needs_serde::<ModifiersState>();
} }