changeset 12621:107316546dfc

Merge
author asaha
date Fri, 16 Dec 2016 17:04:37 -0800
parents 428054a0b832 e2dc0402ce33
children 6e2cee6f088e
files .hgtags src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java src/macosx/native/sun/awt/AWTWindow.m src/share/classes/sun/awt/AWTAccessor.java
diffstat 19 files changed, 380 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Mon Dec 12 12:53:36 2016 -0800
+++ b/.hgtags	Fri Dec 16 17:04:37 2016 -0800
@@ -664,6 +664,8 @@
 60767ec3909b3d0cb26dd7b3f952c62053719dda jdk8u112-b15
 5dd7e4bae5c2f1ee4f80c5570e7e3e2f715f7a32 jdk8u112-b16
 41fac11792c1ee6945f56721ee558a7424395a81 jdk8u112-b31
+548a51660ee94aeb77b2432594aeb87f87c21697 jdk8u112-b32
+a334b0815d34948188537a177a32cee27007ea2c jdk8u112-b33
 ab5ff8f1e52c5e3ca02e988f4d978af63ceca5b8 jdk8u121-b00
 5f0839ac7e0d25dd1ae705df496b12ca76c26d59 jdk8u121-b01
 f91e3aa155b3c6774afb456db15fb358313d5771 jdk8u121-b02
--- a/src/macosx/classes/sun/lwawt/LWMouseInfoPeer.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/LWMouseInfoPeer.java	Fri Dec 16 17:04:37 2016 -0800
@@ -51,8 +51,12 @@
             return false;
         }
 
-        final Object windowPeer = AWTAccessor.getComponentAccessor().getPeer(w);
-        return LWWindowPeer.getWindowUnderCursor() == windowPeer;
+        LWWindowPeer windowPeer = (LWWindowPeer)AWTAccessor.getComponentAccessor().getPeer(w);
+        if (windowPeer == null) {
+            return false;
+        }
+
+        return LWToolkit.getLWToolkit().getPlatformWindowUnderMouse() == windowPeer.getPlatformWindow();
     }
 
 }
--- a/src/macosx/classes/sun/lwawt/LWToolkit.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/LWToolkit.java	Fri Dec 16 17:04:37 2016 -0800
@@ -385,6 +385,8 @@
         return new LWMouseInfoPeer();
     }
 
+    protected abstract PlatformWindow getPlatformWindowUnderMouse();
+
     @Override
     public final PrintJob getPrintJob(Frame frame, String doctitle,
                                       Properties props) {
--- a/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/LWWindowPeer.java	Fri Dec 16 17:04:37 2016 -0800
@@ -749,11 +749,10 @@
                 lastMouseEventPeer = targetPeer;
             }
         } else {
-            PlatformWindow topmostPlatforWindow =
-                    platformWindow.getTopmostPlatformWindowUnderMouse();
+            PlatformWindow topmostPlatformWindow = LWToolkit.getLWToolkit().getPlatformWindowUnderMouse();
 
             LWWindowPeer topmostWindowPeer =
-                    topmostPlatforWindow != null ? topmostPlatforWindow.getPeer() : null;
+                    topmostPlatformWindow != null ? topmostPlatformWindow.getPeer() : null;
 
             // topmostWindowPeer == null condition is added for the backward
             // compatibility with applets. It can be removed when the
@@ -764,8 +763,7 @@
                         screenX, screenY, modifiers, clickCount, popupTrigger,
                         targetPeer);
             } else {
-                LWComponentPeer<?, ?> topmostTargetPeer =
-                        topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null;
+                LWComponentPeer<?, ?> topmostTargetPeer = topmostWindowPeer.findPeerAt(r.x + x, r.y + y);
                 topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y,
                         screenX, screenY, modifiers, clickCount, popupTrigger,
                         topmostTargetPeer);
--- a/src/macosx/classes/sun/lwawt/PlatformWindow.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/PlatformWindow.java	Fri Dec 16 17:04:37 2016 -0800
@@ -107,8 +107,6 @@
 
     public void setAlwaysOnTop(boolean value);
 
