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