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.setVisible() method.
29  @author    anton.tarasov: area=awt.focus
30  @library    ../../regtesthelpers
31  @build      Util
32  @run       main AutoRequestFocusSetVisibleTest
33*/
34
35import java.awt.*;
36import java.awt.event.*;
37import java.applet.Applet;
38import java.util.concurrent.atomic.AtomicBoolean;
39import java.lang.reflect.InvocationTargetException;
40import test.java.awt.regtesthelpers.Util;
41
42public 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        Sysout.createDialogWithInstructions(new String[]
73            {"This is an automatic test. Simply wait until it is done."
74            });
75        toolkitClassName = Toolkit.getDefaultToolkit().getClass().getName();
76    }
77
78    void recreateGUI() {
79        if (focusedFrame != null) {
80            focusedFrame.dispose();
81            frame.dispose();
82            frame2.dispose();
83            window.dispose();
84            ownedWindow.dispose();
85            ownedDialog.dispose();
86            dialog.dispose();
87        }
88
89        focusedFrame = new Frame("Base Frame");
90        focusOwner = new Button("button");
91
92        frame = new Frame("Test Frame");
93        frameButton = new Button("button");
94
95        frame2 = new Frame("Test Frame");
96        frameButton2 = new Button("button");
97
98        window = new Window(focusedFrame);
99        winButton = new Button("button");
100
101        ownedWindow = new Window(frame) {
102                /*
103                 * When 'frame' is shown along with the 'ownedWindow'
104                 * (i.e. showWithParent==true) then it can appear
105                 * that the 'ownedWindow' is shown too early and
106                 * it can't be focused due to its owner can't be
107                 * yet activated. So, to avoid this race, we pospone
108                 * a little the showing of the 'ownedWindow'.
109                 */
110                public void show() {
111                    robot.delay(100);
112                    super.show();
113                }
114            };
115        ownWinButton = new Button("button");
116
117        ownedDialog = new Dialog(frame2);
118        ownDlgButton = new Button("button");
119
120        dialog = new Dialog(focusedFrame, "Test Dialog");
121        dlgButton = new Button("button");
122
123        focusedFrame.add(focusOwner);
124        focusedFrame.setBounds(100, 100, 300, 300);
125
126        frame.setBounds(140, 140, 220, 220);
127        frame.add(frameButton);
128
129        frame2.setBounds(140, 140, 220, 220);
130        frame2.add(frameButton2);
131
132        window.setBounds(140, 140, 220, 220);
133        window.add(winButton);
134
135        ownedWindow.setBounds(180, 180, 140, 140);
136        ownedWindow.add(ownWinButton);
137
138        ownedDialog.setBounds(180, 180, 140, 140);
139        ownedDialog.add(ownDlgButton);
140
141        dialog.setBounds(140, 140, 220, 220);
142        dialog.add(dlgButton);
143    }
144
145    public void start() {
146
147        ///////////////////////////////////////////////////////
148        // 1. Show Frame with owned modal Dialog without delay.
149        //    Check that the Dialog takes focus.
150        ///////////////////////////////////////////////////////
151
152        recreateGUI();
153
154        Sysout.println("Stage 1 in progress...");
155
156        dialog.setModal(true);
157        dialog.setAutoRequestFocus(false);
158        setVisible(focusedFrame, true);
159
160        TestHelper.invokeLaterAndWait(new Runnable() {
161                public void run() {
162                    dialog.setVisible(true);
163                }
164            }, robot);
165
166        if (focusOwner.hasFocus()) {
167            throw new TestFailedException("the modal dialog must gain focus but it didn't!");
168        }
169        setVisible(dialog, false);
170
171        //////////////////////////////////////////////////
172        // 2. Show Frame, activate, auto hide, auto show.
173        //    Check that the Frame takes focus.
174        //////////////////////////////////////////////////
175
176        recreateGUI();
177
178        Sysout.println("Stage 2 in progress...");
179
180        setVisible(focusedFrame, false);
181
182        focusedFrame.setAutoRequestFocus(false);
183        setVisible(focusedFrame, true);
184
185        Util.clickOnTitle(focusedFrame, robot);
186        Util.waitForIdle(robot);
187
188        if (!focusedFrame.isFocused()) {
189            throw new Error("Test error: the frame couldn't be focused.");
190        }
191
192        focusedFrame.setExtendedState(Frame.ICONIFIED);
193        Util.waitForIdle(robot);
194        focusedFrame.setExtendedState(Frame.NORMAL);
195        Util.waitForIdle(robot);
196
197        if (!focusedFrame.isFocused()) {
198            throw new TestFailedException("the restored frame must gain focus but it didn't!");
199        }
200
201
202        ////////////////////////
203        // 3.1 Show Frame normal.
204        ////////////////////////
205
206        recreateGUI();
207
208        test("Stage 3.1 in progress...", frame, frameButton);
209
210
211        // 3.2. Show Frame maximized both.
212        /////////////////////////////////
213
214        if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_BOTH)) {
215            System.out.println("Stage 3.2: Frame.MAXIMIZED_BOTH not supported. Skipping.");
216        } else {
217            frame.setExtendedState(Frame.MAXIMIZED_BOTH);
218
219            test("Stage 3.2 in progress...", frame, frameButton);
220        }
221
222
223        // 3.3. Show Frame maximized vertically.
224        ///////////////////////////////////////
225
226        if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_VERT)) {
227            System.out.println("Stage 3.3: Frame.MAXIMIZED_VERT not supported. Skipping.");
228        } else {
229            frame.setExtendedState(Frame.MAXIMIZED_VERT);
230
231            test("Stage 3.3 in progress...", frame, frameButton);
232        }
233
234
235        // 3.4. Show Frame maximized horizontally.
236        /////////////////////////////////////////
237
238        if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.MAXIMIZED_HORIZ)) {
239            System.out.println("Stage 3.4: Frame.MAXIMIZED_HORIZ not supported. Skipping.");
240        } else {
241            frame.setExtendedState(Frame.MAXIMIZED_HORIZ);
242
243            test("Stage 3.4 in progress...", frame, frameButton);
244        }
245
246
247        // 3.5. Show Frame iconified.
248        ////////////////////////////
249
250        if (!Toolkit.getDefaultToolkit().isFrameStateSupported(Frame.ICONIFIED)) {
251            System.out.println("Stage 3.5: Frame.ICONIFIED not supported. Skipping.");
252        } else {
253            frame.setExtendedState(Frame.ICONIFIED);
254
255            test("Stage 3.5 in progress...", frame, frameButton);
256        }
257
258
259        ///////////////////
260        // 4.1 Show Window.
261        ///////////////////
262        recreateGUI();
263        test("Stage 4.1 in progress...", window, winButton);
264
265
266        // 4.2 Show Dialog.
267        //////////////////
268
269        test("Stage 4.2 in progress...", dialog, dlgButton);
270
271
272        // 4.3. Show modal Dialog.
273        /////////////////////////
274
275        dialog.setModal(true);
276        test("Stage 4.3 in progress...", dialog, dlgButton, true);
277
278
279        ///////////////////////////////////
280        // 5.1 Show Frame with owned Window.
281        ///////////////////////////////////
282
283        // On Windows, an owned Window will not be focused on its showing
284        // if the owner is not currently active.
285        if ("sun.awt.windows.WToolkit".equals(toolkitClassName)) {
286            Sysout.println("Stage 5.1 - Skiping.");
287        } else {
288            setVisible(ownedWindow, true);
289            setVisible(frame, false); // 'ownedWindow' will be shown along with the owner.
290
291            test("Stage 5.1 in progress...", frame, ownedWindow, ownWinButton, true);
292        }
293
294
295        // 5.2 Show Frame with owned Dialog.
296        ///////////////////////////////////
297
298        setVisible(ownedDialog, true);
299        setVisible(frame2, false); // 'ownedDialog' will be shown along with the owner.
300
301        test("Stage 5.2 in progress...", frame2, ownedDialog, ownDlgButton, true);
302
303
304        ///////////////////////////////////
305        // 6. Show unblocking modal Dialog.
306        ///////////////////////////////////
307
308        if ("sun.awt.motif.MToolkit".equals(toolkitClassName)) {
309            Sysout.println("Stage 6 - Skiping.");
310        } else {
311            Sysout.println("Stage 6 in progress...");
312
313            // ---
314            // Testing the bug of activating invisible modal Dialog (awt_Window::SetAndActivateModalBlocker).
315            // Having some window not excluded from modality, so that it would be blocked.
316            Frame f = new Frame("Aux. Frame");
317            f.setSize(100, 100);
318            setVisible(f, true);
319            // ---
320
321            setVisible(focusedFrame, true);
322            if (!focusOwner.hasFocus()) {
323                Util.clickOnComp(focusOwner, robot);
324                Util.waitForIdle(robot);
325                if (!focusOwner.hasFocus()) {
326                    throw new Error("Test error: the frame couldn't be focused.");
327                }
328            }
329
330            dialog.setModal(true);
331            dialog.setAutoRequestFocus(false);
332            focusedFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
333
334            TestHelper.invokeLaterAndWait(new Runnable() {
335                    public void run() {
336                        dialog.setVisible(true);
337                    }
338                }, robot);
339
340            if (dialog.isFocused()) {
341                throw new TestFailedException("the unblocking dialog shouldn't gain focus but it did!");
342            }
343            setVisible(dialog, false);
344        }
345
346        Sysout.println("Test passed.");
347    }
348
349    /*
350     * @param msg notifies test stage number
351     * @param showWindow a window to show/test (if ownedWindow == null)
352     * @param ownedWindow an owned window to show/test, or null if showWindow should be tested
353     * @param clickButton a button of the window (owner or owned) expected to be on the top of stack order
354     * @param shouldFocusChange true the test window should gain focus
355     */
356    void test(String msg, final Window showWindow, Window ownedWindow, final Button clickButton, boolean shouldFocusChange) {
357        Window testWindow = (ownedWindow == null ? showWindow : ownedWindow);
358
359        Sysout.println(msg);
360
361        if (showWindow.isVisible()) {
362            showWindow.dispose();
363            Util.waitForIdle(robot);
364        }
365        if (!focusedFrame.isVisible()) {
366            setVisible(focusedFrame, true);
367        }
368        if (!focusOwner.hasFocus()) {
369            Util.clickOnComp(focusOwner, robot);
370            Util.waitForIdle(robot);
371            if (!focusOwner.hasFocus()) {
372                throw new Error("Test error: the frame couldn't be focused.");
373            }
374        }
375
376        //////////////////////////////////////////
377        // Test focus change on showing the window
378        //////////////////////////////////////////
379
380        final Runnable showAction = new Runnable() {
381                public void run() {
382                    showWindow.setAutoRequestFocus(false);
383                    showWindow.setVisible(true);
384                }
385            };
386
387        final Runnable trackerAction = new Runnable() {
388                public void run() {
389                    if (showWindow instanceof Dialog && ((Dialog)showWindow).isModal()) {
390                        TestHelper.invokeLaterAndWait(showAction, robot);
391                    } else {
392                        showAction.run();
393                    }
394                }
395            };
396
397        if (shouldFocusChange) {
398            trackerAction.run();
399            Util.waitForIdle(robot);
400
401            if (!testWindow.isFocused()) {
402                throw new TestFailedException("the window must gain focus but it didn't!");
403            }
404
405        } else if (TestHelper.trackFocusChangeFor(trackerAction, robot)) {
406            throw new TestFailedException("the window shouldn't gain focus but it did!");
407        }
408
409
410        ////////////////////////////////////////////
411        // Test that the window was shown on the top.
412        // Test that it can be focused.
413        ////////////////////////////////////////////
414
415        if (!(testWindow instanceof Frame) ||
416            ((Frame)testWindow).getExtendedState() != Frame.ICONIFIED)
417        {
418            boolean performed = Util.trackActionPerformed(clickButton, new Runnable() {
419                    public void run() {
420                        /*
421                         * If 'showWindow' is not on the top then
422                         * 'focusOwner' button completely overlaps 'clickButton'
423                         * and we won't catch the action.
424                         */
425                        Util.clickOnComp(clickButton, robot);
426                    }
427                }, 1000, false);
428
429            if (!performed) {
430                // In case of loosing ACTION_PERFORMED, try once more.
431                Sysout.println("(ACTION_EVENT was not generated. One more attemp.)");
432                performed = Util.trackActionPerformed(clickButton, new Runnable() {
433                        public void run() {
434                            Util.clickOnComp(clickButton, robot);
435                        }
436                    }, 1000, false);
437
438                if (!performed) {
439                    throw new TestFailedException("the window shown is not on the top!");
440                }
441            }
442        }
443
444        recreateGUI();
445    }
446
447    void test(String msg, final Window showWindow, Button clickButton) {
448        test(msg, showWindow, null, clickButton, false);
449    }
450    void test(String msg, final Window showWindow, Button clickButton, boolean shouldFocusChange) {
451        test(msg, showWindow, null, clickButton, shouldFocusChange);
452    }
453    void test(String msg, final Window showWindow, Window ownedWindow, Button clickButton) {
454        test(msg, showWindow, ownedWindow, clickButton, false);
455    }
456
457    private static void setVisible(Window w, boolean b) {
458        w.setVisible(b);
459        try {
460            Util.waitForIdle(robot);
461        } catch (RuntimeException rte) { // InfiniteLoop
462            rte.printStackTrace();
463        }
464        robot.delay(200);
465    }
466}
467
468class TestFailedException extends RuntimeException {
469    TestFailedException(String msg) {
470        super("Test failed: " + msg);
471    }
472}
473
474/****************************************************
475 Standard Test Machinery
476 DO NOT modify anything below -- it's a standard
477  chunk of code whose purpose is to make user
478  interaction uniform, and thereby make it simpler
479  to read and understand someone else's test.
480 ****************************************************/
481
482/**
483 This is part of the standard test machinery.
484 It creates a dialog (with the instructions), and is the interface
485  for sending text messages to the user.
486 To print the instructions, send an array of strings to Sysout.createDialog
487  WithInstructions method.  Put one line of instructions per array entry.
488 To display a message for the tester to see, simply call Sysout.println
489  with the string to be displayed.
490 This mimics System.out.println but works within the test harness as well
491  as standalone.
492 */
493
494class Sysout
495{
496    static TestDialog dialog;
497
498    public static void createDialogWithInstructions( String[] instructions )
499    {
500        dialog = new TestDialog( new Frame(), "Instructions" );
501        dialog.printInstructions( instructions );
502//        dialog.setVisible(true);
503        println( "Any messages for the tester will display here." );
504    }
505
506    public static void createDialog( )
507    {
508        dialog = new TestDialog( new Frame(), "Instructions" );
509        String[] defInstr = { "Instructions will appear here. ", "" } ;
510        dialog.printInstructions( defInstr );
511//        dialog.setVisible(true);
512        println( "Any messages for the tester will display here." );
513    }
514
515
516    public static void printInstructions( String[] instructions )
517    {
518        dialog.printInstructions( instructions );
519    }
520
521
522    public static void println( String messageIn )
523    {
524        dialog.displayMessage( messageIn );
525    }
526
527}// Sysout  class
528
529/**
530  This is part of the standard test machinery.  It provides a place for the
531   test instructions to be displayed, and a place for interactive messages
532   to the user to be displayed.
533  To have the test instructions displayed, see Sysout.
534  To have a message to the user be displayed, see Sysout.
535  Do not call anything in this dialog directly.
536  */
537class TestDialog extends Dialog
538{
539
540    TextArea instructionsText;
541    TextArea messageText;
542    int maxStringLength = 80;
543
544    //DO NOT call this directly, go through Sysout
545    public TestDialog( Frame frame, String name )
546    {
547        super( frame, name );
548        int scrollBoth = TextArea.SCROLLBARS_BOTH;
549        instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
550        add( "North", instructionsText );
551
552        messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
553        add("Center", messageText);
554
555        pack();
556
557//        setVisible(true);
558    }// TestDialog()
559
560    //DO NOT call this directly, go through Sysout
561    public void printInstructions( String[] instructions )
562    {
563        //Clear out any current instructions
564        instructionsText.setText( "" );
565
566        //Go down array of instruction strings
567
568        String printStr, remainingStr;
569        for( int i=0; i < instructions.length; i++ )
570        {
571            //chop up each into pieces maxSringLength long
572            remainingStr = instructions[ i ];
573            while( remainingStr.length() > 0 )
574            {
575                //if longer than max then chop off first max chars to print
576                if( remainingStr.length() >= maxStringLength )
577                {
578                    //Try to chop on a word boundary
579                    int posOfSpace = remainingStr.
580                        lastIndexOf( ' ', maxStringLength - 1 );
581
582                    if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
583
584                    printStr = remainingStr.substring( 0, posOfSpace + 1 );
585                    remainingStr = remainingStr.substring( posOfSpace + 1 );
586                }
587                //else just print
588                else
589                {
590                    printStr = remainingStr;
591                    remainingStr = "";
592                }
593
594                instructionsText.append( printStr + "\n" );
595
596            }// while
597
598        }// for
599
600    }//printInstructions()
601
602    //DO NOT call this directly, go through Sysout
603    public void displayMessage( String messageIn )
604    {
605        messageText.append( messageIn + "\n" );
606        System.out.println(messageIn);
607    }
608
609}// TestDialog  class
610