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