1 /* 2 * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /** 27 * JRobot is a wrapper around java.awt.Robot that provides some convenience 28 * methods. 29 * <p>When using jtreg you would include this class via something like: 30 * <pre> 31 * @library ../../../regtesthelpers 32 * @build JRobot 33 * </pre> 34 * 35 */ 36 import java.awt.AWTException; 37 import java.awt.Component; 38 import java.awt.Dimension; 39 import java.awt.EventQueue; 40 import java.awt.Point; 41 import java.awt.Rectangle; 42 import java.awt.event.InputEvent; 43 import java.awt.event.KeyEvent; 44 import javax.swing.SwingUtilities; 45 46 public class JRobot extends java.awt.Robot { 47 private static int DEFAULT_DELAY = 550; 48 private static int INTERNAL_DELAY = 250; 49 50 private int delay; 51 private boolean delaysEnabled; 52 53 protected JRobot(boolean enableDelays) throws AWTException { 54 super(); 55 delaysEnabled = enableDelays; 56 setAutoWaitForIdle(enableDelays); 57 if (enableDelays) { 58 setAutoDelay(INTERNAL_DELAY); 59 setDelay(DEFAULT_DELAY); 60 } 61 } 62 63 /** 64 * Return a JRobot. Delays are enabled by default. 65 * @return a JRobot 66 */ 67 public static JRobot getRobot() { 68 return getRobot(true); 69 } 70 71 /** 72 * Create a JRobot. The parameter controls whether delays are enabled. 73 * @param enableDelays controls whether delays are enabled. 74 * @return a JRobot 75 */ 76 public static JRobot getRobot(boolean enableDelays) { 77 JRobot robot = null; 78 try { 79 robot = new JRobot(enableDelays); 80 } catch (AWTException e) { 81 System.err.println("Coudn't create Robot, details below"); 82 throw new Error(e); 83 } 84 return robot; 85 } 86 87 /** 88 * Press and release a key. 89 * @param keycode which key to press. For example, KeyEvent.VK_DOWN 90 */ 91 public void hitKey(int keycode) { 92 keyPress(keycode); 93 keyRelease(keycode); 94 delay(); 95 } 96 97 /** 98 * Press and release a key with modifiers. 99 * @param keys keys to press. Keys are pressed in order they are passed as 100 * parameters to this method. All keys except the last one are considered 101 * modifiers. For example, to press Ctrl+Shift+T, call: 102 * hitKey(KeyEvent.VK_CONTROL, KeyEvent.VK_SHIFT, KeyEvent.VK_T); 103 */ 104 public void hitKey(int... keys) { 105 for (int i = 0; i < keys.length; i++) { 106 keyPress(keys[i]); 107 } 108 109 for (int i = keys.length - 1; i >= 0; i--) { 110 keyRelease(keys[i]); 111 } 112 delay(); 113 } 114 115 /** 116 * Move mouse cursor to the center of the Component. 117 * @param c Component the mouse is placed over 118 */ 119 public void moveMouseTo(Component c) { 120 Point p = c.getLocationOnScreen(); 121 Dimension size = c.getSize(); 122 p.x += size.width / 2; 123 p.y += size.height / 2; 124 mouseMove(p.x, p.y); 125 delay(); 126 } 127 128 /** 129 * Move mouse smoothly from (x0, y0) to (x1, y1). 130 */ 131 public void glide(int x0, int y0, int x1, int y1) { 132 float dmax = (float)Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0)); 133 float dx = (x1 - x0) / dmax; 134 float dy = (y1 - y0) / dmax; 135 136 mouseMove(x0, y0); 137 for (int i=1; i<=dmax; i++) { 138 mouseMove((int)(x0 + dx*i), (int)(y0 + dy*i)); 139 } 140 delay(); 141 } 142 143 /** 144 * Perform a mouse click, i.e. press and release mouse button(s). 145 * @param buttons mouse button(s). 146 * For example, MouseEvent.BUTTON1_MASK 147 */ 148 public void clickMouse(int buttons) { 149 mousePress(buttons); 150 mouseRelease(buttons); 151 delay(); 152 } 153 154 /** 155 * Perform a click with the first mouse button. 156 */ 157 public void clickMouse() { 158 clickMouse(InputEvent.BUTTON1_MASK); 159 } 160 161 /** 162 * Click in the center of the given Component 163 * @param c the Component to click on 164 * @param buttons mouse button(s). 165 */ 166 public void clickMouseOn(Component c, int buttons) { 167 moveMouseTo(c); 168 clickMouse(buttons); 169 } 170 171 /** 172 * Click the first mouse button in the center of the given Component 173 * @param c the Component to click on 174 */ 175 public void clickMouseOn(Component c) { 176 clickMouseOn(c, InputEvent.BUTTON1_MASK); 177 } 178 179 /** 180 * Return whether delays are enabled 181 * @return whether delays are enabled 182 */ 183 public boolean getDelaysEnabled() { 184 return delaysEnabled; 185 } 186 187 /** 188 * Delay execution by delay milliseconds 189 */ 190 public void delay() { 191 delay(delay); 192 } 193 194 /** 195 * Return the delay amount, in milliseconds 196 */ 197 public int getDelay() { 198 return delay; 199 } 200 201 /** 202 * Set the delay amount, in milliseconds 203 */ 204 public void setDelay(int delay) { 205 this.delay = delay; 206 } 207 208 /** 209 * Waits until all events currently on the event queue have been processed. 210 * Does nothing if called on EDT 211 */ 212 public synchronized void waitForIdle() { 213 if (!EventQueue.isDispatchThread()) { 214 super.waitForIdle(); 215 } 216 } 217 218 /** 219 * Calculate the center of the Rectangle passed, and return them 220 * in a Point object. 221 * @param r a non-null Rectangle 222 * @return a new Point object containing coordinates of r's center 223 */ 224 public Point centerOf(Rectangle r) { 225 return new Point(r.x + r.width / 2, r.y + r.height / 2); 226 } 227 228 /** 229 * Calculate the center of the Rectangle passed, and store it in p. 230 * @param r a non-null Rectangle 231 * @param p a non-null Point that receives coordinates of r's center 232 * @return p 233 */ 234 public Point centerOf(Rectangle r, Point p) { 235 p.x = r.x + r.width / 2; 236 p.y = r.y + r.height / 2; 237 return p; 238 } 239 240 /** 241 * Convert a rectangle from coordinate system of Component c to 242 * screen coordinate system. 243 * @param r a non-null Rectangle 244 * @param c a Component whose coordinate system is used for conversion 245 */ 246 public void convertRectToScreen(Rectangle r, Component c) { 247 Point p = new Point(r.x, r.y); 248 SwingUtilities.convertPointToScreen(p, c); 249 r.x = p.x; 250 r.y = p.y; 251 } 252 253 /** 254 * Compares two rectangles pixel-by-pixel. 255 * @param r0 the first area 256 * @param r1 the second area 257 * return true if all pixels in the two areas are identical 258 */ 259 public boolean compareRects(Rectangle r0, Rectangle r1) { 260 int xShift = r1.x - r0.x; 261 int yShift = r1.y - r0.y; 262 263 for (int y = r0.y; y < r0.y + r0.height; y++) { 264 for (int x = r0.x; x < r0.x + r0.width; x++) { 265 if (!comparePixels(x, y, x + xShift, y + yShift)) { 266 return false; 267 } 268 } 269 } 270 return true; 271 } 272 273 /** 274 * Compares colors of two points on the screen. 275 * @param p0 the first point 276 * @param p1 the second point 277 * return true if the two points have the same color 278 */ 279 public boolean comparePixels(Point p0, Point p1) { 280 return comparePixels(p0.x, p0.y, p1.x, p1.y); 281 } 282 283 /** 284 * Compares colors of two points on the screen. 285 * @param x0 the x coordinate of the first point 286 * @param y0 the y coordinate of the first point 287 * @param x1 the x coordinate of the second point 288 * @param y1 the y coordinate of the second point 289 * return true if the two points have the same color 290 */ 291 public boolean comparePixels(int x0, int y0, int x1, int y1) { 292 return (getPixelColor(x0, y0).equals(getPixelColor(x1, y1))); 293 } 294 }