1 /*
2  * Copyright (c) 2019, 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 8231991
28   @summary Mouse wheel change focus on awt/swing windows
29   @run main MouseWheelOnBackgroundComponent
30 */
31 
32 import javax.swing.*;
33 import java.awt.*;
34 import java.awt.event.FocusEvent;
35 import java.awt.event.FocusListener;
36 import java.awt.event.WindowEvent;
37 
38 /**
39  * MouseWheelOnBackgroundComponent
40  *
41  * Tests that wheel events don't change focus on background components
42  */
43 public class MouseWheelOnBackgroundComponent {
44 
45     private static final String FG = "Foreground";
46     private static final String BG = "Background";
47 
48     private static final String SCROLL_PANE = "scroller_";
49     private static final String TEXT_PANE = "text_";
50 
51     private static JFrame background;
52     private static JFrame foreground;
53 
54     private static final String LOREM_IPSUM = "Sed ut perspiciatis unde omnis iste natus " +
55             "error sit voluptatem accusantium doloremque laudantium, totam " +
56             "rem aperiam, eaque ipsa quae ab illo inventore veritatis et " +
57             "quasi architecto beatae vitae dicta sunt explicabo. Nemo enim " +
58             "ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, " +
59             "sed quia consequuntur magni dolores eos qui ratione voluptatem sequi " +
60             "nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit " +
61             "amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora " +
62             "incidunt ut labore et dolore magnam aliquam quaerat voluptatem. " +
63             "Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis " +
64             "suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis " +
65             "autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil " +
66             "molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla " +
67             "pariatur?";
68 
69     private static class FocusReporter implements FocusListener {
70 
71         private JComponent pane;
72 
73         Component lastFocusedComponent;
74 
FocusReporter()75         public FocusReporter() {
76         }
77 
78         @Override
focusGained(FocusEvent e)79         public void focusGained(FocusEvent e) {
80             lastFocusedComponent = e.getComponent();
81         }
82 
83         @Override
focusLost(FocusEvent e)84         public void focusLost(FocusEvent e) {
85             lastFocusedComponent = null;
86         }
87     }
88 
89     private static FocusReporter reporter;
90 
main(String[] args)91     public static void main(String[] args) throws Exception  {
92 
93         boolean passed = false;
94 
95         SwingUtilities.invokeAndWait(() -> {
96             reporter = new FocusReporter();
97 
98             foreground = createFrame(FG, 100, 0, reporter);
99             background = createFrame(BG, 0, 100, reporter);
100 
101             background.pack();
102             background.setVisible(true);
103 
104             foreground.pack();
105             foreground.setVisible(true);
106         });
107 
108         SwingUtilities.invokeAndWait(() -> {
109             foreground.toFront();
110         });
111 
112         Robot robot = new Robot();
113         robot.waitForIdle();
114 
115         robot.mouseMove(50, 300);
116         robot.waitForIdle();
117 
118         robot.mouseWheel(-100);
119         robot.waitForIdle();
120 
121         String shouldBeFocusedComponentName = TEXT_PANE + FG;
122         Component actual = reporter.lastFocusedComponent;
123         if (reporter.lastFocusedComponent != null &&
124             shouldBeFocusedComponentName.equals(actual.getName()))
125         {
126             passed = true;
127         }
128 
129         robot.waitForIdle();
130 
131         SwingUtilities.invokeAndWait(() -> {
132             foreground.dispatchEvent(new WindowEvent(foreground, WindowEvent.WINDOW_CLOSING));
133             background.dispatchEvent(new WindowEvent(background, WindowEvent.WINDOW_CLOSING));
134         });
135 
136         robot.waitForIdle();
137 
138         if (!passed) {
139             throw new RuntimeException("Wrong component has focus: " + actual);
140         }
141     }
142 
createFrame(String name, int x, int y, FocusReporter reporter)143     private static JFrame createFrame(String name, int x, int y, FocusReporter reporter) {
144         JFrame frame = new JFrame(name);
145         frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
146         frame.setBounds(x, y, 600, 600);
147         frame.setPreferredSize(new Dimension(600, 600));
148 
149         JTextArea text = new JTextArea();
150         text.setText(LOREM_IPSUM);
151         for (int i = 0; i < 10; i++) {
152             text.append(LOREM_IPSUM);
153         }
154 
155         text.setLineWrap(true);
156         text.setName(TEXT_PANE + name);
157         text.addFocusListener(reporter);
158 
159         JScrollPane scroller = new JScrollPane(text);
160         scroller.setName(SCROLL_PANE + name);
161         scroller.setWheelScrollingEnabled(true);
162         scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
163         scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
164         scroller.addFocusListener(reporter);
165 
166         frame.add(scroller);
167 
168         return frame;
169     }
170 }
171