Source Code Cross Referenced for Robot.java in  » 6.0-JDK-Core » AWT » java » awt » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.awt;
027
028        import java.awt.peer.*;
029        import java.awt.image.*;
030        import java.awt.event.*;
031        import java.lang.reflect.InvocationTargetException;
032        import sun.awt.ComponentFactory;
033        import sun.awt.SunToolkit;
034        import sun.security.util.SecurityConstants;
035
036        /**
037         * This class is used to generate native system input events
038         * for the purposes of test automation, self-running demos, and
039         * other applications where control of the mouse and keyboard
040         * is needed. The primary purpose of Robot is to facilitate
041         * automated testing of Java platform implementations.
042         * <p>
043         * Using the class to generate input events differs from posting
044         * events to the AWT event queue or AWT components in that the
045         * events are generated in the platform's native input
046         * queue. For example, <code>Robot.mouseMove</code> will actually move
047         * the mouse cursor instead of just generating mouse move events.
048         * <p>
049         * Note that some platforms require special privileges or extensions 
050         * to access low-level input control. If the current platform configuration
051         * does not allow input control, an <code>AWTException</code> will be thrown
052         * when trying to construct Robot objects. For example, X-Window systems
053         * will throw the exception if the XTEST 2.2 standard extension is not supported
054         * (or not enabled) by the X server.
055         * <p>
056         * Applications that use Robot for purposes other than self-testing should 
057         * handle these error conditions gracefully.
058         *
059         * @version 	1.37, 05/05/07
060         * @author 	Robi Khan
061         * @since   	1.3
062         */
063        public class Robot {
064            private static final int MAX_DELAY = 60000;
065            private RobotPeer peer;
066            private boolean isAutoWaitForIdle = false;
067            private int autoDelay = 0;
068            private static final int LEGAL_BUTTON_MASK = InputEvent.BUTTON1_MASK
069                    | InputEvent.BUTTON2_MASK | InputEvent.BUTTON3_MASK;
070
071            // location of robot's GC, used in mouseMove(), getPixelColor() and captureScreenImage()
072            private Point gdLoc;
073
074            private DirectColorModel screenCapCM = null;
075
076            /**
077             * Constructs a Robot object in the coordinate system of the primary screen.
078             * <p>
079             * 
080             * @throws 	AWTException if the platform configuration does not allow
081             * low-level input control.  This exception is always thrown when
082             * GraphicsEnvironment.isHeadless() returns true
083             * @throws 	SecurityException if <code>createRobot</code> permission is not granted
084             * @see     java.awt.GraphicsEnvironment#isHeadless
085             * @see     SecurityManager#checkPermission
086             * @see 	AWTPermission
087             */
088            public Robot() throws AWTException {
089                if (GraphicsEnvironment.isHeadless()) {
090                    throw new AWTException("headless environment");
091                }
092                init(GraphicsEnvironment.getLocalGraphicsEnvironment()
093                        .getDefaultScreenDevice());
094            }
095
096            /**
097             * Creates a Robot for the given screen device. Coordinates passed
098             * to Robot method calls like mouseMove and createScreenCapture will
099             * be interpreted as being in the same coordinate system as the
100             * specified screen. Note that depending on the platform configuration,
101             * multiple screens may either:
102             * <ul>
103             * <li>share the same coordinate system to form a combined virtual screen</li>
104             * <li>use different coordinate systems to act as independent screens</li>
105             * </ul>
106             * This constructor is meant for the latter case.
107             * <p>
108             * If screen devices are reconfigured such that the coordinate system is
109             * affected, the behavior of existing Robot objects is undefined.
110             *
111             * @param screen	A screen GraphicsDevice indicating the coordinate
112             *			system the Robot will operate in.
113             * @throws 	AWTException if the platform configuration does not allow
114             * low-level input control.  This exception is always thrown when
115             * GraphicsEnvironment.isHeadless() returns true.
116             * @throws  IllegalArgumentException if <code>screen</code> is not a screen
117             *		GraphicsDevice.
118             * @throws 	SecurityException if <code>createRobot</code> permission is not granted
119             * @see     java.awt.GraphicsEnvironment#isHeadless
120             * @see     GraphicsDevice
121             * @see     SecurityManager#checkPermission
122             * @see 	AWTPermission
123             */
124            public Robot(GraphicsDevice screen) throws AWTException {
125                checkIsScreenDevice(screen);
126                init(screen);
127            }
128
129            private void init(GraphicsDevice screen) throws AWTException {
130                checkRobotAllowed();
131                gdLoc = screen.getDefaultConfiguration().getBounds()
132                        .getLocation();
133                Toolkit toolkit = Toolkit.getDefaultToolkit();
134                if (toolkit instanceof  ComponentFactory) {
135                    peer = ((ComponentFactory) toolkit).createRobot(this ,
136                            screen);
137                    disposer = new RobotDisposer(peer);
138                    sun.java2d.Disposer.addRecord(anchor, disposer);
139                }
140            }
141
142            /* determine if the security policy allows Robot's to be created */
143            private void checkRobotAllowed() {
144                SecurityManager security = System.getSecurityManager();
145                if (security != null) {
146                    security
147                            .checkPermission(SecurityConstants.CREATE_ROBOT_PERMISSION);
148                }
149            }
150
151            /* check if the given device is a screen device */
152            private void checkIsScreenDevice(GraphicsDevice device) {
153                if (device == null
154                        || device.getType() != GraphicsDevice.TYPE_RASTER_SCREEN) {
155                    throw new IllegalArgumentException(
156                            "not a valid screen device");
157                }
158            }
159
160            private transient Object anchor = new Object();
161
162            static class RobotDisposer implements  sun.java2d.DisposerRecord {
163                private final RobotPeer peer;
164
165                public RobotDisposer(RobotPeer peer) {
166                    this .peer = peer;
167                }
168
169                public void dispose() {
170                    if (peer != null) {
171                        peer.dispose();
172                    }
173                }
174            }
175
176            private transient RobotDisposer disposer;
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(gdLoc.x + x, gdLoc.y + y);
185                afterEvent();
186            }
187
188            /**
189             * Presses one or more mouse buttons.  The mouse buttons should
190             * be released using the <code>mouseRelease</code> method.
191             *
192             * @param buttons	the Button mask; a combination of one or more
193             * of these flags:
194             * <ul>
195             * <li><code>InputEvent.BUTTON1_MASK</code>
196             * <li><code>InputEvent.BUTTON2_MASK</code>
197             * <li><code>InputEvent.BUTTON3_MASK</code>
198             * </ul>
199             * @throws 	IllegalArgumentException if the button mask is not a
200             *		valid combination
201             * @see #mouseRelease(int)
202             */
203            public synchronized void mousePress(int buttons) {
204                checkButtonsArgument(buttons);
205                peer.mousePress(buttons);
206                afterEvent();
207            }
208
209            /**
210             * Releases one or more mouse buttons. 
211             *
212             * @param buttons	the Button mask; a combination of one or more
213             * of these flags:
214             * <ul>
215             * <li><code>InputEvent.BUTTON1_MASK</code>
216             * <li><code>InputEvent.BUTTON2_MASK</code>
217             * <li><code>InputEvent.BUTTON3_MASK</code>
218             * </ul>
219             * @see #mousePress(int)
220             * @throws 	IllegalArgumentException if the button mask is not a valid
221             *		combination
222             */
223            public synchronized void mouseRelease(int buttons) {
224                checkButtonsArgument(buttons);
225                peer.mouseRelease(buttons);
226                afterEvent();
227            }
228
229            private void checkButtonsArgument(int buttons) {
230                if ((buttons | LEGAL_BUTTON_MASK) != LEGAL_BUTTON_MASK) {
231                    throw new IllegalArgumentException(
232                            "Invalid combination of button flags");
233                }
234            }
235
236            /**
237             * Rotates the scroll wheel on wheel-equipped mice.
238             * 
239             * @param wheelAmt  number of "notches" to move the mouse wheel
240             *                  Negative values indicate movement up/away from the user,
241             *                  positive values indicate movement down/towards the user.
242             *
243             * @since 1.4
244             */
245            public synchronized void mouseWheel(int wheelAmt) {
246                peer.mouseWheel(wheelAmt);
247                afterEvent();
248            }
249
250            /**
251             * Presses a given key.  The key should be released using the
252             * <code>keyRelease</code> method.
253             * <p>
254             * Key codes that have more than one physical key associated with them 
255             * (e.g. <code>KeyEvent.VK_SHIFT</code> could mean either the 
256             * left or right shift key) will map to the left key.
257             *
258             * @param	keycode	Key to press (e.g. <code>KeyEvent.VK_A</code>)
259             * @throws 	IllegalArgumentException if <code>keycode</code> is not
260             *          a valid key
261             * @see     #keyRelease(int)
262             * @see     java.awt.event.KeyEvent
263             */
264            public synchronized void keyPress(int keycode) {
265                checkKeycodeArgument(keycode);
266                peer.keyPress(keycode);
267                afterEvent();
268            }
269
270            /**
271             * Releases a given key.
272             * <p>
273             * Key codes that have more than one physical key associated with them 
274             * (e.g. <code>KeyEvent.VK_SHIFT</code> could mean either the 
275             * left or right shift key) will map to the left key.
276             *
277             * @param	keycode	Key to release (e.g. <code>KeyEvent.VK_A</code>)
278             * @throws 	IllegalArgumentException if <code>keycode</code> is not a
279             *          valid key
280             * @see  #keyPress(int)
281             * @see     java.awt.event.KeyEvent
282             */
283            public synchronized void keyRelease(int keycode) {
284                checkKeycodeArgument(keycode);
285                peer.keyRelease(keycode);
286                afterEvent();
287            }
288
289            private void checkKeycodeArgument(int keycode) {
290                // rather than build a big table or switch statement here, we'll
291                // just check that the key isn't VK_UNDEFINED and assume that the
292                // peer implementations will throw an exception for other bogus
293                // values e.g. -1, 999999
294                if (keycode == KeyEvent.VK_UNDEFINED) {
295                    throw new IllegalArgumentException("Invalid key code");
296                }
297            }
298
299            /**
300             * Returns the color of a pixel at the given screen coordinates.
301             * @param	x	X position of pixel
302             * @param	y	Y position of pixel
303             * @return  Color of the pixel
304             */
305            public synchronized Color getPixelColor(int x, int y) {
306                Color color = new Color(peer.getRGBPixel(gdLoc.x + x, gdLoc.y
307                        + y));
308                return color;
309            }
310
311            /**
312             * Creates an image containing pixels read from the screen.  This image does
313             * not include the mouse cursor.
314             * @param	screenRect	Rect to capture in screen coordinates
315             * @return	The captured image
316             * @throws 	IllegalArgumentException if <code>screenRect</code> width and height are not greater than zero
317             * @throws 	SecurityException if <code>readDisplayPixels</code> permission is not granted
318             * @see     SecurityManager#checkPermission
319             * @see 	AWTPermission
320             */
321            public synchronized BufferedImage createScreenCapture(
322                    Rectangle screenRect) {
323                checkScreenCaptureAllowed();
324
325                // according to the spec, screenRect is relative to robot's GD
326                Rectangle translatedRect = new Rectangle(screenRect);
327                translatedRect.translate(gdLoc.x, gdLoc.y);
328                checkValidRect(translatedRect);
329
330                BufferedImage image;
331                DataBufferInt buffer;
332                WritableRaster raster;
333
334                if (screenCapCM == null) {
335                    /*
336                     * Fix for 4285201 
337                     * Create a DirectColorModel equivalent to the default RGB ColorModel,
338                     * except with no Alpha component.
339                     */
340
341                    screenCapCM = new DirectColorModel(24,
342                    /* red mask */0x00FF0000,
343                    /* green mask */0x0000FF00,
344                    /* blue mask */0x000000FF);
345                }
346
347                int pixels[];
348                int[] bandmasks = new int[3];
349
350                pixels = peer.getRGBPixels(translatedRect);
351                buffer = new DataBufferInt(pixels, pixels.length);
352
353                bandmasks[0] = screenCapCM.getRedMask();
354                bandmasks[1] = screenCapCM.getGreenMask();
355                bandmasks[2] = screenCapCM.getBlueMask();
356
357                raster = Raster.createPackedRaster(buffer,
358                        translatedRect.width, translatedRect.height,
359                        translatedRect.width, bandmasks, null);
360
361                image = new BufferedImage(screenCapCM, raster, false, null);
362
363                return image;
364            }
365
366            private static void checkValidRect(Rectangle rect) {
367                if (rect.width <= 0 || rect.height <= 0) {
368                    throw new IllegalArgumentException(
369                            "Rectangle width and height must be > 0");
370                }
371            }
372
373            private static void checkScreenCaptureAllowed() {
374                SecurityManager security = System.getSecurityManager();
375                if (security != null) {
376                    security
377                            .checkPermission(SecurityConstants.READ_DISPLAY_PIXELS_PERMISSION);
378                }
379            }
380
381            /*
382             * Called after an event is generated
383             */
384            private void afterEvent() {
385                autoWaitForIdle();
386                autoDelay();
387            }
388
389            /**
390             * Returns whether this Robot automatically invokes <code>waitForIdle</code>
391             * after generating an event.
392             * @return Whether <code>waitForIdle</code> is automatically called
393             */
394            public synchronized boolean isAutoWaitForIdle() {
395                return isAutoWaitForIdle;
396            }
397
398            /**
399             * Sets whether this Robot automatically invokes <code>waitForIdle</code>
400             * after generating an event.
401             * @param	isOn	Whether <code>waitForIdle</code> is automatically invoked
402             */
403            public synchronized void setAutoWaitForIdle(boolean isOn) {
404                isAutoWaitForIdle = isOn;
405            }
406
407            /*
408             * Calls waitForIdle after every event if so desired.
409             */
410            private void autoWaitForIdle() {
411                if (isAutoWaitForIdle) {
412                    waitForIdle();
413                }
414            }
415
416            /**
417             * Returns the number of milliseconds this Robot sleeps after generating an event.
418             */
419            public synchronized int getAutoDelay() {
420                return autoDelay;
421            }
422
423            /**
424             * Sets the number of milliseconds this Robot sleeps after generating an event.
425             * @throws 	IllegalArgumentException If <code>ms</code> is not between 0 and 60,000 milliseconds inclusive
426             */
427            public synchronized void setAutoDelay(int ms) {
428                checkDelayArgument(ms);
429                autoDelay = ms;
430            }
431
432            /*
433             * Automatically sleeps for the specified interval after event generated.
434             */
435            private void autoDelay() {
436                delay(autoDelay);
437            }
438
439            /**
440             * Sleeps for the specified time.
441             * To catch any <code>InterruptedException</code>s that occur,
442             * <code>Thread.sleep()</code> may be used instead.
443             * @param	ms	time to sleep in milliseconds
444             * @throws 	IllegalArgumentException if <code>ms</code> is not between 0 and 60,000 milliseconds inclusive
445             * @see     java.lang.Thread#sleep
446             */
447            public synchronized void delay(int ms) {
448                checkDelayArgument(ms);
449                try {
450                    Thread.sleep(ms);
451                } catch (InterruptedException ite) {
452                    ite.printStackTrace();
453                }
454            }
455
456            private void checkDelayArgument(int ms) {
457                if (ms < 0 || ms > MAX_DELAY) {
458                    throw new IllegalArgumentException(
459                            "Delay must be to 0 to 60,000ms");
460                }
461            }
462
463            /**
464             * Waits until all events currently on the event queue have been processed.
465             * @throws 	IllegalThreadStateException if called on the AWT event dispatching thread
466             */
467            public synchronized void waitForIdle() {
468                checkNotDispatchThread();
469                // post a dummy event to the queue so we know when
470                // all the events before it have been processed
471                try {
472                    SunToolkit.flushPendingEvents();
473                    EventQueue.invokeAndWait(new Runnable() {
474                        public void run() {
475                            // dummy implementation
476                        }
477                    });
478                } catch (InterruptedException ite) {
479                    System.err
480                            .println("Robot.waitForIdle, non-fatal exception caught:");
481                    ite.printStackTrace();
482                } catch (InvocationTargetException ine) {
483                    System.err
484                            .println("Robot.waitForIdle, non-fatal exception caught:");
485                    ine.printStackTrace();
486                }
487            }
488
489            private void checkNotDispatchThread() {
490                if (EventQueue.isDispatchThread()) {
491                    throw new IllegalThreadStateException(
492                            "Cannot call method from the event dispatcher thread");
493                }
494            }
495
496            /**
497             * Returns a string representation of this Robot.
498             *
499             * @return	the string representation.
500             */
501            public synchronized String toString() {
502                String params = "autoDelay = " + getAutoDelay() + ", "
503                        + "autoWaitForIdle = " + isAutoWaitForIdle();
504                return getClass().getName() + "[ " + params + " ]";
505            }
506        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.