1 /*
2  * Copyright (c) 2003, 2019, 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 4632143
28   @summary Unit test for the RFE window/frame/dialog always on top
29   @author dom@sparc.spb.su: area=awt.toplevel
30   @run main/othervm/timeout=600 AutoTestOnTop
31 */
32 
33 import java.awt.AWTEvent;
34 import java.awt.AWTException;
35 import java.awt.Component;
36 import java.awt.Dialog;
37 import java.awt.EventQueue;
38 import java.awt.Frame;
39 import java.awt.IllegalComponentStateException;
40 import java.awt.Point;
41 import java.awt.Robot;
42 import java.awt.Toolkit;
43 import java.awt.Window;
44 import java.awt.event.AWTEventListener;
45 import java.awt.event.FocusEvent;
46 import java.awt.event.InputEvent;
47 import java.awt.event.MouseEvent;
48 import java.awt.event.PaintEvent;
49 import java.awt.event.WindowAdapter;
50 import java.awt.event.WindowEvent;
51 import java.lang.reflect.InvocationTargetException;
52 import java.lang.reflect.Method;
53 import java.util.Vector;
54 
55 import javax.swing.JDialog;
56 import javax.swing.JFrame;
57 import javax.swing.JWindow;
58 
59 /**
60  * @author tav@sparc.spb.su
61  * @author dom@sparc.spb.su
62  * Tests that always-on-top windows combine correctly with different kinds of window in different styles and conditions.
63  *
64  * !!! WARNING !!!
65  * The test fails sometimes because the toFront() method doesn't guarantee
66  * that after its invocation the frame will be placed above all other windows.
67  */
68 public class AutoTestOnTop {
69     private static final int X = 300;
70     private static final int Y = 300;
71 
72     static Window topw;
73     static Frame  parentw = new Frame();
74     static Window f;
75     static Frame  parentf = new Frame();
76 
77     static final Object  uncheckedSrc = new Object(); // used when no need to check event source
78     static volatile Object  eventSrc = uncheckedSrc;
79     static boolean dispatchedCond;
80 
81     static Semaphore STATE_SEMA = new Semaphore();
82     static Semaphore VIS_SEMA = new Semaphore();
83     static Vector errors = new Vector();
84 
85     static boolean isUnix = false;
86 
87     static StringBuffer msgError = new StringBuffer();
88     static StringBuffer msgCase = new StringBuffer();
89     static StringBuffer msgAction = new StringBuffer();
90     static StringBuffer msgFunc = new StringBuffer();
91     static StringBuffer msgVisibility = new StringBuffer();
92 
93     static volatile int stageNum;
94     static volatile int actNum;
95     static volatile int testResult = 0;
96 
97     static volatile boolean doCheckEvents;
98     static volatile boolean eventsCheckPassed;
99     static boolean[] eventsCheckInitVals = new boolean[] { // Whether events are checked for abcence or precence
100         true, true, true, true, true, false, false, false, false
101     };
102     static String[] msgEventsChecks = new String[] {
103         null, null, null, null, null,
104         "expected WindowEvent.WINDOW_STATE_CHANGED hasn't been generated",
105         "expected WindowEvent.WINDOW_STATE_CHANGED hasn't been generated",
106         "expected WindowEvent.WINDOW_STATE_CHANGED hasn't been generated",
107         "expected WindowEvent.WINDOW_STATE_CHANGED hasn't been generated",
108     };
109 
110     static final int stagesCount = 7;
111     static final int actionsCount = 9;
112 
113     static Method[] preActions = new Method[actionsCount];
114     static Method[] postActions = new Method[actionsCount];
115     static Method[] isActionsAllowed = new Method[actionsCount];
116     static Method[] checksActionEvents = new Method[actionsCount];
117 
118     static Robot robot;
119 
120     static boolean doStartTest;
121     static String osName = System.getProperty("os.name");
122 
123 
main(String[] args)124     public static void main(String[] args) {
125         checkTesting();
126 
127     }
128 
performTesting()129     public static void performTesting() {
130         isUnix = osName.equals("Linux") || osName.equals("SunOS");
131 
132         Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
133                 public void eventDispatched(AWTEvent e) {
134                     if (e.getID() == MouseEvent.MOUSE_CLICKED) {
135                         if (eventSrc != null & eventSrc != uncheckedSrc && e.getSource() != eventSrc) {
136                             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": " + msgError);
137                             testResult = -1;
138                         }
139                         if (eventSrc != null){
140                             synchronized (eventSrc) {
141                                 dispatchedCond = true;
142                                 eventSrc.notify();
143                             }
144                         }
145                     }
146 
147                     if (doCheckEvents && (e.getSource() == topw || e.getSource() == f)) {
148 
149                         //System.err.println("AWTEventListener: catched the event " + e);
150 
151                         try {
152                             checksActionEvents[actNum].invoke(null, new Object[] {e});
153                         } catch (InvocationTargetException ite) {
154                             ite.printStackTrace();
155                         } catch (IllegalAccessException iae) {
156                             iae.printStackTrace();
157                         }
158                         return;
159                     }
160                 }
161             }, 0xffffffffffffffffL);
162 
163         Method[] allMethods;
164 
165         try {
166             allMethods = AutoTestOnTop.class.getDeclaredMethods();
167         } catch (SecurityException se) {
168             throw new RuntimeException(se);
169         }
170 
171         for (int i = 0; i < allMethods.length; i++) {
172             String name = allMethods[i].getName();
173             if (name.startsWith("preAction")) {
174                 preActions[name.charAt(name.length() - 1) - '0'] = allMethods[i];
175             } else if (name.startsWith("postAction")) {
176                 postActions[name.charAt(name.length() - 1) - '0'] = allMethods[i];
177             } else if (name.startsWith("isActionAllowed")) {
178                 isActionsAllowed[name.charAt(name.length() - 1) - '0'] = allMethods[i];
179             } else if (name.startsWith("checkActionEvents")) {
180                 checksActionEvents[name.charAt(name.length() - 1) - '0'] = allMethods[i];
181             }
182         }
183 
184         f = new Frame("Auxiliary Frame");
185         f.setBounds(X, Y, 650, 100);
186         f.setVisible(true);
187         waitTillShown(f);
188 
189         try {
190             robot = new Robot();
191             robot.setAutoDelay(100);
192         } catch (AWTException e) {
193             throw new RuntimeException("Error: unable to create robot", e);
194         }
195 
196         mainTest();
197 
198         if (testResult != 0) {
199             System.err.println("The following errors were encountered: ");
200             for (int i = 0; i < errors.size(); i++) {
201                 System.err.println(errors.get(i).toString());
202             }
203             throw new RuntimeException("Test failed.");
204         } else {
205             System.err.println("Test PASSED.");
206         }
207     }
208 
mainTest()209     public static void mainTest() {
210 //         stageNum = 0;
211 //         for (int i = 0; i < 5; i++) {
212 //             actNum = 2;
213 //             System.err.println("************************* A C T I O N " + actNum + " *************************");
214 //             doStage(stageNum, actNum);
215 // //             pause(500);
216 //             actNum = 3;
217 //             System.err.println("************************* A C T I O N " + actNum + " *************************");
218 //             doStage(stageNum, actNum);
219 // //             pause(500);
220 //         }
221         for (stageNum = 0; stageNum < stagesCount; stageNum++) {
222             System.err.println("************************* S T A G E " + stageNum + " *************************");
223             for (actNum = 0; actNum < actionsCount; actNum++) {
224                 System.err.println("************************* A C T I O N " + actNum + " *************************");
225                 doStage(stageNum, actNum);
226             } // for thru actNum
227         } // fow thru stageNum
228 
229         eventSrc = null;
230     }
231 
doStage(int stageNum, int actNum)232     private static void doStage(int stageNum, int actNum) {
233         try {
234 
235             if (!((Boolean)isActionsAllowed[actNum].invoke(null, new Object[0])).booleanValue()) {
236                 System.err.println("Action skipped due to a platform limitations");
237                 return;
238             }
239 
240             STATE_SEMA.reset();
241             createWindow(stageNum);
242 
243             //*************************
244             // Set window always-on-top
245             //*************************
246 
247             preActions[actNum].invoke(null, new Object[0]);
248             setAlwaysOnTop(topw, true);
249             waitForIdle(true);
250 
251             if (!topw.isAlwaysOnTopSupported()) return;
252 
253             postActions[actNum].invoke(null, new Object[0]);
254             waitForIdle(false);
255 
256             STATE_SEMA.reset();
257 
258             testForAlwaysOnTop();
259 
260             //*****************************
261             // Set window not always-on-top
262             //*****************************
263 
264             preActions[actNum].invoke(null, new Object[0]);
265             setAlwaysOnTop(topw, false);
266             waitForIdle(true);
267             postActions[actNum].invoke(null, new Object[0]);
268             waitForIdle(false);
269             STATE_SEMA.reset();
270 
271             testForNotAlwaysOnTop();
272 
273         } catch (InvocationTargetException ite) {
274             ite.printStackTrace();
275         } catch (Exception ex) {
276             throw new RuntimeException(ex);
277         }
278     }
279 
checkTesting()280     private static void checkTesting() {
281         if (Toolkit.getDefaultToolkit().isAlwaysOnTopSupported()) {
282             performTesting();
283         }
284     }
285 
testForAlwaysOnTop()286     public static void testForAlwaysOnTop() {
287         System.err.println("Checking for always-on-top " + topw);
288 
289         ensureInitialWinPosition(topw);
290 
291         // Check that always-on-top window is topmost.
292         // - Click on always-on-top window on the windows cross area.
293         clickOn(topw, f, 10, 50, "setting " + msgVisibility +
294                 " window (1) always-on-top didn't make it topmost");
295 
296         // Check that we can't change z-order of always-on-top window.
297         // - a) Try to put the other window on the top.
298         f.toFront();
299         clickOn(uncheckedSrc, f, 450, 50, ""); // coz toFront() works not always
300         pause(300);
301 
302         // - b) Click on always-on-top window on the windows cross area.
303         clickOn(topw, f, 10, 50, "setting " + msgVisibility +
304                 " window (1) always-on-top didn't make it such");
305 
306         // Ask for always-on-top property
307         if (isAlwaysOnTop(topw) != true)
308                 error("Test failed: stage #" + stageNum + ", action #" + actNum + ": " + msgCase + ": " + msgAction +
309                                    ": isAlwaysOnTop() returned 'false' for window (1) set always-on-top at state "
310                                    + msgVisibility);
311     }
312 
testForNotAlwaysOnTop()313     public static void testForNotAlwaysOnTop() {
314         System.err.println("Checking for non always-on-top of " + topw);
315         ensureInitialWinPosition(topw);
316 
317         if (msgVisibility.equals("visible") && actNum != 2) {
318             // Check that the window remains topmost.
319             // - click on the window on the windows cross area.
320             clickOn(topw, f, 10, 50, "setting " + msgVisibility +
321                     " window (1) not always-on-top didn't keep it topmost");
322         }
323 
324         // Check that we can change z-order of not always-on-top window.
325         // - a) try to put the other window on the top.
326         f.toFront();
327         clickOn(uncheckedSrc, f, 450, 50, ""); // coz toFront() works not always
328         pause(300);
329 
330         // - b) click on not always-on-top window on the windows cross area.
331         clickOn(f, f, 10, 50, "setting " + msgVisibility +
332                 " window (1) not always-on-top didn't make it such");
333 
334         // Ask for always-on-top property
335         if (isAlwaysOnTop(topw) != false)
336             error("Test failed: stage #" + stageNum + ", action #" + actNum + ": " + msgCase + ": " + msgAction +
337                                ": isAlwaysOnTop() returned 'true' for window (1) set not always-on-top at state "
338                                + msgVisibility);
339     }
340 
341 
createWindow(int stageNum)342     private static void createWindow(int stageNum) {
343         // Free native resourses
344         if (topw != null) {
345             topw.dispose();
346         }
347 
348         switch (stageNum) {
349         case 0:
350             topw = new Frame("Top Frame");
351             msgCase.replace(0, msgCase.length(), "Frame (1) over Frame (2)");
352             break;
353         case 1:
354             topw = new JFrame("Top JFrame");
355             msgCase.replace(0, msgCase.length(), "JFrame (1) over Frame (2)");
356             break;
357         case 2:
358             topw = new Dialog(parentw, "Top Dialog");
359             msgCase.replace(0, msgCase.length(), "Dialog (1) over Frame (2)");
360             break;
361         case 3:
362             topw = new JDialog(parentw, "Top JDialog");
363             msgCase.replace(0, msgCase.length(), "JDialog (1) over Frame (2)");
364             break;
365         case 4:
366             topw = new Frame("Top Frame");
367             f.dispose();
368             f = new Dialog(parentf, "Auxiliary Dialog");
369             f.setBounds(X, Y, 650, 100);
370             f.setVisible(true);
371             waitTillShown(f);
372             msgCase.replace(0, msgCase.length(), "Frame (1) over Dialog (2)");
373             break;
374         case 5:
375             topw = new Window(parentw);
376             msgCase.replace(0, msgCase.length(), "Window (1) over Frame (2)");
377             break;
378         case 6:
379             topw = new JWindow(parentw);
380             msgCase.replace(0, msgCase.length(), "JWindow (1) over Frame (2)");
381             break;
382         }
383         topw.addWindowStateListener(new WindowAdapter() {
384                 public void windowStateChanged(WindowEvent e) {
385                     System.err.println("* " + e);
386                     STATE_SEMA.raise();
387                 }
388             });
389         topw.setSize(300, 100);
390     }
391 
392     /**
393      * 0: setting always-on-top to invisible window
394      * 1: setting always-on-top to visible window
395      * 2: always-on-top on visible non-focusable window
396      * 3: always-on-top on visible, dragging topw after that
397      * 4: always-on-top on visible, dragging f after that
398      * 5: always-on-top on (visible, maximized), make normal after that
399      * 6: always-on-top on (visible, iconified), make normal after that
400      * 7: always-on-top on visible, iconify/deiconify after that
401      * 8: always-on-top on visible, maximize/restore after that
402      */
preAction_0()403     public static void preAction_0() {
404         topw.setVisible(false);
405     }
postAction_0()406     public static void postAction_0() {
407         if (topw.isShowing()) {
408             error("Test failed: stage #" + stageNum + ", action #" + actNum + ": " + msgCase +
409                                ": no actions with windows: changing always-on-top property at window (1) state 'invisible' makes window (1) visible");
410         }
411         setWindowVisible("no actions with windows", "invisible");
412     }
isActionAllowed_0()413     public static boolean isActionAllowed_0() {
414         // Window on Linux is always always-on-top!
415         return !((stageNum == 5 || stageNum == 6) && isUnix) && (stageNum < stagesCount);
416     }
checkActionEvents_0(AWTEvent e)417     public static void checkActionEvents_0(AWTEvent e) {
418         System.err.println(e.toString());
419    }
420 
preAction_1()421     public static void preAction_1() {
422         setWindowVisible("no actions with windows", "visible");
423     }
postAction_1()424     public static void postAction_1() {}
isActionAllowed_1()425     public static boolean isActionAllowed_1() {
426         return !((stageNum == 5 || stageNum == 6) && isUnix) && (stageNum < stagesCount );
427     }
checkActionEvents_1(AWTEvent e)428     public static void checkActionEvents_1(AWTEvent e) {
429         System.err.println(e.toString());
430         if (e instanceof PaintEvent) {
431             return;
432         }
433         eventsCheckPassed = false;
434         error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
435                            ":  unexpected event " + e + " was generated");
436     }
437 
preAction_2()438     public static void preAction_2() {
439         setWindowVisible("when window (1) set not focusable", "visible");
440         topw.setFocusableWindowState(false);
441         f.toFront();
442         pause(300);
443     }
postAction_2()444     public static void postAction_2() {}
isActionAllowed_2()445     public static boolean isActionAllowed_2() {
446         return !((stageNum == 5 || stageNum == 6) && isUnix) && (stageNum < stagesCount);
447     }
checkActionEvents_2(AWTEvent e)448     public static void checkActionEvents_2(AWTEvent e) {
449         System.err.println(e.toString());
450         if ( (e.getID() >= FocusEvent.FOCUS_FIRST && e.getID() <= FocusEvent.FOCUS_LAST) ||
451              (e.getID() == WindowEvent.WINDOW_LOST_FOCUS && e.getID() == WindowEvent.WINDOW_GAINED_FOCUS)) {
452             eventsCheckPassed = false;
453             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " +
454                                msgAction + ": after call " + msgFunc +
455                                ": unexpected event " + e + " was generated");
456         }
457     }
458 
preAction_3()459     public static void preAction_3() {
460         setWindowVisible("after dragging",  "visible");
461     }
postAction_3()462     public static void postAction_3() {
463         Point p = topw.getLocationOnScreen();
464         int x = p.x + 150, y = p.y + 5;
465 
466         try {                      // Take a pause to avoid double click
467             Thread.sleep(500);     // when called one after another.
468         } catch (InterruptedException ie) {
469             ie.printStackTrace();
470         } catch (IllegalComponentStateException e) {
471             e.printStackTrace();
472         }
473 
474         // Drag the window.
475         robot.mouseMove(x, y);
476         robot.mousePress(InputEvent.BUTTON1_MASK);
477         robot.mouseMove(X + 150, Y + 100);
478         robot.mouseMove(x, y);
479         robot.mouseRelease(InputEvent.BUTTON1_MASK);
480     }
isActionAllowed_3()481     public static boolean isActionAllowed_3() {
482         return (stageNum < 5);
483     }
checkActionEvents_3(AWTEvent e)484     public static void checkActionEvents_3(AWTEvent e) {
485         System.err.println(e.toString());
486     }
487 
preAction_4()488     public static void preAction_4() {
489         setWindowVisible("after dragging window (2)",  "visible");
490     }
postAction_4()491     public static void postAction_4() {
492         Point p = f.getLocationOnScreen();
493         int x = p.x + 400, y = p.y + 5;
494 
495         try {                      // Take a pause to avoid double click
496             Thread.sleep(500);     // when called one after another.
497         } catch (InterruptedException ie) {
498             ie.printStackTrace();
499         } catch (IllegalComponentStateException e) {
500             e.printStackTrace();
501         }
502 
503         // Drag the window.
504         robot.mouseMove(x, y);
505         robot.mousePress(InputEvent.BUTTON1_MASK);
506         robot.mouseMove(X + 400, Y + 100);
507         robot.mouseMove(x, y);
508         robot.mouseRelease(InputEvent.BUTTON1_MASK);
509 
510         ensureInitialWinPosition(f);
511     }
isActionAllowed_4()512     public static boolean isActionAllowed_4() {
513         return !((stageNum == 5 || stageNum == 6) && isUnix);
514     }
checkActionEvents_4(AWTEvent e)515     public static void checkActionEvents_4(AWTEvent e) {
516         System.err.println(e.toString());
517     }
518 
519     // Metacity has a bug not allowing to set a window to NORMAL state!!!
520 
preAction_5()521     public static void preAction_5() {
522         setWindowVisible("at state 'maximized'",  "visible");
523         ((Frame)topw).setExtendedState(Frame.MAXIMIZED_BOTH);
524         waitForStateChange();
525     }
postAction_5()526     public static void postAction_5() {
527         ((Frame)topw).setExtendedState(Frame.NORMAL);
528         waitForStateChange();
529     }
isActionAllowed_5()530     public static boolean isActionAllowed_5() {
531         return (stageNum < 2);
532     }
checkActionEvents_5(AWTEvent e)533     public static void checkActionEvents_5(AWTEvent e) {
534         System.err.println("=" + e.toString());
535         if (e.getID() == WindowEvent.WINDOW_STATE_CHANGED) {
536             eventsCheckPassed = true;
537         }
538     }
539 
preAction_6()540     public static void preAction_6() {
541         setWindowVisible("at state 'iconified'",  "visible");
542         System.err.println("Iconifying " + topw);
543         ((Frame)topw).setExtendedState(Frame.ICONIFIED);
544         if (!waitForStateChange()) {
545             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
546                                ":  state change to ICONIFIED hasn't been generated");
547         }
548     }
postAction_6()549     public static void postAction_6() {
550         System.err.println("Restoring " + topw);
551         ((Frame)topw).setExtendedState(Frame.NORMAL);
552         if (!waitForStateChange()) {
553             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
554                                ":  state change to NORMAL hasn't been generated");
555         }
556     }
isActionAllowed_6()557     public static boolean isActionAllowed_6() {
558         return (stageNum < 2 );
559     }
checkActionEvents_6(AWTEvent e)560     public static void checkActionEvents_6(AWTEvent e) {
561         System.err.println("+" + e.toString());
562         if (e.getID() == WindowEvent.WINDOW_STATE_CHANGED) {
563             eventsCheckPassed = true;
564         }
565     }
566 
preAction_7()567     public static void preAction_7() {
568         setWindowVisible("before state 'iconified'",  "visible");
569     }
postAction_7()570     public static void postAction_7() {
571         System.err.println("Setting iconified");
572         ((Frame)topw).setExtendedState(Frame.ICONIFIED);
573         if (!waitForStateChange()) {
574             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
575                                ":  state change to ICONIFIED hasn't been generated");
576         }
577         System.err.println("Setting normal");
578         ((Frame)topw).setExtendedState(Frame.NORMAL);
579         if (!waitForStateChange()) {
580             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
581                                ":  state change to NORMAL hasn't been generated");
582         }
583     }
isActionAllowed_7()584     public static boolean isActionAllowed_7() {
585         return (stageNum < 2);
586     }
checkActionEvents_7(AWTEvent e)587     public static void checkActionEvents_7(AWTEvent e) {
588         System.err.println(e.toString());
589         if (e.getID() == WindowEvent.WINDOW_STATE_CHANGED) {
590             eventsCheckPassed = true;
591         }
592     }
593 
preAction_8()594     public static void preAction_8() {
595         setWindowVisible("before state 'maximized'",  "visible");
596     }
postAction_8()597     public static void postAction_8() {
598         ((Frame)topw).setExtendedState(Frame.MAXIMIZED_BOTH);
599         if (!waitForStateChange()) {
600             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
601                                ":  state change to MAXIMIZED hasn't been generated");
602         }
603         ((Frame)topw).setExtendedState(Frame.NORMAL);
604         if (!waitForStateChange()) {
605             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
606                                ":  state change to NORMAL hasn't been generated");
607         }
608     }
isActionAllowed_8()609     public static boolean isActionAllowed_8() {
610         return (stageNum < 2);
611     }
checkActionEvents_8(AWTEvent e)612     public static void checkActionEvents_8(AWTEvent e) {
613         System.err.println(e.toString());
614         if (e.getID() == WindowEvent.WINDOW_STATE_CHANGED) {
615            eventsCheckPassed = true;
616         }
617     }
618 
619     //***************************************************************************
620 
setWindowVisible(String mAction, String mVisibility)621     private static void setWindowVisible(String mAction, String mVisibility) {
622         msgAction.replace(0, msgAction.length(), mAction);
623         msgVisibility.replace(0, msgVisibility.length(), mVisibility);
624 
625         topw.setVisible(true);
626         pause(100); // Needs for Sawfish
627         topw.setLocation(X, Y);
628         waitTillShown(topw);
629         f.toFront();
630         pause(300);
631     }
632 
clickOn(Object src, Window relwin, int x, int y, String errorStr)633     private static void clickOn(Object src, Window relwin, int x, int y, String errorStr) {
634         Point p = relwin.getLocationOnScreen();
635         int counter = 10;
636         while (--counter > 0) {
637             eventSrc = src;
638             msgError.replace(0, msgError.length(), errorStr);
639 
640             robot.mouseMove(p.x + x, p.y + y);
641             robot.mousePress(InputEvent.BUTTON1_MASK);
642             robot.mouseRelease(InputEvent.BUTTON1_MASK);
643 
644             synchronized (eventSrc) {
645                 if (!dispatchedCond) {
646                     try {
647                         eventSrc.wait(1000);
648                     } catch (InterruptedException e) {
649                         e.printStackTrace();
650                     }
651                 }
652                 if (!dispatchedCond) {
653                     //System.err.println("clickOn: MOUSE_CLICKED event losed, trying to generate it again...");
654                     continue;
655                 }
656                 dispatchedCond = false;
657             }
658             break;
659         } // end while
660         if (counter <= 0) {
661             eventSrc = uncheckedSrc;
662             error("Test: internal error: could't catch MOUSE_CLICKED event. Skip testing this stage");
663         }
664     }
665 
setAlwaysOnTop(Window w, boolean value)666     private static void setAlwaysOnTop(Window w, boolean value) {
667         System.err.println("Setting always on top on " + w + " to " + value);
668         robot.mouseMove(X - 50, Y - 50); // Move out of the window
669         msgFunc.replace(0, msgCase.length(), "setAlwaysOnTop()");
670         try {
671             w.setAlwaysOnTop(value);
672         } catch (Exception e) {
673             error("Test failed: stage#" + stageNum + "action #" + actNum + ": " + msgCase + ": " + msgAction +
674                                ": setAlwaysOnTop(" + value + ") called at state " + msgVisibility +
675                                " threw exeption " + e);
676         }
677     }
678 
isAlwaysOnTop(Window w)679     private static boolean isAlwaysOnTop(Window w) {
680         robot.mouseMove(X - 50, Y - 50); // Move out of the window
681         msgFunc.replace(0, msgCase.length(), "isAlwaysOnTop()");
682         boolean result = false;
683         try {
684             result = w.isAlwaysOnTop();
685         } catch (Exception e) {
686             error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction +
687                                ": isAlwaysOnTop() called at state " + msgVisibility +
688                                " threw exeption " + e);
689         }
690         return result;
691     }
692 
waitTillShown(Component c)693     private static void waitTillShown(Component c) {
694         while (true) {
695             try {
696                 Thread.sleep(100);
697                 c.getLocationOnScreen();
698                 break;
699             } catch (InterruptedException e) {
700                 e.printStackTrace();
701                 break;
702             }
703         }
704     }
705 
waitForIdle(boolean doCheck)706     private static void waitForIdle(boolean doCheck) {
707         try {
708             robot.waitForIdle();
709             EventQueue.invokeAndWait( new Runnable() {
710                     public void run() {} // Dummy implementation
711                 } );
712         } catch(InterruptedException ite) {
713             System.err.println("waitForIdle, non-fatal exception caught:");
714             ite.printStackTrace();
715         } catch(InvocationTargetException ine) {
716             System.err.println("waitForIdle, non-fatal exception caught:");
717             ine.printStackTrace();
718         }
719         doCheckEvents = doCheck;
720 
721         if (doCheck) {
722             eventsCheckPassed = eventsCheckInitVals[actNum]; // Initialize
723         } else if (!eventsCheckPassed &&
724                  msgEventsChecks[actNum] != null) {
725 
726 
727             // Some expected event hasn't been catched,
728             // so give it one more chance...
729             doCheckEvents = true;
730             pause(500);
731             doCheckEvents = false;
732 
733             if (!eventsCheckPassed) {
734                 testResult = -1;
735                 error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call "
736                                    + msgFunc + ": " + msgEventsChecks[actNum]);
737             }
738         }
739     }
740 
waitForStateChange()741     private static boolean waitForStateChange() {
742         System.err.println("------- Waiting for state change");
743         try {
744             STATE_SEMA.doWait(3000);
745         } catch (InterruptedException ie) {
746             System.err.println("Wait interrupted: " + ie);
747         }
748         boolean state = STATE_SEMA.getState();
749         STATE_SEMA.reset();
750         robot.delay(1000); // animation normal <--> maximized states
751         return state;
752     }
753 
ensureInitialWinPosition(Window w)754     private static void ensureInitialWinPosition(Window w) {
755         int counter = 30;
756         while (w.getLocationOnScreen().y != Y && --counter > 0) {
757             try {
758                 Thread.sleep(100);
759             } catch (InterruptedException e) {
760                 e.printStackTrace();
761                 break;
762             }
763         }
764         if (counter <= 0) {
765             w.setLocation(X, Y);
766             pause(100);
767             System.err.println("Test: window set to initial position forcedly");
768         }
769     }
770 
pause(int mls)771     private static void pause(int mls) {
772         try {
773             Thread.sleep(mls);
774         } catch (InterruptedException e) {
775             e.printStackTrace();
776         }
777     }
778 
error(String msg)779     private static void error(String msg) {
780         errors.add(msg);
781         System.err.println(msg);
782     }
783 }
784 
785 class Semaphore {
786     boolean state = false;
787     int waiting = 0;
Semaphore()788     public Semaphore() {
789     }
doWait()790     public synchronized void doWait() throws InterruptedException {
791         if (state) {
792             return;
793         }
794         waiting++;
795         wait();
796         waiting--;
797     }
doWait(int timeout)798     public synchronized void doWait(int timeout) throws InterruptedException {
799         if (state) {
800             return;
801         }
802         waiting++;
803         wait(timeout);
804         waiting--;
805     }
raise()806     public synchronized void raise() {
807         state = true;
808         if (waiting > 0) {
809             notifyAll();
810         }
811     }
812 
doNotify()813     public synchronized void doNotify() {
814         notifyAll();
815     }
getState()816     public synchronized boolean getState() {
817         return state;
818     }
819 
reset()820     public synchronized void reset() {
821         state = false;
822     }
823 }
824