--- 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);
}
--- 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);
}
--- 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);
}
--- 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);
}
/**
--- 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);
}
/**
--- 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);
}
/************************************************
--- 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);
--- /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;
+ }
+}