Skip to content

Commit 379fd85

Browse files
committed
8277369: Strange behavior of JMenuBar with RIGHT_TO_LEFT orientation, arrow keys behaves opposite traversing through keyboard
Reviewed-by: prr, naoto, serb
1 parent cd3e59e commit 379fd85

File tree

2 files changed

+185
-1
lines changed

2 files changed

+185
-1
lines changed

src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2022, 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
@@ -32,6 +32,7 @@
3232
import java.applet.Applet;
3333

3434
import java.awt.Component;
35+
import java.awt.ComponentOrientation;
3536
import java.awt.KeyboardFocusManager;
3637
import java.awt.Window;
3738
import java.awt.event.*;
@@ -536,6 +537,11 @@ private void selectParentChild(boolean direction) {
536537
// If this is the case, we select another toplevel menu
537538
if (len > 1 && path[0] instanceof JMenuBar) {
538539
MenuElement currentMenu = path[1];
540+
// direction traversal to be reversed for RTL orientation
541+
if (path[0].getComponent().getComponentOrientation().
542+
equals(ComponentOrientation.RIGHT_TO_LEFT)) {
543+
direction = !direction;
544+
}
539545
MenuElement nextMenu = findEnabledChild(
540546
path[0].getSubElements(), currentMenu, direction);
541547

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
import java.awt.BorderLayout;
24+
import java.awt.ComponentOrientation;
25+
import java.awt.Point;
26+
import java.awt.event.ActionEvent;
27+
import java.awt.event.ActionListener;
28+
import java.awt.event.InputEvent;
29+
import java.awt.event.KeyEvent;
30+
import java.awt.Robot;
31+
32+
import javax.swing.JFrame;
33+
import javax.swing.JMenu;
34+
import javax.swing.JMenuBar;
35+
import javax.swing.JMenuItem;
36+
import javax.swing.event.ChangeEvent;
37+
import javax.swing.event.ChangeListener;
38+
import javax.swing.event.MenuEvent;
39+
import javax.swing.event.MenuListener;
40+
import javax.swing.SwingUtilities;
41+
import javax.swing.UIManager;
42+
import javax.swing.UnsupportedLookAndFeelException;
43+
44+
/*
45+
* @test
46+
* @key headful
47+
* @bug 8277369
48+
* @summary Verifies arrow traversal in RTL orientation in JMenuBar
49+
*/
50+
public class MenuBarRTLBug {
51+
52+
static JFrame frame;
53+
static JMenuBar menuBar;
54+
static JMenu firstMenu;
55+
static JMenuItem a;
56+
static JMenuItem b;
57+
static JMenu secondMenu;
58+
static JMenuItem c;
59+
static JMenuItem d;
60+
static JMenu thirdMenu;
61+
static JMenuItem e;
62+
static JMenuItem f;
63+
static JMenu forthMenu;
64+
static JMenu fifthMenu;
65+
66+
static Point p;
67+
static int width;
68+
static int height;
69+
70+
static volatile boolean passed = false;
71+
72+
private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) {
73+
try {
74+
UIManager.setLookAndFeel(laf.getClassName());
75+
} catch (UnsupportedLookAndFeelException ignored) {
76+
System.out.println("Unsupported L&F: " + laf.getClassName());
77+
} catch (ClassNotFoundException | InstantiationException
78+
| IllegalAccessException e) {
79+
throw new RuntimeException(e);
80+
}
81+
}
82+
83+
public static void main(String[] args) throws Exception {
84+
85+
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
86+
System.out.println("Testing L&F: " + laf.getClassName());
87+
passed = false;
88+
SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf));
89+
try {
90+
SwingUtilities.invokeAndWait(() -> {
91+
frame = new JFrame();
92+
frame.setLayout(new BorderLayout());
93+
94+
firstMenu = new JMenu("first");
95+
a = new JMenuItem("a");
96+
b = new JMenuItem("b");
97+
firstMenu.add(a);
98+
firstMenu.add(b);
99+
100+
secondMenu = new JMenu("second");
101+
c = new JMenuItem("c");
102+
d = new JMenuItem("d");
103+
secondMenu.add(c);
104+
secondMenu.add(d);
105+
secondMenu.addMenuListener(new MenuListener() {
106+
@Override
107+
public void menuSelected(MenuEvent e) {
108+
passed = true;
109+
}
110+
@Override
111+
public void menuDeselected(MenuEvent e) {
112+
}
113+
114+
@Override
115+
public void menuCanceled(MenuEvent e) {
116+
}
117+
});
118+
119+
thirdMenu = new JMenu("third");
120+
e = new JMenuItem("e");
121+
f = new JMenuItem("f");
122+
thirdMenu.add(e);
123+
thirdMenu.add(f);
124+
125+
forthMenu = new JMenu("fourth");
126+
e = new JMenuItem("e");
127+
f = new JMenuItem("f");
128+
forthMenu.add(e);
129+
forthMenu.add(f);
130+
131+
fifthMenu = new JMenu("fifth");
132+
e = new JMenuItem("e");
133+
f = new JMenuItem("f");
134+
fifthMenu.add(e);
135+
fifthMenu.add(f);
136+
137+
menuBar = new JMenuBar();
138+
menuBar.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
139+
menuBar.add(firstMenu);
140+
menuBar.add(secondMenu);
141+
menuBar.add(thirdMenu);
142+
menuBar.add(forthMenu);
143+
menuBar.add(fifthMenu);
144+
frame.setJMenuBar(menuBar);
145+
146+
frame.setLocationRelativeTo(null);
147+
frame.pack();
148+
frame.setVisible(true);
149+
});
150+
Robot robot = new Robot();
151+
robot.setAutoDelay(100);
152+
robot.waitForIdle();
153+
robot.delay(1000);
154+
SwingUtilities.invokeAndWait(() -> {
155+
p = thirdMenu.getLocationOnScreen();
156+
width = thirdMenu.getWidth();
157+
height = thirdMenu.getHeight();
158+
});
159+
robot.mouseMove(p.x + width / 2, p.y + height / 2);
160+
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
161+
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
162+
robot.delay(1000);
163+
robot.keyPress(KeyEvent.VK_RIGHT);
164+
robot.keyRelease(KeyEvent.VK_RIGHT);
165+
robot.delay(1000);
166+
if (!passed) {
167+
throw new RuntimeException("Arrow traversal order not correct in RTL orientation");
168+
}
169+
} finally {
170+
SwingUtilities.invokeAndWait(() -> {
171+
if (frame != null) {
172+
frame.dispose();
173+
}
174+
});
175+
}
176+
}
177+
}
178+
}

0 commit comments

Comments
 (0)