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