-    public PlatformWindow getTopmostPlatformWindowUnderMouse();
-
     public void updateFocusableWindowState();
 
     public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java	Fri Dec 16 17:04:37 2016 -0800
@@ -129,11 +129,6 @@
     @Override
     public void setAlwaysOnTop(boolean value) {}
 
-    // This method should be properly implemented for applets.
-    // It returns null just as a stub.
-    @Override
-    public PlatformWindow getTopmostPlatformWindowUnderMouse() { return null; }
-
     @Override
     public void updateFocusableWindowState() {}
 
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java	Fri Dec 16 17:04:37 2016 -0800
@@ -162,11 +162,6 @@
     }
 
     @Override
-    public PlatformWindow getTopmostPlatformWindowUnderMouse(){
-        return null;
-    }
-
-    @Override
     public void setOpacity(float opacity) {
     }
 
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Fri Dec 16 17:04:37 2016 -0800
@@ -31,12 +31,16 @@
 import java.awt.peer.WindowPeer;
 import java.beans.*;
 import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
 import javax.swing.*;
 
 import sun.awt.*;
+import sun.awt.AWTAccessor.ComponentAccessor;
+import sun.awt.AWTAccessor.WindowAccessor;
 import sun.java2d.SurfaceData;
 import sun.java2d.opengl.CGLSurfaceData;
 import sun.lwawt.*;
@@ -62,9 +66,9 @@
     private static native void nativeSetEnabled(long nsWindowPtr, boolean isEnabled);
     private static native void nativeSynthesizeMouseEnteredExitedEvents();
     private static native void nativeDispose(long nsWindowPtr);
-    private static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse();
     private static native void nativeEnterFullScreenMode(long nsWindowPtr);
     private static native void nativeExitFullScreenMode(long nsWindowPtr);
+    static native CPlatformWindow nativeGetTopmostPlatformWindowUnderMouse();
 
     // Loger to report issues happened during execution but that do not affect functionality
     private static final PlatformLogger logger = PlatformLogger.getLogger("sun.lwawt.macosx.CPlatformWindow");
@@ -726,10 +730,6 @@
         setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop);
     }
 
-    public PlatformWindow getTopmostPlatformWindowUnderMouse(){
-        return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse();
-    }
-
     @Override
     public void setOpacity(float opacity) {
         CWrapper.NSWindow.setAlphaValue(getNSWindowPtr(), opacity);
@@ -1019,29 +1019,70 @@
         return true;
     }
 
+    private boolean isOneOfOwnersOrSelf(CPlatformWindow window) {
+        while (window != null) {
+            if (this == window) {
+                return true;
+            }
+            window = window.owner;
+        }
+        return false;
+    }
+
+    private CPlatformWindow getRootOwner() {
+        CPlatformWindow rootOwner = this;
+        while (rootOwner.owner != null) {
+            rootOwner = rootOwner.owner;
+        }
+        return rootOwner;
+    }
+
     private void orderAboveSiblings() {
-        if (owner == null) {
-            return;
+        // Recursively pop up the windows from the very bottom, (i.e. root owner) so that
+        // the windows are ordered above their nearest owner; ancestors of the window,
+        // which is going to become 'main window', are placed above their siblings.
+        CPlatformWindow rootOwner = getRootOwner();
+        if (rootOwner.isVisible()) {
+            CWrapper.NSWindow.orderFront(rootOwner.getNSWindowPtr());
         }
+        final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
+        orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target));
+    }
 
