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