1 /* 2 * Copyright (c) 2007, 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 /* 25 @test 26 @key headful 27 @bug 6533330 28 @summary ANCESTOR_RESIZED is not sent while resizing a frame. Regression caused by 6500477. 29 @author anthony.petrov: area=awt.toplevel 30 @library ../../../regtesthelpers 31 @build Util 32 @run main AncestorResized 33 */ 34 35 36 /** 37 * AncestorResized.java 38 * 39 * summary: After fixing the 6500477, the ANCESTOR_RESIZED event stoped 40 * firing while resizing a frame. This was a regression. 41 * The test checks whether the event starts dispatching as it 42 * was before fixing the 6500477. 43 */ 44 45 import java.awt.*; 46 import java.awt.event.*; 47 import test.java.awt.regtesthelpers.Util; 48 49 50 public class AncestorResized 51 { 52 public static volatile int ancestorResizedCounter = 0; 53 54 55 static class HierarchyBoundsListenerImpl implements HierarchyBoundsListener { 56 public void ancestorMoved(HierarchyEvent ce) { 57 // ANCESTOR_MOVED seems to work OK. 58 } 59 public void ancestorResized(HierarchyEvent ce) { 60 ancestorResizedCounter++; 61 } 62 } 63 64 private static void init() 65 { 66 Frame frame; 67 Panel panel; 68 Button button; 69 Label label; 70 Component[] components; 71 72 String[] instructions = 73 { 74 "This is an AUTOMATIC test, simply wait until it is done.", 75 "The result (passed or failed) will be shown in the", 76 "message window below." 77 }; 78 Sysout.createDialog( ); 79 Sysout.printInstructions( instructions ); 80 81 frame = new Frame("Test Frame"); 82 frame.setLayout(new FlowLayout()); 83 84 panel = new Panel(); 85 button = new Button("Button"); 86 label = new Label("Label"); 87 88 components = new Component[] { 89 panel, button, label 90 }; 91 92 frame.setSize(300, 300); 93 frame.setVisible(true); 94 95 Robot robot = Util.createRobot(); 96 robot.setAutoDelay(20); 97 98 // To ensure the window is shown and packed 99 Util.waitForIdle(robot); 100 101 Insets insets = frame.getInsets(); 102 if (insets.right == 0 || insets.bottom == 0) { 103 // Because we want to catch the "size-grip" of the frame. 104 System.out.println("The test environment must have non-zero right & bottom insets! The current insets are: " + insets); 105 pass(); 106 return; 107 } 108 109 // Let's move the mouse pointer to the bottom-right coner of the frame (the "size-grip") 110 Rectangle bounds = frame.getBounds(); 111 112 robot.mouseMove(bounds.x + bounds.width - 1, bounds.y + bounds.height - 1); 113 114 // From now on the ANCESTOR_RESIZED events get counted. 115 HierarchyBoundsListener listener = new HierarchyBoundsListenerImpl(); 116 for (int i = 0; i < components.length; i++) { 117 components[i].addHierarchyBoundsListener(listener); 118 frame.add(components[i]); 119 } 120 121 // ... and start resizing 122 robot.mousePress( InputEvent.BUTTON1_MASK ); 123 robot.mouseMove(bounds.x + bounds.width + 20, bounds.y + bounds.height + 15); 124 Util.waitForIdle(robot); 125 126 if (ancestorResizedCounter == 0) { 127 robot.mouseRelease( InputEvent.BUTTON1_MASK ); 128 AncestorResized.fail("No ANCESTOR_RESIZED events received."); 129 return; 130 } 131 132 robot.mouseRelease( InputEvent.BUTTON1_MASK ); 133 134 AncestorResized.pass(); 135 }//End init() 136 137 138 139 /***************************************************** 140 * Standard Test Machinery Section 141 * DO NOT modify anything in this section -- it's a 142 * standard chunk of code which has all of the 143 * synchronisation necessary for the test harness. 144 * By keeping it the same in all tests, it is easier 145 * to read and understand someone else's test, as 146 * well as insuring that all tests behave correctly 147 * with the test harness. 148 * There is a section following this for test- 149 * classes 150 ******************************************************/ 151 private static boolean theTestPassed = false; 152 private static boolean testGeneratedInterrupt = false; 153 private static String failureMessage = ""; 154 155 private static Thread mainThread = null; 156 157 private static int sleepTime = 300000; 158 159 // Not sure about what happens if multiple of this test are 160 // instantiated in the same VM. Being static (and using 161 // static vars), it aint gonna work. Not worrying about 162 // it for now. 163 public static void main( String args[] ) throws InterruptedException 164 { 165 mainThread = Thread.currentThread(); 166 try 167 { 168 init(); 169 } 170 catch( TestPassedException e ) 171 { 172 //The test passed, so just return from main and harness will 173 // interepret this return as a pass 174 return; 175 } 176 //At this point, neither test pass nor test fail has been 177 // called -- either would have thrown an exception and ended the 178 // test, so we know we have multiple threads. 179 180 //Test involves other threads, so sleep and wait for them to 181 // called pass() or fail() 182 try 183 { 184 Thread.sleep( sleepTime ); 185 //Timed out, so fail the test 186 throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); 187 } 188 catch (InterruptedException e) 189 { 190 //The test harness may have interrupted the test. If so, rethrow the exception 191 // so that the harness gets it and deals with it. 192 if( ! testGeneratedInterrupt ) throw e; 193 194 //reset flag in case hit this code more than once for some reason (just safety) 195 testGeneratedInterrupt = false; 196 197 if ( theTestPassed == false ) 198 { 199 throw new RuntimeException( failureMessage ); 200 } 201 } 202 203 }//main 204 205 public static synchronized void setTimeoutTo( int seconds ) 206 { 207 sleepTime = seconds * 1000; 208 } 209 210 public static synchronized void pass() 211 { 212 Sysout.println( "The test passed." ); 213 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 214 //first check if this is executing in main thread 215 if ( mainThread == Thread.currentThread() ) 216 { 217 //Still in the main thread, so set the flag just for kicks, 218 // and throw a test passed exception which will be caught 219 // and end the test. 220 theTestPassed = true; 221 throw new TestPassedException(); 222 } 223 theTestPassed = true; 224 testGeneratedInterrupt = true; 225 mainThread.interrupt(); 226 }//pass() 227 228 public static synchronized void fail() 229 { 230 //test writer didn't specify why test failed, so give generic 231 fail( "it just plain failed! :-)" ); 232 } 233 234 public static synchronized void fail( String whyFailed ) 235 { 236 Sysout.println( "The test failed: " + whyFailed ); 237 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 238 //check if this called from main thread 239 if ( mainThread == Thread.currentThread() ) 240 { 241 //If main thread, fail now 'cause not sleeping 242 throw new RuntimeException( whyFailed ); 243 } 244 theTestPassed = false; 245 testGeneratedInterrupt = true; 246 failureMessage = whyFailed; 247 mainThread.interrupt(); 248 }//fail() 249 250 }// class AncestorResized 251 252 //This exception is used to exit from any level of call nesting 253 // when it's determined that the test has passed, and immediately 254 // end the test. 255 class TestPassedException extends RuntimeException 256 { 257 } 258 259 //*********** End Standard Test Machinery Section ********** 260 261 262 //************ Begin classes defined for the test **************** 263 264 // if want to make listeners, here is the recommended place for them, then instantiate 265 // them in init() 266 267 /* Example of a class which may be written as part of a test 268 class NewClass implements anInterface 269 { 270 static int newVar = 0; 271 272 public void eventDispatched(AWTEvent e) 273 { 274 //Counting events to see if we get enough 275 eventCount++; 276 277 if( eventCount == 20 ) 278 { 279 //got enough events, so pass 280 281 AncestorResized.pass(); 282 } 283 else if( tries == 20 ) 284 { 285 //tried too many times without getting enough events so fail 286 287 AncestorResized.fail(); 288 } 289 290 }// eventDispatched() 291 292 }// NewClass class 293 294 */ 295 296 297 //************** End classes defined for the test ******************* 298 299 300 301 302 /**************************************************** 303 Standard Test Machinery 304 DO NOT modify anything below -- it's a standard 305 chunk of code whose purpose is to make user 306 interaction uniform, and thereby make it simpler 307 to read and understand someone else's test. 308 ****************************************************/ 309 310 /** 311 This is part of the standard test machinery. 312 It creates a dialog (with the instructions), and is the interface 313 for sending text messages to the user. 314 To print the instructions, send an array of strings to Sysout.createDialog 315 WithInstructions method. Put one line of instructions per array entry. 316 To display a message for the tester to see, simply call Sysout.println 317 with the string to be displayed. 318 This mimics System.out.println but works within the test harness as well 319 as standalone. 320 */ 321 322 class Sysout 323 { 324 private static TestDialog dialog; 325 326 public static void createDialogWithInstructions( String[] instructions ) 327 { 328 dialog = new TestDialog( new Frame(), "Instructions" ); 329 dialog.printInstructions( instructions ); 330 dialog.setVisible(true); 331 println( "Any messages for the tester will display here." ); 332 } 333 334 public static void createDialog( ) 335 { 336 dialog = new TestDialog( new Frame(), "Instructions" ); 337 String[] defInstr = { "Instructions will appear here. ", "" } ; 338 dialog.printInstructions( defInstr ); 339 dialog.setVisible(true); 340 println( "Any messages for the tester will display here." ); 341 } 342 343 344 public static void printInstructions( String[] instructions ) 345 { 346 dialog.printInstructions( instructions ); 347 } 348 349 350 public static void println( String messageIn ) 351 { 352 dialog.displayMessage( messageIn ); 353 System.out.println(messageIn); 354 } 355 356 }// Sysout class 357 358 /** 359 This is part of the standard test machinery. It provides a place for the 360 test instructions to be displayed, and a place for interactive messages 361 to the user to be displayed. 362 To have the test instructions displayed, see Sysout. 363 To have a message to the user be displayed, see Sysout. 364 Do not call anything in this dialog directly. 365 */ 366 class TestDialog extends Dialog 367 { 368 369 TextArea instructionsText; 370 TextArea messageText; 371 int maxStringLength = 80; 372 373 //DO NOT call this directly, go through Sysout 374 public TestDialog( Frame frame, String name ) 375 { 376 super( frame, name ); 377 int scrollBoth = TextArea.SCROLLBARS_BOTH; 378 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 379 add( "North", instructionsText ); 380 381 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 382 add("Center", messageText); 383 384 pack(); 385 386 setVisible(true); 387 }// TestDialog() 388 389 //DO NOT call this directly, go through Sysout 390 public void printInstructions( String[] instructions ) 391 { 392 //Clear out any current instructions 393 instructionsText.setText( "" ); 394 395 //Go down array of instruction strings 396 397 String printStr, remainingStr; 398 for( int i=0; i < instructions.length; i++ ) 399 { 400 //chop up each into pieces maxSringLength long 401 remainingStr = instructions[ i ]; 402 while( remainingStr.length() > 0 ) 403 { 404 //if longer than max then chop off first max chars to print 405 if( remainingStr.length() >= maxStringLength ) 406 { 407 //Try to chop on a word boundary 408 int posOfSpace = remainingStr. 409 lastIndexOf( ' ', maxStringLength - 1 ); 410 411 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 412 413 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 414 remainingStr = remainingStr.substring( posOfSpace + 1 ); 415 } 416 //else just print 417 else 418 { 419 printStr = remainingStr; 420 remainingStr = ""; 421 } 422 423 instructionsText.append( printStr + "\n" ); 424 425 }// while 426 427 }// for 428 429 }//printInstructions() 430 431 //DO NOT call this directly, go through Sysout 432 public void displayMessage( String messageIn ) 433 { 434 messageText.append( messageIn + "\n" ); 435 System.out.println(messageIn); 436 } 437 438 }// TestDialog class