Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    * Copyright (c) 1999, 2009, 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   import java.lang.reflect.InvocationTargetException;
   37   import sun.awt.ComponentFactory;
   38   import sun.awt.SunToolkit;
   39   import sun.awt.image.SunWritableRaster;
   40   import sun.security.util.SecurityConstants;
   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
   50    * events to the AWT event queue or AWT components in that the
   51    * events are generated in the platform's native input
   52    * queue. For example, <code>Robot.mouseMove</code> will actually move
   53    * the mouse cursor instead of just generating mouse move events.
   54    * <p>
   55    * Note that some platforms require special privileges or extensions
   56    * to access low-level input control. If the current platform configuration
   57    * does not allow input control, an <code>AWTException</code> will be thrown
   58    * when trying to construct Robot objects. For example, X-Window systems
   59    * will throw the exception if the XTEST 2.2 standard extension is not supported
   60    * (or not enabled) by the X server.
   61    * <p>
   62    * Applications that use Robot for purposes other than self-testing should
   63    * handle these error conditions gracefully.
   64    *
   65    * @author      Robi Khan
   66    * @since       1.3
   67    */
   68   public class Robot {
   69       private static final int MAX_DELAY = 60000;
   70       private RobotPeer peer;
   71       private boolean isAutoWaitForIdle = false;
   72       private int autoDelay = 0;
   73       private static int LEGAL_BUTTON_MASK = 0;
   74   
   75       // location of robot's GC, used in mouseMove(), getPixelColor() and captureScreenImage()
   76       private Point gdLoc;
   77   
   78       private DirectColorModel screenCapCM = null;
   79   
   80       /**
   81        * Constructs a Robot object in the coordinate system of the primary screen.
   82        * <p>
   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</code> 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 and createScreenCapture will
  103        * be interpreted as being in the same coordinate system as the
  104        * specified screen. Note that depending on the platform configuration,
  105        * 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        * This constructor is meant for the latter case.
  111        * <p>
  112        * If screen devices are reconfigured such that the coordinate system is
  113        * affected, the behavior of existing Robot objects is undefined.
  114        *
  115        * @param screen    A screen GraphicsDevice indicating the coordinate
  116        *                  system the Robot will operate in.
  117        * @throws  AWTException if the platform configuration does not allow
  118        * low-level input control.  This exception is always thrown when
  119        * GraphicsEnvironment.isHeadless() returns true.
  120        * @throws  IllegalArgumentException if <code>screen</code> is not a screen
  121        *          GraphicsDevice.
  122        * @throws  SecurityException if <code>createRobot</code> permission is not granted
  123        * @see     java.awt.GraphicsEnvironment#isHeadless
  124        * @see     GraphicsDevice
  125        * @see     SecurityManager#checkPermission
  126        * @see     AWTPermission
  127        */
  128       public Robot(GraphicsDevice screen) throws AWTException {
  129           checkIsScreenDevice(screen);
  130           init(screen);
  131       }
  132   
  133       private void init(GraphicsDevice screen) throws AWTException {
  134           checkRobotAllowed();
  135           gdLoc = screen.getDefaultConfiguration().getBounds().getLocation();
  136           Toolkit toolkit = Toolkit.getDefaultToolkit();
  137           if (toolkit instanceof ComponentFactory) {
  138               peer = ((ComponentFactory)toolkit).createRobot(this, screen);
  139               disposer = new RobotDisposer(peer);
  140               sun.java2d.Disposer.addRecord(anchor, disposer);
  141           }
  142           initLegalButtonMask();
  143       }
  144   
  145       private static synchronized void initLegalButtonMask() {
  146           if (LEGAL_BUTTON_MASK != 0) return;
  147   
  148           int tmpMask = 0;
  149           if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){
  150               if (Toolkit.getDefaultToolkit() instanceof SunToolkit) {
  151                   final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
  152                   for (int i = 0; i < buttonsNumber; i++){
  153                       tmpMask |= InputEvent.getMaskForButton(i+1);
  154                   }
  155               }
  156           }
  157           tmpMask |= InputEvent.BUTTON1_MASK|
  158               InputEvent.BUTTON2_MASK|
  159               InputEvent.BUTTON3_MASK|
  160               InputEvent.BUTTON1_DOWN_MASK|
  161               InputEvent.BUTTON2_DOWN_MASK|
  162               InputEvent.BUTTON3_DOWN_MASK;
  163           LEGAL_BUTTON_MASK = tmpMask;
  164       }
  165   
  166       /* determine if the security policy allows Robot's to be created */
  167       private void checkRobotAllowed() {
  168           SecurityManager security = System.getSecurityManager();
  169           if (security != null) {
  170               security.checkPermission(SecurityConstants.AWT.CREATE_ROBOT_PERMISSION);
  171           }
  172       }
  173   
  174       /* check if the given device is a screen device */
  175       private void checkIsScreenDevice(GraphicsDevice device) {
  176           if (device == null || device.getType() != GraphicsDevice.TYPE_RASTER_SCREEN) {
  177               throw new IllegalArgumentException("not a valid screen device");
  178           }
  179       }
  180   
  181       private transient Object anchor = new Object();
  182   
  183       static class RobotDisposer implements sun.java2d.DisposerRecord {
  184           private final RobotPeer peer;
  185           public RobotDisposer(RobotPeer peer) {
  186               this.peer = peer;
  187           }
  188           public void dispose() {
  189               if (peer != null) {
  190                   peer.dispose();
  191               }
  192           }
  193       }
  194   
  195       private transient RobotDisposer disposer;
  196   
  197       /**
  198        * Moves mouse pointer to given screen coordinates.
  199        * @param x         X position
  200        * @param y         Y position
  201        */
  202       public synchronized void mouseMove(int x, int y) {
  203           peer.mouseMove(gdLoc.x + x, gdLoc.y + y);
  204           afterEvent();
  205       }
  206   
  207       /**
  208        * Presses one or more mouse buttons.  The mouse buttons should
  209        * be released using the {@link #mouseRelease(int)} method.
  210        *
  211        * @param buttons the Button mask; a combination of one or more
  212        * mouse button masks.
  213        * <p>
  214        * It is allowed to use only a combination of valid values as a {@code buttons} parameter.
  215        * A valid combination consists of {@code InputEvent.BUTTON1_DOWN_MASK},
  216        * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK}
  217        * and values returned by the
  218        * {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} method.
  219        *
  220        * The valid combination also depends on a
  221        * {@link Toolkit#areExtraMouseButtonsEnabled() Toolkit.areExtraMouseButtonsEnabled()} value as follows:
  222        * <ul>
  223        * <li> If support for extended mouse buttons is
  224        * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
  225        * then it is allowed to use only the following standard button masks:
  226        * {@code InputEvent.BUTTON1_DOWN_MASK}, {@code InputEvent.BUTTON2_DOWN_MASK},
  227        * {@code InputEvent.BUTTON3_DOWN_MASK}.
  228        * <li> If support for extended mouse buttons is
  229        * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java
  230        * then it is allowed to use the standard button masks
  231        * and masks for existing extended mouse buttons, if the mouse has more then three buttons.
  232        * In that way, it is allowed to use the button masks corresponding to the buttons
  233        * in the range from 1 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}.
  234        * <br>
  235        * It is recommended to use the {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)}
  236        * method to obtain the mask for any mouse button by its number.
  237        * </ul>
  238        * <p>
  239        * The following standard button masks are also accepted:
  240        * <ul>
  241        * <li>{@code InputEvent.BUTTON1_MASK}
  242        * <li>{@code InputEvent.BUTTON2_MASK}
  243        * <li>{@code InputEvent.BUTTON3_MASK}
  244        * </ul>
  245        * However, it is recommended to use {@code InputEvent.BUTTON1_DOWN_MASK},
  246        * {@code InputEvent.BUTTON2_DOWN_MASK},  {@code InputEvent.BUTTON3_DOWN_MASK} instead.
  247        * Either extended {@code _DOWN_MASK} or old {@code _MASK} values
  248        * should be used, but both those models should not be mixed.
  249        * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button
  250        *         and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
  251        * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button
  252        *         that does not exist on the mouse and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java
  253        * @see #mouseRelease(int)
  254        * @see InputEvent#getMaskForButton(int)
  255        * @see Toolkit#areExtraMouseButtonsEnabled()
  256        * @see java.awt.MouseInfo#getNumberOfButtons()
  257        * @see java.awt.event.MouseEvent
  258        */
  259       public synchronized void mousePress(int buttons) {
  260           checkButtonsArgument(buttons);
  261           peer.mousePress(buttons);
  262           afterEvent();
  263       }
  264   
  265       /**
  266        * Releases one or more mouse buttons.
  267        *
  268        * @param buttons the Button mask; a combination of one or more
  269        * mouse button masks.
  270        * <p>
  271        * It is allowed to use only a combination of valid values as a {@code buttons} parameter.
  272        * A valid combination consists of {@code InputEvent.BUTTON1_DOWN_MASK},
  273        * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK}
  274        * and values returned by the
  275        * {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} method.
  276        *
  277        * The valid combination also depends on a
  278        * {@link Toolkit#areExtraMouseButtonsEnabled() Toolkit.areExtraMouseButtonsEnabled()} value as follows:
  279        * <ul>
  280        * <li> If the support for extended mouse buttons is
  281        * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
  282        * then it is allowed to use only the following standard button masks:
  283        * {@code InputEvent.BUTTON1_DOWN_MASK}, {@code InputEvent.BUTTON2_DOWN_MASK},
  284        * {@code InputEvent.BUTTON3_DOWN_MASK}.
  285        * <li> If the support for extended mouse buttons is
  286        * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java
  287        * then it is allowed to use the standard button masks
  288        * and masks for existing extended mouse buttons, if the mouse has more then three buttons.
  289        * In that way, it is allowed to use the button masks corresponding to the buttons
  290        * in the range from 1 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}.
  291        * <br>
  292        * It is recommended to use the {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)}
  293        * method to obtain the mask for any mouse button by its number.
  294        * </ul>
  295        * <p>
  296        * The following standard button masks are also accepted:
  297        * <ul>
  298        * <li>{@code InputEvent.BUTTON1_MASK}
  299        * <li>{@code InputEvent.BUTTON2_MASK}
  300        * <li>{@code InputEvent.BUTTON3_MASK}
  301        * </ul>
  302        * However, it is recommended to use {@code InputEvent.BUTTON1_DOWN_MASK},
  303        * {@code InputEvent.BUTTON2_DOWN_MASK},  {@code InputEvent.BUTTON3_DOWN_MASK} instead.
  304        * Either extended {@code _DOWN_MASK} or old {@code _MASK} values
  305        * should be used, but both those models should not be mixed.
  306        * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button
  307        *         and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java
  308        * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button
  309        *         that does not exist on the mouse and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java
  310        * @see #mousePress(int)
  311        * @see InputEvent#getMaskForButton(int)
  312        * @see Toolkit#areExtraMouseButtonsEnabled()
  313        * @see java.awt.MouseInfo#getNumberOfButtons()
  314        * @see java.awt.event.MouseEvent
  315        */
  316       public synchronized void mouseRelease(int buttons) {
  317           checkButtonsArgument(buttons);
  318           peer.mouseRelease(buttons);
  319           afterEvent();
  320       }
  321   
  322       private void checkButtonsArgument(int buttons) {
  323           if ( (buttons|LEGAL_BUTTON_MASK) != LEGAL_BUTTON_MASK ) {
  324               throw new IllegalArgumentException("Invalid combination of button flags");
  325           }
  326       }
  327   
  328       /**
  329        * Rotates the scroll wheel on wheel-equipped mice.
  330        *
  331        * @param wheelAmt  number of "notches" to move the mouse wheel
  332        *                  Negative values indicate movement up/away from the user,
  333        *                  positive values indicate movement down/towards the user.
  334        *
  335        * @since 1.4
  336        */
  337       public synchronized void mouseWheel(int wheelAmt) {
  338           peer.mouseWheel(wheelAmt);
  339           afterEvent();
  340       }
  341   
  342       /**
  343        * Presses a given key.  The key should be released using the
  344        * <code>keyRelease</code> method.
  345        * <p>
  346        * Key codes that have more than one physical key associated with them
  347        * (e.g. <code>KeyEvent.VK_SHIFT</code> could mean either the
  348        * left or right shift key) will map to the left key.
  349        *
  350        * @param   keycode Key to press (e.g. <code>KeyEvent.VK_A</code>)
  351        * @throws  IllegalArgumentException if <code>keycode</code> is not
  352        *          a valid key
  353        * @see     #keyRelease(int)
  354        * @see     java.awt.event.KeyEvent
  355        */
  356       public synchronized void keyPress(int keycode) {
  357           checkKeycodeArgument(keycode);
  358           peer.keyPress(keycode);
  359           afterEvent();
  360       }
  361   
  362       /**
  363        * Releases a given key.
  364        * <p>
  365        * Key codes that have more than one physical key associated with them
  366        * (e.g. <code>KeyEvent.VK_SHIFT</code> could mean either the
  367        * left or right shift key) will map to the left key.
  368        *
  369        * @param   keycode Key to release (e.g. <code>KeyEvent.VK_A</code>)
  370        * @throws  IllegalArgumentException if <code>keycode</code> is not a
  371        *          valid key
  372        * @see  #keyPress(int)
  373        * @see     java.awt.event.KeyEvent
  374        */
  375       public synchronized void keyRelease(int keycode) {
  376           checkKeycodeArgument(keycode);
  377           peer.keyRelease(keycode);
  378           afterEvent();
  379       }
  380   
  381       private void checkKeycodeArgument(int keycode) {
  382           // rather than build a big table or switch statement here, we'll
  383           // just check that the key isn't VK_UNDEFINED and assume that the
  384           // peer implementations will throw an exception for other bogus
  385           // values e.g. -1, 999999
  386           if (keycode == KeyEvent.VK_UNDEFINED) {
  387               throw new IllegalArgumentException("Invalid key code");
  388           }
  389       }
  390   
  391       /**
  392        * Returns the color of a pixel at the given screen coordinates.
  393        * @param   x       X position of pixel
  394        * @param   y       Y position of pixel
  395        * @return  Color of the pixel
  396        */
  397       public synchronized Color getPixelColor(int x, int y) {
  398           Color color = new Color(peer.getRGBPixel(gdLoc.x + x, gdLoc.y + y));
  399           return color;
  400       }
  401   
  402       /**
  403        * Creates an image containing pixels read from the screen.  This image does
  404        * not include the mouse cursor.
  405        * @param   screenRect      Rect to capture in screen coordinates
  406        * @return  The captured image
  407        * @throws  IllegalArgumentException if <code>screenRect</code> width and height are not greater than zero
  408        * @throws  SecurityException if <code>readDisplayPixels</code> permission is not granted
  409        * @see     SecurityManager#checkPermission
  410        * @see     AWTPermission
  411        */
  412       public synchronized BufferedImage createScreenCapture(Rectangle screenRect) {
  413           checkScreenCaptureAllowed();
  414   
  415           // according to the spec, screenRect is relative to robot's GD
  416           Rectangle translatedRect = new Rectangle(screenRect);
  417           translatedRect.translate(gdLoc.x, gdLoc.y);
  418           checkValidRect(translatedRect);
  419   
  420           BufferedImage image;
  421           DataBufferInt buffer;
  422           WritableRaster raster;
  423   
  424           if (screenCapCM == null) {
  425               /*
  426                * Fix for 4285201
  427                * Create a DirectColorModel equivalent to the default RGB ColorModel,
  428                * except with no Alpha component.
  429                */
  430   
  431               screenCapCM = new DirectColorModel(24,
  432                                                  /* red mask */    0x00FF0000,
  433                                                  /* green mask */  0x0000FF00,
  434                                                  /* blue mask */   0x000000FF);
  435           }
  436   
  437           // need to sync the toolkit prior to grabbing the pixels since in some
  438           // cases rendering to the screen may be delayed
  439           Toolkit.getDefaultToolkit().sync();
  440   
  441           int pixels[];
  442           int[] bandmasks = new int[3];
  443   
  444           pixels = peer.getRGBPixels(translatedRect);
  445           buffer = new DataBufferInt(pixels, pixels.length);
  446   
  447           bandmasks[0] = screenCapCM.getRedMask();
  448           bandmasks[1] = screenCapCM.getGreenMask();
  449           bandmasks[2] = screenCapCM.getBlueMask();
  450   
  451           raster = Raster.createPackedRaster(buffer, translatedRect.width, translatedRect.height, translatedRect.width, bandmasks, null);
  452           SunWritableRaster.makeTrackable(buffer);
  453   
  454           image = new BufferedImage(screenCapCM, raster, false, null);
  455   
  456           return image;
  457       }
  458   
  459       private static void checkValidRect(Rectangle rect) {
  460           if (rect.width <= 0 || rect.height <= 0) {
  461               throw new IllegalArgumentException("Rectangle width and height must be > 0");
  462           }
  463       }
  464   
  465       private static void checkScreenCaptureAllowed() {
  466           SecurityManager security = System.getSecurityManager();
  467           if (security != null) {
  468               security.checkPermission(
  469                   SecurityConstants.AWT.READ_DISPLAY_PIXELS_PERMISSION);
  470           }
  471       }
  472   
  473       /*
  474        * Called after an event is generated
  475        */
  476       private void afterEvent() {
  477           autoWaitForIdle();
  478           autoDelay();
  479       }
  480   
  481       /**
  482        * Returns whether this Robot automatically invokes <code>waitForIdle</code>
  483        * after generating an event.
  484        * @return Whether <code>waitForIdle</code> is automatically called
  485        */
  486       public synchronized boolean isAutoWaitForIdle() {
  487           return isAutoWaitForIdle;
  488       }
  489   
  490       /**
  491        * Sets whether this Robot automatically invokes <code>waitForIdle</code>
  492        * after generating an event.
  493        * @param   isOn    Whether <code>waitForIdle</code> is automatically invoked
  494        */
  495       public synchronized void setAutoWaitForIdle(boolean isOn) {
  496           isAutoWaitForIdle = isOn;
  497       }
  498   
  499       /*
  500        * Calls waitForIdle after every event if so desired.
  501        */
  502       private void autoWaitForIdle() {
  503           if (isAutoWaitForIdle) {
  504               waitForIdle();
  505           }
  506       }
  507   
  508       /**
  509        * Returns the number of milliseconds this Robot sleeps after generating an event.
  510        */
  511       public synchronized int getAutoDelay() {
  512           return autoDelay;
  513       }
  514   
  515       /**
  516        * Sets the number of milliseconds this Robot sleeps after generating an event.
  517        * @throws  IllegalArgumentException If <code>ms</code> is not between 0 and 60,000 milliseconds inclusive
  518        */
  519       public synchronized void setAutoDelay(int ms) {
  520           checkDelayArgument(ms);
  521           autoDelay = ms;
  522       }
  523   
  524       /*
  525        * Automatically sleeps for the specified interval after event generated.
  526        */
  527       private void autoDelay() {
  528           delay(autoDelay);
  529       }
  530   
  531       /**
  532        * Sleeps for the specified time.
  533        * To catch any <code>InterruptedException</code>s that occur,
  534        * <code>Thread.sleep()</code> may be used instead.
  535        * @param   ms      time to sleep in milliseconds
  536        * @throws  IllegalArgumentException if <code>ms</code> is not between 0 and 60,000 milliseconds inclusive
  537        * @see     java.lang.Thread#sleep
  538        */
  539       public synchronized void delay(int ms) {
  540           checkDelayArgument(ms);
  541           try {
  542               Thread.sleep(ms);
  543           } catch(InterruptedException ite) {
  544               ite.printStackTrace();
  545           }
  546       }
  547   
  548       private void checkDelayArgument(int ms) {
  549           if (ms < 0 || ms > MAX_DELAY) {
  550               throw new IllegalArgumentException("Delay must be to 0 to 60,000ms");
  551           }
  552       }
  553   
  554       /**
  555        * Waits until all events currently on the event queue have been processed.
  556        * @throws  IllegalThreadStateException if called on the AWT event dispatching thread
  557        */
  558       public synchronized void waitForIdle() {
  559           checkNotDispatchThread();
  560           // post a dummy event to the queue so we know when
  561           // all the events before it have been processed
  562           try {
  563               SunToolkit.flushPendingEvents();
  564               EventQueue.invokeAndWait( new Runnable() {
  565                                               public void run() {
  566                                                   // dummy implementation
  567                                               }
  568                                           } );
  569           } catch(InterruptedException ite) {
  570               System.err.println("Robot.waitForIdle, non-fatal exception caught:");
  571               ite.printStackTrace();
  572           } catch(InvocationTargetException ine) {
  573               System.err.println("Robot.waitForIdle, non-fatal exception caught:");
  574               ine.printStackTrace();
  575           }
  576       }
  577   
  578       private void checkNotDispatchThread() {
  579           if (EventQueue.isDispatchThread()) {
  580               throw new IllegalThreadStateException("Cannot call method from the event dispatcher thread");
  581           }
  582       }
  583   
  584       /**
  585        * Returns a string representation of this Robot.
  586        *
  587        * @return  the string representation.
  588        */
  589       public synchronized String toString() {
  590           String params = "autoDelay = "+getAutoDelay()+", "+"autoWaitForIdle = "+isAutoWaitForIdle();
  591           return getClass().getName() + "[ " + params + " ]";
  592       }
  593   }

Home » openjdk-7 » java » awt » [javadoc | source]