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