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