-        // NOTE: the logic will fail if we have a hierarchy like:
-        //       visible root owner
-        //          invisible owner
-        //              visible dialog
-        // However, this is an unlikely scenario for real life apps
-        if (owner.isVisible()) {
-            // Recursively pop up the windows from the very bottom so that only
-            // the very top-most one becomes the main window
-            owner.orderAboveSiblings();
+    private void orderAboveSiblingsImpl(Window[] windows) {
+        ArrayList<Window> childWindows = new ArrayList<Window>();
 
-            // Order the window to front of the stack of child windows
-            final long nsWindowSelfPtr = getNSWindowPtr();
-            final long nsWindowOwnerPtr = owner.getNSWindowPtr();
-            CWrapper.NSWindow.orderFront(nsWindowOwnerPtr);
-            CWrapper.NSWindow.orderWindow(nsWindowSelfPtr, CWrapper.NSWindow.NSWindowAbove, nsWindowOwnerPtr);
+        final ComponentAccessor componentAccessor = AWTAccessor.getComponentAccessor();
+        final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
+
+        // Go through the list of windows and perform ordering.
+        for (Window w : windows) {
+            final Object p = componentAccessor.getPeer(w);
+            if (p instanceof LWWindowPeer) {
+                CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow();
+                if (pw != null && pw.isVisible()) {
+                    // If the window is one of ancestors of 'main window' or is going to become main by itself,
+                    // the window should be ordered above its siblings; otherwise the window is just ordered
+                    // above its nearest parent.
+                    if (pw.isOneOfOwnersOrSelf(this)) {
+                        CWrapper.NSWindow.orderFront(pw.getNSWindowPtr());
+                    } else {
+                        CWrapper.NSWindow.orderWindow(pw.getNSWindowPtr(), CWrapper.NSWindow.NSWindowAbove,
+                                pw.owner.getNSWindowPtr());
+                    }
+                    pw.applyWindowLevel(w);
+                }
+            }
+            // Retrieve the child windows for each window from the list and store them for future use.
+            // Note: we collect data about child windows even for invisible owners, since they may have
+            // visible children.
+            childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w)));
         }
-
-        applyWindowLevel(target);
+        // If some windows, which have just been ordered, have any child windows, let's start new iteration
+        // and order these child windows.
+        if (!childWindows.isEmpty()) {
+            orderAboveSiblingsImpl(childWindows.toArray(new Window[0]));
+        }
     }
 
     protected void applyWindowLevel(Window target) {
--- a/src/macosx/classes/sun/lwawt/macosx/CRobot.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CRobot.java	Fri Dec 16 17:04:37 2016 -0800
@@ -78,7 +78,7 @@
     @Override
     public void mousePress(int buttons) {
         mouseButtonsState |= buttons;
-
+        checkMousePos();
         mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY,
                    buttons, true, false);
     }
@@ -92,11 +92,40 @@
     @Override
     public void mouseRelease(int buttons) {
         mouseButtonsState &= ~buttons;
-
+        checkMousePos();
         mouseEvent(fDevice.getCGDisplayID(), mouseLastX, mouseLastY,
                    buttons, false, false);
     }
 
+    /**
+     * Set unknown mouse location, if needed.
+     */
+    private void checkMousePos() {
+        if (mouseLastX == MOUSE_LOCATION_UNKNOWN ||
+                mouseLastY == MOUSE_LOCATION_UNKNOWN) {
+
+            Rectangle deviceBounds = fDevice.getDefaultConfiguration().getBounds();
+            Point mousePos = CCursorManager.getInstance().getCursorPosition();
+
+            if (mousePos.x < deviceBounds.x) {
+                mousePos.x = deviceBounds.x;
+            }
+            else if (mousePos.x > deviceBounds.x + deviceBounds.width) {
+                mousePos.x = deviceBounds.x + deviceBounds.width;
+            }
+
+            if (mousePos.y < deviceBounds.y) {
+                mousePos.y = deviceBounds.y;
+            }
+            else if (mousePos.y > deviceBounds.y + deviceBounds.height) {
+                mousePos.y = deviceBounds.y + deviceBounds.height;
+            }
+
+            mouseLastX = mousePos.x;
+            mouseLastY = mousePos.y;
+        }
+    }
+
     @Override
     public native void mouseWheel(int wheelAmt);
 
