diff --git a/core/src/display_object/avm2_button.rs b/core/src/display_object/avm2_button.rs index f66b1badd..f92f8d220 100644 --- a/core/src/display_object/avm2_button.rs +++ b/core/src/display_object/avm2_button.rs @@ -805,6 +805,8 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> { self.set_state(context, new_state); } + self.event_dispatch_to_avm2(context, event); + handled } } diff --git a/core/src/display_object/edit_text.rs b/core/src/display_object/edit_text.rs index 95fbbe5a6..cebe9338e 100644 --- a/core/src/display_object/edit_text.rs +++ b/core/src/display_object/edit_text.rs @@ -1821,7 +1821,7 @@ impl<'gc> TInteractiveObject<'gc> for EditText<'gc> { fn event_dispatch( self, context: &mut UpdateContext<'_, 'gc, '_>, - _event: ClipEvent, + event: ClipEvent, ) -> ClipEventResult { let tracker = context.focus_tracker; tracker.set(Some(self.into()), context); @@ -1835,6 +1835,8 @@ impl<'gc> TInteractiveObject<'gc> for EditText<'gc> { Some(TextSelection::for_position(self.text_length())); } + self.event_dispatch_to_avm2(context, event); + ClipEventResult::Handled } } diff --git a/core/src/display_object/interactive.rs b/core/src/display_object/interactive.rs index d80bf96bc..fa9501ba7 100644 --- a/core/src/display_object/interactive.rs +++ b/core/src/display_object/interactive.rs @@ -1,6 +1,6 @@ //! Interactive object enumtrait -use crate::avm2::Value; +use crate::avm2::{Avm2, Event as Avm2Event, EventData as Avm2EventData, Value as Avm2Value}; use crate::context::UpdateContext; use crate::display_object::avm1_button::Avm1Button; use crate::display_object::avm2_button::Avm2Button; @@ -36,7 +36,7 @@ bitflags! { pub struct InteractiveObjectBase<'gc> { pub base: DisplayObjectBase<'gc>, flags: InteractiveObjectFlags, - context_menu: Value<'gc>, + context_menu: Avm2Value<'gc>, } impl<'gc> Default for InteractiveObjectBase<'gc> { @@ -44,7 +44,7 @@ impl<'gc> Default for InteractiveObjectBase<'gc> { Self { base: Default::default(), flags: InteractiveObjectFlags::MOUSE_ENABLED, - context_menu: Value::Null, + context_menu: Avm2Value::Null, } } } @@ -97,11 +97,11 @@ pub trait TInteractiveObject<'gc>: .set(InteractiveObjectFlags::DOUBLE_CLICK_ENABLED, value) } - fn context_menu(self) -> Value<'gc> { + fn context_menu(self) -> Avm2Value<'gc> { self.ibase().context_menu } - fn set_context_menu(self, mc: MutationContext<'gc, '_>, value: Value<'gc>) { + fn set_context_menu(self, mc: MutationContext<'gc, '_>, value: Avm2Value<'gc>) { self.ibase_mut(mc).context_menu = value; } @@ -150,6 +150,48 @@ pub trait TInteractiveObject<'gc>: _event: ClipEvent, ) -> ClipEventResult; + /// Convert the clip event into an AVM2 event and dispatch it into the + /// AVM2 side of this object. + /// + /// This is only intended to be called for events defined by + /// `InteractiveObject` itself. Display object impls that have their own + /// event types should dispatch them in `event_dispatch`. + fn event_dispatch_to_avm2(self, context: &mut UpdateContext<'_, 'gc, '_>, event: ClipEvent) { + let target = if let Avm2Value::Object(target) = self.as_displayobject().object2() { + target + } else { + return; + }; + + match event { + ClipEvent::MouseDown => { + let mut avm2_event = Avm2Event::new( + "mouseDown", + Avm2EventData::mouse_event(context, self.as_displayobject(), None, 0), + ); + + avm2_event.set_bubbles(true); + + if let Err(e) = Avm2::dispatch_event(context, avm2_event, target) { + log::error!("Got error when dispatching {:?} to AVM2: {}", event, e); + } + } + ClipEvent::MouseUp => { + let mut avm2_event = Avm2Event::new( + "mouseUp", + Avm2EventData::mouse_event(context, self.as_displayobject(), None, 0), + ); + + avm2_event.set_bubbles(true); + + if let Err(e) = Avm2::dispatch_event(context, avm2_event, target) { + log::error!("Got error when dispatching {:?} to AVM2: {}", event, e); + } + } + _ => {} + }; + } + /// Executes and propagates the given clip event. /// Events execute inside-out; the deepest child will react first, followed /// by its parent, and so forth. diff --git a/core/src/display_object/movie_clip.rs b/core/src/display_object/movie_clip.rs index cc584229a..d5c4ac823 100644 --- a/core/src/display_object/movie_clip.rs +++ b/core/src/display_object/movie_clip.rs @@ -2179,6 +2179,8 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> { } } } + } else { + self.event_dispatch_to_avm2(context, event); } handled diff --git a/core/src/display_object/stage.rs b/core/src/display_object/stage.rs index 9f87b83be..634fec0ad 100644 --- a/core/src/display_object/stage.rs +++ b/core/src/display_object/stage.rs @@ -720,6 +720,8 @@ impl<'gc> TInteractiveObject<'gc> for Stage<'gc> { _context: &mut UpdateContext<'_, 'gc, '_>, _event: ClipEvent, ) -> ClipEventResult { + //NOTE: Stage does not appear to fire common InteractiveObject events + //within AVM2. ClipEventResult::Handled } }