avm2: Fire KeyboardEvent.KEY_UP and KeyboardEvent.KEY_DOWN
The 'charCode' and 'keyCode' properties are now implemented on `KeyboardEvent` The input injection code we use does not support keyboard events, so we can't yet write a regression test for this. However, both 'You need to burn the rope' and 'This is the Only Level TOO' now properly handle keyboard events with this PR.
This commit is contained in:
parent
e3e0488ed4
commit
c531994b1c
|
@ -100,6 +100,7 @@ pub struct SystemClasses<'gc> {
|
|||
pub illegaloperationerror: ClassObject<'gc>,
|
||||
pub eventdispatcher: ClassObject<'gc>,
|
||||
pub rectangle: ClassObject<'gc>,
|
||||
pub keyboardevent: ClassObject<'gc>,
|
||||
}
|
||||
|
||||
impl<'gc> SystemClasses<'gc> {
|
||||
|
@ -169,6 +170,7 @@ impl<'gc> SystemClasses<'gc> {
|
|||
illegaloperationerror: object,
|
||||
eventdispatcher: object,
|
||||
rectangle: object,
|
||||
keyboardevent: object,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -711,6 +713,7 @@ fn load_playerglobal<'gc>(
|
|||
("flash.events", "Event", event),
|
||||
("flash.events", "TextEvent", textevent),
|
||||
("flash.events", "ErrorEvent", errorevent),
|
||||
("flash.events", "KeyboardEvent", keyboardevent),
|
||||
("flash.events", "ProgressEvent", progressevent),
|
||||
("flash.events", "SecurityErrorEvent", securityerrorevent),
|
||||
("flash.events", "IOErrorEvent", ioerrorevent),
|
||||
|
|
|
@ -4,11 +4,28 @@ package flash.events
|
|||
{
|
||||
public static const KEY_DOWN:String = "keyDown";
|
||||
public static const KEY_UP:String = "keyUp";
|
||||
private var _charCode:uint;
|
||||
private var _keyCode:uint;
|
||||
|
||||
public function KeyboardEvent(type:String, bubbles:Boolean = true, cancelable:Boolean = false, charCodeValue:uint = 0, keyCodeValue:uint = 0, keyLocationValue:uint = 0, ctrlKeyValue:Boolean = false, altKeyValue:Boolean = false, shiftKeyValue:Boolean = false)
|
||||
{
|
||||
super(type,bubbles,cancelable);
|
||||
// TODO: fill this up
|
||||
this._charCode = charCodeValue;
|
||||
this._keyCode = keyCodeValue;
|
||||
}
|
||||
|
||||
public function get charCode():uint {
|
||||
return this._charCode;
|
||||
}
|
||||
public function set charCode(val:uint) {
|
||||
this._charCode = val;
|
||||
}
|
||||
|
||||
public function get keyCode():uint {
|
||||
return this._keyCode;
|
||||
}
|
||||
public function set keyCode(val:uint) {
|
||||
this._keyCode = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::avm1::object::Object;
|
|||
use crate::avm1::property::Attribute;
|
||||
use crate::avm1::{Avm1, ScriptObject, TObject, Value};
|
||||
use crate::avm2::object::LoaderInfoObject;
|
||||
use crate::avm2::object::TObject as _;
|
||||
use crate::avm2::{
|
||||
Activation as Avm2Activation, Avm2, CallStack, Domain as Avm2Domain,
|
||||
EventObject as Avm2EventObject,
|
||||
|
@ -907,6 +908,55 @@ impl Player {
|
|||
}
|
||||
}
|
||||
|
||||
if context.is_action_script_3() {
|
||||
if let PlayerEvent::KeyDown { key_code, key_char }
|
||||
| PlayerEvent::KeyUp { key_code, key_char } = event
|
||||
{
|
||||
let mut activation = Avm2Activation::from_nothing(context.reborrow());
|
||||
|
||||
let event_name = match event {
|
||||
PlayerEvent::KeyDown { .. } => "keyDown",
|
||||
PlayerEvent::KeyUp { .. } => "keyUp",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let keyboardevent_class = activation.avm2().classes().keyboardevent;
|
||||
let event_name_val: Avm2Value<'_> =
|
||||
AvmString::new_utf8(activation.context.gc_context, event_name).into();
|
||||
let keyboard_event = keyboardevent_class
|
||||
.construct(
|
||||
&mut activation,
|
||||
&[
|
||||
event_name_val,
|
||||
true.into(), /* bubbles */
|
||||
false.into(), /* cancelable */
|
||||
key_char.map_or(0, |c| c as u32).into(), /* charCode */
|
||||
(key_code as u32).into(), /* keyCode */
|
||||
],
|
||||
)
|
||||
.expect("Failed to construct KeyboardEvent");
|
||||
|
||||
let target = activation
|
||||
.context
|
||||
.focus_tracker
|
||||
.get()
|
||||
.unwrap_or_else(|| activation.context.stage.into())
|
||||
.object2()
|
||||
.coerce_to_object(&mut activation)
|
||||
.expect("DisplayObject is not an object!");
|
||||
|
||||
if let Err(e) =
|
||||
Avm2::dispatch_event(&mut activation.context, keyboard_event, target)
|
||||
{
|
||||
log::error!(
|
||||
"Encountered AVM2 error when broadcasting `{}` event: {}",
|
||||
event_name,
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// keyPress events take precedence over text input.
|
||||
if !key_press_handled {
|
||||
if let PlayerEvent::TextInput { codepoint } = event {
|
||||
|
|
Loading…
Reference in New Issue