Skip to content

Commit

Permalink
JBR-7919 add tests for Wayland popups
Browse files Browse the repository at this point in the history
  • Loading branch information
sshelomentsev authored and jbrbot committed Dec 4, 2024
1 parent b794e57 commit 88f8bc6
Show file tree
Hide file tree
Showing 7 changed files with 511 additions and 10 deletions.
3 changes: 3 additions & 0 deletions test/jdk/TEST.groups
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,9 @@ jdk_swing_wayland= \
jb/javax/swing/Popup/WLPopupAsParent.java \
jb/javax/swing/Popup/WLPopupMinSize.java \
jb/javax/swing/Popup/WLPopupResize.java \
jb/javax/swing/Popup/WLPopupLocation.java \
jb/javax/swing/Popup/WLPopupMoves.java \
jb/javax/swing/Popup/WLPopupVisibility.java \
-com/sun/java/swing/plaf/gtk/TestBackSpaceAction.java \
-com/sun/java/swing/plaf/gtk/TestFileChooserCtrlASelection.java \
-com/sun/java/swing/plaf/gtk/TestFileChooserSingleDirectorySelection.java \
Expand Down
4 changes: 4 additions & 0 deletions test/jdk/jb/javax/swing/Popup/WLPopupAsParent.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
* @key headful
* @modules java.desktop/sun.awt
* @run main WLPopupAsParent
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupAsParent
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupAsParent
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupAsParent
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupAsParent
*/
public class WLPopupAsParent {
private static JFrame frame;
Expand Down
125 changes: 125 additions & 0 deletions test/jdk/jb/javax/swing/Popup/WLPopupLocation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright 2024 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

import javax.swing.*;
import java.awt.*;

import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

/**
* @test
* @summary Verifies that the popup-style window can change it's size and location
* @requires os.family == "linux"
* @key headful
* @modules java.desktop/sun.awt
* @run main/othervm WLPopupLocation
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupLocation
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupLocation
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupLocation
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupLocation
*/
public class WLPopupLocation {

private static JFrame frame;
private static JWindow popup;

private static void createAndShowUI() {
frame = new JFrame("WLPopupLocation Test");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}

private static void initPopup() {
JPanel popupContents = new JPanel();
popupContents.add(new JLabel("test popup"));
popup = new JWindow(frame);
popup.setType(Window.Type.POPUP);
sun.awt.AWTAccessor.getWindowAccessor().setPopupParent(popup, frame);
popup.add(popupContents);
}

public static void main(String[] args) throws Exception {
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (!toolkit.getClass().getName().equals("sun.awt.wl.WLToolkit")) {
System.out.println("The test makes sense only for WLToolkit. Exiting...");
return;
}

Robot robot = new Robot();

SwingUtilities.invokeAndWait(WLPopupLocation::createAndShowUI);
pause(robot);

SwingUtilities.invokeAndWait(WLPopupLocation::initPopup);
pause(robot);

int w1 = 150, h1 = 200;
int x1 = 100, y1 = 100;
System.out.printf("Action: locate to (%d, %d), set size (%d, %d)\n", x1, y1, w1, h1);
SwingUtilities.invokeAndWait(() -> {
popup.setVisible(true);
popup.setSize(w1, h1);
popup.setLocation(x1, y1);
});
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
throw new RuntimeException(String.format("Incorrect size (%d, %d), expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
}
if (popup.getBounds().x != x1 || popup.getBounds().y != y1) {
throw new RuntimeException(String.format("Wrong location (via getBounds()): (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x1, y1));
}
pause(robot);
if (popup.getSize().width != h1 || popup.getSize().height != h1) {
throw new RuntimeException(String.format("Incorrect size (%d, %d) after robot's wait for idle, expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
}
if (popup.getBounds().x != x1 || popup.getBounds().y != y1) {
throw new RuntimeException(String.format("Wrong location (via getBounds()) after robot's wait for idle: (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x1, y1));
}

int x2 = 200, y2 = 200;
System.out.printf("Action: set popup size to (%d, %d)\n", x2, y2);
SwingUtilities.invokeAndWait(() -> {
popup.setLocation(x2, y2);
});
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
throw new RuntimeException(String.format("Incorrect size (%d, %d), expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
}
if (popup.getBounds().x != x2 || popup.getBounds().y != y2) {
throw new RuntimeException(String.format("Wrong location (via getBounds()): (%d, %d). Expected: (%x, %d)", popup.getBounds().x, popup.getBounds().y, x2, y2));
}
pause(robot);
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
throw new RuntimeException(String.format("Incorrect size (%d, %d) after robot's wait for idle, expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
}
if (popup.getBounds().x != x2 || popup.getBounds().y != y2) {
throw new RuntimeException(String.format("Wrong location (via getBounds()) after robot's wait for idle: (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x2, y2));
}
SwingUtilities.invokeAndWait(frame::dispose);
}

private static void pause(Robot robot) {
robot.waitForIdle();
robot.delay(500);
}

}
6 changes: 5 additions & 1 deletion test/jdk/jb/javax/swing/Popup/WLPopupMinSize.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@
* @requires os.family == "linux"
* @key headful
* @modules java.desktop/sun.awt
* @run main WLPopupMinSize
* @run main/othervm WLPopupMinSize
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupMinSize
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupMinSize
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupMinSize
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupMinSize
*/
public class WLPopupMinSize {
private static JFrame frame;
Expand Down
171 changes: 171 additions & 0 deletions test/jdk/jb/javax/swing/Popup/WLPopupMoves.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* Copyright 2024 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

import javax.swing.*;
import java.awt.*;
import java.awt.geom.AffineTransform;

import static javax.swing.WindowConstants.EXIT_ON_CLOSE;

/**
* @test
* @summary Verifies that the popup-style window can move under Wayland
* @requires os.family == "linux"
* @key headful
* @modules java.desktop/sun.awt
* @run main/othervm WLPopupMoves
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupMoves
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupMoves
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupMoves
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupMoves
*/
public class WLPopupMoves {

private static JFrame frame;
private static JWindow popup;

private static void createAndShowUI() {
frame = new JFrame("WLPopupMoves Test");
frame.setSize(300, 200);
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.setVisible(true);
}

private static void initPopup() {
JPanel popupContents = new JPanel();
popupContents.add(new JLabel("test popup"));
popup = new JWindow(frame);
popup.setType(Window.Type.POPUP);
sun.awt.AWTAccessor.getWindowAccessor().setPopupParent(popup, frame);
popup.add(popupContents);
}

public static void main(String... args) throws Exception {
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (!toolkit.getClass().getName().equals("sun.awt.wl.WLToolkit")) {
System.out.println("The test makes sense only for WLToolkit. Exiting...");
return;
}

Robot robot = new Robot();

SwingUtilities.invokeAndWait(WLPopupMoves::createAndShowUI);
pause(robot);

SwingUtilities.invokeAndWait(WLPopupMoves::initPopup);
pause(robot);

double uiScale = getUiScale();
System.out.printf("UI scale: %.2f.\n", uiScale);
int pixelThreshold = uiScale == 1.0 ? 0 : (int) Math.ceil(uiScale);
System.out.printf("Pixel threshold for verifications: %d\n", pixelThreshold);

int w = 120, h = 200;
System.out.println("Set popup to (50, 50)");
SwingUtilities.invokeAndWait(() -> {
popup.setBounds(50, 50, w, h);
popup.setVisible(true);
});
verifyBounds("Popup position after setting to (50, 50)\n", 50, 50, w, h, pixelThreshold);
pause(robot);
verifyBounds("Popup position (50, 50) after robot's pause\n", 50, 50, w, h, pixelThreshold);

System.out.println("Set popup to (100, 100)");
SwingUtilities.invokeAndWait(() -> {
popup.setBounds(100, 100, w, h);
});
verifyBounds("Popup position after setting to (100, 100)\n", 100, 100, w, h, pixelThreshold);
pause(robot);
verifyBounds("Popup position (100, 100) after robot's pause\n", 100, 100, w, h, pixelThreshold);

int x1 = (int) (toolkit.getScreenSize().width / (2 * uiScale));
int y1 = (int) (toolkit.getScreenSize().height / (2 * uiScale));
System.out.printf("Set popup to (%d, %d)\n", x1, y1);
SwingUtilities.invokeAndWait(() -> {
popup.setBounds(x1, y1, w, h);
});
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x1, y1), x1, y1, w, h, pixelThreshold);
pause(robot);
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x1, y1), x1, y1, w, h, pixelThreshold);

int x2 = (int) (toolkit.getScreenSize().width / uiScale - 10 - w);
int y2 = (int) (toolkit.getScreenSize().height / uiScale - 10 - h);
System.out.printf("Set popup to (%d, %d). (to the bottom right corner) \n", x2, y2);
SwingUtilities.invokeAndWait(() -> {
popup.setBounds(x2, y2, w, h);
});
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x2, y2), x2, y2, w, h, pixelThreshold);
pause(robot);
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x2, y2), x2, y2, w, h, pixelThreshold);

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = device.getDefaultConfiguration();
Insets insets = toolkit.getScreenInsets(gc);
int x3 = (int) (toolkit.getScreenSize().width / uiScale - 10 - insets.right);
int y3 = (int) (toolkit.getScreenSize().height / uiScale - 10 - insets.bottom);
System.out.printf("Set popup to (%d, %d). (to the bottom right corner) \n", x3, y3);
SwingUtilities.invokeAndWait(() -> {
popup.setBounds(x2, y2, w, h);
});
int x3Relocated = x3 - w;
int y3Relocated = y3 - h;
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x3, y3), x3Relocated, y3Relocated, w, h, pixelThreshold);
pause(robot);
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x3, y3), x3Relocated, y3Relocated, w, h, pixelThreshold);

SwingUtilities.invokeAndWait(frame::dispose);
}

private static Double getUiScale() {
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = device.getDefaultConfiguration();
AffineTransform transform = gc.getDefaultTransform();
double scaleX = transform.getScaleX();
double scaleY = transform.getScaleY();
if (scaleX != scaleY) {
System.out.println("Skip test due to non-uniform display scale");
System.exit(0);
}
return scaleX;
}

private static void verifyBounds(String message, int x, int y, int w, int h, int pixelThreshold) {
Rectangle bounds = popup.getBounds();
System.out.printf("Check %s for bounds: %s\n", message, bounds);
boolean isCorrectPosition = x - pixelThreshold <= bounds.x && bounds.x <= x + pixelThreshold &&
y - pixelThreshold <= bounds.y && bounds.y <= y + pixelThreshold;
if (!isCorrectPosition) {
throw new RuntimeException(String.format("%s has wrong position. Expected: (%d, %d). Actual: (%d, %d)", message, x, y, bounds.x, bounds.y));
}
if (bounds.width != w || bounds.height != h) {
throw new RuntimeException(String.format("%s has wrong size. Expected: (%d, %d). Actual: (%d, %d)", message, w, h, bounds.width, bounds.height));
}
}

private static void pause(Robot robot) {
robot.waitForIdle();
robot.delay(500);
}
}
Loading

0 comments on commit 88f8bc6

Please sign in to comment.