/*
 * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
  @test
  @key headful
  @bug 4632143
  @summary Unit test for the RFE window/frame/dialog always on top
  @author dom@sparc.spb.su: area=awt.toplevel
  @run main/othervm/timeout=600 AutoTestOnTop
*/

import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.Component;
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.IllegalComponentStateException;
import java.awt.Point;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.event.PaintEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Vector;

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JWindow;

/**
 * @author tav@sparc.spb.su
 * @author dom@sparc.spb.su
 * Tests that always-on-top windows combine correctly with different kinds of window in different styles and conditions.
 *
 * !!! WARNING !!!
 * The test fails sometimes because the toFront() method doesn't guarantee
 * that after its invocation the frame will be placed above all other windows.
 */
public class AutoTestOnTop {
    private static final int X = 300;
    private static final int Y = 300;

    static Window topw;
    static Frame  parentw = new Frame();
    static Window f;
    static Frame  parentf = new Frame();

    static final Object  uncheckedSrc = new Object(); // used when no need to check event source
    static volatile Object  eventSrc = uncheckedSrc;
    static boolean dispatchedCond;

    static Semaphore STATE_SEMA = new Semaphore();
    static Semaphore VIS_SEMA = new Semaphore();
    static Vector errors = new Vector();

    static boolean isUnix = false;

    static StringBuffer msgError = new StringBuffer();
    static StringBuffer msgCase = new StringBuffer();
    static StringBuffer msgAction = new StringBuffer();
    static StringBuffer msgFunc = new StringBuffer();
    static StringBuffer msgVisibility = new StringBuffer();

    static volatile int stageNum;
    static volatile int actNum;
    static volatile int testResult = 0;

    static volatile boolean doCheckEvents;
    static volatile boolean eventsCheckPassed;
    static boolean[] eventsCheckInitVals = new boolean[] { // Whether events are checked for abcence or precence
        true, true, true, true, true, false, false, false, false
    };
    static String[] msgEventsChecks = new String[] {
        null, null, null, null, null,
        "expected WindowEvent.WINDOW_STATE_CHANGED hasn't been generated",
        "expected WindowEvent.WINDOW_STATE_CHANGED hasn't been generated",
        "expected WindowEvent.WINDOW_STATE_CHANGED hasn't been generated",
        "expected WindowEvent.WINDOW_STATE_CHANGED hasn't been generated",
    };

    static final int stagesCount = 7;
    static final int actionsCount = 9;

    static Method[] preActions = new Method[actionsCount];
    static Method[] postActions = new Method[actionsCount];
    static Method[] isActionsAllowed = new Method[actionsCount];
    static Method[] checksActionEvents = new Method[actionsCount];

    static Robot robot;

    static boolean doStartTest;
    static String osName = System.getProperty("os.name");


    public static void main(String[] args) {
        checkTesting();

    }

