mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-25 01:30:10 +00:00
8289547: Update javax/swing/Popup/TaskbarPositionTest.java
Reviewed-by: aivanov, dmarkov, honkar
This commit is contained in:
parent
7cf6eecdc8
commit
d73fc70ea2
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -24,6 +24,8 @@
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
@ -33,8 +35,9 @@ import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
@ -47,54 +50,61 @@ import javax.swing.JSeparator;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.PopupMenuListener;
|
||||
import javax.swing.event.PopupMenuEvent;
|
||||
import javax.swing.event.PopupMenuListener;
|
||||
|
||||
/**
|
||||
import jtreg.SkippedException;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4245587 4474813 4425878 4767478 8015599
|
||||
* @key headful
|
||||
* @summary Tests the location of the heavy weight popup portion of JComboBox,
|
||||
* JMenu and JPopupMenu.
|
||||
* The test uses Ctrl+Down Arrow (↓) which is a system shortcut on macOS,
|
||||
* disable it in system settings, otherwise the test will fail
|
||||
* @library ../regtesthelpers
|
||||
* @library /test/lib
|
||||
* @build Util
|
||||
* @build jtreg.SkippedException
|
||||
* @run main TaskbarPositionTest
|
||||
*/
|
||||
public class TaskbarPositionTest implements ActionListener {
|
||||
|
||||
private boolean done;
|
||||
private Throwable error;
|
||||
private static TaskbarPositionTest test;
|
||||
private static JFrame frame;
|
||||
private static JPopupMenu popupMenu;
|
||||
private static JPanel panel;
|
||||
|
||||
private static JComboBox<String> combo1;
|
||||
private static JComboBox<String> combo2;
|
||||
private static JMenuBar menubar;
|
||||
|
||||
private static JMenu menu1;
|
||||
private static JMenu menu2;
|
||||
private static JMenu submenu;
|
||||
|
||||
private static Rectangle fullScreenBounds;
|
||||
// The usable desktop space: screen size - screen insets.
|
||||
private static Rectangle screenBounds;
|
||||
private static String[] numData = {
|
||||
|
||||
private static final String[] numData = {
|
||||
"One", "Two", "Three", "Four", "Five", "Six", "Seven"
|
||||
};
|
||||
private static String[] dayData = {
|
||||
private static final String[] dayData = {
|
||||
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
|
||||
};
|
||||
private static char[] mnDayData = {
|
||||
private static final char[] mnDayData = {
|
||||
'M', 'T', 'W', 'R', 'F', 'S', 'U'
|
||||
};
|
||||
|
||||
public TaskbarPositionTest() {
|
||||
frame = new JFrame("Use CTRL-down to show a JPopupMenu");
|
||||
frame.setContentPane(panel = createContentPane());
|
||||
frame.setJMenuBar(createMenuBar("1 - First Menu", true));
|
||||
frame.setJMenuBar(createMenuBar());
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
// CTRL-down will show the popup.
|
||||
panel.getInputMap().put(KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP");
|
||||
KeyEvent.VK_DOWN, InputEvent.CTRL_DOWN_MASK), "OPEN_POPUP");
|
||||
panel.getActionMap().put("OPEN_POPUP", new PopupHandler());
|
||||
|
||||
frame.pack();
|
||||
@ -103,7 +113,6 @@ public class TaskbarPositionTest implements ActionListener {
|
||||
fullScreenBounds = new Rectangle(new Point(), toolkit.getScreenSize());
|
||||
screenBounds = new Rectangle(new Point(), toolkit.getScreenSize());
|
||||
|
||||
|
||||
// Reduce the screen bounds by the insets.
|
||||
GraphicsConfiguration gc = frame.getGraphicsConfiguration();
|
||||
if (gc != null) {
|
||||
@ -116,37 +125,56 @@ public class TaskbarPositionTest implements ActionListener {
|
||||
}
|
||||
|
||||
// Place the frame near the bottom.
|
||||
frame.setLocation(0, screenBounds.y + screenBounds.height - frame.getHeight());
|
||||
frame.setLocation(screenBounds.x,
|
||||
screenBounds.y + screenBounds.height - frame.getHeight());
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
public static class ComboPopupCheckListener implements PopupMenuListener {
|
||||
private static class ComboPopupCheckListener implements PopupMenuListener {
|
||||
|
||||
@Override
|
||||
public void popupMenuCanceled(PopupMenuEvent ev) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent ev) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent ev) {
|
||||
Point cpos = combo1.getLocation();
|
||||
SwingUtilities.convertPointToScreen(cpos, panel);
|
||||
JComboBox<?> combo = (JComboBox<?>) ev.getSource();
|
||||
Point comboLoc = combo.getLocationOnScreen();
|
||||
|
||||
JPopupMenu pm = (JPopupMenu) combo1.getUI().getAccessibleChild(combo1, 0);
|
||||
JPopupMenu popupMenu = (JPopupMenu) combo.getUI().getAccessibleChild(combo, 0);
|
||||
|
||||
if (pm != null) {
|
||||
Point p = pm.getLocation();
|
||||
SwingUtilities.convertPointToScreen(p, pm);
|
||||
if (p.y+1 < cpos.y) {
|
||||
System.out.println("p.y " + p.y + " cpos.y " + cpos.y);
|
||||
throw new RuntimeException("ComboBox popup is wrongly aligned");
|
||||
} // check that popup was opened down
|
||||
Point popupMenuLoc = popupMenu.getLocationOnScreen();
|
||||
Dimension popupSize = popupMenu.getSize();
|
||||
|
||||
isPopupOnScreen(popupMenu, fullScreenBounds);
|
||||
|
||||
if (comboLoc.x > 0) {
|
||||
// The frame is located at the bottom of the screen,
|
||||
// the combo popups should open upwards
|
||||
if (popupMenuLoc.y + popupSize.height < comboLoc.y) {
|
||||
System.err.println("popup " + popupMenuLoc
|
||||
+ " combo " + comboLoc);
|
||||
throw new RuntimeException("ComboBox popup should open upwards");
|
||||
}
|
||||
} else {
|
||||
// The frame has been moved to negative position away from
|
||||
// the bottom of the screen, the combo popup should
|
||||
// open downwards in this case
|
||||
if (popupMenuLoc.y + 1 < comboLoc.y) {
|
||||
System.err.println("popup " + popupMenuLoc
|
||||
+ " combo " + comboLoc);
|
||||
throw new RuntimeException("ComboBox popup should open downwards");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class PopupHandler extends AbstractAction {
|
||||
|
||||
private static class PopupHandler extends AbstractAction {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (!popupMenu.isVisible()) {
|
||||
popupMenu.show((Component) e.getSource(), 40, 40);
|
||||
@ -155,18 +183,20 @@ public class TaskbarPositionTest implements ActionListener {
|
||||
}
|
||||
}
|
||||
|
||||
class PopupListener extends MouseAdapter {
|
||||
private static class PopupListener extends MouseAdapter {
|
||||
|
||||
private JPopupMenu popup;
|
||||
private final JPopupMenu popup;
|
||||
|
||||
public PopupListener(JPopupMenu popup) {
|
||||
this.popup = popup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
maybeShowPopup(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
maybeShowPopup(e);
|
||||
}
|
||||
@ -182,121 +212,137 @@ public class TaskbarPositionTest implements ActionListener {
|
||||
/**
|
||||
* Tests if the popup is on the screen.
|
||||
*/
|
||||
public static void isPopupOnScreen(JPopupMenu popup, Rectangle checkBounds) {
|
||||
private static void isPopupOnScreen(JPopupMenu popup, Rectangle checkBounds) {
|
||||
if (!popup.isVisible()) {
|
||||
throw new RuntimeException("Popup not visible");
|
||||
}
|
||||
Dimension dim = popup.getSize();
|
||||
Point pt = new Point();
|
||||
SwingUtilities.convertPointToScreen(pt, popup);
|
||||
Point pt = popup.getLocationOnScreen();
|
||||
Rectangle bounds = new Rectangle(pt, dim);
|
||||
|
||||
if (!SwingUtilities.isRectangleContainingRectangle(checkBounds, bounds)) {
|
||||
throw new RuntimeException("We do not match! " + checkBounds + " / " + bounds);
|
||||
throw new RuntimeException("Popup is outside of screen bounds "
|
||||
+ checkBounds + " / " + bounds);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private JPanel createContentPane() {
|
||||
JPanel panel = new JPanel();
|
||||
private static void isComboPopupOnScreen(JComboBox<?> comboBox) {
|
||||
if (!comboBox.isPopupVisible()) {
|
||||
throw new RuntimeException("ComboBox popup not visible");
|
||||
}
|
||||
JPopupMenu popupMenu = (JPopupMenu) comboBox.getUI().getAccessibleChild(comboBox, 0);
|
||||
isPopupOnScreen(popupMenu, screenBounds);
|
||||
}
|
||||
|
||||
|
||||
private JPanel createContentPane() {
|
||||
combo1 = new JComboBox<>(numData);
|
||||
panel.add(combo1);
|
||||
combo1.addPopupMenuListener(new ComboPopupCheckListener());
|
||||
|
||||
combo2 = new JComboBox<>(dayData);
|
||||
combo2.setEditable(true);
|
||||
panel.add(combo2);
|
||||
panel.setSize(300, 200);
|
||||
combo2.addPopupMenuListener(new ComboPopupCheckListener());
|
||||
|
||||
popupMenu = new JPopupMenu();
|
||||
JMenuItem item;
|
||||
for (int i = 0; i < dayData.length; i++) {
|
||||
item = popupMenu.add(new JMenuItem(dayData[i], mnDayData[i]));
|
||||
JMenuItem item = popupMenu.add(new JMenuItem(dayData[i], mnDayData[i]));
|
||||
item.addActionListener(this);
|
||||
}
|
||||
panel.addMouseListener(new PopupListener(popupMenu));
|
||||
|
||||
JTextField field = new JTextField("CTRL+down for Popup");
|
||||
// CTRL-down will show the popup.
|
||||
field.getInputMap().put(KeyStroke.getKeyStroke(
|
||||
KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP");
|
||||
KeyEvent.VK_DOWN, InputEvent.CTRL_DOWN_MASK), "OPEN_POPUP");
|
||||
field.getActionMap().put("OPEN_POPUP", new PopupHandler());
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.add(combo1);
|
||||
panel.add(combo2);
|
||||
panel.setSize(300, 200);
|
||||
panel.addMouseListener(new PopupListener(popupMenu));
|
||||
panel.add(field);
|
||||
|
||||
return panel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param str name of Menu
|
||||
* @param bFlag set mnemonics on menu items
|
||||
*/
|
||||
private JMenuBar createMenuBar(String str, boolean bFlag) {
|
||||
menubar = new JMenuBar();
|
||||
|
||||
menu1 = new JMenu(str);
|
||||
menu1.setMnemonic(str.charAt(0));
|
||||
menu1.addActionListener(this);
|
||||
private JMenuBar createMenuBar() {
|
||||
JMenuBar menubar = new JMenuBar();
|
||||
|
||||
menu1 = new JMenu("1 - First Menu");
|
||||
menu1.setMnemonic('1');
|
||||
createSubMenu(menu1, "1 JMenuItem", 8, null);
|
||||
menubar.add(menu1);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
JMenuItem menuitem = new JMenuItem("1 JMenuItem" + i);
|
||||
menuitem.addActionListener(this);
|
||||
if (bFlag) {
|
||||
menuitem.setMnemonic('0' + i);
|
||||
}
|
||||
menu1.add(menuitem);
|
||||
}
|
||||
|
||||
// second menu
|
||||
menu2 = new JMenu("2 - Second Menu");
|
||||
menu2.addActionListener(this);
|
||||
menu2.setMnemonic('2');
|
||||
|
||||
menubar.add(menu2);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
JMenuItem menuitem = new JMenuItem("2 JMenuItem" + i);
|
||||
menuitem.addActionListener(this);
|
||||
|
||||
if (bFlag) {
|
||||
menuitem.setMnemonic('0' + i);
|
||||
}
|
||||
menu2.add(menuitem);
|
||||
}
|
||||
JMenu submenu = new JMenu("Sub Menu");
|
||||
submenu.setMnemonic('S');
|
||||
submenu.addActionListener(this);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
JMenuItem menuitem = new JMenuItem("S JMenuItem" + i);
|
||||
menuitem.addActionListener(this);
|
||||
if (bFlag) {
|
||||
menuitem.setMnemonic('0' + i);
|
||||
}
|
||||
submenu.add(menuitem);
|
||||
}
|
||||
createSubMenu(menu2, "2 JMenuItem", 4, null);
|
||||
menu2.add(new JSeparator());
|
||||
menubar.add(menu2);
|
||||
|
||||
submenu = new JMenu("Sub Menu");
|
||||
submenu.setMnemonic('S');
|
||||
createSubMenu(submenu, "S JMenuItem", 4, this);
|
||||
menu2.add(submenu);
|
||||
|
||||
return menubar;
|
||||
}
|
||||
|
||||
private static void createSubMenu(JMenu menu, String prefix, int count, ActionListener action) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
JMenuItem menuitem = new JMenuItem(prefix + i);
|
||||
menu.add(menuitem);
|
||||
if (action != null) {
|
||||
menuitem.addActionListener(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void actionPerformed(ActionEvent evt) {
|
||||
Object obj = evt.getSource();
|
||||
if (obj instanceof JMenuItem) {
|
||||
// put the focus on the noneditable combo.
|
||||
// put the focus on the non-editable combo.
|
||||
combo1.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
private static void hidePopup(Robot robot) {
|
||||
robot.keyPress(KeyEvent.VK_ESCAPE);
|
||||
robot.keyRelease(KeyEvent.VK_ESCAPE);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
GraphicsDevice mainScreen = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getDefaultScreenDevice();
|
||||
Rectangle mainScreenBounds = mainScreen.getDefaultConfiguration()
|
||||
.getBounds();
|
||||
GraphicsDevice[] screens = GraphicsEnvironment.getLocalGraphicsEnvironment()
|
||||
.getScreenDevices();
|
||||
for (GraphicsDevice screen : screens) {
|
||||
if (screen == mainScreen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rectangle bounds = screen.getDefaultConfiguration()
|
||||
.getBounds();
|
||||
if (bounds.x < 0) {
|
||||
// The test may fail if a screen have negative origin
|
||||
throw new SkippedException("Configurations with negative screen"
|
||||
+ " origin are not supported");
|
||||
}
|
||||
if (bounds.y >= mainScreenBounds.height) {
|
||||
// The test may fail if there's a screen to bottom of the main monitor
|
||||
throw new SkippedException("Configurations with a screen beneath"
|
||||
+ " the main one are not supported");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// Use Robot to automate the test
|
||||
Robot robot;
|
||||
robot = new Robot();
|
||||
Robot robot = new Robot();
|
||||
robot.setAutoDelay(50);
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
test = new TaskbarPositionTest();
|
||||
}
|
||||
});
|
||||
SwingUtilities.invokeAndWait(TaskbarPositionTest::new);
|
||||
|
||||
robot.waitForIdle();
|
||||
robot.delay(1000);
|
||||
@ -310,58 +356,90 @@ public class TaskbarPositionTest implements ActionListener {
|
||||
// 2 menu with sub menu
|
||||
robot.keyPress(KeyEvent.VK_RIGHT);
|
||||
robot.keyRelease(KeyEvent.VK_RIGHT);
|
||||
Util.hitMnemonics(robot, KeyEvent.VK_S);
|
||||
// Open the submenu
|
||||
robot.keyPress(KeyEvent.VK_S);
|
||||
robot.keyRelease(KeyEvent.VK_S);
|
||||
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(() -> isPopupOnScreen(menu2.getPopupMenu(), screenBounds));
|
||||
SwingUtilities.invokeAndWait(() -> isPopupOnScreen(submenu.getPopupMenu(), screenBounds));
|
||||
|
||||
// Hit Enter to perform the action of
|
||||
// a selected menu item in the submenu
|
||||
// which requests focus on combo1, non-editable combo box
|
||||
robot.keyPress(KeyEvent.VK_ENTER);
|
||||
robot.keyRelease(KeyEvent.VK_ENTER);
|
||||
|
||||
// Focus should go to non editable combo box
|
||||
robot.waitForIdle();
|
||||
robot.delay(500);
|
||||
|
||||
robot.keyPress(KeyEvent.VK_DOWN);
|
||||
|
||||
// How do we check combo boxes?
|
||||
|
||||
// Editable combo box
|
||||
robot.keyPress(KeyEvent.VK_TAB);
|
||||
robot.keyRelease(KeyEvent.VK_TAB);
|
||||
// Focus should go to combo1
|
||||
// Open combo1 popup
|
||||
robot.keyPress(KeyEvent.VK_DOWN);
|
||||
robot.keyRelease(KeyEvent.VK_DOWN);
|
||||
|
||||
// combo1.getUI();
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(() -> isComboPopupOnScreen(combo1));
|
||||
hidePopup(robot);
|
||||
|
||||
// Popup from Text field
|
||||
// Move focus to combo2, editable combo box
|
||||
robot.keyPress(KeyEvent.VK_TAB);
|
||||
robot.keyRelease(KeyEvent.VK_TAB);
|
||||
|
||||
robot.waitForIdle();
|
||||
|
||||
// Open combo2 popup
|
||||
robot.keyPress(KeyEvent.VK_DOWN);
|
||||
robot.keyRelease(KeyEvent.VK_DOWN);
|
||||
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(() -> isComboPopupOnScreen(combo2));
|
||||
hidePopup(robot);
|
||||
|
||||
// Move focus to the text field
|
||||
robot.keyPress(KeyEvent.VK_TAB);
|
||||
robot.keyRelease(KeyEvent.VK_TAB);
|
||||
|
||||
robot.waitForIdle();
|
||||
|
||||
// Open its popup
|
||||
robot.keyPress(KeyEvent.VK_CONTROL);
|
||||
robot.keyPress(KeyEvent.VK_DOWN);
|
||||
robot.keyRelease(KeyEvent.VK_DOWN);
|
||||
robot.keyRelease(KeyEvent.VK_CONTROL);
|
||||
|
||||
// Popup from a mouse click.
|
||||
Point pt = new Point(2, 2);
|
||||
SwingUtilities.convertPointToScreen(pt, panel);
|
||||
robot.mouseMove(pt.x, pt.y);
|
||||
robot.mousePress(InputEvent.BUTTON3_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON3_MASK);
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(() -> isPopupOnScreen(popupMenu, fullScreenBounds));
|
||||
hidePopup(robot);
|
||||
|
||||
// Popup from a mouse click
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
Point pt = panel.getLocationOnScreen();
|
||||
pt.translate(4, 4);
|
||||
robot.mouseMove(pt.x, pt.y);
|
||||
});
|
||||
robot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
|
||||
robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
|
||||
|
||||
// Ensure popupMenu is shown within screen bounds
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(() -> isPopupOnScreen(popupMenu, fullScreenBounds));
|
||||
hidePopup(robot);
|
||||
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
frame.setLocation(-30, 100);
|
||||
combo1.addPopupMenuListener(new ComboPopupCheckListener());
|
||||
combo1.requestFocus();
|
||||
}
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
frame.setLocation(-30, 100);
|
||||
combo1.requestFocus();
|
||||
});
|
||||
|
||||
robot.waitForIdle();
|
||||
|
||||
// Open combo1 popup again
|
||||
robot.keyPress(KeyEvent.VK_DOWN);
|
||||
robot.keyRelease(KeyEvent.VK_DOWN);
|
||||
robot.keyPress(KeyEvent.VK_ESCAPE);
|
||||
robot.keyRelease(KeyEvent.VK_ESCAPE);
|
||||
|
||||
robot.waitForIdle();
|
||||
SwingUtilities.invokeAndWait(() -> isComboPopupOnScreen(combo1));
|
||||
hidePopup(robot);
|
||||
|
||||
robot.waitForIdle();
|
||||
} finally {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user