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