Skip to content

Commit 29de20d

Browse files
author
Alexander Zvegintsev
committed
8280991: [XWayland] No displayChanged event after setDisplayMode call
Reviewed-by: honkar, prr
1 parent 3e86b3a commit 29de20d

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, 2024, 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
@@ -72,6 +72,15 @@ public final class X11GraphicsDevice extends GraphicsDevice
7272
private boolean shutdownHookRegistered;
7373
private int scale;
7474

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

118127
private Rectangle getBoundsImpl() {
119128
Rectangle rect = pGetBounds(getScreen());
129+
130+
if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) {
131+
// XRandR resolution change in Xwayland is an emulation,
132+
// and implemented in such a way that multiple display modes
133+
// for a device are only available in a single screen scenario,
134+
// if we have multiple screens they will each have a single display mode
135+
// (no emulated resolution change is available).
136+
// So we don't have to worry about x and y for a screen here.
137+
rect.setSize(
138+
xwlCurrentDisplayMode.getWidth(),
139+
xwlCurrentDisplayMode.getHeight()
140+
);
141+
}
142+
120143
if (getScaleFactor() != 1) {
121144
rect.x = scaleDown(rect.x);
122145
rect.y = scaleDown(rect.y);
@@ -400,10 +423,19 @@ private DisplayMode getDefaultDisplayMode() {
400423
@Override
401424
public synchronized DisplayMode getDisplayMode() {
402425
if (isFullScreenSupported()) {
426+
if (XToolkit.isOnWayland() && xwlCurrentDisplayMode != null) {
427+
return xwlCurrentDisplayMode;
428+
}
429+
403430
DisplayMode mode = getCurrentDisplayMode(screen);
404431
if (mode == null) {
405432
mode = getDefaultDisplayMode();
406433
}
434+
435+
if (XToolkit.isOnWayland()) {
436+
xwlCurrentDisplayMode = mode;
437+
}
438+
407439
return mode;
408440
} else {
409441
if (origDisplayMode == null) {
@@ -474,6 +506,10 @@ public synchronized void setDisplayMode(DisplayMode dm) {
474506
dm.getWidth(), dm.getHeight(),
475507
dm.getRefreshRate());
476508

509+
if (XToolkit.isOnWayland()) {
510+
xwlCurrentDisplayMode = dm;
511+
}
512+
477513
// update bounds of the fullscreen window
478514
w.setBounds(0, 0, dm.getWidth(), dm.getHeight());
479515

test/jdk/ProblemList.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,6 @@ java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 m
499499

500500
# Wayland related
501501

502-
java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64
503502
java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64
504503

505504
############################################################################

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)