1 /*
   2  * Copyright (c) 2016, 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 import java.awt.Color;
  25 import java.awt.GridBagConstraints;
  26 import java.awt.GridBagLayout;
  27 import java.awt.event.ActionEvent;
  28 import java.awt.event.ActionListener;
  29 import java.awt.event.WindowAdapter;
  30 import java.awt.event.WindowEvent;
  31 import java.util.concurrent.CountDownLatch;
  32 import java.util.concurrent.TimeUnit;
  33 import javax.swing.BoxLayout;
  34 import javax.swing.JButton;
  35 import javax.swing.JFrame;
  36 import javax.swing.JPanel;
  37 import javax.swing.JScrollPane;
  38 import javax.swing.JTextArea;
  39 import javax.swing.SwingUtilities;
  40 
  41 /*
  42  * @test
  43  * @bug 8166591
  44  * @key headful
  45  * @summary [macos 10.12] Trackpad scrolling of text on OS X 10.12 Sierra
  46  *    is very fast (Trackpad, Retina only)
  47  * @requires (os.family == "windows" | os.family == "mac")
  48  * @run main/manual/othervm TooMuchWheelRotationEventsTest
  49  */
  50 public class TooMuchWheelRotationEventsTest {
  51 
  52     private static volatile boolean testResult = false;
  53     private static volatile CountDownLatch countDownLatch;
  54     private static final String INSTRUCTIONS = " INSTRUCTIONS:\n"
  55             + " Try to check the issue with trackpad\n"
  56             + "\n"
  57             + " If the trackpad is not supported, press PASS\n"
  58             + "\n"
  59             + " Use the trackpad to slightly scroll the JTextArea horizontally and vertically.\n"
  60             + " If the text area is scrolled too fast press FAIL, else press PASS.";
  61 
  62     public static void main(String args[]) throws Exception {
  63         countDownLatch = new CountDownLatch(1);
  64 
  65         SwingUtilities.invokeLater(TooMuchWheelRotationEventsTest::createUI);
  66         countDownLatch.await(15, TimeUnit.MINUTES);
  67 
  68         if (!testResult) {
  69             throw new RuntimeException("Test fails!");
  70         }
  71     }
  72 
  73     private static void createUI() {
  74 
  75         final JFrame mainFrame = new JFrame("Trackpad scrolling test");
  76         GridBagLayout layout = new GridBagLayout();
  77         JPanel mainControlPanel = new JPanel(layout);
  78         JPanel resultButtonPanel = new JPanel(layout);
  79 
  80         GridBagConstraints gbc = new GridBagConstraints();
  81 
  82         JPanel testPanel = createTestPanel();
  83 
  84         gbc.gridx = 0;
  85         gbc.gridy = 0;
  86         gbc.fill = GridBagConstraints.HORIZONTAL;
  87         mainControlPanel.add(testPanel, gbc);
  88 
  89         JTextArea instructionTextArea = new JTextArea();
  90         instructionTextArea.setText(INSTRUCTIONS);
  91         instructionTextArea.setEditable(false);
  92         instructionTextArea.setBackground(Color.white);
  93 
  94         gbc.gridx = 0;
  95         gbc.gridy = 1;
  96         gbc.fill = GridBagConstraints.HORIZONTAL;
  97         mainControlPanel.add(instructionTextArea, gbc);
  98 
  99         JButton passButton = new JButton("Pass");
 100         passButton.setActionCommand("Pass");
 101         passButton.addActionListener((ActionEvent e) -> {
 102             testResult = true;
 103             mainFrame.dispose();
 104             countDownLatch.countDown();
 105 
 106         });
 107 
 108         JButton failButton = new JButton("Fail");
 109         failButton.setActionCommand("Fail");
 110         failButton.addActionListener(new ActionListener() {
 111             @Override
 112             public void actionPerformed(ActionEvent e) {
 113                 mainFrame.dispose();
 114                 countDownLatch.countDown();
 115             }
 116         });
 117 
 118         gbc.gridx = 0;
 119         gbc.gridy = 0;
 120         resultButtonPanel.add(passButton, gbc);
 121 
 122         gbc.gridx = 1;
 123         gbc.gridy = 0;
 124         resultButtonPanel.add(failButton, gbc);
 125 
 126         gbc.gridx = 0;
 127         gbc.gridy = 2;
 128         mainControlPanel.add(resultButtonPanel, gbc);
 129 
 130         mainFrame.add(mainControlPanel);
 131         mainFrame.pack();
 132 
 133         mainFrame.addWindowListener(new WindowAdapter() {
 134 
 135             @Override
 136             public void windowClosing(WindowEvent e) {
 137                 mainFrame.dispose();
 138                 countDownLatch.countDown();
 139             }
 140         });
 141         mainFrame.setLocationRelativeTo(null);
 142         mainFrame.setVisible(true);
 143     }
 144 
 145     private static JPanel createTestPanel() {
 146         JPanel panel = new JPanel();
 147         panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
 148         JTextArea textArea = new JTextArea(20, 20);
 149         textArea.setText(getLongString());
 150         JScrollPane scrollPane = new JScrollPane(textArea);
 151         panel.add(scrollPane);
 152         return panel;
 153     }
 154 
 155     private static String getLongString() {
 156 
 157         String lowCaseString = getLongString('a', 'z');
 158         String upperCaseString = getLongString('A', 'Z');
 159         String digitsString = getLongString('0', '9');
 160 
 161         int repeat = 30;
 162         StringBuilder lowCaseBuilder = new StringBuilder();
 163         StringBuilder upperCaseBuilder = new StringBuilder();
 164         StringBuilder digitsBuilder = new StringBuilder();
 165 
 166         for (int i = 0; i < repeat; i++) {
 167             lowCaseBuilder.append(lowCaseString).append(' ');
 168             upperCaseBuilder.append(upperCaseString).append(' ');
 169             digitsBuilder.append(digitsString).append(' ');
 170         }
 171 
 172         StringBuilder builder = new StringBuilder();
 173         for (int i = 0; i < 200; i++) {
 174             builder.append(upperCaseBuilder).append('\n')
 175                     .append(lowCaseBuilder).append('\n')
 176                     .append(digitsBuilder).append("\n\n\n");
 177         }
 178 
 179         return builder.toString();
 180     }
 181 
 182     private static String getLongString(char c1, char c2) {
 183 
 184         char[] chars = new char[c2 - c1 + 1];
 185         for (char i = c1; i <= c2; i++) {
 186             chars[i - c1] = i;
 187         }
 188         return new String(chars);
 189     }
 190 }