RFR: 8345538: Robot.mouseMove doesn't clamp bounds on macOS when trying to move mouse off screen [v3]

Alexey Ivanov aivanov at openjdk.org
Fri Dec 20 21:12:35 UTC 2024


On Fri, 20 Dec 2024 20:59:52 GMT, Alexey Ivanov <aivanov at openjdk.org> wrote:

>>> Displays: 2 Placement: Side-by-side, with the bottom edge aligned as below
>>> 
>>> <img alt="image" width="478" src="https://private-user-images.githubusercontent.com/95945681/397856615-7ea5be69-989f-42b5-ac26-631d170d8db0.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzQ3Mjc0NjMsIm5iZiI6MTczNDcyNzE2MywicGF0aCI6Ii85NTk0NTY4MS8zOTc4NTY2MTUtN2VhNWJlNjktOTg5Zi00MmI1LWFjMjYtNjMxZDE3MGQ4ZGIwLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDEyMjAlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQxMjIwVDIwMzkyM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWZhYWUzZWNkZWZjOGFiZTRjMWE4ODgxMjhhYjE3N2E4NWRkOTA2MmI0MzMyZWJmNmExYTJmODA0ZjgzZGJmMmUmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.vGpCyq1K_5DGxJ-rZPPp5PosfvP4Q90l-3hIAWb1E7M">
>>> Screen bounds: Win32GraphicsDevice[screen=0]:java.awt.Rectangle[x=-1920,y=363,width=1280,height=720] Win32GraphicsDevice[screen=1]:java.awt.Rectangle[x=0,y=0,width=2293,height=960]
>>> 
>>> Stack Trace: ----------System.err:(11/959)---------- java.lang.NullPointerException: Cannot invoke "java.awt.PointerInfo.getLocation()" because the return value of "java.awt.MouseInfo.getPointerInfo()" is null at MouseMoveOffScreen.main(MouseMoveOffScreen.java:57) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) at java.base/java.lang.reflect.Method.invoke(Method.java:565) at com.sun.javatest.regtest.agent.MainWrapper$MainTask.run(MainWrapper.java:138) at java.base/java.lang.Thread.run(Thread.java:1447)
>>> 
>>> JavaTest Message: Test threw exception: java.lang.NullPointerException: Cannot invoke "java.awt.PointerInfo.getLocation()" because the return value of "java.awt.MouseInfo.getPointerInfo()" is null JavaTest Message: shutting down test
>> 
>> The stack trace wasn't as revealing as I hoped. But the monitor config may tell us something.
>> (0, 200) is a location that is off the top of screen 1, so not within the virtual bounds.
>> But it is interesting that you get NPE before the fix as well .. perhaps the windows clamping isn't happening as Alisen said. I think we need to understand that as the next step.
>> 
>> After that , since it looks to me like the bounds of all screens need to be looked at to clamp because we can't rely on a single rectangle defining it even if there's a single virtual screen, and need to look at the union.
>
> Now I ran the test on macOS Sequoia 15.1.1. With the current `Robot` implementation, it's able to move mouse across both displays. With Alisen's updated implementation, the coordinates are limited to the main screen.
> 
> <details>
> <summary>Updated test</summary>
> 
> 
>     private static void moveMouseAndCheck(final Robot robot,
>                                           final int x, final int y) {
>         System.out.println(x + ", " + y);
>         robot.mouseMove(x, y);
>         robot.delay(1000);
> 
>         PointerInfo cursor = MouseInfo.getPointerInfo();
>         if (cursor != null) {
>             System.out.println(cursor.getLocation() + " - "
>                                + cursor.getDevice().getIDstring());
>         }
>     }
> 
>     public static void main(String[] args) throws Exception {
>         Robot robot = new Robot();
> 
>         GraphicsDevice[] screens = getLocalGraphicsEnvironment()
>                                    .getScreenDevices();
>         for (GraphicsDevice screen : screens) {
>             GraphicsConfiguration gc = screen.getDefaultConfiguration();
>             System.out.println(screen.getIDstring());
>             System.out.println("\t" + gc.getBounds());
>             System.out.println("\t" + gc.getDefaultTransform());
>         }
>         System.out.println("\n");
> 
>         for (GraphicsDevice screen : screens) {
>             System.out.println(screen.getIDstring());
>             Rectangle bounds = screen.getDefaultConfiguration()
>                                      .getBounds();
> 
>             moveMouseAndCheck(robot, bounds.x, bounds.y);
>             moveMouseAndCheck(robot, bounds.x + bounds.width, bounds.y);
>             moveMouseAndCheck(robot, bounds.x, bounds.y + bounds.height);
>             moveMouseAndCheck(robot, bounds.x + bounds.width, bounds.y + bounds.height);
>             moveMouseAndCheck(robot, bounds.x + bounds.width / 2, bounds.y + bounds.height / 2);
>         }
> 
> </details>
> 
> Displays are arranged side by side: the built-in Display is on the left, the main display is on the right.
> 
> <details>
> <summary>JDK 21 without the fix</summary>
> 
> **JDK 21 without the fix**
> 
> Display 69734208
> 	java.awt.Rectangle[x=-1440,y=0,width=1440,height=900]
> 	AffineTransform[[2.0, 0.0, 0.0], [0.0, 2.0, 0.0]]
> Display 725353101
> 	java.awt.Rectangle[x=0,y=0,width=1920,height=1080]
> 	AffineTransform[[2.0, 0.0, 0.0], [0.0, 2.0, 0.0]]
> 
> 
> Display 69734208
> -1440, 0
> java.awt.Point[x=-1440,y=0] - Display 69734208
> 0, 0
> java.awt.Point[x=0,y=0] - Display 725353101
> -1440, 900
> cursor == null
> ...

Note that even with Alisen's fix, **the test fails to get the mouse pointer location after moving it off the screen!**

The coordinates are expected to be within the screen bounds.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/22781#discussion_r1894391146


More information about the client-libs-dev mailing list