core: AVM2 wants the same semantics as `Press`/`Release`, not `MouseDown`/`MouseUp`.

`MouseDown`/`MouseUp` are effectively broadcasts; they hit every movie clip that can accept them until one of them has a handler for it. AVM2 instead wants events that only apply to specific mouse-picked display objects, which means we need to use the Player-tracked events `Press`, `Release`, and `ReleaseOutside`. The only problem is that we also need to emit a `mouseUp` event on both `Release` and `ReleaseOutside`.
This commit is contained in:
David Wendt 2021-12-04 20:59:56 -05:00 committed by Mike Welsh
parent f0ab17c979
commit 9d4b222b29
3 changed files with 52 additions and 11 deletions

View File

@ -781,7 +781,6 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> {
context: &mut UpdateContext<'_, 'gc, '_>,
event: ClipEvent,
) -> ClipEventResult {
let handled = ClipEventResult::NotHandled;
let write = self.0.write(context.gc_context);
// Translate the clip event to a button event, based on how the button state changes.
@ -805,9 +804,7 @@ impl<'gc> TInteractiveObject<'gc> for Avm2Button<'gc> {
self.set_state(context, new_state);
}
self.event_dispatch_to_avm2(context, event);
handled
self.event_dispatch_to_avm2(context, event)
}
}

View File

@ -156,15 +156,19 @@ pub trait TInteractiveObject<'gc>:
/// 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) {
fn event_dispatch_to_avm2(
self,
context: &mut UpdateContext<'_, 'gc, '_>,
event: ClipEvent,
) -> ClipEventResult {
let target = if let Avm2Value::Object(target) = self.as_displayobject().object2() {
target
} else {
return;
return ClipEventResult::NotHandled;
};
match event {
ClipEvent::MouseDown => {
ClipEvent::Press => {
let mut avm2_event = Avm2Event::new(
"mouseDown",
Avm2EventData::mouse_event(context, self.as_displayobject(), None, 0),
@ -175,8 +179,10 @@ pub trait TInteractiveObject<'gc>:
if let Err(e) = Avm2::dispatch_event(context, avm2_event, target) {
log::error!("Got error when dispatching {:?} to AVM2: {}", event, e);
}
ClipEventResult::Handled
}
ClipEvent::MouseUp => {
ClipEvent::Release => {
let mut avm2_event = Avm2Event::new(
"mouseUp",
Avm2EventData::mouse_event(context, self.as_displayobject(), None, 0),
@ -187,9 +193,47 @@ pub trait TInteractiveObject<'gc>:
if let Err(e) = Avm2::dispatch_event(context, avm2_event, target) {
log::error!("Got error when dispatching {:?} to AVM2: {}", event, e);
}
let mut avm2_event = Avm2Event::new(
"click",
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);
}
ClipEventResult::Handled
}
_ => {}
};
ClipEvent::ReleaseOutside => {
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);
}
let mut avm2_event = Avm2Event::new(
"releaseOutside",
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);
}
ClipEventResult::Handled
}
_ => ClipEventResult::NotHandled,
}
}
/// Executes and propagates the given clip event.

View File

@ -2205,7 +2205,7 @@ impl<'gc> TInteractiveObject<'gc> for MovieClip<'gc> {
}
}
} else {
self.event_dispatch_to_avm2(context, event);
handled = self.event_dispatch_to_avm2(context, event);
}
handled