mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-03-29 22:56:45 +08:00
410 lines
12 KiB
Rust
410 lines
12 KiB
Rust
use serde::{Deserialize, Serialize};
|
|
use typeshare::typeshare;
|
|
|
|
/// Shared canonical keyboard key identifiers used across frontend and backend.
|
|
///
|
|
/// The enum names intentionally mirror `KeyboardEvent.code` style values so the
|
|
/// browser, virtual keyboard, and HID backend can all speak the same language.
|
|
#[typeshare]
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
|
pub enum CanonicalKey {
|
|
KeyA,
|
|
KeyB,
|
|
KeyC,
|
|
KeyD,
|
|
KeyE,
|
|
KeyF,
|
|
KeyG,
|
|
KeyH,
|
|
KeyI,
|
|
KeyJ,
|
|
KeyK,
|
|
KeyL,
|
|
KeyM,
|
|
KeyN,
|
|
KeyO,
|
|
KeyP,
|
|
KeyQ,
|
|
KeyR,
|
|
KeyS,
|
|
KeyT,
|
|
KeyU,
|
|
KeyV,
|
|
KeyW,
|
|
KeyX,
|
|
KeyY,
|
|
KeyZ,
|
|
Digit1,
|
|
Digit2,
|
|
Digit3,
|
|
Digit4,
|
|
Digit5,
|
|
Digit6,
|
|
Digit7,
|
|
Digit8,
|
|
Digit9,
|
|
Digit0,
|
|
Enter,
|
|
Escape,
|
|
Backspace,
|
|
Tab,
|
|
Space,
|
|
Minus,
|
|
Equal,
|
|
BracketLeft,
|
|
BracketRight,
|
|
Backslash,
|
|
Semicolon,
|
|
Quote,
|
|
Backquote,
|
|
Comma,
|
|
Period,
|
|
Slash,
|
|
CapsLock,
|
|
F1,
|
|
F2,
|
|
F3,
|
|
F4,
|
|
F5,
|
|
F6,
|
|
F7,
|
|
F8,
|
|
F9,
|
|
F10,
|
|
F11,
|
|
F12,
|
|
PrintScreen,
|
|
ScrollLock,
|
|
Pause,
|
|
Insert,
|
|
Home,
|
|
PageUp,
|
|
Delete,
|
|
End,
|
|
PageDown,
|
|
ArrowRight,
|
|
ArrowLeft,
|
|
ArrowDown,
|
|
ArrowUp,
|
|
NumLock,
|
|
NumpadDivide,
|
|
NumpadMultiply,
|
|
NumpadSubtract,
|
|
NumpadAdd,
|
|
NumpadEnter,
|
|
Numpad1,
|
|
Numpad2,
|
|
Numpad3,
|
|
Numpad4,
|
|
Numpad5,
|
|
Numpad6,
|
|
Numpad7,
|
|
Numpad8,
|
|
Numpad9,
|
|
Numpad0,
|
|
NumpadDecimal,
|
|
IntlBackslash,
|
|
ContextMenu,
|
|
F13,
|
|
F14,
|
|
F15,
|
|
F16,
|
|
F17,
|
|
F18,
|
|
F19,
|
|
F20,
|
|
F21,
|
|
F22,
|
|
F23,
|
|
F24,
|
|
ControlLeft,
|
|
ShiftLeft,
|
|
AltLeft,
|
|
MetaLeft,
|
|
ControlRight,
|
|
ShiftRight,
|
|
AltRight,
|
|
MetaRight,
|
|
}
|
|
|
|
impl CanonicalKey {
|
|
/// Convert the canonical key to a stable wire code.
|
|
///
|
|
/// The wire code intentionally matches the USB HID usage for keyboard page
|
|
/// keys so existing low-level behavior stays intact while the semantic type
|
|
/// becomes explicit.
|
|
pub const fn to_hid_usage(self) -> u8 {
|
|
match self {
|
|
Self::KeyA => 0x04,
|
|
Self::KeyB => 0x05,
|
|
Self::KeyC => 0x06,
|
|
Self::KeyD => 0x07,
|
|
Self::KeyE => 0x08,
|
|
Self::KeyF => 0x09,
|
|
Self::KeyG => 0x0A,
|
|
Self::KeyH => 0x0B,
|
|
Self::KeyI => 0x0C,
|
|
Self::KeyJ => 0x0D,
|
|
Self::KeyK => 0x0E,
|
|
Self::KeyL => 0x0F,
|
|
Self::KeyM => 0x10,
|
|
Self::KeyN => 0x11,
|
|
Self::KeyO => 0x12,
|
|
Self::KeyP => 0x13,
|
|
Self::KeyQ => 0x14,
|
|
Self::KeyR => 0x15,
|
|
Self::KeyS => 0x16,
|
|
Self::KeyT => 0x17,
|
|
Self::KeyU => 0x18,
|
|
Self::KeyV => 0x19,
|
|
Self::KeyW => 0x1A,
|
|
Self::KeyX => 0x1B,
|
|
Self::KeyY => 0x1C,
|
|
Self::KeyZ => 0x1D,
|
|
Self::Digit1 => 0x1E,
|
|
Self::Digit2 => 0x1F,
|
|
Self::Digit3 => 0x20,
|
|
Self::Digit4 => 0x21,
|
|
Self::Digit5 => 0x22,
|
|
Self::Digit6 => 0x23,
|
|
Self::Digit7 => 0x24,
|
|
Self::Digit8 => 0x25,
|
|
Self::Digit9 => 0x26,
|
|
Self::Digit0 => 0x27,
|
|
Self::Enter => 0x28,
|
|
Self::Escape => 0x29,
|
|
Self::Backspace => 0x2A,
|
|
Self::Tab => 0x2B,
|
|
Self::Space => 0x2C,
|
|
Self::Minus => 0x2D,
|
|
Self::Equal => 0x2E,
|
|
Self::BracketLeft => 0x2F,
|
|
Self::BracketRight => 0x30,
|
|
Self::Backslash => 0x31,
|
|
Self::Semicolon => 0x33,
|
|
Self::Quote => 0x34,
|
|
Self::Backquote => 0x35,
|
|
Self::Comma => 0x36,
|
|
Self::Period => 0x37,
|
|
Self::Slash => 0x38,
|
|
Self::CapsLock => 0x39,
|
|
Self::F1 => 0x3A,
|
|
Self::F2 => 0x3B,
|
|
Self::F3 => 0x3C,
|
|
Self::F4 => 0x3D,
|
|
Self::F5 => 0x3E,
|
|
Self::F6 => 0x3F,
|
|
Self::F7 => 0x40,
|
|
Self::F8 => 0x41,
|
|
Self::F9 => 0x42,
|
|
Self::F10 => 0x43,
|
|
Self::F11 => 0x44,
|
|
Self::F12 => 0x45,
|
|
Self::PrintScreen => 0x46,
|
|
Self::ScrollLock => 0x47,
|
|
Self::Pause => 0x48,
|
|
Self::Insert => 0x49,
|
|
Self::Home => 0x4A,
|
|
Self::PageUp => 0x4B,
|
|
Self::Delete => 0x4C,
|
|
Self::End => 0x4D,
|
|
Self::PageDown => 0x4E,
|
|
Self::ArrowRight => 0x4F,
|
|
Self::ArrowLeft => 0x50,
|
|
Self::ArrowDown => 0x51,
|
|
Self::ArrowUp => 0x52,
|
|
Self::NumLock => 0x53,
|
|
Self::NumpadDivide => 0x54,
|
|
Self::NumpadMultiply => 0x55,
|
|
Self::NumpadSubtract => 0x56,
|
|
Self::NumpadAdd => 0x57,
|
|
Self::NumpadEnter => 0x58,
|
|
Self::Numpad1 => 0x59,
|
|
Self::Numpad2 => 0x5A,
|
|
Self::Numpad3 => 0x5B,
|
|
Self::Numpad4 => 0x5C,
|
|
Self::Numpad5 => 0x5D,
|
|
Self::Numpad6 => 0x5E,
|
|
Self::Numpad7 => 0x5F,
|
|
Self::Numpad8 => 0x60,
|
|
Self::Numpad9 => 0x61,
|
|
Self::Numpad0 => 0x62,
|
|
Self::NumpadDecimal => 0x63,
|
|
Self::IntlBackslash => 0x64,
|
|
Self::ContextMenu => 0x65,
|
|
Self::F13 => 0x68,
|
|
Self::F14 => 0x69,
|
|
Self::F15 => 0x6A,
|
|
Self::F16 => 0x6B,
|
|
Self::F17 => 0x6C,
|
|
Self::F18 => 0x6D,
|
|
Self::F19 => 0x6E,
|
|
Self::F20 => 0x6F,
|
|
Self::F21 => 0x70,
|
|
Self::F22 => 0x71,
|
|
Self::F23 => 0x72,
|
|
Self::F24 => 0x73,
|
|
Self::ControlLeft => 0xE0,
|
|
Self::ShiftLeft => 0xE1,
|
|
Self::AltLeft => 0xE2,
|
|
Self::MetaLeft => 0xE3,
|
|
Self::ControlRight => 0xE4,
|
|
Self::ShiftRight => 0xE5,
|
|
Self::AltRight => 0xE6,
|
|
Self::MetaRight => 0xE7,
|
|
}
|
|
}
|
|
|
|
/// Convert a wire code / USB HID usage to its canonical key.
|
|
pub const fn from_hid_usage(usage: u8) -> Option<Self> {
|
|
match usage {
|
|
0x04 => Some(Self::KeyA),
|
|
0x05 => Some(Self::KeyB),
|
|
0x06 => Some(Self::KeyC),
|
|
0x07 => Some(Self::KeyD),
|
|
0x08 => Some(Self::KeyE),
|
|
0x09 => Some(Self::KeyF),
|
|
0x0A => Some(Self::KeyG),
|
|
0x0B => Some(Self::KeyH),
|
|
0x0C => Some(Self::KeyI),
|
|
0x0D => Some(Self::KeyJ),
|
|
0x0E => Some(Self::KeyK),
|
|
0x0F => Some(Self::KeyL),
|
|
0x10 => Some(Self::KeyM),
|
|
0x11 => Some(Self::KeyN),
|
|
0x12 => Some(Self::KeyO),
|
|
0x13 => Some(Self::KeyP),
|
|
0x14 => Some(Self::KeyQ),
|
|
0x15 => Some(Self::KeyR),
|
|
0x16 => Some(Self::KeyS),
|
|
0x17 => Some(Self::KeyT),
|
|
0x18 => Some(Self::KeyU),
|
|
0x19 => Some(Self::KeyV),
|
|
0x1A => Some(Self::KeyW),
|
|
0x1B => Some(Self::KeyX),
|
|
0x1C => Some(Self::KeyY),
|
|
0x1D => Some(Self::KeyZ),
|
|
0x1E => Some(Self::Digit1),
|
|
0x1F => Some(Self::Digit2),
|
|
0x20 => Some(Self::Digit3),
|
|
0x21 => Some(Self::Digit4),
|
|
0x22 => Some(Self::Digit5),
|
|
0x23 => Some(Self::Digit6),
|
|
0x24 => Some(Self::Digit7),
|
|
0x25 => Some(Self::Digit8),
|
|
0x26 => Some(Self::Digit9),
|
|
0x27 => Some(Self::Digit0),
|
|
0x28 => Some(Self::Enter),
|
|
0x29 => Some(Self::Escape),
|
|
0x2A => Some(Self::Backspace),
|
|
0x2B => Some(Self::Tab),
|
|
0x2C => Some(Self::Space),
|
|
0x2D => Some(Self::Minus),
|
|
0x2E => Some(Self::Equal),
|
|
0x2F => Some(Self::BracketLeft),
|
|
0x30 => Some(Self::BracketRight),
|
|
0x31 => Some(Self::Backslash),
|
|
0x33 => Some(Self::Semicolon),
|
|
0x34 => Some(Self::Quote),
|
|
0x35 => Some(Self::Backquote),
|
|
0x36 => Some(Self::Comma),
|
|
0x37 => Some(Self::Period),
|
|
0x38 => Some(Self::Slash),
|
|
0x39 => Some(Self::CapsLock),
|
|
0x3A => Some(Self::F1),
|
|
0x3B => Some(Self::F2),
|
|
0x3C => Some(Self::F3),
|
|
0x3D => Some(Self::F4),
|
|
0x3E => Some(Self::F5),
|
|
0x3F => Some(Self::F6),
|
|
0x40 => Some(Self::F7),
|
|
0x41 => Some(Self::F8),
|
|
0x42 => Some(Self::F9),
|
|
0x43 => Some(Self::F10),
|
|
0x44 => Some(Self::F11),
|
|
0x45 => Some(Self::F12),
|
|
0x46 => Some(Self::PrintScreen),
|
|
0x47 => Some(Self::ScrollLock),
|
|
0x48 => Some(Self::Pause),
|
|
0x49 => Some(Self::Insert),
|
|
0x4A => Some(Self::Home),
|
|
0x4B => Some(Self::PageUp),
|
|
0x4C => Some(Self::Delete),
|
|
0x4D => Some(Self::End),
|
|
0x4E => Some(Self::PageDown),
|
|
0x4F => Some(Self::ArrowRight),
|
|
0x50 => Some(Self::ArrowLeft),
|
|
0x51 => Some(Self::ArrowDown),
|
|
0x52 => Some(Self::ArrowUp),
|
|
0x53 => Some(Self::NumLock),
|
|
0x54 => Some(Self::NumpadDivide),
|
|
0x55 => Some(Self::NumpadMultiply),
|
|
0x56 => Some(Self::NumpadSubtract),
|
|
0x57 => Some(Self::NumpadAdd),
|
|
0x58 => Some(Self::NumpadEnter),
|
|
0x59 => Some(Self::Numpad1),
|
|
0x5A => Some(Self::Numpad2),
|
|
0x5B => Some(Self::Numpad3),
|
|
0x5C => Some(Self::Numpad4),
|
|
0x5D => Some(Self::Numpad5),
|
|
0x5E => Some(Self::Numpad6),
|
|
0x5F => Some(Self::Numpad7),
|
|
0x60 => Some(Self::Numpad8),
|
|
0x61 => Some(Self::Numpad9),
|
|
0x62 => Some(Self::Numpad0),
|
|
0x63 => Some(Self::NumpadDecimal),
|
|
0x64 => Some(Self::IntlBackslash),
|
|
0x65 => Some(Self::ContextMenu),
|
|
0x68 => Some(Self::F13),
|
|
0x69 => Some(Self::F14),
|
|
0x6A => Some(Self::F15),
|
|
0x6B => Some(Self::F16),
|
|
0x6C => Some(Self::F17),
|
|
0x6D => Some(Self::F18),
|
|
0x6E => Some(Self::F19),
|
|
0x6F => Some(Self::F20),
|
|
0x70 => Some(Self::F21),
|
|
0x71 => Some(Self::F22),
|
|
0x72 => Some(Self::F23),
|
|
0x73 => Some(Self::F24),
|
|
0xE0 => Some(Self::ControlLeft),
|
|
0xE1 => Some(Self::ShiftLeft),
|
|
0xE2 => Some(Self::AltLeft),
|
|
0xE3 => Some(Self::MetaLeft),
|
|
0xE4 => Some(Self::ControlRight),
|
|
0xE5 => Some(Self::ShiftRight),
|
|
0xE6 => Some(Self::AltRight),
|
|
0xE7 => Some(Self::MetaRight),
|
|
_ => None,
|
|
}
|
|
}
|
|
|
|
pub const fn is_modifier(self) -> bool {
|
|
matches!(
|
|
self,
|
|
Self::ControlLeft
|
|
| Self::ShiftLeft
|
|
| Self::AltLeft
|
|
| Self::MetaLeft
|
|
| Self::ControlRight
|
|
| Self::ShiftRight
|
|
| Self::AltRight
|
|
| Self::MetaRight
|
|
)
|
|
}
|
|
|
|
pub const fn modifier_bit(self) -> Option<u8> {
|
|
match self {
|
|
Self::ControlLeft => Some(0x01),
|
|
Self::ShiftLeft => Some(0x02),
|
|
Self::AltLeft => Some(0x04),
|
|
Self::MetaLeft => Some(0x08),
|
|
Self::ControlRight => Some(0x10),
|
|
Self::ShiftRight => Some(0x20),
|
|
Self::AltRight => Some(0x40),
|
|
Self::MetaRight => Some(0x80),
|
|
_ => None,
|
|
}
|
|
}
|
|
}
|