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