< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.awt;
  27 
  28 import java.awt.event.InputEvent;
  29 import java.awt.event.KeyEvent;



  30 import java.awt.image.BufferedImage;
  31 import java.awt.image.DataBufferInt;
  32 import java.awt.image.DirectColorModel;
  33 import java.awt.image.Raster;
  34 import java.awt.image.WritableRaster;
  35 import java.awt.peer.RobotPeer;
  36 
  37 import sun.awt.AWTPermissions;
  38 import sun.awt.ComponentFactory;
  39 import sun.awt.SunToolkit;
  40 import sun.awt.image.SunWritableRaster;
  41 
  42 /**
  43  * This class is used to generate native system input events
  44  * for the purposes of test automation, self-running demos, and
  45  * other applications where control of the mouse and keyboard
  46  * is needed. The primary purpose of Robot is to facilitate
  47  * automated testing of Java platform implementations.
  48  * <p>
  49  * Using the class to generate input events differs from posting


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





 394         Color color = new Color(peer.getRGBPixel(x, y));
 395         return color;
 396     }
 397 
 398     /**
 399      * Creates an image containing pixels read from the screen.  This image does
 400      * not include the mouse cursor.
 401      * @param   screenRect      Rect to capture in screen coordinates
 402      * @return  The captured image
 403      * @throws  IllegalArgumentException if {@code screenRect} width and height are not greater than zero
 404      * @throws  SecurityException if {@code readDisplayPixels} permission is not granted
 405      * @see     SecurityManager#checkPermission
 406      * @see     AWTPermission
 407      */
 408     public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {






















































 409         checkScreenCaptureAllowed();
 410 
 411         checkValidRect(screenRect);
 412 
 413         BufferedImage image;

 414         DataBufferInt buffer;
 415         WritableRaster raster;

 416 
 417         if (screenCapCM == null) {
 418             /*
 419              * Fix for 4285201
 420              * Create a DirectColorModel equivalent to the default RGB ColorModel,
 421              * except with no Alpha component.
 422              */
 423 
 424             screenCapCM = new DirectColorModel(24,
 425                                                /* red mask */    0x00FF0000,
 426                                                /* green mask */  0x0000FF00,
 427                                                /* blue mask */   0x000000FF);
 428         }
 429 





 430         // need to sync the toolkit prior to grabbing the pixels since in some
 431         // cases rendering to the screen may be delayed
 432         Toolkit.getDefaultToolkit().sync();
 433 




 434         int pixels[];
 435         int[] bandmasks = new int[3];

 436 
 437         pixels = peer.getRGBPixels(screenRect);
 438         buffer = new DataBufferInt(pixels, pixels.length);
 439 
 440         bandmasks[0] = screenCapCM.getRedMask();
 441         bandmasks[1] = screenCapCM.getGreenMask();
 442         bandmasks[2] = screenCapCM.getBlueMask();
 443 
 444         raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null);

 445         SunWritableRaster.makeTrackable(buffer);
 446 
 447         image = new BufferedImage(screenCapCM, raster, false, null);


















































 448 
 449         return image;
 450     }
 451 
 452     private static void checkValidRect(Rectangle rect) {
 453         if (rect.width <= 0 || rect.height <= 0) {
 454             throw new IllegalArgumentException("Rectangle width and height must be > 0");
 455         }
 456     }
 457 
 458     private static void checkScreenCaptureAllowed() {
 459         SecurityManager security = System.getSecurityManager();
 460         if (security != null) {
 461             security.checkPermission(AWTPermissions.READ_DISPLAY_PIXELS_PERMISSION);
 462         }
 463     }
 464 
 465     /*
 466      * Called after an event is generated
 467      */
 468     private void afterEvent() {
 469         autoWaitForIdle();


   1 /*
   2  * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  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.MultiResolutionImage;
  33 import java.awt.image.BufferedImage;
  34 import java.awt.image.DataBufferInt;
  35 import java.awt.image.DirectColorModel;
  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 
  45 /**
  46  * This class is used to generate native system input events
  47  * for the purposes of test automation, self-running demos, and
  48  * other applications where control of the mouse and keyboard
  49  * is needed. The primary purpose of Robot is to facilitate
  50  * automated testing of Java platform implementations.
  51  * <p>
  52  * Using the class to generate input events differs from posting


 377         afterEvent();
 378     }
 379 
 380     private void checkKeycodeArgument(int keycode) {
 381         // rather than build a big table or switch statement here, we'll
 382         // just check that the key isn't VK_UNDEFINED and assume that the
 383         // peer implementations will throw an exception for other bogus
 384         // values e.g. -1, 999999
 385         if (keycode == KeyEvent.VK_UNDEFINED) {
 386             throw new IllegalArgumentException("Invalid key code");
 387         }
 388     }
 389 
 390     /**
 391      * Returns the color of a pixel at the given screen coordinates.
 392      * @param   x       X position of pixel
 393      * @param   y       Y position of pixel
 394      * @return  Color of the pixel
 395      */
 396     public synchronized Color getPixelColor(int x, int y) {
 397         AffineTransform tx = GraphicsEnvironment.
 398                 getLocalGraphicsEnvironment().getDefaultScreenDevice().
 399                 getDefaultConfiguration().getDefaultTransform();
 400         x = (int) (x * tx.getScaleX());
 401         y = (int) (y * tx.getScaleY());
 402         Color color = new Color(peer.getRGBPixel(x, y));
 403         return color;
 404     }
 405 
 406     /**
 407      * Creates an image containing pixels read from the screen.  This image does
 408      * not include the mouse cursor.
 409      * @param   screenRect      Rect to capture in screen coordinates
 410      * @return  The captured image
 411      * @throws  IllegalArgumentException if {@code screenRect} width and height are not greater than zero
 412      * @throws  SecurityException if {@code readDisplayPixels} permission is not granted
 413      * @see     SecurityManager#checkPermission
 414      * @see     AWTPermission
 415      */
 416     public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
 417         return createCompatibleImage(screenRect, false)[0];
 418     }
 419 
 420     /**
 421      * Creates an image containing pixels read from the screen.
 422      * This image does not include the mouse cursor.
 423      * This method can be used in case there is a scaling transform
 424      * from user space to screen (device) space.
 425      * Typically this means that the display is a high resolution screen,
 426      * although strictly it means any case in which there is such a transform.
 427      * Returns a {@link java.awt.image.MultiResolutionImage}.
 428      * <p> 
 429      * For a non-scaled display, the {@code MultiResolutionImage}
 430      * will have one image variant:
 431      * <ul>
 432      * <li> Base Image with user specified size.
 433      * </ul>
 434      * <p>
 435      * For a high resolution display where there is a scaling transform, 
 436      * the {@code MultiResolutionImage} will have two image variants:
 437      * <ul>
 438      * <li> Base Image with user specified size. This is scaled from the screen.
 439      * <li> Native device resolution image with device size pixels.
 440      * </ul>
 441      * <p>
 442      * Example:
 443      * <pre>
 444      *      Image nativeResImage;
 445      *      MultiResolutionImage mrImage = robot.createMultiResolutionScreenCapture(frame.getBounds());
 446      *      List<Image> resolutionVariants = mrImage.getResolutionVariants();
 447      *      if (resolutionVariants.size() > 1) {
 448      *          nativeResImage = resolutionVariants.get(1);
 449      *      } else {
 450      *          nativeResImage = resolutionVariants.get(0);
 451      *      } </pre> 
 452      * @param   screenRect     Rect to capture in screen coordinates
 453      * @return  The captured image
 454      * @throws  IllegalArgumentException if {@code screenRect} width and height are not greater than zero
 455      * @throws  SecurityException if {@code readDisplayPixels} permission is not granted
 456      * @see     SecurityManager#checkPermission
 457      * @see     AWTPermission
 458      *
 459      * @since 9
 460      */
 461     public synchronized MultiResolutionImage 
 462             createMultiResolutionScreenCapture(Rectangle screenRect) {
 463 
 464         return new BaseMultiResolutionImage(
 465                 createCompatibleImage(screenRect, true));
 466     }
 467 
 468     private synchronized BufferedImage[] 
 469             createCompatibleImage(Rectangle screenRect, boolean isHiDPI) {
 470 
 471         checkScreenCaptureAllowed();
 472 
 473         checkValidRect(screenRect);
 474 
 475         BufferedImage lowResolutionImage;
 476         BufferedImage highResolutionImage;
 477         DataBufferInt buffer;
 478         WritableRaster raster;
 479         BufferedImage[] imageArray;
 480 
 481         if (screenCapCM == null) {
 482             /*
 483              * Fix for 4285201
 484              * Create a DirectColorModel equivalent to the default RGB ColorModel,
 485              * except with no Alpha component.
 486              */
 487 
 488             screenCapCM = new DirectColorModel(24,
 489                     /* red mask */ 0x00FF0000,
 490                     /* green mask */ 0x0000FF00,
 491                     /* blue mask */ 0x000000FF);
 492         }
 493 
 494         int[] bandmasks = new int[3];
 495         bandmasks[0] = screenCapCM.getRedMask();
 496         bandmasks[1] = screenCapCM.getGreenMask();
 497         bandmasks[2] = screenCapCM.getBlueMask();
 498         
 499         // need to sync the toolkit prior to grabbing the pixels since in some
 500         // cases rendering to the screen may be delayed
 501         Toolkit.getDefaultToolkit().sync();
 502         AffineTransform tx = GraphicsEnvironment.
 503                 getLocalGraphicsEnvironment().getDefaultScreenDevice().
 504                 getDefaultConfiguration().getDefaultTransform();
 505         double uiScaleX = tx.getScaleX();
 506         double uiScaleY = tx.getScaleY();
 507         int pixels[];
 508 
 509         if (uiScaleX == 1 && uiScaleY == 1) {
 510 
 511             pixels = peer.getRGBPixels(screenRect);
 512             buffer = new DataBufferInt(pixels, pixels.length);
 513 
 514             bandmasks[0] = screenCapCM.getRedMask();
 515             bandmasks[1] = screenCapCM.getGreenMask();
 516             bandmasks[2] = screenCapCM.getBlueMask();
 517 
 518             raster = Raster.createPackedRaster(buffer, screenRect.width,
 519                     screenRect.height, screenRect.width, bandmasks, null);
 520             SunWritableRaster.makeTrackable(buffer);
 521             
 522             highResolutionImage = new BufferedImage(screenCapCM, raster,
 523                     false, null);
 524             imageArray = new BufferedImage[1];
 525             imageArray[0] = highResolutionImage;
 526 
 527         } else {
 528 
 529             int sX = (int) Math.floor(screenRect.x * uiScaleX);
 530             int sY = (int) Math.floor(screenRect.y * uiScaleY);
 531             int sWidth = (int) Math.ceil(screenRect.width * uiScaleX);
 532             int sHeight = (int) Math.ceil(screenRect.height * uiScaleY);
 533             int temppixels[];
 534             Rectangle scaledRect = new Rectangle(sX, sY, sWidth, sHeight);
 535             temppixels = peer.getRGBPixels(scaledRect);
 536 
 537             // HighResolutionImage
 538             pixels = temppixels;
 539             buffer = new DataBufferInt(pixels, pixels.length);
 540             raster = Raster.createPackedRaster(buffer, scaledRect.width,
 541                     scaledRect.height, scaledRect.width, bandmasks, null);
 542             SunWritableRaster.makeTrackable(buffer);
 543 
 544             highResolutionImage = new BufferedImage(screenCapCM, raster,
 545                     false, null);
 546 
 547 
 548             // LowResolutionImage
 549             lowResolutionImage = new BufferedImage(screenRect.width,
 550                     screenRect.height, highResolutionImage.getType());
 551             Graphics2D g = lowResolutionImage.createGraphics();
 552             g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
 553                     RenderingHints.VALUE_INTERPOLATION_BILINEAR);
 554             g.setRenderingHint(RenderingHints.KEY_RENDERING,
 555                     RenderingHints.VALUE_RENDER_QUALITY);
 556             g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
 557                     RenderingHints.VALUE_ANTIALIAS_ON);
 558             g.drawImage(highResolutionImage, 0, 0,
 559                     screenRect.width, screenRect.height,
 560                     0, 0, scaledRect.width, scaledRect.height, null);
 561             g.dispose();
 562 
 563             if(!isHiDPI) {
 564                 imageArray = new BufferedImage[1];
 565                 imageArray[0] = lowResolutionImage;
 566             } else {
 567                 imageArray = new BufferedImage[2];
 568                 imageArray[0] = lowResolutionImage;
 569                 imageArray[1] = highResolutionImage;
 570             }
 571 
 572         }
 573 
 574         return imageArray;
 575     }
 576 
 577     private static void checkValidRect(Rectangle rect) {
 578         if (rect.width <= 0 || rect.height <= 0) {
 579             throw new IllegalArgumentException("Rectangle width and height must be > 0");
 580         }
 581     }
 582 
 583     private static void checkScreenCaptureAllowed() {
 584         SecurityManager security = System.getSecurityManager();
 585         if (security != null) {
 586             security.checkPermission(AWTPermissions.READ_DISPLAY_PIXELS_PERMISSION);
 587         }
 588     }
 589 
 590     /*
 591      * Called after an event is generated
 592      */
 593     private void afterEvent() {
 594         autoWaitForIdle();


< prev index next >