1 /* 2 * Copyright (c) 2007, 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 6187066 27 @summary Tests the Window.autoRequestFocus property for the Window.setVisible() method. 28 @author anton.tarasov: area=awt.focus 29 @library ../../regtesthelpers 30 @build Util 31 @run main AutoRequestFocusSetVisibleTest 32 */ 33 34 import java.awt.*; 35 import java.awt.event.*; 36 import java.applet.Applet; 37 import java.util.concurrent.atomic.AtomicBoolean; 38 import java.lang.reflect.InvocationTargetException; 39 import test.java.awt.regtesthelpers.Util; 40 41 public class AutoRequestFocusSetVisibleTest extends Applet { 42 static Frame focusedFrame; 43 static Button focusOwner; 44 static Frame frame; 45 static Button frameButton; 46 static Frame frame2; 47 static Button frameButton2; 48 static Window window; 49 static Button winButton; 50 static Window ownedWindow; 51 static Button ownWinButton; 52 static Dialog ownedDialog; 53 static Button ownDlgButton; 54 static Dialog dialog; 55 static Button dlgButton; 56 57 static String toolkitClassName; 58 static Robot robot = Util.createRobot(); 59 60 public static void main(String[] args) { 61 AutoRequestFocusSetVisibleTest app = new AutoRequestFocusSetVisibleTest(); 62 app.init(); 63 app.start(); 64 } 65 66 public void init() { 67 // Create instructions for the user here, as well as set up 68 // the environment -- set the layout manager, add buttons, 69 // etc. 70 this.setLayout (new BorderLayout ()); 71 Sysout.createDialogWithInstructions(new String[] 72 {"This is an automatic test. Simply wait until it is done." 73 }); 74 toolkitClassName = Toolkit.getDefaultToolkit().getClass().getName(); 75 } 76 77 void recreateGUI() { 78 if (focusedFrame != null) { 79 focusedFrame.dispose(); 80 frame.dispose(); 81 frame2.dispose(); 82 window.dispose(); 83 ownedWindow.dispose(); 84 ownedDialog.dispose(); 85 dialog.dispose(); 86 } 87 88 focusedFrame = new Frame("Base Frame"); 89 focusOwner = new Button("button"); 90 91 frame = new Frame("Test Frame"); 92 frameButton = new Button("button"); 93 94 frame2 = new Frame("Test Frame"); 95 frameButton2 = new Button("button"); 96 97 window = new Window(focusedFrame); 98 winButton = new Button("button"); 99 100 ownedWindow = new Window(frame) { 101 /* 102 * When 'frame' is shown along with the 'ownedWindow' 103 * (i.e. showWithParent==true) then it can appear 104 * that the 'ownedWindow' is shown too early and 105 * it can't be focused due to its owner can't be 106 * yet activated. So, to avoid this race, we pospone 107 * a little the showing of the 'ownedWindow'. 108 */ 109 public void show() { 110 robot.delay(100); 111 super.show(); 112 } 113 }; 114 ownWinButton = new Button("button"); 115 116 ownedDialog = new Dialog(frame2); 117 ownDlgButton = new Button("button"); 118 119 dialog = new Dialog(focusedFrame, "Test Dialog"); 120 dlgButton = new Button("button"); 121 122 focusedFrame.add(focusOwner); 123 focusedFrame.setBounds(100, 100, 300, 300); 124 125 frame.setBounds(140, 140, 220, 220); 126 frame.add(frameButton); 127 128 frame2.setBounds(140, 140, 220, 220); 129 frame2.add(frameButton2); 130 131 window.setBounds(140, 140, 220, 220); 132 window.add(winButton); 133 134 ownedWindow.setBounds(180, 180, 140, 140); 135 ownedWindow.add(ownWinButton); 136 137 ownedDialog.setBounds(180, 180, 140, 140); 138 ownedDialog.add(ownDlgButton); 139 140 dialog.setBounds(140, 140, 220, 220); 141 dialog.add(dlgButton); 142 } 143 144 public void start() { 145 146 /////////////////////////////////////////////////////// 147 // 1. Show Frame with owned modal Dialog without delay. 148 // Check that the Dialog takes focus. 149 /////////////////////////////////////////////////////// 150 151 recreateGUI(); 152 153 Sysout.println("Stage 1 in progress..."); 154 155 dialog.setModal(true); 156 dialog.setAutoRequestFocus(false); 157 setVisible(focusedFrame, true); 158 159 TestHelper.invokeLaterAndWait(new Runnable() { 160 public void run() { 161 dialog.setVisible(true); 162 } 163 }, robot); 164 165 if (focusOwner.hasFocus()) { 166 throw new TestFailedException("the modal dialog must gain focus but it didn't!"); 167 } 168 setVisible(dialog, false); 169 170 ////////////////////////////////////////////////// 171 // 2. Show Frame, activate, auto hide, auto show. 172 // Check that the Frame takes focus. 173 ////////////////////////////////////////////////// 174 175 recreateGUI(); 176 177 Sysout.println("Stage 2 in progress..."); 178 179 setVisible(focusedFrame, false); 180 181 focusedFrame.setAutoRequestFocus(false); 182 setVisible(focusedFrame, true); 183 184 Util.clickOnTitle(focusedFrame, robot); 185 Util.waitForIdle(robot); 186 187 if (!focusedFrame.isFocused()) { 188 throw new Error("Test error: the frame couldn't be focused."); 189 } 190 191 focusedFrame.setExtendedState(Frame.ICONIFIED); 192 Util.waitForIdle(robot); 193 focusedFrame.setExtendedState(Frame.NORMAL); 194 Util.waitForIdle(robot); 195 196 if (!focusedFrame.isFocused()) { 197 throw new TestFailedException("the restored frame must gain focus but it didn't!"); 198 } 199 200 201 //////////////////////// 202 // 3.1 Show Frame normal. 203 //////////////////////// 204 205 recreateGUI(); 206 207 test("Stage 3.1 in progress...", frame, frameButton); 208 209 210 // 3.2. Show Frame maximized both. 211 ///////////////////////////////// 212 213 if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) { 214 System.out.println("Stage 3.2: Frame.MAXIMIZED_BOTH not supported. Skipping."); 215 } else { 216 frame.setExtendedState(Frame.MAXIMIZED_BOTH); 217 218 test("Stage 3.2 in progress...", frame, frameButton); 219 } 220 221 222 // 3.3. Show Frame maximized vertically. 223 /////////////////////////////////////// 224 225 if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_VERT)) { 226 System.out.println("Stage 3.3: Frame.MAXIMIZED_VERT not supported. Skipping."); 227 } else { 228 frame.setExtendedState(Frame.MAXIMIZED_VERT); 229 230 test("Stage 3.3 in progress...", frame, frameButton); 231 } 232 233 234 // 3.4. Show Frame maximized horizontally. 235 ///////////////////////////////////////// 236 237 if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_HORIZ)) { 238 System.out.println("Stage 3.4: Frame.MAXIMIZED_HORIZ not supported. Skipping."); 239 } else { 240 frame.setExtendedState(Frame.MAXIMIZED_HORIZ); 241 242 test("Stage 3.4 in progress...", frame, frameButton); 243 } 244 245 246 // 3.5. Show Frame iconified. 247 //////////////////////////// 248 249 if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.ICONIFIED)) { 250 System.out.println("Stage 3.5: Frame.ICONIFIED not supported. Skipping."); 251 } else { 252 frame.setExtendedState(Frame.ICONIFIED); 253 254 test("Stage 3.5 in progress...", frame, frameButton); 255 } 256 257 258 /////////////////// 259 // 4.1 Show Window. 260 /////////////////// 261 recreateGUI(); 262 test("Stage 4.1 in progress...", window, winButton); 263 264 265 // 4.2 Show Dialog. 266 ////////////////// 267 268 test("Stage 4.2 in progress...", dialog, dlgButton); 269 270 271 // 4.3. Show modal Dialog. 272 ///////////////////////// 273 274 dialog.setModal(true); 275 test("Stage 4.3 in progress...", dialog, dlgButton, true); 276 277 278 /////////////////////////////////// 279 // 5.1 Show Frame with owned Window. 280 /////////////////////////////////// 281 282 // On Windows, an owned Window will not be focused on its showing 283 // if the owner is not currently active. 284 if ("sun.awt.windows.WToolkit".equals(toolkitClassName)) { 285 Sysout.println("Stage 5.1 - Skiping."); 286 } else { 287 setVisible(ownedWindow, true); 288 setVisible(frame, false); // 'ownedWindow' will be shown along with the owner. 289 290 test("Stage 5.1 in progress...", frame, ownedWindow, ownWinButton, true); 291 } 292 293 294 // 5.2 Show Frame with owned Dialog. 295 /////////////////////////////////// 296 297 setVisible(ownedDialog, true); 298 setVisible(frame2, false); // 'ownedDialog' will be shown along with the owner. 299 300 test("Stage 5.2 in progress...", frame2, ownedDialog, ownDlgButton, true); 301 302 303 /////////////////////////////////// 304 // 6. Show unblocking modal Dialog. 305 /////////////////////////////////// 306 307 if ("sun.awt.motif.MToolkit".equals(toolkitClassName)) { 308 Sysout.println("Stage 6 - Skiping."); 309 } else { 310 Sysout.println("Stage 6 in progress..."); 311 312 // --- 313 // Testing the bug of activating invisible modal Dialog (awt_Window::SetAndActivateModalBlocker). 314 // Having some window not excluded from modality, so that it would be blocked. 315 Frame f = new Frame("Aux. Frame"); 316 f.setSize(100, 100); 317 setVisible(f, true); 318 // --- 319 320 setVisible(focusedFrame, true); 321 if (!focusOwner.hasFocus()) { 322 Util.clickOnComp(focusOwner, robot); 323 Util.waitForIdle(robot); 324 if (!focusOwner.hasFocus()) { 325 throw new Error("Test error: the frame couldn't be focused."); 326 } 327 } 328 329 dialog.setModal(true); 330 dialog.setAutoRequestFocus(false); 331 focusedFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); 332 333 TestHelper.invokeLaterAndWait(new Runnable() { 334 public void run() { 335 dialog.setVisible(true); 336 } 337 }, robot); 338 339 if (dialog.isFocused()) { 340 throw new TestFailedException("the unblocking dialog shouldn't gain focus but it did!"); 341 } 342 setVisible(dialog, false); 343 } 344 345 Sysout.println("Test passed."); 346 } 347 348 /* 349 * @param msg notifies test stage number 350 * @param showWindow a window to show/test (if ownedWindow == null) 351 * @param ownedWindow an owned window to show/test, or null if showWindow should be tested 352 * @param clickButton a button of the window (owner or owned) expected to be on the top of stack order 353 * @param shouldFocusChange true the test window should gain focus 354 */ 355 void test(String msg, final Window showWindow, Window ownedWindow, final Button clickButton, boolean shouldFocusChange) { 356 Window testWindow = (ownedWindow == null ? showWindow : ownedWindow); 357 358 Sysout.println(msg); 359 360 if (showWindow.isVisible()) { 361 showWindow.dispose(); 362 Util.waitForIdle(robot); 363 } 364 if (!focusedFrame.isVisible()) { 365 setVisible(focusedFrame, true); 366 } 367 if (!focusOwner.hasFocus()) { 368 Util.clickOnComp(focusOwner, robot); 369 Util.waitForIdle(robot); 370 if (!focusOwner.hasFocus()) { 371 throw new Error("Test error: the frame couldn't be focused."); 372 } 373 } 374 375 ////////////////////////////////////////// 376 // Test focus change on showing the window 377 ////////////////////////////////////////// 378 379 final Runnable showAction = new Runnable() { 380 public void run() { 381 showWindow.setAutoRequestFocus(false); 382 showWindow.setVisible(true); 383 } 384 }; 385 386 final Runnable trackerAction = new Runnable() { 387 public void run() { 388 if (showWindow instanceof Dialog && ((Dialog)showWindow).isModal()) { 389 TestHelper.invokeLaterAndWait(showAction, robot); 390 } else { 391 showAction.run(); 392 } 393 } 394 }; 395 396 if (shouldFocusChange) { 397 trackerAction.run(); 398 Util.waitForIdle(robot); 399 400 if (!testWindow.isFocused()) { 401 throw new TestFailedException("the window must gain focus but it didn't!"); 402 } 403 404 } else if (TestHelper.trackFocusChangeFor(trackerAction, robot)) { 405 throw new TestFailedException("the window shouldn't gain focus but it did!"); 406 } 407 408 409 //////////////////////////////////////////// 410 // Test that the window was shown on the top. 411 // Test that it can be focused. 412 //////////////////////////////////////////// 413 414 if (!(testWindow instanceof Frame) || 415 ((Frame)testWindow).getExtendedState() != Frame.ICONIFIED) 416 { 417 boolean performed = Util.trackActionPerformed(clickButton, new Runnable() { 418 public void run() { 419 /* 420 * If 'showWindow' is not on the top then 421 * 'focusOwner' button completely overlaps 'clickButton' 422 * and we won't catch the action. 423 */ 424 Util.clickOnComp(clickButton, robot); 425 } 426 }, 1000, false); 427 428 if (!performed) { 429 // In case of loosing ACTION_PERFORMED, try once more. 430 Sysout.println("(ACTION_EVENT was not generated. One more attemp.)"); 431 performed = Util.trackActionPerformed(clickButton, new Runnable() { 432 public void run() { 433 Util.clickOnComp(clickButton, robot); 434 } 435 }, 1000, false); 436 437 if (!performed) { 438 throw new TestFailedException("the window shown is not on the top!"); 439 } 440 } 441 } 442 443 recreateGUI(); 444 } 445 446 void test(String msg, final Window showWindow, Button clickButton) { 447 test(msg, showWindow, null, clickButton, false); 448 } 449 void test(String msg, final Window showWindow, Button clickButton, boolean shouldFocusChange) { 450 test(msg, showWindow, null, clickButton, shouldFocusChange); 451 } 452 void test(String msg, final Window showWindow, Window ownedWindow, Button clickButton) { 453 test(msg, showWindow, ownedWindow, clickButton, false); 454 } 455 456 private static void setVisible(Window w, boolean b) { 457 w.setVisible(b); 458 try { 459 Util.waitForIdle(robot); 460 } catch (RuntimeException rte) { // InfiniteLoop 461 rte.printStackTrace(); 462 } 463 robot.delay(200); 464 } 465 } 466 467 class TestFailedException extends RuntimeException { 468 TestFailedException(String msg) { 469 super("Test failed: " + msg); 470 } 471 } 472 473 /**************************************************** 474 Standard Test Machinery 475 DO NOT modify anything below -- it's a standard 476 chunk of code whose purpose is to make user 477 interaction uniform, and thereby make it simpler 478 to read and understand someone else's test. 479 ****************************************************/ 480 481 /** 482 This is part of the standard test machinery. 483 It creates a dialog (with the instructions), and is the interface 484 for sending text messages to the user. 485 To print the instructions, send an array of strings to Sysout.createDialog 486 WithInstructions method. Put one line of instructions per array entry. 487 To display a message for the tester to see, simply call Sysout.println 488 with the string to be displayed. 489 This mimics System.out.println but works within the test harness as well 490 as standalone. 491 */ 492 493 class Sysout 494 { 495 static TestDialog dialog; 496 497 public static void createDialogWithInstructions( String[] instructions ) 498 { 499 dialog = new TestDialog( new Frame(), "Instructions" ); 500 dialog.printInstructions( instructions ); 501 // dialog.setVisible(true); 502 println( "Any messages for the tester will display here." ); 503 } 504 505 public static void createDialog( ) 506 { 507 dialog = new TestDialog( new Frame(), "Instructions" ); 508 String[] defInstr = { "Instructions will appear here. ", "" } ; 509 dialog.printInstructions( defInstr ); 510 // dialog.setVisible(true); 511 println( "Any messages for the tester will display here." ); 512 } 513 514 515 public static void printInstructions( String[] instructions ) 516 { 517 dialog.printInstructions( instructions ); 518 } 519 520 521 public static void println( String messageIn ) 522 { 523 dialog.displayMessage( messageIn ); 524 } 525 526 }// Sysout class 527 528 /** 529 This is part of the standard test machinery. It provides a place for the 530 test instructions to be displayed, and a place for interactive messages 531 to the user to be displayed. 532 To have the test instructions displayed, see Sysout. 533 To have a message to the user be displayed, see Sysout. 534 Do not call anything in this dialog directly. 535 */ 536 class TestDialog extends Dialog 537 { 538 539 TextArea instructionsText; 540 TextArea messageText; 541 int maxStringLength = 80; 542 543 //DO NOT call this directly, go through Sysout 544 public TestDialog( Frame frame, String name ) 545 { 546 super( frame, name ); 547 int scrollBoth = TextArea.SCROLLBARS_BOTH; 548 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 549 add( "North", instructionsText ); 550 551 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 552 add("Center", messageText); 553 554 pack(); 555 556 // setVisible(true); 557 }// TestDialog() 558 559 //DO NOT call this directly, go through Sysout 560 public void printInstructions( String[] instructions ) 561 { 562 //Clear out any current instructions 563 instructionsText.setText( "" ); 564 565 //Go down array of instruction strings 566 567 String printStr, remainingStr; 568 for( int i=0; i < instructions.length; i++ ) 569 { 570 //chop up each into pieces maxSringLength long 571 remainingStr = instructions[ i ]; 572 while( remainingStr.length() > 0 ) 573 { 574 //if longer than max then chop off first max chars to print 575 if( remainingStr.length() >= maxStringLength ) 576 { 577 //Try to chop on a word boundary 578 int posOfSpace = remainingStr. 579 lastIndexOf( ' ', maxStringLength - 1 ); 580 581 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 582 583 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 584 remainingStr = remainingStr.substring( posOfSpace + 1 ); 585 } 586 //else just print 587 else 588 { 589 printStr = remainingStr; 590 remainingStr = ""; 591 } 592 593 instructionsText.append( printStr + "\n" ); 594 595 }// while 596 597 }// for 598 599 }//printInstructions() 600 601 //DO NOT call this directly, go through Sysout 602 public void displayMessage( String messageIn ) 603 { 604 messageText.append( messageIn + "\n" ); 605 System.out.println(messageIn); 606 } 607 608 }// TestDialog class