1 /*
2  * Copyright (c) 2005, 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.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 /*
27   @test
28   @key headful
29   @bug 5025858 8144125
30   @summary Tests that after programmatically moving or resizing a component,
31            corresponding ComponentEvents are generated only once
32 */
33 
34 import java.awt.Button;
35 import java.awt.Component;
36 import java.awt.Frame;
37 import java.awt.Point;
38 import java.awt.Robot;
39 import java.awt.Window;
40 import java.awt.event.ComponentAdapter;
41 import java.awt.event.ComponentEvent;
42 import java.awt.event.ComponentListener;
43 
44 /*
45   IMPORTANT: this test can fail because some window managers may generate
46   strange events and that would lead to the test to fail. However, on most
47   popular platforms (windows, linux w/ KDE or GNOME, solaris w/ CDE or
48   GNOME) it usually passes successfully.
49 */
50 
51 public class MovedResizedTwiceTest
52 {
53     private static volatile int componentMovedCount;
54     private static volatile int componentResizedCount;
55 
56     private static volatile int rightX, rightY;
57 
58     private static volatile boolean failed = false;
59 
init()60     private static void init()
61     {
62         componentMovedCount = componentResizedCount = 0;
63 
64         Robot robot;
65         try {
66             robot = new Robot();
67         }catch(Exception ex) {
68             ex.printStackTrace();
69             throw new RuntimeException("Cannot create Robot: failure");
70         }
71 
72         Frame f = new Frame("Frame F");
73         f.setLayout(null);
74         f.setBounds(100, 100, 100, 100);
75         f.add(new Button("Button"));
76 
77         f.setVisible(true);
78         robot.waitForIdle();
79 
80         ComponentListener cl = new ComponentAdapter()
81         {
82             public void componentMoved(ComponentEvent e)
83             {
84                 componentMovedCount++;
85                 Component c = (Component)e.getSource();
86                 if (!(c instanceof Window))
87                 {
88                     return;
89                 }
90                 Point p = c.getLocationOnScreen();
91                 if ((p.x != rightX) || (p.y != rightY))
92                 {
93                     System.err.println("Error: wrong location on screen after COMPONENT_MOVED");
94                     System.err.println("Location on screen is (" + p.x + ", " + p.y + ") against right location (" + rightX + ", " + rightY + ")");
95                     failed = true;
96                 }
97             }
98             public void componentResized(ComponentEvent e)
99             {
100                 componentResizedCount++;
101             }
102         };
103 
104         f.addComponentListener(cl);
105 
106         componentResizedCount = componentMovedCount = 0;
107         rightX = 100;
108         rightY = 100;
109         f.setSize(200, 200);
110         robot.waitForIdle();
111         checkResized("setSize", f);
112 
113         componentResizedCount = componentMovedCount = 0;
114         rightX = 200;
115         rightY = 200;
116         f.setLocation(200, 200);
117         robot.waitForIdle();
118         checkMoved("setLocation", f);
119 
120         componentResizedCount = componentMovedCount = 0;
121         rightX = 150;
122         rightY = 150;
123         f.setBounds(150, 150, 100, 100);
124         robot.waitForIdle();
125         checkResized("setBounds", f);
126         checkMoved("setBounds", f);
127 
128         Button b = new Button("B");
129         b.setBounds(10, 10, 40, 40);
130         f.add(b);
131         robot.waitForIdle();
132 
133         b.addComponentListener(cl);
134 
135         componentResizedCount = componentMovedCount = 0;
136         b.setBounds(20, 20, 50, 50);
137         robot.waitForIdle();
138         checkMoved("setBounds", b);
139         checkResized("setBounds", b);
140         f.remove(b);
141 
142         Component c = new Component() {};
143         c.setBounds(10, 10, 40, 40);
144         f.add(c);
145         robot.waitForIdle();
146 
147         c.addComponentListener(cl);
148 
149         componentResizedCount = componentMovedCount = 0;
150         c.setBounds(20, 20, 50, 50);
151         robot.waitForIdle();
152         checkMoved("setBounds", c);
153         checkResized("setBounds", c);
154         f.remove(c);
155 
156         if (failed)
157         {
158             MovedResizedTwiceTest.fail("Test FAILED");
159         }
160         else
161         {
162             MovedResizedTwiceTest.pass();
163         }
164     }
165 
checkResized(String methodName, Component c)166     private static void checkResized(String methodName, Component c)
167     {
168         String failMessage = null;
169         if (componentResizedCount == 1)
170         {
171             return;
172         }
173         else if (componentResizedCount == 0)
174         {
175             failMessage = "Test FAILED: COMPONENT_RESIZED is not sent after call to " + methodName + "()";
176         }
177         else
178         {
179             failMessage = "Test FAILED: COMPONENT_RESIZED is sent " + componentResizedCount + " + times after call to " + methodName + "()";
180         }
181         System.err.println("Failed component: " + c);
182         MovedResizedTwiceTest.fail(failMessage);
183     }
184 
checkMoved(String methodName, Component c)185     private static void checkMoved(String methodName, Component c)
186     {
187         String failMessage = null;
188         if (componentMovedCount == 1)
189         {
190             return;
191         }
192         if (componentMovedCount == 0)
193         {
194             failMessage = "Test FAILED: COMPONENT_MOVED is not sent after call to " + methodName + "()";
195         }
196         else
197         {
198             failMessage = "Test FAILED: COMPONENT_MOVED is sent " + componentMovedCount + " times after call to " + methodName + "()";
199         }
200         System.err.println("Failed component: " + c);
201         MovedResizedTwiceTest.fail(failMessage);
202     }
203 
204     private static boolean theTestPassed = false;
205     private static boolean testGeneratedInterrupt = false;
206     private static String failureMessage = "";
207 
208     private static Thread mainThread = null;
209 
210     private static int sleepTime = 300000;
211 
main( String args[] )212     public static void main( String args[] ) throws InterruptedException
213     {
214         mainThread = Thread.currentThread();
215         try
216         {
217             init();
218         }
219         catch (TestPassedException e)
220         {
221             return;
222         }
223 
224         try
225         {
226             Thread.sleep(sleepTime);
227             throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
228         }
229         catch (InterruptedException e)
230         {
231             if (!testGeneratedInterrupt)
232             {
233                 throw e;
234             }
235 
236             testGeneratedInterrupt = false;
237 
238             if (!theTestPassed)
239             {
240                 throw new RuntimeException( failureMessage );
241             }
242         }
243     }
244 
setTimeoutTo(int seconds)245     public static synchronized void setTimeoutTo(int seconds)
246     {
247         sleepTime = seconds * 1000;
248     }
249 
pass()250     public static synchronized void pass()
251     {
252         if (mainThread == Thread.currentThread())
253         {
254             theTestPassed = true;
255             throw new TestPassedException();
256         }
257         theTestPassed = true;
258         testGeneratedInterrupt = true;
259         mainThread.interrupt();
260     }
261 
fail()262     public static synchronized void fail()
263     {
264         fail("it just plain failed! :-)");
265     }
266 
fail(String whyFailed)267     public static synchronized void fail(String whyFailed)
268     {
269         if (mainThread == Thread.currentThread())
270         {
271             throw new RuntimeException(whyFailed);
272         }
273         theTestPassed = false;
274         testGeneratedInterrupt = true;
275         failureMessage = whyFailed;
276         mainThread.interrupt();
277     }
278 }
279 
280 class TestPassedException extends RuntimeException
281 {
282 }
283