8160270: dual-screen issue with java.awt.Choice
authorserb
Thu, 16 Mar 2017 22:03:08 +0300
changeset 44354 a99429b721a9
parent 44353 eb56196e2a3a
child 44355 bca217cee0d0
child 44645 32f74dc4eaf8
8160270: dual-screen issue with java.awt.Choice Reviewed-by: prr, alexsch
jdk/src/java.desktop/unix/classes/sun/awt/X11/InfoWindow.java
jdk/src/java.desktop/unix/classes/sun/awt/X11/XBaseMenuWindow.java
jdk/src/java.desktop/unix/classes/sun/awt/X11/XChoicePeer.java
jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuBarPeer.java
jdk/src/java.desktop/unix/classes/sun/awt/X11/XMenuWindow.java
jdk/src/java.desktop/unix/classes/sun/awt/X11/XPopupMenuPeer.java
jdk/test/java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java
jdk/test/java/awt/PopupMenu/PopupMenuLocation.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);
         }
 
--- 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;
+    }
+}