From 333009b79fa31bafb16030b6c35ec79b671f8d61 Mon Sep 17 00:00:00 2001 From: michiel2005 <60014996+michiel2005@users.noreply.github.com> Date: Wed, 11 Oct 2023 10:53:57 +0200 Subject: [PATCH] avm1: Implement key.isToggled() --- core/src/avm1/globals/key.rs | 20 ++++++++++++++++++++ core/src/backend/ui.rs | 23 ++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/core/src/avm1/globals/key.rs b/core/src/avm1/globals/key.rs index ef64441e8..f21e1a961 100644 --- a/core/src/avm1/globals/key.rs +++ b/core/src/avm1/globals/key.rs @@ -27,6 +27,7 @@ const OBJECT_DECLS: &[Declaration] = declare_properties! { "TAB" => int(KeyCode::Tab as i32; DONT_ENUM | DONT_DELETE | READ_ONLY); "UP" => int(KeyCode::Up 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); "getCode" => method(get_code; DONT_ENUM | DONT_DELETE | READ_ONLY); }; @@ -47,6 +48,25 @@ pub fn is_down<'gc>( } } +pub fn is_toggled<'gc>( + activation: &mut Activation<'_, 'gc>, + _this: Object<'gc>, + args: &[Value<'gc>], +) -> Result, Error<'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( + 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()) + } +} + pub fn get_ascii<'gc>( activation: &mut Activation<'_, 'gc>, _this: Object<'gc>, diff --git a/core/src/backend/ui.rs b/core/src/backend/ui.rs index 127193878..190ab28ba 100644 --- a/core/src/backend/ui.rs +++ b/core/src/backend/ui.rs @@ -78,6 +78,7 @@ pub enum MouseCursor { pub struct InputManager { keys_down: HashSet, + keys_toggled: HashSet, last_key: KeyCode, last_char: Option, last_text_control: Option, @@ -87,6 +88,7 @@ impl InputManager { pub fn new() -> Self { Self { keys_down: HashSet::new(), + keys_toggled: HashSet::new(), last_key: KeyCode::Unknown, last_char: None, last_text_control: None, @@ -100,6 +102,17 @@ impl InputManager { } } + fn toggle_key(&mut self, key_code: KeyCode) { + if key_code == KeyCode::Unknown || self.keys_down.contains(&key_code) { + return; + } + if self.keys_toggled.contains(&key_code) { + self.keys_toggled.remove(&key_code); + } else { + self.keys_toggled.insert(key_code); + } + } + fn remove_key(&mut self, key_code: KeyCode) { self.last_key = key_code; if key_code != KeyCode::Unknown { @@ -111,6 +124,7 @@ impl InputManager { match *event { PlayerEvent::KeyDown { key_code, key_char } => { self.last_char = key_char; + self.toggle_key(key_code); self.add_key(key_code); } PlayerEvent::KeyUp { key_code, key_char } => { @@ -121,7 +135,10 @@ impl InputManager { PlayerEvent::TextControl { code } => { self.last_text_control = Some(code); } - PlayerEvent::MouseDown { button, .. } => self.add_key(button.into()), + PlayerEvent::MouseDown { button, .. } => { + self.toggle_key(button.into()); + self.add_key(button.into()) + } PlayerEvent::MouseUp { button, .. } => self.remove_key(button.into()), _ => {} } @@ -131,6 +148,10 @@ impl InputManager { self.keys_down.contains(&key) } + pub fn is_key_toggled(&self, key: KeyCode) -> bool { + self.keys_toggled.contains(&key) + } + pub fn last_key_code(&self) -> KeyCode { self.last_key }