< 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


 377         // rather than build a big table or switch statement here, we'll
 378         // just check that the key isn't VK_UNDEFINED and assume that the
 379         // peer implementations will throw an exception for other bogus
 380         // values e.g. -1, 999999
 381         if (keycode == KeyEvent.VK_UNDEFINED) {
 382             throw new IllegalArgumentException("Invalid key code");
 383         }
 384     }
 385 
 386     /**
 387      * Returns the color of a pixel at the given screen coordinates.
 388      * @param   x       X position of pixel
 389      * @param   y       Y position of pixel
 390      * @return  Color of the pixel
 391      */
 392     public synchronized Color getPixelColor(int x, int y) {
 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         checkScreenCaptureAllowed();
 409 
 410         checkValidRect(screenRect);
 411 
 412         BufferedImage image;
 413         DataBufferInt buffer;
 414         WritableRaster raster;
 415 
 416         if (screenCapCM == null) {
 417             /*
 418              * Fix for 4285201
 419              * Create a DirectColorModel equivalent to the default RGB ColorModel,
 420              * except with no Alpha component.
 421              */
 422 
 423             screenCapCM = new DirectColorModel(24,
 424                                                /* red mask */    0x00FF0000,
 425                                                /* green mask */  0x0000FF00,
 426                                                /* blue mask */   0x000000FF);
 427         }
 428 
 429         // need to sync the toolkit prior to grabbing the pixels since in some
 430         // cases rendering to the screen may be delayed
 431         Toolkit.getDefaultToolkit().sync();
 432 




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

 436         pixels = peer.getRGBPixels(screenRect);









































 437         buffer = new DataBufferInt(pixels, pixels.length);
 438 
 439         bandmasks[0] = screenCapCM.getRedMask();
 440         bandmasks[1] = screenCapCM.getGreenMask();
 441         bandmasks[2] = screenCapCM.getBlueMask();
 442 
 443         raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null);
 444         SunWritableRaster.makeTrackable(buffer);
 445 
 446         image = new BufferedImage(screenCapCM, raster, false, null);
 447 
 448         return image;
 449     }
 450 
 451     private static void checkValidRect(Rectangle rect) {
 452         if (rect.width <= 0 || rect.height <= 0) {
 453             throw new IllegalArgumentException("Rectangle width and height must be > 0");
 454         }
 455     }
 456 


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


 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     private static int interp(int pixels[], int x, int y, int w, int h, int fractx1, int fracty1) {
 399         int fractx0 = 256 - fractx1;
 400         int fracty0 = 256 - fracty1;
 401         int i = y * w + x;
 402         int rgb00 = (x < 0 || y < 0 || x >= w || y >= h) ? 0 : pixels[i];
 403         if (fracty1 == 0) {
 404             // No interplation with pixels[y+1]
 405             if (fractx1 == 0) {
 406                 // No interpolation with any neighbors
 407                 return rgb00;
 408             }
 409             int rgb10 = (y < 0 || x + 1 >= w || y >= h) ? 0 : pixels[i + 1];
 410             return interp(rgb00, rgb10, fractx0, fractx1);
 411         } else if (fractx1 == 0) {
 412             // No interpolation with pixels[x+1]
 413             int rgb01 = (x < 0 || x >= w || y + 1 >= h) ? 0 : pixels[i + w];
 414             return interp(rgb00, rgb01, fracty0, fracty1);
 415         } else {
 416             // All 4 neighbors must be interpolated
 417             int rgb10 = (y < 0 || x + 1 >= w || y >= h) ? 0 : pixels[i + 1];
 418             int rgb01 = (x < 0 || x >= w || y + 1 >= h) ? 0 : pixels[i + w];
 419             int rgb11 = (x + 1 >= w || y + 1 >= h) ? 0 : pixels[i + w + 1];
 420             return interp(interp(rgb00, rgb10, fractx0, fractx1),
 421                     interp(rgb01, rgb11, fractx0, fractx1),
 422                     fracty0, fracty1);
 423         }
 424     }
 425 
 426     private static int interp(int rgb0, int rgb1, int fract0, int fract1) {
 427         int a0 = (rgb0 >> 24) & 0xff;
 428         int r0 = (rgb0 >> 16) & 0xff;
 429         int g0 = (rgb0 >> 8) & 0xff;
 430         int b0 = (rgb0) & 0xff;
 431         int a1 = (rgb1 >> 24) & 0xff;
 432         int r1 = (rgb1 >> 16) & 0xff;
 433         int g1 = (rgb1 >> 8) & 0xff;
 434         int b1 = (rgb1) & 0xff;
 435         int a = (a0 * fract0 + a1 * fract1) >> 8;
 436         int r = (r0 * fract0 + r1 * fract1) >> 8;
 437         int g = (g0 * fract0 + g1 * fract1) >> 8;
 438         int b = (b0 * fract0 + b1 * fract1) >> 8;
 439         return (a << 24) | (r << 16) | (g << 8) | b;
 440     }
 441 
 442      /**
 443      * Creates an image containing pixels read from the screen.  This image does
 444      * not include the mouse cursor.
 445      * @param   screenRect      Rect to capture in screen coordinates
 446      * @return  The captured image
 447      * @throws  IllegalArgumentException if {@code screenRect} width and height are not greater than zero
 448      * @throws  SecurityException if {@code readDisplayPixels} permission is not granted
 449      * @see     SecurityManager#checkPermission
 450      * @see     AWTPermission
 451      */
 452     public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
 453           return createScreenCapture(screenRect, false);
 454     }
 455 
 456     /**
 457      * Creates an image containing pixels read from the screen.  This image does
 458      * not include the mouse cursor.
 459      * @param   screenRect  Rect to capture in screen coordinates
 460      * @param   isHiDPI Specifies if HiDPI
 461      * @return  The captured image
 462      * @throws  IllegalArgumentException if {@code screenRect} width and height are not greater than zero
 463      * @throws  SecurityException if {@code readDisplayPixels} permission is not granted
 464      * @see     SecurityManager#checkPermission
 465      * @see     AWTPermission
 466      */
 467     public synchronized BufferedImage createScreenCapture(Rectangle screenRect, 
 468             boolean isHiDPI) {
 469         checkScreenCaptureAllowed();
 470 
 471         checkValidRect(screenRect);
 472 
 473         BufferedImage image;
 474         DataBufferInt buffer;
 475         WritableRaster raster;
 476 
 477         if (screenCapCM == null) {
 478             /*
 479              * Fix for 4285201
 480              * Create a DirectColorModel equivalent to the default RGB ColorModel,
 481              * except with no Alpha component.
 482              */
 483 
 484             screenCapCM = new DirectColorModel(24,
 485                     /* red mask */ 0x00FF0000,
 486                     /* green mask */ 0x0000FF00,
 487                     /* blue mask */ 0x000000FF);
 488         }
 489 
 490         // need to sync the toolkit prior to grabbing the pixels since in some
 491         // cases rendering to the screen may be delayed
 492         Toolkit.getDefaultToolkit().sync();
 493         AffineTransform tx = GraphicsEnvironment.
 494                 getLocalGraphicsEnvironment().getDefaultScreenDevice().
 495                 getDefaultConfiguration().getDefaultTransform();
 496         double uiScaleX = tx.getScaleX();
 497         double uiScaleY = tx.getScaleY();
 498         int pixels[];
 499         int[] bandmasks = new int[3];
 500 
 501         if (uiScaleX == 1 && uiScaleY == 1) {
 502             pixels = peer.getRGBPixels(screenRect);
 503         } else {
 504             int x = screenRect.x;
 505             int y = screenRect.y;
 506             int width = screenRect.width;
 507             int height = screenRect.height;
 508             int pminx = (int) Math.floor(x * uiScaleX);
 509             int pminy = (int) Math.floor(y * uiScaleY);
 510             int pmaxx = (int) Math.ceil((x + width) * uiScaleX);
 511             int pmaxy = (int) Math.ceil((y + height) * uiScaleY);
 512             int pwidth = pmaxx - pminx;
 513             int pheight = pmaxy - pminy;
 514             int temppixels[];
 515             Rectangle rect = new Rectangle(pminx, pminy, pwidth, pheight);
 516             temppixels = peer.getRGBPixels(rect);
 517             if (isHiDPI) {
 518                 pixels = temppixels;
 519                 screenRect.width = pwidth;
 520                 screenRect.height = pheight;
 521             } else {
 522                 pixels = new int[width * height];
 523                 int index = 0;
 524                 for (int iy = 0; iy < height; iy++) {
 525                     float rely = (float) (((y + iy + 0.5f) * uiScaleY)
 526                             - (pminy + 0.5f));
 527                     int irely = (int) Math.floor(rely);
 528                     int fracty = (int) ((rely - irely) * 256);
 529                     for (int ix = 0; ix < width; ix++) {
 530                         float relx = (float) (((x + ix + 0.5f) * uiScaleX)
 531                                 - (pminx + 0.5f));
 532                         int irelx = (int) Math.floor(relx);
 533                         int fractx = (int) ((relx - irelx) * 256);
 534                         pixels[index++]
 535                                 = interp(temppixels, irelx, irely, pwidth,
 536                                         pheight, fractx, fracty);
 537                     }
 538                 }
 539                 screenRect.width = width;
 540                 screenRect.height = height;
 541             }
 542         }
 543 
 544         buffer = new DataBufferInt(pixels, pixels.length);
 545 
 546         bandmasks[0] = screenCapCM.getRedMask();
 547         bandmasks[1] = screenCapCM.getGreenMask();
 548         bandmasks[2] = screenCapCM.getBlueMask();
 549 
 550         raster = Raster.createPackedRaster(buffer, screenRect.width, screenRect.height, screenRect.width, bandmasks, null);
 551         SunWritableRaster.makeTrackable(buffer);
 552 
 553         image = new BufferedImage(screenCapCM, raster, false, null);
 554 
 555         return image;
 556     }
 557 
 558     private static void checkValidRect(Rectangle rect) {
 559         if (rect.width <= 0 || rect.height <= 0) {
 560             throw new IllegalArgumentException("Rectangle width and height must be > 0");
 561         }
 562     }
 563 


< prev index next >