Skip to content

Commit cff84e2

Browse files
Robert Lichtenbergeraghaisas
authored andcommitted
8283509: Invisible menus can lead to IndexOutOfBoundsException
Reviewed-by: aghaisas
1 parent a0db473 commit cff84e2

File tree

2 files changed

+30
-12
lines changed

2 files changed

+30
-12
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@
9090
import com.sun.javafx.scene.control.GlobalMenuAdapter;
9191
import com.sun.javafx.tk.Toolkit;
9292
import java.util.function.Predicate;
93+
import java.util.stream.Collectors;
94+
9395
import javafx.stage.Window;
9496
import javafx.util.Pair;
9597

@@ -1110,11 +1112,13 @@ private Optional<Pair<Menu,Integer>> findSibling(Direction dir, int startIndex)
11101112
return Optional.empty();
11111113
}
11121114

1113-
final int totalMenus = getSkinnable().getMenus().size();
1115+
List<Menu> visibleMenus = getSkinnable().getMenus().stream().filter(Menu::isVisible)
1116+
.collect(Collectors.toList());
1117+
final int totalMenus = visibleMenus.size();
11141118
int i = 0;
11151119
int nextIndex = 0;
11161120

1117-
// Traverse all menus in menubar to find nextIndex
1121+
// Traverse all visible menus in menubar to find nextIndex
11181122
while (i < totalMenus) {
11191123
i++;
11201124

@@ -1126,7 +1130,7 @@ private Optional<Pair<Menu,Integer>> findSibling(Direction dir, int startIndex)
11261130
}
11271131

11281132
// if menu at nextIndex is disabled, skip it
1129-
if (getSkinnable().getMenus().get(nextIndex).isDisable()) {
1133+
if (visibleMenus.get(nextIndex).isDisable()) {
11301134
// Calculate new nextIndex by continuing loop
11311135
startIndex = nextIndex;
11321136
} else {
@@ -1136,7 +1140,7 @@ private Optional<Pair<Menu,Integer>> findSibling(Direction dir, int startIndex)
11361140
}
11371141

11381142
clearMenuButtonHover();
1139-
return Optional.of(new Pair<>(getSkinnable().getMenus().get(nextIndex), nextIndex));
1143+
return Optional.of(new Pair<>(visibleMenus.get(nextIndex), nextIndex));
11401144
}
11411145

11421146
private void updateFocusedIndex() {

modules/javafx.controls/src/test/java/test/javafx/scene/control/skin/MenuBarSkinTest.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,29 @@
2828
import static org.junit.Assert.assertEquals;
2929
import static org.junit.Assert.assertTrue;
3030

31+
import java.util.List;
32+
33+
import org.junit.Before;
34+
import org.junit.BeforeClass;
35+
import org.junit.Test;
36+
3137
import com.sun.javafx.menu.MenuBase;
3238
import com.sun.javafx.stage.WindowHelper;
33-
import test.com.sun.javafx.pgstub.StubToolkit;
3439
import com.sun.javafx.tk.Toolkit;
40+
3541
import javafx.beans.value.ObservableValue;
3642
import javafx.geometry.Insets;
3743
import javafx.scene.Group;
3844
import javafx.scene.Scene;
3945
import javafx.scene.control.Menu;
4046
import javafx.scene.control.MenuBar;
4147
import javafx.scene.control.MenuItem;
42-
import javafx.stage.Stage;
43-
44-
import java.util.List;
4548
import javafx.scene.control.skin.MenuBarSkin;
46-
47-
import org.junit.Before;
48-
import org.junit.BeforeClass;
49-
import org.junit.Test;
49+
import javafx.scene.control.skin.MenuBarSkinShim;
50+
import javafx.scene.input.KeyCode;
51+
import javafx.stage.Stage;
52+
import test.com.sun.javafx.pgstub.StubToolkit;
53+
import test.com.sun.javafx.scene.control.infrastructure.KeyEventFirer;
5054

5155
/**
5256
* This fails with IllegalStateException because of the toolkit's check for the FX application thread
@@ -194,6 +198,16 @@ public class MenuBarSkinTest {
194198
}
195199
}
196200

201+
@Test
202+
public void testInvisibleMenuNavigation() {
203+
menubar.getMenus().get(0).setVisible(false);
204+
MenuBarSkinShim.setFocusedMenuIndex(skin, 0);
205+
206+
KeyEventFirer keyboard = new KeyEventFirer(menubar);
207+
keyboard.doKeyPress(KeyCode.LEFT);
208+
tk.firePulse();
209+
}
210+
197211
public static final class MenuBarSkinMock extends MenuBarSkin {
198212
boolean propertyChanged = false;
199213
int propertyChangeCount = 0;

0 commit comments

Comments
 (0)