Skip to content

Commit

Permalink
8307934: JRobot.moveMouseTo must access component on EDT
Browse files Browse the repository at this point in the history
Reviewed-by: aivanov
  • Loading branch information
Renjithkannath authored and aivanov-jdk committed Jul 3, 2023
1 parent 87c79c0 commit 9d2e0b2
Showing 1 changed file with 64 additions and 30 deletions.
94 changes: 64 additions & 30 deletions test/jdk/javax/swing/regtesthelpers/JRobot.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2023, 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
Expand All @@ -21,29 +21,29 @@
* questions.
*/

/**
* JRobot is a wrapper around java.awt.Robot that provides some convenience
* methods.
* <p>When using jtreg you would include this class via something like:
* <pre>
* @library ../../../regtesthelpers
* @build JRobot
* </pre>
*
*/
import java.awt.AWTException;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.concurrent.atomic.AtomicReference;
import java.lang.reflect.InvocationTargetException;

import javax.swing.SwingUtilities;

/**
* JRobot is a wrapper around java.awt.Robot that provides some convenience
* methods.
* <p>When using jtreg you would include this class via something like:
* <pre>{@code
* @library ../../../regtesthelpers
* @build JRobot
* }</pre>
*/
public class JRobot extends java.awt.Robot {
private static int DEFAULT_DELAY = 550;
private static int INTERNAL_DELAY = 250;
private static final int DEFAULT_DELAY = 550;
private static final int INTERNAL_DELAY = 250;

private int delay;
private boolean delaysEnabled;
Expand Down Expand Up @@ -112,17 +112,35 @@ public void hitKey(int... keys) {

/**
* Move mouse cursor to the center of the Component.
* <p>
* <b>Note:</b> This method is executed on EDT.
*
* @param c Component the mouse is placed over
*/
public void moveMouseTo(Component c) {
Point p = c.getLocationOnScreen();
Dimension size = c.getSize();
p.x += size.width / 2;
p.y += size.height / 2;
Point p = getCenterPoint(c);
mouseMove(p.x, p.y);
delay();
}

private static Point getCenterPoint(Component c) {
AtomicReference<Point> result = new AtomicReference<>();
if (SwingUtilities.isEventDispatchThread()) {
result.set(getCenterPointImpl(c));
} else {
try {
SwingUtilities.invokeAndWait(() -> result.set(getCenterPointImpl(c)));
} catch (InterruptedException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
return result.get();
}

private static Point getCenterPointImpl(Component c) {
return centerOf(new Rectangle(c.getLocationOnScreen(), c.getSize()));
}

/**
* Move mouse smoothly from (x0, y0) to (x1, y1).
*/
Expand Down Expand Up @@ -153,13 +171,16 @@ public void clickMouse(int buttons) {
* Perform a click with the first mouse button.
*/
public void clickMouse() {
clickMouse(InputEvent.BUTTON1_MASK);
clickMouse(InputEvent.BUTTON1_DOWN_MASK);
}

/**
* Click in the center of the given Component
* Click in the center of the given Component.
* <p>
* <b>Note:</b> This method is executed on EDT.
*
* @param c the Component to click on
* @param buttons mouse button(s).
* @param buttons mouse button(s)
*/
public void clickMouseOn(Component c, int buttons) {
moveMouseTo(c);
Expand All @@ -168,10 +189,13 @@ public void clickMouseOn(Component c, int buttons) {

/**
* Click the first mouse button in the center of the given Component
* <p>
* <b>Note:</b> This method is executed on EDT.
*
* @param c the Component to click on
*/
public void clickMouseOn(Component c) {
clickMouseOn(c, InputEvent.BUTTON1_MASK);
clickMouseOn(c, InputEvent.BUTTON1_DOWN_MASK);
}

/**
Expand Down Expand Up @@ -219,8 +243,8 @@ public synchronized void waitForIdle() {
* @param r a non-null Rectangle
* @return a new Point object containing coordinates of r's center
*/
public Point centerOf(Rectangle r) {
return new Point(r.x + r.width / 2, r.y + r.height / 2);
public static Point centerOf(Rectangle r) {
return centerOf(r, new Point());
}

/**
Expand All @@ -229,7 +253,7 @@ public Point centerOf(Rectangle r) {
* @param p a non-null Point that receives coordinates of r's center
* @return p
*/
public Point centerOf(Rectangle r, Point p) {
public static Point centerOf(Rectangle r, Point p) {
p.x = r.x + r.width / 2;
p.y = r.y + r.height / 2;
return p;
Expand All @@ -238,14 +262,24 @@ public Point centerOf(Rectangle r, Point p) {
/**
* Convert a rectangle from coordinate system of Component c to
* screen coordinate system.
* <p>
* <b>Note:</b> This method is executed on EDT.
*
* @param r a non-null Rectangle
* @param c a Component whose coordinate system is used for conversion
*/
public void convertRectToScreen(Rectangle r, Component c) {
Point p = new Point(r.x, r.y);
SwingUtilities.convertPointToScreen(p, c);
r.x = p.x;
r.y = p.y;
AtomicReference<Point> p = new AtomicReference<>();
if (SwingUtilities.isEventDispatchThread()) {
p.set(c.getLocationOnScreen());
} else {
try {
SwingUtilities.invokeAndWait(() -> p.set(c.getLocationOnScreen()));
} catch (InterruptedException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
r.setLocation(p.get());
}

/**
Expand Down

1 comment on commit 9d2e0b2

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.