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