diff --git a/core/src/avm2/object/event_object.rs b/core/src/avm2/object/event_object.rs index 417ce9c91..3364f1a01 100644 --- a/core/src/avm2/object/event_object.rs +++ b/core/src/avm2/object/event_object.rs @@ -145,6 +145,35 @@ impl<'gc> EventObject<'gc> { .unwrap() // we don't expect to break here } + pub fn text_event( + activation: &mut Activation<'_, 'gc>, + event_type: S, + text: AvmString<'gc>, + bubbles: bool, + cancelable: bool, + ) -> Object<'gc> + where + S: Into>, + { + let event_type: AvmString<'gc> = event_type.into(); + + let text_event_cls = activation.avm2().classes().textevent; + text_event_cls + .construct( + activation, + &[ + event_type.into(), + // bubbles + bubbles.into(), + // cancelable + cancelable.into(), + // text + text.into(), + ], + ) + .unwrap() // we don't expect to break here + } + pub fn net_status_event( activation: &mut Activation<'_, 'gc>, event_type: S, diff --git a/core/src/display_object/edit_text.rs b/core/src/display_object/edit_text.rs index ddff1bb4d..7fe35b330 100644 --- a/core/src/display_object/edit_text.rs +++ b/core/src/display_object/edit_text.rs @@ -1637,6 +1637,14 @@ impl<'gc> EditText<'gc> { if let Err(e) = self.execute_avm1_asfunction(context, address) { error!("Couldn't execute URL \"{url:?}\": {e:?}"); } + } else if let Some(address) = url.strip_prefix(WStr::from_units(b"event:")) { + if let Avm2Value::Object(object) = self.object2() { + let mut activation = Avm2Activation::from_nothing(context.reborrow()); + let text = AvmString::new(activation.context.gc_context, address); + let event = Avm2EventObject::text_event(&mut activation, "link", text, true, false); + + Avm2::dispatch_event(&mut activation.context, event, object); + } } else { context .navigator diff --git a/tests/tests/swfs/avm2/textfield_event/Test.as b/tests/tests/swfs/avm2/textfield_event/Test.as new file mode 100644 index 000000000..a5e018040 --- /dev/null +++ b/tests/tests/swfs/avm2/textfield_event/Test.as @@ -0,0 +1,47 @@ +package { + + import flash.display.MovieClip; + import flash.text.TextField; + import flash.events.TextEvent; + + + public class Test extends MovieClip { + public var text: TextField; + + public function Test() { + text.htmlText = "" + + "

Click here to call alert 1

" + + "

Or click here to call alert 2

" + + "

this one is empty

" + + "

But this one has lots of args!

" + + ""; + text.addEventListener(TextEvent.LINK, this.onLink); + } + + function onLink(event: TextEvent) { + trace("/// onLink called!"); + trace("// event.text"); + trace(event.text); + trace(""); + + trace("// event.bubbles"); + trace(event.bubbles); + trace(""); + + trace("// event.cancelable"); + trace(event.cancelable); + trace(""); + + trace("// event.currentTarget"); + trace(event.currentTarget); + trace(""); + + trace("// event.target"); + trace(event.target); + trace(""); + + trace(""); + } + } + +} diff --git a/tests/tests/swfs/avm2/textfield_event/input.json b/tests/tests/swfs/avm2/textfield_event/input.json new file mode 100644 index 000000000..81681fc0d --- /dev/null +++ b/tests/tests/swfs/avm2/textfield_event/input.json @@ -0,0 +1,42 @@ +[ + { + "type": "MouseDown", + "pos": [134, 69], + "btn": "Left" + }, + { + "type": "MouseUp", + "pos": [134, 69], + "btn": "Left" + }, + { + "type": "MouseDown", + "pos": [166, 95], + "btn": "Left" + }, + { + "type": "MouseUp", + "pos": [166, 95], + "btn": "Left" + }, + { + "type": "MouseDown", + "pos": [143, 128], + "btn": "Left" + }, + { + "type": "MouseUp", + "pos": [143, 128], + "btn": "Left" + }, + { + "type": "MouseDown", + "pos": [142, 160], + "btn": "Left" + }, + { + "type": "MouseUp", + "pos": [142, 160], + "btn": "Left" + } +] \ No newline at end of file diff --git a/tests/tests/swfs/avm2/textfield_event/output.txt b/tests/tests/swfs/avm2/textfield_event/output.txt new file mode 100644 index 000000000..67997dea0 --- /dev/null +++ b/tests/tests/swfs/avm2/textfield_event/output.txt @@ -0,0 +1,68 @@ +/// onLink called! +// event.text +alert1 + +// event.bubbles +true + +// event.cancelable +false + +// event.currentTarget +[object TextField] + +// event.target +[object TextField] + + +/// onLink called! +// event.text +Second Test + +// event.bubbles +true + +// event.cancelable +false + +// event.currentTarget +[object TextField] + +// event.target +[object TextField] + + +/// onLink called! +// event.text + + +// event.bubbles +true + +// event.cancelable +false + +// event.currentTarget +[object TextField] + +// event.target +[object TextField] + + +/// onLink called! +// event.text +a,b,c,d + +// event.bubbles +true + +// event.cancelable +false + +// event.currentTarget +[object TextField] + +// event.target +[object TextField] + + diff --git a/tests/tests/swfs/avm2/textfield_event/test.fla b/tests/tests/swfs/avm2/textfield_event/test.fla new file mode 100644 index 000000000..7095be6fc Binary files /dev/null and b/tests/tests/swfs/avm2/textfield_event/test.fla differ diff --git a/tests/tests/swfs/avm2/textfield_event/test.swf b/tests/tests/swfs/avm2/textfield_event/test.swf new file mode 100644 index 000000000..3bc0ea4e8 Binary files /dev/null and b/tests/tests/swfs/avm2/textfield_event/test.swf differ diff --git a/tests/tests/swfs/avm2/textfield_event/test.toml b/tests/tests/swfs/avm2/textfield_event/test.toml new file mode 100644 index 000000000..cf6123969 --- /dev/null +++ b/tests/tests/swfs/avm2/textfield_event/test.toml @@ -0,0 +1 @@ +num_ticks = 1