On Wed, 30 Nov 2022 18:43:42 GMT, Andy Goryachev <ango...@openjdk.org> wrote:

>> Fixed memory leak by using weak listeners and making sure to undo everything 
>> that has been done to MenuBar/Skin in dispose().
>> 
>> This PR depends on a new internal class ListenerHelper, a replacement for 
>> LambdaMultiplePropertyChangeListenerHandler.
>> See https://github.com/openjdk/jfx/pull/908
>
> Andy Goryachev has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   8294589: cleanup

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuBarSkin.java
 line 286:

> 284:         ParentHelper.setTraversalEngine(getSkinnable(), engine);
> 285: 
> 286:         lh.addChangeListener(control.sceneProperty(), true, (scene) -> {

minor: generally, the parenthesis are omitted for lambda's with one parameter 
(multiple occurences)

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuBarSkin.java
 line 293:

> 291: 
> 292:             if (scene != null ) {
> 293:                 sceneListenerHelper = new 
> ListenerHelper(MenuBarSkin.this);

Why does this (still) need to rely on a weak reference?  Skins have a well 
specified life cycle do they not?

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuBarSkin.java
 line 360:

> 358:                                 break;
> 359:                         default:
> 360:                             break;

minor: indent is incorrect (also in original)

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuBarSkin.java
 line 374:

> 372: 
> 373:                 // When the parent window looses focus - menu selection 
> should be cleared
> 374:                 
> sceneListenerHelper.addChangeListener(scene.windowProperty(), true, (sr, 
> oldw, w) -> {

Suggestion:

                sceneListenerHelper.addChangeListener(scene.windowProperty(), 
true, w -> {

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuBarSkin.java
 line 381:

> 379: 
> 380:                     if (w != null) {
> 381:                         windowFocusHelper = 
> sceneListenerHelper.addChangeListener(w.focusedProperty(), true, (s, p, 
> focused) -> {

Suggestion:

                        windowFocusHelper = 
sceneListenerHelper.addChangeListener(w.focusedProperty(), true, focused -> {

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuBarSkin.java
 line 387:

> 385:                         });
> 386:                     }
> 387:                 });

The goal seems to be to subscribe to changes on scene->window->focused.

This can be done with `flatMap` / `orElse`.

Suggestion:

                // When the parent window looses focus - menu selection should 
be cleared
                sceneListenerHelper.addChangeListener(
                    scene.windowProperty()
                         .flatMap(Window::focusedProperty)
                         .orElse(false), 
                    true, 
                    focused -> {
                        if (!focused) {
                            unSelectMenus();
                        }
                    }
                );


You could even do this at the top level I think:

    lh.addChangeListener(
        control.sceneProperty()
            .flatMap(Scene::windowProperty)
            .flatMap(Window::focusedProperty)
            .orElse(false), 
        true, 
        focused -> {
            if (!focused) {
                unSelectMenus();
            }
        }
    );

Also available is to make use of `Subscription`:

        Subscription sub = 
Subscription.subscribe(scene.windowProperty().flatMap(Window::focusedProperty).orElse(false),
 focused -> {
              if (!focused) {
                  unSelectMenus();
              }
        });

The subscription can then be integrated with `ListenerHelper` again (or even 
more directly if it accepted `Subscription`):

        lh.addDisconnectable(sub::unsubscribe);

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuBarSkin.java
 line 436:

> 434:                 if (weakSceneAltKeyEventHandler != null) {
> 435:                     t.removeEventHandler(KeyEvent.ANY, 
> weakSceneAltKeyEventHandler);
> 436:                 }

So, am I correct that `MenuBarSkin` was badly broken before as it never 
re-registers these weak handlers when the scene changes?  It does re-register 
the F10 accelerator, but that's all I can see.

So a scenario where I have a MenuBar, and I move it to another Scene, it would 
basically no longer fully function?

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuBarSkin.java
 line 1180:

> 1178: 
> 1179:     private static final CssMetaData<MenuBar,Pos> ALIGNMENT =
> 1180:             new CssMetaData<>("-fx-alignment", new 
> EnumConverter<Pos>(Pos.class), Pos.TOP_LEFT ) {

minor: You can use the diamond operator here, probably came from the merge 
conflict

Suggestion:

            new CssMetaData<>("-fx-alignment", new EnumConverter<>(Pos.class), 
Pos.TOP_LEFT) {

modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/SkinMemoryLeakTest.java
 line 227:

> 225:                 ComboBox.class,
> 226:                 DatePicker.class,
> 227:                 //MenuBar.class,

minor: commented out code

-------------

PR: https://git.openjdk.org/jfx/pull/906

Reply via email to