< prev index next >

src/java.desktop/share/classes/java/awt/Robot.java

Print this page
rev 60071 : 8211999: Window positioning bugs due to overlapping GraphicsDevice bounds (Windows/HiDPI)
Reviewed-by: XXX


  26 package java.awt;
  27 
  28 import java.awt.event.InputEvent;
  29 import java.awt.event.KeyEvent;
  30 import java.awt.geom.AffineTransform;
  31 import java.awt.image.BaseMultiResolutionImage;
  32 import java.awt.image.BufferedImage;
  33 import java.awt.image.DataBufferInt;
  34 import java.awt.image.DirectColorModel;
  35 import java.awt.image.MultiResolutionImage;
  36 import java.awt.image.Raster;
  37 import java.awt.image.WritableRaster;
  38 import java.awt.peer.RobotPeer;
  39 
  40 import sun.awt.AWTPermissions;
  41 import sun.awt.ComponentFactory;
  42 import sun.awt.SunToolkit;
  43 import sun.awt.image.SunWritableRaster;
  44 import sun.java2d.SunGraphicsEnvironment;
  45 



  46 /**
  47  * This class is used to generate native system input events
  48  * for the purposes of test automation, self-running demos, and
  49  * other applications where control of the mouse and keyboard
  50  * is needed. The primary purpose of Robot is to facilitate
  51  * automated testing of Java platform implementations.
  52  * <p>
  53  * Using the class to generate input events differs from posting
  54  * events to the AWT event queue or AWT components in that the
  55  * events are generated in the platform's native input
  56  * queue. For example, {@code Robot.mouseMove} will actually move
  57  * the mouse cursor instead of just generating mouse move events.
  58  * <p>
  59  * Note that some platforms require special privileges or extensions
  60  * to access low-level input control. If the current platform configuration
  61  * does not allow input control, an {@code AWTException} will be thrown
  62  * when trying to construct Robot objects. For example, X-Window systems
  63  * will throw the exception if the XTEST 2.2 standard extension is not supported
  64  * (or not enabled) by the X server.
  65  * <p>


 368     }
 369 
 370     private static void checkKeycodeArgument(int keycode) {
 371         // rather than build a big table or switch statement here, we'll
 372         // just check that the key isn't VK_UNDEFINED and assume that the
 373         // peer implementations will throw an exception for other bogus
 374         // values e.g. -1, 999999
 375         if (keycode == KeyEvent.VK_UNDEFINED) {
 376             throw new IllegalArgumentException("Invalid key code");
 377         }
 378     }
 379 
 380     /**
 381      * Returns the color of a pixel at the given screen coordinates.
 382      * @param   x       X position of pixel
 383      * @param   y       Y position of pixel
 384      * @return  Color of the pixel
 385      */
 386     public synchronized Color getPixelColor(int x, int y) {
 387         checkScreenCaptureAllowed();
 388         AffineTransform tx = GraphicsEnvironment.
 389                 getLocalGraphicsEnvironment().getDefaultScreenDevice().
 390                 getDefaultConfiguration().getDefaultTransform();
 391         x = (int) (x * tx.getScaleX());
 392         y = (int) (y * tx.getScaleY());
 393         Color color = new Color(peer.getRGBPixel(x, y));
 394         return color;
 395     }
 396 
 397     /**
 398      * Creates an image containing pixels read from the screen.  This image does
 399      * not include the mouse cursor.
 400      * @param   screenRect      Rect to capture in screen coordinates
 401      * @return  The captured image
 402      * @throws  IllegalArgumentException if {@code screenRect} width and height are not greater than zero
 403      * @throws  SecurityException if {@code readDisplayPixels} permission is not granted
 404      * @see     SecurityManager#checkPermission
 405      * @see     AWTPermission
 406      */
 407     public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
 408         return createCompatibleImage(screenRect, false)[0];
 409     }
 410 
 411     /**
 412      * Creates an image containing pixels read from the screen.
 413      * This image does not include the mouse cursor.
 414      * This method can be used in case there is a scaling transform


 506 
 507         if (uiScaleX == 1 && uiScaleY == 1) {
 508 
 509             pixels = peer.getRGBPixels(screenRect);
 510             buffer = new DataBufferInt(pixels, pixels.length);
 511 
 512             bandmasks[0] = screenCapCM.getRedMask();
 513             bandmasks[1] = screenCapCM.getGreenMask();
 514             bandmasks[2] = screenCapCM.getBlueMask();
 515 
 516             raster = Raster.createPackedRaster(buffer, screenRect.width,
 517                     screenRect.height, screenRect.width, bandmasks, null);
 518             SunWritableRaster.makeTrackable(buffer);
 519 
 520             highResolutionImage = new BufferedImage(screenCapCM, raster,
 521                     false, null);
 522             imageArray = new BufferedImage[1];
 523             imageArray[0] = highResolutionImage;
 524 
 525         } else {
 526 
 527             int sX = (int) Math.floor(screenRect.x * uiScaleX);
 528             int sY = (int) Math.floor(screenRect.y * uiScaleY);
 529             int sWidth = (int) Math.ceil(screenRect.width * uiScaleX);
 530             int sHeight = (int) Math.ceil(screenRect.height * uiScaleY);
 531             int[] temppixels;
 532             Rectangle scaledRect = new Rectangle(sX, sY, sWidth, sHeight);
 533             temppixels = peer.getRGBPixels(scaledRect);
 534 
 535             // HighResolutionImage
 536             pixels = temppixels;
 537             buffer = new DataBufferInt(pixels, pixels.length);
 538             raster = Raster.createPackedRaster(buffer, scaledRect.width,
 539                     scaledRect.height, scaledRect.width, bandmasks, null);
 540             SunWritableRaster.makeTrackable(buffer);
 541 
 542             highResolutionImage = new BufferedImage(screenCapCM, raster,
 543                     false, null);
 544 
 545 
 546             // LowResolutionImage
 547             lowResolutionImage = new BufferedImage(screenRect.width,
 548                     screenRect.height, highResolutionImage.getType());
 549             Graphics2D g = lowResolutionImage.createGraphics();
 550             g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
 551                     RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 552             g.setRenderingHint(RenderingHints.KEY_RENDERING,
 553                     RenderingHints.VALUE_RENDER_QUALITY);
 554             g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 555                     RenderingHints.VALUE_ANTIALIAS_ON);
 556             g.drawImage(highResolutionImage, 0, 0,




  26 package java.awt;
  27 
  28 import java.awt.event.InputEvent;
  29 import java.awt.event.KeyEvent;
  30 import java.awt.geom.AffineTransform;
  31 import java.awt.image.BaseMultiResolutionImage;
  32 import java.awt.image.BufferedImage;
  33 import java.awt.image.DataBufferInt;
  34 import java.awt.image.DirectColorModel;
  35 import java.awt.image.MultiResolutionImage;
  36 import java.awt.image.Raster;
  37 import java.awt.image.WritableRaster;
  38 import java.awt.peer.RobotPeer;
  39 
  40 import sun.awt.AWTPermissions;
  41 import sun.awt.ComponentFactory;
  42 import sun.awt.SunToolkit;
  43 import sun.awt.image.SunWritableRaster;
  44 import sun.java2d.SunGraphicsEnvironment;
  45 
  46 import static sun.java2d.SunGraphicsEnvironment.toDeviceSpace;
  47 import static sun.java2d.SunGraphicsEnvironment.toDeviceSpaceAbs;
  48 
  49 /**
  50  * This class is used to generate native system input events
  51  * for the purposes of test automation, self-running demos, and
  52  * other applications where control of the mouse and keyboard
  53  * is needed. The primary purpose of Robot is to facilitate
  54  * automated testing of Java platform implementations.
  55  * <p>
  56  * Using the class to generate input events differs from posting
  57  * events to the AWT event queue or AWT components in that the
  58  * events are generated in the platform's native input
  59  * queue. For example, {@code Robot.mouseMove} will actually move
  60  * the mouse cursor instead of just generating mouse move events.
  61  * <p>
  62  * Note that some platforms require special privileges or extensions
  63  * to access low-level input control. If the current platform configuration
  64  * does not allow input control, an {@code AWTException} will be thrown
  65  * when trying to construct Robot objects. For example, X-Window systems
  66  * will throw the exception if the XTEST 2.2 standard extension is not supported
  67  * (or not enabled) by the X server.
  68  * <p>


 371     }
 372 
 373     private static void checkKeycodeArgument(int keycode) {
 374         // rather than build a big table or switch statement here, we'll
 375         // just check that the key isn't VK_UNDEFINED and assume that the
 376         // peer implementations will throw an exception for other bogus
 377         // values e.g. -1, 999999
 378         if (keycode == KeyEvent.VK_UNDEFINED) {
 379             throw new IllegalArgumentException("Invalid key code");
 380         }
 381     }
 382 
 383     /**
 384      * Returns the color of a pixel at the given screen coordinates.
 385      * @param   x       X position of pixel
 386      * @param   y       Y position of pixel
 387      * @return  Color of the pixel
 388      */
 389     public synchronized Color getPixelColor(int x, int y) {
 390         checkScreenCaptureAllowed();
 391         Point point = peer.useAbsoluteCoordinates() ? toDeviceSpaceAbs(x, y)
 392                                                     : toDeviceSpace(x, y);
 393         return new Color(peer.getRGBPixel(point.x, point.y));




 394     }
 395 
 396     /**
 397      * Creates an image containing pixels read from the screen.  This image does
 398      * not include the mouse cursor.
 399      * @param   screenRect      Rect to capture in screen coordinates
 400      * @return  The captured image
 401      * @throws  IllegalArgumentException if {@code screenRect} width and height are not greater than zero
 402      * @throws  SecurityException if {@code readDisplayPixels} permission is not granted
 403      * @see     SecurityManager#checkPermission
 404      * @see     AWTPermission
 405      */
 406     public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
 407         return createCompatibleImage(screenRect, false)[0];
 408     }
 409 
 410     /**
 411      * Creates an image containing pixels read from the screen.
 412      * This image does not include the mouse cursor.
 413      * This method can be used in case there is a scaling transform


 505 
 506         if (uiScaleX == 1 && uiScaleY == 1) {
 507 
 508             pixels = peer.getRGBPixels(screenRect);
 509             buffer = new DataBufferInt(pixels, pixels.length);
 510 
 511             bandmasks[0] = screenCapCM.getRedMask();
 512             bandmasks[1] = screenCapCM.getGreenMask();
 513             bandmasks[2] = screenCapCM.getBlueMask();
 514 
 515             raster = Raster.createPackedRaster(buffer, screenRect.width,
 516                     screenRect.height, screenRect.width, bandmasks, null);
 517             SunWritableRaster.makeTrackable(buffer);
 518 
 519             highResolutionImage = new BufferedImage(screenCapCM, raster,
 520                     false, null);
 521             imageArray = new BufferedImage[1];
 522             imageArray[0] = highResolutionImage;
 523 
 524         } else {
 525             Rectangle scaledRect;
 526             if (peer.useAbsoluteCoordinates()) {
 527                 scaledRect = toDeviceSpaceAbs(gc, screenRect.x,
 528                         screenRect.y, screenRect.width, screenRect.height);
 529             } else {
 530                 scaledRect = toDeviceSpace(gc, screenRect.x,
 531                         screenRect.y, screenRect.width, screenRect.height);
 532             }

 533             // HighResolutionImage
 534             pixels = peer.getRGBPixels(scaledRect);
 535             buffer = new DataBufferInt(pixels, pixels.length);
 536             raster = Raster.createPackedRaster(buffer, scaledRect.width,
 537                     scaledRect.height, scaledRect.width, bandmasks, null);
 538             SunWritableRaster.makeTrackable(buffer);
 539 
 540             highResolutionImage = new BufferedImage(screenCapCM, raster,
 541                     false, null);
 542 
 543 
 544             // LowResolutionImage
 545             lowResolutionImage = new BufferedImage(screenRect.width,
 546                     screenRect.height, highResolutionImage.getType());
 547             Graphics2D g = lowResolutionImage.createGraphics();
 548             g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
 549                     RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 550             g.setRenderingHint(RenderingHints.KEY_RENDERING,
 551                     RenderingHints.VALUE_RENDER_QUALITY);
 552             g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 553                     RenderingHints.VALUE_ANTIALIAS_ON);
 554             g.drawImage(highResolutionImage, 0, 0,


< prev index next >