8013116: Robot moves mouse to point which differs from set in mouseMove on Unity shell
authorbagiras
Wed, 29 Jan 2014 18:32:10 +0400
changeset 23274 3b6993da89df
parent 23273 986c81d8805b
child 23275 dd5d2076ce38
child 23276 add6f5c93bc6
8013116: Robot moves mouse to point which differs from set in mouseMove on Unity shell Reviewed-by: serb, azvegint
jdk/src/macosx/native/sun/awt/CRobot.m
jdk/src/share/classes/java/awt/Robot.java
jdk/test/java/awt/Multiscreen/MultiScreenLocationTest/MultiScreenLocationTest.java
jdk/test/java/awt/regtesthelpers/Util.java
--- a/jdk/src/macosx/native/sun/awt/CRobot.m	Wed Jan 29 16:50:22 2014 +0400
+++ b/jdk/src/macosx/native/sun/awt/CRobot.m	Wed Jan 29 18:32:10 2014 +0400
@@ -187,9 +187,8 @@
     // volatile, otherwise it warns that it might be clobbered by 'longjmp'
     volatile CGPoint point;
 
-    // Translate the device relative point into a valid global CGPoint.
-    point.x = mouseLastX + globalDeviceBounds.origin.x;
-    point.y = mouseLastY + globalDeviceBounds.origin.y;
+    point.x = mouseLastX;
+    point.y = mouseLastY;
 
     __block CGMouseButton button = kCGMouseButtonLeft;
     __block CGEventType type = kCGEventMouseMoved;
--- a/jdk/src/share/classes/java/awt/Robot.java	Wed Jan 29 16:50:22 2014 +0400
+++ b/jdk/src/share/classes/java/awt/Robot.java	Wed Jan 29 18:32:10 2014 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -72,9 +72,6 @@
     private int autoDelay = 0;
     private static int LEGAL_BUTTON_MASK = 0;
 
-    // location of robot's GC, used in mouseMove(), getPixelColor() and captureScreenImage()
-    private Point gdLoc;
-
     private DirectColorModel screenCapCM = null;
 
     /**
@@ -132,7 +129,6 @@
 
     private void init(GraphicsDevice screen) throws AWTException {
         checkRobotAllowed();
-        gdLoc = screen.getDefaultConfiguration().getBounds().getLocation();
         Toolkit toolkit = Toolkit.getDefaultToolkit();
         if (toolkit instanceof ComponentFactory) {
             peer = ((ComponentFactory)toolkit).createRobot(this, screen);
@@ -200,7 +196,7 @@
      * @param y         Y position
      */
     public synchronized void mouseMove(int x, int y) {
-        peer.mouseMove(gdLoc.x + x, gdLoc.y + y);
+        peer.mouseMove(x, y);
         afterEvent();
     }
 
@@ -395,7 +391,7 @@
      * @return  Color of the pixel
      */
     public synchronized Color getPixelColor(int x, int y) {
-        Color color = new Color(peer.getRGBPixel(gdLoc.x + x, gdLoc.y + y));
+        Color color = new Color(peer.getRGBPixel(x, y));
         return color;
     }
 
@@ -412,10 +408,7 @@
     public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
         checkScreenCaptureAllowed();
 
-        // according to the spec, screenRect is relative to robot's GD
-        Rectangle translatedRect = new Rectangle(screenRect);
-        translatedRect.translate(gdLoc.x, gdLoc.y);
-        checkValidRect(translatedRect);
+        checkValidRect(screenRect);
 
         BufferedImage image;
         DataBufferInt buffer;
@@ -441,14 +434,14 @@
         int pixels[];
         int[] bandmasks = new int[3];
 
-        pixels = peer.getRGBPixels(translatedRect);
+        pixels = peer.getRGBPixels(screenRect);
         buffer = new DataBufferInt(pixels, pixels.length);
 
         bandmasks[0] = screenCapCM.getRedMask();
         bandmasks[1] = screenCapCM.getGreenMask();
         bandmasks[2] = screenCapCM.getBlueMask();
 
-        raster = Raster.createPackedRaster(buffer, translatedRect.width, translatedRect.height, translatedRect.width, bandmasks, null);
+        raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null);
         SunWritableRaster.makeTrackable(buffer);
 
         image = new BufferedImage(screenCapCM, raster, false, null);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Multiscreen/MultiScreenLocationTest/MultiScreenLocationTest.java	Wed Jan 29 18:32:10 2014 +0400
