/* * Copyright (c) 1999, 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import sun.awt.ExtendedKeyCodes; import sun.awt.SunToolkit; import java.awt.AWTException; import java.awt.Robot; import java.awt.GraphicsDevice; import java.awt.Toolkit; import java.awt.Point; import java.awt.MouseInfo; import java.awt.event.InputEvent; /** * ExtendedRobot is a wrapper around java.awt.Robot that provides some convenience * methods. It contains methods that are ought to be moved to {@code java.awt.Robot} * class *

* When using jtreg you would include this class via something like: *

 * {@literal @}library ../../../../lib/testlibrary
 * {@literal @}build ExtendedRobot
 * 
* * @author Dmitriy Ermashov * @since 1.9 */ public class ExtendedRobot extends Robot { private static int DEFAULT_SPEED = 20; // Speed for mouse glide and click private static int DEFAULT_SYNC_DELAY = 500; // Additional delay for realSync private static int DEFAULT_STEP_LENGTH = 2; // Step length (in pixels) for mouse glide private int syncDelay = DEFAULT_SYNC_DELAY; /** * {@inheritDoc} */ public ExtendedRobot() throws AWTException { super(); } /** * {@inheritDoc} */ public ExtendedRobot(GraphicsDevice screen) throws AWTException { super(screen); } /** * Sets the delay length for {@link #waitForIdle()} method * * @param delay Delay value */ public void setSyncDelay(int delay){ this.syncDelay = delay; } /** * Returns delay length for {@link #waitForIdle()} method * * @return Current delay value */ public int getSyncDelay(){ return this.syncDelay; } /** * Clicks mouse button(s) by calling {@link java.awt.Robot#mousePress(int)} * and {@link java.awt.Robot#mouseRelease(int)} methods * * @param buttons the Button mask; a combination of one or more * mouse button masks. * @see #mousePress(int) * @see #mouseRelease(int) */ public void click(int buttons) { mousePress(buttons); waitForIdle(DEFAULT_SPEED); mouseRelease(buttons); waitForIdle(); } /** * Clicks mouse button 1 * * @see #click(int) */ public void click() { click(InputEvent.BUTTON1_DOWN_MASK); } /** * Waits until all events currently on the event queue have been processed. * It uses more advanced method of synchronizing threads unlike {@link java.awt.Robot#waitForIdle()} * * @param delayValue Delay length in milliseconds to wait until realSync been executed */ public synchronized void waitForIdle(int delayValue) { SunToolkit.flushPendingEvents(); ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); delay(delayValue); } /** * Waits until all events currently on the event queue have been processed * with delay {@link #getSyncDelay()} after using {@link sun.awt.SunToolkit#realSync()} call. * It uses more advanced method of synchronizing threads unlike {@link java.awt.Robot#waitForIdle()} * * @see #waitForIdle(int) */ @Override public synchronized void waitForIdle() { waitForIdle(syncDelay); } /** * Move the mouse in multiple steps from where it is * now to the destination coordinates.

* * @param x Destination point x coordinate * @param y Destination point y coordinate * @see #glide(java.awt.Point) */ public void glide(int x, int y) { glide(new Point(x, y)); } /** * Move the mouse in multiple steps from where it is * now to the destination point.

* * @param dest Destination point * @see #glide(java.awt.Point, java.awt.Point) */ public void glide(Point dest) { glide(MouseInfo.getPointerInfo().getLocation(), dest); } /** * Move the mouse in multiple steps from source coordinates * to the destination coordinates.

* * @param fromX Source point x coordinate * @param fromY Source point y coordinate * @param toX Destination point x coordinate * @param toY Destination point y coordinate * @see #glide(java.awt.Point, java.awt.Point) */ public void glide(int fromX, int fromY, int toX, int toY) { glide(new Point(fromX, fromY), new Point(toX, toY)); } /** * Move the mouse in multiple steps from source point to the * destination point with default speed and step length. * * @param src Source point * @param dest Destination point * @see #glide(java.awt.Point, java.awt.Point, int, int) */ public void glide(Point src, Point dest) { glide(src, dest, DEFAULT_STEP_LENGTH, DEFAULT_SPEED); } /** * Move the mouse in multiple steps from source point to the * destination point with given speed and step length. * * @param src Source point * @param dest Destination point * @param stepLength Approximate length of one step * @param speed Delay between steps. * @see #mouseMove(int, int) * @see #delay(int) */ public void glide(Point src, Point dest, int stepLength, int speed) { int stepNum; double tDx, tDy; double dx, dy, ds; double x, y; dx = (dest.getX() - src.getX()); dy = (dest.getY() - src.getY()); ds = Math.sqrt(dx*dx + dy*dy); tDx = dx / ds * stepLength; tDy = dy / ds * stepLength; int stepsCount = (int) ds / stepLength; // Walk the mouse to the destination one step at a time mouseMove(src.x, src.y); for (x = src.x, y = src.y, stepNum = 0; stepNum < stepsCount; stepNum++) { x += tDx; y += tDy; mouseMove((int)x, (int)y); delay(speed); } // Ensure the mouse moves to the right destination. // The steps may have led the mouse to a slightly wrong place. mouseMove(dest.x, dest.y); } /** * Moves mouse pointer to given screen coordinates. * * @param position Point position * @see java.awt.Robot#mouseMove(int, int) */ public synchronized void mouseMove(Point position) { mouseMove(position.x, position.y); } /** * Successively presses and releases a given key. *

* Key codes that have more than one physical key associated with them * (e.g. {@code KeyEvent.VK_SHIFT} could mean either the * left or right shift key) will map to the left key. * * @param kc Key to press (e.g. {@code KeyEvent.VK_A}) * @see java.awt.Robot#keyPress(int) * @see java.awt.Robot#keyRelease(int) * @see java.awt.event.KeyEvent */ public void type(int kc) { keyPress(kc); keyRelease(kc); } /** * Types given character * * @param c Character to be typed (e.g. {@code 'a'}) * @see #type(int) * @see java.awt.event.KeyEvent */ public void type(char c) { type(ExtendedKeyCodes.getExtendedKeyCodeForChar(c)); } /** * Types given array of characters one by one * * @param symbols Array of characters to be typed * @see #type(char) */ public void type(char[] symbols) { for (int i = 0; i < symbols.length; i++) { type(symbols[i]); } } /** * Types given string * * @param s String to be typed * @see #type(char[]) */ public void type(String s) { type(s.toCharArray()); } }