Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/lib/testlibrary/ExtendedRobot.java
38833 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425import sun.awt.ExtendedKeyCodes;26import sun.awt.SunToolkit;2728import java.awt.AWTException;29import java.awt.Robot;30import java.awt.GraphicsDevice;31import java.awt.Toolkit;32import java.awt.Point;33import java.awt.MouseInfo;34import java.awt.event.InputEvent;3536/**37* ExtendedRobot is a subclass of {@link java.awt.Robot}. It provides some convenience methods that are38* ought to be moved to {@link java.awt.Robot} class.39* <p>40* ExtendedRobot uses delay {@link #getSyncDelay()} to make syncing threads with {@link #waitForIdle()}41* more stable. This delay can be set once on creating object and could not be changed throughout object42* lifecycle. Constructor reads vm integer property {@code java.awt.robotdelay} and sets the delay value43* equal to the property value. If the property was not set 500 milliseconds default value is used.44* <p>45* When using jtreg you would include this class via something like:46* <pre>47* {@literal @}library ../../../../lib/testlibrary48* {@literal @}build ExtendedRobot49* </pre>50*51* @author Dmitriy Ermashov52* @since 1.953*/5455public class ExtendedRobot extends Robot {5657private static int DEFAULT_SPEED = 20; // Speed for mouse glide and click58private static int DEFAULT_SYNC_DELAY = 500; // Default Additional delay for waitForIdle()59private static int DEFAULT_STEP_LENGTH = 2; // Step length (in pixels) for mouse glide6061private final int syncDelay = DEFAULT_SYNC_DELAY;6263//TODO: uncomment three lines below after moving functionality to java.awt.Robot64//{65// syncDelay = AccessController.doPrivileged(new GetIntegerAction("java.awt.robotdelay", DEFAULT_SYNC_DELAY));66//}6768/**69* Constructs an ExtendedRobot object in the coordinate system of the primary screen.70*71* @throws AWTException if the platform configuration does not allow low-level input72* control. This exception is always thrown when73* GraphicsEnvironment.isHeadless() returns true74* @throws SecurityException if {@code createRobot} permission is not granted75*76* @see java.awt.GraphicsEnvironment#isHeadless77* @see SecurityManager#checkPermission78* @see java.awt.AWTPermission79*/80public ExtendedRobot() throws AWTException {81super();82}8384/**85* Creates an ExtendedRobot for the given screen device. Coordinates passed86* to ExtendedRobot method calls like mouseMove and createScreenCapture will87* be interpreted as being in the same coordinate system as the specified screen.88* Note that depending on the platform configuration, multiple screens may either:89* <ul>90* <li>share the same coordinate system to form a combined virtual screen</li>91* <li>use different coordinate systems to act as independent screens</li>92* </ul>93* This constructor is meant for the latter case.94* <p>95* If screen devices are reconfigured such that the coordinate system is96* affected, the behavior of existing ExtendedRobot objects is undefined.97*98* @param screen A screen GraphicsDevice indicating the coordinate99* system the Robot will operate in.100* @throws AWTException if the platform configuration does not allow low-level input101* control. This exception is always thrown when102* GraphicsEnvironment.isHeadless() returns true.103* @throws IllegalArgumentException if {@code screen} is not a screen104* GraphicsDevice.105* @throws SecurityException if {@code createRobot} permission is not granted106*107* @see java.awt.GraphicsEnvironment#isHeadless108* @see GraphicsDevice109* @see SecurityManager#checkPermission110* @see java.awt.AWTPermission111*/112public ExtendedRobot(GraphicsDevice screen) throws AWTException {113super(screen);114}115116/**117* Returns delay length for {@link #waitForIdle()} method118*119* @return Current delay value120*121* @see #waitForIdle()122*/123public int getSyncDelay(){ return this.syncDelay; }124125/**126* Clicks mouse button(s) by calling {@link java.awt.Robot#mousePress(int)} and127* {@link java.awt.Robot#mouseRelease(int)} methods128*129*130* @param buttons The button mask; a combination of one or more mouse button masks.131* @throws IllegalArgumentException if the {@code buttons} mask contains the mask for132* extra mouse button and support for extended mouse buttons is133* {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java134* @throws IllegalArgumentException if the {@code buttons} mask contains the mask for135* extra mouse button that does not exist on the mouse and support for extended136* mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled}137* by Java138*139* @see #mousePress(int)140* @see #mouseRelease(int)141* @see InputEvent#getMaskForButton(int)142* @see Toolkit#areExtraMouseButtonsEnabled()143* @see java.awt.event.MouseEvent144*/145public void click(int buttons) {146mousePress(buttons);147waitForIdle(DEFAULT_SPEED);148mouseRelease(buttons);149waitForIdle();150}151152/**153* Clicks mouse button 1154*155* @throws IllegalArgumentException if the {@code buttons} mask contains the mask for156* extra mouse button and support for extended mouse buttons is157* {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java158* @throws IllegalArgumentException if the {@code buttons} mask contains the mask for159* extra mouse button that does not exist on the mouse and support for extended160* mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled}161* by Java162*163* @see #click(int)164*/165public void click() {166click(InputEvent.BUTTON1_DOWN_MASK);167}168169/**170* Waits until all events currently on the event queue have been processed with given171* delay after syncing threads. It uses more advanced method of synchronizing threads172* unlike {@link java.awt.Robot#waitForIdle()}173*174* @param delayValue Additional delay length in milliseconds to wait until thread175* sync been completed176* @throws sun.awt.SunToolkit.IllegalThreadException if called on the AWT event177* dispatching thread178*/179public synchronized void waitForIdle(int delayValue) {180SunToolkit.flushPendingEvents();181((SunToolkit) Toolkit.getDefaultToolkit()).realSync();182delay(delayValue);183}184185/**186* Waits until all events currently on the event queue have been processed with delay187* {@link #getSyncDelay()} after syncing threads. It uses more advanced method of188* synchronizing threads unlike {@link java.awt.Robot#waitForIdle()}189*190* @throws sun.awt.SunToolkit.IllegalThreadException if called on the AWT event191* dispatching thread192*193* @see #waitForIdle(int)194*/195@Override196public synchronized void waitForIdle() {197waitForIdle(syncDelay);198}199200/**201* Move the mouse in multiple steps from where it is202* now to the destination coordinates.203*204* @param x Destination point x coordinate205* @param y Destination point y coordinate206*207* @see #glide(int, int, int, int)208*/209public void glide(int x, int y) {210Point p = MouseInfo.getPointerInfo().getLocation();211glide(p.x, p.y, x, y);212}213214/**215* Move the mouse in multiple steps from where it is216* now to the destination point.217*218* @param dest Destination point219*220* @see #glide(int, int)221*/222public void glide(Point dest) {223glide(dest.x, dest.y);224}225226/**227* Move the mouse in multiple steps from source coordinates228* to the destination coordinates.229*230* @param fromX Source point x coordinate231* @param fromY Source point y coordinate232* @param toX Destination point x coordinate233* @param toY Destination point y coordinate234*235* @see #glide(int, int, int, int, int, int)236*/237public void glide(int fromX, int fromY, int toX, int toY) {238glide(fromX, fromY, toX, toY, DEFAULT_STEP_LENGTH, DEFAULT_SPEED);239}240241/**242* Move the mouse in multiple steps from source point to the243* destination point with default speed and step length.244*245* @param src Source point246* @param dest Destination point247*248* @see #glide(int, int, int, int, int, int)249*/250public void glide(Point src, Point dest) {251glide(src.x, src.y, dest.x, dest.y, DEFAULT_STEP_LENGTH, DEFAULT_SPEED);252}253254/**255* Move the mouse in multiple steps from source point to the256* destination point with given speed and step length.257*258* @param srcX Source point x cordinate259* @param srcY Source point y cordinate260* @param destX Destination point x cordinate261* @param destY Destination point y cordinate262* @param stepLength Approximate length of one step263* @param speed Delay between steps.264*265* @see #mouseMove(int, int)266* @see #delay(int)267*/268public void glide(int srcX, int srcY, int destX, int destY, int stepLength, int speed) {269int stepNum;270double tDx, tDy;271double dx, dy, ds;272double x, y;273274dx = (destX - srcX);275dy = (destY - srcY);276ds = Math.sqrt(dx*dx + dy*dy);277278tDx = dx / ds * stepLength;279tDy = dy / ds * stepLength;280281int stepsCount = (int) ds / stepLength;282283// Walk the mouse to the destination one step at a time284mouseMove(srcX, srcY);285286for (x = srcX, y = srcY, stepNum = 0;287stepNum < stepsCount;288stepNum++) {289x += tDx;290y += tDy;291mouseMove((int)x, (int)y);292delay(speed);293}294295// Ensure the mouse moves to the right destination.296// The steps may have led the mouse to a slightly wrong place.297mouseMove(destX, destY);298}299300/**301* Moves mouse pointer to given screen coordinates.302*303* @param position Target position304*305* @see java.awt.Robot#mouseMove(int, int)306*/307public synchronized void mouseMove(Point position) {308mouseMove(position.x, position.y);309}310311312/**313* Emulate native drag and drop process using {@code InputEvent.BUTTON1_DOWN_MASK}.314* The method successively moves mouse cursor to point with coordinates315* ({@code fromX}, {@code fromY}), presses mouse button 1, drag mouse to316* point with coordinates ({@code toX}, {@code toY}) and releases mouse317* button 1 at last.318*319* @param fromX Source point x coordinate320* @param fromY Source point y coordinate321* @param toX Destination point x coordinate322* @param toY Destination point y coordinate323*324* @see #mousePress(int)325* @see #glide(int, int, int, int)326*/327public void dragAndDrop(int fromX, int fromY, int toX, int toY){328mouseMove(fromX, fromY);329mousePress(InputEvent.BUTTON1_DOWN_MASK);330waitForIdle();331glide(toX, toY);332mouseRelease(InputEvent.BUTTON1_DOWN_MASK);333waitForIdle();334}335336/**337* Emulate native drag and drop process using {@code InputEvent.BUTTON1_DOWN_MASK}.338* The method successively moves mouse cursor to point {@code from},339* presses mouse button 1, drag mouse to point {@code to} and releases340* mouse button 1 at last.341*342* @param from Source point343* @param to Destination point344*345* @see #mousePress(int)346* @see #glide(int, int, int, int)347* @see #dragAndDrop(int, int, int, int)348*/349public void dragAndDrop(Point from, Point to){350dragAndDrop(from.x, from.y, to.x, to.y);351}352353/**354* Successively presses and releases a given key.355* <p>356* Key codes that have more than one physical key associated with them357* (e.g. {@code KeyEvent.VK_SHIFT} could mean either the358* left or right shift key) will map to the left key.359*360* @param keycode Key to press (e.g. {@code KeyEvent.VK_A})361* @throws IllegalArgumentException if {@code keycode} is not362* a valid key363*364* @see java.awt.Robot#keyPress(int)365* @see java.awt.Robot#keyRelease(int)366* @see java.awt.event.KeyEvent367*/368public void type(int keycode) {369keyPress(keycode);370waitForIdle(DEFAULT_SPEED);371keyRelease(keycode);372waitForIdle(DEFAULT_SPEED);373}374375/**376* Types given character377*378* @param c Character to be typed (e.g. {@code 'a'})379*380* @see #type(int)381* @see java.awt.event.KeyEvent382*/383public void type(char c) {384type(ExtendedKeyCodes.getExtendedKeyCodeForChar(c));385}386387/**388* Types given array of characters one by one389*390* @param symbols Array of characters to be typed391*392* @see #type(char)393*/394public void type(char[] symbols) {395for (int i = 0; i < symbols.length; i++) {396type(symbols[i]);397}398}399400/**401* Types given string402*403* @param s String to be typed404*405* @see #type(char[])406*/407public void type(String s) {408type(s.toCharArray());409}410}411412413