# HG changeset patch # User serb # Date 1489690988 -10800 # Node ID a99429b721a940570a3a0c964203079bfa8b8bac # Parent eb56196e2a3a5e2df8045a66d9ae7b0fa1db334e 8160270: dual-screen issue with java.awt.Choice Reviewed-by: prr, alexsch diff -r eb56196e2a3a -r a99429b721a9 jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java Thu Mar 16 23:29:52 2017 +0300 +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java Thu Mar 16 22:03:08 2017 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, 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 @@ -25,17 +25,34 @@ package sun.awt.X11; -import java.awt.*; -import java.awt.event.*; -import java.awt.peer.TrayIconPeer; -import sun.awt.*; - -import java.awt.image.*; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Image; +import java.awt.Insets; +import java.awt.Label; +import java.awt.MouseInfo; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.text.BreakIterator; import java.util.concurrent.ArrayBlockingQueue; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.lang.reflect.InvocationTargetException; + +import sun.awt.SunToolkit; /** * An utility window class. This is a base class for Tooltip and Balloon. @@ -81,16 +98,16 @@ Dimension size = getSize(); Rectangle scrSize = getGraphicsConfiguration().getBounds(); - if (corner.x < scrSize.width/2 && corner.y < scrSize.height/2) { // 1st square + if (corner.x < scrSize.x + scrSize.width/2 && corner.y < scrSize.y + scrSize.height/2) { // 1st square setLocation(corner.x + indent, corner.y + indent); - } else if (corner.x >= scrSize.width/2 && corner.y < scrSize.height/2) { // 2nd square + } else if (corner.x >= scrSize.x + scrSize.width/2 && corner.y < scrSize.y + scrSize.height/2) { // 2nd square setLocation(corner.x - indent - size.width, corner.y + indent); - } else if (corner.x < scrSize.width/2 && corner.y >= scrSize.height/2) { // 3rd square + } else if (corner.x < scrSize.x + scrSize.width/2 && corner.y >= scrSize.y + scrSize.height/2) { // 3rd square setLocation(corner.x + indent, corner.y - indent - size.height); - } else if (corner.x >= scrSize.width/2 && corner.y >= scrSize.height/2) { // 4th square + } else if (corner.x >= scrSize.x +scrSize.width/2 && corner.y >= scrSize.y +scrSize.height/2) { // 4th square setLocation(corner.x - indent - size.width, corner.y - indent - size.height); } diff -r eb56196e2a3a -r a99429b721a9 jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java Thu Mar 16 23:29:52 2017 +0300 +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java Thu Mar 16 22:03:08 2017 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -25,17 +25,15 @@ package sun.awt.X11; import java.awt.*; -import java.awt.peer.*; import java.awt.event.*; -import java.awt.image.ColorModel; import sun.awt.*; +import java.awt.peer.ComponentPeer; import java.util.ArrayList; import java.util.Vector; import sun.util.logging.PlatformLogger; import sun.java2d.SurfaceData; -import sun.java2d.SunGraphics2D; /** * The abstract class XBaseMenuWindow is the superclass @@ -656,28 +654,37 @@ * ************************************************/ + GraphicsConfiguration getCurrentGraphicsConfiguration() { + Component hw = SunToolkit.getHeavyweightComponent(target); + XWindow peer = AWTAccessor.getComponentAccessor().getPeer(hw); + if (peer != null && peer.graphicsConfig != null) { + return peer.graphicsConfig; + } + return graphicsConfig; + } + /** * Checks if window fits below specified item * returns rectangle that the window fits to or null. * @param itemBounds rectangle of item in global coordinates * @param windowSize size of submenu window to fit - * @param screenSize size of screen + * @param screenBounds size of screen */ - Rectangle fitWindowBelow(Rectangle itemBounds, Dimension windowSize, Dimension screenSize) { + Rectangle fitWindowBelow(Rectangle itemBounds, Dimension windowSize, Rectangle screenBounds) { int width = windowSize.width; int height = windowSize.height; //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened //near the periphery of the screen, XToolkit //Window should be moved if it's outside top-left screen bounds - int x = (itemBounds.x > 0) ? itemBounds.x : 0; - int y = (itemBounds.y + itemBounds.height > 0) ? itemBounds.y + itemBounds.height : 0; - if (y + height <= screenSize.height) { + int x = (itemBounds.x > screenBounds.x) ? itemBounds.x : screenBounds.x; + int y = (itemBounds.y + itemBounds.height > screenBounds.y) ? itemBounds.y + itemBounds.height : screenBounds.y; + if (y + height <= screenBounds.y + screenBounds.height) { //move it to the left if needed - if (width > screenSize.width) { - width = screenSize.width; + if (width > screenBounds.width) { + width = screenBounds.width; } - if (x + width > screenSize.width) { - x = screenSize.width - width; + if (x + width > screenBounds.x + screenBounds.width) { + x = screenBounds.x + screenBounds.width - width; } return new Rectangle(x, y, width, height); } else { @@ -690,23 +697,23 @@ * returns rectangle that the window fits to or null. * @param itemBounds rectangle of item in global coordinates * @param windowSize size of submenu window to fit - * @param screenSize size of screen + * @param screenBounds size of screen */ - Rectangle fitWindowAbove(Rectangle itemBounds, Dimension windowSize, Dimension screenSize) { + Rectangle fitWindowAbove(Rectangle itemBounds, Dimension windowSize, Rectangle screenBounds) { int width = windowSize.width; int height = windowSize.height; //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened //near the periphery of the screen, XToolkit //Window should be moved if it's outside bottom-left screen bounds - int x = (itemBounds.x > 0) ? itemBounds.x : 0; - int y = (itemBounds.y > screenSize.height) ? screenSize.height - height : itemBounds.y - height; - if (y >= 0) { + int x = (itemBounds.x > screenBounds.x) ? itemBounds.x : screenBounds.x; + int y = (itemBounds.y > screenBounds.y + screenBounds.height) ? screenBounds.y + screenBounds.height - height : itemBounds.y - height; + if (y >= screenBounds.y) { //move it to the left if needed - if (width > screenSize.width) { - width = screenSize.width; + if (width > screenBounds.width) { + width = screenBounds.width; } - if (x + width > screenSize.width) { - x = screenSize.width - width; + if (x + width > screenBounds.x + screenBounds.width) { + x = screenBounds.x + screenBounds.width - width; } return new Rectangle(x, y, width, height); } else { @@ -719,23 +726,23 @@ * returns rectangle that the window fits to or null. * @param itemBounds rectangle of item in global coordinates * @param windowSize size of submenu window to fit - * @param screenSize size of screen + * @param screenBounds size of screen */ - Rectangle fitWindowRight(Rectangle itemBounds, Dimension windowSize, Dimension screenSize) { + Rectangle fitWindowRight(Rectangle itemBounds, Dimension windowSize, Rectangle screenBounds) { int width = windowSize.width; int height = windowSize.height; //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened //near the periphery of the screen, XToolkit //Window should be moved if it's outside top-left screen bounds - int x = (itemBounds.x + itemBounds.width > 0) ? itemBounds.x + itemBounds.width : 0; - int y = (itemBounds.y > 0) ? itemBounds.y : 0; - if (x + width <= screenSize.width) { + int x = (itemBounds.x + itemBounds.width > screenBounds.x) ? itemBounds.x + itemBounds.width : screenBounds.x; + int y = (itemBounds.y > screenBounds.y) ? itemBounds.y : screenBounds.y; + if (x + width <= screenBounds.x + screenBounds.width) { //move it to the top if needed - if (height > screenSize.height) { - height = screenSize.height; + if (height > screenBounds.height) { + height = screenBounds.height; } - if (y + height > screenSize.height) { - y = screenSize.height - height; + if (y + height > screenBounds.y + screenBounds.height) { + y = screenBounds.y + screenBounds.height - height; } return new Rectangle(x, y, width, height); } else { @@ -748,23 +755,23 @@ * returns rectangle that the window fits to or null. * @param itemBounds rectangle of item in global coordinates * @param windowSize size of submenu window to fit - * @param screenSize size of screen + * @param screenBounds size of screen */ - Rectangle fitWindowLeft(Rectangle itemBounds, Dimension windowSize, Dimension screenSize) { + Rectangle fitWindowLeft(Rectangle itemBounds, Dimension windowSize, Rectangle screenBounds) { int width = windowSize.width; int height = windowSize.height; //Fix for 6267162: PIT: Popup Menu gets hidden below the screen when opened //near the periphery of the screen, XToolkit //Window should be moved if it's outside top-right screen bounds - int x = (itemBounds.x < screenSize.width) ? itemBounds.x - width : screenSize.width - width; - int y = (itemBounds.y > 0) ? itemBounds.y : 0; - if (x >= 0) { + int x = (itemBounds.x < screenBounds.x + screenBounds.width) ? itemBounds.x - width : screenBounds.x + screenBounds.width - width; + int y = (itemBounds.y > screenBounds.y) ? itemBounds.y : screenBounds.y; + if (x >= screenBounds.x) { //move it to the top if needed - if (height > screenSize.height) { - height = screenSize.height; + if (height > screenBounds.height) { + height = screenBounds.height; } - if (y + height > screenSize.height) { - y = screenSize.height - height; + if (y + height > screenBounds.y + screenBounds.height) { + y = screenBounds.y + screenBounds.height - height; } return new Rectangle(x, y, width, height); } else { @@ -777,12 +784,12 @@ * to fit it on screen - move it to the * top-left edge and cut by screen dimensions * @param windowSize size of submenu window to fit - * @param screenSize size of screen + * @param screenBounds size of screen */ - Rectangle fitWindowToScreen(Dimension windowSize, Dimension screenSize) { - int width = (windowSize.width < screenSize.width) ? windowSize.width : screenSize.width; - int height = (windowSize.height < screenSize.height) ? windowSize.height : screenSize.height; - return new Rectangle(0, 0, width, height); + Rectangle fitWindowToScreen(Dimension windowSize, Rectangle screenBounds) { + int width = (windowSize.width < screenBounds.width) ? windowSize.width : screenBounds.width; + int height = (windowSize.height < screenBounds.height) ? windowSize.height : screenBounds.height; + return new Rectangle(screenBounds.x, screenBounds.y, width, height); } diff -r eb56196e2a3a -r a99429b721a9 jdk/src/java.desktop/unix/classes/sun/awt/X11/XChoicePeer.java --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XChoicePeer.java Thu Mar 16 23:29:52 2017 +0300 +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XChoicePeer.java Thu Mar 16 22:03:08 2017 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -42,7 +42,7 @@ // TODO: make painting more efficient (i.e. when down arrow is pressed, only two items should need to be repainted. -public class XChoicePeer extends XComponentPeer implements ChoicePeer, ToplevelStateListener { +public final class XChoicePeer extends XComponentPeer implements ChoicePeer, ToplevelStateListener { private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XChoicePeer"); private static final int MAX_UNFURLED_ITEMS = 10; // Maximum number of @@ -741,6 +741,16 @@ } } + @Override + protected void initGraphicsConfiguration() { + super.initGraphicsConfiguration(); + // The popup have the same graphic config, so update it at the same time + if (unfurledChoice != null) { + unfurledChoice.initGraphicsConfiguration(); + unfurledChoice.doValidateSurface(); + } + } + /**************************************************************************/ /* Common functionality between List & Choice /**************************************************************************/ @@ -749,7 +759,7 @@ * Inner class for the unfurled Choice list * Much, much more docs */ - class UnfurledChoice extends XWindow /*implements XScrollbarClient*/ { + final class UnfurledChoice extends XWindow /*implements XScrollbarClient*/ { // First try - use Choice as the target @@ -785,7 +795,7 @@ numItemsDisplayed = Math.min(MAX_UNFURLED_ITEMS, numItems); } Point global = XChoicePeer.this.toGlobal(0,0); - Rectangle screen = graphicsConfig.getBounds(); + Rectangle screenBounds = graphicsConfig.getBounds(); if (alignUnder != null) { Rectangle choiceRec = XChoicePeer.this.getBounds(); @@ -807,19 +817,19 @@ height = 2*BORDER_WIDTH + numItemsDisplayed*(helper.getItemHeight()+2*ITEM_MARGIN); } - // Don't run off the edge of the screen - if (x < 0) { - x = 0; + // Don't run off the edge of the screenBounds + if (x < screenBounds.x) { + x = screenBounds.x; } - else if (x + width > screen.width) { - x = screen.width - width; + else if (x + width > screenBounds.x + screenBounds.width) { + x = screenBounds.x + screenBounds.width - width; } - if (y + height > screen.height) { + if (y + height > screenBounds.y + screenBounds.height) { y = global.y - height; } - if (y < 0) { - y = 0; + if (y < screenBounds.y) { + y = screenBounds.y; } return new Rectangle(x, y, width, height); } diff -r eb56196e2a3a -r a99429b721a9 jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java Thu Mar 16 23:29:52 2017 +0300 +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java Thu Mar 16 22:03:08 2017 +0300 @@ -298,25 +298,25 @@ */ protected Rectangle getSubmenuBounds(Rectangle itemBounds, Dimension windowSize) { Rectangle globalBounds = toGlobal(itemBounds); - Dimension screenSize = graphicsConfig.getBounds().getSize(); + Rectangle screenBounds = getCurrentGraphicsConfiguration().getBounds(); Rectangle res; - res = fitWindowBelow(globalBounds, windowSize, screenSize); + res = fitWindowBelow(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowAbove(globalBounds, windowSize, screenSize); + res = fitWindowAbove(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowRight(globalBounds, windowSize, screenSize); + res = fitWindowRight(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowLeft(globalBounds, windowSize, screenSize); + res = fitWindowLeft(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - return fitWindowToScreen(windowSize, screenSize); + return fitWindowToScreen(windowSize, screenBounds); } /** diff -r eb56196e2a3a -r a99429b721a9 jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java Thu Mar 16 23:29:52 2017 +0300 +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java Thu Mar 16 22:03:08 2017 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -278,25 +278,25 @@ */ protected Rectangle getSubmenuBounds(Rectangle itemBounds, Dimension windowSize) { Rectangle globalBounds = toGlobal(itemBounds); - Dimension screenSize = graphicsConfig.getBounds().getSize(); + Rectangle screenBounds = getCurrentGraphicsConfiguration().getBounds(); Rectangle res; - res = fitWindowRight(globalBounds, windowSize, screenSize); + res = fitWindowRight(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowBelow(globalBounds, windowSize, screenSize); + res = fitWindowBelow(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowAbove(globalBounds, windowSize, screenSize); + res = fitWindowAbove(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowLeft(globalBounds, windowSize, screenSize); + res = fitWindowLeft(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - return fitWindowToScreen(windowSize, screenSize); + return fitWindowToScreen(windowSize, screenBounds); } /** diff -r eb56196e2a3a -r a99429b721a9 jdk/src/java.desktop/unix/classes/sun/awt/X11/XPopupMenuPeer.java --- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XPopupMenuPeer.java Thu Mar 16 23:29:52 2017 +0300 +++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XPopupMenuPeer.java Thu Mar 16 22:03:08 2017 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -216,25 +216,25 @@ */ protected Rectangle getWindowBounds(Point origin, Dimension windowSize) { Rectangle globalBounds = new Rectangle(origin.x, origin.y, 0, 0); - Dimension screenSize = graphicsConfig.getBounds().getSize(); + Rectangle screenBounds = getCurrentGraphicsConfiguration().getBounds(); Rectangle res; - res = fitWindowRight(globalBounds, windowSize, screenSize); + res = fitWindowRight(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowLeft(globalBounds, windowSize, screenSize); + res = fitWindowLeft(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowBelow(globalBounds, windowSize, screenSize); + res = fitWindowBelow(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - res = fitWindowAbove(globalBounds, windowSize, screenSize); + res = fitWindowAbove(globalBounds, windowSize, screenBounds); if (res != null) { return res; } - return fitWindowToScreen(windowSize, screenSize); + return fitWindowToScreen(windowSize, screenBounds); } /************************************************ diff -r eb56196e2a3a -r a99429b721a9 jdk/test/java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java --- a/jdk/test/java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java Thu Mar 16 23:29:52 2017 +0300 +++ b/jdk/test/java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java Thu Mar 16 22:03:08 2017 +0300 @@ -42,17 +42,23 @@ public final class ChoicePopupLocation { private static final int SIZE = 350; + private static int frameWidth; public static void main(final String[] args) throws Exception { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice[] sds = ge.getScreenDevices(); Point left = null; + Point right = null; for (GraphicsDevice sd : sds) { GraphicsConfiguration gc = sd.getDefaultConfiguration(); Rectangle bounds = gc.getBounds(); if (left == null || left.x > bounds.x) { left = new Point(bounds.x, bounds.y + bounds.height / 2); } + if (right == null || right.x < bounds.x + bounds.width) { + right = new Point(bounds.x + bounds.width, + bounds.y + bounds.height / 2); + } Point point = new Point(bounds.x, bounds.y); Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); @@ -69,6 +75,10 @@ left.translate(-50, 0); test(left); } + if (right != null) { + right.translate(-frameWidth + 50, 0); + test(right); + } } private static void test(final Point tmp) throws Exception { @@ -82,7 +92,8 @@ frame.setLayout(new FlowLayout()); frame.add(choice); frame.pack(); - frame.setSize(frame.getWidth(), SIZE); + frameWidth = frame.getWidth(); + frame.setSize(frameWidth, SIZE); frame.setVisible(true); frame.setLocation(tmp.x, tmp.y); openPopup(choice); diff -r eb56196e2a3a -r a99429b721a9 jdk/test/java/awt/PopupMenu/PopupMenuLocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/awt/PopupMenu/PopupMenuLocation.java Thu Mar 16 22:03:08 2017 +0300 @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2017, 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 + * 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 java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Insets; +import java.awt.Point; +import java.awt.PopupMenu; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.*; + +/** + * @test + * @bug 8160270 + * @run main/timeout=300 PopupMenuLocation + */ +public final class PopupMenuLocation { + + private static final int SIZE = 350; + public static final String TEXT = + "Long-long-long-long-long-long-long text in the item-"; + private static volatile boolean action = false; + + public static void main(final String[] args) throws Exception { + GraphicsEnvironment ge = + GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] sds = ge.getScreenDevices(); + for (GraphicsDevice sd : sds) { + GraphicsConfiguration gc = sd.getDefaultConfiguration(); + Rectangle bounds = gc.getBounds(); + Point point = new Point(bounds.x, bounds.y); + Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gc); + while (point.y < bounds.y + bounds.height - insets.bottom - SIZE) { + while (point.x + < bounds.x + bounds.width - insets.right - SIZE) { + test(point); + point.translate(bounds.width / 5, 0); + } + point.setLocation(bounds.x, point.y + bounds.height / 5); + } + } + } + + private static void test(final Point tmp) throws Exception { + PopupMenu pm = new PopupMenu(); + for (int i = 1; i < 7; i++) { + pm.add(TEXT + i); + } + pm.addActionListener(e -> action = true); + Frame frame = new Frame(); + try { + frame.setAlwaysOnTop(true); + frame.setLayout(new FlowLayout()); + frame.add(pm); + frame.pack(); + frame.setSize(SIZE, SIZE); + frame.setVisible(true); + frame.setLocation(tmp.x, tmp.y); + frame.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + show(e); + } + + public void mouseReleased(MouseEvent e) { + show(e); + } + + private void show(MouseEvent e) { + if (e.isPopupTrigger()) { + pm.show(frame, 0, 50); + } + } + }); + openPopup(frame); + } finally { + frame.dispose(); + } + } + + private static void openPopup(final Frame frame) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(200); + robot.waitForIdle(); + Point pt = frame.getLocationOnScreen(); + robot.mouseMove(pt.x + frame.getWidth() / 2, pt.y + 50); + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + int x = pt.x + frame.getWidth() / 2; + int y = pt.y + 130; + robot.mouseMove(x, y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + if (!action) { + throw new RuntimeException(); + } + action = false; + } +}