8013116: Robot moves mouse to point which differs from set in mouseMove on Unity shell
Reviewed-by: serb, azvegint
--- 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();