@@ -0,0 +1,110 @@
+/*
+ * 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
+  @bug 8013116
+  @summary Robot moves mouse to point which differs from set in mouseMove on
+ Unity shell
+  @author Oleg Pekhovskiy
+  @library ../../regtesthelpers
+  @build Util
+  @run main MultiScreenLocationTest
+ */
+
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.Frame;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsDevice;
+import java.awt.GraphicsEnvironment;
+import java.awt.MouseInfo;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.image.BufferedImage;
+import test.java.awt.regtesthelpers.Util;
+
+public class MultiScreenLocationTest {
+    private static final Point mouseOffset = new Point(150, 150);
+    private static final Point frameOffset = new Point(100, 100);
+    private static final Color color = Color.YELLOW;
+
+    private static String getErrorText(final String name, int screen)
+    {
+        return name + " test failed on Screen #" + screen + "!";
+    }
+
+    public static void main(String[] args) throws AWTException
+    {
+        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+        GraphicsDevice[] gds = ge.getScreenDevices();
+        if (gds.length < 2) {
+            System.out.println("It's a multiscreen test... skipping!");
+            return;
+        }
+
+        for (int i = 0; i < gds.length; ++i) {
+            GraphicsDevice gd = gds[i];
+            GraphicsConfiguration gc = gd.getDefaultConfiguration();
+            Rectangle screen = gc.getBounds();
+            Robot robot = new Robot(gd);
+
+            // check Robot.mouseMove()
+            robot.mouseMove(screen.x + mouseOffset.x, screen.y + mouseOffset.y);
+            Point mouse = MouseInfo.getPointerInfo().getLocation();
+            Point point = screen.getLocation();
+            point.translate(mouseOffset.x, mouseOffset.y);
+            if (!point.equals(mouse)) {
+                throw new RuntimeException(getErrorText("Robot.mouseMove", i));
+            }
+
+            // check Robot.getPixelColor()
+            Frame frame = new Frame(gc);
+            frame.setUndecorated(true);
+            frame.setSize(100, 100);
+            frame.setLocation(screen.x + frameOffset.x, screen.y + frameOffset.y);
+            frame.setBackground(color);
+            frame.setVisible(true);
+            robot.waitForIdle();
+            Rectangle bounds = frame.getBounds();
+            if (!Util.testBoundsColor(bounds, color, 5, 1000, robot)) {
+                throw new RuntimeException(getErrorText("Robot.getPixelColor", i));
+            }
+
+            // check Robot.createScreenCapture()
+            BufferedImage image = robot.createScreenCapture(bounds);
+            int rgb = color.getRGB();
+            if (image.getRGB(0, 0) != rgb
+                || image.getRGB(image.getWidth() - 1, 0) != rgb
+                || image.getRGB(image.getWidth() - 1, image.getHeight() - 1) != rgb
+                || image.getRGB(0, image.getHeight() - 1) != rgb) {
+                    throw new RuntimeException(
+                            getErrorText("Robot.createScreenCapture", i));
+            }
+            frame.dispose();
+        }
+
+        System.out.println("Test PASSED!");
+    }
+}
--- a/jdk/test/java/awt/regtesthelpers/Util.java	Wed Jan 29 16:50:22 2014 +0400
+++ b/jdk/test/java/awt/regtesthelpers/Util.java	Wed Jan 29 18:32:10 2014 +0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -51,6 +51,7 @@
 import java.awt.IllegalComponentStateException;
 import java.awt.AWTException;
 import java.awt.AWTEvent;
+import java.awt.Color;
 
 import java.awt.event.InputEvent;
 import java.awt.event.WindowAdapter;
@@ -184,6 +185,57 @@
         }
     }
 
+    /**
+     * Tests whether screen pixel has the expected color performing several
+     * attempts. This method is useful for asynchronous window manager where
+     * it's impossible to determine when drawing actually takes place.
+     *
+     * @param x X position of pixel
+     * @param y Y position of pixel
+     * @param color expected color
+     * @param attempts number of attempts to undertake
+     * @param delay delay before each attempt
+     * @param robot a robot to use for retrieving pixel color
+     * @return true if pixel color matches the color expected, otherwise false
+     */
+    public static boolean testPixelColor(int x, int y, final Color color, int attempts, int delay, final Robot robot) {
+        while (attempts-- > 0) {
+            robot.delay(delay);
+            Color screen = robot.getPixelColor(x, y);
+            if (screen.equals(color)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Tests whether the area within boundaries has the expected color
+     * performing several attempts. This method is useful for asynchronous
+     * window manager where it's impossible to determine when drawing actually
+     * takes place.
+     *
+     * @param bounds position of area
+     * @param color expected color
+     * @param attempts number of attempts to undertake
+     * @param delay delay before each attempt
+     * @param robot a robot to use for retrieving pixel color
+     * @return true if area color matches the color expected, otherwise false
+     */
+    public static boolean testBoundsColor(final Rectangle bounds, final Color color, int attempts, int delay, final Robot robot) {
+        int right = bounds.x + bounds.width - 1;
+        int bottom = bounds.y + bounds.height - 1;
+        while (attempts-- > 0) {
+            if (testPixelColor(bounds.x, bounds.y, color, 1, delay, robot)
+                && testPixelColor(right, bounds.y, color, 1, 0, robot)
+                && testPixelColor(right, bottom, color, 1, 0, robot)
+                && testPixelColor(bounds.x, bottom, color, 1, 0, robot)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public static void waitForIdle(final Robot robot) {
         // we do not use robot for now, use SunToolkit.realSync() instead
         ((sun.awt.SunToolkit)Toolkit.getDefaultToolkit()).realSync();