--- a/src/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java	Fri Dec 16 17:04:37 2016 -0800
@@ -144,11 +144,6 @@
     }
 
     @Override
-    public PlatformWindow getTopmostPlatformWindowUnderMouse() {
-        return null;
-    }
-
-    @Override
     public void updateFocusableWindowState() {
     }
 
--- a/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Fri Dec 16 17:04:37 2016 -0800
@@ -917,4 +917,9 @@
                 !path.endsWith("/") &&
                 !path.endsWith(".");
     }
+
+    @Override
+    protected PlatformWindow getPlatformWindowUnderMouse() {
+        return CPlatformWindow.nativeGetTopmostPlatformWindowUnderMouse();
+    }
 }
--- a/src/macosx/native/sun/awt/AWTWindow.m	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/native/sun/awt/AWTWindow.m	Fri Dec 16 17:04:37 2016 -0800
@@ -1255,15 +1255,16 @@
 JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeGetTopmostPlatformWindowUnderMouse
 (JNIEnv *env, jclass clazz)
 {
-    jobject topmostWindowUnderMouse = nil;
+    __block jobject topmostWindowUnderMouse = nil;
 
     JNF_COCOA_ENTER(env);
-    AWT_ASSERT_APPKIT_THREAD;
 
-    AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];
-    if (awtWindow != nil) {
-        topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject];
-    }
+    [ThreadUtilities performOnMainThreadWaiting:YES block:^{
+        AWTWindow *awtWindow = [AWTWindow getTopmostWindowUnderMouse];
+        if (awtWindow != nil) {
+            topmostWindowUnderMouse = [awtWindow.javaPlatformWindow jObject];
+        }
+    }];
 
     JNF_COCOA_EXIT(env);
 
--- a/src/macosx/native/sun/awt/CCursorManager.m	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/native/sun/awt/CCursorManager.m	Fri Dec 16 17:04:37 2016 -0800
@@ -118,13 +118,11 @@
 
 JNF_COCOA_ENTER(env);
 
-    __block NSPoint pt = NSZeroPoint;
-    
-    [ThreadUtilities performOnMainThreadWaiting:YES block:^(){
-            pt = ConvertNSScreenPoint(env, [NSEvent mouseLocation]);
-    }];
-    
-    jpt = NSToJavaPoint(env, pt);
+    CGEventRef event = CGEventCreate(NULL);
+    CGPoint globalPos = CGEventGetLocation(event);
+    CFRelease(event);
+
+    jpt = NSToJavaPoint(env, globalPos);
 
 JNF_COCOA_EXIT(env);
 
--- a/src/macosx/native/sun/awt/CRobot.m	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/macosx/native/sun/awt/CRobot.m	Fri Dec 16 17:04:37 2016 -0800
@@ -146,47 +146,10 @@
 
     // This is the native method called when Robot mouse events occur.
     // The CRobot tracks the mouse position, and which button was
-    // pressed. If the mouse position is unknown it is obtained from
-    // CGEvents. The peer also tracks the mouse button desired state,
+    // pressed. The peer also tracks the mouse button desired state,
     // the appropriate key modifier state, and whether the mouse action
     // is simply a mouse move with no mouse button state changes.
 
