OSDN Git Service

libjava/
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / awt / Robot.java
1 /* Robot.java -- a native input event generator
2    Copyright (C) 2004, 2005  Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package java.awt;
40
41 import gnu.java.awt.ClasspathToolkit;
42
43 import java.lang.reflect.InvocationTargetException;
44 import java.awt.event.InputEvent;
45 import java.awt.image.BufferedImage;
46 import java.awt.peer.RobotPeer;
47
48 /**
49  * The Robot class is used to simulate user interaction with graphical
50  * programs.  It can generate native windowing system input events and
51  * retrieve image data from the current screen.  Robot is used to test
52  * the AWT and Swing library implementations; it can also be used to
53  * create self-running demo programs.
54  *
55  * Since Robot generates native windowing system events, rather than
56  * simply inserting {@link AWTEvent}s on the AWT event queue, its use
57  * is not restricted to Java programs.  It can be used to
58  * programatically drive any graphical application.
59  *
60  * This implementation requires an X server that supports the XTest
61  * extension.
62  *
63  * @author Thomas Fitzsimmons (fitzsim@redhat.com)
64  *
65  * @since 1.3
66  */
67 public class Robot
68 {
69   private boolean waitForIdle;
70   private int autoDelay;
71   private RobotPeer peer;
72
73   /**
74    * Construct a Robot object that operates on the default screen.
75    *
76    * @exception AWTException if GraphicsEnvironment.isHeadless()
77    * returns true or if the X server does not support the XTest
78    * extension
79    * @exception SecurityException if createRobot permission is not
80    * granted
81    */
82   public Robot () throws AWTException
83   {
84     if (GraphicsEnvironment.isHeadless ())
85       throw new AWTException ("Robot: headless graphics environment");
86
87     SecurityManager sm = System.getSecurityManager ();
88     if (sm != null)
89       sm.checkPermission (new AWTPermission ("createRobot"));
90
91     ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit ();
92
93     // createRobot will throw AWTException if XTest is not supported.
94     peer = tk.createRobot (GraphicsEnvironment.getLocalGraphicsEnvironment ()
95                            .getDefaultScreenDevice ());
96   }
97
98   /**
99    * Construct a Robot object that operates on the specified screen.
100    *
101    * @exception AWTException if GraphicsEnvironment.isHeadless()
102    * returns true or if the X server does not support the XTest
103    * extension
104    * @exception IllegalArgumentException if screen is not a screen
105    * GraphicsDevice
106    * @exception SecurityException if createRobot permission is not
107    * granted
108    */
109   public Robot (GraphicsDevice screen) throws AWTException
110   {
111     if (GraphicsEnvironment.isHeadless ())
112       throw new AWTException ("Robot: headless graphics environment");
113
114     if (screen.getType () != GraphicsDevice.TYPE_RASTER_SCREEN)
115       throw new IllegalArgumentException ("Robot: graphics"
116                                           + " device is not a screen");
117
118     SecurityManager sm = System.getSecurityManager ();
119     if (sm != null)
120       sm.checkPermission (new AWTPermission ("createRobot"));
121
122     ClasspathToolkit tk = (ClasspathToolkit) Toolkit.getDefaultToolkit ();
123
124     // createRobot will throw AWTException if XTest is not supported.
125     peer = tk.createRobot (screen);
126   }
127
128   /**
129    * Move the mouse pointer to absolute coordinates (x, y).
130    *
131    * @param x the destination x coordinate
132    * @param y the destination y coordinate
133    */
134   public void mouseMove(int x, int y)
135   {
136     peer.mouseMove (x, y);
137
138     if (waitForIdle)
139       waitForIdle ();
140
141     if (autoDelay > 0)
142       delay (autoDelay);
143   }
144
145   /**
146    * Press one or more mouse buttons.
147    *
148    * @param buttons the buttons to press; a bitmask of one or more of
149    * these {@link InputEvent} fields:
150    *
151    * <ul>
152    *   <li>BUTTON1_MASK</li>
153    *   <li>BUTTON2_MASK</li>
154    *   <li>BUTTON3_MASK</li>
155    * </ul>
156    *
157    * @exception IllegalArgumentException if the button mask is invalid
158    */
159   public void mousePress (int buttons)
160   {
161     if ((buttons & InputEvent.BUTTON1_MASK) == 0
162         && (buttons & InputEvent.BUTTON2_MASK) == 0
163         && (buttons & InputEvent.BUTTON3_MASK) == 0)
164       throw new IllegalArgumentException ("Robot: mousePress:"
165                                           + " invalid button mask");
166
167     peer.mousePress (buttons);
168
169     if (waitForIdle)
170       waitForIdle ();
171
172     if (autoDelay > 0)
173       delay (autoDelay);
174   }
175
176   /**
177    * Release one or more mouse buttons.
178    *
179    * @param buttons the buttons to release; a bitmask of one or more
180    * of these {@link InputEvent} fields:
181    *
182    * <ul>
183    *   <li>BUTTON1_MASK</li>
184    *   <li>BUTTON2_MASK</li>
185    *   <li>BUTTON3_MASK</li>
186    * </ul>
187    *
188    * @exception IllegalArgumentException if the button mask is invalid
189    */
190   public void mouseRelease(int buttons)
191   {
192     if ((buttons & InputEvent.BUTTON1_MASK) == 0
193         && (buttons & InputEvent.BUTTON2_MASK) == 0
194         && (buttons & InputEvent.BUTTON3_MASK) == 0)
195       throw new IllegalArgumentException ("Robot: mouseRelease:"
196                                           + " invalid button mask");
197
198     peer.mouseRelease (buttons);
199
200     if (waitForIdle)
201       waitForIdle ();
202
203     if (autoDelay > 0)
204       delay (autoDelay);
205   }
206
207   /**
208    * Rotate the mouse scroll wheel.
209    *
210    * @param wheelAmt number of steps to rotate mouse wheel.  negative
211    * to rotate wheel up (away from the user), positive to rotate wheel
212    * down (toward the user).
213    *
214    * @since 1.4
215    */
216   public void mouseWheel (int wheelAmt)
217   {
218     peer.mouseWheel (wheelAmt);
219
220     if (waitForIdle)
221       waitForIdle ();
222
223     if (autoDelay > 0)
224       delay (autoDelay);
225   }
226
227   /**
228    * Press a key.
229    *
230    * @param keycode key to press, a {@link java.awt.event.KeyEvent} VK_ constant
231    *
232    * @exception IllegalArgumentException if keycode is not a valid key
233    */
234   public void keyPress (int keycode)
235   {
236     peer.keyPress (keycode);
237
238     if (waitForIdle)
239       waitForIdle ();
240
241     if (autoDelay > 0)
242       delay (autoDelay);
243   }
244
245   /**
246    * Release a key.
247    *
248    * @param keycode key to release, a {@link java.awt.event.KeyEvent} VK_ 
249    *                constant
250    *
251    * @exception IllegalArgumentException if keycode is not a valid key
252    */
253   public void keyRelease (int keycode)
254   {
255     peer.keyRelease (keycode);
256
257     if (waitForIdle)
258       waitForIdle ();
259
260     if (autoDelay > 0)
261       delay (autoDelay);
262   }
263
264   /**
265    * Return the color of the pixel at the given screen coordinates.
266    *
267    * @param x the x coordinate of the pixel
268    * @param y the y coordinate of the pixel
269    *
270    * @return the Color of the pixel at screen coodinates <code>(x, y)</code>
271    */
272   public Color getPixelColor (int x, int y)
273   {
274     return new Color (peer.getRGBPixel (x, y));
275   }
276
277   /**
278    * Create an image containing pixels read from the screen.  The
279    * image does not include the mouse pointer.
280    *
281    * @param screenRect the rectangle of pixels to capture, in screen
282    * coordinates
283    *
284    * @return a BufferedImage containing the requested pixels
285    *
286    * @exception IllegalArgumentException if requested width and height
287    * are not both greater than zero
288    * @exception SecurityException if readDisplayPixels permission is
289    * not granted
290    */
291   public BufferedImage createScreenCapture (Rectangle screenRect)
292   {
293     if (screenRect.width <= 0)
294       throw new IllegalArgumentException ("Robot: capture width is <= 0");
295
296     if (screenRect.height <= 0)
297       throw new IllegalArgumentException ("Robot: capture height is <= 0");
298
299     SecurityManager sm = System.getSecurityManager ();
300     if (sm != null)
301       sm.checkPermission (new AWTPermission ("readDisplayPixels"));
302
303     int[] pixels = peer.getRGBPixels (screenRect);
304
305     BufferedImage bufferedImage =
306       new BufferedImage (screenRect.width, screenRect.height,
307                          BufferedImage.TYPE_INT_ARGB);
308
309     bufferedImage.setRGB (0, 0, screenRect.width, screenRect.height,
310                           pixels, 0, screenRect.width);
311
312     return bufferedImage;
313   }
314
315   /**
316    * Check if this Robot automatically calls {@link #waitForIdle()} after
317    * generating an event.
318    *
319    * @return true if waitForIdle is automatically called
320    */
321   public boolean isAutoWaitForIdle ()
322   {
323     return waitForIdle;
324   }
325
326   /**
327    * Set whether or not this Robot automatically calls {@link
328    * #waitForIdle()} after generating an event.
329    *
330    * @param isOn true if waitForIdle should be called automatically
331    */
332   public void setAutoWaitForIdle (boolean isOn)
333   {
334     waitForIdle = isOn;
335   }
336
337   /**
338    * Retrieve the length of time this Robot sleeps after generating an
339    * event.
340    *
341    * @return the length of time in milliseconds
342    */
343   public int getAutoDelay ()
344   {
345     return autoDelay;
346   }
347
348   /**
349    * Set the length of time this Robot sleeps after generating an
350    * event.
351    *
352    * @param ms the length of time in milliseconds
353    *
354    * @exception IllegalArgumentException if ms is not between 0 and
355    * 60,000 milliseconds inclusive
356    */
357   public void setAutoDelay (int ms)
358   {
359     if (ms <= 0 || ms >= 60000)
360       throw new IllegalArgumentException ("Robot: delay length out-of-bounds");
361
362     autoDelay = ms;
363   }
364
365   /**
366    * Sleep for a specified length of time.
367    *
368    * @param ms the length of time in milliseconds
369    *
370    * @exception IllegalArgumentException if ms is not between 0 and
371    * 60,000 milliseconds inclusive
372    */
373   public void delay (int ms)
374   {
375     if (ms < 0 || ms > 60000)
376       throw new IllegalArgumentException ("Robot: delay length out-of-bounds");
377
378     try
379       {
380         Thread.sleep (ms);
381       }
382     catch (InterruptedException e)
383       {
384         System.err.println ("Robot: delay interrupted");
385       }
386   }
387
388   /**
389    * Wait until all events currently on the event queue have been
390    * dispatched.
391    */
392   public void waitForIdle ()
393   {
394     if (EventQueue.isDispatchThread ())
395       throw new IllegalThreadStateException ("Robot: waitForIdle called from "
396                                              + "the event dispatch thread");
397
398     try
399       {
400         EventQueue.invokeAndWait (new Runnable () { public void run () { } });
401       }
402     catch (InterruptedException e)
403       {
404         System.err.println ("Robot: waitForIdle interrupted");
405       }
406     catch (InvocationTargetException e)
407       {
408         System.err.println ("Robot: waitForIdle cannot invoke target");
409       }
410   }
411
412   /**
413    * Return a string representation of this Robot.
414    *
415    * @return a string representation
416    */
417   public String toString ()
418   {
419     return getClass ().getName ()
420         + "[ autoDelay = " + autoDelay + ", autoWaitForIdle = "
421         + waitForIdle + " ]";
422   }
423 }