    public static void performTesting() {
        isUnix = osName.equals("Linux");

        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
                public void eventDispatched(AWTEvent e) {
                    if (e.getID() == MouseEvent.MOUSE_CLICKED) {
                        if (eventSrc != null & eventSrc != uncheckedSrc && e.getSource() != eventSrc) {
                            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": " + msgError);
                            testResult = -1;
                        }
                        if (eventSrc != null){
                            synchronized (eventSrc) {
                                dispatchedCond = true;
                                eventSrc.notify();
                            }
                        }
                    }

                    if (doCheckEvents && (e.getSource() == topw || e.getSource() == f)) {

                        //System.err.println("AWTEventListener: catched the event " + e);

                        try {
                            checksActionEvents[actNum].invoke(null, new Object[] {e});
                        } catch (InvocationTargetException ite) {
                            ite.printStackTrace();
                        } catch (IllegalAccessException iae) {
                            iae.printStackTrace();
                        }
                        return;
                    }
                }
            }, 0xffffffffffffffffL);

        Method[] allMethods;

        try {
            allMethods = AutoTestOnTop.class.getDeclaredMethods();
        } catch (SecurityException se) {
            throw new RuntimeException(se);
        }

        for (int i = 0; i < allMethods.length; i++) {
            String name = allMethods[i].getName();
            if (name.startsWith("preAction")) {
                preActions[name.charAt(name.length() - 1) - '0'] = allMethods[i];
            } else if (name.startsWith("postAction")) {
                postActions[name.charAt(name.length() - 1) - '0'] = allMethods[i];
            } else if (name.startsWith("isActionAllowed")) {
                isActionsAllowed[name.charAt(name.length() - 1) - '0'] = allMethods[i];
            } else if (name.startsWith("checkActionEvents")) {
                checksActionEvents[name.charAt(name.length() - 1) - '0'] = allMethods[i];
            }
        }

        f = new Frame("Auxiliary Frame");
        f.setBounds(X, Y, 650, 100);
        f.setVisible(true);
        waitTillShown(f);

        try {
            robot = new Robot();
            robot.setAutoDelay(100);
        } catch (AWTException e) {
            throw new RuntimeException("Error: unable to create robot", e);
        }

        mainTest();

        if (testResult != 0) {
            System.err.println("The following errors were encountered: ");
            for (int i = 0; i < errors.size(); i++) {
                System.err.println(errors.get(i).toString());
            }
            throw new RuntimeException("Test failed.");
        } else {
            System.err.println("Test PASSED.");
        }
    }

    public static void mainTest() {
//         stageNum = 0;
//         for (int i = 0; i < 5; i++) {
//             actNum = 2;
//             System.err.println("************************* A C T I O N " + actNum + " *************************");
//             doStage(stageNum, actNum);
// //             pause(500);
//             actNum = 3;
//             System.err.println("************************* A C T I O N " + actNum + " *************************");
//             doStage(stageNum, actNum);
// //             pause(500);
//         }
        for (stageNum = 0; stageNum < stagesCount; stageNum++) {
            System.err.println("************************* S T A G E " + stageNum + " *************************");
            for (actNum = 0; actNum < actionsCount; actNum++) {
                System.err.println("************************* A C T I O N " + actNum + " *************************");
                doStage(stageNum, actNum);
            } // for thru actNum
        } // fow thru stageNum

        eventSrc = null;
    }

    private static void doStage(int stageNum, int actNum) {
        try {

            if (!((Boolean)isActionsAllowed[actNum].invoke(null, new Object[0])).booleanValue()) {
                System.err.println("Action skipped due to a platform limitations");
                return;
            }

            STATE_SEMA.reset();
            createWindow(stageNum);

            //*************************
            // Set window always-on-top
            //*************************

            preActions[actNum].invoke(null, new Object[0]);
            setAlwaysOnTop(topw, true);
            waitForIdle(true);

            if (!topw.isAlwaysOnTopSupported()) return;

            postActions[actNum].invoke(null, new Object[0]);
            waitForIdle(false);

            STATE_SEMA.reset();

            testForAlwaysOnTop();

            //*****************************
            // Set window not always-on-top
            //*****************************

            preActions[actNum].invoke(null, new Object[0]);
            setAlwaysOnTop(topw, false);
            waitForIdle(true);
            postActions[actNum].invoke(null, new Object[0]);
            waitForIdle(false);
            STATE_SEMA.reset();

            testForNotAlwaysOnTop();

        } catch (InvocationTargetException ite) {
            ite.printStackTrace();
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    private static void checkTesting() {
        if (Toolkit.getDefaultToolkit().isAlwaysOnTopSupported()) {
            performTesting();
        }
    }

    public static void testForAlwaysOnTop() {
        System.err.println("Checking for always-on-top " + topw);

        ensureInitialWinPosition(topw);

        // Check that always-on-top window is topmost.
        // - Click on always-on-top window on the windows cross area.
        clickOn(topw, f, 10, 50, "setting " + msgVisibility +
                " window (1) always-on-top didn't make it topmost");

        // Check that we can't change z-order of always-on-top window.
        // - a) Try to put the other window on the top.
        f.toFront();
        clickOn(uncheckedSrc, f, 450, 50, ""); // coz toFront() works not always
        pause(300);

        // - b) Click on always-on-top window on the windows cross area.
        clickOn(topw, f, 10, 50, "setting " + msgVisibility +
                " window (1) always-on-top didn't make it such");

        // Ask for always-on-top property
        if (isAlwaysOnTop(topw) != true)
                error("Test failed: stage #" + stageNum + ", action #" + actNum + ": " + msgCase + ": " + msgAction +
                                   ": isAlwaysOnTop() returned 'false' for window (1) set always-on-top at state "
                                   + msgVisibility);
    }

    public static void testForNotAlwaysOnTop() {
        System.err.println("Checking for non always-on-top of " + topw);
        ensureInitialWinPosition(topw);

        if (msgVisibility.equals("visible") && actNum != 2) {
            // Check that the window remains topmost.
            // - click on the window on the windows cross area.
            clickOn(topw, f, 10, 50, "setting " + msgVisibility +
                    " window (1) not always-on-top didn't keep it topmost");
        }

        // Check that we can change z-order of not always-on-top window.
        // - a) try to put the other window on the top.
        f.toFront();
        clickOn(uncheckedSrc, f, 450, 50, ""); // coz toFront() works not always
        pause(300);

        // - b) click on not always-on-top window on the windows cross area.
        clickOn(f, f, 10, 50, "setting " + msgVisibility +
                " window (1) not always-on-top didn't make it such");

        // Ask for always-on-top property
        if (isAlwaysOnTop(topw) != false)
            error("Test failed: stage #" + stageNum + ", action #" + actNum + ": " + msgCase + ": " + msgAction +
                               ": isAlwaysOnTop() returned 'true' for window (1) set not always-on-top at state "
                               + msgVisibility);
    }


    private static void createWindow(int stageNum) {
        // Free native resourses
        if (topw != null) {
            topw.dispose();
        }

        switch (stageNum) {
        case 0:
            topw = new Frame("Top Frame");
            msgCase.replace(0, msgCase.length(), "Frame (1) over Frame (2)");
            break;
        case 1:
            topw = new JFrame("Top JFrame");
            msgCase.replace(0, msgCase.length(), "JFrame (1) over Frame (2)");
            break;
        case 2:
            topw = new Dialog(parentw, "Top Dialog");
            msgCase.replace(0, msgCase.length(), "Dialog (1) over Frame (2)");
            break;
        case 3:
            topw = new JDialog(parentw, "Top JDialog");
            msgCase.replace(0, msgCase.length(), "JDialog (1) over Frame (2)");
            break;
        case 4:
            topw = new Frame("Top Frame");
            f.dispose();
            f = new Dialog(parentf, "Auxiliary Dialog");
            f.setBounds(X, Y, 650, 100);
            f.setVisible(true);
            waitTillShown(f);
            msgCase.replace(0, msgCase.length(), "Frame (1) over Dialog (2)");
            break;
        case 5:
            topw = new Window(parentw);
            msgCase.replace(0, msgCase.length(), "Window (1) over Frame (2)");
            break;
        case 6:
            topw = new JWindow(parentw);
            msgCase.replace(0, msgCase.length(), "JWindow (1) over Frame (2)");
            break;
        }
        topw.addWindowStateListener(new WindowAdapter() {
                public void windowStateChanged(WindowEvent e) {
                    System.err.println("* " + e);
                    STATE_SEMA.raise();
                }
            });
        topw.setSize(300, 100);
    }

    /**
     * 0: setting always-on-top to invisible window
     * 1: setting always-on-top to visible window
     * 2: always-on-top on visible non-focusable window
     * 3: always-on-top on visible, dragging topw after that
     * 4: always-on-top on visible, dragging f after that
     * 5: always-on-top on (visible, maximized), make normal after that
     * 6: always-on-top on (visible, iconified), make normal after that
     * 7: always-on-top on visible, iconify/deiconify after that
     * 8: always-on-top on visible, maximize/restore after that
     */
    public static void preAction_0() {
        topw.setVisible(false);
    }
    public static void postAction_0() {
        if (topw.isShowing()) {
            error("Test failed: stage #" + stageNum + ", action #" + actNum + ": " + msgCase +
                               ": no actions with windows: changing always-on-top property at window (1) state 'invisible' makes window (1) visible");
        }
        setWindowVisible("no actions with windows", "invisible");
    }
    public static boolean isActionAllowed_0() {
        // Window on Linux is always always-on-top!
        return !((stageNum == 5 || stageNum == 6) && isUnix) && (stageNum < stagesCount);
    }
    public static void checkActionEvents_0(AWTEvent e) {
        System.err.println(e.toString());
   }

    public static void preAction_1() {
        setWindowVisible("no actions with windows", "visible");
    }
    public static void postAction_1() {}
    public static boolean isActionAllowed_1() {
        return !((stageNum == 5 || stageNum == 6) && isUnix) && (stageNum < stagesCount );
    }
    public static void checkActionEvents_1(AWTEvent e) {
        System.err.println(e.toString());
        if (e instanceof PaintEvent) {
            return;
        }
        eventsCheckPassed = false;
        error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
                           ":  unexpected event " + e + " was generated");
    }

    public static void preAction_2() {
        setWindowVisible("when window (1) set not focusable", "visible");
        topw.setFocusableWindowState(false);
        f.toFront();
        pause(300);
    }
    public static void postAction_2() {}
    public static boolean isActionAllowed_2() {
        return !((stageNum == 5 || stageNum == 6) && isUnix) && (stageNum < stagesCount);
    }
    public static void checkActionEvents_2(AWTEvent e) {
        System.err.println(e.toString());
        if ( (e.getID() >= FocusEvent.FOCUS_FIRST && e.getID() <= FocusEvent.FOCUS_LAST) ||
             (e.getID() == WindowEvent.WINDOW_LOST_FOCUS && e.getID() == WindowEvent.WINDOW_GAINED_FOCUS)) {
            eventsCheckPassed = false;
            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " +
                               msgAction + ": after call " + msgFunc +
                               ": unexpected event " + e + " was generated");
        }
    }

    public static void preAction_3() {
        setWindowVisible("after dragging",  "visible");
    }
    public static void postAction_3() {
        Point p = topw.getLocationOnScreen();
        int x = p.x + 150, y = p.y + 5;

        try {                      // Take a pause to avoid double click
            Thread.sleep(500);     // when called one after another.
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        } catch (IllegalComponentStateException e) {
            e.printStackTrace();
        }

        // Drag the window.
        robot.mouseMove(x, y);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.mouseMove(X + 150, Y + 100);
        robot.mouseMove(x, y);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);
    }
    public static boolean isActionAllowed_3() {
        return (stageNum < 5);
    }
    public static void checkActionEvents_3(AWTEvent e) {
        System.err.println(e.toString());
    }

    public static void preAction_4() {
        setWindowVisible("after dragging window (2)",  "visible");
    }
    public static void postAction_4() {
        Point p = f.getLocationOnScreen();
        int x = p.x + 400, y = p.y + 5;

        try {                      // Take a pause to avoid double click
            Thread.sleep(500);     // when called one after another.
        } catch (InterruptedException ie) {
            ie.printStackTrace();
        } catch (IllegalComponentStateException e) {
            e.printStackTrace();
        }

        // Drag the window.
        robot.mouseMove(x, y);
        robot.mousePress(InputEvent.BUTTON1_MASK);
        robot.mouseMove(X + 400, Y + 100);
        robot.mouseMove(x, y);
        robot.mouseRelease(InputEvent.BUTTON1_MASK);

        ensureInitialWinPosition(f);
    }
    public static boolean isActionAllowed_4() {
        return !((stageNum == 5 || stageNum == 6) && isUnix);
    }
    public static void checkActionEvents_4(AWTEvent e) {
        System.err.println(e.toString());
    }

    // Metacity has a bug not allowing to set a window to NORMAL state!!!

    public static void preAction_5() {
        setWindowVisible("at state 'maximized'",  "visible");
        ((Frame)topw).setExtendedState(Frame.MAXIMIZED_BOTH);
        waitForStateChange();
    }
    public static void postAction_5() {
        ((Frame)topw).setExtendedState(Frame.NORMAL);
        waitForStateChange();
    }
    public static boolean isActionAllowed_5() {
        return (stageNum < 2);
    }
    public static void checkActionEvents_5(AWTEvent e) {
        System.err.println("=" + e.toString());
        if (e.getID() == WindowEvent.WINDOW_STATE_CHANGED) {
            eventsCheckPassed = true;
        }
    }

    public static void preAction_6() {
        setWindowVisible("at state 'iconified'",  "visible");
        System.err.println("Iconifying " + topw);
        ((Frame)topw).setExtendedState(Frame.ICONIFIED);
        if (!waitForStateChange()) {
            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
                               ":  state change to ICONIFIED hasn't been generated");
        }
    }
    public static void postAction_6() {
        System.err.println("Restoring " + topw);
        ((Frame)topw).setExtendedState(Frame.NORMAL);
        if (!waitForStateChange()) {
            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
                               ":  state change to NORMAL hasn't been generated");
        }
    }
    public static boolean isActionAllowed_6() {
        return (stageNum < 2 );
    }
    public static void checkActionEvents_6(AWTEvent e) {
        System.err.println("+" + e.toString());
        if (e.getID() == WindowEvent.WINDOW_STATE_CHANGED) {
            eventsCheckPassed = true;
        }
    }

    public static void preAction_7() {
        setWindowVisible("before state 'iconified'",  "visible");
    }
    public static void postAction_7() {
        System.err.println("Setting iconified");
        ((Frame)topw).setExtendedState(Frame.ICONIFIED);
        if (!waitForStateChange()) {
            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
                               ":  state change to ICONIFIED hasn't been generated");
        }
        System.err.println("Setting normal");
        ((Frame)topw).setExtendedState(Frame.NORMAL);
        if (!waitForStateChange()) {
            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
                               ":  state change to NORMAL hasn't been generated");
        }
    }
    public static boolean isActionAllowed_7() {
        return (stageNum < 2);
    }
    public static void checkActionEvents_7(AWTEvent e) {
        System.err.println(e.toString());
        if (e.getID() == WindowEvent.WINDOW_STATE_CHANGED) {
            eventsCheckPassed = true;
        }
    }

    public static void preAction_8() {
        setWindowVisible("before state 'maximized'",  "visible");
    }
    public static void postAction_8() {
        ((Frame)topw).setExtendedState(Frame.MAXIMIZED_BOTH);
        if (!waitForStateChange()) {
            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
                               ":  state change to MAXIMIZED hasn't been generated");
        }
        ((Frame)topw).setExtendedState(Frame.NORMAL);
        if (!waitForStateChange()) {
            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call " + msgFunc +
                               ":  state change to NORMAL hasn't been generated");
        }
    }
    public static boolean isActionAllowed_8() {
        return (stageNum < 2);
    }
    public static void checkActionEvents_8(AWTEvent e) {
        System.err.println(e.toString());
        if (e.getID() == WindowEvent.WINDOW_STATE_CHANGED) {
           eventsCheckPassed = true;
        }
    }

    //***************************************************************************

    private static void setWindowVisible(String mAction, String mVisibility) {
        msgAction.replace(0, msgAction.length(), mAction);
        msgVisibility.replace(0, msgVisibility.length(), mVisibility);

        topw.setVisible(true);
        pause(100); // Needs for Sawfish
        topw.setLocation(X, Y);
        waitTillShown(topw);
        f.toFront();
        pause(300);
    }

    private static void clickOn(Object src, Window relwin, int x, int y, String errorStr) {
        Point p = relwin.getLocationOnScreen();
        int counter = 10;
        while (--counter > 0) {
            eventSrc = src;
            msgError.replace(0, msgError.length(), errorStr);

            robot.mouseMove(p.x + x, p.y + y);
            robot.mousePress(InputEvent.BUTTON1_MASK);
            robot.mouseRelease(InputEvent.BUTTON1_MASK);

            synchronized (eventSrc) {
                if (!dispatchedCond) {
                    try {
                        eventSrc.wait(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if (!dispatchedCond) {
                    //System.err.println("clickOn: MOUSE_CLICKED event losed, trying to generate it again...");
                    continue;
                }
                dispatchedCond = false;
            }
            break;
        } // end while
        if (counter <= 0) {
            eventSrc = uncheckedSrc;
            error("Test: internal error: could't catch MOUSE_CLICKED event. Skip testing this stage");
        }
    }

    private static void setAlwaysOnTop(Window w, boolean value) {
        System.err.println("Setting always on top on " + w + " to " + value);
        robot.mouseMove(X - 50, Y - 50); // Move out of the window
        msgFunc.replace(0, msgCase.length(), "setAlwaysOnTop()");
        try {
            w.setAlwaysOnTop(value);
        } catch (Exception e) {
            error("Test failed: stage#" + stageNum + "action #" + actNum + ": " + msgCase + ": " + msgAction +
                               ": setAlwaysOnTop(" + value + ") called at state " + msgVisibility +
                               " threw exception " + e);
        }
    }

    private static boolean isAlwaysOnTop(Window w) {
        robot.mouseMove(X - 50, Y - 50); // Move out of the window
        msgFunc.replace(0, msgCase.length(), "isAlwaysOnTop()");
        boolean result = false;
        try {
            result = w.isAlwaysOnTop();
        } catch (Exception e) {
            error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction +
                               ": isAlwaysOnTop() called at state " + msgVisibility +
                               " threw exception " + e);
        }
        return result;
    }

    private static void waitTillShown(Component c) {
        while (true) {
            try {
                Thread.sleep(100);
                c.getLocationOnScreen();
                break;
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }

    private static void waitForIdle(boolean doCheck) {
        try {
            robot.waitForIdle();
            EventQueue.invokeAndWait( new Runnable() {
                    public void run() {} // Dummy implementation
                } );
        } catch(InterruptedException ite) {
            System.err.println("waitForIdle, non-fatal exception caught:");
            ite.printStackTrace();
        } catch(InvocationTargetException ine) {
            System.err.println("waitForIdle, non-fatal exception caught:");
            ine.printStackTrace();
        }
        doCheckEvents = doCheck;

        if (doCheck) {
            eventsCheckPassed = eventsCheckInitVals[actNum]; // Initialize
        } else if (!eventsCheckPassed &&
                 msgEventsChecks[actNum] != null) {


            // Some expected event hasn't been catched,
            // so give it one more chance...
            doCheckEvents = true;
            pause(500);
            doCheckEvents = false;

            if (!eventsCheckPassed) {
                testResult = -1;
                error("Test failed: stage #" + stageNum + ", action # " + actNum + ": " + msgCase + ": " + msgAction + ": after call "
                                   + msgFunc + ": " + msgEventsChecks[actNum]);
            }
        }
    }

    private static boolean waitForStateChange() {
        System.err.println("------- Waiting for state change");
        try {
            STATE_SEMA.doWait(3000);
        } catch (InterruptedException ie) {
            System.err.println("Wait interrupted: " + ie);
        }
        boolean state = STATE_SEMA.getState();
        STATE_SEMA.reset();
        robot.delay(1000); // animation normal <--> maximized states
        return state;
    }

    private static void ensureInitialWinPosition(Window w) {
        int counter = 30;
        while (w.getLocationOnScreen().y != Y && --counter > 0) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
        if (counter <= 0) {
            w.setLocation(X, Y);
            pause(100);
            System.err.println("Test: window set to initial position forcedly");
        }
    }

    private static void pause(int mls) {
        try {
            Thread.sleep(mls);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static void error(String msg) {
        errors.add(msg);
        System.err.println(msg);
    }
}

class Semaphore {
    boolean state = false;
    int waiting = 0;
    public Semaphore() {
    }
    public synchronized void doWait() throws InterruptedException {
        if (state) {
            return;
        }
        waiting++;
        wait();
        waiting--;
    }
    public synchronized void doWait(int timeout) throws InterruptedException {
        if (state) {
            return;
        }
        waiting++;
        wait(timeout);
        waiting--;
    }
    public synchronized void raise() {
        state = true;
        if (waiting > 0) {
            notifyAll();
        }
    }

    public synchronized void doNotify() {
        notifyAll();
    }
    public synchronized boolean getState() {
        return state;
    }

    public synchronized void reset() {
        state = false;
    }
}
