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