1 /*
2  * Copyright (c) 2012, 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  * @bug 4697612 6244705
27  * @author Peter Zhelezniakov
28  * @library ../../regtesthelpers
29  * @build Util
30  * @run main bug4697612
31  */
32 import java.io.*;
33 import java.awt.*;
34 import java.awt.event.*;
35 import javax.swing.*;
36 
37 import javax.swing.text.BadLocationException;
38 
39 public class bug4697612 {
40 
41     static final int FRAME_WIDTH = 300;
42     static final int FRAME_HEIGHT = 300;
43     static final int FONT_HEIGHT = 16;
44     private static volatile int frameHeight;
45     private static volatile int fontHeight;
46     private static JFrame frame;
47     private static JTextArea text;
48     private static JScrollPane scroller;
49 
main(String[] args)50     public static void main(String[] args) throws Throwable {
51         Robot robot = new Robot();
52         robot.setAutoDelay(100);
53 
54         SwingUtilities.invokeAndWait(new Runnable() {
55 
56             @Override
57             public void run() {
58                 createAndShowGUI();
59             }
60         });
61 
62         robot.waitForIdle();
63 
64         SwingUtilities.invokeAndWait(new Runnable() {
65 
66             @Override
67             public void run() {
68                 text.requestFocus();
69             }
70         });
71 
72         robot.waitForIdle();
73 
74         // 4697612: pressing PgDn + PgUp should not alter caret position
75         Util.hitKeys(robot, KeyEvent.VK_HOME);
76         Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN);
77 
78 
79         int pos0 = getTextCaretPosition();
80         int caretHeight = getTextCaretHeight();
81         fontHeight = FONT_HEIGHT;
82 
83         // iterate two times, for different (even and odd) font height
84         for (int i = 0; i < 2; i++) {
85 
86             SwingUtilities.invokeAndWait(new Runnable() {
87 
88                 public void run() {
89                     text.setFont(text.getFont().deriveFont(fontHeight));
90                 }
91             });
92 
93             frameHeight = FRAME_HEIGHT;
94 
95             for (int j = 0; j < caretHeight; j++) {
96                 SwingUtilities.invokeAndWait(new Runnable() {
97 
98                     public void run() {
99                         frame.setSize(FRAME_WIDTH, frameHeight);
100                     }
101                 });
102 
103                 robot.waitForIdle();
104 
105                 Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN);
106                 Util.hitKeys(robot, KeyEvent.VK_PAGE_UP);
107                 robot.waitForIdle();
108 
109                 int pos = getTextCaretPosition();
110                 if (pos0 != pos) {
111                     throw new RuntimeException("Failed 4697612: PgDn & PgUp keys scroll by different amounts");
112                 }
113                 frameHeight++;
114             }
115             fontHeight++;
116         }
117 
118 
119         // 6244705: pressing PgDn at the very bottom should not scroll
120         LookAndFeel laf = UIManager.getLookAndFeel();
121         if (laf.getID().equals("Aqua")) {
122             Util.hitKeys(robot, KeyEvent.VK_END);
123         } else {
124             Util.hitKeys(robot, KeyEvent.VK_CONTROL, KeyEvent.VK_END);
125         }
126 
127         robot.waitForIdle();
128 
129         pos0 = getScrollerViewPosition();
130         Util.hitKeys(robot, KeyEvent.VK_PAGE_DOWN);
131         robot.waitForIdle();
132 
133         int pos = getScrollerViewPosition();
134 
135         if (pos0 != pos) {
136             throw new RuntimeException("Failed 6244705: PgDn at the bottom causes scrolling");
137         }
138     }
139 
getTextCaretPosition()140     private static int getTextCaretPosition() throws Exception {
141         final int[] result = new int[1];
142         SwingUtilities.invokeAndWait(new Runnable() {
143 
144             @Override
145             public void run() {
146                 result[0] = text.getCaretPosition();
147             }
148         });
149 
150         return result[0];
151     }
152 
getTextCaretHeight()153     private static int getTextCaretHeight() throws Exception {
154         final int[] result = new int[1];
155         SwingUtilities.invokeAndWait(new Runnable() {
156 
157             @Override
158             public void run() {
159                 try {
160                     int pos0 = text.getCaretPosition();
161                     Rectangle dotBounds = text.modelToView(pos0);
162                     result[0] = dotBounds.height;
163                 } catch (BadLocationException ex) {
164                     throw new RuntimeException(ex);
165                 }
166             }
167         });
168 
169         return result[0];
170     }
171 
getScrollerViewPosition()172     private static int getScrollerViewPosition() throws Exception {
173         final int[] result = new int[1];
174         SwingUtilities.invokeAndWait(new Runnable() {
175 
176             @Override
177             public void run() {
178                 result[0] = scroller.getViewport().getViewPosition().y;
179             }
180         });
181 
182         return result[0];
183     }
184 
createAndShowGUI()185     private static void createAndShowGUI() {
186         frame = new JFrame();
187         frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
188         frame.setPreferredSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT));
189         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
190 
191         text = new JTextArea();
192         try {
193             InputStream is =
194                     bug4697612.class.getResourceAsStream("bug4697612.txt");
195             text.read(new InputStreamReader(is), null);
196         } catch (IOException e) {
197             throw new Error(e);
198         }
199 
200         scroller = new JScrollPane(text);
201 
202         frame.getContentPane().add(scroller);
203 
204         frame.pack();
205         frame.setVisible(true);
206     }
207 }
208