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.toFront() method.
  29   @author    anton.tarasov: area=awt.focus
  30   @library /java/awt/patchlib     ../../regtesthelpers
  31   @build java.desktop/java.awt.Helper
  32   @build      Util
  33   @run       main AutoRequestFocusToFrontTest
  34 */
  35 
  36 import java.awt.*;
  37 import java.awt.event.*;
  38 import java.applet.Applet;
  39 import java.util.concurrent.atomic.AtomicBoolean;
  40 import java.lang.reflect.InvocationTargetException;
  41 import test.java.awt.regtesthelpers.Util;
  42 
  43 public class AutoRequestFocusToFrontTest extends Applet {
  44     static boolean haveDelays;
  45 
  46     static Frame auxFrame;
  47     static Frame frame;
  48     static Button frameButton;
  49     static Frame frame2;
  50     static Button frameButton2;
  51     static Frame frame3;
  52     static Button frameButton3;
  53     static Window window;
  54     static Button winButton;
  55     static Dialog dialog;
  56     static Button dlgButton;
  57     static Window ownedWindow;
  58     static Button ownWinButton;
  59     static Dialog ownedDialog;
  60     static Button ownDlgButton;
  61     static Dialog modalDialog;
  62     static Button modalDlgButton;
  63 
  64     static String toolkitClassName;
  65     static Robot robot = Util.createRobot();
  66 
  67     public static void main(String[] args) {
  68 
  69         if (args.length != 0) {
  70             haveDelays = "delay".equals(args[0]) ? true : false;
  71         }
  72 
  73         AutoRequestFocusToFrontTest app = new AutoRequestFocusToFrontTest();
  74         app.init();
  75         app.start();
  76     }
  77 
  78     public void init() {
  79         // Create instructions for the user here, as well as set up
  80         // the environment -- set the layout manager, add buttons,
  81         // etc.
  82         this.setLayout (new BorderLayout ());
  83         toolkitClassName = Toolkit.getDefaultToolkit().getClass().getName();
  84     }
  85 
  86     static void recreateGUI() {
  87         if (auxFrame != null) {
  88             auxFrame.dispose();
  89             frame.dispose();
  90             frame2.dispose();
  91             frame3.dispose();
  92             window.dispose();
  93             dialog.dispose();
  94             ownedWindow.dispose();
  95             ownedDialog.dispose();
  96             modalDialog.dispose();
  97         }
  98 
  99         auxFrame = new Frame("Auxiliary Frame");
 100 
 101         frame = new Frame("Test Frame");
 102         frameButton = new Button("button");
 103 
 104         frame2 = new Frame("Test Frame 2");
 105         frameButton2 = new Button("button");
 106 
 107         frame3 = new Frame("Test Frame 3");
 108         frameButton3 = new Button("button");
 109 
 110         window = new Window(null);
 111         winButton = new Button("button");
 112         dialog = new Dialog((Frame)null, "Test Dialog");
 113         dlgButton = new Button("button");
 114 
 115         ownedWindow = new Window(frame);
 116         ownWinButton = new Button("button");
 117 
 118         ownedDialog = new Dialog(frame2, "Test Owned Dialog");
 119         ownDlgButton = new Button("button");
 120 
 121         modalDialog = new Dialog(frame3, "Test Modal Dialog");
 122         modalDlgButton = new Button("button");
 123 
 124         auxFrame.setBounds(100, 100, 300, 300);
 125 
 126         frame.setBounds(120, 120, 260, 260);
 127         frame.add(frameButton);
 128 
 129         frame2.setBounds(120, 120, 260, 260);
 130         frame2.add(frameButton2);
 131 
 132         frame3.setBounds(120, 120, 260, 260);
 133         frame3.add(frameButton3);
 134 
 135         window.setBounds(120, 120, 260, 260);
 136         window.add(winButton);
 137 
 138         dialog.setBounds(120, 120, 260, 260);
 139         dialog.add(dlgButton);
 140 
 141         ownedWindow.setBounds(140, 140, 220, 220);
 142         ownedWindow.add(ownWinButton);
 143 
 144         ownedDialog.setBounds(140, 140, 220, 220);
 145         ownedDialog.add(ownDlgButton);
 146 
 147         modalDialog.setBounds(140, 140, 220, 220);
 148         modalDialog.add(modalDlgButton);
 149         modalDialog.setModal(true);
 150     }
 151 
 152     public void start() {
 153         // 1. Simple Frame.
 154         //////////////////
 155 
 156         recreateGUI();
 157         Test.setWindows(frame, null, null);
 158         Test.test("Test stage 1 in progress", frameButton);
 159 
 160 
 161         // 2. Ownerless Window.
 162         //////////////////////
 163 
 164         recreateGUI();
 165         Test.setWindows(window, null, null);
 166         Test.test("Test stage 2 in progress", winButton);
 167 
 168 
 169         // 3. Ownerless Dialog.
 170         //////////////////////
 171 
 172         recreateGUI();
 173         Test.setWindows(dialog, null, null);
 174         Test.test("Test stage 3 in progress", dlgButton);
 175 
 176 
 177         // 4.1. Owner Frame (with owned Window).
 178         ///////////////////////////////////////
 179 
 180         recreateGUI();
 181         Test.setWindows(frame, null, new Window[] {ownedWindow, frame});
 182         Test.test("Test stage 4.1 in progress", ownWinButton);
 183 
 184 
 185         // 4.2. Owned Window (with owner Frame).
 186         ///////////////////////////////////////
 187 
 188         recreateGUI();
 189         Test.setWindows(ownedWindow, null, new Window[] {ownedWindow, frame});
 190         Test.test("Test stage 4.2 in progress", ownWinButton);
 191 
 192 
 193         // 5.1. Owner Frame (with owned Dialog).
 194         ///////////////////////////////////////
 195 
 196         recreateGUI();
 197         Test.setWindows(frame2, null, new Window[] {ownedDialog, frame2});
 198         Test.test("Test stage 5.1 in progress", ownDlgButton);
 199 
 200 
 201         // 5.2. Owned Dialog (with owner Frame).
 202         ///////////////////////////////////////
 203 
 204         recreateGUI();
 205         Test.setWindows(ownedDialog, null, new Window[] {ownedDialog, frame2});
 206         Test.test("Test stage 5.2 in progress", ownDlgButton);
 207 
 208 
 209         ////////////////////////////////////////////////
 210         // 6.1. Owned modal Dialog (with owner Frame).
 211         //      Focused frame is excluded from modality.
 212         ////////////////////////////////////////////////
 213 
 214         if (!"sun.awt.motif.MToolkit".equals(toolkitClassName)) {
 215             recreateGUI();
 216             auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
 217 
 218             Test.setWindows(modalDialog, modalDialog, new Window[] {modalDialog, frame3});
 219             Test.test("Test stage 6.1 in progress", modalDlgButton);
 220         }
 221 
 222 
 223         // 6.2. Owner Frame (with owned modal Dialog).
 224         //      Focused frame is excluded from modality.
 225         ////////////////////////////////////////////////
 226 
 227         if (!"sun.awt.motif.MToolkit".equals(toolkitClassName)) {
 228             recreateGUI();
 229             auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
 230 
 231             Test.setWindows(frame3, modalDialog, new Window[] {modalDialog, frame3});
 232             Test.test("Test stage 6.2 in progress", modalDlgButton, true);
 233         }
 234 
 235         ///////////////////////////////////////////////////
 236         // 7. Calling setVisible(true) for the shown Frame.
 237         ///////////////////////////////////////////////////
 238 
 239         recreateGUI();
 240         Test.setWindows(frame, null, null);
 241         Test.setTestSetVisible();
 242         Test.test("Test stage 7 in progress", frameButton);
 243 
 244 
 245         System.out.println("Test passed.");
 246     }
 247 
 248     static class Test {
 249         static Window testWindow; // a window to move to front with autoRequestFocus set
 250         static Window focusWindow; // a window to gain focus
 251         static Window[] showWindows; // windows to show, or null if only testWindow should be shown
 252 
 253         static boolean testSetVisible;
 254 
 255         static void setWindows(Window _testWindow, Window _focusWindow, Window[] _showWindows) {
 256             testWindow = _testWindow;
 257             focusWindow = _focusWindow;
 258             showWindows = _showWindows;
 259         }
 260         static void setTestSetVisible() {
 261             testSetVisible = true;
 262         }
 263 
 264         /*
 265          * @param msg notifies test stage number
 266          * @param testButton a button of the window (owner or owned) that is to be on the top of stack order
 267          * @param shouldFocusChange true for modal dialogs
 268          */
 269         static void test(String msg, final Button testButton, boolean shouldFocusChange) {
 270             System.out.println(msg);
 271 
 272             showWindows(testWindow, showWindows, true);
 273 
 274             pause(100);
 275 
 276             /////////////////////////////////////////////////////////
 277             // Test that calling toFront() doesn't cause focus change
 278             // when 'autoRequestFocus' is false.
 279             /////////////////////////////////////////////////////////
 280 
 281             Runnable action = new Runnable() {
 282                     public void run() {
 283                         testWindow.setAutoRequestFocus(false);
 284                         if (testSetVisible) {
 285                             setVisible(testWindow, true);
 286                         } else {
 287                             toFront(testWindow);
 288                         }
 289                     }
 290                 };
 291 
 292             if (shouldFocusChange) {
 293                 action.run();
 294                 Util.waitForIdle(robot);
 295                 if (!focusWindow.isFocused()) {
 296                     throw new TestFailedException("the window must gain focus on moving to front but it didn't!");
 297                 }
 298             } else if (TestHelper.trackFocusChangeFor(action, robot)) {
 299                 throw new TestFailedException("the window shouldn't gain focus on moving to front but it did!");
 300             }
 301 
 302             pause(100);
 303 
 304             ///////////////////////////////////////////////////////
 305             // Test that the window (or its owned window) is on top.
 306             ///////////////////////////////////////////////////////
 307 
 308             // The latest versions of Metacity (e.g. 2.16) have problems with moving a window to the front.
 309             if (Util.getWMID() != Util.METACITY_WM) {
 310 
 311                 boolean performed = Util.trackActionPerformed(testButton, new Runnable() {
 312                         public void run() {
 313                             Util.clickOnComp(testButton, robot);
 314                         }
 315                     }, 1000, false);
 316 
 317                 if (!performed) {
 318                     // For the case when the robot failed to trigger ACTION_EVENT.
 319                     System.out.println("(ACTION_EVENT was not generated. One more attemp.)");
 320                     performed = Util.trackActionPerformed(testButton, new Runnable() {
 321                             public void run() {
 322                                 Util.clickOnComp(testButton, robot);
 323                             }
 324                         }, 1000, false);
 325                     if (!performed) {
 326                         throw new TestFailedException("the window moved to front is not on the top!");
 327                     }
 328                 }
 329             }
 330 
 331             showWindows(testWindow, showWindows, false);
 332 
 333 
 334             /////////////////////////////////////////////////
 335             // Test that calling toFront() focuses the window
 336             // when 'autoRequestFocus' is true.
 337             /////////////////////////////////////////////////
 338 
 339             // Skip this stage for unfocusable window
 340             if (!testWindow.isFocusableWindow()) {
 341                 return;
 342             }
 343 
 344             showWindows(testWindow, showWindows, true);
 345 
 346             pause(100);
 347 
 348             boolean gained = Util.trackWindowGainedFocus(testWindow, new Runnable() {
 349                     public void run() {
 350                         testWindow.setAutoRequestFocus(true);
 351                         if (testSetVisible) {
 352                             setVisible(testWindow, true);
 353                         } else {
 354                             toFront(testWindow);
 355                         }
 356                     }
 357                 }, 1000, false);
 358 
 359             // Either the window or its owned window must be focused
 360             if (!gained && !testButton.hasFocus()) {
 361                 throw new TestFailedException("the window should gain focus automatically but it didn't!");
 362             }
 363 
 364             showWindows(testWindow, showWindows, false);
 365         }
 366 
 367         static void test(String msg, Button testButton) {
 368             test(msg, testButton, false);
 369         }
 370 
 371         private static void showWindows(Window win, Window[] wins, final boolean visible) {
 372             pause(100);
 373 
 374             if (wins == null) {
 375                 wins = new Window[] {win}; // operate with 'win'
 376             }
 377             for (final Window w: wins) {
 378                 if (visible) {
 379                     if ((w instanceof Dialog) && ((Dialog)w).isModal()) {
 380                         TestHelper.invokeLaterAndWait(new Runnable() {
 381                                 public void run() {
 382                                     w.setVisible(true);
 383                                 }
 384                             }, robot);
 385                     } else {
 386                         setVisible(w, true);
 387                     }
 388                 } else {
 389                     w.dispose();
 390                 }
 391             }
 392             setVisible(auxFrame, visible);
 393 
 394             if (visible) {
 395                 if (!auxFrame.isFocused()) {
 396                     Util.clickOnTitle(auxFrame, robot);
 397                     Util.waitForIdle(robot);
 398                     if (!auxFrame.isFocused()) {
 399                         throw new Error("Test error: the frame couldn't be focused.");
 400                     }
 401                 }
 402             }
 403         }
 404     }
 405 
 406     private static void setVisible(Window w, boolean b) {
 407         w.setVisible(b);
 408         try {
 409             Util.waitForIdle(robot);
 410         } catch (RuntimeException rte) { // InfiniteLoop
 411             rte.printStackTrace();
 412         }
 413         robot.delay(200);
 414     }
 415 
 416     private static void toFront(Window w) {
 417         w.toFront();
 418         Util.waitForIdle(robot);
 419         robot.delay(200);
 420     }
 421 
 422     private static void pause(int msec) {
 423         if (haveDelays) {
 424             robot.delay(msec);
 425         }
 426     }
 427 }
 428 
 429 class TestFailedException extends RuntimeException {
 430     TestFailedException(String msg) {
 431         super("Test failed: " + msg);
 432     }
 433 }
 434