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.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         Sysout.createDialogWithInstructions(new String[]
  84             {"This is an automatic test. Simply wait until it is done."
  85             });
  86         toolkitClassName = Toolkit.getDefaultToolkit().getClass().getName();
  87     }
  88 
  89     static void recreateGUI() {
  90         if (auxFrame != null) {
  91             auxFrame.dispose();
  92             frame.dispose();
  93             frame2.dispose();
  94             frame3.dispose();
  95             window.dispose();
  96             dialog.dispose();
  97             ownedWindow.dispose();
  98             ownedDialog.dispose();
  99             modalDialog.dispose();
 100         }
 101 
 102         auxFrame = new Frame("Auxiliary Frame");
 103 
 104         frame = new Frame("Test Frame");
 105         frameButton = new Button("button");
 106 
 107         frame2 = new Frame("Test Frame 2");
 108         frameButton2 = new Button("button");
 109 
 110         frame3 = new Frame("Test Frame 3");
 111         frameButton3 = new Button("button");
 112 
 113         window = new Window(null);
 114         winButton = new Button("button");
 115         dialog = new Dialog((Frame)null, "Test Dialog");
 116         dlgButton = new Button("button");
 117 
 118         ownedWindow = new Window(frame);
 119         ownWinButton = new Button("button");
 120 
 121         ownedDialog = new Dialog(frame2, "Test Owned Dialog");
 122         ownDlgButton = new Button("button");
 123 
 124         modalDialog = new Dialog(frame3, "Test Modal Dialog");
 125         modalDlgButton = new Button("button");
 126 
 127         auxFrame.setBounds(100, 100, 300, 300);
 128 
 129         frame.setBounds(120, 120, 260, 260);
 130         frame.add(frameButton);
 131 
 132         frame2.setBounds(120, 120, 260, 260);
 133         frame2.add(frameButton2);
 134 
 135         frame3.setBounds(120, 120, 260, 260);
 136         frame3.add(frameButton3);
 137 
 138         window.setBounds(120, 120, 260, 260);
 139         window.add(winButton);
 140 
 141         dialog.setBounds(120, 120, 260, 260);
 142         dialog.add(dlgButton);
 143 
 144         ownedWindow.setBounds(140, 140, 220, 220);
 145         ownedWindow.add(ownWinButton);
 146 
 147         ownedDialog.setBounds(140, 140, 220, 220);
 148         ownedDialog.add(ownDlgButton);
 149 
 150         modalDialog.setBounds(140, 140, 220, 220);
 151         modalDialog.add(modalDlgButton);
 152         modalDialog.setModal(true);
 153     }
 154 
 155     public void start() {
 156         // 1. Simple Frame.
 157         //////////////////
 158 
 159         recreateGUI();
 160         Test.setWindows(frame, null, null);
 161         Test.test("Test stage 1 in progress", frameButton);
 162 
 163 
 164         // 2. Ownerless Window.
 165         //////////////////////
 166 
 167         recreateGUI();
 168         Test.setWindows(window, null, null);
 169         Test.test("Test stage 2 in progress", winButton);
 170 
 171 
 172         // 3. Ownerless Dialog.
 173         //////////////////////
 174 
 175         recreateGUI();
 176         Test.setWindows(dialog, null, null);
 177         Test.test("Test stage 3 in progress", dlgButton);
 178 
 179 
 180         // 4.1. Owner Frame (with owned Window).
 181         ///////////////////////////////////////
 182 
 183         recreateGUI();
 184         Test.setWindows(frame, null, new Window[] {ownedWindow, frame});
 185         Test.test("Test stage 4.1 in progress", ownWinButton);
 186 
 187 
 188         // 4.2. Owned Window (with owner Frame).
 189         ///////////////////////////////////////
 190 
 191         recreateGUI();
 192         Test.setWindows(ownedWindow, null, new Window[] {ownedWindow, frame});
 193         Test.test("Test stage 4.2 in progress", ownWinButton);
 194 
 195 
 196         // 5.1. Owner Frame (with owned Dialog).
 197         ///////////////////////////////////////
 198 
 199         recreateGUI();
 200         Test.setWindows(frame2, null, new Window[] {ownedDialog, frame2});
 201         Test.test("Test stage 5.1 in progress", ownDlgButton);
 202 
 203 
 204         // 5.2. Owned Dialog (with owner Frame).
 205         ///////////////////////////////////////
 206 
 207         recreateGUI();
 208         Test.setWindows(ownedDialog, null, new Window[] {ownedDialog, frame2});
 209         Test.test("Test stage 5.2 in progress", ownDlgButton);
 210 
 211 
 212         ////////////////////////////////////////////////
 213         // 6.1. Owned modal Dialog (with owner Frame).
 214         //      Focused frame is excluded from modality.
 215         ////////////////////////////////////////////////
 216 
 217         if (!"sun.awt.motif.MToolkit".equals(toolkitClassName)) {
 218             recreateGUI();
 219             auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
 220 
 221             Test.setWindows(modalDialog, modalDialog, new Window[] {modalDialog, frame3});
 222             Test.test("Test stage 6.1 in progress", modalDlgButton);
 223         }
 224 
 225 
 226         // 6.2. Owner Frame (with owned modal Dialog).
 227         //      Focused frame is excluded from modality.
 228         ////////////////////////////////////////////////
 229 
 230         if (!"sun.awt.motif.MToolkit".equals(toolkitClassName)) {
 231             recreateGUI();
 232             auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
 233 
 234             Test.setWindows(frame3, modalDialog, new Window[] {modalDialog, frame3});
 235             Test.test("Test stage 6.2 in progress", modalDlgButton, true);
 236         }
 237 
 238         ///////////////////////////////////////////////////
 239         // 7. Calling setVisible(true) for the shown Frame.
 240         ///////////////////////////////////////////////////
 241 
 242         recreateGUI();
 243         Test.setWindows(frame, null, null);
 244         Test.setTestSetVisible();
 245         Test.test("Test stage 7 in progress", frameButton);
 246 
 247 
 248         Sysout.println("Test passed.");
 249     }
 250 
 251     static class Test {
 252         static Window testWindow; // a window to move to front with autoRequestFocus set
 253         static Window focusWindow; // a window to gain focus
 254         static Window[] showWindows; // windows to show, or null if only testWindow should be shown
 255 
 256         static boolean testSetVisible;
 257 
 258         static void setWindows(Window _testWindow, Window _focusWindow, Window[] _showWindows) {
 259             testWindow = _testWindow;
 260             focusWindow = _focusWindow;
 261             showWindows = _showWindows;
 262         }
 263         static void setTestSetVisible() {
 264             testSetVisible = true;
 265         }
 266 
 267         /*
 268          * @param msg notifies test stage number
 269          * @param testButton a button of the window (owner or owned) that is to be on the top of stack order
 270          * @param shouldFocusChange true for modal dialogs
 271          */
 272         static void test(String msg, final Button testButton, boolean shouldFocusChange) {
 273             Sysout.println(msg);
 274 
 275             showWindows(testWindow, showWindows, true);
 276 
 277             pause(100);
 278 
 279             /////////////////////////////////////////////////////////
 280             // Test that calling toFront() doesn't cause focus change
 281             // when 'autoRequestFocus' is false.
 282             /////////////////////////////////////////////////////////
 283 
 284             Runnable action = new Runnable() {
 285                     public void run() {
 286                         testWindow.setAutoRequestFocus(false);
 287                         if (testSetVisible) {
 288                             setVisible(testWindow, true);
 289                         } else {
 290                             toFront(testWindow);
 291                         }
 292                     }
 293                 };
 294 
 295             if (shouldFocusChange) {
 296                 action.run();
 297                 Util.waitForIdle(robot);
 298                 if (!focusWindow.isFocused()) {
 299                     throw new TestFailedException("the window must gain focus on moving to front but it didn't!");
 300                 }
 301             } else if (TestHelper.trackFocusChangeFor(action, robot)) {
 302                 throw new TestFailedException("the window shouldn't gain focus on moving to front but it did!");
 303             }
 304 
 305             pause(100);
 306 
 307             ///////////////////////////////////////////////////////
 308             // Test that the window (or its owned window) is on top.
 309             ///////////////////////////////////////////////////////
 310 
 311             // The latest versions of Metacity (e.g. 2.16) have problems with moving a window to the front.
 312             if (Util.getWMID() != Util.METACITY_WM) {
 313 
 314                 boolean performed = Util.trackActionPerformed(testButton, new Runnable() {
 315                         public void run() {
 316                             Util.clickOnComp(testButton, robot);
 317                         }
 318                     }, 1000, false);
 319 
 320                 if (!performed) {
 321                     // For the case when the robot failed to trigger ACTION_EVENT.
 322                     Sysout.println("(ACTION_EVENT was not generated. One more attemp.)");
 323                     performed = Util.trackActionPerformed(testButton, new Runnable() {
 324                             public void run() {
 325                                 Util.clickOnComp(testButton, robot);
 326                             }
 327                         }, 1000, false);
 328                     if (!performed) {
 329                         throw new TestFailedException("the window moved to front is not on the top!");
 330                     }
 331                 }
 332             }
 333 
 334             showWindows(testWindow, showWindows, false);
 335 
 336 
 337             /////////////////////////////////////////////////
 338             // Test that calling toFront() focuses the window
 339             // when 'autoRequestFocus' is true.
 340             /////////////////////////////////////////////////
 341 
 342             // Skip this stage for unfocusable window
 343             if (!testWindow.isFocusableWindow()) {
 344                 return;
 345             }
 346 
 347             showWindows(testWindow, showWindows, true);
 348 
 349             pause(100);
 350 
 351             boolean gained = Util.trackWindowGainedFocus(testWindow, new Runnable() {
 352                     public void run() {
 353                         testWindow.setAutoRequestFocus(true);
 354                         if (testSetVisible) {
 355                             setVisible(testWindow, true);
 356                         } else {
 357                             toFront(testWindow);
 358                         }
 359                     }
 360                 }, 1000, false);
 361 
 362             // Either the window or its owned window must be focused
 363             if (!gained && !testButton.hasFocus()) {
 364                 throw new TestFailedException("the window should gain focus automatically but it didn't!");
 365             }
 366 
 367             showWindows(testWindow, showWindows, false);
 368         }
 369 
 370         static void test(String msg, Button testButton) {
 371             test(msg, testButton, false);
 372         }
 373 
 374         private static void showWindows(Window win, Window[] wins, final boolean visible) {
 375             pause(100);
 376 
 377             if (wins == null) {
 378                 wins = new Window[] {win}; // operate with 'win'
 379             }
 380             for (final Window w: wins) {
 381                 if (visible) {
 382                     if ((w instanceof Dialog) && ((Dialog)w).isModal()) {
 383                         TestHelper.invokeLaterAndWait(new Runnable() {
 384                                 public void run() {
 385                                     w.setVisible(true);
 386                                 }
 387                             }, robot);
 388                     } else {
 389                         setVisible(w, true);
 390                     }
 391                 } else {
 392                     w.dispose();
 393                 }
 394             }
 395             setVisible(auxFrame, visible);
 396 
 397             if (visible) {
 398                 if (!auxFrame.isFocused()) {
 399                     Util.clickOnTitle(auxFrame, robot);
 400                     Util.waitForIdle(robot);
 401                     if (!auxFrame.isFocused()) {
 402                         throw new Error("Test error: the frame couldn't be focused.");
 403                     }
 404                 }
 405             }
 406         }
 407     }
 408 
 409     private static void setVisible(Window w, boolean b) {
 410         w.setVisible(b);
 411         try {
 412             Util.waitForIdle(robot);
 413         } catch (RuntimeException rte) { // InfiniteLoop
 414             rte.printStackTrace();
 415         }
 416         robot.delay(200);
 417     }
 418 
 419     private static void toFront(Window w) {
 420         w.toFront();
 421         Util.waitForIdle(robot);
 422         robot.delay(200);
 423     }
 424 
 425     private static void pause(int msec) {
 426         if (haveDelays) {
 427             robot.delay(msec);
 428         }
 429     }
 430 }
 431 
 432 class TestFailedException extends RuntimeException {
 433     TestFailedException(String msg) {
 434         super("Test failed: " + msg);
 435     }
 436 }
 437 
 438 /****************************************************
 439  Standard Test Machinery
 440  DO NOT modify anything below -- it's a standard
 441   chunk of code whose purpose is to make user
 442   interaction uniform, and thereby make it simpler
 443   to read and understand someone else's test.
 444  ****************************************************/
 445 
 446 /**
 447  This is part of the standard test machinery.
 448  It creates a dialog (with the instructions), and is the interface
 449   for sending text messages to the user.
 450  To print the instructions, send an array of strings to Sysout.createDialog
 451   WithInstructions method.  Put one line of instructions per array entry.
 452  To display a message for the tester to see, simply call Sysout.println
 453   with the string to be displayed.
 454  This mimics System.out.println but works within the test harness as well
 455   as standalone.
 456  */
 457 
 458 class Sysout
 459 {
 460     static TestDialog dialog;
 461 
 462     public static void createDialogWithInstructions( String[] instructions )
 463     {
 464         dialog = new TestDialog( new Frame(), "Instructions" );
 465         dialog.printInstructions( instructions );
 466 //        dialog.setVisible(true);
 467         println( "Any messages for the tester will display here." );
 468     }
 469 
 470     public static void createDialog( )
 471     {
 472         dialog = new TestDialog( new Frame(), "Instructions" );
 473         String[] defInstr = { "Instructions will appear here. ", "" } ;
 474         dialog.printInstructions( defInstr );
 475 //        dialog.setVisible(true);
 476         println( "Any messages for the tester will display here." );
 477     }
 478 
 479 
 480     public static void printInstructions( String[] instructions )
 481     {
 482         dialog.printInstructions( instructions );
 483     }
 484 
 485 
 486     public static void println( String messageIn )
 487     {
 488         dialog.displayMessage( messageIn );
 489     }
 490 
 491 }// Sysout  class
 492 
 493 /**
 494   This is part of the standard test machinery.  It provides a place for the
 495    test instructions to be displayed, and a place for interactive messages
 496    to the user to be displayed.
 497   To have the test instructions displayed, see Sysout.
 498   To have a message to the user be displayed, see Sysout.
 499   Do not call anything in this dialog directly.
 500   */
 501 class TestDialog extends Dialog
 502 {
 503 
 504     TextArea instructionsText;
 505     TextArea messageText;
 506     int maxStringLength = 80;
 507 
 508     //DO NOT call this directly, go through Sysout
 509     public TestDialog( Frame frame, String name )
 510     {
 511         super( frame, name );
 512         int scrollBoth = TextArea.SCROLLBARS_BOTH;
 513         instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
 514         add( "North", instructionsText );
 515 
 516         messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
 517         add("Center", messageText);
 518 
 519         pack();
 520 
 521 //        setVisible(true);
 522     }// TestDialog()
 523 
 524     //DO NOT call this directly, go through Sysout
 525     public void printInstructions( String[] instructions )
 526     {
 527         //Clear out any current instructions
 528         instructionsText.setText( "" );
 529 
 530         //Go down array of instruction strings
 531 
 532         String printStr, remainingStr;
 533         for( int i=0; i < instructions.length; i++ )
 534         {
 535             //chop up each into pieces maxSringLength long
 536             remainingStr = instructions[ i ];
 537             while( remainingStr.length() > 0 )
 538             {
 539                 //if longer than max then chop off first max chars to print
 540                 if( remainingStr.length() >= maxStringLength )
 541                 {
 542                     //Try to chop on a word boundary
 543                     int posOfSpace = remainingStr.
 544                         lastIndexOf( ' ', maxStringLength - 1 );
 545 
 546                     if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
 547 
 548                     printStr = remainingStr.substring( 0, posOfSpace + 1 );
 549                     remainingStr = remainingStr.substring( posOfSpace + 1 );
 550                 }
 551                 //else just print
 552                 else
 553                 {
 554                     printStr = remainingStr;
 555                     remainingStr = "";
 556                 }
 557 
 558                 instructionsText.append( printStr + "\n" );
 559 
 560             }// while
 561 
 562         }// for
 563 
 564     }//printInstructions()
 565 
 566     //DO NOT call this directly, go through Sysout
 567     public void displayMessage( String messageIn )
 568     {
 569         messageText.append( messageIn + "\n" );
 570         System.out.println(messageIn);
 571     }
 572 
 573 }// TestDialog  class