use crate::{Button, Key};
use windows::Win32::UI::Input::KeyboardAndMouse::{
MOUSE_EVENT_FLAGS, MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEDOWN,
MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_RIGHTUP, MOUSEEVENTF_XDOWN,
MOUSEEVENTF_XUP,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) struct WindowsScancode {
pub code: u16,
pub extended: bool,
}
impl WindowsScancode {
pub const fn new(code: u16) -> Self {
Self {
code,
extended: false,
}
}
pub const fn extended(code: u16) -> Self {
Self {
code,
extended: true,
}
}
}
pub(crate) fn key_to_platform(key: Key) -> Option<WindowsScancode> {
match key {
Key::A => Some(WindowsScancode::new(0x1E)),
Key::B => Some(WindowsScancode::new(0x30)),
Key::C => Some(WindowsScancode::new(0x2E)),
Key::D => Some(WindowsScancode::new(0x20)),
Key::E => Some(WindowsScancode::new(0x12)),
Key::F => Some(WindowsScancode::new(0x21)),
Key::G => Some(WindowsScancode::new(0x22)),
Key::H => Some(WindowsScancode::new(0x23)),
Key::I => Some(WindowsScancode::new(0x17)),
Key::J => Some(WindowsScancode::new(0x24)),
Key::K => Some(WindowsScancode::new(0x25)),
Key::L => Some(WindowsScancode::new(0x26)),
Key::M => Some(WindowsScancode::new(0x32)),
Key::N => Some(WindowsScancode::new(0x31)),
Key::O => Some(WindowsScancode::new(0x18)),
Key::P => Some(WindowsScancode::new(0x19)),
Key::Q => Some(WindowsScancode::new(0x10)),
Key::R => Some(WindowsScancode::new(0x13)),
Key::S => Some(WindowsScancode::new(0x1F)),
Key::T => Some(WindowsScancode::new(0x14)),
Key::U => Some(WindowsScancode::new(0x16)),
Key::V => Some(WindowsScancode::new(0x2F)),
Key::W => Some(WindowsScancode::new(0x11)),
Key::X => Some(WindowsScancode::new(0x2D)),
Key::Y => Some(WindowsScancode::new(0x15)),
Key::Z => Some(WindowsScancode::new(0x2C)),
Key::Digit1 => Some(WindowsScancode::new(0x02)),
Key::Digit2 => Some(WindowsScancode::new(0x03)),
Key::Digit3 => Some(WindowsScancode::new(0x04)),
Key::Digit4 => Some(WindowsScancode::new(0x05)),
Key::Digit5 => Some(WindowsScancode::new(0x06)),
Key::Digit6 => Some(WindowsScancode::new(0x07)),
Key::Digit7 => Some(WindowsScancode::new(0x08)),
Key::Digit8 => Some(WindowsScancode::new(0x09)),
Key::Digit9 => Some(WindowsScancode::new(0x0A)),
Key::Digit0 => Some(WindowsScancode::new(0x0B)),
Key::F1 => Some(WindowsScancode::new(0x3B)),
Key::F2 => Some(WindowsScancode::new(0x3C)),
Key::F3 => Some(WindowsScancode::new(0x3D)),
Key::F4 => Some(WindowsScancode::new(0x3E)),
Key::F5 => Some(WindowsScancode::new(0x3F)),
Key::F6 => Some(WindowsScancode::new(0x40)),
Key::F7 => Some(WindowsScancode::new(0x41)),
Key::F8 => Some(WindowsScancode::new(0x42)),
Key::F9 => Some(WindowsScancode::new(0x43)),
Key::F10 => Some(WindowsScancode::new(0x44)),
Key::F11 => Some(WindowsScancode::new(0x57)),
Key::F12 => Some(WindowsScancode::new(0x58)),
Key::F13 => Some(WindowsScancode::new(0x64)),
Key::F14 => Some(WindowsScancode::new(0x65)),
Key::F15 => Some(WindowsScancode::new(0x66)),
Key::F16 => Some(WindowsScancode::new(0x67)),
Key::F17 => Some(WindowsScancode::new(0x68)),
Key::F18 => Some(WindowsScancode::new(0x69)),
Key::F19 => Some(WindowsScancode::new(0x6A)),
Key::F20 => Some(WindowsScancode::new(0x6B)),
Key::F21 => Some(WindowsScancode::new(0x6C)),
Key::F22 => Some(WindowsScancode::new(0x6D)),
Key::F23 => Some(WindowsScancode::new(0x6E)),
Key::F24 => Some(WindowsScancode::new(0x76)),
Key::ShiftLeft => Some(WindowsScancode::new(0x2A)),
Key::ShiftRight => Some(WindowsScancode::new(0x36)),
Key::ControlLeft => Some(WindowsScancode::new(0x1D)),
Key::ControlRight => Some(WindowsScancode::extended(0x1D)),
Key::AltLeft => Some(WindowsScancode::new(0x38)),
Key::AltRight => Some(WindowsScancode::extended(0x38)),
Key::MetaLeft => Some(WindowsScancode::extended(0x5B)),
Key::MetaRight => Some(WindowsScancode::extended(0x5C)),
Key::Escape => Some(WindowsScancode::new(0x01)),
Key::Space => Some(WindowsScancode::new(0x39)),
Key::Enter => Some(WindowsScancode::new(0x1C)),
Key::Tab => Some(WindowsScancode::new(0x0F)),
Key::Backspace => Some(WindowsScancode::new(0x0E)),
Key::CapsLock => Some(WindowsScancode::new(0x3A)),
Key::NumLock => Some(WindowsScancode::new(0x45)),
Key::ScrollLock => Some(WindowsScancode::new(0x46)),
Key::Backquote => Some(WindowsScancode::new(0x29)),
Key::Minus => Some(WindowsScancode::new(0x0C)),
Key::Equal => Some(WindowsScancode::new(0x0D)),
Key::BracketLeft => Some(WindowsScancode::new(0x1A)),
Key::BracketRight => Some(WindowsScancode::new(0x1B)),
Key::Backslash => Some(WindowsScancode::new(0x2B)),
Key::Semicolon => Some(WindowsScancode::new(0x27)),
Key::Quote => Some(WindowsScancode::new(0x28)),
Key::Comma => Some(WindowsScancode::new(0x33)),
Key::Period => Some(WindowsScancode::new(0x34)),
Key::Slash => Some(WindowsScancode::new(0x35)),
Key::IsoBackslash => Some(WindowsScancode::new(0x56)),
Key::Insert => Some(WindowsScancode::extended(0x52)),
Key::Delete => Some(WindowsScancode::extended(0x53)),
Key::Home => Some(WindowsScancode::extended(0x47)),
Key::End => Some(WindowsScancode::extended(0x4F)),
Key::PageUp => Some(WindowsScancode::extended(0x49)),
Key::PageDown => Some(WindowsScancode::extended(0x51)),
Key::ArrowUp => Some(WindowsScancode::extended(0x48)),
Key::ArrowDown => Some(WindowsScancode::extended(0x50)),
Key::ArrowLeft => Some(WindowsScancode::extended(0x4B)),
Key::ArrowRight => Some(WindowsScancode::extended(0x4D)),
Key::Numpad0 => Some(WindowsScancode::new(0x52)),
Key::Numpad1 => Some(WindowsScancode::new(0x4F)),
Key::Numpad2 => Some(WindowsScancode::new(0x50)),
Key::Numpad3 => Some(WindowsScancode::new(0x51)),
Key::Numpad4 => Some(WindowsScancode::new(0x4B)),
Key::Numpad5 => Some(WindowsScancode::new(0x4C)),
Key::Numpad6 => Some(WindowsScancode::new(0x4D)),
Key::Numpad7 => Some(WindowsScancode::new(0x47)),
Key::Numpad8 => Some(WindowsScancode::new(0x48)),
Key::Numpad9 => Some(WindowsScancode::new(0x49)),
Key::NumpadAdd => Some(WindowsScancode::new(0x4E)),
Key::NumpadSubtract => Some(WindowsScancode::new(0x4A)),
Key::NumpadMultiply => Some(WindowsScancode::new(0x37)),
Key::NumpadDivide => Some(WindowsScancode::extended(0x35)),
Key::NumpadDecimal => Some(WindowsScancode::new(0x53)),
Key::NumpadEnter => Some(WindowsScancode::extended(0x1C)),
Key::NumpadEqual => Some(WindowsScancode::new(0x59)),
Key::NumpadComma => Some(WindowsScancode::new(0x7E)),
Key::PrintScreen => Some(WindowsScancode::extended(0x37)),
Key::Pause => Some(WindowsScancode::extended(0x46)),
Key::ContextMenu => Some(WindowsScancode::extended(0x5D)),
Key::Power => Some(WindowsScancode::extended(0x5E)),
Key::Sleep => Some(WindowsScancode::extended(0x5F)),
Key::Wake => Some(WindowsScancode::extended(0x63)),
Key::VolumeMute => Some(WindowsScancode::extended(0x20)),
Key::VolumeDown => Some(WindowsScancode::extended(0x2E)),
Key::VolumeUp => Some(WindowsScancode::extended(0x30)),
Key::MediaPlayPause => Some(WindowsScancode::extended(0x22)),
Key::MediaStop => Some(WindowsScancode::extended(0x24)),
Key::MediaTrackNext => Some(WindowsScancode::extended(0x19)),
Key::MediaTrackPrevious => Some(WindowsScancode::extended(0x10)),
Key::BrowserBack => Some(WindowsScancode::extended(0x6A)),
Key::BrowserForward => Some(WindowsScancode::extended(0x69)),
Key::BrowserRefresh => Some(WindowsScancode::extended(0x67)),
Key::BrowserStop => Some(WindowsScancode::extended(0x68)),
Key::BrowserSearch => Some(WindowsScancode::extended(0x65)),
Key::BrowserFavorites => Some(WindowsScancode::extended(0x66)),
Key::BrowserHome => Some(WindowsScancode::extended(0x32)),
Key::LaunchMail => Some(WindowsScancode::extended(0x6C)),
Key::LaunchMediaPlayer => Some(WindowsScancode::extended(0x6D)),
Key::LaunchApp1 => Some(WindowsScancode::extended(0x6B)),
Key::LaunchApp2 => Some(WindowsScancode::extended(0x21)),
Key::NonConvert => Some(WindowsScancode::new(0x7B)),
Key::Convert => Some(WindowsScancode::new(0x79)),
Key::KanaMode => Some(WindowsScancode::new(0x70)),
Key::IntlYen => Some(WindowsScancode::new(0x7D)),
Key::IntlRo => Some(WindowsScancode::new(0x73)),
Key::Lang1 => Some(WindowsScancode::new(0xF2)),
Key::Lang2 => Some(WindowsScancode::new(0xF1)),
Key::Lang3 => Some(WindowsScancode::new(0x78)),
Key::Lang4 => Some(WindowsScancode::new(0x77)),
Key::Help => Some(WindowsScancode::extended(0x63)),
Key::Undo => Some(WindowsScancode::extended(0x08)),
Key::Redo => Some(WindowsScancode::extended(0x07)),
Key::Cut => Some(WindowsScancode::extended(0x04)),
Key::Copy => Some(WindowsScancode::extended(0x18)),
Key::Paste => Some(WindowsScancode::extended(0x0A)),
Key::Find => Some(WindowsScancode::extended(0x65)),
}
}
pub(crate) fn button_to_platform(
button: Button,
released: bool,
) -> Option<(MOUSE_EVENT_FLAGS, u32)> {
match (button, released) {
(Button::Left, false) => Some((MOUSEEVENTF_LEFTDOWN, 0)),
(Button::Left, true) => Some((MOUSEEVENTF_LEFTUP, 0)),
(Button::Right, false) => Some((MOUSEEVENTF_RIGHTDOWN, 0)),
(Button::Right, true) => Some((MOUSEEVENTF_RIGHTUP, 0)),
(Button::Middle, false) => Some((MOUSEEVENTF_MIDDLEDOWN, 0)),
(Button::Middle, true) => Some((MOUSEEVENTF_MIDDLEUP, 0)),
(Button::Extra1, false) => Some((MOUSEEVENTF_XDOWN, 1)),
(Button::Extra1, true) => Some((MOUSEEVENTF_XUP, 1)),
(Button::Extra2, false) => Some((MOUSEEVENTF_XDOWN, 2)),
(Button::Extra2, true) => Some((MOUSEEVENTF_XUP, 2)),
(Button::Extra3, _) => None,
(Button::Extra4, _) => None,
}
}
pub(crate) fn platform_to_key(scancode: u16, extended: bool) -> Option<Key> {
match (scancode, extended) {
(0x1E, false) => Some(Key::A),
(0x30, false) => Some(Key::B),
(0x2E, false) => Some(Key::C),
(0x20, false) => Some(Key::D),
(0x12, false) => Some(Key::E),
(0x21, false) => Some(Key::F),
(0x22, false) => Some(Key::G),
(0x23, false) => Some(Key::H),
(0x17, false) => Some(Key::I),
(0x24, false) => Some(Key::J),
(0x25, false) => Some(Key::K),
(0x26, false) => Some(Key::L),
(0x32, false) => Some(Key::M),
(0x31, false) => Some(Key::N),
(0x18, false) => Some(Key::O),
(0x19, false) => Some(Key::P),
(0x10, false) => Some(Key::Q),
(0x13, false) => Some(Key::R),
(0x1F, false) => Some(Key::S),
(0x14, false) => Some(Key::T),
(0x16, false) => Some(Key::U),
(0x2F, false) => Some(Key::V),
(0x11, false) => Some(Key::W),
(0x2D, false) => Some(Key::X),
(0x15, false) => Some(Key::Y),
(0x2C, false) => Some(Key::Z),
(0x02, false) => Some(Key::Digit1),
(0x03, false) => Some(Key::Digit2),
(0x04, false) => Some(Key::Digit3),
(0x05, false) => Some(Key::Digit4),
(0x06, false) => Some(Key::Digit5),
(0x07, false) => Some(Key::Digit6),
(0x08, false) => Some(Key::Digit7),
(0x09, false) => Some(Key::Digit8),
(0x0A, false) => Some(Key::Digit9),
(0x0B, false) => Some(Key::Digit0),
(0x3B, false) => Some(Key::F1),
(0x3C, false) => Some(Key::F2),
(0x3D, false) => Some(Key::F3),
(0x3E, false) => Some(Key::F4),
(0x3F, false) => Some(Key::F5),
(0x40, false) => Some(Key::F6),
(0x41, false) => Some(Key::F7),
(0x42, false) => Some(Key::F8),
(0x43, false) => Some(Key::F9),
(0x44, false) => Some(Key::F10),
(0x57, false) => Some(Key::F11),
(0x58, false) => Some(Key::F12),
(0x64, false) => Some(Key::F13),
(0x65, false) => Some(Key::F14),
(0x66, false) => Some(Key::F15),
(0x67, false) => Some(Key::F16),
(0x68, false) => Some(Key::F17),
(0x69, false) => Some(Key::F18),
(0x6A, false) => Some(Key::F19),
(0x6B, false) => Some(Key::F20),
(0x6C, false) => Some(Key::F21),
(0x6D, false) => Some(Key::F22),
(0x6E, false) => Some(Key::F23),
(0x76, false) => Some(Key::F24),
(0x2A, false) => Some(Key::ShiftLeft),
(0x36, false) => Some(Key::ShiftRight),
(0x1D, false) => Some(Key::ControlLeft),
(0x1D, true) => Some(Key::ControlRight),
(0x38, false) => Some(Key::AltLeft),
(0x38, true) => Some(Key::AltRight),
(0x5B, true) => Some(Key::MetaLeft),
(0x5C, true) => Some(Key::MetaRight),
(0x01, false) => Some(Key::Escape),
(0x39, false) => Some(Key::Space),
(0x1C, false) => Some(Key::Enter),
(0x0F, false) => Some(Key::Tab),
(0x0E, false) => Some(Key::Backspace),
(0x3A, false) => Some(Key::CapsLock),
(0x45, false) => Some(Key::NumLock),
(0x46, false) => Some(Key::ScrollLock),
(0x29, false) => Some(Key::Backquote),
(0x0C, false) => Some(Key::Minus),
(0x0D, false) => Some(Key::Equal),
(0x1A, false) => Some(Key::BracketLeft),
(0x1B, false) => Some(Key::BracketRight),
(0x2B, false) => Some(Key::Backslash),
(0x27, false) => Some(Key::Semicolon),
(0x28, false) => Some(Key::Quote),
(0x33, false) => Some(Key::Comma),
(0x34, false) => Some(Key::Period),
(0x35, false) => Some(Key::Slash),
(0x56, false) => Some(Key::IsoBackslash),
(0x52, true) => Some(Key::Insert),
(0x53, true) => Some(Key::Delete),
(0x47, true) => Some(Key::Home),
(0x4F, true) => Some(Key::End),
(0x49, true) => Some(Key::PageUp),
(0x51, true) => Some(Key::PageDown),
(0x48, true) => Some(Key::ArrowUp),
(0x50, true) => Some(Key::ArrowDown),
(0x4B, true) => Some(Key::ArrowLeft),
(0x4D, true) => Some(Key::ArrowRight),
(0x52, false) => Some(Key::Numpad0),
(0x4F, false) => Some(Key::Numpad1),
(0x50, false) => Some(Key::Numpad2),
(0x51, false) => Some(Key::Numpad3),
(0x4B, false) => Some(Key::Numpad4),
(0x4C, false) => Some(Key::Numpad5),
(0x4D, false) => Some(Key::Numpad6),
(0x47, false) => Some(Key::Numpad7),
(0x48, false) => Some(Key::Numpad8),
(0x49, false) => Some(Key::Numpad9),
(0x4E, false) => Some(Key::NumpadAdd),
(0x4A, false) => Some(Key::NumpadSubtract),
(0x37, false) => Some(Key::NumpadMultiply),
(0x35, true) => Some(Key::NumpadDivide),
(0x53, false) => Some(Key::NumpadDecimal),
(0x1C, true) => Some(Key::NumpadEnter),
(0x59, false) => Some(Key::NumpadEqual),
(0x7E, false) => Some(Key::NumpadComma),
(0x37, true) => Some(Key::PrintScreen),
(0x46, true) => Some(Key::Pause),
(0x5D, true) => Some(Key::ContextMenu),
(0x5E, true) => Some(Key::Power),
(0x5F, true) => Some(Key::Sleep),
(0x63, true) => Some(Key::Wake),
(0x20, true) => Some(Key::VolumeMute),
(0x2E, true) => Some(Key::VolumeDown),
(0x30, true) => Some(Key::VolumeUp),
(0x22, true) => Some(Key::MediaPlayPause),
(0x24, true) => Some(Key::MediaStop),
(0x19, true) => Some(Key::MediaTrackNext),
(0x10, true) => Some(Key::MediaTrackPrevious),
(0x6A, true) => Some(Key::BrowserBack),
(0x69, true) => Some(Key::BrowserForward),
(0x67, true) => Some(Key::BrowserRefresh),
(0x68, true) => Some(Key::BrowserStop),
(0x65, true) => Some(Key::BrowserSearch),
(0x66, true) => Some(Key::BrowserFavorites),
(0x32, true) => Some(Key::BrowserHome),
(0x6C, true) => Some(Key::LaunchMail),
(0x6D, true) => Some(Key::LaunchMediaPlayer),
(0x6B, true) => Some(Key::LaunchApp1),
(0x21, true) => Some(Key::LaunchApp2),
(0x7B, false) => Some(Key::NonConvert),
(0x79, false) => Some(Key::Convert),
(0x70, false) => Some(Key::KanaMode),
(0x7D, false) => Some(Key::IntlYen),
(0x73, false) => Some(Key::IntlRo),
(0xF2, false) => Some(Key::Lang1),
(0xF1, false) => Some(Key::Lang2),
(0x78, false) => Some(Key::Lang3),
(0x77, false) => Some(Key::Lang4),
(0x08, true) => Some(Key::Undo),
(0x07, true) => Some(Key::Redo),
(0x04, true) => Some(Key::Cut),
(0x18, true) => Some(Key::Copy),
(0x0A, true) => Some(Key::Paste),
_ => None,
}
}