Skip to content

core: Fix MovieClip's AVM2 mouse picking for AVM1 content#23468

Open
ChrisCPI wants to merge 1 commit intoruffle-rs:masterfrom
ChrisCPI:fix-mixed-avm-mouse-pick
Open

core: Fix MovieClip's AVM2 mouse picking for AVM1 content#23468
ChrisCPI wants to merge 1 commit intoruffle-rs:masterfrom
ChrisCPI:fix-mixed-avm-mouse-pick

Conversation

@ChrisCPI
Copy link
Copy Markdown
Contributor

@ChrisCPI ChrisCPI commented Apr 16, 2026

Refactors the setting of the res value so that if mouse_pick_avm1 on the child returns None, instead of counting it as a Miss, it will allow the hit_test_shape check to happen, so that the pick can correctly propagate to the parent.

Prior to this, an AVM1 child would not respect mouseChildren on its parent, and landing on a non-interactive AVM1 object would just go through to the stage (or whatever would happen to be below it).

I also plan on making a follow up PR to apply a similar fix to LoaderDisplay.

@ChrisCPI ChrisCPI force-pushed the fix-mixed-avm-mouse-pick branch from 3d5e4c7 to 10c5556 Compare April 16, 2026 21:43
Comment thread core/src/display_object/movie_clip.rs Outdated
@ChrisCPI ChrisCPI force-pushed the fix-mixed-avm-mouse-pick branch 2 times, most recently from d82beed to 5ff719a Compare April 17, 2026 00:25
@ChrisCPI ChrisCPI requested a review from kjarosh April 17, 2026 00:37
@ChrisCPI
Copy link
Copy Markdown
Contributor Author

The only downside to this new approach is that it runs mouse_pick_avm1 twice, but not sure how I could get around that.

@ChrisCPI
Copy link
Copy Markdown
Contributor Author

Another possible option, which moves the hit_test_shape check to its own function and runs that twice. Would this be better?

                let hit_test_shape = |context: &mut UpdateContext<'gc>| {
                    if child.hit_test_shape(context, point, options)
                        && child
                            .masker()
                            .map(|mask| mask.hit_test_shape(context, point, options))
                            .unwrap_or(true)
                    {
                        if self.mouse_enabled() {
                            Avm2MousePick::Hit(this)
                        } else {
                            Avm2MousePick::PropagateToParent
                        }
                    } else {
                        Avm2MousePick::Miss
                    }
                };

                let mut res = if let Some(child) = child.as_interactive() {
                    if child.as_displayobject().movie().is_action_script_3() {
                        child.mouse_pick_avm2(context, point, require_button_mode)
                    } else {
                        let avm1_result =
                            child.mouse_pick_avm1(context, point, require_button_mode);
                        if let Some(result) = avm1_result {
                            Avm2MousePick::Hit(result)
                        } else {
                            hit_test_shape(context)
                        }
                    }
                } else {
                    hit_test_shape(context)
                };

Refactors the setting of the `res` value so that if `mouse_pick_avm1` on the child returns `None`, instead of counting it as a `Miss`, it will allow the `hit_test_shape` check to happen, so that the pick can correctly propagate to the parent.

Prior to this, an AVM1 child would not respect `mouseChildren` on its parent, and landing on a non-interactive AVM1 object would just go through to the stage (or whatever would happen to be below it).
@ChrisCPI ChrisCPI force-pushed the fix-mixed-avm-mouse-pick branch from 5ff719a to 758b8b7 Compare April 19, 2026 00:57
@ChrisCPI
Copy link
Copy Markdown
Contributor Author

Sorry for going back and forth on this, but I've finally landed on a solution I think I'm happy with.

@Lord-McSweeney Lord-McSweeney added A-core Area: Core player, where no other category fits T-compat Type: Compatibility with Flash Player labels Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-core Area: Core player, where no other category fits T-compat Type: Compatibility with Flash Player

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants