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:
parent
b9e1e96eaa
commit
acfeff5327
31 changed files with 1456 additions and 1277 deletions
|
|
@ -80,8 +80,8 @@ use crate::{
|
|||
WindowEvent,
|
||||
},
|
||||
event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW},
|
||||
keyboard::{KeyCode, ModifiersState},
|
||||
platform::{pump_events::PumpStatus, scancode::KeyCodeExtScancode},
|
||||
keyboard::{KeyCode, ModifiersState, PhysicalKey},
|
||||
platform::{pump_events::PumpStatus, scancode::PhysicalKeyExtScancode},
|
||||
platform_impl::platform::{
|
||||
dark_mode::try_theme,
|
||||
dpi::{become_dpi_aware, dpi_to_scale_factor},
|
||||
|
|
@ -2518,7 +2518,7 @@ unsafe fn handle_raw_input<T: 'static>(userdata: &ThreadMsgTargetData<T>, data:
|
|||
// https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
|
||||
return;
|
||||
}
|
||||
let code = if keyboard.VKey == VK_NUMLOCK {
|
||||
let physical_key = if keyboard.VKey == VK_NUMLOCK {
|
||||
// Historically, the NumLock and the Pause key were one and the same physical key.
|
||||
// The user could trigger Pause by pressing Ctrl+NumLock.
|
||||
// Now these are often physically separate and the two keys can be differentiated by
|
||||
|
|
@ -2531,47 +2531,49 @@ unsafe fn handle_raw_input<T: 'static>(userdata: &ThreadMsgTargetData<T>, data:
|
|||
// For more on this, read the article by Raymond Chen, titled:
|
||||
// "Why does Ctrl+ScrollLock cancel dialogs?"
|
||||
// https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
|
||||
KeyCode::NumLock
|
||||
PhysicalKey::Code(KeyCode::NumLock)
|
||||
} else {
|
||||
KeyCode::from_scancode(scancode as u32)
|
||||
PhysicalKey::from_scancode(scancode as u32)
|
||||
};
|
||||
if keyboard.VKey == VK_SHIFT {
|
||||
match code {
|
||||
KeyCode::NumpadDecimal
|
||||
| KeyCode::Numpad0
|
||||
| KeyCode::Numpad1
|
||||
| KeyCode::Numpad2
|
||||
| KeyCode::Numpad3
|
||||
| KeyCode::Numpad4
|
||||
| KeyCode::Numpad5
|
||||
| KeyCode::Numpad6
|
||||
| KeyCode::Numpad7
|
||||
| KeyCode::Numpad8
|
||||
| KeyCode::Numpad9 => {
|
||||
// On Windows, holding the Shift key makes numpad keys behave as if NumLock
|
||||
// wasn't active. The way this is exposed to applications by the system is that
|
||||
// the application receives a fake key release event for the shift key at the
|
||||
// moment when the numpad key is pressed, just before receiving the numpad key
|
||||
// as well.
|
||||
//
|
||||
// The issue is that in the raw device event (here), the fake shift release
|
||||
// event reports the numpad key as the scancode. Unfortunately, the event doesn't
|
||||
// have any information to tell whether it's the left shift or the right shift
|
||||
// that needs to get the fake release (or press) event so we don't forward this
|
||||
// event to the application at all.
|
||||
//
|
||||
// For more on this, read the article by Raymond Chen, titled:
|
||||
// "The shift key overrides NumLock"
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040906-00/?p=37953
|
||||
return;
|
||||
if let PhysicalKey::Code(code) = physical_key {
|
||||
match code {
|
||||
KeyCode::NumpadDecimal
|
||||
| KeyCode::Numpad0
|
||||
| KeyCode::Numpad1
|
||||
| KeyCode::Numpad2
|
||||
| KeyCode::Numpad3
|
||||
| KeyCode::Numpad4
|
||||
| KeyCode::Numpad5
|
||||
| KeyCode::Numpad6
|
||||
| KeyCode::Numpad7
|
||||
| KeyCode::Numpad8
|
||||
| KeyCode::Numpad9 => {
|
||||
// On Windows, holding the Shift key makes numpad keys behave as if NumLock
|
||||
// wasn't active. The way this is exposed to applications by the system is that
|
||||
// the application receives a fake key release event for the shift key at the
|
||||
// moment when the numpad key is pressed, just before receiving the numpad key
|
||||
// as well.
|
||||
//
|
||||
// The issue is that in the raw device event (here), the fake shift release
|
||||
// event reports the numpad key as the scancode. Unfortunately, the event doesn't
|
||||
// have any information to tell whether it's the left shift or the right shift
|
||||
// that needs to get the fake release (or press) event so we don't forward this
|
||||
// event to the application at all.
|
||||
//
|
||||
// For more on this, read the article by Raymond Chen, titled:
|
||||
// "The shift key overrides NumLock"
|
||||
// https://devblogs.microsoft.com/oldnewthing/20040906-00/?p=37953
|
||||
return;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
userdata.send_event(Event::DeviceEvent {
|
||||
device_id,
|
||||
event: Key(RawKeyEvent {
|
||||
physical_key: code,
|
||||
physical_key,
|
||||
state,
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ use unicode_segmentation::UnicodeSegmentation;
|
|||
|
||||
use crate::{
|
||||
event::{ElementState, KeyEvent},
|
||||
keyboard::{Key, KeyCode, KeyLocation, NativeKey, NativeKeyCode},
|
||||
platform::scancode::KeyCodeExtScancode,
|
||||
keyboard::{Key, KeyCode, KeyLocation, NamedKey, NativeKey, NativeKeyCode, PhysicalKey},
|
||||
platform::scancode::PhysicalKeyExtScancode,
|
||||
platform_impl::platform::{
|
||||
event_loop::ProcResult,
|
||||
keyboard_layout::{Layout, LayoutCache, WindowsModifiers, LAYOUT_CACHE},
|
||||
|
|
@ -264,8 +264,8 @@ impl KeyEventBuilder {
|
|||
let mod_no_ctrl = mod_state.remove_only_ctrl();
|
||||
let num_lock_on = kbd_state[VK_NUMLOCK as usize] & 1 != 0;
|
||||
let vkey = event_info.vkey;
|
||||
let keycode = &event_info.code;
|
||||
let key = layout.get_key(mod_no_ctrl, num_lock_on, vkey, keycode);
|
||||
let physical_key = &event_info.physical_key;
|
||||
let key = layout.get_key(mod_no_ctrl, num_lock_on, vkey, physical_key);
|
||||
event_info.text = PartialText::Text(key.to_text().map(SmolStr::new));
|
||||
}
|
||||
let ev = event_info.finalize();
|
||||
|
|
@ -454,15 +454,16 @@ impl KeyEventBuilder {
|
|||
return None;
|
||||
}
|
||||
let scancode = scancode as ExScancode;
|
||||
let code = KeyCode::from_scancode(scancode as u32);
|
||||
let physical_key = PhysicalKey::from_scancode(scancode as u32);
|
||||
let mods = if caps_lock_on {
|
||||
WindowsModifiers::CAPS_LOCK
|
||||
} else {
|
||||
WindowsModifiers::empty()
|
||||
};
|
||||
let layout = layouts.layouts.get(&(locale_id as u64)).unwrap();
|
||||
let logical_key = layout.get_key(mods, num_lock_on, vk, &code);
|
||||
let key_without_modifiers = layout.get_key(WindowsModifiers::empty(), false, vk, &code);
|
||||
let logical_key = layout.get_key(mods, num_lock_on, vk, &physical_key);
|
||||
let key_without_modifiers =
|
||||
layout.get_key(WindowsModifiers::empty(), false, vk, &physical_key);
|
||||
let text = if key_state == ElementState::Pressed {
|
||||
logical_key.to_text().map(SmolStr::new)
|
||||
} else {
|
||||
|
|
@ -474,7 +475,7 @@ impl KeyEventBuilder {
|
|||
key_without_modifiers,
|
||||
key_state,
|
||||
is_repeat: false,
|
||||
code,
|
||||
physical_key,
|
||||
location: get_location(scancode, locale_id),
|
||||
utf16parts: Vec::with_capacity(8),
|
||||
text: PartialText::Text(text.clone()),
|
||||
|
|
@ -511,7 +512,7 @@ struct PartialKeyEventInfo {
|
|||
vkey: VIRTUAL_KEY,
|
||||
key_state: ElementState,
|
||||
is_repeat: bool,
|
||||
code: KeyCode,
|
||||
physical_key: PhysicalKey,
|
||||
location: KeyLocation,
|
||||
logical_key: PartialLogicalKey,
|
||||
|
||||
|
|
@ -543,7 +544,7 @@ impl PartialKeyEventInfo {
|
|||
} else {
|
||||
new_ex_scancode(lparam_struct.scancode, lparam_struct.extended)
|
||||
};
|
||||
let code = KeyCode::from_scancode(scancode as u32);
|
||||
let physical_key = PhysicalKey::from_scancode(scancode as u32);
|
||||
let location = get_location(scancode, layout.hkl as HKL);
|
||||
|
||||
let kbd_state = get_kbd_state();
|
||||
|
|
@ -558,16 +559,17 @@ impl PartialKeyEventInfo {
|
|||
// "Why does Ctrl+ScrollLock cancel dialogs?"
|
||||
// https://devblogs.microsoft.com/oldnewthing/20080211-00/?p=23503
|
||||
let code_as_key = if mods.contains(WindowsModifiers::CONTROL) {
|
||||
match code {
|
||||
KeyCode::NumLock => Some(Key::NumLock),
|
||||
KeyCode::Pause => Some(Key::Pause),
|
||||
match physical_key {
|
||||
PhysicalKey::Code(KeyCode::NumLock) => Some(Key::Named(NamedKey::NumLock)),
|
||||
PhysicalKey::Code(KeyCode::Pause) => Some(Key::Named(NamedKey::Pause)),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let preliminary_logical_key = layout.get_key(mods_without_ctrl, num_lock_on, vkey, &code);
|
||||
let preliminary_logical_key =
|
||||
layout.get_key(mods_without_ctrl, num_lock_on, vkey, &physical_key);
|
||||
let key_is_char = matches!(preliminary_logical_key, Key::Character(_));
|
||||
let is_pressed = state == ElementState::Pressed;
|
||||
|
||||
|
|
@ -583,7 +585,7 @@ impl PartialKeyEventInfo {
|
|||
let key_without_modifiers = if let Some(key) = code_as_key {
|
||||
key
|
||||
} else {
|
||||
match layout.get_key(NO_MODS, false, vkey, &code) {
|
||||
match layout.get_key(NO_MODS, false, vkey, &physical_key) {
|
||||
// We convert dead keys into their character.
|
||||
// The reason for this is that `key_without_modifiers` is designed for key-bindings,
|
||||
// but the US International layout treats `'` (apostrophe) as a dead key and the
|
||||
|
|
@ -609,7 +611,7 @@ impl PartialKeyEventInfo {
|
|||
logical_key,
|
||||
key_without_modifiers,
|
||||
is_repeat: lparam_struct.is_repeat,
|
||||
code,
|
||||
physical_key,
|
||||
location,
|
||||
utf16parts: Vec::with_capacity(8),
|
||||
text: PartialText::System(Vec::new()),
|
||||
|
|
@ -656,7 +658,7 @@ impl PartialKeyEventInfo {
|
|||
};
|
||||
|
||||
KeyEvent {
|
||||
physical_key: self.code,
|
||||
physical_key: self.physical_key,
|
||||
logical_key,
|
||||
text,
|
||||
location: self.location,
|
||||
|
|
@ -740,7 +742,10 @@ fn get_async_kbd_state() -> [u8; 256] {
|
|||
/// the next event is a right Alt (AltGr) event. If this is the case, the current event must be the
|
||||
/// fake Ctrl event.
|
||||
fn is_current_fake(curr_info: &PartialKeyEventInfo, next_msg: MSG, layout: &Layout) -> bool {
|
||||
let curr_is_ctrl = matches!(curr_info.logical_key, PartialLogicalKey::This(Key::Control));
|
||||
let curr_is_ctrl = matches!(
|
||||
curr_info.logical_key,
|
||||
PartialLogicalKey::This(Key::Named(NamedKey::Control))
|
||||
);
|
||||
if layout.has_alt_graph {
|
||||
let next_code = ex_scancode_from_lparam(next_msg.lParam);
|
||||
let next_is_altgr = next_code == 0xE038; // 0xE038 is right alt
|
||||
|
|
@ -937,7 +942,7 @@ fn get_location(scancode: ExScancode, hkl: HKL) -> KeyLocation {
|
|||
}
|
||||
}
|
||||
|
||||
impl KeyCodeExtScancode for KeyCode {
|
||||
impl PhysicalKeyExtScancode for PhysicalKey {
|
||||
fn to_scancode(self) -> Option<u32> {
|
||||
// See `from_scancode` for more info
|
||||
|
||||
|
|
@ -946,7 +951,17 @@ impl KeyCodeExtScancode for KeyCode {
|
|||
let primary_lang_id = primarylangid(loword(hkl as u32));
|
||||
let is_korean = primary_lang_id as u32 == LANG_KOREAN;
|
||||
|
||||
match self {
|
||||
let code = match self {
|
||||
PhysicalKey::Code(code) => code,
|
||||
PhysicalKey::Unidentified(code) => {
|
||||
return match code {
|
||||
NativeKeyCode::Windows(scancode) => Some(scancode as u32),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
match code {
|
||||
KeyCode::Backquote => Some(0x0029),
|
||||
KeyCode::Backslash => Some(0x002B),
|
||||
KeyCode::Backspace => Some(0x000E),
|
||||
|
|
@ -1106,17 +1121,16 @@ impl KeyCodeExtScancode for KeyCode {
|
|||
KeyCode::AudioVolumeDown => Some(0xE02E),
|
||||
KeyCode::AudioVolumeMute => Some(0xE020),
|
||||
KeyCode::AudioVolumeUp => Some(0xE030),
|
||||
KeyCode::Unidentified(NativeKeyCode::Windows(scancode)) => Some(scancode as u32),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_scancode(scancode: u32) -> KeyCode {
|
||||
fn from_scancode(scancode: u32) -> PhysicalKey {
|
||||
// See: https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
|
||||
// and: https://www.w3.org/TR/uievents-code/
|
||||
// and: The widget/NativeKeyToDOMCodeName.h file in the firefox source
|
||||
|
||||
match scancode {
|
||||
PhysicalKey::Code(match scancode {
|
||||
0x0029 => KeyCode::Backquote,
|
||||
0x002B => KeyCode::Backslash,
|
||||
0x000E => KeyCode::Backspace,
|
||||
|
|
@ -1266,7 +1280,7 @@ impl KeyCodeExtScancode for KeyCode {
|
|||
0xE02E => KeyCode::AudioVolumeDown,
|
||||
0xE020 => KeyCode::AudioVolumeMute,
|
||||
0xE030 => KeyCode::AudioVolumeUp,
|
||||
_ => KeyCode::Unidentified(NativeKeyCode::Windows(scancode as u16)),
|
||||
}
|
||||
_ => return PhysicalKey::Unidentified(NativeKeyCode::Windows(scancode as u16)),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ use windows_sys::Win32::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
keyboard::{Key, KeyCode, ModifiersState, NativeKey},
|
||||
platform::scancode::KeyCodeExtScancode,
|
||||
keyboard::{Key, KeyCode, ModifiersState, NamedKey, NativeKey, PhysicalKey},
|
||||
platform::scancode::PhysicalKeyExtScancode,
|
||||
platform_impl::{loword, primarylangid},
|
||||
};
|
||||
|
||||
|
|
@ -224,7 +224,7 @@ impl Layout {
|
|||
mods: WindowsModifiers,
|
||||
num_lock_on: bool,
|
||||
vkey: VIRTUAL_KEY,
|
||||
keycode: &KeyCode,
|
||||
physical_key: &PhysicalKey,
|
||||
) -> Key {
|
||||
let native_code = NativeKey::Windows(vkey);
|
||||
|
||||
|
|
@ -252,9 +252,11 @@ impl Layout {
|
|||
} else if let Some(key) = self.numlock_off_keys.get(&vkey) {
|
||||
return key.clone();
|
||||
}
|
||||
if let Some(keys) = self.keys.get(&mods) {
|
||||
if let Some(key) = keys.get(keycode) {
|
||||
return key.clone();
|
||||
if let PhysicalKey::Code(code) = physical_key {
|
||||
if let Some(keys) = self.keys.get(&mods) {
|
||||
if let Some(key) = keys.get(code) {
|
||||
return key.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
Key::Unidentified(native_code)
|
||||
|
|
@ -334,7 +336,11 @@ impl LayoutCache {
|
|||
if scancode == 0 {
|
||||
continue;
|
||||
}
|
||||
let keycode = KeyCode::from_scancode(scancode);
|
||||
let keycode = match PhysicalKey::from_scancode(scancode) {
|
||||
PhysicalKey::Code(code) => code,
|
||||
// TODO: validate that we can skip on unidentified keys (probably never occurs?)
|
||||
_ => continue,
|
||||
};
|
||||
if !is_numpad_specific(vk as VIRTUAL_KEY) && NUMPAD_KEYCODES.contains(&keycode) {
|
||||
let native_code = NativeKey::Windows(vk as VIRTUAL_KEY);
|
||||
let map_vkey = keycode_to_vkey(keycode, locale_id);
|
||||
|
|
@ -382,7 +388,11 @@ impl LayoutCache {
|
|||
}
|
||||
|
||||
let native_code = NativeKey::Windows(vk as VIRTUAL_KEY);
|
||||
let key_code = KeyCode::from_scancode(scancode);
|
||||
let key_code = match PhysicalKey::from_scancode(scancode) {
|
||||
PhysicalKey::Code(code) => code,
|
||||
// TODO: validate that we can skip on unidentified keys (probably never occurs?)
|
||||
_ => continue,
|
||||
};
|
||||
// Let's try to get the key from just the scancode and vk
|
||||
// We don't necessarily know yet if AltGraph is present on this layout so we'll
|
||||
// assume it isn't. Then we'll do a second pass where we set the "AltRight" keys to
|
||||
|
|
@ -446,7 +456,7 @@ impl LayoutCache {
|
|||
let mod_state = WindowsModifiers::from_bits_retain(mod_state);
|
||||
if let Some(keys) = layout.keys.get_mut(&mod_state) {
|
||||
if let Some(key) = keys.get_mut(&KeyCode::AltRight) {
|
||||
*key = Key::AltGraph;
|
||||
*key = Key::Named(NamedKey::AltGraph);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -733,7 +743,6 @@ fn keycode_to_vkey(keycode: KeyCode, hkl: u64) -> VIRTUAL_KEY {
|
|||
KeyCode::F33 => 0,
|
||||
KeyCode::F34 => 0,
|
||||
KeyCode::F35 => 0,
|
||||
KeyCode::Unidentified(_) => 0,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
|
|
@ -769,56 +778,56 @@ fn vkey_to_non_char_key(
|
|||
VK_MBUTTON => Key::Unidentified(NativeKey::Unidentified), // Mouse
|
||||
VK_XBUTTON1 => Key::Unidentified(NativeKey::Unidentified), // Mouse
|
||||
VK_XBUTTON2 => Key::Unidentified(NativeKey::Unidentified), // Mouse
|
||||
VK_BACK => Key::Backspace,
|
||||
VK_TAB => Key::Tab,
|
||||
VK_CLEAR => Key::Clear,
|
||||
VK_RETURN => Key::Enter,
|
||||
VK_SHIFT => Key::Shift,
|
||||
VK_CONTROL => Key::Control,
|
||||
VK_MENU => Key::Alt,
|
||||
VK_PAUSE => Key::Pause,
|
||||
VK_CAPITAL => Key::CapsLock,
|
||||
VK_BACK => Key::Named(NamedKey::Backspace),
|
||||
VK_TAB => Key::Named(NamedKey::Tab),
|
||||
VK_CLEAR => Key::Named(NamedKey::Clear),
|
||||
VK_RETURN => Key::Named(NamedKey::Enter),
|
||||
VK_SHIFT => Key::Named(NamedKey::Shift),
|
||||
VK_CONTROL => Key::Named(NamedKey::Control),
|
||||
VK_MENU => Key::Named(NamedKey::Alt),
|
||||
VK_PAUSE => Key::Named(NamedKey::Pause),
|
||||
VK_CAPITAL => Key::Named(NamedKey::CapsLock),
|
||||
|
||||
//VK_HANGEUL => Key::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
|
||||
// we use appropriate conditions to differentate between them
|
||||
VK_HANGUL if is_korean => Key::HangulMode,
|
||||
VK_KANA if is_japanese => Key::KanaMode,
|
||||
VK_HANGUL if is_korean => Key::Named(NamedKey::HangulMode),
|
||||
VK_KANA if is_japanese => Key::Named(NamedKey::KanaMode),
|
||||
|
||||
VK_JUNJA => Key::JunjaMode,
|
||||
VK_FINAL => Key::FinalMode,
|
||||
VK_JUNJA => Key::Named(NamedKey::JunjaMode),
|
||||
VK_FINAL => Key::Named(NamedKey::FinalMode),
|
||||
|
||||
// VK_HANJA and VK_KANJI are defined as the same constant, therefore
|
||||
// we use appropriate conditions to differentate between them
|
||||
VK_HANJA if is_korean => Key::HanjaMode,
|
||||
VK_KANJI if is_japanese => Key::KanjiMode,
|
||||
VK_HANJA if is_korean => Key::Named(NamedKey::HanjaMode),
|
||||
VK_KANJI if is_japanese => Key::Named(NamedKey::KanjiMode),
|
||||
|
||||
VK_ESCAPE => Key::Escape,
|
||||
VK_CONVERT => Key::Convert,
|
||||
VK_NONCONVERT => Key::NonConvert,
|
||||
VK_ACCEPT => Key::Accept,
|
||||
VK_MODECHANGE => Key::ModeChange,
|
||||
VK_SPACE => Key::Space,
|
||||
VK_PRIOR => Key::PageUp,
|
||||
VK_NEXT => Key::PageDown,
|
||||
VK_END => Key::End,
|
||||
VK_HOME => Key::Home,
|
||||
VK_LEFT => Key::ArrowLeft,
|
||||
VK_UP => Key::ArrowUp,
|
||||
VK_RIGHT => Key::ArrowRight,
|
||||
VK_DOWN => Key::ArrowDown,
|
||||
VK_SELECT => Key::Select,
|
||||
VK_PRINT => Key::Print,
|
||||
VK_EXECUTE => Key::Execute,
|
||||
VK_SNAPSHOT => Key::PrintScreen,
|
||||
VK_INSERT => Key::Insert,
|
||||
VK_DELETE => Key::Delete,
|
||||
VK_HELP => Key::Help,
|
||||
VK_LWIN => Key::Super,
|
||||
VK_RWIN => Key::Super,
|
||||
VK_APPS => Key::ContextMenu,
|
||||
VK_SLEEP => Key::Standby,
|
||||
VK_ESCAPE => Key::Named(NamedKey::Escape),
|
||||
VK_CONVERT => Key::Named(NamedKey::Convert),
|
||||
VK_NONCONVERT => Key::Named(NamedKey::NonConvert),
|
||||
VK_ACCEPT => Key::Named(NamedKey::Accept),
|
||||
VK_MODECHANGE => Key::Named(NamedKey::ModeChange),
|
||||
VK_SPACE => Key::Named(NamedKey::Space),
|
||||
VK_PRIOR => Key::Named(NamedKey::PageUp),
|
||||
VK_NEXT => Key::Named(NamedKey::PageDown),
|
||||
VK_END => Key::Named(NamedKey::End),
|
||||
VK_HOME => Key::Named(NamedKey::Home),
|
||||
VK_LEFT => Key::Named(NamedKey::ArrowLeft),
|
||||
VK_UP => Key::Named(NamedKey::ArrowUp),
|
||||
VK_RIGHT => Key::Named(NamedKey::ArrowRight),
|
||||
VK_DOWN => Key::Named(NamedKey::ArrowDown),
|
||||
VK_SELECT => Key::Named(NamedKey::Select),
|
||||
VK_PRINT => Key::Named(NamedKey::Print),
|
||||
VK_EXECUTE => Key::Named(NamedKey::Execute),
|
||||
VK_SNAPSHOT => Key::Named(NamedKey::PrintScreen),
|
||||
VK_INSERT => Key::Named(NamedKey::Insert),
|
||||
VK_DELETE => Key::Named(NamedKey::Delete),
|
||||
VK_HELP => Key::Named(NamedKey::Help),
|
||||
VK_LWIN => Key::Named(NamedKey::Super),
|
||||
VK_RWIN => Key::Named(NamedKey::Super),
|
||||
VK_APPS => Key::Named(NamedKey::ContextMenu),
|
||||
VK_SLEEP => Key::Named(NamedKey::Standby),
|
||||
|
||||
// Numpad keys produce characters
|
||||
VK_NUMPAD0 => Key::Unidentified(native_code),
|
||||
|
|
@ -838,30 +847,30 @@ fn vkey_to_non_char_key(
|
|||
VK_DECIMAL => Key::Unidentified(native_code),
|
||||
VK_DIVIDE => Key::Unidentified(native_code),
|
||||
|
||||
VK_F1 => Key::F1,
|
||||
VK_F2 => Key::F2,
|
||||
VK_F3 => Key::F3,
|
||||
VK_F4 => Key::F4,
|
||||
VK_F5 => Key::F5,
|
||||
VK_F6 => Key::F6,
|
||||
VK_F7 => Key::F7,
|
||||
VK_F8 => Key::F8,
|
||||
VK_F9 => Key::F9,
|
||||
VK_F10 => Key::F10,
|
||||
VK_F11 => Key::F11,
|
||||
VK_F12 => Key::F12,
|
||||
VK_F13 => Key::F13,
|
||||
VK_F14 => Key::F14,
|
||||
VK_F15 => Key::F15,
|
||||
VK_F16 => Key::F16,
|
||||
VK_F17 => Key::F17,
|
||||
VK_F18 => Key::F18,
|
||||
VK_F19 => Key::F19,
|
||||
VK_F20 => Key::F20,
|
||||
VK_F21 => Key::F21,
|
||||
VK_F22 => Key::F22,
|
||||
VK_F23 => Key::F23,
|
||||
VK_F24 => Key::F24,
|
||||
VK_F1 => Key::Named(NamedKey::F1),
|
||||
VK_F2 => Key::Named(NamedKey::F2),
|
||||
VK_F3 => Key::Named(NamedKey::F3),
|
||||
VK_F4 => Key::Named(NamedKey::F4),
|
||||
VK_F5 => Key::Named(NamedKey::F5),
|
||||
VK_F6 => Key::Named(NamedKey::F6),
|
||||
VK_F7 => Key::Named(NamedKey::F7),
|
||||
VK_F8 => Key::Named(NamedKey::F8),
|
||||
VK_F9 => Key::Named(NamedKey::F9),
|
||||
VK_F10 => Key::Named(NamedKey::F10),
|
||||
VK_F11 => Key::Named(NamedKey::F11),
|
||||
VK_F12 => Key::Named(NamedKey::F12),
|
||||
VK_F13 => Key::Named(NamedKey::F13),
|
||||
VK_F14 => Key::Named(NamedKey::F14),
|
||||
VK_F15 => Key::Named(NamedKey::F15),
|
||||
VK_F16 => Key::Named(NamedKey::F16),
|
||||
VK_F17 => Key::Named(NamedKey::F17),
|
||||
VK_F18 => Key::Named(NamedKey::F18),
|
||||
VK_F19 => Key::Named(NamedKey::F19),
|
||||
VK_F20 => Key::Named(NamedKey::F20),
|
||||
VK_F21 => Key::Named(NamedKey::F21),
|
||||
VK_F22 => Key::Named(NamedKey::F22),
|
||||
VK_F23 => Key::Named(NamedKey::F23),
|
||||
VK_F24 => Key::Named(NamedKey::F24),
|
||||
VK_NAVIGATION_VIEW => Key::Unidentified(native_code),
|
||||
VK_NAVIGATION_MENU => Key::Unidentified(native_code),
|
||||
VK_NAVIGATION_UP => Key::Unidentified(native_code),
|
||||
|
|
@ -870,44 +879,44 @@ fn vkey_to_non_char_key(
|
|||
VK_NAVIGATION_RIGHT => Key::Unidentified(native_code),
|
||||
VK_NAVIGATION_ACCEPT => Key::Unidentified(native_code),
|
||||
VK_NAVIGATION_CANCEL => Key::Unidentified(native_code),
|
||||
VK_NUMLOCK => Key::NumLock,
|
||||
VK_SCROLL => Key::ScrollLock,
|
||||
VK_NUMLOCK => Key::Named(NamedKey::NumLock),
|
||||
VK_SCROLL => Key::Named(NamedKey::ScrollLock),
|
||||
VK_OEM_NEC_EQUAL => Key::Unidentified(native_code),
|
||||
//VK_OEM_FJ_JISHO => Key::Unidentified(native_code), // Conflicts with `VK_OEM_NEC_EQUAL`
|
||||
VK_OEM_FJ_MASSHOU => Key::Unidentified(native_code),
|
||||
VK_OEM_FJ_TOUROKU => Key::Unidentified(native_code),
|
||||
VK_OEM_FJ_LOYA => Key::Unidentified(native_code),
|
||||
VK_OEM_FJ_ROYA => Key::Unidentified(native_code),
|
||||
VK_LSHIFT => Key::Shift,
|
||||
VK_RSHIFT => Key::Shift,
|
||||
VK_LCONTROL => Key::Control,
|
||||
VK_RCONTROL => Key::Control,
|
||||
VK_LMENU => Key::Alt,
|
||||
VK_LSHIFT => Key::Named(NamedKey::Shift),
|
||||
VK_RSHIFT => Key::Named(NamedKey::Shift),
|
||||
VK_LCONTROL => Key::Named(NamedKey::Control),
|
||||
VK_RCONTROL => Key::Named(NamedKey::Control),
|
||||
VK_LMENU => Key::Named(NamedKey::Alt),
|
||||
VK_RMENU => {
|
||||
if has_alt_graph {
|
||||
Key::AltGraph
|
||||
Key::Named(NamedKey::AltGraph)
|
||||
} else {
|
||||
Key::Alt
|
||||
Key::Named(NamedKey::Alt)
|
||||
}
|
||||
}
|
||||
VK_BROWSER_BACK => Key::BrowserBack,
|
||||
VK_BROWSER_FORWARD => Key::BrowserForward,
|
||||
VK_BROWSER_REFRESH => Key::BrowserRefresh,
|
||||
VK_BROWSER_STOP => Key::BrowserStop,
|
||||
VK_BROWSER_SEARCH => Key::BrowserSearch,
|
||||
VK_BROWSER_FAVORITES => Key::BrowserFavorites,
|
||||
VK_BROWSER_HOME => Key::BrowserHome,
|
||||
VK_VOLUME_MUTE => Key::AudioVolumeMute,
|
||||
VK_VOLUME_DOWN => Key::AudioVolumeDown,
|
||||
VK_VOLUME_UP => Key::AudioVolumeUp,
|
||||
VK_MEDIA_NEXT_TRACK => Key::MediaTrackNext,
|
||||
VK_MEDIA_PREV_TRACK => Key::MediaTrackPrevious,
|
||||
VK_MEDIA_STOP => Key::MediaStop,
|
||||
VK_MEDIA_PLAY_PAUSE => Key::MediaPlayPause,
|
||||
VK_LAUNCH_MAIL => Key::LaunchMail,
|
||||
VK_LAUNCH_MEDIA_SELECT => Key::LaunchMediaPlayer,
|
||||
VK_LAUNCH_APP1 => Key::LaunchApplication1,
|
||||
VK_LAUNCH_APP2 => Key::LaunchApplication2,
|
||||
VK_BROWSER_BACK => Key::Named(NamedKey::BrowserBack),
|
||||
VK_BROWSER_FORWARD => Key::Named(NamedKey::BrowserForward),
|
||||
VK_BROWSER_REFRESH => Key::Named(NamedKey::BrowserRefresh),
|
||||
VK_BROWSER_STOP => Key::Named(NamedKey::BrowserStop),
|
||||
VK_BROWSER_SEARCH => Key::Named(NamedKey::BrowserSearch),
|
||||
VK_BROWSER_FAVORITES => Key::Named(NamedKey::BrowserFavorites),
|
||||
VK_BROWSER_HOME => Key::Named(NamedKey::BrowserHome),
|
||||
VK_VOLUME_MUTE => Key::Named(NamedKey::AudioVolumeMute),
|
||||
VK_VOLUME_DOWN => Key::Named(NamedKey::AudioVolumeDown),
|
||||
VK_VOLUME_UP => Key::Named(NamedKey::AudioVolumeUp),
|
||||
VK_MEDIA_NEXT_TRACK => Key::Named(NamedKey::MediaTrackNext),
|
||||
VK_MEDIA_PREV_TRACK => Key::Named(NamedKey::MediaTrackPrevious),
|
||||
VK_MEDIA_STOP => Key::Named(NamedKey::MediaStop),
|
||||
VK_MEDIA_PLAY_PAUSE => Key::Named(NamedKey::MediaPlayPause),
|
||||
VK_LAUNCH_MAIL => Key::Named(NamedKey::LaunchMail),
|
||||
VK_LAUNCH_MEDIA_SELECT => Key::Named(NamedKey::LaunchMediaPlayer),
|
||||
VK_LAUNCH_APP1 => Key::Named(NamedKey::LaunchApplication1),
|
||||
VK_LAUNCH_APP2 => Key::Named(NamedKey::LaunchApplication2),
|
||||
|
||||
// This function only converts "non-printable"
|
||||
VK_OEM_1 => Key::Unidentified(native_code),
|
||||
|
|
@ -955,7 +964,7 @@ fn vkey_to_non_char_key(
|
|||
VK_ICO_HELP => Key::Unidentified(native_code),
|
||||
VK_ICO_00 => Key::Unidentified(native_code),
|
||||
|
||||
VK_PROCESSKEY => Key::Process,
|
||||
VK_PROCESSKEY => Key::Named(NamedKey::Process),
|
||||
|
||||
VK_ICO_CLEAR => Key::Unidentified(native_code),
|
||||
VK_PACKET => Key::Unidentified(native_code),
|
||||
|
|
@ -967,32 +976,32 @@ fn vkey_to_non_char_key(
|
|||
VK_OEM_WSCTRL => Key::Unidentified(native_code),
|
||||
VK_OEM_CUSEL => Key::Unidentified(native_code),
|
||||
|
||||
VK_OEM_ATTN => Key::Attn,
|
||||
VK_OEM_ATTN => Key::Named(NamedKey::Attn),
|
||||
VK_OEM_FINISH => {
|
||||
if is_japanese {
|
||||
Key::Katakana
|
||||
Key::Named(NamedKey::Katakana)
|
||||
} else {
|
||||
// This matches IE and Firefox behaviour according to
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values
|
||||
// At the time of writing, there is no `Key::Finish` variant as
|
||||
// At the time of writing, there is no `NamedKey::Finish` variant as
|
||||
// Finish is not mentionned at https://w3c.github.io/uievents-key/
|
||||
// Also see: https://github.com/pyfisch/keyboard-types/issues/9
|
||||
Key::Unidentified(native_code)
|
||||
}
|
||||
}
|
||||
VK_OEM_COPY => Key::Copy,
|
||||
VK_OEM_AUTO => Key::Hankaku,
|
||||
VK_OEM_ENLW => Key::Zenkaku,
|
||||
VK_OEM_BACKTAB => Key::Romaji,
|
||||
VK_ATTN => Key::KanaMode,
|
||||
VK_CRSEL => Key::CrSel,
|
||||
VK_EXSEL => Key::ExSel,
|
||||
VK_EREOF => Key::EraseEof,
|
||||
VK_PLAY => Key::Play,
|
||||
VK_ZOOM => Key::ZoomToggle,
|
||||
VK_OEM_COPY => Key::Named(NamedKey::Copy),
|
||||
VK_OEM_AUTO => Key::Named(NamedKey::Hankaku),
|
||||
VK_OEM_ENLW => Key::Named(NamedKey::Zenkaku),
|
||||
VK_OEM_BACKTAB => Key::Named(NamedKey::Romaji),
|
||||
VK_ATTN => Key::Named(NamedKey::KanaMode),
|
||||
VK_CRSEL => Key::Named(NamedKey::CrSel),
|
||||
VK_EXSEL => Key::Named(NamedKey::ExSel),
|
||||
VK_EREOF => Key::Named(NamedKey::EraseEof),
|
||||
VK_PLAY => Key::Named(NamedKey::Play),
|
||||
VK_ZOOM => Key::Named(NamedKey::ZoomToggle),
|
||||
VK_NONAME => Key::Unidentified(native_code),
|
||||
VK_PA1 => Key::Unidentified(native_code),
|
||||
VK_OEM_CLEAR => Key::Clear,
|
||||
VK_OEM_CLEAR => Key::Named(NamedKey::Clear),
|
||||
_ => Key::Unidentified(native_code),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue