WrongSelectionOnMouseOver.java revision 17113:d17577d4839b
1/*
2 * Copyright (c) 2015, 2017, 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.
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/*
25 * @test
26 * @key headful
27 * @bug 8072900
28 * @summary Mouse events are captured by the wrong menu in OS X
29 * @author Anton Nashatyrev
30 * @run main WrongSelectionOnMouseOver
31 */
32
33import javax.swing.*;
34import javax.swing.event.MenuEvent;
35import javax.swing.event.MenuListener;
36import java.awt.*;
37import java.awt.event.MouseAdapter;
38import java.awt.event.MouseEvent;
39import java.util.concurrent.CountDownLatch;
40import java.util.concurrent.TimeUnit;
41
42import static javax.swing.UIManager.getInstalledLookAndFeels;
43
44public class WrongSelectionOnMouseOver implements Runnable {
45
46    CountDownLatch firstMenuSelected = new CountDownLatch(1);
47    CountDownLatch secondMenuMouseEntered = new CountDownLatch(1);
48    CountDownLatch secondMenuSelected = new CountDownLatch(1);
49
50    JMenu m1, m2;
51
52    private UIManager.LookAndFeelInfo laf;
53    JFrame frame1;
54    JFrame frame2;
55    private Point menu1location;
56    private Point menu2location;
57
58    public WrongSelectionOnMouseOver(UIManager.LookAndFeelInfo laf) throws Exception {
59        this.laf = laf;
60    }
61
62    private void createUI() throws Exception {
63        System.out.println("Testing UI: " + laf);
64        UIManager.setLookAndFeel(laf.getClassName());
65
66        {
67            frame1 = new JFrame("Frame1");
68            JMenuBar mb = new JMenuBar();
69            m1 = new JMenu("File");
70            JMenuItem i1 = new JMenuItem("Save");
71            JMenuItem i2 = new JMenuItem("Load");
72
73            m1.addMenuListener(new MenuListener() {
74                @Override
75                public void menuSelected(MenuEvent e) {
76                    firstMenuSelected.countDown();
77                    System.out.println("Menu1: menuSelected");
78                }
79
80                @Override
81                public void menuDeselected(MenuEvent e) {
82                    System.out.println("Menu1: menuDeselected");
83                }
84
85                @Override
86                public void menuCanceled(MenuEvent e) {
87                    System.out.println("Menu1: menuCanceled");
88                }
89            });
90
91            frame1.setJMenuBar(mb);
92            mb.add(m1);
93            m1.add(i1);
94            m1.add(i2);
95
96            frame1.setLayout(new FlowLayout());
97            frame1.setBounds(200, 200, 200, 200);
98
99            frame1.setVisible(true);
100        }
101
102        {
103            frame2 = new JFrame("Frame2");
104            JMenuBar mb = new JMenuBar();
105            m2 = new JMenu("File");
106            JMenuItem i1 = new JMenuItem("Save");
107            JMenuItem i2 = new JMenuItem("Load");
108
109            m2.addMouseListener(new MouseAdapter() {
110                @Override
111                public void mouseEntered(MouseEvent e) {
112                    secondMenuMouseEntered.countDown();
113                    System.out.println("WrongSelectionOnMouseOver.mouseEntered");
114                }
115            });
116
117            m2.addMenuListener(new MenuListener() {
118                @Override
119                public void menuSelected(MenuEvent e) {
120                    secondMenuSelected.countDown();
121                    System.out.println("Menu2: menuSelected");
122                }
123
124                @Override
125                public void menuDeselected(MenuEvent e) {
126                    System.out.println("Menu2: menuDeselected");
127                }
128
129                @Override
130                public void menuCanceled(MenuEvent e) {
131                    System.out.println("Menu2: menuCanceled");
132                }
133            });
134
135            frame2.setJMenuBar(mb);
136            mb.add(m2);
137            m2.add(i1);
138            m2.add(i2);
139
140            frame2.setLayout(new FlowLayout());
141            frame2.setBounds(450, 200, 200, 200);
142
143            frame2.setVisible(true);
144        }
145    }
146
147    public void disposeUI() {
148        frame1.dispose();
149        frame2.dispose();
150    }
151
152    @Override
153    public void run() {
154        try {
155            if (frame1 == null) {
156                createUI();
157            } else {
158                disposeUI();
159            }
160        } catch (Exception e) {
161            throw new RuntimeException(e);
162        }
163    }
164
165    public void test() throws Exception {
166        Robot robot = new Robot();
167        robot.setAutoDelay(100);
168
169        robot.waitForIdle();
170
171        SwingUtilities.invokeAndWait(() -> {
172            menu1location = m1.getLocationOnScreen();
173            menu2location = m2.getLocationOnScreen();
174        });
175
176        robot.mouseMove((int) menu1location.getX() + 5,
177                (int) menu1location.getY() + 5);
178        robot.mousePress(MouseEvent.BUTTON1_MASK);
179        robot.mouseRelease(MouseEvent.BUTTON1_MASK);
180
181        if (!firstMenuSelected.await(5, TimeUnit.SECONDS)) {
182            throw new RuntimeException("Menu has not been selected.");
183        };
184
185        robot.mouseMove((int) menu2location.getX() + 5,
186                (int) menu2location.getY() + 5);
187
188        if (!secondMenuMouseEntered.await(5, TimeUnit.SECONDS)) {
189            throw new RuntimeException("MouseEntered event missed for the second menu");
190        };
191
192        if (secondMenuSelected.await(1, TimeUnit.SECONDS)) {
193            throw new RuntimeException("The second menu has been selected");
194        };
195    }
196
197    public static void main(final String[] args) throws Exception {
198        for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) {
199            WrongSelectionOnMouseOver test = new WrongSelectionOnMouseOver(laf);
200            SwingUtilities.invokeAndWait(test);
201            test.test();
202            SwingUtilities.invokeAndWait(test);
203        }
204        System.out.println("Test passed");
205    }
206}
207