< prev index next >

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

Print this page


   1 /*
   2  * Copyright (c) 1999, 2019, 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


  73     private static final int MAX_DELAY = 60000;
  74     private RobotPeer peer;
  75     private boolean isAutoWaitForIdle = false;
  76     private int autoDelay = 0;
  77     private static int LEGAL_BUTTON_MASK = 0;
  78 
  79     private DirectColorModel screenCapCM = null;
  80 
  81     /**
  82      * Constructs a Robot object in the coordinate system of the primary screen.
  83      *
  84      * @throws  AWTException if the platform configuration does not allow
  85      * low-level input control.  This exception is always thrown when
  86      * GraphicsEnvironment.isHeadless() returns true
  87      * @throws  SecurityException if {@code createRobot} permission is not granted
  88      * @see     java.awt.GraphicsEnvironment#isHeadless
  89      * @see     SecurityManager#checkPermission
  90      * @see     AWTPermission
  91      */
  92     public Robot() throws AWTException {
  93         if (GraphicsEnvironment.isHeadless()) {
  94             throw new AWTException("headless environment");
  95         }
  96         init(GraphicsEnvironment.getLocalGraphicsEnvironment()
  97             .getDefaultScreenDevice());
  98     }
  99 
 100     /**
 101      * Creates a Robot for the given screen device. Coordinates passed
 102      * to Robot method calls like mouseMove, getPixelColor and
 103      * createScreenCapture will be interpreted as being in the same coordinate
 104      * system as the specified screen. Note that depending on the platform
 105      * configuration, multiple screens may either:
 106      * <ul>
 107      * <li>share the same coordinate system to form a combined virtual screen</li>
 108      * <li>use different coordinate systems to act as independent screens</li>
 109      * </ul>
 110      * <p>
 111      * If screen devices are reconfigured such that the coordinate system is
 112      * affected, the behavior of existing Robot objects is undefined.
 113      *
 114      * @param screen    A screen GraphicsDevice indicating the coordinate
 115      *                  system the Robot will operate in.
 116      * @throws  AWTException if the platform configuration does not allow
 117      * low-level input control.  This exception is always thrown when
 118      * GraphicsEnvironment.isHeadless() returns true.
 119      * @throws  IllegalArgumentException if {@code screen} is not a screen
 120      *          GraphicsDevice.
 121      * @throws  SecurityException if {@code createRobot} permission is not granted
 122      * @see     java.awt.GraphicsEnvironment#isHeadless
 123      * @see     GraphicsDevice
 124      * @see     SecurityManager#checkPermission
 125      * @see     AWTPermission
 126      */
 127     public Robot(GraphicsDevice screen) throws AWTException {

 128         checkIsScreenDevice(screen);
 129         init(screen);
 130     }
 131 
 132     private void init(GraphicsDevice screen) throws AWTException {
 133         checkRobotAllowed();
 134         Toolkit toolkit = Toolkit.getDefaultToolkit();
 135         if (toolkit instanceof ComponentFactory) {
 136             peer = ((ComponentFactory)toolkit).createRobot(this, screen);
 137         }
 138         initLegalButtonMask();
 139     }
 140 
 141     @SuppressWarnings("deprecation")
 142     private static synchronized void initLegalButtonMask() {
 143         if (LEGAL_BUTTON_MASK != 0) return;
 144 
 145         int tmpMask = 0;
 146         if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){
 147             if (Toolkit.getDefaultToolkit() instanceof SunToolkit) {
 148                 final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
 149                 for (int i = 0; i < buttonsNumber; i++){
 150                     tmpMask |= InputEvent.getMaskForButton(i+1);
 151                 }
 152             }
 153         }
 154         tmpMask |= InputEvent.BUTTON1_MASK|
 155             InputEvent.BUTTON2_MASK|
 156             InputEvent.BUTTON3_MASK|
 157             InputEvent.BUTTON1_DOWN_MASK|
 158             InputEvent.BUTTON2_DOWN_MASK|
 159             InputEvent.BUTTON3_DOWN_MASK;
 160         LEGAL_BUTTON_MASK = tmpMask;
 161     }
 162 
 163     /* determine if the security policy allows Robot's to be created */
 164     private void checkRobotAllowed() {
 165         SecurityManager security = System.getSecurityManager();
 166         if (security != null) {
 167             security.checkPermission(AWTPermissions.CREATE_ROBOT_PERMISSION);
 168         }
 169     }
 170 









 171     /* check if the given device is a screen device */
 172     private void checkIsScreenDevice(GraphicsDevice device) {
 173         if (device == null || device.getType() != GraphicsDevice.TYPE_RASTER_SCREEN) {
 174             throw new IllegalArgumentException("not a valid screen device");
 175         }
 176     }
 177 
 178     /**
 179      * Moves mouse pointer to given screen coordinates.
 180      * @param x         X position
 181      * @param y         Y position
 182      */
 183     public synchronized void mouseMove(int x, int y) {
 184         peer.mouseMove(x, y);
 185         afterEvent();
 186     }
 187 
 188     /**
 189      * Presses one or more mouse buttons.  The mouse buttons should
 190      * be released using the {@link #mouseRelease(int)} method.
 191      *
 192      * @param buttons the Button mask; a combination of one or more


 283      * However, it is recommended to use {@code InputEvent.BUTTON1_DOWN_MASK},
 284      * {@code InputEvent.BUTTON2_DOWN_MASK},  {@code InputEvent.BUTTON3_DOWN_MASK} instead.
 285      * Either extended {@code _DOWN_MASK} or old {@code _MASK} values
 286      * should be used, but both those models should not be mixed.
 287      * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button
 288      *         and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
 289      * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button
 290      *         that does not exist on the mouse and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java
 291      * @see #mousePress(int)
 292      * @see InputEvent#getMaskForButton(int)
 293      * @see Toolkit#areExtraMouseButtonsEnabled()
 294      * @see java.awt.MouseInfo#getNumberOfButtons()
 295      * @see java.awt.event.MouseEvent
 296      */
 297     public synchronized void mouseRelease(int buttons) {
 298         checkButtonsArgument(buttons);
 299         peer.mouseRelease(buttons);
 300         afterEvent();
 301     }
 302 
 303     private void checkButtonsArgument(int buttons) {
 304         if ( (buttons|LEGAL_BUTTON_MASK) != LEGAL_BUTTON_MASK ) {
 305             throw new IllegalArgumentException("Invalid combination of button flags");
 306         }
 307     }
 308 
 309     /**
 310      * Rotates the scroll wheel on wheel-equipped mice.
 311      *
 312      * @param wheelAmt  number of "notches" to move the mouse wheel
 313      *                  Negative values indicate movement up/away from the user,
 314      *                  positive values indicate movement down/towards the user.
 315      *
 316      * @since 1.4
 317      */
 318     public synchronized void mouseWheel(int wheelAmt) {
 319         peer.mouseWheel(wheelAmt);
 320         afterEvent();
 321     }
 322 
 323     /**


 342 
 343     /**
 344      * Releases a given key.
 345      * <p>
 346      * Key codes that have more than one physical key associated with them
 347      * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the
 348      * left or right shift key) will map to the left key.
 349      *
 350      * @param   keycode Key to release (e.g. {@code KeyEvent.VK_A})
 351      * @throws  IllegalArgumentException if {@code keycode} is not a
 352      *          valid key
 353      * @see  #keyPress(int)
 354      * @see     java.awt.event.KeyEvent
 355      */
 356     public synchronized void keyRelease(int keycode) {
 357         checkKeycodeArgument(keycode);
 358         peer.keyRelease(keycode);
 359         afterEvent();
 360     }
 361 
 362     private void checkKeycodeArgument(int keycode) {
 363         // rather than build a big table or switch statement here, we'll
 364         // just check that the key isn't VK_UNDEFINED and assume that the
 365         // peer implementations will throw an exception for other bogus
 366         // values e.g. -1, 999999
 367         if (keycode == KeyEvent.VK_UNDEFINED) {
 368             throw new IllegalArgumentException("Invalid key code");
 369         }
 370     }
 371 
 372     /**
 373      * Returns the color of a pixel at the given screen coordinates.
 374      * @param   x       X position of pixel
 375      * @param   y       Y position of pixel
 376      * @return  Color of the pixel
 377      */
 378     public synchronized Color getPixelColor(int x, int y) {
 379         checkScreenCaptureAllowed();
 380         AffineTransform tx = GraphicsEnvironment.
 381                 getLocalGraphicsEnvironment().getDefaultScreenDevice().
 382                 getDefaultConfiguration().getDefaultTransform();


 647      * immediately with the interrupt status set. If the interrupted status is
 648      * already set, this method returns immediately with the interrupt status
 649      * set.
 650      *
 651      * @param  ms time to sleep in milliseconds
 652      * @throws IllegalArgumentException if {@code ms} is not between {@code 0}
 653      *         and {@code 60,000} milliseconds inclusive
 654      */
 655     public void delay(int ms) {
 656         checkDelayArgument(ms);
 657         Thread thread = Thread.currentThread();
 658         if (!thread.isInterrupted()) {
 659             try {
 660                 Thread.sleep(ms);
 661             } catch (final InterruptedException ignored) {
 662                 thread.interrupt(); // Preserve interrupt status
 663             }
 664         }
 665     }
 666 
 667     private void checkDelayArgument(int ms) {
 668         if (ms < 0 || ms > MAX_DELAY) {
 669             throw new IllegalArgumentException("Delay must be to 0 to 60,000ms");
 670         }
 671     }
 672 
 673     /**
 674      * Waits until all events currently on the event queue have been processed.
 675      * @throws  IllegalThreadStateException if called on the AWT event dispatching thread
 676      */
 677     public synchronized void waitForIdle() {
 678         checkNotDispatchThread();
 679         SunToolkit.flushPendingEvents();
 680         ((SunToolkit) Toolkit.getDefaultToolkit()).realSync();
 681     }
 682 
 683     private void checkNotDispatchThread() {
 684         if (EventQueue.isDispatchThread()) {
 685             throw new IllegalThreadStateException("Cannot call method from the event dispatcher thread");
 686         }
 687     }
 688 
 689     /**
 690      * Returns a string representation of this Robot.
 691      *
 692      * @return  the string representation.
 693      */
 694     @Override
 695     public synchronized String toString() {
 696         String params = "autoDelay = "+getAutoDelay()+", "+"autoWaitForIdle = "+isAutoWaitForIdle();
 697         return getClass().getName() + "[ " + params + " ]";
 698     }
 699 }
   1 /*
   2  * Copyright (c) 1999, 2020, 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


  73     private static final int MAX_DELAY = 60000;
  74     private RobotPeer peer;
  75     private boolean isAutoWaitForIdle = false;
  76     private int autoDelay = 0;
  77     private static int LEGAL_BUTTON_MASK = 0;
  78 
  79     private DirectColorModel screenCapCM = null;
  80 
  81     /**
  82      * Constructs a Robot object in the coordinate system of the primary screen.
  83      *
  84      * @throws  AWTException if the platform configuration does not allow
  85      * low-level input control.  This exception is always thrown when
  86      * GraphicsEnvironment.isHeadless() returns true
  87      * @throws  SecurityException if {@code createRobot} permission is not granted
  88      * @see     java.awt.GraphicsEnvironment#isHeadless
  89      * @see     SecurityManager#checkPermission
  90      * @see     AWTPermission
  91      */
  92     public Robot() throws AWTException {
  93         checkHeadless();


  94         init(GraphicsEnvironment.getLocalGraphicsEnvironment()
  95             .getDefaultScreenDevice());
  96     }
  97 
  98     /**
  99      * Creates a Robot for the given screen device. Coordinates passed
 100      * to Robot method calls like mouseMove, getPixelColor and
 101      * createScreenCapture will be interpreted as being in the same coordinate
 102      * system as the specified screen. Note that depending on the platform
 103      * configuration, multiple screens may either:
 104      * <ul>
 105      * <li>share the same coordinate system to form a combined virtual screen</li>
 106      * <li>use different coordinate systems to act as independent screens</li>
 107      * </ul>
 108      * <p>
 109      * If screen devices are reconfigured such that the coordinate system is
 110      * affected, the behavior of existing Robot objects is undefined.
 111      *
 112      * @param screen    A screen GraphicsDevice indicating the coordinate
 113      *                  system the Robot will operate in.
 114      * @throws  AWTException if the platform configuration does not allow
 115      * low-level input control.  This exception is always thrown when
 116      * GraphicsEnvironment.isHeadless() returns true.
 117      * @throws  IllegalArgumentException if {@code screen} is not a screen
 118      *          GraphicsDevice.
 119      * @throws  SecurityException if {@code createRobot} permission is not granted
 120      * @see     java.awt.GraphicsEnvironment#isHeadless
 121      * @see     GraphicsDevice
 122      * @see     SecurityManager#checkPermission
 123      * @see     AWTPermission
 124      */
 125     public Robot(GraphicsDevice screen) throws AWTException {
 126         checkHeadless();
 127         checkIsScreenDevice(screen);
 128         init(screen);
 129     }
 130 
 131     private void init(GraphicsDevice screen) throws AWTException {
 132         checkRobotAllowed();
 133         Toolkit toolkit = Toolkit.getDefaultToolkit();
 134         if (toolkit instanceof ComponentFactory) {
 135             peer = ((ComponentFactory)toolkit).createRobot(this, screen);
 136         }
 137         initLegalButtonMask();
 138     }
 139 
 140     @SuppressWarnings("deprecation")
 141     private static synchronized void initLegalButtonMask() {
 142         if (LEGAL_BUTTON_MASK != 0) return;
 143 
 144         int tmpMask = 0;
 145         if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){
 146             if (Toolkit.getDefaultToolkit() instanceof SunToolkit) {
 147                 final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
 148                 for (int i = 0; i < buttonsNumber; i++){
 149                     tmpMask |= InputEvent.getMaskForButton(i+1);
 150                 }
 151             }
 152         }
 153         tmpMask |= InputEvent.BUTTON1_MASK|
 154             InputEvent.BUTTON2_MASK|
 155             InputEvent.BUTTON3_MASK|
 156             InputEvent.BUTTON1_DOWN_MASK|
 157             InputEvent.BUTTON2_DOWN_MASK|
 158             InputEvent.BUTTON3_DOWN_MASK;
 159         LEGAL_BUTTON_MASK = tmpMask;
 160     }
 161 
 162     /* determine if the security policy allows Robot's to be created */
 163     private static void checkRobotAllowed() {
 164         SecurityManager security = System.getSecurityManager();
 165         if (security != null) {
 166             security.checkPermission(AWTPermissions.CREATE_ROBOT_PERMISSION);
 167         }
 168     }
 169 
 170     /**
 171      * Check for headless state and throw {@code AWTException} if headless.
 172      */
 173     private static void checkHeadless() throws AWTException {
 174         if (GraphicsEnvironment.isHeadless()) {
 175             throw new AWTException("headless environment");
 176         }
 177     }
 178 
 179     /* check if the given device is a screen device */
 180     private static void checkIsScreenDevice(GraphicsDevice device) {
 181         if (device == null || device.getType() != GraphicsDevice.TYPE_RASTER_SCREEN) {
 182             throw new IllegalArgumentException("not a valid screen device");
 183         }
 184     }
 185 
 186     /**
 187      * Moves mouse pointer to given screen coordinates.
 188      * @param x         X position
 189      * @param y         Y position
 190      */
 191     public synchronized void mouseMove(int x, int y) {
 192         peer.mouseMove(x, y);
 193         afterEvent();
 194     }
 195 
 196     /**
 197      * Presses one or more mouse buttons.  The mouse buttons should
 198      * be released using the {@link #mouseRelease(int)} method.
 199      *
 200      * @param buttons the Button mask; a combination of one or more


 291      * However, it is recommended to use {@code InputEvent.BUTTON1_DOWN_MASK},
 292      * {@code InputEvent.BUTTON2_DOWN_MASK},  {@code InputEvent.BUTTON3_DOWN_MASK} instead.
 293      * Either extended {@code _DOWN_MASK} or old {@code _MASK} values
 294      * should be used, but both those models should not be mixed.
 295      * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button
 296      *         and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
 297      * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button
 298      *         that does not exist on the mouse and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java
 299      * @see #mousePress(int)
 300      * @see InputEvent#getMaskForButton(int)
 301      * @see Toolkit#areExtraMouseButtonsEnabled()
 302      * @see java.awt.MouseInfo#getNumberOfButtons()
 303      * @see java.awt.event.MouseEvent
 304      */
 305     public synchronized void mouseRelease(int buttons) {
 306         checkButtonsArgument(buttons);
 307         peer.mouseRelease(buttons);
 308         afterEvent();
 309     }
 310 
 311     private static void checkButtonsArgument(int buttons) {
 312         if ( (buttons|LEGAL_BUTTON_MASK) != LEGAL_BUTTON_MASK ) {
 313             throw new IllegalArgumentException("Invalid combination of button flags");
 314         }
 315     }
 316 
 317     /**
 318      * Rotates the scroll wheel on wheel-equipped mice.
 319      *
 320      * @param wheelAmt  number of "notches" to move the mouse wheel
 321      *                  Negative values indicate movement up/away from the user,
 322      *                  positive values indicate movement down/towards the user.
 323      *
 324      * @since 1.4
 325      */
 326     public synchronized void mouseWheel(int wheelAmt) {
 327         peer.mouseWheel(wheelAmt);
 328         afterEvent();
 329     }
 330 
 331     /**


 350 
 351     /**
 352      * Releases a given key.
 353      * <p>
 354      * Key codes that have more than one physical key associated with them
 355      * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the
 356      * left or right shift key) will map to the left key.
 357      *
 358      * @param   keycode Key to release (e.g. {@code KeyEvent.VK_A})
 359      * @throws  IllegalArgumentException if {@code keycode} is not a
 360      *          valid key
 361      * @see  #keyPress(int)
 362      * @see     java.awt.event.KeyEvent
 363      */
 364     public synchronized void keyRelease(int keycode) {
 365         checkKeycodeArgument(keycode);
 366         peer.keyRelease(keycode);
 367         afterEvent();
 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();


 655      * immediately with the interrupt status set. If the interrupted status is
 656      * already set, this method returns immediately with the interrupt status
 657      * set.
 658      *
 659      * @param  ms time to sleep in milliseconds
 660      * @throws IllegalArgumentException if {@code ms} is not between {@code 0}
 661      *         and {@code 60,000} milliseconds inclusive
 662      */
 663     public void delay(int ms) {
 664         checkDelayArgument(ms);
 665         Thread thread = Thread.currentThread();
 666         if (!thread.isInterrupted()) {
 667             try {
 668                 Thread.sleep(ms);
 669             } catch (final InterruptedException ignored) {
 670                 thread.interrupt(); // Preserve interrupt status
 671             }
 672         }
 673     }
 674 
 675     private static void checkDelayArgument(int ms) {
 676         if (ms < 0 || ms > MAX_DELAY) {
 677             throw new IllegalArgumentException("Delay must be to 0 to 60,000ms");
 678         }
 679     }
 680 
 681     /**
 682      * Waits until all events currently on the event queue have been processed.
 683      * @throws  IllegalThreadStateException if called on the AWT event dispatching thread
 684      */
 685     public synchronized void waitForIdle() {
 686         checkNotDispatchThread();
 687         SunToolkit.flushPendingEvents();
 688         ((SunToolkit) Toolkit.getDefaultToolkit()).realSync();
 689     }
 690 
 691     private static void checkNotDispatchThread() {
 692         if (EventQueue.isDispatchThread()) {
 693             throw new IllegalThreadStateException("Cannot call method from the event dispatcher thread");
 694         }
 695     }
 696 
 697     /**
 698      * Returns a string representation of this Robot.
 699      *
 700      * @return  the string representation.
 701      */
 702     @Override
 703     public synchronized String toString() {
 704         String params = "autoDelay = "+getAutoDelay()+", "+"autoWaitForIdle = "+isAutoWaitForIdle();
 705         return getClass().getName() + "[ " + params + " ]";
 706     }
 707 }
< prev index next >