-    CGError err = kCGErrorSuccess;
-
-    CGRect globalDeviceBounds = CGDisplayBounds(displayID);
-
-    // Set unknown mouse location, if needed.
-    if ((mouseLastX == sun_lwawt_macosx_CRobot_MOUSE_LOCATION_UNKNOWN) ||
-        (mouseLastY == sun_lwawt_macosx_CRobot_MOUSE_LOCATION_UNKNOWN))
-    {
-        CGEventRef event = CGEventCreate(NULL);
-        if (event == NULL) {
-            return;
-        }
-
-        CGPoint globalPos = CGEventGetLocation(event);
-        CFRelease(event);
-
-        // Normalize the coords within this display device, as
-        // per Robot rules.
-        if (globalPos.x < CGRectGetMinX(globalDeviceBounds)) {
-            globalPos.x = CGRectGetMinX(globalDeviceBounds);
-        }
-        else if (globalPos.x > CGRectGetMaxX(globalDeviceBounds)) {
-            globalPos.x = CGRectGetMaxX(globalDeviceBounds);
-        }
-
-        if (globalPos.y < CGRectGetMinY(globalDeviceBounds)) {
-            globalPos.y = CGRectGetMinY(globalDeviceBounds);
-        }
-        else if (globalPos.y > CGRectGetMaxY(globalDeviceBounds)) {
-            globalPos.y = CGRectGetMaxY(globalDeviceBounds);
-        }
-
-        mouseLastX = (jint)globalPos.x;
-        mouseLastY = (jint)globalPos.y;
-    }
-
     // volatile, otherwise it warns that it might be clobbered by 'longjmp'
     volatile CGPoint point;
 
--- a/src/share/classes/java/awt/Window.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/share/classes/java/awt/Window.java	Fri Dec 16 17:04:37 2016 -0800
@@ -4100,6 +4100,10 @@
             public void setTrayIconWindow(Window w, boolean isTrayIconWindow) {
                 w.isTrayIconWindow = isTrayIconWindow;
             }
+
+            public Window[] getOwnedWindows(Window w) {
+                return w.getOwnedWindows_NoClientCode();
+            }
         }); // WindowAccessor
     } // static
 
--- a/src/share/classes/sun/awt/AWTAccessor.java	Mon Dec 12 12:53:36 2016 -0800
+++ b/src/share/classes/sun/awt/AWTAccessor.java	Fri Dec 16 17:04:37 2016 -0800
@@ -334,6 +334,12 @@
          * Marks the specified window as an utility window for TrayIcon.
          */
         void setTrayIconWindow(Window w, boolean isTrayIconWindow);
