Skip to content

Commit 818ac00

Browse files
committed
8175358: Memory leak when moving MenuButton into another Scene
Reviewed-by: fastegal, arapte
1 parent 91d4c8b commit 818ac00

File tree

2 files changed

+46
-2
lines changed

2 files changed

+46
-2
lines changed

modules/javafx.controls/src/main/java/javafx/scene/control/skin/MenuButtonSkinBase.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -147,6 +147,10 @@ public MenuButtonSkinBase(final C control) {
147147
ControlAcceleratorSupport.addAcceleratorsIntoScene(getSkinnable().getItems(), getSkinnable());
148148
}
149149
control.sceneProperty().addListener((scene, oldValue, newValue) -> {
150+
if (oldValue != null) {
151+
ControlAcceleratorSupport.removeAcceleratorsFromScene(getSkinnable().getItems(), oldValue);
152+
}
153+
150154
if (getSkinnable() != null && getSkinnable().getScene() != null) {
151155
ControlAcceleratorSupport.addAcceleratorsIntoScene(getSkinnable().getItems(), getSkinnable());
152156
}

modules/javafx.controls/src/test/java/test/javafx/scene/control/MenuItemTest.java

+41-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,9 @@
2525

2626
package test.javafx.scene.control;
2727

28+
import test.com.sun.javafx.scene.control.infrastructure.KeyEventFirer;
29+
import test.com.sun.javafx.scene.control.infrastructure.KeyModifier;
30+
import test.com.sun.javafx.scene.control.infrastructure.StageLoader;
2831
import javafx.beans.property.ObjectProperty;
2932
import javafx.beans.property.SimpleBooleanProperty;
3033
import javafx.beans.property.SimpleObjectProperty;
@@ -33,10 +36,14 @@
3336
import javafx.event.Event;
3437
import javafx.event.EventHandler;
3538
import javafx.event.EventType;
39+
import javafx.scene.Group;
3640
import javafx.scene.Node;
41+
import javafx.scene.Scene;
3742
import javafx.scene.control.Menu;
43+
import javafx.scene.control.MenuButton;
3844
import javafx.scene.control.MenuItem;
3945
import javafx.scene.input.KeyCharacterCombination;
46+
import javafx.scene.input.KeyCode;
4047
import javafx.scene.input.KeyCodeCombination;
4148
import javafx.scene.input.KeyCombination;
4249
import javafx.scene.input.KeyCombination.Modifier;
@@ -581,4 +588,37 @@ public static final class NewEventHandlerStub implements EventHandler<Event> {
581588
menuItem.getProperties().put(null, null);
582589
assertTrue(menuItem.getProperties().size() > 0);
583590
}
591+
592+
private int eventCounter = 0;
593+
@Test public void testAcceleratorIsNotFiredWhenMenuItemRemovedFromScene() {
594+
MenuItem item = new MenuItem("Item 1");
595+
item.setOnAction(e -> eventCounter++);
596+
item.setAccelerator(KeyCombination.valueOf("alt+1"));
597+
598+
MenuButton menuButton = new MenuButton();
599+
menuButton.getItems().add(item);
600+
601+
StageLoader s = new StageLoader(menuButton);
602+
Scene scene = s.getStage().getScene();
603+
KeyEventFirer keyboard = new KeyEventFirer(item, scene);
604+
605+
// Invoke MenuItem's action listener twice by using accelerator KeyCombination
606+
keyboard.doKeyPress(KeyCode.DIGIT1, KeyModifier.ALT);
607+
assertEquals(1, eventCounter);
608+
609+
keyboard.doKeyPress(KeyCode.DIGIT1, KeyModifier.ALT);
610+
assertEquals(2, eventCounter);
611+
612+
// Remove all children from the scene
613+
Group root = (Group)scene.getRoot();
614+
root.getChildren().clear();
615+
616+
// Assert that the MenuItem's action listener is not invoked
617+
// after MenuItem has been removed from the scene
618+
keyboard.doKeyPress(KeyCode.DIGIT1, KeyModifier.ALT);
619+
assertEquals(2, eventCounter);
620+
621+
// Assert that key combination does not remain in the scene's list of accelerators
622+
assertFalse(scene.getAccelerators().containsKey(KeyCombination.keyCombination("alt+1")));
623+
}
584624
}

0 commit comments

Comments
 (0)