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 + "\n Mouse: " + mouse + "\n Window 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