1 /*
   2  * Copyright (c) 2007, 2018, 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   @library    ../../regtesthelpers
  30   @build      Util
  31   @run       main AutoRequestFocusSetVisibleTest
  32 */
  33 
  34 import java.awt.*;
  35 import test.java.awt.regtesthelpers.Util;
  36 
  37 public class AutoRequestFocusSetVisibleTest {
  38     static Frame focusedFrame;
  39     static Button focusOwner;
  40     static Frame frame;
  41     static Button frameButton;
  42     static Frame frame2;
  43     static Button frameButton2;
  44     static Window window;
  45     static Button winButton;
  46     static Window ownedWindow;
  47     static Button ownWinButton;
  48     static Dialog ownedDialog;
  49     static Button ownDlgButton;
  50     static Dialog dialog;
  51     static Button dlgButton;
  52 
  53     static String toolkitClassName;
  54     static Robot robot = Util.createRobot();
  55 
  56     public static void main(String[] args) {
  57         AutoRequestFocusSetVisibleTest app = new AutoRequestFocusSetVisibleTest();
  58         app.init();
  59         app.start();
  60     }
  61 
  62     public void init() {
  63         toolkitClassName = Toolkit.getDefaultToolkit().getClass().getName();
  64     }
  65 
  66     void recreateGUI() {
  67         if (focusedFrame != null) {
  68             focusedFrame.dispose();
  69             frame.dispose();
  70             frame2.dispose();
  71             window.dispose();
  72             ownedWindow.dispose();
  73             ownedDialog.dispose();
  74             dialog.dispose();
  75         }
  76 
  77         focusedFrame = new Frame("Base Frame");
  78         focusOwner = new Button("button");
  79 
  80         frame = new Frame("Test Frame");
  81         frameButton = new Button("button");
  82 
  83         frame2 = new Frame("Test Frame");
  84         frameButton2 = new Button("button");
  85 
  86         window = new Window(focusedFrame);
  87         winButton = new Button("button");
  88 
  89         ownedWindow = new Window(frame) {
  90                 /*
  91                  * When 'frame' is shown along with the 'ownedWindow'
  92                  * (i.e. showWithParent==true) then it can appear
  93                  * that the 'ownedWindow' is shown too early and
  94                  * it can't be focused due to its owner can't be
  95                  * yet activated. So, to avoid this race, we pospone
  96                  * a little the showing of the 'ownedWindow'.
  97                  */
  98                 public void show() {
  99                     robot.delay(100);
 100                     super.show();
 101                 }
 102             };
 103         ownWinButton = new Button("button");
 104 
 105         ownedDialog = new Dialog(frame2);
 106         ownDlgButton = new Button("button");
 107 
 108         dialog = new Dialog(focusedFrame, "Test Dialog");
 109         dlgButton = new Button("button");
 110 
 111         focusedFrame.add(focusOwner);
 112         focusedFrame.setBounds(100, 100, 300, 300);
 113 
 114         frame.setBounds(140, 140, 220, 220);
 115         frame.add(frameButton);
 116 
 117         frame2.setBounds(140, 140, 220, 220);
 118         frame2.add(frameButton2);
 119 
 120         window.setBounds(140, 140, 220, 220);
 121         window.add(winButton);
 122 
 123         ownedWindow.setBounds(180, 180, 140, 140);
 124         ownedWindow.add(ownWinButton);
 125 
 126         ownedDialog.setBounds(180, 180, 140, 140);
 127         ownedDialog.add(ownDlgButton);
 128 
 129         dialog.setBounds(140, 140, 220, 220);
 130         dialog.add(dlgButton);
 131     }
 132 
 133     public void start() {
 134 
 135         ///////////////////////////////////////////////////////
 136         // 1. Show Frame with owned modal Dialog without delay.
 137         //    Check that the Dialog takes focus.
 138         ///////////////////////////////////////////////////////
 139 
 140         recreateGUI();
 141 
 142         System.out.println("Stage 1 in progress...");
 143 
 144         dialog.setModal(true);
 145         dialog.setAutoRequestFocus(false);
 146         setVisible(focusedFrame, true);
 147 
 148         TestHelper.invokeLaterAndWait(new Runnable() {
 149                 public void run() {
 150                     dialog.setVisible(true);
 151                 }
 152             }, robot);
 153 
 154         if (focusOwner.hasFocus()) {
 155             throw new TestFailedException("the modal dialog must gain focus but it didn't!");
 156         }
 157         setVisible(dialog, false);
 158 
 159         //////////////////////////////////////////////////
 160         // 2. Show Frame, activate, auto hide, auto show.
 161         //    Check that the Frame takes focus.
 162         //////////////////////////////////////////////////
 163 
 164         recreateGUI();
 165 
 166         System.out.println("Stage 2 in progress...");
 167 
 168         setVisible(focusedFrame, false);
 169 
 170         focusedFrame.setAutoRequestFocus(false);
 171         setVisible(focusedFrame, true);
 172 
 173         Util.clickOnTitle(focusedFrame, robot);
 174         Util.waitForIdle(robot);
 175 
 176         if (!focusedFrame.isFocused()) {
 177             throw new Error("Test error: the frame couldn't be focused.");
 178         }
 179 
 180         focusedFrame.setExtendedState(Frame.ICONIFIED);
 181         Util.waitForIdle(robot);
 182         focusedFrame.setExtendedState(Frame.NORMAL);
 183         Util.waitForIdle(robot);
 184 
 185         if (!focusedFrame.isFocused()) {
 186             throw new TestFailedException("the restored frame must gain focus but it didn't!");
 187         }
 188 
 189 
 190         ////////////////////////
 191         // 3.1 Show Frame normal.
 192         ////////////////////////
 193 
 194         recreateGUI();
 195 
 196         test("Stage 3.1 in progress...", frame, frameButton);
 197 
 198 
 199         // 3.2. Show Frame maximized both.
 200         /////////////////////////////////
 201 
 202         if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
 203             System.out.println("Stage 3.2: Frame.MAXIMIZED_BOTH not supported. Skipping.");
 204         } else {
 205             frame.setExtendedState(Frame.MAXIMIZED_BOTH);
 206 
 207             test("Stage 3.2 in progress...", frame, frameButton);
 208         }
 209 
 210 
 211         // 3.3. Show Frame maximized vertically.
 212         ///////////////////////////////////////
 213 
 214         if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_VERT)) {
 215             System.out.println("Stage 3.3: Frame.MAXIMIZED_VERT not supported. Skipping.");
 216         } else {
 217             frame.setExtendedState(Frame.MAXIMIZED_VERT);
 218 
 219             test("Stage 3.3 in progress...", frame, frameButton);
 220         }
 221 
 222 
 223         // 3.4. Show Frame maximized horizontally.
 224         /////////////////////////////////////////
 225 
 226         if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_HORIZ)) {
 227             System.out.println("Stage 3.4: Frame.MAXIMIZED_HORIZ not supported. Skipping.");
 228         } else {
 229             frame.setExtendedState(Frame.MAXIMIZED_HORIZ);
 230 
 231             test("Stage 3.4 in progress...", frame, frameButton);
 232         }
 233 
 234 
 235         // 3.5. Show Frame iconified.
 236         ////////////////////////////
 237 
 238         if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.ICONIFIED)) {
 239             System.out.println("Stage 3.5: Frame.ICONIFIED not supported. Skipping.");
 240         } else {
 241             frame.setExtendedState(Frame.ICONIFIED);
 242 
 243             test("Stage 3.5 in progress...", frame, frameButton);
 244         }
 245 
 246 
 247         ///////////////////
 248         // 4.1 Show Window.
 249         ///////////////////
 250         recreateGUI();
 251         test("Stage 4.1 in progress...", window, winButton);
 252 
 253 
 254         // 4.2 Show Dialog.
 255         //////////////////
 256 
 257         test("Stage 4.2 in progress...", dialog, dlgButton);
 258 
 259 
 260         // 4.3. Show modal Dialog.
 261         /////////////////////////
 262 
 263         dialog.setModal(true);
 264         test("Stage 4.3 in progress...", dialog, dlgButton, true);
 265 
 266 
 267         ///////////////////////////////////
 268         // 5.1 Show Frame with owned Window.
 269         ///////////////////////////////////
 270 
 271         // On Windows, an owned Window will not be focused on its showing
 272         // if the owner is not currently active.
 273         if ("sun.awt.windows.WToolkit".equals(toolkitClassName)) {
 274             System.out.println("Stage 5.1 - Skiping.");
 275         } else {
 276             setVisible(ownedWindow, true);
 277             setVisible(frame, false); // 'ownedWindow' will be shown along with the owner.
 278 
 279             test("Stage 5.1 in progress...", frame, ownedWindow, ownWinButton, true);
 280         }
 281 
 282 
 283         // 5.2 Show Frame with owned Dialog.
 284         ///////////////////////////////////
 285 
 286         setVisible(ownedDialog, true);
 287         setVisible(frame2, false); // 'ownedDialog' will be shown along with the owner.
 288 
 289         test("Stage 5.2 in progress...", frame2, ownedDialog, ownDlgButton, true);
 290 
 291 
 292         ///////////////////////////////////
 293         // 6. Show unblocking modal Dialog.
 294         ///////////////////////////////////
 295 
 296         if ("sun.awt.motif.MToolkit".equals(toolkitClassName)) {
 297             System.out.println("Stage 6 - Skiping.");
 298         } else {
 299             System.out.println("Stage 6 in progress...");
 300 
 301             // ---
 302             // Testing the bug of activating invisible modal Dialog (awt_Window::SetAndActivateModalBlocker).
 303             // Having some window not excluded from modality, so that it would be blocked.
 304             Frame f = new Frame("Aux. Frame");
 305             f.setSize(100, 100);
 306             setVisible(f, true);
 307             // ---
 308 
 309             setVisible(focusedFrame, true);
 310             if (!focusOwner.hasFocus()) {
 311                 Util.clickOnComp(focusOwner, robot);
 312                 Util.waitForIdle(robot);
 313                 if (!focusOwner.hasFocus()) {
 314                     throw new Error("Test error: the frame couldn't be focused.");
 315                 }
 316             }
 317 
 318             dialog.setModal(true);
 319             dialog.setAutoRequestFocus(false);
 320             focusedFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
 321 
 322             TestHelper.invokeLaterAndWait(new Runnable() {
 323                     public void run() {
 324                         dialog.setVisible(true);
 325                     }
 326                 }, robot);
 327 
 328             if (dialog.isFocused()) {
 329                 throw new TestFailedException("the unblocking dialog shouldn't gain focus but it did!");
 330             }
 331             setVisible(dialog, false);
 332         }
 333 
 334         System.out.println("Test passed.");
 335     }
 336 
 337     /*
 338      * @param msg notifies test stage number
 339      * @param showWindow a window to show/test (if ownedWindow == null)
 340      * @param ownedWindow an owned window to show/test, or null if showWindow should be tested
 341      * @param clickButton a button of the window (owner or owned) expected to be on the top of stack order
 342      * @param shouldFocusChange true the test window should gain focus
 343      */
 344     void test(String msg, final Window showWindow, Window ownedWindow, final Button clickButton, boolean shouldFocusChange) {
 345         Window testWindow = (ownedWindow == null ? showWindow : ownedWindow);
 346 
 347         System.out.println(msg);
 348 
 349         if (showWindow.isVisible()) {
 350             showWindow.dispose();
 351             Util.waitForIdle(robot);
 352         }
 353         if (!focusedFrame.isVisible()) {
 354             setVisible(focusedFrame, true);
 355         }
 356         if (!focusOwner.hasFocus()) {
 357             Util.clickOnComp(focusOwner, robot);
 358             Util.waitForIdle(robot);
 359             if (!focusOwner.hasFocus()) {
 360                 throw new Error("Test error: the frame couldn't be focused.");
 361             }
 362         }
 363 
 364         //////////////////////////////////////////
 365         // Test focus change on showing the window
 366         //////////////////////////////////////////
 367 
 368         final Runnable showAction = new Runnable() {
 369                 public void run() {
 370                     showWindow.setAutoRequestFocus(false);
 371                     showWindow.setVisible(true);
 372                 }
 373             };
 374 
 375         final Runnable trackerAction = new Runnable() {
 376                 public void run() {
 377                     if (showWindow instanceof Dialog && ((Dialog)showWindow).isModal()) {
 378                         TestHelper.invokeLaterAndWait(showAction, robot);
 379                     } else {
 380                         showAction.run();
 381                     }
 382                 }
 383             };
 384 
 385         if (shouldFocusChange) {
 386             trackerAction.run();
 387             Util.waitForIdle(robot);
 388 
 389             if (!testWindow.isFocused()) {
 390                 throw new TestFailedException("the window must gain focus but it didn't!");
 391             }
 392 
 393         } else if (TestHelper.trackFocusChangeFor(trackerAction, robot)) {
 394             throw new TestFailedException("the window shouldn't gain focus but it did!");
 395         }
 396 
 397 
 398         ////////////////////////////////////////////
 399         // Test that the window was shown on the top.
 400         // Test that it can be focused.
 401         ////////////////////////////////////////////
 402 
 403         if (!(testWindow instanceof Frame) ||
 404             ((Frame)testWindow).getExtendedState() != Frame.ICONIFIED)
 405         {
 406             boolean performed = Util.trackActionPerformed(clickButton, new Runnable() {
 407                     public void run() {
 408                         /*
 409                          * If 'showWindow' is not on the top then
 410                          * 'focusOwner' button completely overlaps 'clickButton'
 411                          * and we won't catch the action.
 412                          */
 413                         Util.clickOnComp(clickButton, robot);
 414                     }
 415                 }, 1000, false);
 416 
 417             if (!performed) {
 418                 // In case of loosing ACTION_PERFORMED, try once more.
 419                 System.out.println("(ACTION_EVENT was not generated. One more attemp.)");
 420                 performed = Util.trackActionPerformed(clickButton, new Runnable() {
 421                         public void run() {
 422                             Util.clickOnComp(clickButton, robot);
 423                         }
 424                     }, 1000, false);
 425 
 426                 if (!performed) {
 427                     throw new TestFailedException("the window shown is not on the top!");
 428                 }
 429             }
 430         }
 431 
 432         recreateGUI();
 433     }
 434 
 435     void test(String msg, final Window showWindow, Button clickButton) {
 436         test(msg, showWindow, null, clickButton, false);
 437     }
 438     void test(String msg, final Window showWindow, Button clickButton, boolean shouldFocusChange) {
 439         test(msg, showWindow, null, clickButton, shouldFocusChange);
 440     }
 441     void test(String msg, final Window showWindow, Window ownedWindow, Button clickButton) {
 442         test(msg, showWindow, ownedWindow, clickButton, false);
 443     }
 444 
 445     private static void setVisible(Window w, boolean b) {
 446         w.setVisible(b);
 447         try {
 448             Util.waitForIdle(robot);
 449         } catch (RuntimeException rte) { // InfiniteLoop
 450             rte.printStackTrace();
 451         }
 452         robot.delay(200);
 453     }
 454 }
 455 
 456 class TestFailedException extends RuntimeException {
 457     TestFailedException(String msg) {
 458         super("Test failed: " + msg);
 459     }
 460 }