Skip to content

Commit 00f2b3f

Browse files
committed
8281988: Create a regression test for JDK-4618767
Backport-of: 43dc9ef619b823e033cb1e298bbc091eb5a50967
1 parent 3a57cc6 commit 00f2b3f

File tree

1 file changed

+222
-0
lines changed

1 file changed

+222
-0
lines changed
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/*
2+
* Copyright (c) 2002, 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+
24+
import java.awt.Robot;
25+
import java.awt.event.FocusAdapter;
26+
import java.awt.event.FocusEvent;
27+
import java.awt.event.KeyEvent;
28+
import java.util.Arrays;
29+
import java.util.List;
30+
import java.util.concurrent.CountDownLatch;
31+
import java.util.concurrent.TimeUnit;
32+
import java.util.concurrent.atomic.AtomicBoolean;
33+
import java.util.concurrent.atomic.AtomicReference;
34+
import java.util.stream.Collectors;
35+
import javax.swing.JFrame;
36+
import javax.swing.JList;
37+
import javax.swing.JMenu;
38+
import javax.swing.JMenuBar;
39+
import javax.swing.JMenuItem;
40+
import javax.swing.SwingUtilities;
41+
import javax.swing.UIManager;
42+
import javax.swing.UIManager.LookAndFeelInfo;
43+
import javax.swing.UnsupportedLookAndFeelException;
44+
import javax.swing.event.MenuEvent;
45+
import javax.swing.event.MenuListener;
46+
47+
48+
import static javax.swing.UIManager.getInstalledLookAndFeels;
49+
50+
/*
51+
* @test
52+
* @key headful
53+
* @bug 4618767
54+
* @summary This test confirms that typing a letter while a JList has focus now makes the selection
55+
* not jump to the item whose text starts with that letter if that typed letter is accompanied
56+
* by modifier keys such as ALT or CTRL(eg: ALT+F).
57+
* @run main JListSelectedElementTest
58+
*/
59+
public class JListSelectedElementTest {
60+
61+
private static final int FILE_MENU = KeyEvent.VK_F;
62+
private static JFrame frame;
63+
private static JList<String> list;
64+
private static Robot robot;
65+
private static CountDownLatch listGainedFocusLatch;
66+
private static CountDownLatch menuSelectedEventLatch;
67+
68+
public static void main(String[] args) throws Exception {
69+
runTest();
70+
}
71+
72+
public static void runTest() throws Exception {
73+
robot = new Robot();
74+
robot.setAutoWaitForIdle(true);
75+
robot.setAutoDelay(200);
76+
77+
final boolean isMac = System.getProperty("os.name")
78+
.toLowerCase()
79+
.contains("os x");
80+
81+
List<String> lafs = Arrays.stream(getInstalledLookAndFeels())
82+
.map(LookAndFeelInfo::getClassName)
83+
.collect(Collectors.toList());
84+
for (final String laf : lafs) {
85+
listGainedFocusLatch = new CountDownLatch(1);
86+
menuSelectedEventLatch = new CountDownLatch(1);
87+
try {
88+
AtomicBoolean lafSetSuccess = new AtomicBoolean(false);
89+
SwingUtilities.invokeAndWait(() -> {
90+
lafSetSuccess.set(setLookAndFeel(laf));
91+
if (lafSetSuccess.get()) {
92+
createUI();
93+
}
94+
});
95+
if (!lafSetSuccess.get()) {
96+
continue;
97+
}
98+
robot.waitForIdle();
99+
100+
// Wait until the list gains focus.
101+
if (!listGainedFocusLatch.await(3, TimeUnit.SECONDS)) {
102+
throw new RuntimeException("Waited too long, but can't gain focus for list");
103+
}
104+
105+
// Select element named as 'bill'
106+
hitKeys(KeyEvent.VK_B);
107+
108+
// Assertion check to verify that the selected node is 'bill'
109+
AtomicReference<String> elementSel = new AtomicReference<>();
110+
SwingUtilities.invokeAndWait(() -> elementSel.set(list.getSelectedValue()));
111+
final String elementSelBefore = elementSel.get();
112+
if (!"bill".equals(elementSelBefore)) {
113+
throw new RuntimeException("Test failed for " + laf
114+
+ " as the list element selected: " + elementSel
115+
+ " is not the expected one 'bill'"
116+
);
117+
}
118+
119+
// Now operate Menu using Mnemonics, different key combinations for different OSes.
120+
// For most OSes it's ALT+F; on macOS it's ALT+CNTRL+F except for Nimbus LaF.
121+
if (isMac && !laf.contains("Nimbus")) {
122+
hitKeys(KeyEvent.VK_ALT, KeyEvent.VK_CONTROL, FILE_MENU);
123+
} else {
124+
hitKeys(KeyEvent.VK_ALT, FILE_MENU);
125+
}
126+
127+
// Wait until the menu got selected.
128+
if (!menuSelectedEventLatch.await(3, TimeUnit.SECONDS)) {
129+
throw new RuntimeException("Waited too long, but can't select menu using mnemonics for " + laf);
130+
}
131+
132+
hitKeys(KeyEvent.VK_ENTER);
133+
134+
AtomicReference<String> elementSelAfter = new AtomicReference<>();
135+
SwingUtilities.invokeAndWait(() -> elementSelAfter.set(list.getSelectedValue()));
136+
137+
// As per the fix of BugID 4618767, the list element selection should not change
138+
if (!elementSelBefore.equals(elementSelAfter.get())) {
139+
throw new RuntimeException("Test failed for " + laf
140+
+ " as list.getSelectedValue() before = " + elementSel
141+
+ " not equal to list.getSelectedValue() after pressing Enter = " + elementSelAfter
142+
);
143+
}
144+
System.out.println("Test passed for laf: " + laf);
145+
146+
} finally {
147+
SwingUtilities.invokeAndWait(JListSelectedElementTest::disposeFrame);
148+
}
149+
}
150+
}
151+
152+
private static void hitKeys(int... keys) {
153+
for (int key : keys) {
154+
robot.keyPress(key);
155+
}
156+
157+
for (int i = keys.length - 1; i >= 0; i--) {
158+
robot.keyRelease(keys[i]);
159+
}
160+
}
161+
162+
private static void createUI() {
163+
frame = new JFrame();
164+
list = new JList<>(new String[]{"anaheim", "bill", "chicago", "dingo", "ernie", "freak"});
165+
list.addFocusListener(new FocusAdapter() {
166+
@Override
167+
public void focusGained(FocusEvent e) {
168+
listGainedFocusLatch.countDown();
169+
}
170+
});
171+
JMenu menu = new JMenu("File");
172+
menu.setMnemonic(FILE_MENU);
173+
JMenuItem menuItem = new JMenuItem("Dummy");
174+
menu.add(menuItem);
175+
menu.addMenuListener(new MenuListener() {
176+
@Override
177+
public void menuSelected(MenuEvent e) {
178+
menuSelectedEventLatch.countDown();
179+
}
180+
181+
@Override
182+
public void menuDeselected(MenuEvent e) {
183+
}
184+
185+
@Override
186+
public void menuCanceled(MenuEvent e) {
187+
}
188+
});
189+
190+
JMenuBar menuBar = new JMenuBar();
191+
menuBar.add(menu);
192+
193+
frame.setJMenuBar(menuBar);
194+
frame.setContentPane(list);
195+
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
196+
frame.pack();
197+
frame.setAlwaysOnTop(true);
198+
frame.setLocationRelativeTo(null);
199+
frame.setVisible(true);
200+
}
201+
202+
private static boolean setLookAndFeel(String lafName) {
203+
try {
204+
UIManager.setLookAndFeel(lafName);
205+
} catch (UnsupportedLookAndFeelException ignored) {
206+
System.out.println("Ignoring Unsupported L&F: " + lafName);
207+
return false;
208+
} catch (ClassNotFoundException | InstantiationException
209+
| IllegalAccessException e) {
210+
throw new RuntimeException(e);
211+
}
212+
return true;
213+
}
214+
215+
private static void disposeFrame() {
216+
if (frame != null) {
217+
frame.dispose();
218+
frame = null;
219+
}
220+
}
221+
222+
}

0 commit comments

Comments
 (0)