Skip to content

Commit ba27e5b

Browse files
mkartashevOnePatchGuy
authored andcommitted
JBR-9987 Wayland: MouseInfo.getPointerInfo() returns inconsistent data in multi-monitor configurations
1 parent 64a0748 commit ba27e5b

2 files changed

Lines changed: 98 additions & 0 deletions

File tree

src/java.desktop/unix/classes/sun/awt/wl/WLMouseInfoPeer.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ public int fillPointWithCoords(Point point) {
4040
WLInputState inputState = WLToolkit.getInputState();
4141
// NB: these are surface-local coordinates
4242
point.setLocation(inputState.getPointerX(), inputState.getPointerY());
43+
// Make the best effort to fulfill the peer's promise that
44+
// "coordinates are calculated in the coordinate system of the screen
45+
// device where the pointer is located."
46+
var peerUnderMouse = getPeerUnderMouse();
47+
if (peerUnderMouse != null) {
48+
var gc = peerUnderMouse.getGraphicsConfiguration();
49+
if (gc != null) {
50+
var screenLocation = gc.getBounds().getLocation();
51+
point.translate(screenLocation.x, screenLocation.y);
52+
}
53+
}
4354
return 0;
4455
}
4556

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright 2026 JetBrains s.r.o.
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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import javax.swing.JButton;
25+
import javax.swing.JFrame;
26+
import javax.swing.JLabel;
27+
import javax.swing.JPanel;
28+
import javax.swing.SwingUtilities;
29+
import java.awt.BorderLayout;
30+
import java.awt.MouseInfo;
31+
import java.awt.Point;
32+
import java.awt.Rectangle;
33+
import java.util.concurrent.CompletableFuture;
34+
35+
/**
36+
* @test
37+
* @summary Verifies mouse pointer location is consistent in multi-monitor configurations
38+
* @requires os.family == "linux"
39+
* @key headful
40+
* @run main/manual WLPointerLocation
41+
*/
42+
public class WLPointerLocation {
43+
static final CompletableFuture<RuntimeException> swingError = new CompletableFuture<>();
44+
45+
public static void main(String[] args) throws Exception {
46+
SwingUtilities.invokeLater(() -> {
47+
JFrame f = new JFrame("WLPointerLocation Test");
48+
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
49+
50+
JPanel content = new JPanel();
51+
var layout = new BorderLayout();
52+
content.setLayout(layout);
53+
JLabel l = new JLabel("<html><h1>INSTRUCTIONS</h1>" +
54+
"<p>Setup: a multi-monitor configuration where monitors are NOT aligned horizontally, " +
55+
"i.e. one is slightly below the other.</p>" +
56+
"<p>For each monitor, move the window to that monitor, and press the Test button.</p>" +
57+
"<p>When done, press Done.</p>" +
58+
"<p>The test passes when every time the Test button was pressed," +
59+
" the mouse pointer was within the windows's boundaries.</p></html>");
60+
content.add(l, BorderLayout.NORTH);
61+
62+
JButton b = new JButton("Test");
63+
content.add(b, BorderLayout.CENTER);
64+
b.addActionListener(e -> {
65+
Rectangle window = new Rectangle(f.getLocationOnScreen(), f.getSize());
66+
Point mouse = MouseInfo.getPointerInfo().getLocation();
67+
boolean windowContainsMouse = window.contains(mouse);
68+
System.out.println("Window: " + window + "\nMouse: " + mouse + "\nWindow contains mouse: " + windowContainsMouse);
69+
if (!windowContainsMouse) {
70+
swingError.completeExceptionally(new RuntimeException("Window does not contain mouse"));
71+
}
72+
});
73+
74+
JButton done = new JButton("Done");
75+
content.add(done, BorderLayout.SOUTH);
76+
done.addActionListener(e -> {
77+
swingError.complete(null);
78+
});
79+
80+
f.setContentPane(content);
81+
f.pack();
82+
f.setVisible(true);
83+
});
84+
85+
swingError.get();
86+
}
87+
}

0 commit comments

Comments
 (0)