/*
 * Copyright 2003-2005 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/**
 * This class is a placeholder for all internal static objects that represent
 * system state. We keep our representation up-to-date with actual system
 * state by tracking events, such as X Focus, Component under cursor etc.
 * All attributes should be static private with accessors to simpify change
 * tracking.
 */
package sun.awt.X11;

import java.awt.Component;
import java.lang.ref.WeakReference;

class XAwtState {
    /**
     * The mouse is over this component.
     * If the component is not disabled, it received MOUSE_ENTERED but no MOUSE_EXITED.
     */
    private static WeakReference componentMouseEnteredRef = null;

    static void setComponentMouseEntered(Component component) {
        XToolkit.awtLock();
        try {
            if (component == null) {
                componentMouseEnteredRef = null;
                return;
            }
            if (component != getComponentMouseEntered()) {
                componentMouseEnteredRef = new WeakReference(component);
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    static Component getComponentMouseEntered() {
        XToolkit.awtLock();
        try {
            if (componentMouseEnteredRef == null) {
                return null;
            }
            return (Component)componentMouseEnteredRef.get();
        } finally {
            XToolkit.awtUnlock();
        }
    }

    /**
     * The XBaseWindow is created with OwnerGrabButtonMask
     * (see X vol. 1, 8.3.3.2) so inside the app Key, Motion, and Button events
     * are received by the window they actualy happened on, not the grabber.
     * Then XBaseWindow dispatches them to the grabber. As a result
     * XAnyEvent.get_window() returns actual window the event is originated,
     * though the event is dispatched by  the grabber.
     */
    private static boolean inManualGrab = false;

    static boolean isManualGrab() {
        return inManualGrab;
    }

    private static WeakReference grabWindowRef = null;

    /**
     * The X Active Grab overrides any other active grab by the same
     * client see XGrabPointer, XGrabKeyboard
     */
    static void setGrabWindow(XBaseWindow grabWindow) {
        setGrabWindow(grabWindow, false);
    }

    /**
     * Automatic passive grab doesn't override active grab see XGrabButton
     */
    static void setAutoGrabWindow(XBaseWindow grabWindow) {
        setGrabWindow(grabWindow, true);
    }

    private static void setGrabWindow(XBaseWindow grabWindow, boolean isAutoGrab) {
        XToolkit.awtLock();
        try {
            if (inManualGrab && isAutoGrab) {
                return;
            }
            inManualGrab = grabWindow != null && !isAutoGrab;
            if (grabWindow == null) {
                grabWindowRef = null;
                return;
            }
            if (grabWindow != getGrabWindow()) {
                grabWindowRef = new WeakReference(grabWindow);
            }
        } finally {
            XToolkit.awtUnlock();
        }
    }

    static XBaseWindow getGrabWindow() {
        XToolkit.awtLock();
        try {
            if (grabWindowRef == null) {
                return null;
            }
            XBaseWindow xbw = (XBaseWindow)grabWindowRef.get();
            if( xbw != null && xbw.isDisposed() ) {
                xbw = null;
                grabWindowRef = null;
            }else if( xbw == null ) {
                grabWindowRef = null;
            }
            return xbw;
        } finally {
            XToolkit.awtUnlock();
        }
    }
}
