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