+
+        /**
+         * Return an array containing all the windows this
+         * window currently owns.
+         */
+        Window[] getOwnedWindows(Window w);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/Dialog/DialogAboveFrame/DialogAboveFrameTest.java	Fri Dec 16 17:04:37 2016 -0800
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ * @test
+ * @bug 8169589
+ * @summary Activating a dialog puts to back another dialog owned by the same frame
+ * @author Dmitry Markov
+ * @library ../../regtesthelpers
+ * @build Util
+ * @run main DialogAboveFrameTest
+ */
+
+import java.awt.Color;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Point;
+import java.awt.Robot;
+
+import test.java.awt.regtesthelpers.Util;
+
+public class DialogAboveFrameTest {
+    public static void main(String[] args) {
+        Robot robot = Util.createRobot();
+
+        Frame frame = new Frame("Frame");
+        frame.setBackground(Color.BLUE);
+        frame.setBounds(200, 50, 300, 300);
+        frame.setVisible(true);
+
+        Dialog dialog1 = new Dialog(frame, "Dialog 1", false);
+        dialog1.setBackground(Color.RED);
+        dialog1.setBounds(100, 100, 200, 200);
+        dialog1.setVisible(true);
+
+        Dialog dialog2 = new Dialog(frame, "Dialog 2", false);
+        dialog2.setBackground(Color.GREEN);
+        dialog2.setBounds(400, 100, 200, 200);
+        dialog2.setVisible(true);
+
+        Util.waitForIdle(robot);
+
+        Util.clickOnComp(dialog2, robot);
+        Util.waitForIdle(robot);
+
+        Point point = dialog1.getLocationOnScreen();
+        int x = point.x + (int)(dialog1.getWidth() * 0.9);
+        int y = point.y + (int)(dialog1.getHeight() * 0.9);
+
+        try {
+            if (!robot.getPixelColor(x, y).equals(dialog1.getBackground())) {
+                throw new RuntimeException("Test FAILED: Dialog is behind the frame");
+            }
+        } finally {
+            frame.dispose();
+            dialog1.dispose();
+            dialog2.dispose();
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/MouseInfo/GetPointerInfoTest.java	Fri Dec 16 17:04:37 2016 -0800
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+  @test
+  @summary unit test for getPointerInfo() from MouseInfo class
+  @author dav@sparc.spb.su: area=
+  @bug 4009555
+  @run main GetPointerInfoTest
+*/
+
+import java.awt.*;
+
+/**
+ * Simply check the result on non-null and results are correct.
+ */
+public class GetPointerInfoTest {
+    private static final String successStage = "Test stage completed.Passed.";
+
+    public static void main(String[] args) throws Exception {
+        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        GraphicsDevice[] gds = ge.getScreenDevices();
+        int gdslen = gds.length;
+        System.out.println("There are " + gdslen + " Graphics Devices");
+        if (gdslen == 0) {
+            System.out.println("Nothing to be done.");
+            return;
+        }
+        Robot robot = new Robot(gds[0]);
+        robot.setAutoDelay(0);
+        robot.setAutoWaitForIdle(true);
+        robot.delay(10);
+        robot.waitForIdle();
+        Point p = new Point(101, 99);
+        robot.mouseMove(p.x, p.y);
+
+        PointerInfo pi = MouseInfo.getPointerInfo();
+        if (pi == null) {
+            throw new RuntimeException("Test failed. getPointerInfo() returned null value.");
+        } else {
+            System.out.println(successStage);
+        }
+        Point piLocation = pi.getLocation();
+
+        if (piLocation.x != p.x || piLocation.y != p.y) {
+            throw new RuntimeException("Test failed.getPointerInfo() returned incorrect result.");
+        } else {
+            System.out.println(successStage);
+        }
+
+        System.out.println("Test PASSED.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/MouseInfo/MultiscreenPointerInfo.java	Fri Dec 16 17:04:37 2016 -0800
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+/*
+  @test
+  @summary unit test for getPointerInfo() from MouseInfo class
+  @author prs@sparc.spb.su: area=
+  @bug 4009555
+  @run main MultiscreenPointerInfo
+*/
+
+import java.awt.*;
+
+/**
+ * Simply check the result on non-null and results are correct.
+ */
+public class MultiscreenPointerInfo
+{
+    private static final String successStage = "Test stage completed.Passed.";
+
+    public static void main(String[] args) throws Exception {
+        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        GraphicsDevice[] gds = ge.getScreenDevices();
+        int gdslen = gds.length;
+        System.out.println("There are " + gdslen + " Graphics Devices");
+        if (gdslen < 2) {
+            System.out.println("Nothing to be done. PASSED automatically.");
+            return;
+        }
+        Rectangle rx = gds[1].getDefaultConfiguration().getBounds();
+        Robot robot;
+
+        if (rx.x == 0 && rx.y == 0) {
+            // Assuming independent graphics devices
+            robot = new Robot(gds[1]);
+        } else {
+            // Means we have a virtual device
+            robot = new Robot(gds[0]);
+        }
+        robot.setAutoDelay(0);
+        robot.setAutoWaitForIdle(true);
+        robot.delay(10);
+        robot.waitForIdle();
+        Point p = new Point(rx.x + 101, rx.y + 99);
+        robot.mouseMove(p.x, p.y);
+        PointerInfo pi = MouseInfo.getPointerInfo();
+        if (pi == null) {
+            throw new RuntimeException("Test failed. getPointerInfo() returned null value.");
+        } else {
+            System.out.println(successStage);
+        }
+
+        Point piLocation = pi.getLocation();
+
+        if (piLocation.x != p.x || piLocation.y != p.y) {
+            throw new RuntimeException("Test failed.getPointerInfo() returned incorrect location.");
+        } else {
+            System.out.println(successStage);
+        }
+
+        GraphicsDevice dev = pi.getDevice();
+
+        if (dev != gds[1]) {
+            throw new RuntimeException("Test failed.getPointerInfo() returned incorrect device.");
+        } else {
+            System.out.println(successStage);
+        }
+        System.out.println("Test PASSED.");
+    }
+}