diff --git a/core/src/events.rs b/core/src/events.rs index ae3214761c84c..4eac437521329 100644 --- a/core/src/events.rs +++ b/core/src/events.rs @@ -5,12 +5,10 @@ use swf::ClipEventFlag; #[derive(Debug, Clone)] pub enum PlayerEvent { KeyDown { - key_code: KeyCode, - key_char: Option, + key: KeyDescriptor, }, KeyUp { - key_code: KeyCode, - key_char: Option, + key: KeyDescriptor, }, MouseMove { x: f64, @@ -830,3 +828,302 @@ impl FromStr for GamepadButton { }) } } + +#[derive(Debug, Clone, Copy)] +pub struct KeyDescriptor { + pub physical_key: PhysicalKey, + pub logical_key: LogicalKey, + pub key_location: KeyLocation, +} + +/// Physical keys are keys that exist physically on a keyboard (or other devices). +/// +/// For instance: +/// * pressing E while using ANSI keyboard and Colemak keyboard layout +/// will produce physical key [`PhysicalKey::KeyE`] and logical key `F`, +/// * pressing left backslash on a UK keyboard will produce physical key +/// [`PhysicalKey::IntlBackslash`] and logical key `\`. +/// +/// See . +#[derive(Debug, Clone, Copy)] +pub enum PhysicalKey { + Unknown = 0, + + // Alphanumeric Section + Backquote, + Digit0, + Digit1, + Digit2, + Digit4, + Digit3, + Digit5, + Digit6, + Digit7, + Digit8, + Digit9, + Minus, + Equal, + IntlYen, + 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, + BracketLeft, + BracketRight, + Backslash, + Semicolon, + Quote, + IntlBackslash, + Comma, + Period, + Slash, + IntlRo, + Backspace, + Tab, + CapsLock, + Enter, + ShiftLeft, + ShiftRight, + ControlLeft, + SuperLeft, + AltLeft, + Space, + AltRight, + SuperRight, + ContextMenu, + ControlRight, + + // Control Pad Section + Insert, + Delete, + Home, + End, + PageUp, + PageDown, + + // Arrow Pad Section + ArrowUp, + ArrowLeft, + ArrowDown, + ArrowRight, + + // Numpad Section + NumLock, + NumpadDivide, + NumpadMultiply, + NumpadSubtract, + Numpad7, + Numpad8, + Numpad9, + Numpad4, + Numpad5, + Numpad6, + Numpad1, + Numpad2, + Numpad3, + Numpad0, + NumpadAdd, + NumpadComma, + NumpadEnter, + NumpadDecimal, + + // Function Section + Escape, + 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, + Fn, + FnLock, + PrintScreen, + ScrollLock, + Pause, +} + +/// Logical key represents the semantics behind a pressed physical key +/// taking into account any system keyboard layouts and mappings. +/// +/// Most keys will be mapped into a [`LogicalKey::Character`], but some keys that do not produce +/// any characters (such as `F1...Fn` keys, `Home`, `Ctrl`, etc.) will be mapped into +/// [`LogicalKey::Named`], which is similar to a physical key, but: +/// * it does not take into account duplicate keys, e.g. there's only one Shift, +/// * it respects the keyboard layout, so that e.g. pressing CapsLock +/// with Colemak can produce `Backspace`. +/// +/// See . +#[derive(Debug, Clone, Copy)] +pub enum LogicalKey { + Unknown, + Character(char), + Named(NamedKey), +} + +impl LogicalKey { + pub fn character(self) -> Option { + match self { + LogicalKey::Unknown => None, + LogicalKey::Character(ch) => Some(ch), + LogicalKey::Named(NamedKey::Backspace) => Some('\u{0008}'), + LogicalKey::Named(NamedKey::Tab) => Some('\u{0009}'), + LogicalKey::Named(NamedKey::Enter) => Some('\u{000D}'), + LogicalKey::Named(NamedKey::Escape) => Some('\u{001B}'), + LogicalKey::Named(NamedKey::Delete) => Some('\u{007F}'), + LogicalKey::Named(_) => None, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum NamedKey { + // Modifier Keys + Alt, + AltGraph, + CapsLock, + Control, + Fn, + FnLock, + Super, + NumLock, + ScrollLock, + Shift, + Symbol, + SymbolLock, + + // Whitespace Keys + Enter, + Tab, + + // Navigation Keys + ArrowDown, + ArrowLeft, + ArrowRight, + ArrowUp, + End, + Home, + PageDown, + PageUp, + + // Editing Keys + Backspace, + Clear, + Copy, + CrSel, + Cut, + Delete, + EraseEof, + ExSel, + Insert, + Paste, + Redo, + Undo, + + // UI Keys + ContextMenu, + Escape, + Pause, + Play, + Select, + ZoomIn, + ZoomOut, + + // Device Keys + PrintScreen, + + // General-Purpose Function Keys + 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, +} + +#[derive(Debug, Clone, Copy)] +pub enum KeyLocation { + Standard = 0, + Left = 1, + Right = 2, + Numpad = 3, +} diff --git a/core/src/input.rs b/core/src/input.rs index e65f90625ae7d..f6b5e1fb2a892 100644 --- a/core/src/input.rs +++ b/core/src/input.rs @@ -1,9 +1,18 @@ use crate::events::{ - GamepadButton, KeyCode, MouseButton, MouseWheelDelta, PlayerEvent, TextControlCode, + GamepadButton, KeyCode, KeyDescriptor, KeyLocation, LogicalKey, MouseButton, MouseWheelDelta, + NamedKey, PhysicalKey, PlayerEvent, TextControlCode, }; use chrono::{DateTime, TimeDelta, Utc}; use std::collections::{HashMap, HashSet}; +pub enum KeyCodeMappingType { + // TODO Make this configurable, it's not + // yet possible to use this mapping type. + #[allow(dead_code)] + Physical, + Logical, +} + /// An event describing input in general. /// /// It's usually a processed [`PlayerEvent`]. @@ -12,10 +21,12 @@ pub enum InputEvent { KeyDown { key_code: KeyCode, key_char: Option, + key_location: KeyLocation, }, KeyUp { key_code: KeyCode, key_char: Option, + key_location: KeyLocation, }, MouseMove { x: f64, @@ -68,6 +79,8 @@ pub struct InputManager { /// A map from gamepad buttons to key codes. gamepad_button_mapping: HashMap, + + key_code_mapping_type: KeyCodeMappingType, } impl InputManager { @@ -79,6 +92,7 @@ impl InputManager { last_char: None, last_click: None, gamepad_button_mapping, + key_code_mapping_type: KeyCodeMappingType::Logical, } } @@ -115,6 +129,8 @@ impl InputManager { InputEvent::KeyDown { key_code: *key_code, key_char: None, + // TODO what location shoud we use here? + key_location: KeyLocation::Standard, } } else { // Just ignore this event. @@ -126,6 +142,8 @@ impl InputManager { InputEvent::KeyUp { key_code: *key_code, key_char: None, + // TODO what location shoud we use here? + key_location: KeyLocation::Standard, } } else { // Just ignore this event. @@ -133,10 +151,26 @@ impl InputManager { } } - PlayerEvent::KeyDown { key_code, key_char } => { - InputEvent::KeyDown { key_code, key_char } + PlayerEvent::KeyDown { key } => { + let key_code = self.map_to_key_code(key)?; + let key_char = self.map_to_key_char(key); + let key_location = self.map_to_key_location(key); + InputEvent::KeyDown { + key_code, + key_char, + key_location, + } + } + PlayerEvent::KeyUp { key } => { + let key_code = self.map_to_key_code(key)?; + let key_char = self.map_to_key_char(key); + let key_location = self.map_to_key_location(key); + InputEvent::KeyUp { + key_code, + key_char, + key_location, + } } - PlayerEvent::KeyUp { key_code, key_char } => InputEvent::KeyUp { key_code, key_char }, PlayerEvent::MouseMove { x, y } => InputEvent::MouseMove { x, y }, PlayerEvent::MouseUp { x, y, button } => InputEvent::MouseUp { x, y, button }, @@ -166,14 +200,39 @@ impl InputManager { Some(event) } + fn map_to_key_code(&self, descriptor: KeyDescriptor) -> Option { + match self.key_code_mapping_type { + KeyCodeMappingType::Physical => map_to_key_code_physical(descriptor.physical_key), + KeyCodeMappingType::Logical => { + map_to_key_code_logical(descriptor.logical_key, descriptor.key_location) + } + } + } + + fn map_to_key_char(&self, descriptor: KeyDescriptor) -> Option { + descriptor.logical_key.character() + } + + fn map_to_key_location(&self, descriptor: KeyDescriptor) -> KeyLocation { + match descriptor.logical_key { + // NumLock in FP reports Standard location, not Numpad + LogicalKey::Named(NamedKey::NumLock) => KeyLocation::Standard, + _ => descriptor.key_location, + } + } + fn handle_event(&mut self, event: &InputEvent) { match *event { - InputEvent::KeyDown { key_code, key_char } => { + InputEvent::KeyDown { + key_code, key_char, .. + } => { self.last_char = key_char; self.toggle_key(key_code); self.add_key(key_code); } - InputEvent::KeyUp { key_code, key_char } => { + InputEvent::KeyUp { + key_code, key_char, .. + } => { self.last_char = key_char; self.remove_key(key_code); } @@ -247,3 +306,238 @@ impl InputManager { buttons } } + +fn map_to_key_code_physical(key: PhysicalKey) -> Option { + Some(match key { + PhysicalKey::Unknown => KeyCode::UNKNOWN, + PhysicalKey::Backquote => KeyCode::BACKQUOTE, + PhysicalKey::Digit0 => KeyCode::NUMBER_0, + PhysicalKey::Digit1 => KeyCode::NUMBER_1, + PhysicalKey::Digit2 => KeyCode::NUMBER_2, + PhysicalKey::Digit3 => KeyCode::NUMBER_3, + PhysicalKey::Digit4 => KeyCode::NUMBER_4, + PhysicalKey::Digit5 => KeyCode::NUMBER_5, + PhysicalKey::Digit6 => KeyCode::NUMBER_6, + PhysicalKey::Digit7 => KeyCode::NUMBER_7, + PhysicalKey::Digit8 => KeyCode::NUMBER_8, + PhysicalKey::Digit9 => KeyCode::NUMBER_9, + PhysicalKey::Minus => KeyCode::MINUS, + PhysicalKey::Equal => KeyCode::EQUAL, + PhysicalKey::KeyA => KeyCode::A, + PhysicalKey::KeyB => KeyCode::B, + PhysicalKey::KeyC => KeyCode::C, + PhysicalKey::KeyD => KeyCode::D, + PhysicalKey::KeyE => KeyCode::E, + PhysicalKey::KeyF => KeyCode::F, + PhysicalKey::KeyG => KeyCode::G, + PhysicalKey::KeyH => KeyCode::H, + PhysicalKey::KeyI => KeyCode::I, + PhysicalKey::KeyJ => KeyCode::J, + PhysicalKey::KeyK => KeyCode::K, + PhysicalKey::KeyL => KeyCode::L, + PhysicalKey::KeyM => KeyCode::M, + PhysicalKey::KeyN => KeyCode::N, + PhysicalKey::KeyO => KeyCode::O, + PhysicalKey::KeyP => KeyCode::P, + PhysicalKey::KeyQ => KeyCode::Q, + PhysicalKey::KeyR => KeyCode::R, + PhysicalKey::KeyS => KeyCode::S, + PhysicalKey::KeyT => KeyCode::T, + PhysicalKey::KeyU => KeyCode::U, + PhysicalKey::KeyV => KeyCode::V, + PhysicalKey::KeyW => KeyCode::W, + PhysicalKey::KeyX => KeyCode::X, + PhysicalKey::KeyY => KeyCode::Y, + PhysicalKey::KeyZ => KeyCode::Z, + PhysicalKey::BracketLeft => KeyCode::LEFTBRACKET, + PhysicalKey::BracketRight => KeyCode::RIGHTBRACKET, + PhysicalKey::Backslash => KeyCode::BACKSLASH, + PhysicalKey::Semicolon => KeyCode::SEMICOLON, + PhysicalKey::Quote => KeyCode::QUOTE, + PhysicalKey::Comma => KeyCode::COMMA, + PhysicalKey::Period => KeyCode::PERIOD, + PhysicalKey::Slash => KeyCode::SLASH, + PhysicalKey::Backspace => KeyCode::BACKSPACE, + PhysicalKey::Tab => KeyCode::TAB, + PhysicalKey::CapsLock => KeyCode::CAPS_LOCK, + PhysicalKey::Enter => KeyCode::ENTER, + PhysicalKey::Space => KeyCode::SPACE, + PhysicalKey::AltLeft => KeyCode::ALT, + PhysicalKey::AltRight => return None, + PhysicalKey::SuperLeft | PhysicalKey::SuperRight => return None, + PhysicalKey::ContextMenu => return None, + PhysicalKey::ShiftLeft | PhysicalKey::ShiftRight => KeyCode::SHIFT, + PhysicalKey::ControlRight | PhysicalKey::ControlLeft => KeyCode::CONTROL, + PhysicalKey::Insert => KeyCode::INSERT, + PhysicalKey::Delete => KeyCode::DELETE, + PhysicalKey::Home => KeyCode::HOME, + PhysicalKey::End => KeyCode::END, + PhysicalKey::PageUp => KeyCode::PAGE_UP, + PhysicalKey::PageDown => KeyCode::PAGE_DOWN, + PhysicalKey::ArrowUp => KeyCode::UP, + PhysicalKey::ArrowLeft => KeyCode::LEFT, + PhysicalKey::ArrowDown => KeyCode::DOWN, + PhysicalKey::ArrowRight => KeyCode::RIGHT, + PhysicalKey::NumLock => KeyCode::NUM_LOCK, + PhysicalKey::NumpadDivide => KeyCode::NUMPAD_DIVIDE, + PhysicalKey::NumpadMultiply => KeyCode::NUMPAD_MULTIPLY, + PhysicalKey::NumpadSubtract => KeyCode::NUMPAD_SUBTRACT, + PhysicalKey::Numpad1 => KeyCode::NUMPAD_1, + PhysicalKey::Numpad2 => KeyCode::NUMPAD_2, + PhysicalKey::Numpad3 => KeyCode::NUMPAD_3, + PhysicalKey::Numpad4 => KeyCode::NUMPAD_4, + PhysicalKey::Numpad5 => KeyCode::NUMPAD_5, + PhysicalKey::Numpad6 => KeyCode::NUMPAD_6, + PhysicalKey::Numpad7 => KeyCode::NUMPAD_7, + PhysicalKey::Numpad8 => KeyCode::NUMPAD_8, + PhysicalKey::Numpad9 => KeyCode::NUMPAD_9, + PhysicalKey::Numpad0 => KeyCode::NUMPAD_0, + PhysicalKey::NumpadAdd => KeyCode::NUMPAD_ADD, + PhysicalKey::NumpadEnter => KeyCode::NUMPAD_ENTER, + PhysicalKey::NumpadDecimal => KeyCode::NUMPAD_DECIMAL, + PhysicalKey::Escape => KeyCode::ESCAPE, + PhysicalKey::F1 => KeyCode::F1, + PhysicalKey::F2 => KeyCode::F2, + PhysicalKey::F3 => KeyCode::F3, + PhysicalKey::F4 => KeyCode::F4, + PhysicalKey::F5 => KeyCode::F5, + PhysicalKey::F6 => KeyCode::F6, + PhysicalKey::F7 => KeyCode::F7, + PhysicalKey::F8 => KeyCode::F8, + PhysicalKey::F9 => KeyCode::F9, + PhysicalKey::F10 => KeyCode::F10, + PhysicalKey::F11 => KeyCode::F11, + PhysicalKey::F12 => KeyCode::F12, + PhysicalKey::F13 => KeyCode::F13, + PhysicalKey::F14 => KeyCode::F14, + PhysicalKey::F15 => KeyCode::F15, + PhysicalKey::F16 => KeyCode::F16, + PhysicalKey::F17 => KeyCode::F17, + PhysicalKey::F18 => KeyCode::F18, + PhysicalKey::F19 => KeyCode::F19, + PhysicalKey::F20 => KeyCode::F20, + PhysicalKey::F21 => KeyCode::F21, + PhysicalKey::F22 => KeyCode::F22, + PhysicalKey::F23 => KeyCode::F23, + PhysicalKey::F24 => KeyCode::F24, + PhysicalKey::Fn => return None, + PhysicalKey::FnLock => return None, + // TODO FP returns -1 for PrintScreen? + PhysicalKey::PrintScreen => KeyCode::UNKNOWN, + PhysicalKey::ScrollLock => KeyCode::SCROLL_LOCK, + PhysicalKey::Pause => KeyCode::PAUSE, + _ => return None, + }) +} + +fn map_to_key_code_logical(key: LogicalKey, location: KeyLocation) -> Option { + let is_numpad = matches!(location, KeyLocation::Numpad); + Some(match key { + LogicalKey::Named(NamedKey::Backspace) => KeyCode::BACKSPACE, + LogicalKey::Named(NamedKey::Tab) => KeyCode::TAB, + LogicalKey::Named(NamedKey::Enter) => KeyCode::ENTER, + LogicalKey::Named(NamedKey::Shift) => KeyCode::SHIFT, + LogicalKey::Named(NamedKey::Control) => KeyCode::CONTROL, + LogicalKey::Named(NamedKey::Alt) => KeyCode::ALT, + LogicalKey::Named(NamedKey::AltGraph) => return None, + LogicalKey::Named(NamedKey::ContextMenu) => return None, + LogicalKey::Named(NamedKey::CapsLock) => KeyCode::CAPS_LOCK, + LogicalKey::Named(NamedKey::Escape) => KeyCode::ESCAPE, + LogicalKey::Character(' ') => KeyCode::SPACE, + LogicalKey::Character('0') if is_numpad => KeyCode::NUMPAD_0, + LogicalKey::Character('1') if is_numpad => KeyCode::NUMPAD_1, + LogicalKey::Character('2') if is_numpad => KeyCode::NUMPAD_2, + LogicalKey::Character('3') if is_numpad => KeyCode::NUMPAD_3, + LogicalKey::Character('4') if is_numpad => KeyCode::NUMPAD_4, + LogicalKey::Character('5') if is_numpad => KeyCode::NUMPAD_5, + LogicalKey::Character('6') if is_numpad => KeyCode::NUMPAD_6, + LogicalKey::Character('7') if is_numpad => KeyCode::NUMPAD_7, + LogicalKey::Character('8') if is_numpad => KeyCode::NUMPAD_8, + LogicalKey::Character('9') if is_numpad => KeyCode::NUMPAD_9, + LogicalKey::Character('*') if is_numpad => KeyCode::NUMPAD_MULTIPLY, + LogicalKey::Character('+') if is_numpad => KeyCode::NUMPAD_ADD, + LogicalKey::Character('-') if is_numpad => KeyCode::NUMPAD_SUBTRACT, + LogicalKey::Character('.' | ',') if is_numpad => KeyCode::NUMPAD_DECIMAL, + LogicalKey::Character('/') if is_numpad => KeyCode::NUMPAD_DIVIDE, + LogicalKey::Character('0' | ')') => KeyCode::NUMBER_0, + LogicalKey::Character('1' | '!') => KeyCode::NUMBER_1, + LogicalKey::Character('2' | '@') => KeyCode::NUMBER_2, + LogicalKey::Character('3' | '#') => KeyCode::NUMBER_3, + LogicalKey::Character('4' | '$') => KeyCode::NUMBER_4, + LogicalKey::Character('5' | '%') => KeyCode::NUMBER_5, + LogicalKey::Character('6' | '^') => KeyCode::NUMBER_6, + LogicalKey::Character('7' | '&') => KeyCode::NUMBER_7, + LogicalKey::Character('8' | '*') => KeyCode::NUMBER_8, + LogicalKey::Character('9' | '(') => KeyCode::NUMBER_9, + LogicalKey::Character(';' | ':') => KeyCode::SEMICOLON, + LogicalKey::Character('=' | '+') => KeyCode::EQUAL, + LogicalKey::Character(',' | '<') => KeyCode::COMMA, + LogicalKey::Character('-' | '_') => KeyCode::MINUS, + LogicalKey::Character('.' | '>') => KeyCode::PERIOD, + LogicalKey::Character('/' | '?') => KeyCode::SLASH, + LogicalKey::Character('`' | '~') => KeyCode::BACKQUOTE, + LogicalKey::Character('[' | '{') => KeyCode::LEFTBRACKET, + LogicalKey::Character('\\' | '|') => KeyCode::BACKSLASH, + LogicalKey::Character(']' | '}') => KeyCode::RIGHTBRACKET, + LogicalKey::Character('\'' | '"') => KeyCode::QUOTE, + LogicalKey::Named(NamedKey::PageUp) => KeyCode::PAGE_UP, + LogicalKey::Named(NamedKey::PageDown) => KeyCode::PAGE_DOWN, + LogicalKey::Named(NamedKey::End) => KeyCode::END, + LogicalKey::Named(NamedKey::Home) => KeyCode::HOME, + LogicalKey::Named(NamedKey::ArrowLeft) => KeyCode::LEFT, + LogicalKey::Named(NamedKey::ArrowUp) => KeyCode::UP, + LogicalKey::Named(NamedKey::ArrowRight) => KeyCode::RIGHT, + LogicalKey::Named(NamedKey::ArrowDown) => KeyCode::DOWN, + LogicalKey::Named(NamedKey::Insert) => KeyCode::INSERT, + LogicalKey::Named(NamedKey::Delete) => KeyCode::DELETE, + LogicalKey::Named(NamedKey::Pause) => KeyCode::PAUSE, + LogicalKey::Named(NamedKey::NumLock) => KeyCode::NUM_LOCK, + LogicalKey::Named(NamedKey::ScrollLock) => KeyCode::SCROLL_LOCK, + LogicalKey::Named(NamedKey::F1) => KeyCode::F1, + LogicalKey::Named(NamedKey::F2) => KeyCode::F2, + LogicalKey::Named(NamedKey::F3) => KeyCode::F3, + LogicalKey::Named(NamedKey::F4) => KeyCode::F4, + LogicalKey::Named(NamedKey::F5) => KeyCode::F5, + LogicalKey::Named(NamedKey::F6) => KeyCode::F6, + LogicalKey::Named(NamedKey::F7) => KeyCode::F7, + LogicalKey::Named(NamedKey::F8) => KeyCode::F8, + LogicalKey::Named(NamedKey::F9) => KeyCode::F9, + LogicalKey::Named(NamedKey::F10) => KeyCode::F10, + LogicalKey::Named(NamedKey::F11) => KeyCode::F11, + LogicalKey::Named(NamedKey::F12) => KeyCode::F12, + LogicalKey::Named(NamedKey::F13) => KeyCode::F13, + LogicalKey::Named(NamedKey::F14) => KeyCode::F14, + LogicalKey::Named(NamedKey::F15) => KeyCode::F15, + LogicalKey::Named(NamedKey::F16) => KeyCode::F16, + LogicalKey::Named(NamedKey::F17) => KeyCode::F17, + LogicalKey::Named(NamedKey::F18) => KeyCode::F18, + LogicalKey::Named(NamedKey::F19) => KeyCode::F19, + LogicalKey::Named(NamedKey::F20) => KeyCode::F20, + LogicalKey::Named(NamedKey::F21) => KeyCode::F21, + LogicalKey::Named(NamedKey::F22) => KeyCode::F22, + LogicalKey::Named(NamedKey::F23) => KeyCode::F23, + LogicalKey::Named(NamedKey::F24) => KeyCode::F24, + LogicalKey::Character(char) => { + // Handle alphabetic characters + map_character_to_key_code(char).unwrap_or(KeyCode::UNKNOWN) + } + _ => return None, + }) +} + +fn map_character_to_key_code(char: char) -> Option { + if char.is_ascii_alphabetic() { + // ASCII alphabetic characters are all mapped to + // their respective KeyCodes, which happen to have + // the same numerical value as uppercase characters. + return Some(KeyCode::from_code(char.to_ascii_uppercase() as u32)); + } + + if !char.is_ascii() { + // Non-ASCII inputs have codes equal to their Unicode codes and yes, + // they overlap with other codes, so that typing '½' and '-' both produce 189. + return Some(KeyCode::from_code(char as u32)); + } + + None +} diff --git a/core/src/player.rs b/core/src/player.rs index 6c3d72efb98e5..c74f5a33c512c 100644 --- a/core/src/player.rs +++ b/core/src/player.rs @@ -1139,8 +1139,16 @@ impl Player { let button_event = ButtonKeyCode::from_input_event(&event) .map(|key_code| ClipEvent::KeyPress { key_code }); - if let InputEvent::KeyDown { key_code, key_char } - | InputEvent::KeyUp { key_code, key_char } = &event + if let InputEvent::KeyDown { + key_code, + key_char, + key_location, + } + | InputEvent::KeyUp { + key_code, + key_char, + key_location, + } = &event { let ctrl_key = context.input.is_key_down(KeyCode::CONTROL); let alt_key = context.input.is_key_down(KeyCode::ALT); @@ -1156,7 +1164,6 @@ impl Player { let keyboardevent_class = activation.avm2().classes().keyboardevent; - // TODO: keyLocation should not be a dummy value. // ctrlKey and controlKey can be different from each other on Mac. // commandKey should be supported. let keyboard_event = Avm2EventObject::from_class_and_args( @@ -1168,7 +1175,7 @@ impl Player { false.into(), /* cancelable */ key_char.map_or(0, |c| c as u32).into(), /* charCode */ key_code.value().into(), /* keyCode */ - 0.into(), /* keyLocation */ + (*key_location as u32).into(), /* keyLocation */ ctrl_key.into(), /* ctrlKey */ alt_key.into(), /* altKey */ shift_key.into(), /* shiftKey */ diff --git a/desktop/src/app.rs b/desktop/src/app.rs index 3cbf49ea9608e..f0d7ea10e34a2 100644 --- a/desktop/src/app.rs +++ b/desktop/src/app.rs @@ -4,7 +4,7 @@ use crate::player::{LaunchOptions, PlayerController}; use crate::preferences::GlobalPreferences; use crate::util::{ get_screen_size, gilrs_button_to_gamepad_button, parse_url, plot_stats_in_tracy, - winit_to_ruffle_key_code, winit_to_ruffle_text_control, + winit_input_to_ruffle_key_descriptor, winit_to_ruffle_text_control, }; use anyhow::Error; use gilrs::{Event, EventType, Gilrs}; @@ -205,15 +205,10 @@ impl MainWindow { .send_event(RuffleEvent::ExitFullScreen); } - let key_code = winit_to_ruffle_key_code(&event); - // [NA] TODO: This event used to give a single char. `last()` is functionally the same, - // but we may want to be better at this in the future. - let key_char = event.text.clone().and_then(|text| text.chars().last()); - - match (key_code, &event.state) { - (Some(key_code), ElementState::Pressed) => { - self.player - .handle_event(PlayerEvent::KeyDown { key_code, key_char }); + let key = winit_input_to_ruffle_key_descriptor(&event); + match event.state { + ElementState::Pressed => { + self.player.handle_event(PlayerEvent::KeyDown { key }); if let Some(control_code) = winit_to_ruffle_text_control(&event, &self.modifiers) { @@ -226,11 +221,9 @@ impl MainWindow { } } } - (Some(key_code), ElementState::Released) => { - self.player - .handle_event(PlayerEvent::KeyUp { key_code, key_char }); + ElementState::Released => { + self.player.handle_event(PlayerEvent::KeyUp { key }); } - _ => {} }; self.check_redraw(); } diff --git a/desktop/src/util.rs b/desktop/src/util.rs index db8fba620b13a..8fef369faf5bf 100644 --- a/desktop/src/util.rs +++ b/desktop/src/util.rs @@ -1,11 +1,17 @@ use anyhow::{anyhow, Error}; use gilrs::Button; -use ruffle_core::events::{GamepadButton, KeyCode, TextControlCode}; +use ruffle_core::events::{ + GamepadButton, KeyDescriptor, KeyLocation, LogicalKey, NamedKey as RuffleNamedKey, PhysicalKey, + TextControlCode, +}; use std::path::Path; use url::Url; use winit::dpi::PhysicalSize; use winit::event::{KeyEvent, Modifiers}; -use winit::keyboard::{Key, KeyLocation, NamedKey}; +use winit::keyboard::{ + Key, KeyCode as WinitKeyCode, KeyLocation as WinitKeyLocation, NamedKey, + PhysicalKey as WinitPhysicalKey, +}; use winit::window::Window; /// Converts a winit event to a Ruffle `TextControlCode`. @@ -55,127 +61,276 @@ pub fn winit_to_ruffle_text_control( } } -/// Convert a winit event into a Ruffle `KeyCode`. -/// Return `KeyCode::Unknown` if there is no matching Flash key code. -pub fn winit_to_ruffle_key_code(event: &KeyEvent) -> Option { +pub fn winit_input_to_ruffle_key_descriptor(event: &KeyEvent) -> KeyDescriptor { + let physical_key = map_physical_key(event); + let logical_key = map_logical_key(event); + let key_location = map_key_location(event); + KeyDescriptor { + physical_key, + logical_key, + key_location, + } +} + +fn map_physical_key(event: &KeyEvent) -> PhysicalKey { + match event.physical_key { + WinitPhysicalKey::Code(key_code) => match key_code { + WinitKeyCode::Backquote => PhysicalKey::Backquote, + WinitKeyCode::Backslash => PhysicalKey::Backslash, + WinitKeyCode::BracketLeft => PhysicalKey::BracketLeft, + WinitKeyCode::BracketRight => PhysicalKey::BracketRight, + WinitKeyCode::Comma => PhysicalKey::Comma, + WinitKeyCode::Digit0 => PhysicalKey::Digit0, + WinitKeyCode::Digit1 => PhysicalKey::Digit1, + WinitKeyCode::Digit2 => PhysicalKey::Digit2, + WinitKeyCode::Digit3 => PhysicalKey::Digit3, + WinitKeyCode::Digit4 => PhysicalKey::Digit4, + WinitKeyCode::Digit5 => PhysicalKey::Digit5, + WinitKeyCode::Digit6 => PhysicalKey::Digit6, + WinitKeyCode::Digit7 => PhysicalKey::Digit7, + WinitKeyCode::Digit8 => PhysicalKey::Digit8, + WinitKeyCode::Digit9 => PhysicalKey::Digit9, + WinitKeyCode::Equal => PhysicalKey::Equal, + WinitKeyCode::IntlBackslash => PhysicalKey::IntlBackslash, + WinitKeyCode::IntlRo => PhysicalKey::IntlRo, + WinitKeyCode::IntlYen => PhysicalKey::IntlYen, + WinitKeyCode::KeyA => PhysicalKey::KeyA, + WinitKeyCode::KeyB => PhysicalKey::KeyB, + WinitKeyCode::KeyC => PhysicalKey::KeyC, + WinitKeyCode::KeyD => PhysicalKey::KeyD, + WinitKeyCode::KeyE => PhysicalKey::KeyE, + WinitKeyCode::KeyF => PhysicalKey::KeyF, + WinitKeyCode::KeyG => PhysicalKey::KeyG, + WinitKeyCode::KeyH => PhysicalKey::KeyH, + WinitKeyCode::KeyI => PhysicalKey::KeyI, + WinitKeyCode::KeyJ => PhysicalKey::KeyJ, + WinitKeyCode::KeyK => PhysicalKey::KeyK, + WinitKeyCode::KeyL => PhysicalKey::KeyL, + WinitKeyCode::KeyM => PhysicalKey::KeyM, + WinitKeyCode::KeyN => PhysicalKey::KeyN, + WinitKeyCode::KeyO => PhysicalKey::KeyO, + WinitKeyCode::KeyP => PhysicalKey::KeyP, + WinitKeyCode::KeyQ => PhysicalKey::KeyQ, + WinitKeyCode::KeyR => PhysicalKey::KeyR, + WinitKeyCode::KeyS => PhysicalKey::KeyS, + WinitKeyCode::KeyT => PhysicalKey::KeyT, + WinitKeyCode::KeyU => PhysicalKey::KeyU, + WinitKeyCode::KeyV => PhysicalKey::KeyV, + WinitKeyCode::KeyW => PhysicalKey::KeyW, + WinitKeyCode::KeyX => PhysicalKey::KeyX, + WinitKeyCode::KeyY => PhysicalKey::KeyY, + WinitKeyCode::KeyZ => PhysicalKey::KeyZ, + WinitKeyCode::Minus => PhysicalKey::Minus, + WinitKeyCode::Period => PhysicalKey::Period, + WinitKeyCode::Quote => PhysicalKey::Quote, + WinitKeyCode::Semicolon => PhysicalKey::Semicolon, + WinitKeyCode::Slash => PhysicalKey::Slash, + WinitKeyCode::AltLeft => PhysicalKey::AltLeft, + WinitKeyCode::AltRight => PhysicalKey::AltRight, + WinitKeyCode::Backspace => PhysicalKey::Backspace, + WinitKeyCode::CapsLock => PhysicalKey::CapsLock, + WinitKeyCode::ContextMenu => PhysicalKey::ContextMenu, + WinitKeyCode::ControlLeft => PhysicalKey::ControlLeft, + WinitKeyCode::ControlRight => PhysicalKey::ControlRight, + WinitKeyCode::Enter => PhysicalKey::Enter, + WinitKeyCode::SuperLeft => PhysicalKey::SuperLeft, + WinitKeyCode::SuperRight => PhysicalKey::SuperRight, + WinitKeyCode::ShiftLeft => PhysicalKey::ShiftLeft, + WinitKeyCode::ShiftRight => PhysicalKey::ShiftRight, + WinitKeyCode::Space => PhysicalKey::Space, + WinitKeyCode::Tab => PhysicalKey::Tab, + WinitKeyCode::Convert => PhysicalKey::Unknown, + WinitKeyCode::KanaMode => PhysicalKey::Unknown, + WinitKeyCode::Lang1 => PhysicalKey::Unknown, + WinitKeyCode::Lang2 => PhysicalKey::Unknown, + WinitKeyCode::Lang3 => PhysicalKey::Unknown, + WinitKeyCode::Lang4 => PhysicalKey::Unknown, + WinitKeyCode::Lang5 => PhysicalKey::Unknown, + WinitKeyCode::NonConvert => PhysicalKey::Unknown, + WinitKeyCode::Delete => PhysicalKey::Delete, + WinitKeyCode::End => PhysicalKey::End, + WinitKeyCode::Help => PhysicalKey::Unknown, + WinitKeyCode::Home => PhysicalKey::Home, + WinitKeyCode::Insert => PhysicalKey::Insert, + WinitKeyCode::PageDown => PhysicalKey::PageDown, + WinitKeyCode::PageUp => PhysicalKey::PageUp, + WinitKeyCode::ArrowDown => PhysicalKey::ArrowDown, + WinitKeyCode::ArrowLeft => PhysicalKey::ArrowLeft, + WinitKeyCode::ArrowRight => PhysicalKey::ArrowRight, + WinitKeyCode::ArrowUp => PhysicalKey::ArrowUp, + WinitKeyCode::NumLock => PhysicalKey::NumLock, + WinitKeyCode::Numpad0 => PhysicalKey::Numpad0, + WinitKeyCode::Numpad1 => PhysicalKey::Numpad1, + WinitKeyCode::Numpad2 => PhysicalKey::Numpad2, + WinitKeyCode::Numpad3 => PhysicalKey::Numpad3, + WinitKeyCode::Numpad4 => PhysicalKey::Numpad4, + WinitKeyCode::Numpad5 => PhysicalKey::Numpad5, + WinitKeyCode::Numpad6 => PhysicalKey::Numpad6, + WinitKeyCode::Numpad7 => PhysicalKey::Numpad7, + WinitKeyCode::Numpad8 => PhysicalKey::Numpad8, + WinitKeyCode::Numpad9 => PhysicalKey::Numpad9, + WinitKeyCode::NumpadAdd => PhysicalKey::NumpadAdd, + WinitKeyCode::NumpadComma => PhysicalKey::NumpadComma, + WinitKeyCode::NumpadDecimal => PhysicalKey::NumpadDecimal, + WinitKeyCode::NumpadDivide => PhysicalKey::NumpadDivide, + WinitKeyCode::NumpadEnter => PhysicalKey::NumpadEnter, + WinitKeyCode::NumpadMultiply => PhysicalKey::NumpadMultiply, + WinitKeyCode::NumpadSubtract => PhysicalKey::NumpadSubtract, + WinitKeyCode::Escape => PhysicalKey::Escape, + WinitKeyCode::Fn => PhysicalKey::Fn, + WinitKeyCode::FnLock => PhysicalKey::FnLock, + WinitKeyCode::PrintScreen => PhysicalKey::PrintScreen, + WinitKeyCode::ScrollLock => PhysicalKey::ScrollLock, + WinitKeyCode::Pause => PhysicalKey::Pause, + WinitKeyCode::F1 => PhysicalKey::F1, + WinitKeyCode::F2 => PhysicalKey::F2, + WinitKeyCode::F3 => PhysicalKey::F3, + WinitKeyCode::F4 => PhysicalKey::F4, + WinitKeyCode::F5 => PhysicalKey::F5, + WinitKeyCode::F6 => PhysicalKey::F6, + WinitKeyCode::F7 => PhysicalKey::F7, + WinitKeyCode::F8 => PhysicalKey::F8, + WinitKeyCode::F9 => PhysicalKey::F9, + WinitKeyCode::F10 => PhysicalKey::F10, + WinitKeyCode::F11 => PhysicalKey::F11, + WinitKeyCode::F12 => PhysicalKey::F12, + WinitKeyCode::F13 => PhysicalKey::F13, + WinitKeyCode::F14 => PhysicalKey::F14, + WinitKeyCode::F15 => PhysicalKey::F15, + WinitKeyCode::F16 => PhysicalKey::F16, + WinitKeyCode::F17 => PhysicalKey::F17, + WinitKeyCode::F18 => PhysicalKey::F18, + WinitKeyCode::F19 => PhysicalKey::F19, + WinitKeyCode::F20 => PhysicalKey::F20, + WinitKeyCode::F21 => PhysicalKey::F21, + WinitKeyCode::F22 => PhysicalKey::F22, + WinitKeyCode::F23 => PhysicalKey::F23, + WinitKeyCode::F24 => PhysicalKey::F24, + WinitKeyCode::F25 => PhysicalKey::F25, + WinitKeyCode::F26 => PhysicalKey::F26, + WinitKeyCode::F27 => PhysicalKey::F27, + WinitKeyCode::F28 => PhysicalKey::F28, + WinitKeyCode::F29 => PhysicalKey::F29, + WinitKeyCode::F30 => PhysicalKey::F30, + WinitKeyCode::F31 => PhysicalKey::F31, + WinitKeyCode::F32 => PhysicalKey::F32, + WinitKeyCode::F33 => PhysicalKey::F33, + WinitKeyCode::F34 => PhysicalKey::F34, + WinitKeyCode::F35 => PhysicalKey::F35, + _ => PhysicalKey::Unknown, + }, + WinitPhysicalKey::Unidentified(_) => PhysicalKey::Unknown, + } +} + +fn map_logical_key(event: &KeyEvent) -> LogicalKey { // Note: it would be tempting to use event.key_without_modifiers() here, but FP // does not care about keys without modifiers at all, it does its own mapping, // so that on English UK, Shift+3 produces 16+163, not 16+51. - let is_numpad = event.location == KeyLocation::Numpad; - let key_code = match event.logical_key.as_ref() { - Key::Named(NamedKey::Backspace) => KeyCode::BACKSPACE, - Key::Named(NamedKey::Tab) => KeyCode::TAB, - Key::Named(NamedKey::Enter) => KeyCode::ENTER, - Key::Named(NamedKey::Shift) => KeyCode::SHIFT, - Key::Named(NamedKey::Control) => KeyCode::CONTROL, - Key::Named(NamedKey::Alt) => KeyCode::ALT, - // AltGr is ignored by FP - Key::Named(NamedKey::AltGraph) => return None, - Key::Named(NamedKey::CapsLock) => KeyCode::CAPS_LOCK, - Key::Named(NamedKey::Escape) => KeyCode::ESCAPE, - Key::Named(NamedKey::Space) => KeyCode::SPACE, - // Note: FP DOES care about modifiers for numpad keys, - // so that Shift+Numpad7 produces 16+36, not 16+103. - Key::Character("0") if is_numpad => KeyCode::NUMPAD_0, - Key::Character("1") if is_numpad => KeyCode::NUMPAD_1, - Key::Character("2") if is_numpad => KeyCode::NUMPAD_2, - Key::Character("3") if is_numpad => KeyCode::NUMPAD_3, - Key::Character("4") if is_numpad => KeyCode::NUMPAD_4, - Key::Character("5") if is_numpad => KeyCode::NUMPAD_5, - Key::Character("6") if is_numpad => KeyCode::NUMPAD_6, - Key::Character("7") if is_numpad => KeyCode::NUMPAD_7, - Key::Character("8") if is_numpad => KeyCode::NUMPAD_8, - Key::Character("9") if is_numpad => KeyCode::NUMPAD_9, - Key::Character("*") if is_numpad => KeyCode::NUMPAD_MULTIPLY, - Key::Character("+") if is_numpad => KeyCode::NUMPAD_ADD, - Key::Character("-") if is_numpad => KeyCode::NUMPAD_SUBTRACT, - Key::Character(".") if is_numpad => KeyCode::NUMPAD_DECIMAL, - Key::Character("/") if is_numpad => KeyCode::NUMPAD_DIVIDE, - Key::Character("0") | Key::Character(")") => KeyCode::NUMBER_0, - Key::Character("1") | Key::Character("!") => KeyCode::NUMBER_1, - Key::Character("2") | Key::Character("@") => KeyCode::NUMBER_2, - Key::Character("3") | Key::Character("#") => KeyCode::NUMBER_3, - Key::Character("4") | Key::Character("$") => KeyCode::NUMBER_4, - Key::Character("5") | Key::Character("%") => KeyCode::NUMBER_5, - Key::Character("6") | Key::Character("^") => KeyCode::NUMBER_6, - Key::Character("7") | Key::Character("&") => KeyCode::NUMBER_7, - Key::Character("8") | Key::Character("*") => KeyCode::NUMBER_8, - Key::Character("9") | Key::Character("(") => KeyCode::NUMBER_9, - Key::Character(";") | Key::Character(":") => KeyCode::SEMICOLON, - Key::Character("=") | Key::Character("+") => KeyCode::EQUAL, - Key::Character(",") | Key::Character("<") => KeyCode::COMMA, - Key::Character("-") | Key::Character("_") => KeyCode::MINUS, - Key::Character(".") | Key::Character(">") => KeyCode::PERIOD, - Key::Character("/") | Key::Character("?") => KeyCode::SLASH, - Key::Character("`") | Key::Character("~") => KeyCode::BACKQUOTE, - Key::Character("[") | Key::Character("{") => KeyCode::LEFTBRACKET, - Key::Character("\\") | Key::Character("|") => KeyCode::BACKSLASH, - Key::Character("]") | Key::Character("}") => KeyCode::RIGHTBRACKET, - Key::Character("'") | Key::Character("\"") => KeyCode::QUOTE, - Key::Named(NamedKey::PageUp) => KeyCode::PAGE_UP, - Key::Named(NamedKey::PageDown) => KeyCode::PAGE_DOWN, - Key::Named(NamedKey::End) => KeyCode::END, - Key::Named(NamedKey::Home) => KeyCode::HOME, - Key::Named(NamedKey::ArrowLeft) => KeyCode::LEFT, - Key::Named(NamedKey::ArrowUp) => KeyCode::UP, - Key::Named(NamedKey::ArrowRight) => KeyCode::RIGHT, - Key::Named(NamedKey::ArrowDown) => KeyCode::DOWN, - Key::Named(NamedKey::Insert) => KeyCode::INSERT, - Key::Named(NamedKey::Delete) => KeyCode::DELETE, - Key::Named(NamedKey::Pause) => KeyCode::PAUSE, - Key::Named(NamedKey::NumLock) => KeyCode::NUM_LOCK, - Key::Named(NamedKey::ScrollLock) => KeyCode::SCROLL_LOCK, - Key::Named(NamedKey::F1) => KeyCode::F1, - Key::Named(NamedKey::F2) => KeyCode::F2, - Key::Named(NamedKey::F3) => KeyCode::F3, - Key::Named(NamedKey::F4) => KeyCode::F4, - Key::Named(NamedKey::F5) => KeyCode::F5, - Key::Named(NamedKey::F6) => KeyCode::F6, - Key::Named(NamedKey::F7) => KeyCode::F7, - Key::Named(NamedKey::F8) => KeyCode::F8, - Key::Named(NamedKey::F9) => KeyCode::F9, - Key::Named(NamedKey::F10) => KeyCode::F10, - Key::Named(NamedKey::F11) => KeyCode::F11, - Key::Named(NamedKey::F12) => KeyCode::F12, - Key::Named(NamedKey::F13) => KeyCode::F13, - Key::Named(NamedKey::F14) => KeyCode::F14, - Key::Named(NamedKey::F15) => KeyCode::F15, - Key::Named(NamedKey::F16) => KeyCode::F16, - Key::Named(NamedKey::F17) => KeyCode::F17, - Key::Named(NamedKey::F18) => KeyCode::F18, - Key::Named(NamedKey::F19) => KeyCode::F19, - Key::Named(NamedKey::F20) => KeyCode::F20, - Key::Named(NamedKey::F21) => KeyCode::F21, - Key::Named(NamedKey::F22) => KeyCode::F22, - Key::Named(NamedKey::F23) => KeyCode::F23, - Key::Named(NamedKey::F24) => KeyCode::F24, - Key::Character(char) => { + match event.logical_key.as_ref() { + Key::Named(NamedKey::Alt) => LogicalKey::Named(RuffleNamedKey::Alt), + Key::Named(NamedKey::AltGraph) => LogicalKey::Named(RuffleNamedKey::AltGraph), + Key::Named(NamedKey::CapsLock) => LogicalKey::Named(RuffleNamedKey::CapsLock), + Key::Named(NamedKey::Control) => LogicalKey::Named(RuffleNamedKey::Control), + Key::Named(NamedKey::Fn) => LogicalKey::Named(RuffleNamedKey::Fn), + Key::Named(NamedKey::FnLock) => LogicalKey::Named(RuffleNamedKey::FnLock), + Key::Named(NamedKey::NumLock) => LogicalKey::Named(RuffleNamedKey::NumLock), + Key::Named(NamedKey::ScrollLock) => LogicalKey::Named(RuffleNamedKey::ScrollLock), + Key::Named(NamedKey::Shift) => LogicalKey::Named(RuffleNamedKey::Shift), + Key::Named(NamedKey::Symbol) => LogicalKey::Named(RuffleNamedKey::Symbol), + Key::Named(NamedKey::SymbolLock) => LogicalKey::Named(RuffleNamedKey::SymbolLock), + Key::Named(NamedKey::Super) => LogicalKey::Named(RuffleNamedKey::Super), + Key::Named(NamedKey::Enter) => LogicalKey::Named(RuffleNamedKey::Enter), + Key::Named(NamedKey::Tab) => LogicalKey::Named(RuffleNamedKey::Tab), + Key::Named(NamedKey::Space) => LogicalKey::Character(' '), + Key::Named(NamedKey::ArrowDown) => LogicalKey::Named(RuffleNamedKey::ArrowDown), + Key::Named(NamedKey::ArrowLeft) => LogicalKey::Named(RuffleNamedKey::ArrowLeft), + Key::Named(NamedKey::ArrowRight) => LogicalKey::Named(RuffleNamedKey::ArrowRight), + Key::Named(NamedKey::ArrowUp) => LogicalKey::Named(RuffleNamedKey::ArrowUp), + Key::Named(NamedKey::End) => LogicalKey::Named(RuffleNamedKey::End), + Key::Named(NamedKey::Home) => LogicalKey::Named(RuffleNamedKey::Home), + Key::Named(NamedKey::PageDown) => LogicalKey::Named(RuffleNamedKey::PageDown), + Key::Named(NamedKey::PageUp) => LogicalKey::Named(RuffleNamedKey::PageUp), + Key::Named(NamedKey::Backspace) => LogicalKey::Named(RuffleNamedKey::Backspace), + Key::Named(NamedKey::Clear) => LogicalKey::Named(RuffleNamedKey::Clear), + Key::Named(NamedKey::Copy) => LogicalKey::Named(RuffleNamedKey::Copy), + Key::Named(NamedKey::CrSel) => LogicalKey::Named(RuffleNamedKey::CrSel), + Key::Named(NamedKey::Cut) => LogicalKey::Named(RuffleNamedKey::Cut), + Key::Named(NamedKey::Delete) => LogicalKey::Named(RuffleNamedKey::Delete), + Key::Named(NamedKey::EraseEof) => LogicalKey::Named(RuffleNamedKey::EraseEof), + Key::Named(NamedKey::ExSel) => LogicalKey::Named(RuffleNamedKey::ExSel), + Key::Named(NamedKey::Insert) => LogicalKey::Named(RuffleNamedKey::Insert), + Key::Named(NamedKey::Paste) => LogicalKey::Named(RuffleNamedKey::Paste), + Key::Named(NamedKey::Redo) => LogicalKey::Named(RuffleNamedKey::Redo), + Key::Named(NamedKey::Undo) => LogicalKey::Named(RuffleNamedKey::Undo), + Key::Named(NamedKey::ContextMenu) => LogicalKey::Named(RuffleNamedKey::ContextMenu), + Key::Named(NamedKey::Escape) => LogicalKey::Named(RuffleNamedKey::Escape), + Key::Named(NamedKey::Pause) => LogicalKey::Named(RuffleNamedKey::Pause), + Key::Named(NamedKey::Play) => LogicalKey::Named(RuffleNamedKey::Play), + Key::Named(NamedKey::Select) => LogicalKey::Named(RuffleNamedKey::Select), + Key::Named(NamedKey::ZoomIn) => LogicalKey::Named(RuffleNamedKey::ZoomIn), + Key::Named(NamedKey::ZoomOut) => LogicalKey::Named(RuffleNamedKey::ZoomOut), + Key::Named(NamedKey::PrintScreen) => LogicalKey::Named(RuffleNamedKey::PrintScreen), + Key::Named(NamedKey::F1) => LogicalKey::Named(RuffleNamedKey::F1), + Key::Named(NamedKey::F2) => LogicalKey::Named(RuffleNamedKey::F2), + Key::Named(NamedKey::F3) => LogicalKey::Named(RuffleNamedKey::F3), + Key::Named(NamedKey::F4) => LogicalKey::Named(RuffleNamedKey::F4), + Key::Named(NamedKey::F5) => LogicalKey::Named(RuffleNamedKey::F5), + Key::Named(NamedKey::F6) => LogicalKey::Named(RuffleNamedKey::F6), + Key::Named(NamedKey::F7) => LogicalKey::Named(RuffleNamedKey::F7), + Key::Named(NamedKey::F8) => LogicalKey::Named(RuffleNamedKey::F8), + Key::Named(NamedKey::F9) => LogicalKey::Named(RuffleNamedKey::F9), + Key::Named(NamedKey::F10) => LogicalKey::Named(RuffleNamedKey::F10), + Key::Named(NamedKey::F11) => LogicalKey::Named(RuffleNamedKey::F11), + Key::Named(NamedKey::F12) => LogicalKey::Named(RuffleNamedKey::F12), + Key::Named(NamedKey::F13) => LogicalKey::Named(RuffleNamedKey::F13), + Key::Named(NamedKey::F14) => LogicalKey::Named(RuffleNamedKey::F14), + Key::Named(NamedKey::F15) => LogicalKey::Named(RuffleNamedKey::F15), + Key::Named(NamedKey::F16) => LogicalKey::Named(RuffleNamedKey::F16), + Key::Named(NamedKey::F17) => LogicalKey::Named(RuffleNamedKey::F17), + Key::Named(NamedKey::F18) => LogicalKey::Named(RuffleNamedKey::F18), + Key::Named(NamedKey::F19) => LogicalKey::Named(RuffleNamedKey::F19), + Key::Named(NamedKey::F20) => LogicalKey::Named(RuffleNamedKey::F20), + Key::Named(NamedKey::F21) => LogicalKey::Named(RuffleNamedKey::F21), + Key::Named(NamedKey::F22) => LogicalKey::Named(RuffleNamedKey::F22), + Key::Named(NamedKey::F23) => LogicalKey::Named(RuffleNamedKey::F23), + Key::Named(NamedKey::F24) => LogicalKey::Named(RuffleNamedKey::F24), + Key::Named(NamedKey::F25) => LogicalKey::Named(RuffleNamedKey::F25), + Key::Named(NamedKey::F26) => LogicalKey::Named(RuffleNamedKey::F26), + Key::Named(NamedKey::F27) => LogicalKey::Named(RuffleNamedKey::F27), + Key::Named(NamedKey::F28) => LogicalKey::Named(RuffleNamedKey::F28), + Key::Named(NamedKey::F29) => LogicalKey::Named(RuffleNamedKey::F29), + Key::Named(NamedKey::F30) => LogicalKey::Named(RuffleNamedKey::F30), + Key::Named(NamedKey::F31) => LogicalKey::Named(RuffleNamedKey::F31), + Key::Named(NamedKey::F32) => LogicalKey::Named(RuffleNamedKey::F32), + Key::Named(NamedKey::F33) => LogicalKey::Named(RuffleNamedKey::F33), + Key::Named(NamedKey::F34) => LogicalKey::Named(RuffleNamedKey::F34), + Key::Named(NamedKey::F35) => LogicalKey::Named(RuffleNamedKey::F35), + Key::Character(ch) => { // Handle alphabetic characters - alpha_to_ruffle_key_code(char).unwrap_or(KeyCode::UNKNOWN) + alpha_to_logical(ch) } - _ => KeyCode::UNKNOWN, - }; - Some(key_code) + _ => LogicalKey::Unknown, + } } -fn alpha_to_ruffle_key_code(char: &str) -> Option { - let char = char.chars().next()?; - - if char.is_ascii_alphabetic() { - // ASCII alphabetic characters are all mapped to - // their respective KeyCodes, which happen to have - // the same numerical value as uppercase characters. - return Some(KeyCode::from_code(char.to_ascii_uppercase() as u32)); +fn alpha_to_logical(ch: &str) -> LogicalKey { + // TODO What if we get multiple chars? + if let Some(ch) = ch.chars().last() { + LogicalKey::Character(ch) + } else { + LogicalKey::Unknown } +} - if !char.is_ascii() { - // Non-ASCII inputs have codes equal to their Unicode codes and yes, - // they overlap with other codes, so that typing '½' and '-' both produce 189. - return Some(KeyCode::from_code(char as u32)); +fn map_key_location(event: &KeyEvent) -> KeyLocation { + match event.location { + WinitKeyLocation::Standard => KeyLocation::Standard, + WinitKeyLocation::Left => KeyLocation::Left, + WinitKeyLocation::Right => KeyLocation::Right, + WinitKeyLocation::Numpad => KeyLocation::Numpad, } - - None } pub fn gilrs_button_to_gamepad_button(button: Button) -> Option { diff --git a/tests/framework/src/runner.rs b/tests/framework/src/runner.rs index bb4a7eeae46f9..dafd7ecf36008 100644 --- a/tests/framework/src/runner.rs +++ b/tests/framework/src/runner.rs @@ -9,7 +9,10 @@ use anyhow::{anyhow, Error, Result}; use image::ImageFormat; use pretty_assertions::Comparison; use ruffle_core::backend::navigator::NullExecutor; -use ruffle_core::events::{KeyCode, TextControlCode as RuffleTextControlCode}; +use ruffle_core::events::{ + KeyDescriptor, KeyLocation, LogicalKey, NamedKey, PhysicalKey, + TextControlCode as RuffleTextControlCode, +}; use ruffle_core::events::{MouseButton as RuffleMouseButton, MouseWheelDelta}; use ruffle_core::limits::ExecutionLimit; use ruffle_core::tag_utils::SwfMovie; @@ -236,12 +239,10 @@ impl TestRunner { }, }, AutomatedEvent::KeyDown { key } => PlayerEvent::KeyDown { - key_code: automated_key_to_key_code(*key), - key_char: None, + key: automated_key_to_descriptor(*key), }, AutomatedEvent::KeyUp { key } => PlayerEvent::KeyUp { - key_code: automated_key_to_key_code(*key), - key_char: None, + key: automated_key_to_descriptor(*key), }, AutomatedEvent::TextInput { codepoint } => PlayerEvent::TextInput { codepoint: *codepoint, @@ -575,45 +576,78 @@ fn assert_text_matches(ruffle: &str, flash: &str) -> Result<()> { } } -fn automated_key_to_key_code(automated_key: AutomatedKey) -> KeyCode { - match automated_key { - AutomatedKey::Char(ch) => KeyCode::from_code(ch.to_ascii_uppercase() as u32), - AutomatedKey::Numpad(ch) => match ch { - '0' => KeyCode::NUMPAD_0, - '1' => KeyCode::NUMPAD_1, - '2' => KeyCode::NUMPAD_2, - '3' => KeyCode::NUMPAD_3, - '4' => KeyCode::NUMPAD_4, - '5' => KeyCode::NUMPAD_5, - '6' => KeyCode::NUMPAD_6, - '7' => KeyCode::NUMPAD_7, - '8' => KeyCode::NUMPAD_8, - '9' => KeyCode::NUMPAD_9, - '*' => KeyCode::NUMPAD_MULTIPLY, - '+' => KeyCode::NUMPAD_ADD, - '-' => KeyCode::NUMPAD_SUBTRACT, - '.' | ',' => KeyCode::NUMPAD_DECIMAL, - '/' => KeyCode::NUMPAD_DIVIDE, - ch => panic!("Unknown numpad key: {}", ch), - }, - AutomatedKey::ArrowDown => KeyCode::DOWN, - AutomatedKey::ArrowLeft => KeyCode::LEFT, - AutomatedKey::ArrowRight => KeyCode::RIGHT, - AutomatedKey::ArrowUp => KeyCode::UP, - AutomatedKey::Backspace => KeyCode::BACKSPACE, - AutomatedKey::CapsLock => KeyCode::CAPS_LOCK, - AutomatedKey::Control => KeyCode::CONTROL, - AutomatedKey::Delete => KeyCode::DELETE, - AutomatedKey::End => KeyCode::END, - AutomatedKey::Enter => KeyCode::ENTER, - AutomatedKey::Escape => KeyCode::ESCAPE, - AutomatedKey::Home => KeyCode::HOME, - AutomatedKey::Insert => KeyCode::INSERT, - AutomatedKey::PageDown => KeyCode::PAGE_DOWN, - AutomatedKey::PageUp => KeyCode::PAGE_UP, - AutomatedKey::Shift => KeyCode::SHIFT, - AutomatedKey::Space => KeyCode::SPACE, - AutomatedKey::Tab => KeyCode::TAB, - AutomatedKey::Unknown => KeyCode::UNKNOWN, +fn automated_key_to_descriptor(automated_key: AutomatedKey) -> KeyDescriptor { + let logical_key = match automated_key { + AutomatedKey::Char(ch) | AutomatedKey::Numpad(ch) => LogicalKey::Character(ch), + AutomatedKey::ArrowDown => LogicalKey::Named(NamedKey::ArrowDown), + AutomatedKey::ArrowLeft => LogicalKey::Named(NamedKey::ArrowLeft), + AutomatedKey::ArrowRight => LogicalKey::Named(NamedKey::ArrowRight), + AutomatedKey::ArrowUp => LogicalKey::Named(NamedKey::ArrowUp), + AutomatedKey::Backspace => LogicalKey::Named(NamedKey::Backspace), + AutomatedKey::CapsLock => LogicalKey::Named(NamedKey::CapsLock), + AutomatedKey::Delete => LogicalKey::Named(NamedKey::Delete), + AutomatedKey::End => LogicalKey::Named(NamedKey::End), + AutomatedKey::Enter => LogicalKey::Named(NamedKey::Enter), + AutomatedKey::Escape => LogicalKey::Named(NamedKey::Escape), + AutomatedKey::F1 => LogicalKey::Named(NamedKey::F1), + AutomatedKey::F2 => LogicalKey::Named(NamedKey::F2), + AutomatedKey::F3 => LogicalKey::Named(NamedKey::F3), + AutomatedKey::F4 => LogicalKey::Named(NamedKey::F4), + AutomatedKey::F5 => LogicalKey::Named(NamedKey::F5), + AutomatedKey::F6 => LogicalKey::Named(NamedKey::F6), + AutomatedKey::F7 => LogicalKey::Named(NamedKey::F7), + AutomatedKey::F8 => LogicalKey::Named(NamedKey::F8), + AutomatedKey::F9 => LogicalKey::Named(NamedKey::F9), + AutomatedKey::Home => LogicalKey::Named(NamedKey::Home), + AutomatedKey::Insert => LogicalKey::Named(NamedKey::Insert), + AutomatedKey::LeftAlt => LogicalKey::Named(NamedKey::Alt), + AutomatedKey::LeftControl => LogicalKey::Named(NamedKey::Control), + AutomatedKey::LeftShift => LogicalKey::Named(NamedKey::Shift), + AutomatedKey::NumLock => LogicalKey::Named(NamedKey::NumLock), + AutomatedKey::NumpadDelete => LogicalKey::Named(NamedKey::Delete), + AutomatedKey::NumpadDown => LogicalKey::Named(NamedKey::ArrowDown), + AutomatedKey::NumpadEnd => LogicalKey::Named(NamedKey::End), + AutomatedKey::NumpadHome => LogicalKey::Named(NamedKey::Home), + AutomatedKey::NumpadInsert => LogicalKey::Named(NamedKey::Insert), + AutomatedKey::NumpadLeft => LogicalKey::Named(NamedKey::ArrowLeft), + AutomatedKey::NumpadPageDown => LogicalKey::Named(NamedKey::PageDown), + AutomatedKey::NumpadPageUp => LogicalKey::Named(NamedKey::PageUp), + AutomatedKey::NumpadRight => LogicalKey::Named(NamedKey::ArrowRight), + AutomatedKey::NumpadUp => LogicalKey::Named(NamedKey::ArrowUp), + AutomatedKey::PageDown => LogicalKey::Named(NamedKey::PageDown), + AutomatedKey::PageUp => LogicalKey::Named(NamedKey::PageUp), + AutomatedKey::Pause => LogicalKey::Named(NamedKey::Pause), + AutomatedKey::RightControl => LogicalKey::Named(NamedKey::Control), + AutomatedKey::RightShift => LogicalKey::Named(NamedKey::Shift), + AutomatedKey::ScrollLock => LogicalKey::Named(NamedKey::ScrollLock), + AutomatedKey::Space => LogicalKey::Character(' '), + AutomatedKey::Tab => LogicalKey::Named(NamedKey::Tab), + AutomatedKey::Unknown => LogicalKey::Unknown, + }; + let key_location = match automated_key { + AutomatedKey::Numpad(_) => KeyLocation::Numpad, + AutomatedKey::LeftAlt => KeyLocation::Left, + AutomatedKey::LeftControl => KeyLocation::Left, + AutomatedKey::LeftShift => KeyLocation::Left, + AutomatedKey::NumLock => KeyLocation::Numpad, + AutomatedKey::NumpadDelete => KeyLocation::Numpad, + AutomatedKey::NumpadDown => KeyLocation::Numpad, + AutomatedKey::NumpadEnd => KeyLocation::Numpad, + AutomatedKey::NumpadHome => KeyLocation::Numpad, + AutomatedKey::NumpadInsert => KeyLocation::Numpad, + AutomatedKey::NumpadLeft => KeyLocation::Numpad, + AutomatedKey::NumpadPageDown => KeyLocation::Numpad, + AutomatedKey::NumpadPageUp => KeyLocation::Numpad, + AutomatedKey::NumpadRight => KeyLocation::Numpad, + AutomatedKey::NumpadUp => KeyLocation::Numpad, + AutomatedKey::RightControl => KeyLocation::Right, + AutomatedKey::RightShift => KeyLocation::Right, + _ => KeyLocation::Standard, + }; + KeyDescriptor { + // We don't use physical keys in tests + physical_key: PhysicalKey::Unknown, + logical_key, + key_location, } } diff --git a/tests/input-format/src/format.rs b/tests/input-format/src/format.rs index aa13b3269f22e..21959bc5c8246 100644 --- a/tests/input-format/src/format.rs +++ b/tests/input-format/src/format.rs @@ -60,16 +60,41 @@ pub enum AutomatedKey { ArrowUp, Backspace, CapsLock, - Control, Delete, End, Enter, Escape, + F1, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, Home, Insert, + LeftAlt, + LeftControl, + LeftShift, + NumLock, + NumpadDelete, + NumpadDown, + NumpadEnd, + NumpadHome, + NumpadInsert, + NumpadLeft, + NumpadPageDown, + NumpadPageUp, + NumpadRight, + NumpadUp, PageDown, PageUp, - Shift, + Pause, + RightControl, + RightShift, + ScrollLock, Space, Tab, Unknown, diff --git a/tests/tests/swfs/avm1/key_isToggled/input.json b/tests/tests/swfs/avm1/key_isToggled/input.json index 46db3a16b6643..8530be4667022 100644 --- a/tests/tests/swfs/avm1/key_isToggled/input.json +++ b/tests/tests/swfs/avm1/key_isToggled/input.json @@ -30,6 +30,6 @@ }, { "type": "KeyDown", - "key": "Unknown" + "key": { "Char": "b" } } ] diff --git a/tests/tests/swfs/avm1/tab_ordering_reverse/input.json b/tests/tests/swfs/avm1/tab_ordering_reverse/input.json index 89758822c7940..848df1dd8fcc5 100644 --- a/tests/tests/swfs/avm1/tab_ordering_reverse/input.json +++ b/tests/tests/swfs/avm1/tab_ordering_reverse/input.json @@ -1,24 +1,24 @@ [ { "type": "KeyDown", "key": "Tab" }, { "type": "KeyDown", "key": "Tab" }, - { "type": "KeyDown", "key": "Shift" }, + { "type": "KeyDown", "key": "LeftShift" }, { "type": "KeyDown", "key": "Tab" }, - { "type": "KeyUp", "key": "Shift" }, + { "type": "KeyUp", "key": "LeftShift" }, { "type": "KeyDown", "key": "Tab" }, - { "type": "KeyDown", "key": "Shift" }, + { "type": "KeyDown", "key": "LeftShift" }, { "type": "KeyDown", "key": "Tab" }, { "type": "KeyDown", "key": "Tab" }, { "type": "KeyDown", "key": "Tab" }, - { "type": "KeyUp", "key": "Shift" }, + { "type": "KeyUp", "key": "LeftShift" }, { "type": "KeyDown", "key": "Tab" }, { "type": "KeyDown", "key": "Tab" }, - { "type": "KeyDown", "key": "Control" }, + { "type": "KeyDown", "key": "LeftControl" }, { "type": "KeyDown", "key": "Tab" }, - { "type": "KeyUp", "key": "Control" }, - { "type": "KeyDown", "key": "Shift" }, - { "type": "KeyDown", "key": "Control" }, + { "type": "KeyUp", "key": "LeftControl" }, + { "type": "KeyDown", "key": "LeftShift" }, + { "type": "KeyDown", "key": "LeftControl" }, { "type": "KeyDown", "key": "Tab" }, - { "type": "KeyUp", "key": "Control" }, - { "type": "KeyUp", "key": "Shift" }, + { "type": "KeyUp", "key": "LeftControl" }, + { "type": "KeyUp", "key": "LeftShift" }, { "type": "KeyDown", "key": "Tab" } ] diff --git a/tests/tests/swfs/avm2/edittext_paste_events/input.json b/tests/tests/swfs/avm2/edittext_paste_events/input.json index 5622e34c60e73..e75df82b1bd3b 100644 --- a/tests/tests/swfs/avm2/edittext_paste_events/input.json +++ b/tests/tests/swfs/avm2/edittext_paste_events/input.json @@ -1,8 +1,8 @@ [ { "type": "SetClipboardText", "text": "Test" }, - { "type": "KeyDown", "key": "Control" }, + { "type": "KeyDown", "key": "LeftControl" }, { "type": "TextControl", "code": "Paste" }, - { "type": "KeyUp", "key": "Control" }, + { "type": "KeyUp", "key": "LeftControl" }, { "type": "KeyDown", "key": { "Char": "x" } }, { "type": "TextInput", "codepoint": "x" }, { "type": "KeyUp", "key": { "Char": "x" } }, diff --git a/tests/tests/swfs/avm2/edittext_paste_maxchars/input.json b/tests/tests/swfs/avm2/edittext_paste_maxchars/input.json index c251ace490451..69d1c5fa280c3 100644 --- a/tests/tests/swfs/avm2/edittext_paste_maxchars/input.json +++ b/tests/tests/swfs/avm2/edittext_paste_maxchars/input.json @@ -1,7 +1,7 @@ [ { "type": "SetClipboardText", "text": "a\nb" }, - { "type": "KeyDown", "key": "Control" }, + { "type": "KeyDown", "key": "LeftControl" }, { "type": "TextControl", "code": "Paste" }, - { "type": "KeyUp", "key": "Control" }, + { "type": "KeyUp", "key": "LeftControl" }, { "type": "Wait" } ] diff --git a/tests/tests/swfs/avm2/edittext_paste_restrict/input.json b/tests/tests/swfs/avm2/edittext_paste_restrict/input.json index 74ff0f356a4e4..14f9d05ef1e93 100644 --- a/tests/tests/swfs/avm2/edittext_paste_restrict/input.json +++ b/tests/tests/swfs/avm2/edittext_paste_restrict/input.json @@ -1,12 +1,12 @@ [ { "type": "SetClipboardText", "text": "abc" }, - { "type": "KeyDown", "key": "Control" }, + { "type": "KeyDown", "key": "LeftControl" }, { "type": "TextControl", "code": "Paste" }, - { "type": "KeyUp", "key": "Control" }, + { "type": "KeyUp", "key": "LeftControl" }, { "type": "SetClipboardText", "text": "ayb" }, - { "type": "KeyDown", "key": "Control" }, + { "type": "KeyDown", "key": "LeftControl" }, { "type": "TextControl", "code": "Paste" }, - { "type": "KeyUp", "key": "Control" }, + { "type": "KeyUp", "key": "LeftControl" }, { "type": "KeyDown", "key": { "Char": "x" } }, { "type": "TextInput", "codepoint": "x" }, { "type": "KeyUp", "key": { "Char": "x" } }, diff --git a/tests/tests/swfs/avm2/edittext_restrict_events/input.json b/tests/tests/swfs/avm2/edittext_restrict_events/input.json index fb44d7b9ff845..8fd92b28390a5 100644 --- a/tests/tests/swfs/avm2/edittext_restrict_events/input.json +++ b/tests/tests/swfs/avm2/edittext_restrict_events/input.json @@ -1,21 +1,21 @@ [ { "type": "SetClipboardText", "text": "text" }, - { "type": "KeyDown", "key": "Control" }, + { "type": "KeyDown", "key": "LeftControl" }, { "type": "TextControl", "code": "Paste" }, - { "type": "KeyUp", "key": "Control" }, + { "type": "KeyUp", "key": "LeftControl" }, { "type": "KeyDown", "key": { "Char": "y" } }, { "type": "TextInput", "codepoint": "y" }, { "type": "KeyUp", "key": { "Char": "y" } }, { "type": "KeyDown", "key": { "Char": "x" } }, { "type": "TextInput", "codepoint": "x" }, { "type": "KeyUp", "key": { "Char": "x" } }, - { "type": "KeyDown", "key": "Shift" }, + { "type": "KeyDown", "key": "LeftShift" }, { "type": "KeyDown", "key": { "Char": "X" } }, { "type": "TextInput", "codepoint": "X" }, { "type": "KeyUp", "key": { "Char": "X" } }, - { "type": "KeyUp", "key": "Shift" }, + { "type": "KeyUp", "key": "LeftShift" }, { "type": "SetClipboardText", "text": "xxxxx" }, - { "type": "KeyDown", "key": "Control" }, + { "type": "KeyDown", "key": "LeftControl" }, { "type": "TextControl", "code": "Paste" }, - { "type": "KeyUp", "key": "Control" } + { "type": "KeyUp", "key": "LeftControl" } ] diff --git a/tests/tests/swfs/avm2/key_input_80percent/Test.as b/tests/tests/swfs/avm2/key_input_80percent/Test.as new file mode 100644 index 0000000000000..9814e9bb3d1d7 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_80percent/Test.as @@ -0,0 +1,30 @@ +package { +import flash.display.*; +import flash.text.*; +import flash.text.engine.*; +import flash.events.*; +import flash.geom.*; +import flash.utils.getTimer; + +[SWF(frameRate="25")] +public class Test extends MovieClip { + public function Test() { + stage.addEventListener("keyDown", function(evt: KeyboardEvent): void { + trace("Key down:"); + printKey(evt); + }); + stage.addEventListener("keyUp", function(evt: KeyboardEvent): void { + trace("Key up:"); + printKey(evt); + }); + } + + private function printKey(evt: KeyboardEvent): void { + trace(" altKey: " + evt.altKey); + trace(" charCode: " + evt.charCode); + trace(" ctrlKey: " + evt.ctrlKey); + trace(" keyCode: " + evt.keyCode); + trace(" shiftKey: " + evt.shiftKey); + } +} +} diff --git a/tests/tests/swfs/avm2/key_input_80percent/input.json b/tests/tests/swfs/avm2/key_input_80percent/input.json new file mode 100644 index 0000000000000..ee55546c00a95 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_80percent/input.json @@ -0,0 +1,309 @@ +[ + { "type": "KeyDown", "key": "Escape" }, + { "type": "KeyUp", "key": "Escape" }, + { "type": "KeyDown", "key": "F1" }, + { "type": "KeyUp", "key": "F1" }, + { "type": "KeyDown", "key": "F2" }, + { "type": "KeyUp", "key": "F2" }, + { "type": "KeyDown", "key": "F3" }, + { "type": "KeyUp", "key": "F3" }, + { "type": "KeyDown", "key": "F4" }, + { "type": "KeyUp", "key": "F4" }, + { "type": "KeyDown", "key": "F5" }, + { "type": "KeyUp", "key": "F5" }, + { "type": "KeyDown", "key": "F6" }, + { "type": "KeyUp", "key": "F6" }, + { "type": "KeyDown", "key": "F7" }, + { "type": "KeyUp", "key": "F7" }, + { "type": "KeyDown", "key": "F8" }, + { "type": "KeyUp", "key": "F8" }, + { "type": "KeyDown", "key": "F9" }, + { "type": "KeyUp", "key": "F9" }, + { "type": "KeyDown", "key": "ScrollLock" }, + { "type": "KeyUp", "key": "ScrollLock" }, + { "type": "KeyDown", "key": "Pause" }, + { "type": "KeyUp", "key": "Pause" }, + { "type": "KeyDown", "key": { "Char": "`" } }, + { "type": "KeyUp", "key": { "Char": "`" } }, + { "type": "KeyDown", "key": { "Char": "1" } }, + { "type": "KeyUp", "key": { "Char": "1" } }, + { "type": "KeyDown", "key": { "Char": "2" } }, + { "type": "KeyUp", "key": { "Char": "2" } }, + { "type": "KeyDown", "key": { "Char": "3" } }, + { "type": "KeyUp", "key": { "Char": "3" } }, + { "type": "KeyDown", "key": { "Char": "4" } }, + { "type": "KeyUp", "key": { "Char": "4" } }, + { "type": "KeyDown", "key": { "Char": "5" } }, + { "type": "KeyUp", "key": { "Char": "5" } }, + { "type": "KeyDown", "key": { "Char": "6" } }, + { "type": "KeyUp", "key": { "Char": "6" } }, + { "type": "KeyDown", "key": { "Char": "7" } }, + { "type": "KeyUp", "key": { "Char": "7" } }, + { "type": "KeyDown", "key": { "Char": "8" } }, + { "type": "KeyUp", "key": { "Char": "8" } }, + { "type": "KeyDown", "key": { "Char": "9" } }, + { "type": "KeyUp", "key": { "Char": "9" } }, + { "type": "KeyDown", "key": { "Char": "0" } }, + { "type": "KeyUp", "key": { "Char": "0" } }, + { "type": "KeyDown", "key": { "Char": "-" } }, + { "type": "KeyUp", "key": { "Char": "-" } }, + { "type": "KeyDown", "key": { "Char": "=" } }, + { "type": "KeyUp", "key": { "Char": "=" } }, + { "type": "KeyDown", "key": "Backspace" }, + { "type": "KeyUp", "key": "Backspace" }, + { "type": "KeyDown", "key": "Insert" }, + { "type": "KeyUp", "key": "Insert" }, + { "type": "KeyDown", "key": "Home" }, + { "type": "KeyUp", "key": "Home" }, + { "type": "KeyDown", "key": "PageUp" }, + { "type": "KeyUp", "key": "PageUp" }, + { "type": "KeyDown", "key": "Tab" }, + { "type": "KeyUp", "key": "Tab" }, + { "type": "KeyDown", "key": { "Char": "q" } }, + { "type": "KeyUp", "key": { "Char": "q" } }, + { "type": "KeyDown", "key": { "Char": "w" } }, + { "type": "KeyUp", "key": { "Char": "w" } }, + { "type": "KeyDown", "key": { "Char": "e" } }, + { "type": "KeyUp", "key": { "Char": "e" } }, + { "type": "KeyDown", "key": { "Char": "r" } }, + { "type": "KeyUp", "key": { "Char": "r" } }, + { "type": "KeyDown", "key": { "Char": "t" } }, + { "type": "KeyUp", "key": { "Char": "t" } }, + { "type": "KeyDown", "key": { "Char": "y" } }, + { "type": "KeyUp", "key": { "Char": "y" } }, + { "type": "KeyDown", "key": { "Char": "u" } }, + { "type": "KeyUp", "key": { "Char": "u" } }, + { "type": "KeyDown", "key": { "Char": "i" } }, + { "type": "KeyUp", "key": { "Char": "i" } }, + { "type": "KeyDown", "key": { "Char": "o" } }, + { "type": "KeyUp", "key": { "Char": "o" } }, + { "type": "KeyDown", "key": { "Char": "p" } }, + { "type": "KeyUp", "key": { "Char": "p" } }, + { "type": "KeyDown", "key": { "Char": "[" } }, + { "type": "KeyUp", "key": { "Char": "[" } }, + { "type": "KeyDown", "key": { "Char": "]" } }, + { "type": "KeyUp", "key": { "Char": "]" } }, + { "type": "KeyDown", "key": { "Char": "\\" } }, + { "type": "KeyUp", "key": { "Char": "\\" } }, + { "type": "KeyDown", "key": "Delete" }, + { "type": "KeyUp", "key": "Delete" }, + { "type": "KeyDown", "key": "End" }, + { "type": "KeyUp", "key": "End" }, + { "type": "KeyDown", "key": "PageDown" }, + { "type": "KeyUp", "key": "PageDown" }, + { "type": "KeyDown", "key": { "Char": "a" } }, + { "type": "KeyUp", "key": { "Char": "a" } }, + { "type": "KeyDown", "key": { "Char": "s" } }, + { "type": "KeyUp", "key": { "Char": "s" } }, + { "type": "KeyDown", "key": { "Char": "d" } }, + { "type": "KeyUp", "key": { "Char": "d" } }, + { "type": "KeyDown", "key": { "Char": "f" } }, + { "type": "KeyUp", "key": { "Char": "f" } }, + { "type": "KeyDown", "key": { "Char": "g" } }, + { "type": "KeyUp", "key": { "Char": "g" } }, + { "type": "KeyDown", "key": { "Char": "h" } }, + { "type": "KeyUp", "key": { "Char": "h" } }, + { "type": "KeyDown", "key": { "Char": "j" } }, + { "type": "KeyUp", "key": { "Char": "j" } }, + { "type": "KeyDown", "key": { "Char": "k" } }, + { "type": "KeyUp", "key": { "Char": "k" } }, + { "type": "KeyDown", "key": { "Char": "l" } }, + { "type": "KeyUp", "key": { "Char": "l" } }, + { "type": "KeyDown", "key": { "Char": ";" } }, + { "type": "KeyUp", "key": { "Char": ";" } }, + { "type": "KeyDown", "key": { "Char": "'" } }, + { "type": "KeyUp", "key": { "Char": "'" } }, + { "type": "KeyDown", "key": "Enter" }, + { "type": "KeyUp", "key": "Enter" }, + { "type": "KeyDown", "key": "LeftShift" }, + { "type": "KeyUp", "key": "LeftShift" }, + { "type": "KeyDown", "key": { "Char": "z" } }, + { "type": "KeyUp", "key": { "Char": "z" } }, + { "type": "KeyDown", "key": { "Char": "x" } }, + { "type": "KeyUp", "key": { "Char": "x" } }, + { "type": "KeyDown", "key": { "Char": "c" } }, + { "type": "KeyUp", "key": { "Char": "c" } }, + { "type": "KeyDown", "key": { "Char": "v" } }, + { "type": "KeyUp", "key": { "Char": "v" } }, + { "type": "KeyDown", "key": { "Char": "b" } }, + { "type": "KeyUp", "key": { "Char": "b" } }, + { "type": "KeyDown", "key": { "Char": "n" } }, + { "type": "KeyUp", "key": { "Char": "n" } }, + { "type": "KeyDown", "key": { "Char": "m" } }, + { "type": "KeyUp", "key": { "Char": "m" } }, + { "type": "KeyDown", "key": { "Char": "," } }, + { "type": "KeyUp", "key": { "Char": "," } }, + { "type": "KeyDown", "key": { "Char": "." } }, + { "type": "KeyUp", "key": { "Char": "." } }, + { "type": "KeyDown", "key": { "Char": "/" } }, + { "type": "KeyUp", "key": { "Char": "/" } }, + { "type": "KeyDown", "key": "RightShift" }, + { "type": "KeyUp", "key": "RightShift" }, + { "type": "KeyDown", "key": "ArrowUp" }, + { "type": "KeyUp", "key": "ArrowUp" }, + { "type": "KeyDown", "key": "LeftControl" }, + { "type": "KeyUp", "key": "LeftControl" }, + { "type": "KeyDown", "key": "LeftAlt" }, + { "type": "KeyUp", "key": "LeftAlt" }, + { "type": "KeyDown", "key": { "Char": " " } }, + { "type": "KeyUp", "key": { "Char": " " } }, + { "type": "KeyDown", "key": "RightControl" }, + { "type": "KeyUp", "key": "RightControl" }, + { "type": "KeyDown", "key": "ArrowLeft" }, + { "type": "KeyUp", "key": "ArrowLeft" }, + { "type": "KeyDown", "key": "ArrowDown" }, + { "type": "KeyUp", "key": "ArrowDown" }, + { "type": "KeyDown", "key": "ArrowRight" }, + { "type": "KeyUp", "key": "ArrowRight" }, + + { "type": "Wait" }, + + { "type": "KeyDown", "key": "LeftShift" }, + { "type": "KeyDown", "key": "Escape" }, + { "type": "KeyUp", "key": "Escape" }, + { "type": "KeyDown", "key": "F1" }, + { "type": "KeyUp", "key": "F1" }, + { "type": "KeyDown", "key": "F2" }, + { "type": "KeyUp", "key": "F2" }, + { "type": "KeyDown", "key": "F3" }, + { "type": "KeyUp", "key": "F3" }, + { "type": "KeyDown", "key": "F4" }, + { "type": "KeyUp", "key": "F4" }, + { "type": "KeyDown", "key": "F5" }, + { "type": "KeyUp", "key": "F5" }, + { "type": "KeyDown", "key": "F6" }, + { "type": "KeyUp", "key": "F6" }, + { "type": "KeyDown", "key": "F7" }, + { "type": "KeyUp", "key": "F7" }, + { "type": "KeyDown", "key": "F8" }, + { "type": "KeyUp", "key": "F8" }, + { "type": "KeyDown", "key": "F9" }, + { "type": "KeyUp", "key": "F9" }, + { "type": "KeyDown", "key": "ScrollLock" }, + { "type": "KeyUp", "key": "ScrollLock" }, + { "type": "KeyDown", "key": "Pause" }, + { "type": "KeyUp", "key": "Pause" }, + { "type": "KeyDown", "key": { "Char": "~" } }, + { "type": "KeyUp", "key": { "Char": "~" } }, + { "type": "KeyDown", "key": { "Char": "!" } }, + { "type": "KeyUp", "key": { "Char": "!" } }, + { "type": "KeyDown", "key": { "Char": "@" } }, + { "type": "KeyUp", "key": { "Char": "@" } }, + { "type": "KeyDown", "key": { "Char": "#" } }, + { "type": "KeyUp", "key": { "Char": "#" } }, + { "type": "KeyDown", "key": { "Char": "$" } }, + { "type": "KeyUp", "key": { "Char": "$" } }, + { "type": "KeyDown", "key": { "Char": "%" } }, + { "type": "KeyUp", "key": { "Char": "%" } }, + { "type": "KeyDown", "key": { "Char": "^" } }, + { "type": "KeyUp", "key": { "Char": "^" } }, + { "type": "KeyDown", "key": { "Char": "&" } }, + { "type": "KeyUp", "key": { "Char": "&" } }, + { "type": "KeyDown", "key": { "Char": "*" } }, + { "type": "KeyUp", "key": { "Char": "*" } }, + { "type": "KeyDown", "key": { "Char": "(" } }, + { "type": "KeyUp", "key": { "Char": "(" } }, + { "type": "KeyDown", "key": { "Char": ")" } }, + { "type": "KeyUp", "key": { "Char": ")" } }, + { "type": "KeyDown", "key": { "Char": "_" } }, + { "type": "KeyUp", "key": { "Char": "_" } }, + { "type": "KeyDown", "key": { "Char": "+" } }, + { "type": "KeyUp", "key": { "Char": "+" } }, + { "type": "KeyDown", "key": "Backspace" }, + { "type": "KeyUp", "key": "Backspace" }, + { "type": "KeyDown", "key": "Insert" }, + { "type": "KeyUp", "key": "Insert" }, + { "type": "KeyDown", "key": "Home" }, + { "type": "KeyUp", "key": "Home" }, + { "type": "KeyDown", "key": "PageUp" }, + { "type": "KeyUp", "key": "PageUp" }, + { "type": "KeyDown", "key": "Tab" }, + { "type": "KeyUp", "key": "Tab" }, + { "type": "KeyDown", "key": { "Char": "Q" } }, + { "type": "KeyUp", "key": { "Char": "Q" } }, + { "type": "KeyDown", "key": { "Char": "W" } }, + { "type": "KeyUp", "key": { "Char": "W" } }, + { "type": "KeyDown", "key": { "Char": "E" } }, + { "type": "KeyUp", "key": { "Char": "E" } }, + { "type": "KeyDown", "key": { "Char": "R" } }, + { "type": "KeyUp", "key": { "Char": "R" } }, + { "type": "KeyDown", "key": { "Char": "T" } }, + { "type": "KeyUp", "key": { "Char": "T" } }, + { "type": "KeyDown", "key": { "Char": "Y" } }, + { "type": "KeyUp", "key": { "Char": "Y" } }, + { "type": "KeyDown", "key": { "Char": "U" } }, + { "type": "KeyUp", "key": { "Char": "U" } }, + { "type": "KeyDown", "key": { "Char": "I" } }, + { "type": "KeyUp", "key": { "Char": "I" } }, + { "type": "KeyDown", "key": { "Char": "O" } }, + { "type": "KeyUp", "key": { "Char": "O" } }, + { "type": "KeyDown", "key": { "Char": "P" } }, + { "type": "KeyUp", "key": { "Char": "P" } }, + { "type": "KeyDown", "key": { "Char": "{" } }, + { "type": "KeyUp", "key": { "Char": "{" } }, + { "type": "KeyDown", "key": { "Char": "}" } }, + { "type": "KeyUp", "key": { "Char": "}" } }, + { "type": "KeyDown", "key": { "Char": "|" } }, + { "type": "KeyUp", "key": { "Char": "|" } }, + { "type": "KeyDown", "key": "Delete" }, + { "type": "KeyUp", "key": "Delete" }, + { "type": "KeyDown", "key": "End" }, + { "type": "KeyUp", "key": "End" }, + { "type": "KeyDown", "key": "PageDown" }, + { "type": "KeyUp", "key": "PageDown" }, + { "type": "KeyDown", "key": { "Char": "A" } }, + { "type": "KeyUp", "key": { "Char": "A" } }, + { "type": "KeyDown", "key": { "Char": "S" } }, + { "type": "KeyUp", "key": { "Char": "S" } }, + { "type": "KeyDown", "key": { "Char": "D" } }, + { "type": "KeyUp", "key": { "Char": "D" } }, + { "type": "KeyDown", "key": { "Char": "F" } }, + { "type": "KeyUp", "key": { "Char": "F" } }, + { "type": "KeyDown", "key": { "Char": "G" } }, + { "type": "KeyUp", "key": { "Char": "G" } }, + { "type": "KeyDown", "key": { "Char": "H" } }, + { "type": "KeyUp", "key": { "Char": "H" } }, + { "type": "KeyDown", "key": { "Char": "J" } }, + { "type": "KeyUp", "key": { "Char": "J" } }, + { "type": "KeyDown", "key": { "Char": "K" } }, + { "type": "KeyUp", "key": { "Char": "K" } }, + { "type": "KeyDown", "key": { "Char": "L" } }, + { "type": "KeyUp", "key": { "Char": "L" } }, + { "type": "KeyDown", "key": { "Char": ":" } }, + { "type": "KeyUp", "key": { "Char": ":" } }, + { "type": "KeyDown", "key": { "Char": "\"" } }, + { "type": "KeyUp", "key": { "Char": "\"" } }, + { "type": "KeyDown", "key": "Enter" }, + { "type": "KeyUp", "key": "Enter" }, + { "type": "KeyDown", "key": { "Char": "Z" } }, + { "type": "KeyUp", "key": { "Char": "Z" } }, + { "type": "KeyDown", "key": { "Char": "X" } }, + { "type": "KeyUp", "key": { "Char": "X" } }, + { "type": "KeyDown", "key": { "Char": "C" } }, + { "type": "KeyUp", "key": { "Char": "C" } }, + { "type": "KeyDown", "key": { "Char": "V" } }, + { "type": "KeyUp", "key": { "Char": "V" } }, + { "type": "KeyDown", "key": { "Char": "B" } }, + { "type": "KeyUp", "key": { "Char": "B" } }, + { "type": "KeyDown", "key": { "Char": "N" } }, + { "type": "KeyUp", "key": { "Char": "N" } }, + { "type": "KeyDown", "key": { "Char": "M" } }, + { "type": "KeyUp", "key": { "Char": "M" } }, + { "type": "KeyDown", "key": { "Char": "<" } }, + { "type": "KeyUp", "key": { "Char": "<" } }, + { "type": "KeyDown", "key": { "Char": ">" } }, + { "type": "KeyUp", "key": { "Char": ">" } }, + { "type": "KeyDown", "key": { "Char": "?" } }, + { "type": "KeyUp", "key": { "Char": "?" } }, + { "type": "KeyDown", "key": "ArrowUp" }, + { "type": "KeyUp", "key": "ArrowUp" }, + { "type": "KeyDown", "key": "ArrowLeft" }, + { "type": "KeyUp", "key": "ArrowLeft" }, + { "type": "KeyDown", "key": "ArrowDown" }, + { "type": "KeyUp", "key": "ArrowDown" }, + { "type": "KeyDown", "key": "ArrowRight" }, + { "type": "KeyUp", "key": "ArrowRight" }, + { "type": "KeyUp", "key": "LeftShift" }, + + { "type": "Wait" } +] diff --git a/tests/tests/swfs/avm2/key_input_80percent/output.txt b/tests/tests/swfs/avm2/key_input_80percent/output.txt new file mode 100644 index 0000000000000..1969ebe90f3cf --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_80percent/output.txt @@ -0,0 +1,1812 @@ +Key down: + altKey: false + charCode: 27 + ctrlKey: false + keyCode: 27 + shiftKey: false +Key up: + altKey: false + charCode: 27 + ctrlKey: false + keyCode: 27 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 112 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 112 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 113 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 113 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 114 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 114 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 115 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 115 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 116 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 116 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 117 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 117 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 118 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 118 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 119 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 119 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 120 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 120 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 145 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 145 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 19 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 19 + shiftKey: false +Key down: + altKey: false + charCode: 96 + ctrlKey: false + keyCode: 192 + shiftKey: false +Key up: + altKey: false + charCode: 96 + ctrlKey: false + keyCode: 192 + shiftKey: false +Key down: + altKey: false + charCode: 49 + ctrlKey: false + keyCode: 49 + shiftKey: false +Key up: + altKey: false + charCode: 49 + ctrlKey: false + keyCode: 49 + shiftKey: false +Key down: + altKey: false + charCode: 50 + ctrlKey: false + keyCode: 50 + shiftKey: false +Key up: + altKey: false + charCode: 50 + ctrlKey: false + keyCode: 50 + shiftKey: false +Key down: + altKey: false + charCode: 51 + ctrlKey: false + keyCode: 51 + shiftKey: false +Key up: + altKey: false + charCode: 51 + ctrlKey: false + keyCode: 51 + shiftKey: false +Key down: + altKey: false + charCode: 52 + ctrlKey: false + keyCode: 52 + shiftKey: false +Key up: + altKey: false + charCode: 52 + ctrlKey: false + keyCode: 52 + shiftKey: false +Key down: + altKey: false + charCode: 53 + ctrlKey: false + keyCode: 53 + shiftKey: false +Key up: + altKey: false + charCode: 53 + ctrlKey: false + keyCode: 53 + shiftKey: false +Key down: + altKey: false + charCode: 54 + ctrlKey: false + keyCode: 54 + shiftKey: false +Key up: + altKey: false + charCode: 54 + ctrlKey: false + keyCode: 54 + shiftKey: false +Key down: + altKey: false + charCode: 55 + ctrlKey: false + keyCode: 55 + shiftKey: false +Key up: + altKey: false + charCode: 55 + ctrlKey: false + keyCode: 55 + shiftKey: false +Key down: + altKey: false + charCode: 56 + ctrlKey: false + keyCode: 56 + shiftKey: false +Key up: + altKey: false + charCode: 56 + ctrlKey: false + keyCode: 56 + shiftKey: false +Key down: + altKey: false + charCode: 57 + ctrlKey: false + keyCode: 57 + shiftKey: false +Key up: + altKey: false + charCode: 57 + ctrlKey: false + keyCode: 57 + shiftKey: false +Key down: + altKey: false + charCode: 48 + ctrlKey: false + keyCode: 48 + shiftKey: false +Key up: + altKey: false + charCode: 48 + ctrlKey: false + keyCode: 48 + shiftKey: false +Key down: + altKey: false + charCode: 45 + ctrlKey: false + keyCode: 189 + shiftKey: false +Key up: + altKey: false + charCode: 45 + ctrlKey: false + keyCode: 189 + shiftKey: false +Key down: + altKey: false + charCode: 61 + ctrlKey: false + keyCode: 187 + shiftKey: false +Key up: + altKey: false + charCode: 61 + ctrlKey: false + keyCode: 187 + shiftKey: false +Key down: + altKey: false + charCode: 8 + ctrlKey: false + keyCode: 8 + shiftKey: false +Key up: + altKey: false + charCode: 8 + ctrlKey: false + keyCode: 8 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 45 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 45 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 36 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 36 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 33 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 33 + shiftKey: false +Key down: + altKey: false + charCode: 9 + ctrlKey: false + keyCode: 9 + shiftKey: false +Key up: + altKey: false + charCode: 9 + ctrlKey: false + keyCode: 9 + shiftKey: false +Key down: + altKey: false + charCode: 113 + ctrlKey: false + keyCode: 81 + shiftKey: false +Key up: + altKey: false + charCode: 113 + ctrlKey: false + keyCode: 81 + shiftKey: false +Key down: + altKey: false + charCode: 119 + ctrlKey: false + keyCode: 87 + shiftKey: false +Key up: + altKey: false + charCode: 119 + ctrlKey: false + keyCode: 87 + shiftKey: false +Key down: + altKey: false + charCode: 101 + ctrlKey: false + keyCode: 69 + shiftKey: false +Key up: + altKey: false + charCode: 101 + ctrlKey: false + keyCode: 69 + shiftKey: false +Key down: + altKey: false + charCode: 114 + ctrlKey: false + keyCode: 82 + shiftKey: false +Key up: + altKey: false + charCode: 114 + ctrlKey: false + keyCode: 82 + shiftKey: false +Key down: + altKey: false + charCode: 116 + ctrlKey: false + keyCode: 84 + shiftKey: false +Key up: + altKey: false + charCode: 116 + ctrlKey: false + keyCode: 84 + shiftKey: false +Key down: + altKey: false + charCode: 121 + ctrlKey: false + keyCode: 89 + shiftKey: false +Key up: + altKey: false + charCode: 121 + ctrlKey: false + keyCode: 89 + shiftKey: false +Key down: + altKey: false + charCode: 117 + ctrlKey: false + keyCode: 85 + shiftKey: false +Key up: + altKey: false + charCode: 117 + ctrlKey: false + keyCode: 85 + shiftKey: false +Key down: + altKey: false + charCode: 105 + ctrlKey: false + keyCode: 73 + shiftKey: false +Key up: + altKey: false + charCode: 105 + ctrlKey: false + keyCode: 73 + shiftKey: false +Key down: + altKey: false + charCode: 111 + ctrlKey: false + keyCode: 79 + shiftKey: false +Key up: + altKey: false + charCode: 111 + ctrlKey: false + keyCode: 79 + shiftKey: false +Key down: + altKey: false + charCode: 112 + ctrlKey: false + keyCode: 80 + shiftKey: false +Key up: + altKey: false + charCode: 112 + ctrlKey: false + keyCode: 80 + shiftKey: false +Key down: + altKey: false + charCode: 91 + ctrlKey: false + keyCode: 219 + shiftKey: false +Key up: + altKey: false + charCode: 91 + ctrlKey: false + keyCode: 219 + shiftKey: false +Key down: + altKey: false + charCode: 93 + ctrlKey: false + keyCode: 221 + shiftKey: false +Key up: + altKey: false + charCode: 93 + ctrlKey: false + keyCode: 221 + shiftKey: false +Key down: + altKey: false + charCode: 92 + ctrlKey: false + keyCode: 220 + shiftKey: false +Key up: + altKey: false + charCode: 92 + ctrlKey: false + keyCode: 220 + shiftKey: false +Key down: + altKey: false + charCode: 127 + ctrlKey: false + keyCode: 46 + shiftKey: false +Key up: + altKey: false + charCode: 127 + ctrlKey: false + keyCode: 46 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 35 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 35 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 34 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 34 + shiftKey: false +Key down: + altKey: false + charCode: 97 + ctrlKey: false + keyCode: 65 + shiftKey: false +Key up: + altKey: false + charCode: 97 + ctrlKey: false + keyCode: 65 + shiftKey: false +Key down: + altKey: false + charCode: 115 + ctrlKey: false + keyCode: 83 + shiftKey: false +Key up: + altKey: false + charCode: 115 + ctrlKey: false + keyCode: 83 + shiftKey: false +Key down: + altKey: false + charCode: 100 + ctrlKey: false + keyCode: 68 + shiftKey: false +Key up: + altKey: false + charCode: 100 + ctrlKey: false + keyCode: 68 + shiftKey: false +Key down: + altKey: false + charCode: 102 + ctrlKey: false + keyCode: 70 + shiftKey: false +Key up: + altKey: false + charCode: 102 + ctrlKey: false + keyCode: 70 + shiftKey: false +Key down: + altKey: false + charCode: 103 + ctrlKey: false + keyCode: 71 + shiftKey: false +Key up: + altKey: false + charCode: 103 + ctrlKey: false + keyCode: 71 + shiftKey: false +Key down: + altKey: false + charCode: 104 + ctrlKey: false + keyCode: 72 + shiftKey: false +Key up: + altKey: false + charCode: 104 + ctrlKey: false + keyCode: 72 + shiftKey: false +Key down: + altKey: false + charCode: 106 + ctrlKey: false + keyCode: 74 + shiftKey: false +Key up: + altKey: false + charCode: 106 + ctrlKey: false + keyCode: 74 + shiftKey: false +Key down: + altKey: false + charCode: 107 + ctrlKey: false + keyCode: 75 + shiftKey: false +Key up: + altKey: false + charCode: 107 + ctrlKey: false + keyCode: 75 + shiftKey: false +Key down: + altKey: false + charCode: 108 + ctrlKey: false + keyCode: 76 + shiftKey: false +Key up: + altKey: false + charCode: 108 + ctrlKey: false + keyCode: 76 + shiftKey: false +Key down: + altKey: false + charCode: 59 + ctrlKey: false + keyCode: 186 + shiftKey: false +Key up: + altKey: false + charCode: 59 + ctrlKey: false + keyCode: 186 + shiftKey: false +Key down: + altKey: false + charCode: 39 + ctrlKey: false + keyCode: 222 + shiftKey: false +Key up: + altKey: false + charCode: 39 + ctrlKey: false + keyCode: 222 + shiftKey: false +Key down: + altKey: false + charCode: 13 + ctrlKey: false + keyCode: 13 + shiftKey: false +Key up: + altKey: false + charCode: 13 + ctrlKey: false + keyCode: 13 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + shiftKey: false +Key down: + altKey: false + charCode: 122 + ctrlKey: false + keyCode: 90 + shiftKey: false +Key up: + altKey: false + charCode: 122 + ctrlKey: false + keyCode: 90 + shiftKey: false +Key down: + altKey: false + charCode: 120 + ctrlKey: false + keyCode: 88 + shiftKey: false +Key up: + altKey: false + charCode: 120 + ctrlKey: false + keyCode: 88 + shiftKey: false +Key down: + altKey: false + charCode: 99 + ctrlKey: false + keyCode: 67 + shiftKey: false +Key up: + altKey: false + charCode: 99 + ctrlKey: false + keyCode: 67 + shiftKey: false +Key down: + altKey: false + charCode: 118 + ctrlKey: false + keyCode: 86 + shiftKey: false +Key up: + altKey: false + charCode: 118 + ctrlKey: false + keyCode: 86 + shiftKey: false +Key down: + altKey: false + charCode: 98 + ctrlKey: false + keyCode: 66 + shiftKey: false +Key up: + altKey: false + charCode: 98 + ctrlKey: false + keyCode: 66 + shiftKey: false +Key down: + altKey: false + charCode: 110 + ctrlKey: false + keyCode: 78 + shiftKey: false +Key up: + altKey: false + charCode: 110 + ctrlKey: false + keyCode: 78 + shiftKey: false +Key down: + altKey: false + charCode: 109 + ctrlKey: false + keyCode: 77 + shiftKey: false +Key up: + altKey: false + charCode: 109 + ctrlKey: false + keyCode: 77 + shiftKey: false +Key down: + altKey: false + charCode: 44 + ctrlKey: false + keyCode: 188 + shiftKey: false +Key up: + altKey: false + charCode: 44 + ctrlKey: false + keyCode: 188 + shiftKey: false +Key down: + altKey: false + charCode: 46 + ctrlKey: false + keyCode: 190 + shiftKey: false +Key up: + altKey: false + charCode: 46 + ctrlKey: false + keyCode: 190 + shiftKey: false +Key down: + altKey: false + charCode: 47 + ctrlKey: false + keyCode: 191 + shiftKey: false +Key up: + altKey: false + charCode: 47 + ctrlKey: false + keyCode: 191 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 38 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 38 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: true + keyCode: 17 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 17 + shiftKey: false +Key down: + altKey: true + charCode: 0 + ctrlKey: false + keyCode: 18 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 18 + shiftKey: false +Key down: + altKey: false + charCode: 32 + ctrlKey: false + keyCode: 32 + shiftKey: false +Key up: + altKey: false + charCode: 32 + ctrlKey: false + keyCode: 32 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: true + keyCode: 17 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 17 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 37 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 37 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 40 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 40 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 39 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 39 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + shiftKey: true +Key down: + altKey: false + charCode: 27 + ctrlKey: false + keyCode: 27 + shiftKey: true +Key up: + altKey: false + charCode: 27 + ctrlKey: false + keyCode: 27 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 112 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 112 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 113 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 113 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 114 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 114 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 115 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 115 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 116 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 116 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 117 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 117 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 118 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 118 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 119 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 119 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 120 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 120 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 145 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 145 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 19 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 19 + shiftKey: true +Key down: + altKey: false + charCode: 126 + ctrlKey: false + keyCode: 192 + shiftKey: true +Key up: + altKey: false + charCode: 126 + ctrlKey: false + keyCode: 192 + shiftKey: true +Key down: + altKey: false + charCode: 33 + ctrlKey: false + keyCode: 49 + shiftKey: true +Key up: + altKey: false + charCode: 33 + ctrlKey: false + keyCode: 49 + shiftKey: true +Key down: + altKey: false + charCode: 64 + ctrlKey: false + keyCode: 50 + shiftKey: true +Key up: + altKey: false + charCode: 64 + ctrlKey: false + keyCode: 50 + shiftKey: true +Key down: + altKey: false + charCode: 35 + ctrlKey: false + keyCode: 51 + shiftKey: true +Key up: + altKey: false + charCode: 35 + ctrlKey: false + keyCode: 51 + shiftKey: true +Key down: + altKey: false + charCode: 36 + ctrlKey: false + keyCode: 52 + shiftKey: true +Key up: + altKey: false + charCode: 36 + ctrlKey: false + keyCode: 52 + shiftKey: true +Key down: + altKey: false + charCode: 37 + ctrlKey: false + keyCode: 53 + shiftKey: true +Key up: + altKey: false + charCode: 37 + ctrlKey: false + keyCode: 53 + shiftKey: true +Key down: + altKey: false + charCode: 94 + ctrlKey: false + keyCode: 54 + shiftKey: true +Key up: + altKey: false + charCode: 94 + ctrlKey: false + keyCode: 54 + shiftKey: true +Key down: + altKey: false + charCode: 38 + ctrlKey: false + keyCode: 55 + shiftKey: true +Key up: + altKey: false + charCode: 38 + ctrlKey: false + keyCode: 55 + shiftKey: true +Key down: + altKey: false + charCode: 42 + ctrlKey: false + keyCode: 56 + shiftKey: true +Key up: + altKey: false + charCode: 42 + ctrlKey: false + keyCode: 56 + shiftKey: true +Key down: + altKey: false + charCode: 40 + ctrlKey: false + keyCode: 57 + shiftKey: true +Key up: + altKey: false + charCode: 40 + ctrlKey: false + keyCode: 57 + shiftKey: true +Key down: + altKey: false + charCode: 41 + ctrlKey: false + keyCode: 48 + shiftKey: true +Key up: + altKey: false + charCode: 41 + ctrlKey: false + keyCode: 48 + shiftKey: true +Key down: + altKey: false + charCode: 95 + ctrlKey: false + keyCode: 189 + shiftKey: true +Key up: + altKey: false + charCode: 95 + ctrlKey: false + keyCode: 189 + shiftKey: true +Key down: + altKey: false + charCode: 43 + ctrlKey: false + keyCode: 187 + shiftKey: true +Key up: + altKey: false + charCode: 43 + ctrlKey: false + keyCode: 187 + shiftKey: true +Key down: + altKey: false + charCode: 8 + ctrlKey: false + keyCode: 8 + shiftKey: true +Key up: + altKey: false + charCode: 8 + ctrlKey: false + keyCode: 8 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 45 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 45 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 36 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 36 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 33 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 33 + shiftKey: true +Key down: + altKey: false + charCode: 9 + ctrlKey: false + keyCode: 9 + shiftKey: true +Key up: + altKey: false + charCode: 9 + ctrlKey: false + keyCode: 9 + shiftKey: true +Key down: + altKey: false + charCode: 81 + ctrlKey: false + keyCode: 81 + shiftKey: true +Key up: + altKey: false + charCode: 81 + ctrlKey: false + keyCode: 81 + shiftKey: true +Key down: + altKey: false + charCode: 87 + ctrlKey: false + keyCode: 87 + shiftKey: true +Key up: + altKey: false + charCode: 87 + ctrlKey: false + keyCode: 87 + shiftKey: true +Key down: + altKey: false + charCode: 69 + ctrlKey: false + keyCode: 69 + shiftKey: true +Key up: + altKey: false + charCode: 69 + ctrlKey: false + keyCode: 69 + shiftKey: true +Key down: + altKey: false + charCode: 82 + ctrlKey: false + keyCode: 82 + shiftKey: true +Key up: + altKey: false + charCode: 82 + ctrlKey: false + keyCode: 82 + shiftKey: true +Key down: + altKey: false + charCode: 84 + ctrlKey: false + keyCode: 84 + shiftKey: true +Key up: + altKey: false + charCode: 84 + ctrlKey: false + keyCode: 84 + shiftKey: true +Key down: + altKey: false + charCode: 89 + ctrlKey: false + keyCode: 89 + shiftKey: true +Key up: + altKey: false + charCode: 89 + ctrlKey: false + keyCode: 89 + shiftKey: true +Key down: + altKey: false + charCode: 85 + ctrlKey: false + keyCode: 85 + shiftKey: true +Key up: + altKey: false + charCode: 85 + ctrlKey: false + keyCode: 85 + shiftKey: true +Key down: + altKey: false + charCode: 73 + ctrlKey: false + keyCode: 73 + shiftKey: true +Key up: + altKey: false + charCode: 73 + ctrlKey: false + keyCode: 73 + shiftKey: true +Key down: + altKey: false + charCode: 79 + ctrlKey: false + keyCode: 79 + shiftKey: true +Key up: + altKey: false + charCode: 79 + ctrlKey: false + keyCode: 79 + shiftKey: true +Key down: + altKey: false + charCode: 80 + ctrlKey: false + keyCode: 80 + shiftKey: true +Key up: + altKey: false + charCode: 80 + ctrlKey: false + keyCode: 80 + shiftKey: true +Key down: + altKey: false + charCode: 123 + ctrlKey: false + keyCode: 219 + shiftKey: true +Key up: + altKey: false + charCode: 123 + ctrlKey: false + keyCode: 219 + shiftKey: true +Key down: + altKey: false + charCode: 125 + ctrlKey: false + keyCode: 221 + shiftKey: true +Key up: + altKey: false + charCode: 125 + ctrlKey: false + keyCode: 221 + shiftKey: true +Key down: + altKey: false + charCode: 124 + ctrlKey: false + keyCode: 220 + shiftKey: true +Key up: + altKey: false + charCode: 124 + ctrlKey: false + keyCode: 220 + shiftKey: true +Key down: + altKey: false + charCode: 127 + ctrlKey: false + keyCode: 46 + shiftKey: true +Key up: + altKey: false + charCode: 127 + ctrlKey: false + keyCode: 46 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 35 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 35 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 34 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 34 + shiftKey: true +Key down: + altKey: false + charCode: 65 + ctrlKey: false + keyCode: 65 + shiftKey: true +Key up: + altKey: false + charCode: 65 + ctrlKey: false + keyCode: 65 + shiftKey: true +Key down: + altKey: false + charCode: 83 + ctrlKey: false + keyCode: 83 + shiftKey: true +Key up: + altKey: false + charCode: 83 + ctrlKey: false + keyCode: 83 + shiftKey: true +Key down: + altKey: false + charCode: 68 + ctrlKey: false + keyCode: 68 + shiftKey: true +Key up: + altKey: false + charCode: 68 + ctrlKey: false + keyCode: 68 + shiftKey: true +Key down: + altKey: false + charCode: 70 + ctrlKey: false + keyCode: 70 + shiftKey: true +Key up: + altKey: false + charCode: 70 + ctrlKey: false + keyCode: 70 + shiftKey: true +Key down: + altKey: false + charCode: 71 + ctrlKey: false + keyCode: 71 + shiftKey: true +Key up: + altKey: false + charCode: 71 + ctrlKey: false + keyCode: 71 + shiftKey: true +Key down: + altKey: false + charCode: 72 + ctrlKey: false + keyCode: 72 + shiftKey: true +Key up: + altKey: false + charCode: 72 + ctrlKey: false + keyCode: 72 + shiftKey: true +Key down: + altKey: false + charCode: 74 + ctrlKey: false + keyCode: 74 + shiftKey: true +Key up: + altKey: false + charCode: 74 + ctrlKey: false + keyCode: 74 + shiftKey: true +Key down: + altKey: false + charCode: 75 + ctrlKey: false + keyCode: 75 + shiftKey: true +Key up: + altKey: false + charCode: 75 + ctrlKey: false + keyCode: 75 + shiftKey: true +Key down: + altKey: false + charCode: 76 + ctrlKey: false + keyCode: 76 + shiftKey: true +Key up: + altKey: false + charCode: 76 + ctrlKey: false + keyCode: 76 + shiftKey: true +Key down: + altKey: false + charCode: 58 + ctrlKey: false + keyCode: 186 + shiftKey: true +Key up: + altKey: false + charCode: 58 + ctrlKey: false + keyCode: 186 + shiftKey: true +Key down: + altKey: false + charCode: 34 + ctrlKey: false + keyCode: 222 + shiftKey: true +Key up: + altKey: false + charCode: 34 + ctrlKey: false + keyCode: 222 + shiftKey: true +Key down: + altKey: false + charCode: 13 + ctrlKey: false + keyCode: 13 + shiftKey: true +Key up: + altKey: false + charCode: 13 + ctrlKey: false + keyCode: 13 + shiftKey: true +Key down: + altKey: false + charCode: 90 + ctrlKey: false + keyCode: 90 + shiftKey: true +Key up: + altKey: false + charCode: 90 + ctrlKey: false + keyCode: 90 + shiftKey: true +Key down: + altKey: false + charCode: 88 + ctrlKey: false + keyCode: 88 + shiftKey: true +Key up: + altKey: false + charCode: 88 + ctrlKey: false + keyCode: 88 + shiftKey: true +Key down: + altKey: false + charCode: 67 + ctrlKey: false + keyCode: 67 + shiftKey: true +Key up: + altKey: false + charCode: 67 + ctrlKey: false + keyCode: 67 + shiftKey: true +Key down: + altKey: false + charCode: 86 + ctrlKey: false + keyCode: 86 + shiftKey: true +Key up: + altKey: false + charCode: 86 + ctrlKey: false + keyCode: 86 + shiftKey: true +Key down: + altKey: false + charCode: 66 + ctrlKey: false + keyCode: 66 + shiftKey: true +Key up: + altKey: false + charCode: 66 + ctrlKey: false + keyCode: 66 + shiftKey: true +Key down: + altKey: false + charCode: 78 + ctrlKey: false + keyCode: 78 + shiftKey: true +Key up: + altKey: false + charCode: 78 + ctrlKey: false + keyCode: 78 + shiftKey: true +Key down: + altKey: false + charCode: 77 + ctrlKey: false + keyCode: 77 + shiftKey: true +Key up: + altKey: false + charCode: 77 + ctrlKey: false + keyCode: 77 + shiftKey: true +Key down: + altKey: false + charCode: 60 + ctrlKey: false + keyCode: 188 + shiftKey: true +Key up: + altKey: false + charCode: 60 + ctrlKey: false + keyCode: 188 + shiftKey: true +Key down: + altKey: false + charCode: 62 + ctrlKey: false + keyCode: 190 + shiftKey: true +Key up: + altKey: false + charCode: 62 + ctrlKey: false + keyCode: 190 + shiftKey: true +Key down: + altKey: false + charCode: 63 + ctrlKey: false + keyCode: 191 + shiftKey: true +Key up: + altKey: false + charCode: 63 + ctrlKey: false + keyCode: 191 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 38 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 38 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 37 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 37 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 40 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 40 + shiftKey: true +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 39 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 39 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + shiftKey: false diff --git a/tests/tests/swfs/avm2/key_input_80percent/test.swf b/tests/tests/swfs/avm2/key_input_80percent/test.swf new file mode 100644 index 0000000000000..d7d2cb3edc5f5 Binary files /dev/null and b/tests/tests/swfs/avm2/key_input_80percent/test.swf differ diff --git a/tests/tests/swfs/avm2/key_input_80percent/test.toml b/tests/tests/swfs/avm2/key_input_80percent/test.toml new file mode 100644 index 0000000000000..7cfc6eecb6364 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_80percent/test.toml @@ -0,0 +1 @@ +num_ticks = 4 diff --git a/tests/tests/swfs/avm2/key_input_location/Test.as b/tests/tests/swfs/avm2/key_input_location/Test.as new file mode 100644 index 0000000000000..d014f4958dd56 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_location/Test.as @@ -0,0 +1,31 @@ +package { +import flash.display.*; +import flash.text.*; +import flash.text.engine.*; +import flash.events.*; +import flash.geom.*; +import flash.utils.getTimer; + +[SWF(frameRate="25")] +public class Test extends MovieClip { + public function Test() { + stage.addEventListener("keyDown", function(evt: KeyboardEvent): void { + trace("Key down:"); + printKey(evt); + }); + stage.addEventListener("keyUp", function(evt: KeyboardEvent): void { + trace("Key up:"); + printKey(evt); + }); + } + + private function printKey(evt: KeyboardEvent): void { + trace(" altKey: " + evt.altKey); + trace(" charCode: " + evt.charCode); + trace(" ctrlKey: " + evt.ctrlKey); + trace(" keyCode: " + evt.keyCode); + trace(" keyLocation: " + evt.keyLocation); + trace(" shiftKey: " + evt.shiftKey); + } +} +} diff --git a/tests/tests/swfs/avm2/key_input_location/input.json b/tests/tests/swfs/avm2/key_input_location/input.json new file mode 100644 index 0000000000000..893a814d1e031 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_location/input.json @@ -0,0 +1,23 @@ +[ + { "type": "KeyDown", "key": { "Char": "a" } }, + { "type": "KeyUp", "key": { "Char": "a" } }, + { "type": "KeyDown", "key": "LeftShift" }, + { "type": "KeyUp", "key": "LeftShift" }, + { "type": "KeyDown", "key": "RightShift" }, + { "type": "KeyUp", "key": "RightShift" }, + { "type": "KeyDown", "key": "LeftControl" }, + { "type": "KeyUp", "key": "LeftControl" }, + { "type": "KeyDown", "key": "RightControl" }, + { "type": "KeyUp", "key": "RightControl" }, + { "type": "KeyDown", "key": "LeftAlt" }, + { "type": "KeyUp", "key": "LeftAlt" }, + + { "type": "KeyDown", "key": { "Numpad": "1" } }, + { "type": "KeyUp", "key": { "Numpad": "1" } }, + { "type": "KeyDown", "key": "NumLock" }, + { "type": "KeyUp", "key": "NumLock" }, + { "type": "KeyDown", "key": "NumpadEnd" }, + { "type": "KeyUp", "key": "NumpadEnd" }, + + { "type": "Wait" } +] diff --git a/tests/tests/swfs/avm2/key_input_location/output.txt b/tests/tests/swfs/avm2/key_input_location/output.txt new file mode 100644 index 0000000000000..e2971f425626f --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_location/output.txt @@ -0,0 +1,126 @@ +Key down: + altKey: false + charCode: 97 + ctrlKey: false + keyCode: 65 + keyLocation: 0 + shiftKey: false +Key up: + altKey: false + charCode: 97 + ctrlKey: false + keyCode: 65 + keyLocation: 0 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + keyLocation: 1 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + keyLocation: 1 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + keyLocation: 2 + shiftKey: true +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 16 + keyLocation: 2 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: true + keyCode: 17 + keyLocation: 1 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 17 + keyLocation: 1 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: true + keyCode: 17 + keyLocation: 2 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 17 + keyLocation: 2 + shiftKey: false +Key down: + altKey: true + charCode: 0 + ctrlKey: false + keyCode: 18 + keyLocation: 1 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 18 + keyLocation: 1 + shiftKey: false +Key down: + altKey: false + charCode: 49 + ctrlKey: false + keyCode: 97 + keyLocation: 3 + shiftKey: false +Key up: + altKey: false + charCode: 49 + ctrlKey: false + keyCode: 97 + keyLocation: 3 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 144 + keyLocation: 0 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 144 + keyLocation: 0 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 35 + keyLocation: 3 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 35 + keyLocation: 3 + shiftKey: false diff --git a/tests/tests/swfs/avm2/key_input_location/test.swf b/tests/tests/swfs/avm2/key_input_location/test.swf new file mode 100644 index 0000000000000..b7b371714de00 Binary files /dev/null and b/tests/tests/swfs/avm2/key_input_location/test.swf differ diff --git a/tests/tests/swfs/avm2/key_input_location/test.toml b/tests/tests/swfs/avm2/key_input_location/test.toml new file mode 100644 index 0000000000000..cf6123969a1d6 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_location/test.toml @@ -0,0 +1 @@ +num_ticks = 1 diff --git a/tests/tests/swfs/avm2/key_input_numpad/Test.as b/tests/tests/swfs/avm2/key_input_numpad/Test.as new file mode 100644 index 0000000000000..9814e9bb3d1d7 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_numpad/Test.as @@ -0,0 +1,30 @@ +package { +import flash.display.*; +import flash.text.*; +import flash.text.engine.*; +import flash.events.*; +import flash.geom.*; +import flash.utils.getTimer; + +[SWF(frameRate="25")] +public class Test extends MovieClip { + public function Test() { + stage.addEventListener("keyDown", function(evt: KeyboardEvent): void { + trace("Key down:"); + printKey(evt); + }); + stage.addEventListener("keyUp", function(evt: KeyboardEvent): void { + trace("Key up:"); + printKey(evt); + }); + } + + private function printKey(evt: KeyboardEvent): void { + trace(" altKey: " + evt.altKey); + trace(" charCode: " + evt.charCode); + trace(" ctrlKey: " + evt.ctrlKey); + trace(" keyCode: " + evt.keyCode); + trace(" shiftKey: " + evt.shiftKey); + } +} +} diff --git a/tests/tests/swfs/avm2/key_input_numpad/input.json b/tests/tests/swfs/avm2/key_input_numpad/input.json new file mode 100644 index 0000000000000..f37f14a3ea031 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_numpad/input.json @@ -0,0 +1,75 @@ +[ + { "type": "KeyDown", "key": { "Numpad": "/" } }, + { "type": "KeyUp", "key": { "Numpad": "/" } }, + { "type": "KeyDown", "key": { "Numpad": "*" } }, + { "type": "KeyUp", "key": { "Numpad": "*" } }, + { "type": "KeyDown", "key": { "Numpad": "-" } }, + { "type": "KeyUp", "key": { "Numpad": "-" } }, + { "type": "KeyDown", "key": "NumpadHome" }, + { "type": "KeyUp", "key": "NumpadHome" }, + { "type": "KeyDown", "key": "NumpadUp" }, + { "type": "KeyUp", "key": "NumpadUp" }, + { "type": "KeyDown", "key": "NumpadPageUp" }, + { "type": "KeyUp", "key": "NumpadPageUp" }, + { "type": "KeyDown", "key": { "Numpad": "+" } }, + { "type": "KeyUp", "key": { "Numpad": "+" } }, + { "type": "KeyDown", "key": "NumpadLeft" }, + { "type": "KeyUp", "key": "NumpadLeft" }, + { "type": "KeyDown", "key": "NumpadRight" }, + { "type": "KeyUp", "key": "NumpadRight" }, + { "type": "KeyDown", "key": "NumpadEnd" }, + { "type": "KeyUp", "key": "NumpadEnd" }, + { "type": "KeyDown", "key": "NumpadDown" }, + { "type": "KeyUp", "key": "NumpadDown" }, + { "type": "KeyDown", "key": "NumpadPageDown" }, + { "type": "KeyUp", "key": "NumpadPageDown" }, + { "type": "KeyDown", "key": "Enter" }, + { "type": "KeyUp", "key": "Enter" }, + { "type": "KeyDown", "key": "NumpadInsert" }, + { "type": "KeyUp", "key": "NumpadInsert" }, + { "type": "KeyDown", "key": "NumpadDelete" }, + { "type": "KeyUp", "key": "NumpadDelete" }, + + { "type": "Wait" }, + + { "type": "KeyDown", "key": "NumLock" }, + { "type": "KeyUp", "key": "NumLock" }, + + { "type": "Wait" }, + + { "type": "KeyDown", "key": { "Numpad": "/" } }, + { "type": "KeyUp", "key": { "Numpad": "/" } }, + { "type": "KeyDown", "key": { "Numpad": "*" } }, + { "type": "KeyUp", "key": { "Numpad": "*" } }, + { "type": "KeyDown", "key": { "Numpad": "-" } }, + { "type": "KeyUp", "key": { "Numpad": "-" } }, + { "type": "KeyDown", "key": { "Numpad": "7" } }, + { "type": "KeyUp", "key": { "Numpad": "7" } }, + { "type": "KeyDown", "key": { "Numpad": "8" } }, + { "type": "KeyUp", "key": { "Numpad": "8" } }, + { "type": "KeyDown", "key": { "Numpad": "9" } }, + { "type": "KeyUp", "key": { "Numpad": "9" } }, + { "type": "KeyDown", "key": { "Numpad": "+" } }, + { "type": "KeyUp", "key": { "Numpad": "+" } }, + { "type": "KeyDown", "key": { "Numpad": "4" } }, + { "type": "KeyUp", "key": { "Numpad": "4" } }, + { "type": "KeyDown", "key": { "Numpad": "5" } }, + { "type": "KeyUp", "key": { "Numpad": "5" } }, + { "type": "KeyDown", "key": { "Numpad": "6" } }, + { "type": "KeyUp", "key": { "Numpad": "6" } }, + { "type": "KeyDown", "key": { "Numpad": "1" } }, + { "type": "KeyUp", "key": { "Numpad": "1" } }, + { "type": "KeyDown", "key": { "Numpad": "2" } }, + { "type": "KeyUp", "key": { "Numpad": "2" } }, + { "type": "KeyDown", "key": { "Numpad": "3" } }, + { "type": "KeyUp", "key": { "Numpad": "3" } }, + { "type": "KeyDown", "key": "Enter" }, + { "type": "KeyUp", "key": "Enter" }, + { "type": "KeyDown", "key": { "Numpad": "0" } }, + { "type": "KeyUp", "key": { "Numpad": "0" } }, + { "type": "KeyDown", "key": { "Numpad": "." } }, + { "type": "KeyUp", "key": { "Numpad": "." } }, + + + { "type": "Wait" } +] diff --git a/tests/tests/swfs/avm2/key_input_numpad/output.txt b/tests/tests/swfs/avm2/key_input_numpad/output.txt new file mode 100644 index 0000000000000..464b282c12750 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_numpad/output.txt @@ -0,0 +1,384 @@ +Key down: + altKey: false + charCode: 47 + ctrlKey: false + keyCode: 111 + shiftKey: false +Key up: + altKey: false + charCode: 47 + ctrlKey: false + keyCode: 111 + shiftKey: false +Key down: + altKey: false + charCode: 42 + ctrlKey: false + keyCode: 106 + shiftKey: false +Key up: + altKey: false + charCode: 42 + ctrlKey: false + keyCode: 106 + shiftKey: false +Key down: + altKey: false + charCode: 45 + ctrlKey: false + keyCode: 109 + shiftKey: false +Key up: + altKey: false + charCode: 45 + ctrlKey: false + keyCode: 109 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 36 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 36 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 38 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 38 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 33 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 33 + shiftKey: false +Key down: + altKey: false + charCode: 43 + ctrlKey: false + keyCode: 107 + shiftKey: false +Key up: + altKey: false + charCode: 43 + ctrlKey: false + keyCode: 107 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 37 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 37 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 39 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 39 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 35 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 35 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 40 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 40 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 34 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 34 + shiftKey: false +Key down: + altKey: false + charCode: 13 + ctrlKey: false + keyCode: 13 + shiftKey: false +Key up: + altKey: false + charCode: 13 + ctrlKey: false + keyCode: 13 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 45 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 45 + shiftKey: false +Key down: + altKey: false + charCode: 127 + ctrlKey: false + keyCode: 46 + shiftKey: false +Key up: + altKey: false + charCode: 127 + ctrlKey: false + keyCode: 46 + shiftKey: false +Key down: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 144 + shiftKey: false +Key up: + altKey: false + charCode: 0 + ctrlKey: false + keyCode: 144 + shiftKey: false +Key down: + altKey: false + charCode: 47 + ctrlKey: false + keyCode: 111 + shiftKey: false +Key up: + altKey: false + charCode: 47 + ctrlKey: false + keyCode: 111 + shiftKey: false +Key down: + altKey: false + charCode: 42 + ctrlKey: false + keyCode: 106 + shiftKey: false +Key up: + altKey: false + charCode: 42 + ctrlKey: false + keyCode: 106 + shiftKey: false +Key down: + altKey: false + charCode: 45 + ctrlKey: false + keyCode: 109 + shiftKey: false +Key up: + altKey: false + charCode: 45 + ctrlKey: false + keyCode: 109 + shiftKey: false +Key down: + altKey: false + charCode: 55 + ctrlKey: false + keyCode: 103 + shiftKey: false +Key up: + altKey: false + charCode: 55 + ctrlKey: false + keyCode: 103 + shiftKey: false +Key down: + altKey: false + charCode: 56 + ctrlKey: false + keyCode: 104 + shiftKey: false +Key up: + altKey: false + charCode: 56 + ctrlKey: false + keyCode: 104 + shiftKey: false +Key down: + altKey: false + charCode: 57 + ctrlKey: false + keyCode: 105 + shiftKey: false +Key up: + altKey: false + charCode: 57 + ctrlKey: false + keyCode: 105 + shiftKey: false +Key down: + altKey: false + charCode: 43 + ctrlKey: false + keyCode: 107 + shiftKey: false +Key up: + altKey: false + charCode: 43 + ctrlKey: false + keyCode: 107 + shiftKey: false +Key down: + altKey: false + charCode: 52 + ctrlKey: false + keyCode: 100 + shiftKey: false +Key up: + altKey: false + charCode: 52 + ctrlKey: false + keyCode: 100 + shiftKey: false +Key down: + altKey: false + charCode: 53 + ctrlKey: false + keyCode: 101 + shiftKey: false +Key up: + altKey: false + charCode: 53 + ctrlKey: false + keyCode: 101 + shiftKey: false +Key down: + altKey: false + charCode: 54 + ctrlKey: false + keyCode: 102 + shiftKey: false +Key up: + altKey: false + charCode: 54 + ctrlKey: false + keyCode: 102 + shiftKey: false +Key down: + altKey: false + charCode: 49 + ctrlKey: false + keyCode: 97 + shiftKey: false +Key up: + altKey: false + charCode: 49 + ctrlKey: false + keyCode: 97 + shiftKey: false +Key down: + altKey: false + charCode: 50 + ctrlKey: false + keyCode: 98 + shiftKey: false +Key up: + altKey: false + charCode: 50 + ctrlKey: false + keyCode: 98 + shiftKey: false +Key down: + altKey: false + charCode: 51 + ctrlKey: false + keyCode: 99 + shiftKey: false +Key up: + altKey: false + charCode: 51 + ctrlKey: false + keyCode: 99 + shiftKey: false +Key down: + altKey: false + charCode: 13 + ctrlKey: false + keyCode: 13 + shiftKey: false +Key up: + altKey: false + charCode: 13 + ctrlKey: false + keyCode: 13 + shiftKey: false +Key down: + altKey: false + charCode: 48 + ctrlKey: false + keyCode: 96 + shiftKey: false +Key up: + altKey: false + charCode: 48 + ctrlKey: false + keyCode: 96 + shiftKey: false +Key down: + altKey: false + charCode: 46 + ctrlKey: false + keyCode: 110 + shiftKey: false +Key up: + altKey: false + charCode: 46 + ctrlKey: false + keyCode: 110 + shiftKey: false diff --git a/tests/tests/swfs/avm2/key_input_numpad/test.swf b/tests/tests/swfs/avm2/key_input_numpad/test.swf new file mode 100644 index 0000000000000..d2b0f2b90ed0b Binary files /dev/null and b/tests/tests/swfs/avm2/key_input_numpad/test.swf differ diff --git a/tests/tests/swfs/avm2/key_input_numpad/test.toml b/tests/tests/swfs/avm2/key_input_numpad/test.toml new file mode 100644 index 0000000000000..7cfc6eecb6364 --- /dev/null +++ b/tests/tests/swfs/avm2/key_input_numpad/test.toml @@ -0,0 +1 @@ +num_ticks = 4 diff --git a/web/src/input.rs b/web/src/input.rs index 0666ac5785a64..01e9cd8c391e9 100644 --- a/web/src/input.rs +++ b/web/src/input.rs @@ -1,145 +1,268 @@ -use ruffle_core::events::{KeyCode, TextControlCode}; +use ruffle_core::events::{ + KeyDescriptor, KeyLocation, LogicalKey, NamedKey, PhysicalKey, TextControlCode, +}; +use web_sys::KeyboardEvent; -/// Convert a web `KeyboardEvent.code` value into a Ruffle `KeyCode`. -/// Return `KeyCode::Unknown` if there is no matching Flash key code. -pub fn web_to_ruffle_key_code(key_code: &str) -> KeyCode { +pub fn web_input_to_ruffle_key_descriptor(event: &KeyboardEvent) -> KeyDescriptor { + let physical_key = map_physical_key(&event.code()); + let logical_key = map_logical_key(&event.key()); + let key_location = map_key_location(event.location()); + KeyDescriptor { + physical_key, + logical_key, + key_location, + } +} + +/// Convert a web `KeyboardEvent.code` value into a Ruffle `PhysicalKey`. +fn map_physical_key(key_code: &str) -> PhysicalKey { match key_code { - "Backspace" => KeyCode::BACKSPACE, - "Tab" => KeyCode::TAB, - "Enter" => KeyCode::ENTER, - "ShiftLeft" | "ShiftRight" => KeyCode::SHIFT, - "ControlLeft" | "ControlRight" => KeyCode::CONTROL, - "AltLeft" | "AltRight" => KeyCode::ALT, - "CapsLock" => KeyCode::CAPS_LOCK, - "Escape" => KeyCode::ESCAPE, - "Space" => KeyCode::SPACE, - "Digit0" => KeyCode::NUMBER_0, - "Digit1" => KeyCode::NUMBER_1, - "Digit2" => KeyCode::NUMBER_2, - "Digit3" => KeyCode::NUMBER_3, - "Digit4" => KeyCode::NUMBER_4, - "Digit5" => KeyCode::NUMBER_5, - "Digit6" => KeyCode::NUMBER_6, - "Digit7" => KeyCode::NUMBER_7, - "Digit8" => KeyCode::NUMBER_8, - "Digit9" => KeyCode::NUMBER_9, - "KeyA" => KeyCode::A, - "KeyB" => KeyCode::B, - "KeyC" => KeyCode::C, - "KeyD" => KeyCode::D, - "KeyE" => KeyCode::E, - "KeyF" => KeyCode::F, - "KeyG" => KeyCode::G, - "KeyH" => KeyCode::H, - "KeyI" => KeyCode::I, - "KeyJ" => KeyCode::J, - "KeyK" => KeyCode::K, - "KeyL" => KeyCode::L, - "KeyM" => KeyCode::M, - "KeyN" => KeyCode::N, - "KeyO" => KeyCode::O, - "KeyP" => KeyCode::P, - "KeyQ" => KeyCode::Q, - "KeyR" => KeyCode::R, - "KeyS" => KeyCode::S, - "KeyT" => KeyCode::T, - "KeyU" => KeyCode::U, - "KeyV" => KeyCode::V, - "KeyW" => KeyCode::W, - "KeyX" => KeyCode::X, - "KeyY" => KeyCode::Y, - "KeyZ" => KeyCode::Z, - "Semicolon" => KeyCode::SEMICOLON, - "Equal" => KeyCode::EQUAL, - "Comma" => KeyCode::COMMA, - "Minus" => KeyCode::MINUS, - "Period" => KeyCode::PERIOD, - "Slash" => KeyCode::SLASH, - "Backquote" => KeyCode::BACKQUOTE, - "BracketLeft" => KeyCode::LEFTBRACKET, - "Backslash" => KeyCode::BACKSLASH, - "BracketRight" => KeyCode::RIGHTBRACKET, - "Quote" => KeyCode::QUOTE, - "Numpad0" => KeyCode::NUMPAD_0, - "Numpad1" => KeyCode::NUMPAD_1, - "Numpad2" => KeyCode::NUMPAD_2, - "Numpad3" => KeyCode::NUMPAD_3, - "Numpad4" => KeyCode::NUMPAD_4, - "Numpad5" => KeyCode::NUMPAD_5, - "Numpad6" => KeyCode::NUMPAD_6, - "Numpad7" => KeyCode::NUMPAD_7, - "Numpad8" => KeyCode::NUMPAD_8, - "Numpad9" => KeyCode::NUMPAD_9, - "NumpadMultiply" => KeyCode::NUMPAD_MULTIPLY, - "NumpadAdd" => KeyCode::NUMPAD_ADD, - "NumpadSubtract" => KeyCode::NUMPAD_SUBTRACT, - "NumpadDecimal" => KeyCode::NUMPAD_DECIMAL, - "NumpadDivide" => KeyCode::NUMPAD_DIVIDE, - "NumpadEnter" => KeyCode::ENTER, - "PageUp" => KeyCode::PAGE_UP, - "PageDown" => KeyCode::PAGE_DOWN, - "End" => KeyCode::END, - "Home" => KeyCode::HOME, - "ArrowLeft" => KeyCode::LEFT, - "ArrowUp" => KeyCode::UP, - "ArrowRight" => KeyCode::RIGHT, - "ArrowDown" => KeyCode::DOWN, - "Insert" => KeyCode::INSERT, - "Delete" => KeyCode::DELETE, - "Pause" => KeyCode::PAUSE, - "NumLock" => KeyCode::NUM_LOCK, - "ScrollLock" => KeyCode::SCROLL_LOCK, - "F1" => KeyCode::F1, - "F2" => KeyCode::F2, - "F3" => KeyCode::F3, - "F4" => KeyCode::F4, - "F5" => KeyCode::F5, - "F6" => KeyCode::F6, - "F7" => KeyCode::F7, - "F8" => KeyCode::F8, - "F9" => KeyCode::F9, - "F10" => KeyCode::F10, - "F11" => KeyCode::F11, - "F12" => KeyCode::F12, - "F13" => KeyCode::F13, - "F14" => KeyCode::F14, - "F15" => KeyCode::F15, - "F16" => KeyCode::F16, - "F17" => KeyCode::F17, - "F18" => KeyCode::F18, - "F19" => KeyCode::F19, - "F20" => KeyCode::F20, - "F21" => KeyCode::F21, - "F22" => KeyCode::F22, - "F23" => KeyCode::F23, - "F24" => KeyCode::F24, - _ => KeyCode::UNKNOWN, + "Backquote" => PhysicalKey::Backquote, + "Digit0" => PhysicalKey::Digit0, + "Digit1" => PhysicalKey::Digit1, + "Digit2" => PhysicalKey::Digit2, + "Digit4" => PhysicalKey::Digit4, + "Digit3" => PhysicalKey::Digit3, + "Digit5" => PhysicalKey::Digit5, + "Digit6" => PhysicalKey::Digit6, + "Digit7" => PhysicalKey::Digit7, + "Digit8" => PhysicalKey::Digit8, + "Digit9" => PhysicalKey::Digit9, + "Minus" => PhysicalKey::Minus, + "Equal" => PhysicalKey::Equal, + "IntlYen" => PhysicalKey::IntlYen, + "KeyQ" => PhysicalKey::KeyQ, + "KeyW" => PhysicalKey::KeyW, + "KeyE" => PhysicalKey::KeyE, + "KeyR" => PhysicalKey::KeyR, + "KeyT" => PhysicalKey::KeyT, + "KeyY" => PhysicalKey::KeyY, + "KeyU" => PhysicalKey::KeyU, + "KeyI" => PhysicalKey::KeyI, + "KeyO" => PhysicalKey::KeyO, + "KeyP" => PhysicalKey::KeyP, + "KeyA" => PhysicalKey::KeyA, + "KeyS" => PhysicalKey::KeyS, + "KeyD" => PhysicalKey::KeyD, + "KeyF" => PhysicalKey::KeyF, + "KeyG" => PhysicalKey::KeyG, + "KeyH" => PhysicalKey::KeyH, + "KeyJ" => PhysicalKey::KeyJ, + "KeyK" => PhysicalKey::KeyK, + "KeyL" => PhysicalKey::KeyL, + "KeyZ" => PhysicalKey::KeyZ, + "KeyX" => PhysicalKey::KeyX, + "KeyC" => PhysicalKey::KeyC, + "KeyV" => PhysicalKey::KeyV, + "KeyB" => PhysicalKey::KeyB, + "KeyN" => PhysicalKey::KeyN, + "KeyM" => PhysicalKey::KeyM, + "BracketLeft" => PhysicalKey::BracketLeft, + "BracketRight" => PhysicalKey::BracketRight, + "Backslash" => PhysicalKey::Backslash, + "Semicolon" => PhysicalKey::Semicolon, + "Quote" => PhysicalKey::Quote, + "IntlBackslash" => PhysicalKey::IntlBackslash, + "Comma" => PhysicalKey::Comma, + "Period" => PhysicalKey::Period, + "Slash" => PhysicalKey::Slash, + "IntlRo" => PhysicalKey::IntlRo, + "Backspace" => PhysicalKey::Backspace, + "Tab" => PhysicalKey::Tab, + "CapsLock" => PhysicalKey::CapsLock, + "Enter" => PhysicalKey::Enter, + "ShiftLeft" => PhysicalKey::ShiftLeft, + "ShiftRight" => PhysicalKey::ShiftRight, + "ControlLeft" => PhysicalKey::ControlLeft, + "SuperLeft" => PhysicalKey::SuperLeft, + "AltLeft" => PhysicalKey::AltLeft, + "Space" => PhysicalKey::Space, + "AltRight" => PhysicalKey::AltRight, + "SuperRight" => PhysicalKey::SuperRight, + "ContextMenu" => PhysicalKey::ContextMenu, + "ControlRight" => PhysicalKey::ControlRight, + "Insert" => PhysicalKey::Insert, + "Delete" => PhysicalKey::Delete, + "Home" => PhysicalKey::Home, + "End" => PhysicalKey::End, + "PageUp" => PhysicalKey::PageUp, + "PageDown" => PhysicalKey::PageDown, + "ArrowUp" => PhysicalKey::ArrowUp, + "ArrowLeft" => PhysicalKey::ArrowLeft, + "ArrowDown" => PhysicalKey::ArrowDown, + "ArrowRight" => PhysicalKey::ArrowRight, + "NumLock" => PhysicalKey::NumLock, + "NumpadDivide" => PhysicalKey::NumpadDivide, + "NumpadMultiply" => PhysicalKey::NumpadMultiply, + "NumpadSubtract" => PhysicalKey::NumpadSubtract, + "Numpad7" => PhysicalKey::Numpad7, + "Numpad8" => PhysicalKey::Numpad8, + "Numpad9" => PhysicalKey::Numpad9, + "Numpad4" => PhysicalKey::Numpad4, + "Numpad5" => PhysicalKey::Numpad5, + "Numpad6" => PhysicalKey::Numpad6, + "Numpad1" => PhysicalKey::Numpad1, + "Numpad2" => PhysicalKey::Numpad2, + "Numpad3" => PhysicalKey::Numpad3, + "Numpad0" => PhysicalKey::Numpad0, + "NumpadAdd" => PhysicalKey::NumpadAdd, + "NumpadComma" => PhysicalKey::NumpadComma, + "NumpadEnter" => PhysicalKey::NumpadEnter, + "NumpadDecimal" => PhysicalKey::NumpadDecimal, + "Escape" => PhysicalKey::Escape, + "F1" => PhysicalKey::F1, + "F2" => PhysicalKey::F2, + "F3" => PhysicalKey::F3, + "F4" => PhysicalKey::F4, + "F5" => PhysicalKey::F5, + "F6" => PhysicalKey::F6, + "F7" => PhysicalKey::F7, + "F8" => PhysicalKey::F8, + "F9" => PhysicalKey::F9, + "F10" => PhysicalKey::F10, + "F11" => PhysicalKey::F11, + "F12" => PhysicalKey::F12, + "F13" => PhysicalKey::F13, + "F14" => PhysicalKey::F14, + "F15" => PhysicalKey::F15, + "F16" => PhysicalKey::F16, + "F17" => PhysicalKey::F17, + "F18" => PhysicalKey::F18, + "F19" => PhysicalKey::F19, + "F20" => PhysicalKey::F20, + "F21" => PhysicalKey::F21, + "F22" => PhysicalKey::F22, + "F23" => PhysicalKey::F23, + "F24" => PhysicalKey::F24, + "F25" => PhysicalKey::F25, + "F26" => PhysicalKey::F26, + "F27" => PhysicalKey::F27, + "F28" => PhysicalKey::F28, + "F29" => PhysicalKey::F29, + "F30" => PhysicalKey::F30, + "F31" => PhysicalKey::F31, + "F32" => PhysicalKey::F32, + "F33" => PhysicalKey::F33, + "F34" => PhysicalKey::F34, + "F35" => PhysicalKey::F35, + "Fn" => PhysicalKey::Fn, + "FnLock" => PhysicalKey::FnLock, + "PrintScreen" => PhysicalKey::PrintScreen, + "ScrollLock" => PhysicalKey::ScrollLock, + "Pause" => PhysicalKey::Pause, + _ => PhysicalKey::Unknown, } } -/// Convert a web `KeyboardEvent.key` value into a character codepoint. -/// Return `None` if they input was not a printable character. -pub fn web_key_to_codepoint(key: &str) -> Option { +/// Convert a web `KeyboardEvent.key` value into a Ruffle `LogicalKey`. +fn map_logical_key(key: &str) -> LogicalKey { // TODO: This is a very cheesy way to tell if a `KeyboardEvent.key` is a printable character. // Single character strings will be an actual printable char that we can use as text input. // All the other special values are multiple characters (e.g. "ArrowLeft"). // It's probably better to explicitly match on all the variants. let mut chars = key.chars(); let (c1, c2) = (chars.next(), chars.next()); - if c2.is_none() { + if c1.is_none() { + LogicalKey::Unknown + } else if let (Some(ch), None) = (c1, c2) { // Single character. - c1 + LogicalKey::Character(ch) } else { // Check for special characters. match key { - "Backspace" => Some(8 as char), - "Delete" => Some(127 as char), - "Enter" => Some(13 as char), - _ => None, + "Unidentified" => LogicalKey::Unknown, + "Alt" => LogicalKey::Named(NamedKey::Alt), + "AltGraph" => LogicalKey::Named(NamedKey::AltGraph), + "CapsLock" => LogicalKey::Named(NamedKey::CapsLock), + "Control" => LogicalKey::Named(NamedKey::Control), + "Fn" => LogicalKey::Named(NamedKey::Fn), + "FnLock" => LogicalKey::Named(NamedKey::FnLock), + "Hyper" => LogicalKey::Unknown, + "Meta" => LogicalKey::Unknown, + "NumLock" => LogicalKey::Named(NamedKey::NumLock), + "ScrollLock" => LogicalKey::Named(NamedKey::ScrollLock), + "Shift" => LogicalKey::Named(NamedKey::Shift), + "Super" => LogicalKey::Named(NamedKey::Super), + "Symbol" => LogicalKey::Named(NamedKey::Symbol), + "SymbolLock" => LogicalKey::Named(NamedKey::SymbolLock), + "Enter" => LogicalKey::Named(NamedKey::Enter), + "Tab" => LogicalKey::Named(NamedKey::Tab), + "ArrowDown" => LogicalKey::Named(NamedKey::ArrowDown), + "ArrowLeft" => LogicalKey::Named(NamedKey::ArrowLeft), + "ArrowRight" => LogicalKey::Named(NamedKey::ArrowRight), + "ArrowUp" => LogicalKey::Named(NamedKey::ArrowUp), + "End" => LogicalKey::Named(NamedKey::End), + "Home" => LogicalKey::Named(NamedKey::Home), + "PageDown" => LogicalKey::Named(NamedKey::PageDown), + "PageUp" => LogicalKey::Named(NamedKey::PageUp), + "Backspace" => LogicalKey::Named(NamedKey::Backspace), + "Clear" => LogicalKey::Named(NamedKey::Clear), + "Copy" => LogicalKey::Named(NamedKey::Copy), + "CrSel" => LogicalKey::Named(NamedKey::CrSel), + "Cut" => LogicalKey::Named(NamedKey::Cut), + "Delete" => LogicalKey::Named(NamedKey::Delete), + "EraseEof" => LogicalKey::Named(NamedKey::EraseEof), + "ExSel" => LogicalKey::Named(NamedKey::ExSel), + "Insert" => LogicalKey::Named(NamedKey::Insert), + "Paste" => LogicalKey::Named(NamedKey::Paste), + "Redo" => LogicalKey::Named(NamedKey::Redo), + "Undo" => LogicalKey::Named(NamedKey::Undo), + "Accept" => LogicalKey::Unknown, + "Again" => LogicalKey::Unknown, + "Attn" => LogicalKey::Unknown, + "Cancel" => LogicalKey::Unknown, + "ContextMenu" => LogicalKey::Named(NamedKey::ContextMenu), + "Escape" => LogicalKey::Named(NamedKey::Escape), + "Execute" => LogicalKey::Unknown, + "Find" => LogicalKey::Unknown, + "Finish" => LogicalKey::Unknown, + "Help" => LogicalKey::Unknown, + "Pause" => LogicalKey::Named(NamedKey::Pause), + "Play" => LogicalKey::Named(NamedKey::Play), + "Props" => LogicalKey::Unknown, + "Select" => LogicalKey::Named(NamedKey::Select), + "ZoomIn" => LogicalKey::Named(NamedKey::ZoomIn), + "ZoomOut" => LogicalKey::Named(NamedKey::ZoomOut), + "F1" => LogicalKey::Named(NamedKey::F1), + "F2" => LogicalKey::Named(NamedKey::F2), + "F3" => LogicalKey::Named(NamedKey::F3), + "F4" => LogicalKey::Named(NamedKey::F4), + "F5" => LogicalKey::Named(NamedKey::F5), + "F6" => LogicalKey::Named(NamedKey::F6), + "F7" => LogicalKey::Named(NamedKey::F7), + "F8" => LogicalKey::Named(NamedKey::F8), + "F9" => LogicalKey::Named(NamedKey::F9), + "F10" => LogicalKey::Named(NamedKey::F10), + "F11" => LogicalKey::Named(NamedKey::F11), + "F12" => LogicalKey::Named(NamedKey::F12), + "F13" => LogicalKey::Named(NamedKey::F13), + "F14" => LogicalKey::Named(NamedKey::F14), + "F15" => LogicalKey::Named(NamedKey::F15), + "F16" => LogicalKey::Named(NamedKey::F16), + "F17" => LogicalKey::Named(NamedKey::F17), + "F18" => LogicalKey::Named(NamedKey::F18), + "F19" => LogicalKey::Named(NamedKey::F19), + "F20" => LogicalKey::Named(NamedKey::F20), + "Decimal" => LogicalKey::Character('.'), + "Multiply" => LogicalKey::Character('*'), + "Add" => LogicalKey::Character('+'), + "Divide" => LogicalKey::Character('/'), + "Subtract" => LogicalKey::Character('-'), + _ => LogicalKey::Unknown, } } } +/// Convert a web `KeyboardEvent.location` value into a Ruffle `KeyLocation`. +fn map_key_location(location: u32) -> KeyLocation { + match location { + 1 => KeyLocation::Left, + 2 => KeyLocation::Right, + 3 => KeyLocation::Numpad, + _ => KeyLocation::Standard, + } +} + /// Convert a web `KeyboardEvent.key` value to a Ruffle `TextControlCode`, /// given the states of the modifier keys. Return `None` if there is no match. pub fn web_to_ruffle_text_control( diff --git a/web/src/lib.rs b/web/src/lib.rs index 10b943d4d1112..b33ba182320c6 100644 --- a/web/src/lib.rs +++ b/web/src/lib.rs @@ -14,7 +14,7 @@ mod zip; use crate::builder::RuffleInstanceBuilder; use external_interface::{external_to_js_value, js_to_external_value}; -use input::{web_key_to_codepoint, web_to_ruffle_key_code, web_to_ruffle_text_control}; +use input::{web_input_to_ruffle_key_descriptor, web_to_ruffle_text_control}; use js_sys::{Error as JsError, Uint8Array}; use ruffle_core::context::UpdateContext; use ruffle_core::context_menu::ContextMenuCallback; @@ -694,10 +694,9 @@ impl RuffleHandle { if instance.has_focus { let mut paste_event = false; let _ = instance.with_core_mut(|core| { - let key_code = web_to_ruffle_key_code(&js_event.code()); - let key_char = web_key_to_codepoint(&js_event.key()); + let key = web_input_to_ruffle_key_descriptor(&js_event); let is_ctrl_cmd = js_event.ctrl_key() || js_event.meta_key(); - core.handle_event(PlayerEvent::KeyDown { key_code, key_char }); + core.handle_event(PlayerEvent::KeyDown { key }); if let Some(control_code) = web_to_ruffle_text_control( &js_event.key(), @@ -712,7 +711,7 @@ impl RuffleHandle { code: control_code, }); } - } else if let Some(codepoint) = key_char { + } else if let Some(codepoint) = key.logical_key.character() { core.handle_event(PlayerEvent::TextInput { codepoint }); } }); @@ -763,9 +762,8 @@ impl RuffleHandle { let _ = ruffle.with_instance(|instance| { if instance.has_focus { let _ = instance.with_core_mut(|core| { - let key_code = web_to_ruffle_key_code(&js_event.code()); - let key_char = web_key_to_codepoint(&js_event.key()); - core.handle_event(PlayerEvent::KeyUp { key_code, key_char }); + let key = web_input_to_ruffle_key_descriptor(&js_event); + core.handle_event(PlayerEvent::KeyUp { key }); }); js_event.prevent_default(); }