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
373 afterEvent();
374 }
375
376 private void checkKeycodeArgument(int keycode) {
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
457 private static void checkScreenCaptureAllowed() {
458 SecurityManager security = System.getSecurityManager();
459 if (security != null) {
460 security.checkPermission(AWTPermissions.READ_DISPLAY_PIXELS_PERMISSION);
461 }
462 }
463
464 /*
465 * Called after an event is generated
466 */
467 private void afterEvent() {
468 autoWaitForIdle();
|
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.BaseMultiResolutionImage;
32 import java.awt.image.BufferedImage;
33 import java.awt.image.DataBufferInt;
34 import java.awt.image.DirectColorModel;
35 import java.awt.image.Raster;
36 import java.awt.image.WritableRaster;
37 import java.awt.peer.RobotPeer;
38
39 import sun.awt.AWTPermissions;
40 import sun.awt.ComponentFactory;
41 import sun.awt.SunToolkit;
42 import sun.awt.image.SunWritableRaster;
43
44 /**
45 * This class is used to generate native system input events
46 * for the purposes of test automation, self-running demos, and
47 * other applications where control of the mouse and keyboard
48 * is needed. The primary purpose of Robot is to facilitate
49 * automated testing of Java platform implementations.
50 * <p>
51 * Using the class to generate input events differs from posting
375 afterEvent();
376 }
377
378 private void checkKeycodeArgument(int keycode) {
379 // rather than build a big table or switch statement here, we'll
380 // just check that the key isn't VK_UNDEFINED and assume that the
381 // peer implementations will throw an exception for other bogus
382 // values e.g. -1, 999999
383 if (keycode == KeyEvent.VK_UNDEFINED) {
384 throw new IllegalArgumentException("Invalid key code");
385 }
386 }
387
388 /**
389 * Returns the color of a pixel at the given screen coordinates.
390 * @param x X position of pixel
391 * @param y Y position of pixel
392 * @return Color of the pixel
393 */
394 public synchronized Color getPixelColor(int x, int y) {
395 AffineTransform tx = GraphicsEnvironment.
396 getLocalGraphicsEnvironment().getDefaultScreenDevice().
397 getDefaultConfiguration().getDefaultTransform();
398 x = (int) (x * tx.getScaleX());
399 y = (int) (y * tx.getScaleY());
400 Color color = new Color(peer.getRGBPixel(x, y));
401 return color;
402 }
403
404 /**
405 * Creates an image containing pixels read from the screen. This image does
406 * not include the mouse cursor.
407 * @param screenRect Rect to capture in screen coordinates
408 * @return The captured image
409 * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero
410 * @throws SecurityException if {@code readDisplayPixels} permission is not granted
411 * @see SecurityManager#checkPermission
412 * @see AWTPermission
413 */
414 public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
415 return (BufferedImage) createScreenCapture(screenRect, false);
416 }
417
418 /**
419 * Creates an image containing pixels read from the screen.
420 * This image does not include the mouse cursor.
421 * Returns BufferedImage for Non-HiDPI display and
422 * MultiResolutionImage for HiDPI display with two resolution variants,
423 * Base Image with user specified size and
424 * High Resolution Image with original size.
425 * @param screenRect Rect to capture in screen coordinates
426 * @param isHiDPI Indicates if HiDPI Display
427 * @return The captured image
428 * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero
429 * @throws SecurityException if {@code readDisplayPixels} permission is not granted
430 * @see SecurityManager#checkPermission
431 * @see AWTPermission
432 */
433
434 public synchronized Image createScreenCapture(Rectangle screenRect, boolean isHiDPI) {
435 checkScreenCaptureAllowed();
436
437 checkValidRect(screenRect);
438
439 BufferedImage lowResolutionImage;
440 BufferedImage highResolutionImage;
441 DataBufferInt buffer;
442 WritableRaster raster;
443
444 if (screenCapCM == null) {
445 /*
446 * Fix for 4285201
447 * Create a DirectColorModel equivalent to the default RGB ColorModel,
448 * except with no Alpha component.
449 */
450
451 screenCapCM = new DirectColorModel(24,
452 /* red mask */ 0x00FF0000,
453 /* green mask */ 0x0000FF00,
454 /* blue mask */ 0x000000FF);
455 }
456
457 int[] bandmasks = new int[3];
458 bandmasks[0] = screenCapCM.getRedMask();
459 bandmasks[1] = screenCapCM.getGreenMask();
460 bandmasks[2] = screenCapCM.getBlueMask();
461
462 // need to sync the toolkit prior to grabbing the pixels since in some
463 // cases rendering to the screen may be delayed
464 Toolkit.getDefaultToolkit().sync();
465 AffineTransform tx = GraphicsEnvironment.
466 getLocalGraphicsEnvironment().getDefaultScreenDevice().
467 getDefaultConfiguration().getDefaultTransform();
468 double uiScaleX = tx.getScaleX();
469 double uiScaleY = tx.getScaleY();
470 int pixels[];
471
472 if (uiScaleX == 1 && uiScaleY == 1) {
473 pixels = peer.getRGBPixels(screenRect);
474 buffer = new DataBufferInt(pixels, pixels.length);
475
476 bandmasks[0] = screenCapCM.getRedMask();
477 bandmasks[1] = screenCapCM.getGreenMask();
478 bandmasks[2] = screenCapCM.getBlueMask();
479
480 raster = Raster.createPackedRaster(buffer, screenRect.width,
481 screenRect.height, screenRect.width, bandmasks, null);
482 SunWritableRaster.makeTrackable(buffer);
483
484 return new BufferedImage(screenCapCM, raster, false, null);
485
486 } else {
487
488 int x = screenRect.x;
489 int y = screenRect.y;
490 int width = screenRect.width;
491 int height = screenRect.height;
492 int pminx = (int) Math.floor(x * uiScaleX);
493 int pminy = (int) Math.floor(y * uiScaleY);
494 int pmaxx = (int) Math.ceil((x + width) * uiScaleX);
495 int pmaxy = (int) Math.ceil((y + height) * uiScaleY);
496 int pwidth = pmaxx - pminx;
497 int pheight = pmaxy - pminy;
498 int temppixels[];
499 Rectangle scaledRect = new Rectangle(pminx, pminy, pwidth, pheight);
500 temppixels = peer.getRGBPixels(scaledRect);
501
502 // HighResolutionImage
503 pixels = temppixels;
504 buffer = new DataBufferInt(pixels, pixels.length);
505 raster = Raster.createPackedRaster(buffer, scaledRect.width,
506 scaledRect.height, scaledRect.width, bandmasks, null);
507 SunWritableRaster.makeTrackable(buffer);
508
509 highResolutionImage = new BufferedImage(screenCapCM, raster,
510 false, null);
511
512 // LowResolutionImage
513 lowResolutionImage = new BufferedImage(screenRect.width,
514 screenRect.height, highResolutionImage.getType());
515 Graphics2D g = lowResolutionImage.createGraphics();
516 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
517 RenderingHints.VALUE_INTERPOLATION_BILINEAR);
518 g.setRenderingHint(RenderingHints.KEY_RENDERING,
519 RenderingHints.VALUE_RENDER_QUALITY);
520 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
521 RenderingHints.VALUE_ANTIALIAS_ON);
522 g.drawImage(highResolutionImage, 0, 0,
523 screenRect.width, screenRect.height,
524 0, 0, scaledRect.width, scaledRect.height, null);
525 g.dispose();
526
527 if (!isHiDPI) {
528 return lowResolutionImage;
529 } else {
530 // MultiResoltuionImage
531 return new BaseMultiResolutionImage(
532 lowResolutionImage, highResolutionImage);
533 }
534 }
535 }
536
537 private static void checkValidRect(Rectangle rect) {
538 if (rect.width <= 0 || rect.height <= 0) {
539 throw new IllegalArgumentException("Rectangle width and height must be > 0");
540 }
541 }
542
543 private static void checkScreenCaptureAllowed() {
544 SecurityManager security = System.getSecurityManager();
545 if (security != null) {
546 security.checkPermission(AWTPermissions.READ_DISPLAY_PIXELS_PERMISSION);
547 }
548 }
549
550 /*
551 * Called after an event is generated
552 */
553 private void afterEvent() {
554 autoWaitForIdle();
|