--- /dev/null 2014-03-28 17:53:11.000000000 +0400 +++ new/test/lib/testlibrary/RobotWrapper.java 2014-03-28 17:53:10.811367800 +0400 @@ -0,0 +1,360 @@ +/* + * 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.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; +import java.awt.event.KeyEvent; + +/** + * RobotWrapper is a wrapper around java.awt.Robot that provides some convenience + * methods. It contains methods that are ought to be moved to java.awt.Robot + * class + *

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

+ * {@literal @}library ../../../regtesthelpers
+ * {@literal @}build RobotWrapper
+ * 
+ * + * @author Dmitriy Ermashov, David Herron + * @since 1.9 + */ + +public class RobotWrapper extends Robot { + + private static int DEFAULT_SPEED = 20; // Speed for mouse glide and click + private static int DEFAULT_SYNC_DELAY = 100; // 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 RobotWrapper() throws AWTException { + super(); + } + + /** + * {@inheritDoc} + */ + public RobotWrapper(GraphicsDevice screen) throws AWTException { + super(screen); + } + + /** + * Sets the delay length for waitForIdle() method + * + * @param delay Delay value + */ + public void setSyncDelay(int delay){ + this.syncDelay = delay; + } + + /** + * Returns delay length for waitForIdle() method + * + * @return Current delay value + */ + public int setSyncDelay(){ + return this.syncDelay; + } + + /** + * Clicks mouse button(s) by calling java.awt.Robot.mousePress(int) + * and 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(); + mouseRelease(buttons); + waitForIdle(); + } + + /** + * Clicks mouse button 1 with the default pause between Press and Release. + * + * @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 java.awt.Robot#waitForIdle() + */ + public synchronized void waitForIdle() { + SunToolkit.flushPendingEvents(); + ((SunToolkit) Toolkit.getDefaultToolkit()).realSync(); + delay(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. 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. 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. 'a') + * @see #type(int) + * @see java.awt.event.KeyEvent + */ + public void type(char c) { + try { + if (Character.isLetter(c)) { + boolean low = Character.isLowerCase(c); + if (!low) + keyPress(KeyEvent.VK_SHIFT); + type(Character.getNumericValue(c) + 55); + if (!low) + keyRelease(KeyEvent.VK_SHIFT); + return; + } + if (Character.isDigit(c)) { + switch (c) { + case '0': type(KeyEvent.VK_0); break; + case '1': type(KeyEvent.VK_1); break; + case '2': type(KeyEvent.VK_2); break; + case '3': type(KeyEvent.VK_3); break; + case '4': type(KeyEvent.VK_4); break; + case '5': type(KeyEvent.VK_5); break; + case '6': type(KeyEvent.VK_6); break; + case '7': type(KeyEvent.VK_7); break; + case '8': type(KeyEvent.VK_8); break; + case '9': type(KeyEvent.VK_9); break; + } + return; + } + if (Character.isWhitespace(c)) { + switch (c) { + case '\t': type(KeyEvent.VK_TAB); break; + case '\n': type(KeyEvent.VK_ENTER); break; + case '\f': + keyPress(KeyEvent.VK_CONTROL); + type(KeyEvent.VK_L); + keyRelease(KeyEvent.VK_CONTROL); + break; + case ' ': type(KeyEvent.VK_SPACE); break; + } + return; + } + if (Character.isISOControl(c)) { + keyPress(KeyEvent.VK_CONTROL); + type(c + ' '); + keyRelease(KeyEvent.VK_CONTROL); + return; + } + switch (c) { + case '!': type(KeyEvent.VK_EXCLAMATION_MARK); return; + case '@': type(KeyEvent.VK_AT); return; + case '#': type(KeyEvent.VK_NUMBER_SIGN); return; + case '$': type(KeyEvent.VK_DOLLAR); return; + case '%': break; + case '^': type(KeyEvent.VK_CIRCUMFLEX); return; + case '&': type(KeyEvent.VK_AMPERSAND); return; + case '*': type(KeyEvent.VK_ASTERISK); return; + case '(': type(KeyEvent.VK_LEFT_PARENTHESIS); return; + case ')': type(KeyEvent.VK_RIGHT_PARENTHESIS); return; + case '-': type(KeyEvent.VK_MINUS); return; + case '_': type(KeyEvent.VK_UNDERSCORE); return; + case '=': type(KeyEvent.VK_EQUALS); return; + case '+': type(KeyEvent.VK_PLUS); return; + case '\\': type(KeyEvent.VK_BACK_SLASH); return; + case '|': break; + case '`': type(KeyEvent.VK_BACK_QUOTE); return; + case '~': break; + case '[': type(KeyEvent.VK_OPEN_BRACKET); return; + case '{': type(KeyEvent.VK_BRACELEFT); return; + case '}': type(KeyEvent.VK_BRACERIGHT); return; + case ']': type(KeyEvent.VK_CLOSE_BRACKET); return; + case ';': type(KeyEvent.VK_SEMICOLON); return; + case ':': type(KeyEvent.VK_COLON); return; + case '\'': type(KeyEvent.VK_QUOTE); return; + case '"': type(KeyEvent.VK_QUOTEDBL); return; + case ',': type(KeyEvent.VK_COMMA); return; + case '<': type(KeyEvent.VK_LESS); return; + case '.': type(KeyEvent.VK_PERIOD); return; + case '>': type(KeyEvent.VK_GREATER); return; + case '/': type(KeyEvent.VK_SLASH); return; + case '?': break; + } + type(Character.getNumericValue(c) + 55); + } catch (Exception e) { + System.err.println("ProbeRobot.type: caught " + e.toString() + + " for character '" + 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()); + } +}