core: Add support for wider range of key codes

This patch changes the definition of KeyCode from an enum,
which was constraining the possible key codes, to a struct with
a u32 field, which covers all possible cases of a key code.

Key codes in Flash are not related to the physical buttons,
but rather to logical button values.
For instance, typing a non-ASCII key produces a key code related
to that character, and using a non-ANSI keyboard or a layout different
from US QWERTY also produces results matching that assumption.
This commit is contained in:
Kamil Jarosz 2024-06-24 22:11:12 +02:00
parent ad0d3f8fbf
commit 898db260a3
11 changed files with 461 additions and 338 deletions

View File

@ -7,25 +7,25 @@ use crate::context::GcContext;
use crate::events::KeyCode;
const OBJECT_DECLS: &[Declaration] = declare_properties! {
"ALT" => int(KeyCode::Alt as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"BACKSPACE" => int(KeyCode::Backspace as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"CAPSLOCK" => int(KeyCode::CapsLock as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"CONTROL" => int(KeyCode::Control as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"DELETEKEY" => int(KeyCode::Delete as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"DOWN" => int(KeyCode::Down as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"END" => int(KeyCode::End as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"ENTER" => int(KeyCode::Return as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"ESCAPE" => int(KeyCode::Escape as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"HOME" => int(KeyCode::Home as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"INSERT" => int(KeyCode::Insert as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"LEFT" => int(KeyCode::Left as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"PGDN" => int(KeyCode::PgDown as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"PGUP" => int(KeyCode::PgUp as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"RIGHT" => int(KeyCode::Right as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"SHIFT" => int(KeyCode::Shift as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"SPACE" => int(KeyCode::Space as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"TAB" => int(KeyCode::Tab as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"UP" => int(KeyCode::Up as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"ALT" => int(KeyCode::ALT.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"BACKSPACE" => int(KeyCode::BACKSPACE.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"CAPSLOCK" => int(KeyCode::CAPS_LOCK.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"CONTROL" => int(KeyCode::CONTROL.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"DELETEKEY" => int(KeyCode::DELETE.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"DOWN" => int(KeyCode::DOWN.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"END" => int(KeyCode::END.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"ENTER" => int(KeyCode::RETURN.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"ESCAPE" => int(KeyCode::ESCAPE.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"HOME" => int(KeyCode::HOME.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"INSERT" => int(KeyCode::INSERT.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"LEFT" => int(KeyCode::LEFT.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"PGDN" => int(KeyCode::PG_DOWN.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"PGUP" => int(KeyCode::PG_UP.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"RIGHT" => int(KeyCode::RIGHT.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"SHIFT" => int(KeyCode::SHIFT.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"SPACE" => int(KeyCode::SPACE.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"TAB" => int(KeyCode::TAB.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"UP" => int(KeyCode::UP.value() as i32; DONT_ENUM | DONT_DELETE | READ_ONLY);
"isDown" => method(is_down; DONT_ENUM | DONT_DELETE | READ_ONLY);
"isToggled" => method(is_toggled; DONT_ENUM | DONT_DELETE | READ_ONLY);
"getAscii" => method(get_ascii; DONT_ENUM | DONT_DELETE | READ_ONLY);
@ -37,15 +37,13 @@ pub fn is_down<'gc>(
_this: Object<'gc>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(key) = KeyCode::from_u8(
let key = KeyCode::from_code(
args.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_i32(activation)? as u8,
) {
Ok(activation.context.input.is_key_down(key).into())
} else {
Ok(false.into())
}
.coerce_to_i32(activation)? as u32,
);
Ok(activation.context.input.is_key_down(key).into())
}
pub fn is_toggled<'gc>(
@ -56,15 +54,13 @@ pub fn is_toggled<'gc>(
// This is not perfect: Flash Player could get the status of the Caps Lock, Num Lock,
// and Scroll Lock keys properly. We are just toggling them if the Ruffle window is
// in focus. This is the desired behavior for all keys, except these three.
if let Some(key) = KeyCode::from_u8(
let key = KeyCode::from_code(
args.get(0)
.unwrap_or(&Value::Undefined)
.coerce_to_i32(activation)? as u8,
) {
Ok(activation.context.input.is_key_toggled(key).into())
} else {
Ok(false.into())
}
.coerce_to_i32(activation)? as u32,
);
Ok(activation.context.input.is_key_toggled(key).into())
}
pub fn get_ascii<'gc>(
@ -81,7 +77,7 @@ pub fn get_code<'gc>(
_this: Object<'gc>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
let code = activation.context.input.last_key_code() as u8;
let code = activation.context.input.last_key_code().value();
Ok(code.into())
}

View File

@ -136,12 +136,12 @@ impl<'gc> EventObject<'gc> {
activation
.context
.input
.is_key_down(KeyCode::Control)
.is_key_down(KeyCode::CONTROL)
.into(),
// altKey
activation.context.input.is_key_down(KeyCode::Alt).into(),
activation.context.input.is_key_down(KeyCode::ALT).into(),
// shiftKey
activation.context.input.is_key_down(KeyCode::Shift).into(),
activation.context.input.is_key_down(KeyCode::SHIFT).into(),
// buttonDown
activation.context.input.is_key_down(button.into()).into(),
// delta
@ -318,13 +318,13 @@ impl<'gc> EventObject<'gc> {
event_type: S,
cancelable: bool,
related_object: Option<InteractiveObject<'gc>>,
key_code: u8,
key_code: u32,
) -> Object<'gc>
where
S: Into<AvmString<'gc>>,
{
let event_type: AvmString<'gc> = event_type.into();
let shift_key = activation.context.input.is_key_down(KeyCode::Shift);
let shift_key = activation.context.input.is_key_down(KeyCode::SHIFT);
let class = activation.avm2().classes().focusevent;
class

View File

@ -183,7 +183,7 @@ impl InputManager {
Self {
keys_down: HashSet::new(),
keys_toggled: HashSet::new(),
last_key: KeyCode::Unknown,
last_key: KeyCode::UNKNOWN,
last_char: None,
last_text_control: None,
last_click: None,
@ -192,13 +192,13 @@ impl InputManager {
fn add_key(&mut self, key_code: KeyCode) {
self.last_key = key_code;
if key_code != KeyCode::Unknown {
if key_code != KeyCode::UNKNOWN {
self.keys_down.insert(key_code);
}
}
fn toggle_key(&mut self, key_code: KeyCode) {
if key_code == KeyCode::Unknown || self.keys_down.contains(&key_code) {
if key_code == KeyCode::UNKNOWN || self.keys_down.contains(&key_code) {
return;
}
if self.keys_toggled.contains(&key_code) {
@ -210,7 +210,7 @@ impl InputManager {
fn remove_key(&mut self, key_code: KeyCode) {
self.last_key = key_code;
if key_code != KeyCode::Unknown {
if key_code != KeyCode::UNKNOWN {
self.keys_down.remove(&key_code);
}
}

View File

@ -466,148 +466,153 @@ impl TextControlCode {
}
/// Flash virtual keycode.
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)]
pub enum KeyCode {
Unknown = 0,
MouseLeft = 1,
MouseRight = 2,
MouseMiddle = 4,
Backspace = 8,
Tab = 9,
Return = 13,
Command = 15,
Shift = 16,
Control = 17,
Alt = 18,
Pause = 19,
CapsLock = 20,
Numpad = 21,
Escape = 27,
Space = 32,
PgUp = 33,
PgDown = 34,
End = 35,
Home = 36,
Left = 37,
Up = 38,
Right = 39,
Down = 40,
Insert = 45,
Delete = 46,
Key0 = 48,
Key1 = 49,
Key2 = 50,
Key3 = 51,
Key4 = 52,
Key5 = 53,
Key6 = 54,
Key7 = 55,
Key8 = 56,
Key9 = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
Numpad0 = 96,
Numpad1 = 97,
Numpad2 = 98,
Numpad3 = 99,
Numpad4 = 100,
Numpad5 = 101,
Numpad6 = 102,
Numpad7 = 103,
Numpad8 = 104,
Numpad9 = 105,
Multiply = 106,
Plus = 107,
NumpadEnter = 108,
NumpadMinus = 109,
NumpadPeriod = 110,
NumpadSlash = 111,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
F13 = 124,
F14 = 125,
F15 = 126,
F16 = 127, // undocumented
F17 = 128, // undocumented
F18 = 129, // undocumented
F19 = 130, // undocumented
F20 = 131, // undocumented
F21 = 132, // undocumented
F22 = 133, // undocumented
F23 = 134, // undocumented
F24 = 135, // undocumented
NumLock = 144,
ScrollLock = 145,
Semicolon = 186,
Equals = 187,
Comma = 188,
Minus = 189,
Period = 190,
Slash = 191,
Grave = 192,
LBracket = 219,
Backslash = 220,
RBracket = 221,
Apostrophe = 222,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct KeyCode(u32);
impl KeyCode {
pub fn from_u8(n: u8) -> Option<Self> {
num_traits::FromPrimitive::from_u8(n)
pub const UNKNOWN: KeyCode = KeyCode(0);
pub const MOUSE_LEFT: KeyCode = KeyCode(1);
pub const MOUSE_RIGHT: KeyCode = KeyCode(2);
pub const MOUSE_MIDDLE: KeyCode = KeyCode(4);
pub const BACKSPACE: KeyCode = KeyCode(8);
pub const TAB: KeyCode = KeyCode(9);
pub const RETURN: KeyCode = KeyCode(13);
pub const COMMAND: KeyCode = KeyCode(15);
pub const SHIFT: KeyCode = KeyCode(16);
pub const CONTROL: KeyCode = KeyCode(17);
pub const ALT: KeyCode = KeyCode(18);
pub const PAUSE: KeyCode = KeyCode(19);
pub const CAPS_LOCK: KeyCode = KeyCode(20);
pub const NUMPAD: KeyCode = KeyCode(21);
pub const ESCAPE: KeyCode = KeyCode(27);
pub const SPACE: KeyCode = KeyCode(32);
pub const PG_UP: KeyCode = KeyCode(33);
pub const PG_DOWN: KeyCode = KeyCode(34);
pub const END: KeyCode = KeyCode(35);
pub const HOME: KeyCode = KeyCode(36);
pub const LEFT: KeyCode = KeyCode(37);
pub const UP: KeyCode = KeyCode(38);
pub const RIGHT: KeyCode = KeyCode(39);
pub const DOWN: KeyCode = KeyCode(40);
pub const INSERT: KeyCode = KeyCode(45);
pub const DELETE: KeyCode = KeyCode(46);
pub const KEY0: KeyCode = KeyCode(48);
pub const KEY1: KeyCode = KeyCode(49);
pub const KEY2: KeyCode = KeyCode(50);
pub const KEY3: KeyCode = KeyCode(51);
pub const KEY4: KeyCode = KeyCode(52);
pub const KEY5: KeyCode = KeyCode(53);
pub const KEY6: KeyCode = KeyCode(54);
pub const KEY7: KeyCode = KeyCode(55);
pub const KEY8: KeyCode = KeyCode(56);
pub const KEY9: KeyCode = KeyCode(57);
pub const A: KeyCode = KeyCode(65);
pub const B: KeyCode = KeyCode(66);
pub const C: KeyCode = KeyCode(67);
pub const D: KeyCode = KeyCode(68);
pub const E: KeyCode = KeyCode(69);
pub const F: KeyCode = KeyCode(70);
pub const G: KeyCode = KeyCode(71);
pub const H: KeyCode = KeyCode(72);
pub const I: KeyCode = KeyCode(73);
pub const J: KeyCode = KeyCode(74);
pub const K: KeyCode = KeyCode(75);
pub const L: KeyCode = KeyCode(76);
pub const M: KeyCode = KeyCode(77);
pub const N: KeyCode = KeyCode(78);
pub const O: KeyCode = KeyCode(79);
pub const P: KeyCode = KeyCode(80);
pub const Q: KeyCode = KeyCode(81);
pub const R: KeyCode = KeyCode(82);
pub const S: KeyCode = KeyCode(83);
pub const T: KeyCode = KeyCode(84);
pub const U: KeyCode = KeyCode(85);
pub const V: KeyCode = KeyCode(86);
pub const W: KeyCode = KeyCode(87);
pub const X: KeyCode = KeyCode(88);
pub const Y: KeyCode = KeyCode(89);
pub const Z: KeyCode = KeyCode(90);
pub const NUMPAD0: KeyCode = KeyCode(96);
pub const NUMPAD1: KeyCode = KeyCode(97);
pub const NUMPAD2: KeyCode = KeyCode(98);
pub const NUMPAD3: KeyCode = KeyCode(99);
pub const NUMPAD4: KeyCode = KeyCode(100);
pub const NUMPAD5: KeyCode = KeyCode(101);
pub const NUMPAD6: KeyCode = KeyCode(102);
pub const NUMPAD7: KeyCode = KeyCode(103);
pub const NUMPAD8: KeyCode = KeyCode(104);
pub const NUMPAD9: KeyCode = KeyCode(105);
pub const MULTIPLY: KeyCode = KeyCode(106);
pub const PLUS: KeyCode = KeyCode(107);
pub const NUMPAD_ENTER: KeyCode = KeyCode(108);
pub const NUMPAD_MINUS: KeyCode = KeyCode(109);
pub const NUMPAD_PERIOD: KeyCode = KeyCode(110);
pub const NUMPAD_SLASH: KeyCode = KeyCode(111);
pub const F1: KeyCode = KeyCode(112);
pub const F2: KeyCode = KeyCode(113);
pub const F3: KeyCode = KeyCode(114);
pub const F4: KeyCode = KeyCode(115);
pub const F5: KeyCode = KeyCode(116);
pub const F6: KeyCode = KeyCode(117);
pub const F7: KeyCode = KeyCode(118);
pub const F8: KeyCode = KeyCode(119);
pub const F9: KeyCode = KeyCode(120);
pub const F10: KeyCode = KeyCode(121);
pub const F11: KeyCode = KeyCode(122);
pub const F12: KeyCode = KeyCode(123);
pub const F13: KeyCode = KeyCode(124);
pub const F14: KeyCode = KeyCode(125);
pub const F15: KeyCode = KeyCode(126);
pub const F16: KeyCode = KeyCode(127); // undocumented
pub const F17: KeyCode = KeyCode(128); // undocumented
pub const F18: KeyCode = KeyCode(129); // undocumented
pub const F19: KeyCode = KeyCode(130); // undocumented
pub const F20: KeyCode = KeyCode(131); // undocumented
pub const F21: KeyCode = KeyCode(132); // undocumented
pub const F22: KeyCode = KeyCode(133); // undocumented
pub const F23: KeyCode = KeyCode(134); // undocumented
pub const F24: KeyCode = KeyCode(135); // undocumented
pub const NUM_LOCK: KeyCode = KeyCode(144);
pub const SCROLL_LOCK: KeyCode = KeyCode(145);
pub const SEMICOLON: KeyCode = KeyCode(186);
pub const EQUALS: KeyCode = KeyCode(187);
pub const COMMA: KeyCode = KeyCode(188);
pub const MINUS: KeyCode = KeyCode(189);
pub const PERIOD: KeyCode = KeyCode(190);
pub const SLASH: KeyCode = KeyCode(191);
pub const GRAVE: KeyCode = KeyCode(192);
pub const LBRACKET: KeyCode = KeyCode(219);
pub const BACKSLASH: KeyCode = KeyCode(220);
pub const RBRACKET: KeyCode = KeyCode(221);
pub const APOSTROPHE: KeyCode = KeyCode(222);
#[inline]
pub const fn from_code(code: u32) -> Self {
Self(code)
}
#[inline]
pub const fn value(self) -> u32 {
self.0
}
}
/// Subset of `KeyCode` that contains only mouse buttons.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MouseButton {
Unknown = KeyCode::Unknown as isize,
Left = KeyCode::MouseLeft as isize,
Right = KeyCode::MouseRight as isize,
Middle = KeyCode::MouseMiddle as isize,
Unknown,
Left,
Right,
Middle,
}
impl From<MouseButton> for KeyCode {
fn from(button: MouseButton) -> Self {
match button {
MouseButton::Unknown => Self::Unknown,
MouseButton::Left => Self::MouseLeft,
MouseButton::Right => Self::MouseRight,
MouseButton::Middle => Self::MouseMiddle,
MouseButton::Unknown => Self::UNKNOWN,
MouseButton::Left => Self::MOUSE_LEFT,
MouseButton::Right => Self::MOUSE_RIGHT,
MouseButton::Middle => Self::MOUSE_MIDDLE,
}
}
}
@ -743,20 +748,20 @@ impl ButtonKeyCode {
pub fn key_code_to_button_key_code(key_code: KeyCode) -> Option<ButtonKeyCode> {
let out = match key_code {
KeyCode::Left => ButtonKeyCode::Left,
KeyCode::Right => ButtonKeyCode::Right,
KeyCode::Home => ButtonKeyCode::Home,
KeyCode::End => ButtonKeyCode::End,
KeyCode::Insert => ButtonKeyCode::Insert,
KeyCode::Delete => ButtonKeyCode::Delete,
KeyCode::Backspace => ButtonKeyCode::Backspace,
KeyCode::Return => ButtonKeyCode::Return,
KeyCode::Up => ButtonKeyCode::Up,
KeyCode::Down => ButtonKeyCode::Down,
KeyCode::PgUp => ButtonKeyCode::PgUp,
KeyCode::PgDown => ButtonKeyCode::PgDown,
KeyCode::Escape => ButtonKeyCode::Escape,
KeyCode::Tab => ButtonKeyCode::Tab,
KeyCode::LEFT => ButtonKeyCode::Left,
KeyCode::RIGHT => ButtonKeyCode::Right,
KeyCode::HOME => ButtonKeyCode::Home,
KeyCode::END => ButtonKeyCode::End,
KeyCode::INSERT => ButtonKeyCode::Insert,
KeyCode::DELETE => ButtonKeyCode::Delete,
KeyCode::BACKSPACE => ButtonKeyCode::Backspace,
KeyCode::RETURN => ButtonKeyCode::Return,
KeyCode::UP => ButtonKeyCode::Up,
KeyCode::DOWN => ButtonKeyCode::Down,
KeyCode::PG_UP => ButtonKeyCode::PgUp,
KeyCode::PG_DOWN => ButtonKeyCode::PgDown,
KeyCode::ESCAPE => ButtonKeyCode::Escape,
KeyCode::TAB => ButtonKeyCode::Tab,
_ => return None,
};
Some(out)

View File

@ -239,7 +239,7 @@ impl<'gc> FocusTracker<'gc> {
};
let mut activation = Activation::from_nothing(context);
let key_code = key_code.map(|k| k as u8).unwrap_or_default();
let key_code = key_code.map(|k| k.value()).unwrap_or_default();
let event =
EventObject::focus_event(&mut activation, event_type, true, related_object, key_code);
Avm2::dispatch_event(activation.context, event, target);
@ -300,7 +300,7 @@ impl<'gc> FocusTracker<'gc> {
};
if next.is_some() {
self.set_by_key(next.copied(), KeyCode::Tab, context);
self.set_by_key(next.copied(), KeyCode::TAB, context);
self.update_highlight(context);
}
}
@ -528,20 +528,20 @@ pub enum NavigationDirection {
impl NavigationDirection {
pub fn from_key_code(key_code: KeyCode) -> Option<Self> {
Some(match key_code {
KeyCode::Up => Self::Up,
KeyCode::Right => Self::Right,
KeyCode::Down => Self::Down,
KeyCode::Left => Self::Left,
KeyCode::UP => Self::Up,
KeyCode::RIGHT => Self::Right,
KeyCode::DOWN => Self::Down,
KeyCode::LEFT => Self::Left,
_ => return None,
})
}
fn key(self) -> KeyCode {
match self {
Self::Up => KeyCode::Up,
Self::Right => KeyCode::Right,
Self::Down => KeyCode::Down,
Self::Left => KeyCode::Left,
Self::Up => KeyCode::UP,
Self::Right => KeyCode::RIGHT,
Self::Down => KeyCode::DOWN,
Self::Left => KeyCode::LEFT,
}
}
}

View File

@ -1049,8 +1049,8 @@ impl Player {
PlayerEvent::KeyDown {
key_code: KeyCode::V,
..
} if self.input.is_key_down(KeyCode::Control)
&& self.input.is_key_down(KeyCode::Alt) =>
} if self.input.is_key_down(KeyCode::CONTROL)
&& self.input.is_key_down(KeyCode::ALT) =>
{
self.mutate_with_update_context(|context| {
let mut dumper = VariableDumper::new(" ");
@ -1083,8 +1083,8 @@ impl Player {
PlayerEvent::KeyDown {
key_code: KeyCode::D,
..
} if self.input.is_key_down(KeyCode::Control)
&& self.input.is_key_down(KeyCode::Alt) =>
} if self.input.is_key_down(KeyCode::CONTROL)
&& self.input.is_key_down(KeyCode::ALT) =>
{
self.mutate_with_update_context(|context| {
if context.avm1.show_debug_output() {
@ -1105,8 +1105,8 @@ impl Player {
PlayerEvent::KeyDown {
key_code: KeyCode::F,
..
} if self.input.is_key_down(KeyCode::Control)
&& self.input.is_key_down(KeyCode::Alt) =>
} if self.input.is_key_down(KeyCode::CONTROL)
&& self.input.is_key_down(KeyCode::ALT) =>
{
self.mutate_with_update_context(|context| {
context.stage.display_render_tree(0);
@ -1141,9 +1141,9 @@ impl Player {
if let PlayerEvent::KeyDown { key_code, key_char }
| PlayerEvent::KeyUp { key_code, key_char } = event
{
let ctrl_key = context.input.is_key_down(KeyCode::Control);
let alt_key = context.input.is_key_down(KeyCode::Alt);
let shift_key = context.input.is_key_down(KeyCode::Shift);
let ctrl_key = context.input.is_key_down(KeyCode::CONTROL);
let alt_key = context.input.is_key_down(KeyCode::ALT);
let shift_key = context.input.is_key_down(KeyCode::SHIFT);
let mut activation = Avm2Activation::from_nothing(context);
@ -1168,7 +1168,7 @@ impl Player {
true.into(), /* bubbles */
false.into(), /* cancelable */
key_char.map_or(0, |c| c as u32).into(), /* charCode */
(key_code as u32).into(), /* keyCode */
key_code.value().into(), /* keyCode */
0.into(), /* keyLocation */
ctrl_key.into(), /* ctrlKey */
alt_key.into(), /* altKey */
@ -1294,11 +1294,11 @@ impl Player {
// KeyPress events also take precedence over tabbing.
if !key_press_handled {
if let PlayerEvent::KeyDown {
key_code: KeyCode::Tab,
key_code: KeyCode::TAB,
..
} = event
{
let reversed = context.input.is_key_down(KeyCode::Shift);
let reversed = context.input.is_key_down(KeyCode::SHIFT);
let tracker = context.focus_tracker;
tracker.cycle(context, reversed);
}
@ -1311,7 +1311,7 @@ impl Player {
if matches!(
event,
PlayerEvent::KeyDown {
key_code: KeyCode::Return,
key_code: KeyCode::RETURN,
..
} | PlayerEvent::TextInput { codepoint: ' ' }
) {

View File

@ -256,13 +256,13 @@ fn parse_gamepad_button(mapping: &str) -> Result<(GamepadButton, KeyCode), Error
to_aliases(GamepadButton::value_variants())
)
})?;
let key_code = KeyCode::from_str(&mapping[pos + 1..], true).map_err(|err| {
let key_code = NamedKeyCode::from_str(&mapping[pos + 1..], true).map_err(|err| {
anyhow!(
"Could not parse <key name>: {err}\n The possible values are: {}",
to_aliases(KeyCode::value_variants())
to_aliases(NamedKeyCode::value_variants())
)
})?;
Ok((button, key_code))
Ok((button, KeyCode::from_code(key_code as u32)))
}
impl Opt {
@ -281,3 +281,125 @@ impl Opt {
})
}
}
// TODO The following enum exists in order to preserve
// the behavior of mapping gamepad buttons,
// We should probably do something smarter here.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, clap::ValueEnum)]
enum NamedKeyCode {
Unknown = 0,
MouseLeft = 1,
MouseRight = 2,
MouseMiddle = 4,
Backspace = 8,
Tab = 9,
Return = 13,
Command = 15,
Shift = 16,
Control = 17,
Alt = 18,
Pause = 19,
CapsLock = 20,
Numpad = 21,
Escape = 27,
Space = 32,
PgUp = 33,
PgDown = 34,
End = 35,
Home = 36,
Left = 37,
Up = 38,
Right = 39,
Down = 40,
Insert = 45,
Delete = 46,
Key0 = 48,
Key1 = 49,
Key2 = 50,
Key3 = 51,
Key4 = 52,
Key5 = 53,
Key6 = 54,
Key7 = 55,
Key8 = 56,
Key9 = 57,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
Numpad0 = 96,
Numpad1 = 97,
Numpad2 = 98,
Numpad3 = 99,
Numpad4 = 100,
Numpad5 = 101,
Numpad6 = 102,
Numpad7 = 103,
Numpad8 = 104,
Numpad9 = 105,
Multiply = 106,
Plus = 107,
NumpadEnter = 108,
NumpadMinus = 109,
NumpadPeriod = 110,
NumpadSlash = 111,
F1 = 112,
F2 = 113,
F3 = 114,
F4 = 115,
F5 = 116,
F6 = 117,
F7 = 118,
F8 = 119,
F9 = 120,
F10 = 121,
F11 = 122,
F12 = 123,
F13 = 124,
F14 = 125,
F15 = 126,
F16 = 127,
F17 = 128,
F18 = 129,
F19 = 130,
F20 = 131,
F21 = 132,
F22 = 133,
F23 = 134,
F24 = 135,
NumLock = 144,
ScrollLock = 145,
Semicolon = 186,
Equals = 187,
Comma = 188,
Minus = 189,
Period = 190,
Slash = 191,
Grave = 192,
LBracket = 219,
Backslash = 220,
RBracket = 221,
Apostrophe = 222,
}

View File

@ -65,68 +65,68 @@ pub fn winit_to_ruffle_key_code(event: &KeyEvent) -> Option<KeyCode> {
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::Return,
Key::Named(NamedKey::Shift) => KeyCode::Shift,
Key::Named(NamedKey::Control) => KeyCode::Control,
Key::Named(NamedKey::Alt) => KeyCode::Alt,
Key::Named(NamedKey::Backspace) => KeyCode::BACKSPACE,
Key::Named(NamedKey::Tab) => KeyCode::TAB,
Key::Named(NamedKey::Enter) => KeyCode::RETURN,
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::CapsLock,
Key::Named(NamedKey::Escape) => KeyCode::Escape,
Key::Named(NamedKey::Space) => KeyCode::Space,
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::Numpad0,
Key::Character("1") if is_numpad => KeyCode::Numpad1,
Key::Character("2") if is_numpad => KeyCode::Numpad2,
Key::Character("3") if is_numpad => KeyCode::Numpad3,
Key::Character("4") if is_numpad => KeyCode::Numpad4,
Key::Character("5") if is_numpad => KeyCode::Numpad5,
Key::Character("6") if is_numpad => KeyCode::Numpad6,
Key::Character("7") if is_numpad => KeyCode::Numpad7,
Key::Character("8") if is_numpad => KeyCode::Numpad8,
Key::Character("9") if is_numpad => KeyCode::Numpad9,
Key::Character("*") if is_numpad => KeyCode::Multiply,
Key::Character("+") if is_numpad => KeyCode::Plus,
Key::Character("-") if is_numpad => KeyCode::NumpadMinus,
Key::Character(".") if is_numpad => KeyCode::NumpadPeriod,
Key::Character("/") if is_numpad => KeyCode::NumpadSlash,
Key::Character("0") | Key::Character(")") => KeyCode::Key0,
Key::Character("1") | Key::Character("!") => KeyCode::Key1,
Key::Character("2") | Key::Character("@") => KeyCode::Key2,
Key::Character("3") | Key::Character("#") => KeyCode::Key3,
Key::Character("4") | Key::Character("$") => KeyCode::Key4,
Key::Character("5") | Key::Character("%") => KeyCode::Key5,
Key::Character("6") | Key::Character("^") => KeyCode::Key6,
Key::Character("7") | Key::Character("&") => KeyCode::Key7,
Key::Character("8") | Key::Character("*") => KeyCode::Key8,
Key::Character("9") | Key::Character("(") => KeyCode::Key9,
Key::Character(";") | Key::Character(":") => KeyCode::Semicolon,
Key::Character("=") | Key::Character("+") => KeyCode::Equals,
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::Grave,
Key::Character("[") | Key::Character("{") => KeyCode::LBracket,
Key::Character("\\") | Key::Character("|") => KeyCode::Backslash,
Key::Character("]") | Key::Character("}") => KeyCode::RBracket,
Key::Character("'") | Key::Character("\"") => KeyCode::Apostrophe,
Key::Named(NamedKey::PageUp) => KeyCode::PgUp,
Key::Named(NamedKey::PageDown) => KeyCode::PgDown,
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::NumLock,
Key::Named(NamedKey::ScrollLock) => KeyCode::ScrollLock,
Key::Character("0") if is_numpad => KeyCode::NUMPAD0,
Key::Character("1") if is_numpad => KeyCode::NUMPAD1,
Key::Character("2") if is_numpad => KeyCode::NUMPAD2,
Key::Character("3") if is_numpad => KeyCode::NUMPAD3,
Key::Character("4") if is_numpad => KeyCode::NUMPAD4,
Key::Character("5") if is_numpad => KeyCode::NUMPAD5,
Key::Character("6") if is_numpad => KeyCode::NUMPAD6,
Key::Character("7") if is_numpad => KeyCode::NUMPAD7,
Key::Character("8") if is_numpad => KeyCode::NUMPAD8,
Key::Character("9") if is_numpad => KeyCode::NUMPAD9,
Key::Character("*") if is_numpad => KeyCode::MULTIPLY,
Key::Character("+") if is_numpad => KeyCode::PLUS,
Key::Character("-") if is_numpad => KeyCode::NUMPAD_MINUS,
Key::Character(".") if is_numpad => KeyCode::NUMPAD_PERIOD,
Key::Character("/") if is_numpad => KeyCode::NUMPAD_SLASH,
Key::Character("0") | Key::Character(")") => KeyCode::KEY0,
Key::Character("1") | Key::Character("!") => KeyCode::KEY1,
Key::Character("2") | Key::Character("@") => KeyCode::KEY2,
Key::Character("3") | Key::Character("#") => KeyCode::KEY3,
Key::Character("4") | Key::Character("$") => KeyCode::KEY4,
Key::Character("5") | Key::Character("%") => KeyCode::KEY5,
Key::Character("6") | Key::Character("^") => KeyCode::KEY6,
Key::Character("7") | Key::Character("&") => KeyCode::KEY7,
Key::Character("8") | Key::Character("*") => KeyCode::KEY8,
Key::Character("9") | Key::Character("(") => KeyCode::KEY9,
Key::Character(";") | Key::Character(":") => KeyCode::SEMICOLON,
Key::Character("=") | Key::Character("+") => KeyCode::EQUALS,
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::GRAVE,
Key::Character("[") | Key::Character("{") => KeyCode::LBRACKET,
Key::Character("\\") | Key::Character("|") => KeyCode::BACKSLASH,
Key::Character("]") | Key::Character("}") => KeyCode::RBRACKET,
Key::Character("'") | Key::Character("\"") => KeyCode::APOSTROPHE,
Key::Named(NamedKey::PageUp) => KeyCode::PG_UP,
Key::Named(NamedKey::PageDown) => KeyCode::PG_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,
@ -153,9 +153,9 @@ pub fn winit_to_ruffle_key_code(event: &KeyEvent) -> Option<KeyCode> {
Key::Named(NamedKey::F24) => KeyCode::F24,
Key::Character(char) => {
// Handle alphabetic characters
alpha_to_ruffle_key_code(char).unwrap_or(KeyCode::Unknown)
alpha_to_ruffle_key_code(char).unwrap_or(KeyCode::UNKNOWN)
}
_ => KeyCode::Unknown,
_ => KeyCode::UNKNOWN,
};
Some(key_code)
}
@ -171,7 +171,7 @@ fn alpha_to_ruffle_key_code(char: &str) -> Option<KeyCode> {
// ASCII alphabetic characters are all mapped to
// their respective KeyCodes, which happen to have
// the same numerical value as uppercase characters.
return KeyCode::from_u8(char.to_ascii_uppercase() as u8);
return Some(KeyCode::from_code(char.to_ascii_uppercase() as u32));
}
if !char.is_ascii() {

View File

@ -236,11 +236,11 @@ impl TestRunner {
},
},
AutomatedEvent::KeyDown { key_code } => PlayerEvent::KeyDown {
key_code: KeyCode::from_u8(*key_code).expect("Invalid keycode in test"),
key_code: KeyCode::from_code(*key_code),
key_char: None,
},
AutomatedEvent::KeyUp { key_code } => PlayerEvent::KeyUp {
key_code: KeyCode::from_u8(*key_code).expect("Invalid keycode in test"),
key_code: KeyCode::from_code(*key_code),
key_char: None,
},
AutomatedEvent::TextInput { codepoint } => PlayerEvent::TextInput {

View File

@ -82,10 +82,10 @@ pub enum AutomatedEvent {
},
/// Press a key
KeyDown { key_code: u8 },
KeyDown { key_code: u32 },
/// Release a key
KeyUp { key_code: u8 },
KeyUp { key_code: u32 },
/// Input a character code
TextInput { codepoint: char },

View File

@ -4,25 +4,25 @@ use ruffle_core::events::{KeyCode, TextControlCode};
/// Return `KeyCode::Unknown` if there is no matching Flash key code.
pub fn web_to_ruffle_key_code(key_code: &str) -> KeyCode {
match key_code {
"Backspace" => KeyCode::Backspace,
"Tab" => KeyCode::Tab,
"Enter" => KeyCode::Return,
"ShiftLeft" | "ShiftRight" => KeyCode::Shift,
"ControlLeft" | "ControlRight" => KeyCode::Control,
"AltLeft" | "AltRight" => KeyCode::Alt,
"CapsLock" => KeyCode::CapsLock,
"Escape" => KeyCode::Escape,
"Space" => KeyCode::Space,
"Digit0" => KeyCode::Key0,
"Digit1" => KeyCode::Key1,
"Digit2" => KeyCode::Key2,
"Digit3" => KeyCode::Key3,
"Digit4" => KeyCode::Key4,
"Digit5" => KeyCode::Key5,
"Digit6" => KeyCode::Key6,
"Digit7" => KeyCode::Key7,
"Digit8" => KeyCode::Key8,
"Digit9" => KeyCode::Key9,
"Backspace" => KeyCode::BACKSPACE,
"Tab" => KeyCode::TAB,
"Enter" => KeyCode::RETURN,
"ShiftLeft" | "ShiftRight" => KeyCode::SHIFT,
"ControlLeft" | "ControlRight" => KeyCode::CONTROL,
"AltLeft" | "AltRight" => KeyCode::ALT,
"CapsLock" => KeyCode::CAPS_LOCK,
"Escape" => KeyCode::ESCAPE,
"Space" => KeyCode::SPACE,
"Digit0" => KeyCode::KEY0,
"Digit1" => KeyCode::KEY1,
"Digit2" => KeyCode::KEY2,
"Digit3" => KeyCode::KEY3,
"Digit4" => KeyCode::KEY4,
"Digit5" => KeyCode::KEY5,
"Digit6" => KeyCode::KEY6,
"Digit7" => KeyCode::KEY7,
"Digit8" => KeyCode::KEY8,
"Digit9" => KeyCode::KEY9,
"KeyA" => KeyCode::A,
"KeyB" => KeyCode::B,
"KeyC" => KeyCode::C,
@ -49,46 +49,46 @@ pub fn web_to_ruffle_key_code(key_code: &str) -> KeyCode {
"KeyX" => KeyCode::X,
"KeyY" => KeyCode::Y,
"KeyZ" => KeyCode::Z,
"Semicolon" => KeyCode::Semicolon,
"Equal" => KeyCode::Equals,
"Comma" => KeyCode::Comma,
"Minus" => KeyCode::Minus,
"Period" => KeyCode::Period,
"Slash" => KeyCode::Slash,
"Backquote" => KeyCode::Grave,
"BracketLeft" => KeyCode::LBracket,
"Backslash" => KeyCode::Backslash,
"BracketRight" => KeyCode::RBracket,
"Quote" => KeyCode::Apostrophe,
"Numpad0" => KeyCode::Numpad0,
"Numpad1" => KeyCode::Numpad1,
"Numpad2" => KeyCode::Numpad2,
"Numpad3" => KeyCode::Numpad3,
"Numpad4" => KeyCode::Numpad4,
"Numpad5" => KeyCode::Numpad5,
"Numpad6" => KeyCode::Numpad6,
"Numpad7" => KeyCode::Numpad7,
"Numpad8" => KeyCode::Numpad8,
"Numpad9" => KeyCode::Numpad9,
"NumpadMultiply" => KeyCode::Multiply,
"NumpadAdd" => KeyCode::Plus,
"NumpadSubtract" => KeyCode::NumpadMinus,
"NumpadDecimal" => KeyCode::NumpadPeriod,
"NumpadDivide" => KeyCode::NumpadSlash,
"NumpadEnter" => KeyCode::Return,
"PageUp" => KeyCode::PgUp,
"PageDown" => KeyCode::PgDown,
"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::NumLock,
"ScrollLock" => KeyCode::ScrollLock,
"Semicolon" => KeyCode::SEMICOLON,
"Equal" => KeyCode::EQUALS,
"Comma" => KeyCode::COMMA,
"Minus" => KeyCode::MINUS,
"Period" => KeyCode::PERIOD,
"Slash" => KeyCode::SLASH,
"Backquote" => KeyCode::GRAVE,
"BracketLeft" => KeyCode::LBRACKET,
"Backslash" => KeyCode::BACKSLASH,
"BracketRight" => KeyCode::RBRACKET,
"Quote" => KeyCode::APOSTROPHE,
"Numpad0" => KeyCode::NUMPAD0,
"Numpad1" => KeyCode::NUMPAD1,
"Numpad2" => KeyCode::NUMPAD2,
"Numpad3" => KeyCode::NUMPAD3,
"Numpad4" => KeyCode::NUMPAD4,
"Numpad5" => KeyCode::NUMPAD5,
"Numpad6" => KeyCode::NUMPAD6,
"Numpad7" => KeyCode::NUMPAD7,
"Numpad8" => KeyCode::NUMPAD8,
"Numpad9" => KeyCode::NUMPAD9,
"NumpadMultiply" => KeyCode::MULTIPLY,
"NumpadAdd" => KeyCode::PLUS,
"NumpadSubtract" => KeyCode::NUMPAD_MINUS,
"NumpadDecimal" => KeyCode::NUMPAD_PERIOD,
"NumpadDivide" => KeyCode::NUMPAD_SLASH,
"NumpadEnter" => KeyCode::RETURN,
"PageUp" => KeyCode::PG_UP,
"PageDown" => KeyCode::PG_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,
@ -113,7 +113,7 @@ pub fn web_to_ruffle_key_code(key_code: &str) -> KeyCode {
"F22" => KeyCode::F22,
"F23" => KeyCode::F23,
"F24" => KeyCode::F24,
_ => KeyCode::Unknown,
_ => KeyCode::UNKNOWN,
}
}