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