Skip to content

Commit dda39ec

Browse files
committed
8280991: [XWayland] No displayChanged event after setDisplayMode call
Backport-of: 29de20dbc22e0b68698a1b9cb1241ae5861a6b9a
1 parent e31723b commit dda39ec

File tree

4 files changed

+87
-4
lines changed

4 files changed

+87
-4
lines changed

src/java.desktop/unix/classes/sun/awt/X11GraphicsDevice.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 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
@@ -73,6 +73,15 @@ public final class X11GraphicsDevice extends GraphicsDevice
7373
private boolean shutdownHookRegistered;
7474
private int scale;
7575

76+
// Wayland clients are by design not allowed to change the resolution in Wayland.
77+
// XRandR in Xwayland is just an emulation, it doesn't actually change the resolution.
78+
// This emulation is per window/x11 client, so different clients can have
79+
// different emulated resolutions at the same time.
80+
// So any request to get the current display mode will always return
81+
// the original screen resolution, even if we are in emulated resolution.
82+
// To handle this situation, we store the last set display mode in this variable.
83+
private volatile DisplayMode xwlCurrentDisplayMode;
84+
7685
public X11GraphicsDevice(int screennum) {
7786
this.screen = screennum;
7887
this.scale = initScaleFactor();
@@ -125,6 +134,20 @@ public int scaleDown(int x) {
125134

126135
private Rectangle getBoundsImpl() {
127136
Rectangle rect = pGetBounds(getScreen());
137+
138+
if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) {
139+
// XRandR resolution change in Xwayland is an emulation,
140+
// and implemented in such a way that multiple display modes
141+
// for a device are only available in a single screen scenario,
142+
// if we have multiple screens they will each have a single display mode
143+
// (no emulated resolution change is available).
144+
// So we don't have to worry about x and y for a screen here.
145+
rect.setSize(
146+
xwlCurrentDisplayMode.getWidth(),
147+
xwlCurrentDisplayMode.getHeight()
148+
);
149+
}
150+
128151
if (getScaleFactor() != 1) {
129152
rect.x = scaleDown(rect.x);
130153
rect.y = scaleDown(rect.y);
@@ -424,10 +447,19 @@ private DisplayMode getDefaultDisplayMode() {
424447
@Override
425448
public synchronized DisplayMode getDisplayMode() {
426449
if (isFullScreenSupported()) {
450+
if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) {
451+
return xwlCurrentDisplayMode;
452+
}
453+
427454
DisplayMode mode = getCurrentDisplayMode(screen);
428455
if (mode == null) {
429456
mode = getDefaultDisplayMode();
430457
}
458+
459+
if (XToolkit.isOnWayland()) {
460+
xwlCurrentDisplayMode = mode;
461+
}
462+
431463
return mode;
432464
} else {
433465
if (origDisplayMode == null) {
@@ -503,6 +535,10 @@ public synchronized void setDisplayMode(DisplayMode dm) {
503535
dm.getWidth(), dm.getHeight(),
504536
dm.getRefreshRate());
505537

538+
if (XToolkit.isOnWayland()) {
539+
xwlCurrentDisplayMode = dm;
540+
}
541+
506542
// update bounds of the fullscreen window
507543
w.setBounds(0, 0, dm.getWidth(), dm.getHeight());
508544

test/jdk/ProblemList.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -489,7 +489,6 @@ java/awt/Dialog/ChoiceModalDialogTest.java 8161475 macosx-all
489489

490490
# Wayland related
491491

492-
java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64
493492

494493
############################################################################
495494

test/jdk/java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2020, 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
@@ -52,6 +52,10 @@ public void paint(Graphics g) {
5252
super.paint(g);
5353
g.setColor(Color.GREEN);
5454
g.fillRect(0, 0, getWidth(), getHeight());
55+
g.setColor(Color.RED);
56+
DisplayMode displayMode =
57+
getGraphicsConfiguration().getDevice().getDisplayMode();
58+
g.drawString(displayMode.toString(), 100, 100);
5559
}
5660
};
5761
try {

test/jdk/java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2007, 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
@@ -26,6 +26,8 @@
2626
* @bug 6646411
2727
* @summary Tests that full screen window and its children receive resize
2828
event when display mode changes
29+
* @library /test/lib
30+
* @build jdk.test.lib.Platform jtreg.SkippedException
2931
* @run main/othervm NoResizeEventOnDMChangeTest
3032
* @run main/othervm -Dsun.java2d.d3d=false NoResizeEventOnDMChangeTest
3133
*/
@@ -44,9 +46,21 @@
4446
import java.awt.event.ComponentEvent;
4547
import java.awt.event.WindowAdapter;
4648
import java.awt.event.WindowEvent;
49+
import java.io.BufferedReader;
50+
import java.io.IOException;
51+
52+
import static java.util.concurrent.TimeUnit.SECONDS;
53+
import jdk.test.lib.Platform;
54+
import jtreg.SkippedException;
4755

4856
public class NoResizeEventOnDMChangeTest {
57+
4958
public static void main(String[] args) {
59+
if (Platform.isOnWayland() && !isFixDelivered()) {
60+
throw new SkippedException("Test skipped because fix was not" +
61+
"delivered in current GnomeShell version");
62+
}
63+
5064
final GraphicsDevice gd = GraphicsEnvironment.
5165
getLocalGraphicsEnvironment().getDefaultScreenDevice();
5266

@@ -231,4 +245,34 @@ public synchronized int getDmChanges() {
231245
return dmChanges;
232246
}
233247
}
248+
249+
private static boolean isFixDelivered() {
250+
try {
251+
Process process =
252+
new ProcessBuilder("/usr/bin/gnome-shell", "--version")
253+
.start();
254+
255+
try (BufferedReader reader = process.inputReader()) {
256+
if (process.waitFor(2, SECONDS) && process.exitValue() == 0) {
257+
String line = reader.readLine();
258+
if (line != null) {
259+
System.out.println("Gnome shell version: " + line);
260+
String[] versionComponents = line
261+
.replaceAll("[^\\d.]", "")
262+
.split("\\.");
263+
264+
if (versionComponents.length >= 1) {
265+
return Integer.parseInt(versionComponents[0]) > 42;
266+
}
267+
}
268+
}
269+
}
270+
} catch (IOException
271+
| InterruptedException
272+
| IllegalThreadStateException
273+
| NumberFormatException ignored) {
274+
}
275+
276+
return false;
277+
}
234278
}

0 commit comments

Comments
 (0)