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