Skip to content

Commit 7799ff6

Browse files
committed
JBR-9503 Wayland: IDE frame disappears after click on 'Cancel'
1 parent f28a524 commit 7799ff6

File tree

5 files changed

+151
-15
lines changed

5 files changed

+151
-15
lines changed

src/java.desktop/share/classes/java/awt/Window.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4373,11 +4373,6 @@ public void dumpStats(final Window w, final boolean reset, StringBuilder sb) {
43734373
}
43744374
}
43754375

4376-
@Override
4377-
public void addWindowListener(Window w, WindowListener listener) {
4378-
w.addWindowListener(listener);
4379-
}
4380-
43814376
private static void dumpCounter(final String counterName, final double valPerSecond) {
43824377
if (USE_COUNTERS) {
43834378
doLog(String.format("%s per second: %.2f", counterName, valPerSecond),

src/java.desktop/share/classes/sun/awt/AWTAccessor.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import java.awt.event.InvocationEvent;
3838
import java.awt.event.KeyEvent;
3939
import java.awt.event.MouseEvent;
40-
import java.awt.event.WindowListener;
4140
import java.awt.image.BufferStrategy;
4241
import java.awt.peer.ComponentPeer;
4342

@@ -338,8 +337,6 @@ public interface WindowAccessor {
338337
double getCounterPerSecond(Window w, String counterName);
339338

340339
void dumpStats(Window w, boolean reset, StringBuilder sb);
341-
342-
void addWindowListener(Window w, WindowListener listener);
343340
}
344341

345342
/**

src/java.desktop/unix/classes/sun/awt/wl/WLFramePeer.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
package sun.awt.wl;
2727

2828
import java.awt.*;
29-
import java.awt.event.WindowAdapter;
3029
import java.awt.event.WindowEvent;
3130
import java.awt.peer.FramePeer;
3231
import sun.awt.AWTAccessor;
@@ -43,12 +42,6 @@ public WLFramePeer(Frame target) {
4342
super(target, target.isUndecorated(),
4443
Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.ICONIFIED),
4544
Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH));
46-
AWTAccessor.getWindowAccessor().addWindowListener(target, new WindowAdapter() {
47-
@Override
48-
public void windowClosing(WindowEvent e) {
49-
getFrame().removeNotify();
50-
}
51-
});
5245
}
5346

5447
@Override

src/java.desktop/unix/classes/sun/awt/wl/WLToolkit.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
import java.awt.peer.WindowPeer;
8484
import java.security.AccessController;
8585
import java.security.PrivilegedAction;
86+
import java.util.ArrayList;
8687
import java.util.Arrays;
8788
import java.util.Collections;
8889
import java.util.HashMap;
@@ -173,11 +174,31 @@ public WLToolkit() {
173174
toolkitSystemThread.start();
174175

175176
dataDevice = new WLDataDevice(0); // TODO: for multiseat support pass wl_seat pointer here
177+
178+
registerShutdownHook();
176179
} else {
177180
dataDevice = null;
178181
}
179182
}
180183

184+
private void registerShutdownHook() {
185+
Runnable r = () -> {
186+
ArrayList<WLWindowPeer> livePeers;
187+
synchronized (wlSurfaceToPeerMap) {
188+
livePeers = new ArrayList<>(wlSurfaceToPeerMap.values());
189+
}
190+
livePeers.forEach(p -> {
191+
Component target = p.getTarget();
192+
if (target.isDisplayable()) {
193+
target.removeNotify();
194+
}
195+
});
196+
};
197+
Thread shutdownThread = InnocuousThread.newSystemThread("WLToolkit-Shutdown-Thread", r);
198+
shutdownThread.setDaemon(true);
199+
Runtime.getRuntime().addShutdownHook(shutdownThread);
200+
}
201+
181202
public static synchronized boolean getSunAwtDisableGtkFileDialogs() {
182203
if (sunAwtDisableGtkFileDialogs == null) {
183204
sunAwtDisableGtkFileDialogs = Boolean.getBoolean("sun.awt.disableGtkFileDialogs");
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2025 JetBrains s.r.o.
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 javax.swing.JButton;
25+
import javax.swing.JFrame;
26+
import javax.swing.JLabel;
27+
import javax.swing.JOptionPane;
28+
import javax.swing.JPanel;
29+
import javax.swing.SwingUtilities;
30+
import java.awt.GridLayout;
31+
import java.awt.event.WindowAdapter;
32+
import java.awt.event.WindowEvent;
33+
import java.io.IOException;
34+
import java.util.concurrent.CompletableFuture;
35+
36+
import jdk.test.lib.process.ProcessTools;
37+
38+
/**
39+
* @test
40+
* @summary Verifies cancelling window close operation does not close the window
41+
* @requires os.family == "linux"
42+
* @library /test/lib
43+
* @key headful
44+
* @run main/manual ConfirmWindowClose
45+
*/
46+
public class ConfirmWindowClose {
47+
static final CompletableFuture<RuntimeException> swingError = new CompletableFuture<>();
48+
static Process testProcess;
49+
50+
public static void main(String[] args) throws Exception {
51+
if (args.length > 0) {
52+
SwingUtilities.invokeLater(ConfirmWindowClose::showTestUI);
53+
} else {
54+
try {
55+
SwingUtilities.invokeAndWait(ConfirmWindowClose::showControlUI);
56+
swingError.get();
57+
} finally {
58+
if (testProcess != null) {
59+
testProcess.destroy();
60+
}
61+
}
62+
}
63+
}
64+
65+
private static void showTestUI() {
66+
JFrame frame = new JFrame("ConfirmWindowClose Test");
67+
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
68+
69+
JLabel l = new JLabel("<html><h1>INSTRUCTIONS</h1><p>Click on the close button on the window.</p></html>");
70+
frame.getContentPane().add(l);
71+
72+
frame.addWindowListener(new WindowAdapter() {
73+
@Override
74+
public void windowClosing(WindowEvent e) {
75+
int result = JOptionPane.showConfirmDialog(
76+
frame,
77+
"Do you really want to close it? (click No first)",
78+
"Confirm Exit",
79+
JOptionPane.YES_NO_CANCEL_OPTION,
80+
JOptionPane.QUESTION_MESSAGE
81+
);
82+
83+
if (result == JOptionPane.YES_OPTION) {
84+
frame.dispose();
85+
}
86+
}
87+
});
88+
89+
frame.pack();
90+
frame.setVisible(true);
91+
}
92+
93+
private static void showControlUI() {
94+
JFrame frame = new JFrame("ConfirmWindow Control Frame");
95+
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
96+
97+
JPanel content = new JPanel();
98+
var layout = new GridLayout(4, 1, 10, 10);
99+
content.setLayout(layout);
100+
JButton runButton = new JButton("Launch Test");
101+
runButton.addActionListener(e -> {
102+
ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(ConfirmWindowClose.class.getName(), "runTest");
103+
try {
104+
testProcess = pb.start();
105+
} catch (IOException ex) {
106+
swingError.complete(new RuntimeException(ex));
107+
throw new RuntimeException(ex);
108+
}
109+
});
110+
111+
JButton passButton = new JButton("Pass");
112+
passButton.addActionListener(e -> {swingError.complete(null);});
113+
114+
JButton failButton = new JButton("Fail");
115+
failButton.addActionListener(e -> {swingError.completeExceptionally(new RuntimeException("The tester has pressed FAILED"));});
116+
117+
content.add(runButton);
118+
content.add(failButton);
119+
content.add(passButton);
120+
content.add(new JLabel("<html><center><h1>INSTRUCTIONS</h1></center>" +
121+
"<p>Press Launch Test</p>" +
122+
"<p>In the 'ConfirmWindowClose Test' window that appears, click the window close icon on the titlebar.</p>" +
123+
"<p>When the confirmation dialog appears click No.</p>" +
124+
"<p>Make sure that the 'ConfirmWindowClose Test' has not disappeared.</p>" +
125+
"<p>If the window has not disappeared, press Pass here; otherwise, press Fail.</p></html>"));
126+
frame.setContentPane(content);
127+
frame.pack();
128+
frame.setVisible(true);
129+
}
130+
}

0 commit comments

Comments
 (0)