Skip to content

Commit 3f234d9

Browse files
committed
8346581: JRadioButton/ButtonGroupFocusTest.java fails in CI on Linux
Backport-of: 57af52c57390f6f7413b5d3ffe64921c9b83aae4
1 parent 7eb2f79 commit 3f234d9

File tree

1 file changed

+111
-39
lines changed

1 file changed

+111
-39
lines changed
Lines changed: 111 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2025, 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
@@ -28,26 +28,53 @@
2828
* @run main ButtonGroupFocusTest
2929
*/
3030

31-
import javax.swing.*;
32-
import java.awt.*;
31+
import java.awt.AWTEvent;
32+
import java.awt.Container;
33+
import java.awt.FlowLayout;
34+
import java.awt.KeyboardFocusManager;
35+
import java.awt.Rectangle;
36+
import java.awt.Robot;
37+
import java.awt.Toolkit;
38+
import java.awt.event.FocusAdapter;
39+
import java.awt.event.FocusEvent;
3340
import java.awt.event.KeyEvent;
41+
import java.awt.image.BufferedImage;
42+
import java.io.File;
43+
import java.util.concurrent.CountDownLatch;
3444

35-
public class ButtonGroupFocusTest {
45+
import javax.imageio.ImageIO;
46+
import javax.swing.ButtonGroup;
47+
import javax.swing.JFrame;
48+
import javax.swing.JRadioButton;
49+
import javax.swing.SwingUtilities;
50+
51+
import static java.awt.KeyboardFocusManager.getCurrentKeyboardFocusManager;
52+
import static java.util.concurrent.TimeUnit.MILLISECONDS;
53+
import static java.util.concurrent.TimeUnit.SECONDS;
54+
55+
public final class ButtonGroupFocusTest {
3656

3757
private static JRadioButton button1;
3858
private static JRadioButton button2;
3959
private static JRadioButton button3;
4060
private static JRadioButton button4;
4161
private static JRadioButton button5;
42-
private static Robot robot;
62+
63+
private static final CountDownLatch button2FocusLatch = new CountDownLatch(1);
64+
private static final CountDownLatch button3FocusLatch = new CountDownLatch(1);
65+
private static final CountDownLatch button4FocusLatch = new CountDownLatch(1);
66+
67+
private static final CountDownLatch button2FocusLatch2 = new CountDownLatch(2);
68+
69+
private static final long FOCUS_TIMEOUT = 4;
70+
4371
private static JFrame frame;
4472

4573
public static void main(String[] args) throws Exception {
46-
robot = new Robot();
47-
robot.setAutoDelay(100);
74+
final Robot robot = new Robot();
4875

4976
SwingUtilities.invokeAndWait(() -> {
50-
frame = new JFrame();
77+
frame = new JFrame("ButtonGroupFocusTest");
5178
Container contentPane = frame.getContentPane();
5279
contentPane.setLayout(new FlowLayout());
5380
button1 = new JRadioButton("Button 1");
@@ -60,6 +87,7 @@ public static void main(String[] args) throws Exception {
6087
contentPane.add(button4);
6188
button5 = new JRadioButton("Button 5");
6289
contentPane.add(button5);
90+
6391
ButtonGroup group = new ButtonGroup();
6492
group.add(button1);
6593
group.add(button2);
@@ -69,52 +97,96 @@ public static void main(String[] args) throws Exception {
6997
group.add(button4);
7098
group.add(button5);
7199

100+
button2.addFocusListener(new LatchFocusListener(button2FocusLatch));
101+
button3.addFocusListener(new LatchFocusListener(button3FocusLatch));
102+
button4.addFocusListener(new LatchFocusListener(button4FocusLatch));
103+
104+
button2.addFocusListener(new LatchFocusListener(button2FocusLatch2));
105+
72106
button2.setSelected(true);
73107

108+
// Debugging aid: log focus owner changes...
109+
KeyboardFocusManager focusManager = getCurrentKeyboardFocusManager();
110+
focusManager.addPropertyChangeListener("focusOwner",
111+
e -> System.out.println(e.getPropertyName()
112+
+ "\n\t" + e.getOldValue()
113+
+ "\n\t" + e.getNewValue()));
114+
115+
// ...and dispatched key events
116+
Toolkit.getDefaultToolkit().addAWTEventListener(
117+
e -> System.out.println("Dispatched " + e),
118+
AWTEvent.KEY_EVENT_MASK);
119+
74120
frame.pack();
121+
frame.setLocationRelativeTo(null);
75122
frame.setVisible(true);
76123
});
77124

78-
robot.waitForIdle();
79-
robot.delay(200);
80-
81-
SwingUtilities.invokeAndWait(() -> {
82-
if( !button2.hasFocus() ) {
83-
frame.dispose();
84-
throw new RuntimeException(
85-
"Button 2 should get focus after activation");
125+
try {
126+
if (!button2FocusLatch.await(FOCUS_TIMEOUT, SECONDS)) {
127+
throw new RuntimeException("Button 2 should get focus "
128+
+ "after activation");
86129
}
87-
});
130+
robot.waitForIdle();
131+
robot.delay(200);
88132

89-
robot.keyPress(KeyEvent.VK_TAB);
90-
robot.keyRelease(KeyEvent.VK_TAB);
133+
System.out.println("\n\n*** Tab 1st");
134+
robot.keyPress(KeyEvent.VK_TAB);
135+
robot.keyRelease(KeyEvent.VK_TAB);
91136

92-
robot.waitForIdle();
93-
robot.delay(200);
137+
if (!button4FocusLatch.await(FOCUS_TIMEOUT, SECONDS)) {
138+
throw new RuntimeException("Button 4 should get focus");
139+
}
140+
robot.waitForIdle();
141+
robot.delay(200);
94142

95-
SwingUtilities.invokeAndWait(() -> {
96-
if( !button4.hasFocus() ) {
97-
frame.dispose();
98-
throw new RuntimeException(
99-
"Button 4 should get focus");
143+
if (button2FocusLatch2.await(1, MILLISECONDS)) {
144+
throw new RuntimeException("Focus moved back to Button 2");
100145
}
101-
button3.setSelected(true);
102-
});
103146

104-
robot.keyPress(KeyEvent.VK_TAB);
105-
robot.keyRelease(KeyEvent.VK_TAB);
147+
SwingUtilities.invokeAndWait(() -> button3.setSelected(true));
148+
robot.waitForIdle();
149+
robot.delay(200);
106150

107-
robot.waitForIdle();
108-
robot.delay(200);
151+
System.out.println("\n\n*** Tab 2nd");
152+
robot.keyPress(KeyEvent.VK_TAB);
153+
robot.keyRelease(KeyEvent.VK_TAB);
109154

110-
SwingUtilities.invokeAndWait(() -> {
111-
if( !button3.hasFocus() ) {
112-
frame.dispose();
113-
throw new RuntimeException(
114-
"selected Button 3 should get focus");
155+
if (!button3FocusLatch.await(FOCUS_TIMEOUT, SECONDS)) {
156+
throw new RuntimeException("Selected Button 3 should get focus");
115157
}
116-
});
158+
} catch (Exception e) {
159+
BufferedImage image = robot.createScreenCapture(getFrameBounds());
160+
ImageIO.write(image, "png",
161+
new File("image.png"));
162+
163+
SwingUtilities.invokeAndWait(() ->
164+
System.err.println("Current focus owner: "
165+
+ getCurrentKeyboardFocusManager()
166+
.getFocusOwner()));
167+
168+
throw e;
169+
} finally {
170+
SwingUtilities.invokeAndWait(frame::dispose);
171+
}
172+
}
173+
174+
private static Rectangle getFrameBounds() throws Exception {
175+
Rectangle[] bounds = new Rectangle[1];
176+
SwingUtilities.invokeAndWait(() -> bounds[0] = frame.getBounds());
177+
return bounds[0];
178+
}
179+
180+
private static final class LatchFocusListener extends FocusAdapter {
181+
private final CountDownLatch focusGainedLatch;
182+
183+
private LatchFocusListener(CountDownLatch focusGainedLatch) {
184+
this.focusGainedLatch = focusGainedLatch;
185+
}
117186

118-
SwingUtilities.invokeLater(frame::dispose);
187+
@Override
188+
public void focusGained(FocusEvent e) {
189+
focusGainedLatch.countDown();
190+
}
119191
}
120192
}

0 commit comments

Comments
 (0)