/*
 * Copyright (c) 2000, 2008, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package java.awt;

import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;

import java.awt.peer.KeyboardFocusManagerPeer;
import java.awt.peer.LightweightPeer;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;

import java.lang.ref.WeakReference;

import java.lang.reflect.Field;

import java.security.AccessController;
import java.security.PrivilegedAction;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.WeakHashMap;

import sun.util.logging.PlatformLogger;

import sun.awt.AppContext;
import sun.awt.HeadlessToolkit;
import sun.awt.SunToolkit;
import sun.awt.CausedFocusEvent;
import sun.awt.KeyboardFocusManagerPeerProvider;
import sun.awt.AWTAccessor;

/**
 * The KeyboardFocusManager is responsible for managing the active and focused
 * Windows, and the current focus owner. The focus owner is defined as the
 * Component in an application that will typically receive all KeyEvents
 * generated by the user. The focused Window is the Window that is, or
 * contains, the focus owner. Only a Frame or a Dialog can be the active
 * Window. The native windowing system may denote the active Window or its
 * children with special decorations, such as a highlighted title bar. The
 * active Window is always either the focused Window, or the first Frame or
 * Dialog that is an owner of the focused Window.
 * <p>
 * The KeyboardFocusManager is both a centralized location for client code to
 * query for the focus owner and initiate focus changes, and an event
 * dispatcher for all FocusEvents, WindowEvents related to focus, and
 * KeyEvents.
 * <p>
 * Some browsers partition applets in different code bases into separate
 * contexts, and establish walls between these contexts. In such a scenario,
 * there will be one KeyboardFocusManager per context. Other browsers place all
 * applets into the same context, implying that there will be only a single,
 * global KeyboardFocusManager for all applets. This behavior is
 * implementation-dependent. Consult your browser's documentation for more
 * information. No matter how many contexts there may be, however, there can
 * never be more than one focus owner, focused Window, or active Window, per
 * ClassLoader.
 * <p>
 * Please see
 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
 * How to Use the Focus Subsystem</a>,
 * a section in <em>The Java Tutorial</em>, and the
 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
 * for more information.
 *
 * @author David Mendenhall
 *
 * @see Window
 * @see Frame
 * @see Dialog
 * @see java.awt.event.FocusEvent
 * @see java.awt.event.WindowEvent
 * @see java.awt.event.KeyEvent
 * @since 1.4
 */
public abstract class KeyboardFocusManager
    implements KeyEventDispatcher, KeyEventPostProcessor
{

    // Shared focus engine logger
    private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");

    static {
        /* ensure that the necessary native libraries are loaded */
        Toolkit.loadLibraries();
        if (!GraphicsEnvironment.isHeadless()) {
            initIDs();
        }
        AWTAccessor.setKeyboardFocusManagerAccessor(
            new AWTAccessor.KeyboardFocusManagerAccessor() {
                public int shouldNativelyFocusHeavyweight(Component heavyweight,
                                                   Component descendant,
                                                   boolean temporary,
                                                   boolean focusedWindowChangeAllowed,
                                                   long time,
                                                   CausedFocusEvent.Cause cause)
                {
                    return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
                        heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
                }
                public boolean processSynchronousLightweightTransfer(Component heavyweight,
                                                              Component descendant,
                                                              boolean temporary,
                                                              boolean focusedWindowChangeAllowed,
                                                              long time)
                {
                    return KeyboardFocusManager.processSynchronousLightweightTransfer(
                        heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
                }
                public void removeLastFocusRequest(Component heavyweight) {
                    KeyboardFocusManager.removeLastFocusRequest(heavyweight);
                }
            }
        );
    }

    transient KeyboardFocusManagerPeer peer;

    /**
     * Initialize JNI field and method IDs
     */
    private static native void initIDs();

    private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.KeyboardFocusManager");

    /**
     * The identifier for the Forward focus traversal keys.
     *
     * @see #setDefaultFocusTraversalKeys
     * @see #getDefaultFocusTraversalKeys
     * @see Component#setFocusTraversalKeys
     * @see Component#getFocusTraversalKeys
     */
    public static final int FORWARD_TRAVERSAL_KEYS = 0;

    /**
     * The identifier for the Backward focus traversal keys.
     *
     * @see #setDefaultFocusTraversalKeys
     * @see #getDefaultFocusTraversalKeys
     * @see Component#setFocusTraversalKeys
     * @see Component#getFocusTraversalKeys
     */
    public static final int BACKWARD_TRAVERSAL_KEYS = 1;

    /**
     * The identifier for the Up Cycle focus traversal keys.
     *
     * @see #setDefaultFocusTraversalKeys
     * @see #getDefaultFocusTraversalKeys
     * @see Component#setFocusTraversalKeys
     * @see Component#getFocusTraversalKeys
     */
    public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;

    /**
     * The identifier for the Down Cycle focus traversal keys.
     *
     * @see #setDefaultFocusTraversalKeys
     * @see #getDefaultFocusTraversalKeys
     * @see Component#setFocusTraversalKeys
     * @see Component#getFocusTraversalKeys
     */
    public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;

    static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;

    /**
     * Returns the current KeyboardFocusManager instance for the calling
     * thread's context.
     *
     * @return this thread's context's KeyboardFocusManager
     * @see #setCurrentKeyboardFocusManager
     */
    public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
        return getCurrentKeyboardFocusManager(AppContext.getAppContext());
    }

    synchronized static KeyboardFocusManager
        getCurrentKeyboardFocusManager(AppContext appcontext)
    {
        KeyboardFocusManager manager = (KeyboardFocusManager)
            appcontext.get(KeyboardFocusManager.class);
        if (manager == null) {
            manager = new DefaultKeyboardFocusManager();
            appcontext.put(KeyboardFocusManager.class, manager);
        }
        return manager;
    }

    /**
     * Sets the current KeyboardFocusManager instance for the calling thread's
     * context. If null is specified, then the current KeyboardFocusManager
     * is replaced with a new instance of DefaultKeyboardFocusManager.
     * <p>
     * If a SecurityManager is installed, the calling thread must be granted
     * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
     * the current KeyboardFocusManager. If this permission is not granted,
     * this method will throw a SecurityException, and the current
     * KeyboardFocusManager will be unchanged.
     *
     * @param newManager the new KeyboardFocusManager for this thread's context
     * @see #getCurrentKeyboardFocusManager
     * @see DefaultKeyboardFocusManager
     * @throws SecurityException if the calling thread does not have permission
     *         to replace the current KeyboardFocusManager
     */
    public static void setCurrentKeyboardFocusManager(
        KeyboardFocusManager newManager) throws SecurityException
    {
        SecurityManager security = System.getSecurityManager();
        if (security != null) {
            if (replaceKeyboardFocusManagerPermission == null) {
                replaceKeyboardFocusManagerPermission =
                    new AWTPermission("replaceKeyboardFocusManager");
            }
            security.
                checkPermission(replaceKeyboardFocusManagerPermission);
        }

        KeyboardFocusManager oldManager = null;

        synchronized (KeyboardFocusManager.class) {
            AppContext appcontext = AppContext.getAppContext();

            if (newManager != null) {
                oldManager = getCurrentKeyboardFocusManager(appcontext);

                appcontext.put(KeyboardFocusManager.class, newManager);
            } else {
                oldManager = getCurrentKeyboardFocusManager(appcontext);
                appcontext.remove(KeyboardFocusManager.class);
            }
        }

        if (oldManager != null) {
            oldManager.firePropertyChange("managingFocus",
                                          Boolean.TRUE,
                                          Boolean.FALSE);
        }
        if (newManager != null) {
            newManager.firePropertyChange("managingFocus",
                                          Boolean.FALSE,
                                          Boolean.TRUE);
        }
    }

    /**
     * The Component in an application that will typically receive all
     * KeyEvents generated by the user.
     */
    private static Component focusOwner;

    /**
     * The Component in an application that will regain focus when an
     * outstanding temporary focus transfer has completed, or the focus owner,
     * if no outstanding temporary transfer exists.
     */
    private static Component permanentFocusOwner;

    /**
     * The Window which is, or contains, the focus owner.
     */
    private static Window focusedWindow;

    /**
     * Only a Frame or a Dialog can be the active Window. The native windowing
     * system may denote the active Window with a special decoration, such as a
     * highlighted title bar. The active Window is always either the focused
     * Window, or the first Frame or Dialog which is an owner of the focused
     * Window.
     */
    private static Window activeWindow;

    /**
     * The default FocusTraversalPolicy for all Windows that have no policy of
     * their own set. If those Windows have focus-cycle-root children that have
     * no keyboard-traversal policy of their own, then those children will also
     * inherit this policy (as will, recursively, their focus-cycle-root
     * children).
     */
    private FocusTraversalPolicy defaultPolicy =
        new DefaultFocusTraversalPolicy();

    /**
     * The bound property names of each focus traversal key.
     */
    private static final String[] defaultFocusTraversalKeyPropertyNames = {
        "forwardDefaultFocusTraversalKeys",
        "backwardDefaultFocusTraversalKeys",
        "upCycleDefaultFocusTraversalKeys",
        "downCycleDefaultFocusTraversalKeys"
    };

    /**
     * The default strokes for initializing the default focus traversal keys.
     */
    private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
        {
            AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false),
            AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false),
        },
        {
            AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false),
            AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
                                         InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK,
                                         false),
        },
        {},
        {},
      };
    /**
     * The default focus traversal keys. Each array of traversal keys will be
     * in effect on all Windows that have no such array of their own explicitly
     * set. Each array will also be inherited, recursively, by any child
     * Component of those Windows that has no such array of its own explicitly
     * set.
     */
    private Set[] defaultFocusTraversalKeys = new Set[4];

    /**
     * The current focus cycle root. If the focus owner is itself a focus cycle
     * root, then it may be ambiguous as to which Components represent the next
     * and previous Components to focus during normal focus traversal. In that
     * case, the current focus cycle root is used to differentiate among the
     * possibilities.
     */
    private static Container currentFocusCycleRoot;

    /**
     * A description of any VetoableChangeListeners which have been registered.
     */
    private VetoableChangeSupport vetoableSupport;

    /**
     * A description of any PropertyChangeListeners which have been registered.
     */
    private PropertyChangeSupport changeSupport;

    /**
     * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
     * include this KeyboardFocusManager unless it was explicitly re-registered
     * via a call to <code>addKeyEventDispatcher</code>. If no other
     * KeyEventDispatchers are registered, this field may be null or refer to
     * a List of length 0.
     */
    private java.util.LinkedList keyEventDispatchers;

    /**
     * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
     * not include this KeyboardFocusManager unless it was explicitly
     * re-registered via a call to <code>addKeyEventPostProcessor</code>.
     * If no other KeyEventPostProcessors are registered, this field may be
     * null or refer to a List of length 0.
     */
    private java.util.LinkedList keyEventPostProcessors;

    /**
     * Maps Windows to those Windows' most recent focus owners.
     */
    private static java.util.Map mostRecentFocusOwners = new WeakHashMap();

    /**
     * Error String for initializing SecurityExceptions.
     */
    private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";

    /**
     * We cache the permission used to verify that the calling thread is
     * permitted to access the global focus state.
     */
    private static AWTPermission replaceKeyboardFocusManagerPermission;

    /*
     * SequencedEvent which is currently dispatched in AppContext.
     */
    transient SequencedEvent currentSequencedEvent = null;

    final void setCurrentSequencedEvent(SequencedEvent current) {
        synchronized (SequencedEvent.class) {
            assert(current == null || currentSequencedEvent == null);
            currentSequencedEvent = current;
        }
    }

    final SequencedEvent getCurrentSequencedEvent() {
        synchronized (SequencedEvent.class) {
            return currentSequencedEvent;
        }
    }

    static Set initFocusTraversalKeysSet(String value, Set targetSet) {
        StringTokenizer tokens = new StringTokenizer(value, ",");
        while (tokens.hasMoreTokens()) {
            targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken()));
        }
        return (targetSet.isEmpty())
            ? Collections.EMPTY_SET
            : Collections.unmodifiableSet(targetSet);
    }

    /**
     * Initializes a KeyboardFocusManager.
     */
    public KeyboardFocusManager() {
        for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
            Set work_set = new HashSet();
            for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
                work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
            }
            defaultFocusTraversalKeys[i] = (work_set.isEmpty())
                ? Collections.EMPTY_SET
                : Collections.unmodifiableSet(work_set);
        }
        initPeer();
    }

    private void initPeer() {
        Toolkit tk = Toolkit.getDefaultToolkit();
        KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk;
        peer = peerProvider.createKeyboardFocusManagerPeer(this);
    }

    /**
     * Returns the focus owner, if the focus owner is in the same context as
     * the calling thread. The focus owner is defined as the Component in an
     * application that will typically receive all KeyEvents generated by the
     * user. KeyEvents which map to the focus owner's focus traversal keys will
     * not be delivered if focus traversal keys are enabled for the focus
     * owner. In addition, KeyEventDispatchers may retarget or consume
     * KeyEvents before they reach the focus owner.
     *
     * @return the focus owner, or null if the focus owner is not a member of
     *         the calling thread's context
     * @see #getGlobalFocusOwner
     * @see #setGlobalFocusOwner
     */
    public Component getFocusOwner() {
        synchronized (KeyboardFocusManager.class) {
            if (focusOwner == null) {
                return null;
            }

            return (focusOwner.appContext == AppContext.getAppContext())
                ? focusOwner
                : null;
        }
    }

    /**
     * Returns the focus owner, even if the calling thread is in a different
     * context than the focus owner. The focus owner is defined as the
     * Component in an application that will typically receive all KeyEvents
     * generated by the user. KeyEvents which map to the focus owner's focus
     * traversal keys will not be delivered if focus traversal keys are enabled
     * for the focus owner. In addition, KeyEventDispatchers may retarget or
     * consume KeyEvents before they reach the focus owner.
     * <p>
     * This method will throw a SecurityException if this KeyboardFocusManager
     * is not the current KeyboardFocusManager for the calling thread's
     * context.
     *
     * @return the focus owner
     * @see #getFocusOwner
     * @see #setGlobalFocusOwner
     * @throws SecurityException if this KeyboardFocusManager is not the
     *         current KeyboardFocusManager for the calling thread's context
     */
    protected Component getGlobalFocusOwner() throws SecurityException {
        synchronized (KeyboardFocusManager.class) {
            if (this == getCurrentKeyboardFocusManager()) {
                return focusOwner;
            } else {
                if (focusLog.isLoggable(PlatformLogger.FINER)) {
                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                }
                throw new SecurityException(notPrivileged);
            }
        }
    }

    /**
     * Sets the focus owner. The operation will be cancelled if the Component
     * is not focusable. The focus owner is defined as the Component in an
     * application that will typically receive all KeyEvents generated by the
     * user. KeyEvents which map to the focus owner's focus traversal keys will
     * not be delivered if focus traversal keys are enabled for the focus
     * owner. In addition, KeyEventDispatchers may retarget or consume
     * KeyEvents before they reach the focus owner.
     * <p>
     * This method does not actually set the focus to the specified Component.
     * It merely stores the value to be subsequently returned by
     * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
     * or <code>Component.requestFocusInWindow()</code> to change the focus
     * owner, subject to platform limitations.
     *
     * @param focusOwner the focus owner
     * @see #getFocusOwner
     * @see #getGlobalFocusOwner
     * @see Component#requestFocus()
     * @see Component#requestFocusInWindow()
     * @see Component#isFocusable
     * @beaninfo
     *       bound: true
     */
    protected void setGlobalFocusOwner(Component focusOwner) {
        Component oldFocusOwner = null;
        boolean shouldFire = false;

        if (focusOwner == null || focusOwner.isFocusable()) {
            synchronized (KeyboardFocusManager.class) {
                oldFocusOwner = getFocusOwner();

                try {
                    fireVetoableChange("focusOwner", oldFocusOwner,
                                       focusOwner);
                } catch (PropertyVetoException e) {
                    // rejected
                    return;
                }

                KeyboardFocusManager.focusOwner = focusOwner;

                if (focusOwner != null &&
                    (getCurrentFocusCycleRoot() == null ||
                     !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot())))
                {
                    Container rootAncestor =
                        focusOwner.getFocusCycleRootAncestor();
                    if (rootAncestor == null && (focusOwner instanceof Window))
                    {
                        rootAncestor = (Container)focusOwner;
                    }
                    if (rootAncestor != null) {
                        setGlobalCurrentFocusCycleRoot(rootAncestor);
                    }
                }

                shouldFire = true;
            }
        }

        if (shouldFire) {
            firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
        }
    }

    /**
     * Clears the global focus owner at both the Java and native levels. If
     * there exists a focus owner, that Component will receive a permanent
     * FOCUS_LOST event. After this operation completes, the native windowing
     * system will discard all user-generated KeyEvents until the user selects
     * a new Component to receive focus, or a Component is given focus
     * explicitly via a call to <code>requestFocus()</code>. This operation
     * does not change the focused or active Windows.
     *
     * @see Component#requestFocus()
     * @see java.awt.event.FocusEvent#FOCUS_LOST
     */
    public void clearGlobalFocusOwner() {
        if (!GraphicsEnvironment.isHeadless()) {
            // Toolkit must be fully initialized, otherwise
            // _clearGlobalFocusOwner will crash or throw an exception
            Toolkit.getDefaultToolkit();

            _clearGlobalFocusOwner();
        }
    }
    private void _clearGlobalFocusOwner() {
        Window activeWindow = markClearGlobalFocusOwner();
        peer.clearGlobalFocusOwner(activeWindow);
    }

    Component getNativeFocusOwner() {
        return peer.getCurrentFocusOwner();
    }

    void setNativeFocusOwner(Component comp) {
        if (focusLog.isLoggable(PlatformLogger.FINEST)) {
            focusLog.finest("Calling peer {0} setCurrentFocusOwner for {1}",
                            String.valueOf(peer), String.valueOf(comp));
        }
        peer.setCurrentFocusOwner(comp);
    }

    Window getNativeFocusedWindow() {
        return peer.getCurrentFocusedWindow();
    }

    /**
     * Returns the permanent focus owner, if the permanent focus owner is in
     * the same context as the calling thread. The permanent focus owner is
     * defined as the last Component in an application to receive a permanent
     * FOCUS_GAINED event. The focus owner and permanent focus owner are
     * equivalent unless a temporary focus change is currently in effect. In
     * such a situation, the permanent focus owner will again be the focus
     * owner when the temporary focus change ends.
     *
     * @return the permanent focus owner, or null if the permanent focus owner
     *         is not a member of the calling thread's context
     * @see #getGlobalPermanentFocusOwner
     * @see #setGlobalPermanentFocusOwner
     */
    public Component getPermanentFocusOwner() {
        synchronized (KeyboardFocusManager.class) {
            if (permanentFocusOwner == null) {
                return null;
            }

            return (permanentFocusOwner.appContext ==
                    AppContext.getAppContext())
                ? permanentFocusOwner
                : null;
        }
    }

    /**
     * Returns the permanent focus owner, even if the calling thread is in a
     * different context than the permanent focus owner. The permanent focus
     * owner is defined as the last Component in an application to receive a
     * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
     * are equivalent unless a temporary focus change is currently in effect.
     * In such a situation, the permanent focus owner will again be the focus
     * owner when the temporary focus change ends.
     * <p>
     * This method will throw a SecurityException if this KeyboardFocusManager
     * is not the current KeyboardFocusManager for the calling thread's
     * context.
     *
     * @return the permanent focus owner
     * @see #getPermanentFocusOwner
     * @see #setGlobalPermanentFocusOwner
     * @throws SecurityException if this KeyboardFocusManager is not the
     *         current KeyboardFocusManager for the calling thread's context
     */
    protected Component getGlobalPermanentFocusOwner()
        throws SecurityException
    {
        synchronized (KeyboardFocusManager.class) {
            if (this == getCurrentKeyboardFocusManager()) {
                return permanentFocusOwner;
            } else {
                if (focusLog.isLoggable(PlatformLogger.FINER)) {
                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                }
                throw new SecurityException(notPrivileged);
            }
        }
    }

    /**
     * Sets the permanent focus owner. The operation will be cancelled if the
     * Component is not focusable. The permanent focus owner is defined as the
     * last Component in an application to receive a permanent FOCUS_GAINED
     * event. The focus owner and permanent focus owner are equivalent unless
     * a temporary focus change is currently in effect. In such a situation,
     * the permanent focus owner will again be the focus owner when the
     * temporary focus change ends.
     * <p>
     * This method does not actually set the focus to the specified Component.
     * It merely stores the value to be subsequently returned by
     * <code>getPermanentFocusOwner()</code>. Use
     * <code>Component.requestFocus()</code> or
     * <code>Component.requestFocusInWindow()</code> to change the focus owner,
     * subject to platform limitations.
     *
     * @param permanentFocusOwner the permanent focus owner
     * @see #getPermanentFocusOwner
     * @see #getGlobalPermanentFocusOwner
     * @see Component#requestFocus()
     * @see Component#requestFocusInWindow()
     * @see Component#isFocusable
     * @beaninfo
     *       bound: true
     */
    protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner)
    {
        Component oldPermanentFocusOwner = null;
        boolean shouldFire = false;

        if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
            synchronized (KeyboardFocusManager.class) {
                oldPermanentFocusOwner = getPermanentFocusOwner();

                try {
                    fireVetoableChange("permanentFocusOwner",
                                       oldPermanentFocusOwner,
                                       permanentFocusOwner);
                } catch (PropertyVetoException e) {
                    // rejected
                    return;
                }

                KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;

                KeyboardFocusManager.
                    setMostRecentFocusOwner(permanentFocusOwner);

                shouldFire = true;
            }
        }

        if (shouldFire) {
            firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
                               permanentFocusOwner);
        }
    }

    /**
     * Returns the focused Window, if the focused Window is in the same context
     * as the calling thread. The focused Window is the Window that is or
     * contains the focus owner.
     *
     * @return the focused Window, or null if the focused Window is not a
     *         member of the calling thread's context
     * @see #getGlobalFocusedWindow
     * @see #setGlobalFocusedWindow
     */
    public Window getFocusedWindow() {
        synchronized (KeyboardFocusManager.class) {
            if (focusedWindow == null) {
                return null;
            }

            return (focusedWindow.appContext == AppContext.getAppContext())
                ? focusedWindow
                : null;
        }
    }

    /**
     * Returns the focused Window, even if the calling thread is in a different
     * context than the focused Window. The focused Window is the Window that
     * is or contains the focus owner.
     * <p>
     * This method will throw a SecurityException if this KeyboardFocusManager
     * is not the current KeyboardFocusManager for the calling thread's
     * context.
     *
     * @return the focused Window
     * @see #getFocusedWindow
     * @see #setGlobalFocusedWindow
     * @throws SecurityException if this KeyboardFocusManager is not the
     *         current KeyboardFocusManager for the calling thread's context
     */
    protected Window getGlobalFocusedWindow() throws SecurityException {
        synchronized (KeyboardFocusManager.class) {
            if (this == getCurrentKeyboardFocusManager()) {
               return focusedWindow;
            } else {
                if (focusLog.isLoggable(PlatformLogger.FINER)) {
                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                }
                throw new SecurityException(notPrivileged);
            }
        }
    }

    /**
     * Sets the focused Window. The focused Window is the Window that is or
     * contains the focus owner. The operation will be cancelled if the
     * specified Window to focus is not a focusable Window.
     * <p>
     * This method does not actually change the focused Window as far as the
     * native windowing system is concerned. It merely stores the value to be
     * subsequently returned by <code>getFocusedWindow()</code>. Use
     * <code>Component.requestFocus()</code> or
     * <code>Component.requestFocusInWindow()</code> to change the focused
     * Window, subject to platform limitations.
     *
     * @param focusedWindow the focused Window
     * @see #getFocusedWindow
     * @see #getGlobalFocusedWindow
     * @see Component#requestFocus()
     * @see Component#requestFocusInWindow()
     * @see Window#isFocusableWindow
     * @beaninfo
     *       bound: true
     */
    protected void setGlobalFocusedWindow(Window focusedWindow) {
        Window oldFocusedWindow = null;
        boolean shouldFire = false;

        if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
            synchronized (KeyboardFocusManager.class) {
                oldFocusedWindow = getFocusedWindow();

                try {
                    fireVetoableChange("focusedWindow", oldFocusedWindow,
                                       focusedWindow);
                } catch (PropertyVetoException e) {
                    // rejected
                    return;
                }

                KeyboardFocusManager.focusedWindow = focusedWindow;
                shouldFire = true;
            }
        }

        if (shouldFire) {
            firePropertyChange("focusedWindow", oldFocusedWindow,
                               focusedWindow);
        }
    }

    /**
     * Returns the active Window, if the active Window is in the same context
     * as the calling thread. Only a Frame or a Dialog can be the active
     * Window. The native windowing system may denote the active Window or its
     * children with special decorations, such as a highlighted title bar.
     * The active Window is always either the focused Window, or the first
     * Frame or Dialog that is an owner of the focused Window.
     *
     * @return the active Window, or null if the active Window is not a member
     *         of the calling thread's context
     * @see #getGlobalActiveWindow
     * @see #setGlobalActiveWindow
     */
    public Window getActiveWindow() {
        synchronized (KeyboardFocusManager.class) {
            if (activeWindow == null) {
                return null;
            }

            return (activeWindow.appContext == AppContext.getAppContext())
                ? activeWindow
                : null;
        }
    }

    /**
     * Returns the active Window, even if the calling thread is in a different
     * context than the active Window. Only a Frame or a Dialog can be the
     * active Window. The native windowing system may denote the active Window
     * or its children with special decorations, such as a highlighted title
     * bar. The active Window is always either the focused Window, or the first
     * Frame or Dialog that is an owner of the focused Window.
     * <p>
     * This method will throw a SecurityException if this KeyboardFocusManager
     * is not the current KeyboardFocusManager for the calling thread's
     * context.
     *
     * @return the active Window
     * @see #getActiveWindow
     * @see #setGlobalActiveWindow
     * @throws SecurityException if this KeyboardFocusManager is not the
     *         current KeyboardFocusManager for the calling thread's context
     */
    protected Window getGlobalActiveWindow() throws SecurityException {
        synchronized (KeyboardFocusManager.class) {
            if (this == getCurrentKeyboardFocusManager()) {
               return activeWindow;
            } else {
                if (focusLog.isLoggable(PlatformLogger.FINER)) {
                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                }
                throw new SecurityException(notPrivileged);
            }
        }
    }

    /**
     * Sets the active Window. Only a Frame or a Dialog can be the active
     * Window. The native windowing system may denote the active Window or its
     * children with special decorations, such as a highlighted title bar. The
     * active Window is always either the focused Window, or the first Frame or
     * Dialog that is an owner of the focused Window.
     * <p>
     * This method does not actually change the active Window as far as the
     * native windowing system is concerned. It merely stores the value to be
     * subsequently returned by <code>getActiveWindow()</code>. Use
     * <code>Component.requestFocus()</code> or
     * <code>Component.requestFocusInWindow()</code>to change the active
     * Window, subject to platform limitations.
     *
     * @param activeWindow the active Window
     * @see #getActiveWindow
     * @see #getGlobalActiveWindow
     * @see Component#requestFocus()
     * @see Component#requestFocusInWindow()
     * @beaninfo
     *       bound: true
     */
    protected void setGlobalActiveWindow(Window activeWindow) {
        Window oldActiveWindow;
        synchronized (KeyboardFocusManager.class) {
            oldActiveWindow = getActiveWindow();
            if (focusLog.isLoggable(PlatformLogger.FINER)) {
                focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
            }

            try {
                fireVetoableChange("activeWindow", oldActiveWindow,
                                   activeWindow);
            } catch (PropertyVetoException e) {
                // rejected
                return;
            }

            KeyboardFocusManager.activeWindow = activeWindow;
        }

        firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
    }

    /**
     * Returns the default FocusTraversalPolicy. Top-level components
     * use this value on their creation to initialize their own focus traversal
     * policy by explicit call to Container.setFocusTraversalPolicy.
     *
     * @return the default FocusTraversalPolicy. null will never be returned.
     * @see #setDefaultFocusTraversalPolicy
     * @see Container#setFocusTraversalPolicy
     * @see Container#getFocusTraversalPolicy
     */
    public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
        return defaultPolicy;
    }

    /**
     * Sets the default FocusTraversalPolicy. Top-level components
     * use this value on their creation to initialize their own focus traversal
     * policy by explicit call to Container.setFocusTraversalPolicy.
     * Note: this call doesn't affect already created components as they have
     * their policy initialized. Only new components will use this policy as
     * their default policy.
     *
     * @param defaultPolicy the new, default FocusTraversalPolicy
     * @see #getDefaultFocusTraversalPolicy
     * @see Container#setFocusTraversalPolicy
     * @see Container#getFocusTraversalPolicy
     * @throws IllegalArgumentException if defaultPolicy is null
     * @beaninfo
     *       bound: true
     */
    public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy
                                               defaultPolicy) {
        if (defaultPolicy == null) {
            throw new IllegalArgumentException("default focus traversal policy cannot be null");
        }

        FocusTraversalPolicy oldPolicy;

        synchronized (this) {
            oldPolicy = this.defaultPolicy;
            this.defaultPolicy = defaultPolicy;
        }

        firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
                           defaultPolicy);
    }

    /**
     * Sets the default focus traversal keys for a given traversal operation.
     * This traversal key <code>Set</code> will be in effect on all
     * <code>Window</code>s that have no such <code>Set</code> of
     * their own explicitly defined. This <code>Set</code> will also be
     * inherited, recursively, by any child <code>Component</code> of
     * those <code>Windows</code> that has
     * no such <code>Set</code> of its own explicitly defined.
     * <p>
     * The default values for the default focus traversal keys are
     * implementation-dependent. Sun recommends that all implementations for a
     * particular native platform use the same default values. The
     * recommendations for Windows and Unix are listed below. These
     * recommendations are used in the Sun AWT implementations.
     *
     * <table border=1 summary="Recommended default values for focus traversal keys">
     * <tr>
     *    <th>Identifier</th>
     *    <th>Meaning</th>
     *    <th>Default</th>
     * </tr>
     * <tr>
     *    <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
     *    <td>Normal forward keyboard traversal</td>
     *    <td><code>TAB</code> on <code>KEY_PRESSED</code>,
     *        <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
     * </tr>
     * <tr>
     *    <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
     *    <td>Normal reverse keyboard traversal</td>
     *    <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
     *        <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
     * </tr>
     * <tr>
     *    <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
     *    <td>Go up one focus traversal cycle</td>
     *    <td>none</td>
     * </tr>
     * <tr>
     *    <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
     *    <td>Go down one focus traversal cycle</td>
     *    <td>none</td>
     * </tr>
     * </table>
     *
     * To disable a traversal key, use an empty <code>Set</code>;
     * <code>Collections.EMPTY_SET</code> is recommended.
     * <p>
     * Using the <code>AWTKeyStroke</code> API, client code can
     * specify on which of two
     * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
     * <code>KEY_RELEASED</code>, the focus traversal operation will
     * occur. Regardless of which <code>KeyEvent</code> is specified,
     * however, all <code>KeyEvent</code>s related to the focus
     * traversal key, including the associated <code>KEY_TYPED</code>
     * event, will be consumed, and will not be dispatched
     * to any <code>Component</code>. It is a runtime error to
     * specify a <code>KEY_TYPED</code> event as
     * mapping to a focus traversal operation, or to map the same event to
     * multiple default focus traversal operations.
     *
     * @param id one of
     *        <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
     *        <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
     *        <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
     *        <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
     * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
     *        specified operation
     * @see #getDefaultFocusTraversalKeys
     * @see Component#setFocusTraversalKeys
     * @see Component#getFocusTraversalKeys
     * @throws IllegalArgumentException if id is not one of
     *         <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
     *         <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
     *         <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
     *         <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
     *         or if keystrokes is <code>null</code>,
     *         or if keystrokes contains <code>null</code>,
     *         or if any <code>Object</code> in
     *         keystrokes is not an <code>AWTKeyStroke</code>,
     *         or if any keystroke
     *         represents a <code>KEY_TYPED</code> event,
     *         or if any keystroke already maps
     *         to another default focus traversal operation
     * @beaninfo
     *       bound: true
     */
    public void
        setDefaultFocusTraversalKeys(int id,
                                     Set<? extends AWTKeyStroke> keystrokes)
    {
        if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
            throw new IllegalArgumentException("invalid focus traversal key identifier");
        }
        if (keystrokes == null) {
            throw new IllegalArgumentException("cannot set null Set of default focus traversal keys");
        }

        Set oldKeys;

        synchronized (this) {
            for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) {
                Object obj = iter.next();

                if (obj == null) {
                    throw new IllegalArgumentException("cannot set null focus traversal key");
                }

                // Fix for 6195831:
                //According to javadoc this method should throw IAE instead of ClassCastException
                if (!(obj instanceof AWTKeyStroke)) {
                    throw new IllegalArgumentException("object is expected to be AWTKeyStroke");
                }
                AWTKeyStroke keystroke = (AWTKeyStroke)obj;

                if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
                    throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
                }

                // Check to see if key already maps to another traversal
                // operation
                for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
                    if (i == id) {
                        continue;
                    }

                    if (defaultFocusTraversalKeys[i].contains(keystroke)) {
                        throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
                    }
                }
            }

            oldKeys = defaultFocusTraversalKeys[id];
            defaultFocusTraversalKeys[id] =
                Collections.unmodifiableSet(new HashSet(keystrokes));
        }

        firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
                           oldKeys, keystrokes);
    }

    /**
     * Returns a Set of default focus traversal keys for a given traversal
     * operation. This traversal key Set will be in effect on all Windows that
     * have no such Set of their own explicitly defined. This Set will also be
     * inherited, recursively, by any child Component of those Windows that has
     * no such Set of its own explicitly defined. (See
     * <code>setDefaultFocusTraversalKeys</code> for a full description of each
     * operation.)
     *
     * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
     *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
     *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
     *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
     * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
     *         for the specified operation; the <code>Set</code>
     *         will be unmodifiable, and may be empty; <code>null</code>
     *         will never be returned
     * @see #setDefaultFocusTraversalKeys
     * @see Component#setFocusTraversalKeys
     * @see Component#getFocusTraversalKeys
     * @throws IllegalArgumentException if id is not one of
     *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
     *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
     *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
     *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
     */
    public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
        if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
            throw new IllegalArgumentException("invalid focus traversal key identifier");
        }

        // Okay to return Set directly because it is an unmodifiable view
        return defaultFocusTraversalKeys[id];
    }

    /**
     * Returns the current focus cycle root, if the current focus cycle root is
     * in the same context as the calling thread. If the focus owner is itself
     * a focus cycle root, then it may be ambiguous as to which Components
     * represent the next and previous Components to focus during normal focus
     * traversal. In that case, the current focus cycle root is used to
     * differentiate among the possibilities.
     * <p>
     * This method is intended to be used only by KeyboardFocusManagers and
     * focus implementations. It is not for general client use.
     *
     * @return the current focus cycle root, or null if the current focus cycle
     *         root is not a member of the calling thread's context
     * @see #getGlobalCurrentFocusCycleRoot
     * @see #setGlobalCurrentFocusCycleRoot
     */
    public Container getCurrentFocusCycleRoot() {
        synchronized (KeyboardFocusManager.class) {
            if (currentFocusCycleRoot == null) {
                return null;
            }

            return (currentFocusCycleRoot.appContext ==
                    AppContext.getAppContext())
                ? currentFocusCycleRoot
                : null;
        }
    }

    /**
     * Returns the current focus cycle root, even if the calling thread is in a
     * different context than the current focus cycle root. If the focus owner
     * is itself a focus cycle root, then it may be ambiguous as to which
     * Components represent the next and previous Components to focus during
     * normal focus traversal. In that case, the current focus cycle root is
     * used to differentiate among the possibilities.
     * <p>
     * This method will throw a SecurityException if this KeyboardFocusManager
     * is not the current KeyboardFocusManager for the calling thread's
     * context.
     *
     * @return the current focus cycle root, or null if the current focus cycle
     *         root is not a member of the calling thread's context
     * @see #getCurrentFocusCycleRoot
     * @see #setGlobalCurrentFocusCycleRoot
     * @throws SecurityException if this KeyboardFocusManager is not the
     *         current KeyboardFocusManager for the calling thread's context
     */
    protected Container getGlobalCurrentFocusCycleRoot()
        throws SecurityException
    {
        synchronized (KeyboardFocusManager.class) {
            if (this == getCurrentKeyboardFocusManager()) {
                return currentFocusCycleRoot;
            } else {
                if (focusLog.isLoggable(PlatformLogger.FINER)) {
                    focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
                }
                throw new SecurityException(notPrivileged);
            }
        }
    }

    /**
     * Sets the current focus cycle root. If the focus owner is itself a focus
     * cycle root, then it may be ambiguous as to which Components represent
     * the next and previous Components to focus during normal focus traversal.
     * In that case, the current focus cycle root is used to differentiate
     * among the possibilities.
     * <p>
     * This method is intended to be used only by KeyboardFocusManagers and
     * focus implementations. It is not for general client use.
     *
     * @param newFocusCycleRoot the new focus cycle root
     * @see #getCurrentFocusCycleRoot
     * @see #getGlobalCurrentFocusCycleRoot
     * @beaninfo
     *       bound: true
     */
    public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
        Container oldFocusCycleRoot;

        synchronized (KeyboardFocusManager.class) {
            oldFocusCycleRoot  = getCurrentFocusCycleRoot();
            currentFocusCycleRoot = newFocusCycleRoot;
        }

        firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
                           newFocusCycleRoot);
    }

    /**
     * Adds a PropertyChangeListener to the listener list. The listener is
     * registered for all bound properties of this class, including the
     * following:
     * <ul>
     *    <li>whether the KeyboardFocusManager is currently managing focus
     *        for this application or applet's browser context
     *        ("managingFocus")</li>
     *    <li>the focus owner ("focusOwner")</li>
     *    <li>the permanent focus owner ("permanentFocusOwner")</li>
     *    <li>the focused Window ("focusedWindow")</li>
     *    <li>the active Window ("activeWindow")</li>
     *    <li>the default focus traversal policy
     *        ("defaultFocusTraversalPolicy")</li>
     *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
     *        ("forwardDefaultFocusTraversalKeys")</li>
     *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
     *        ("backwardDefaultFocusTraversalKeys")</li>
     *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
     *        ("upCycleDefaultFocusTraversalKeys")</li>
     *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
     *        ("downCycleDefaultFocusTraversalKeys")</li>
     *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
     * </ul>
     * If listener is null, no exception is thrown and no action is performed.
     *
     * @param listener the PropertyChangeListener to be added
     * @see #removePropertyChangeListener
     * @see #getPropertyChangeListeners
     * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
     */
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        if (listener != null) {
            synchronized (this) {
                if (changeSupport == null) {
                    changeSupport = new PropertyChangeSupport(this);
                }
                changeSupport.addPropertyChangeListener(listener);
            }
        }
    }

    /**
     * Removes a PropertyChangeListener from the listener list. This method
     * should be used to remove the PropertyChangeListeners that were
     * registered for all bound properties of this class.
     * <p>
     * If listener is null, no exception is thrown and no action is performed.
     *
     * @param listener the PropertyChangeListener to be removed
     * @see #addPropertyChangeListener
     * @see #getPropertyChangeListeners
     * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
     */
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        if (listener != null) {
            synchronized (this) {
                if (changeSupport != null) {
                    changeSupport.removePropertyChangeListener(listener);
                }
            }
        }
    }

    /**
     * Returns an array of all the property change listeners
     * registered on this keyboard focus manager.
     *
     * @return all of this keyboard focus manager's
     *         <code>PropertyChangeListener</code>s
     *         or an empty array if no property change
     *         listeners are currently registered
     *
     * @see #addPropertyChangeListener
     * @see #removePropertyChangeListener
     * @see #getPropertyChangeListeners(java.lang.String)
     * @since 1.4
     */
    public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
        if (changeSupport == null) {
            changeSupport = new PropertyChangeSupport(this);
        }
        return changeSupport.getPropertyChangeListeners();
    }

    /**
     * Adds a PropertyChangeListener to the listener list for a specific
     * property. The specified property may be user-defined, or one of the
     * following:
     * <ul>
     *    <li>whether the KeyboardFocusManager is currently managing focus
     *        for this application or applet's browser context
     *        ("managingFocus")</li>
     *    <li>the focus owner ("focusOwner")</li>
     *    <li>the permanent focus owner ("permanentFocusOwner")</li>
     *    <li>the focused Window ("focusedWindow")</li>
     *    <li>the active Window ("activeWindow")</li>
     *    <li>the default focus traversal policy
     *        ("defaultFocusTraversalPolicy")</li>
     *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
     *        ("forwardDefaultFocusTraversalKeys")</li>
     *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
     *        ("backwardDefaultFocusTraversalKeys")</li>
     *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
     *        ("upCycleDefaultFocusTraversalKeys")</li>
     *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
     *        ("downCycleDefaultFocusTraversalKeys")</li>
     *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
     * </ul>
     * If listener is null, no exception is thrown and no action is performed.
     *
     * @param propertyName one of the property names listed above
     * @param listener the PropertyChangeListener to be added
     * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
     * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
     * @see #getPropertyChangeListeners(java.lang.String)
     */
    public void addPropertyChangeListener(String propertyName,
                                          PropertyChangeListener listener) {
        if (listener != null) {
            synchronized (this) {
                if (changeSupport == null) {
                    changeSupport = new PropertyChangeSupport(this);
                }
                changeSupport.addPropertyChangeListener(propertyName,
                                                        listener);
            }
        }
    }

    /**
     * Removes a PropertyChangeListener from the listener list for a specific
     * property. This method should be used to remove PropertyChangeListeners
     * that were registered for a specific bound property.
     * <p>
     * If listener is null, no exception is thrown and no action is performed.
     *
     * @param propertyName a valid property name
     * @param listener the PropertyChangeListener to be removed
     * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
     * @see #getPropertyChangeListeners(java.lang.String)
     * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
     */
    public void removePropertyChangeListener(String propertyName,
                                             PropertyChangeListener listener) {
        if (listener != null) {
            synchronized (this) {
                if (changeSupport != null) {
                    changeSupport.removePropertyChangeListener(propertyName,
                                                               listener);
                }
            }
        }
    }

    /**
     * Returns an array of all the <code>PropertyChangeListener</code>s
     * associated with the named property.
     *
     * @return all of the <code>PropertyChangeListener</code>s associated with
     *         the named property or an empty array if no such listeners have
     *         been added.
     *
     * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
     * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
     * @since 1.4
     */
    public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
        if (changeSupport == null) {
            changeSupport = new PropertyChangeSupport(this);
        }
        return changeSupport.getPropertyChangeListeners(propertyName);
    }

    /**
     * Fires a PropertyChangeEvent in response to a change in a bound property.
     * The event will be delivered to all registered PropertyChangeListeners.
     * No event will be delivered if oldValue and newValue are the same.
     *
     * @param propertyName the name of the property that has changed
     * @param oldValue the property's previous value
     * @param newValue the property's new value
     */
    protected void firePropertyChange(String propertyName, Object oldValue,
                                      Object newValue)
    {
        if (oldValue == newValue) {
            return;
        }
        PropertyChangeSupport changeSupport = this.changeSupport;
        if (changeSupport != null) {
            changeSupport.firePropertyChange(propertyName, oldValue, newValue);
        }
    }

    /**
     * Adds a VetoableChangeListener to the listener list. The listener is
     * registered for all vetoable properties of this class, including the
     * following:
     * <ul>
     *    <li>the focus owner ("focusOwner")</li>
     *    <li>the permanent focus owner ("permanentFocusOwner")</li>
     *    <li>the focused Window ("focusedWindow")</li>
     *    <li>the active Window ("activeWindow")</li>
     * </ul>
     * If listener is null, no exception is thrown and no action is performed.
     *
     * @param listener the VetoableChangeListener to be added
     * @see #removeVetoableChangeListener
     * @see #getVetoableChangeListeners
     * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
     */
    public void addVetoableChangeListener(VetoableChangeListener listener) {
        if (listener != null) {
            synchronized (this) {
                if (vetoableSupport == null) {
                    vetoableSupport =
                        new VetoableChangeSupport(this);
                }
                vetoableSupport.addVetoableChangeListener(listener);
            }
        }
    }

    /**
     * Removes a VetoableChangeListener from the listener list. This method
     * should be used to remove the VetoableChangeListeners that were
     * registered for all vetoable properties of this class.
     * <p>
     * If listener is null, no exception is thrown and no action is performed.
     *
     * @param listener the VetoableChangeListener to be removed
     * @see #addVetoableChangeListener
     * @see #getVetoableChangeListeners
     * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
     */
    public void removeVetoableChangeListener(VetoableChangeListener listener) {
        if (listener != null) {
            synchronized (this) {
                if (vetoableSupport != null) {
                    vetoableSupport.removeVetoableChangeListener(listener);
                }
            }
        }
    }

    /**
     * Returns an array of all the vetoable change listeners
     * registered on this keyboard focus manager.
     *
     * @return all of this keyboard focus manager's
     *         <code>VetoableChangeListener</code>s
     *         or an empty array if no vetoable change
     *         listeners are currently registered
     *
     * @see #addVetoableChangeListener
     * @see #removeVetoableChangeListener
     * @see #getVetoableChangeListeners(java.lang.String)
     * @since 1.4
     */
    public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
        if (vetoableSupport == null) {
            vetoableSupport = new VetoableChangeSupport(this);
        }
        return vetoableSupport.getVetoableChangeListeners();
    }

    /**
     * Adds a VetoableChangeListener to the listener list for a specific
     * property. The specified property may be user-defined, or one of the
     * following:
     * <ul>
     *    <li>the focus owner ("focusOwner")</li>
     *    <li>the permanent focus owner ("permanentFocusOwner")</li>
     *    <li>the focused Window ("focusedWindow")</li>
     *    <li>the active Window ("activeWindow")</li>
     * </ul>
     * If listener is null, no exception is thrown and no action is performed.
     *
     * @param propertyName one of the property names listed above
     * @param listener the VetoableChangeListener to be added
     * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
     * @see #removeVetoableChangeListener
     * @see #getVetoableChangeListeners
     */
    public void addVetoableChangeListener(String propertyName,
                                          VetoableChangeListener listener) {
        if (listener != null) {
            synchronized (this) {
                if (vetoableSupport == null) {
                    vetoableSupport =
                        new VetoableChangeSupport(this);
                }
                vetoableSupport.addVetoableChangeListener(propertyName,
                                                          listener);
            }
        }
    }

    /**
     * Removes a VetoableChangeListener from the listener list for a specific
     * property. This method should be used to remove VetoableChangeListeners
     * that were registered for a specific bound property.
     * <p>
     * If listener is null, no exception is thrown and no action is performed.
     *
     * @param propertyName a valid property name
     * @param listener the VetoableChangeListener to be removed
     * @see #addVetoableChangeListener
     * @see #getVetoableChangeListeners
     * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
     */
    public void removeVetoableChangeListener(String propertyName,
                                             VetoableChangeListener listener) {
        if (listener != null) {
            synchronized (this) {
                if (vetoableSupport != null) {
                    vetoableSupport.removeVetoableChangeListener(propertyName,
                                                                 listener);
                }
            }
        }
    }

    /**
     * Returns an array of all the <code>VetoableChangeListener</code>s
     * associated with the named property.
     *
     * @return all of the <code>VetoableChangeListener</code>s associated with
     *         the named property or an empty array if no such listeners have
     *         been added.
     *
     * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
     * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
     * @see #getVetoableChangeListeners
     * @since 1.4
     */
    public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
        if (vetoableSupport == null) {
            vetoableSupport = new VetoableChangeSupport(this);
        }
        return vetoableSupport.getVetoableChangeListeners(propertyName);
    }

    /**
     * Fires a PropertyChangeEvent in response to a change in a vetoable
     * property. The event will be delivered to all registered
     * VetoableChangeListeners. If a VetoableChangeListener throws a
     * PropertyVetoException, a new event is fired reverting all
     * VetoableChangeListeners to the old value and the exception is then
     * rethrown. No event will be delivered if oldValue and newValue are the
     * same.
     *
     * @param propertyName the name of the property that has changed
     * @param oldValue the property's previous value
     * @param newValue the property's new value
     * @throws java.beans.PropertyVetoException if a
     *         <code>VetoableChangeListener</code> threw
     *         <code>PropertyVetoException</code>
     */
    protected void fireVetoableChange(String propertyName, Object oldValue,
                                      Object newValue)
        throws PropertyVetoException
    {
        if (oldValue == newValue) {
            return;
        }
        VetoableChangeSupport vetoableSupport =
            this.vetoableSupport;
        if (vetoableSupport != null) {
            vetoableSupport.fireVetoableChange(propertyName, oldValue,
                                               newValue);
        }
    }

    /**
     * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
     * chain. This KeyboardFocusManager will request that each
     * KeyEventDispatcher dispatch KeyEvents generated by the user before
     * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
     * notified in the order in which they were added. Notifications will halt
     * as soon as one KeyEventDispatcher returns <code>true</code> from its
     * <code>dispatchKeyEvent</code> method. There is no limit to the total
     * number of KeyEventDispatchers which can be added, nor to the number of
     * times which a particular KeyEventDispatcher instance can be added.
     * <p>
     * If a null dispatcher is specified, no action is taken and no exception
     * is thrown.
     * <p>
     * In a multithreaded application, {@link KeyEventDispatcher} behaves
     * the same as other AWT listeners.  See
     * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
     * >AWT Threading Issues</a> for more details.
     *
     * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
     * @see #removeKeyEventDispatcher
     */
    public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
        if (dispatcher != null) {
            synchronized (this) {
                if (keyEventDispatchers == null) {
                    keyEventDispatchers = new java.util.LinkedList();
                }
                keyEventDispatchers.add(dispatcher);
            }
        }
    }

    /**
     * Removes a KeyEventDispatcher which was previously added to this
     * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
     * cannot itself be removed, unless it was explicitly re-registered via a
     * call to <code>addKeyEventDispatcher</code>.
     * <p>
     * If a null dispatcher is specified, if the specified dispatcher is not
     * in the dispatcher chain, or if this KeyboardFocusManager is specified
     * without having been explicitly re-registered, no action is taken and no
     * exception is thrown.
     * <p>
     * In a multithreaded application, {@link KeyEventDispatcher} behaves
     * the same as other AWT listeners.  See
     * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
     * >AWT Threading Issues</a> for more details.
     *
     * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
     *        chain
     * @see #addKeyEventDispatcher
     */
    public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
        if (dispatcher != null) {
            synchronized (this) {
                if (keyEventDispatchers != null) {
                    keyEventDispatchers.remove(dispatcher);
                }
            }
        }
    }

    /**
     * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
     * The List will not include this KeyboardFocusManager unless it was
     * explicitly re-registered via a call to
     * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
     * registered, implementations are free to return null or a List of length
     * 0. Client code should not assume one behavior over another, nor should
     * it assume that the behavior, once established, will not change.
     *
     * @return a possibly null or empty List of KeyEventDispatchers
     * @see #addKeyEventDispatcher
     * @see #removeKeyEventDispatcher
     */
    protected synchronized java.util.List<KeyEventDispatcher>
        getKeyEventDispatchers()
    {
        return (keyEventDispatchers != null)
            ? (java.util.List)keyEventDispatchers.clone()
            : null;
    }

    /**
     * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
     * processor chain. After a KeyEvent has been dispatched to and handled by
     * its target, KeyboardFocusManager will request that each
     * KeyEventPostProcessor perform any necessary post-processing as part
     * of the KeyEvent's final resolution. KeyEventPostProcessors
     * will be notified in the order in which they were added; the current
     * KeyboardFocusManager will be notified last. Notifications will halt
     * as soon as one KeyEventPostProcessor returns <code>true</code> from its
     * <code>postProcessKeyEvent</code> method. There is no limit to the the
     * total number of KeyEventPostProcessors that can be added, nor to the
     * number of times that a particular KeyEventPostProcessor instance can be
     * added.
     * <p>
     * If a null post-processor is specified, no action is taken and no
     * exception is thrown.
     * <p>
     * In a multithreaded application, {@link KeyEventPostProcessor} behaves
     * the same as other AWT listeners.  See
     * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
     * >AWT Threading Issues</a> for more details.
     *
     * @param processor the KeyEventPostProcessor to add to the post-processor
     *        chain
     * @see #removeKeyEventPostProcessor
     */
    public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
        if (processor != null) {
            synchronized (this) {
                if (keyEventPostProcessors == null) {
                    keyEventPostProcessors = new java.util.LinkedList();
                }
                keyEventPostProcessors.add(processor);
            }
        }
    }


    /**
     * Removes a previously added KeyEventPostProcessor from this
     * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
     * cannot itself be entirely removed from the chain. Only additional
     * references added via <code>addKeyEventPostProcessor</code> can be
     * removed.
     * <p>
     * If a null post-processor is specified, if the specified post-processor
     * is not in the post-processor chain, or if this KeyboardFocusManager is
     * specified without having been explicitly added, no action is taken and
     * no exception is thrown.
     * <p>
     * In a multithreaded application, {@link KeyEventPostProcessor} behaves
     * the same as other AWT listeners.  See
     * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
     * >AWT Threading Issues</a> for more details.
     *
     * @param processor the KeyEventPostProcessor to remove from the post-
     *        processor chain
     * @see #addKeyEventPostProcessor
     */
    public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
        if (processor != null) {
            synchronized (this) {
                if (keyEventPostProcessors != null) {
                    keyEventPostProcessors.remove(processor);
                }
            }
        }
    }


    /**
     * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
     * List. The List will not include this KeyboardFocusManager unless it was
     * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
     * no KeyEventPostProcessors are registered, implementations are free to
     * return null or a List of length 0. Client code should not assume one
     * behavior over another, nor should it assume that the behavior, once
     * established, will not change.
     *
     * @return a possibly null or empty List of KeyEventPostProcessors
     * @see #addKeyEventPostProcessor
     * @see #removeKeyEventPostProcessor
     */
    protected java.util.List<KeyEventPostProcessor>
        getKeyEventPostProcessors()
    {
        return (keyEventPostProcessors != null)
            ? (java.util.List)keyEventPostProcessors.clone()
            : null;
    }



    static void setMostRecentFocusOwner(Component component) {
        Component window = component;
        while (window != null && !(window instanceof Window)) {
            window = window.parent;
        }
        if (window != null) {
            setMostRecentFocusOwner((Window)window, component);
        }
    }
    static synchronized void setMostRecentFocusOwner(Window window,
                                                     Component component) {
        // ATTN: component has a strong reference to window via chain
        // of Component.parent fields.  Since WeakHasMap refers to its
        // values strongly, we need to break the strong link from the
        // value (component) back to its key (window).
        WeakReference weakValue = null;
        if (component != null) {
            weakValue = new WeakReference(component);
        }
        mostRecentFocusOwners.put(window, weakValue);
    }
    static void clearMostRecentFocusOwner(Component comp) {
        Container window;

        if (comp == null) {
            return;
        }

        synchronized (comp.getTreeLock()) {
            window = comp.getParent();
            while (window != null && !(window instanceof Window)) {
                window = window.getParent();
            }
        }

        synchronized (KeyboardFocusManager.class) {
            if ((window != null)
                && (getMostRecentFocusOwner((Window)window) == comp))
            {
                setMostRecentFocusOwner((Window)window, null);
            }
            // Also clear temporary lost component stored in Window
            if (window != null) {
                Window realWindow = (Window)window;
                if (realWindow.getTemporaryLostComponent() == comp) {
                    realWindow.setTemporaryLostComponent(null);
                }
            }
        }
    }

    /*
     * Please be careful changing this method! It is called from
     * javax.swing.JComponent.runInputVerifier() using reflection.
     */
    static synchronized Component getMostRecentFocusOwner(Window window) {
        WeakReference weakValue =
            (WeakReference)mostRecentFocusOwners.get(window);
        return weakValue == null ? null : (Component)weakValue.get();
    }

    /**
     * This method is called by the AWT event dispatcher requesting that the
     * current KeyboardFocusManager dispatch the specified event on its behalf.
     * It is expected that all KeyboardFocusManagers will dispatch all
     * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
     * These events should be dispatched based on the KeyboardFocusManager's
     * notion of the focus owner and the focused and active Windows, sometimes
     * overriding the source of the specified AWTEvent. Dispatching must be
     * done using <code>redispatchEvent</code> to prevent the AWT event
     * dispatcher from recursively requesting that the KeyboardFocusManager
     * dispatch the event again. If this method returns <code>false</code>,
     * then the AWT event dispatcher will attempt to dispatch the event itself.
     *
     * @param e the AWTEvent to be dispatched
     * @return <code>true</code> if this method dispatched the event;
     *         <code>false</code> otherwise
     * @see #redispatchEvent
     * @see #dispatchKeyEvent
     */
    public abstract boolean dispatchEvent(AWTEvent e);

    /**
     * Redispatches an AWTEvent in such a way that the AWT event dispatcher
     * will not recursively request that the KeyboardFocusManager, or any
     * installed KeyEventDispatchers, dispatch the event again. Client
     * implementations of <code>dispatchEvent</code> and client-defined
     * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
     * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
     * <p>
     * This method is intended to be used only by KeyboardFocusManagers and
     * KeyEventDispatchers. It is not for general client use.
     *
     * @param target the Component to which the event should be dispatched
     * @param e the event to dispatch
     * @see #dispatchEvent
     * @see KeyEventDispatcher
     */
    public final void redispatchEvent(Component target, AWTEvent e) {
        e.focusManagerIsDispatching = true;
        target.dispatchEvent(e);
        e.focusManagerIsDispatching = false;
    }

    /**
     * Typically this method will be called by <code>dispatchEvent</code> if no
     * other KeyEventDispatcher in the dispatcher chain dispatched the
     * KeyEvent, or if no other KeyEventDispatchers are registered. If an
     * implementation of this method returns <code>false</code>,
     * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
     * may simply return <code>false</code>. If <code>true</code> is returned,
     * <code>dispatchEvent</code> should return <code>true</code> as well.
     *
     * @param e the KeyEvent which the current KeyboardFocusManager has
     *        requested that this KeyEventDispatcher dispatch
     * @return <code>true</code> if the KeyEvent was dispatched;
     *         <code>false</code> otherwise
     * @see #dispatchEvent
     */
    public abstract boolean dispatchKeyEvent(KeyEvent e);

    /**
     * This method will be called by <code>dispatchKeyEvent</code>.
     * By default, this method will handle any unconsumed KeyEvents that
     * map to an AWT <code>MenuShortcut</code> by consuming the event
     * and activating the shortcut.
     *
     * @param e the KeyEvent to post-process
     * @return <code>true</code> to indicate that no other
     *         KeyEventPostProcessor will be notified of the KeyEvent.
     * @see #dispatchKeyEvent
     * @see MenuShortcut
     */
    public abstract boolean postProcessKeyEvent(KeyEvent e);

    /**
     * This method initiates a focus traversal operation if and only if the
     * KeyEvent represents a focus traversal key for the specified
     * focusedComponent. It is expected that focusedComponent is the current
     * focus owner, although this need not be the case. If it is not,
     * focus traversal will nevertheless proceed as if focusedComponent
     * were the current focus owner.
     *
     * @param focusedComponent the Component that will be the basis for a focus
     *        traversal operation if the specified event represents a focus
     *        traversal key for the Component
     * @param e the event that may represent a focus traversal key
     */
    public abstract void processKeyEvent(Component focusedComponent,
                                         KeyEvent e);

    /**
     * Called by the AWT to notify the KeyboardFocusManager that it should
     * delay dispatching of KeyEvents until the specified Component becomes
     * the focus owner. If client code requests a focus change, and the AWT
     * determines that this request might be granted by the native windowing
     * system, then the AWT will call this method. It is the responsibility of
     * the KeyboardFocusManager to delay dispatching of KeyEvents with
     * timestamps later than the specified time stamp until the specified
     * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
     * request by invoking <code>dequeueKeyEvents</code> or
     * <code>discardKeyEvents</code>.
     *
     * @param after timestamp of current event, or the current, system time if
     *        the current event has no timestamp, or the AWT cannot determine
     *        which event is currently being handled
     * @param untilFocused Component which should receive a FOCUS_GAINED event
     *        before any pending KeyEvents
     * @see #dequeueKeyEvents
     * @see #discardKeyEvents
     */
    protected abstract void enqueueKeyEvents(long after,
                                             Component untilFocused);

    /**
     * Called by the AWT to notify the KeyboardFocusManager that it should
     * cancel delayed dispatching of KeyEvents. All KeyEvents which were
     * enqueued because of a call to <code>enqueueKeyEvents</code> with the
     * same timestamp and Component should be released for normal dispatching
     * to the current focus owner. If the given timestamp is less than zero,
     * the outstanding enqueue request for the given Component with the <b>
     * oldest</b> timestamp (if any) should be cancelled.
     *
     * @param after the timestamp specified in the call to
     *        <code>enqueueKeyEvents</code>, or any value < 0
     * @param untilFocused the Component specified in the call to
     *        <code>enqueueKeyEvents</code>
     * @see #enqueueKeyEvents
     * @see #discardKeyEvents
     */
    protected abstract void dequeueKeyEvents(long after,
                                             Component untilFocused);

    /**
     * Called by the AWT to notify the KeyboardFocusManager that it should
     * cancel delayed dispatching of KeyEvents. All KeyEvents which were
     * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
     * with the same Component should be discarded.
     *
     * @param comp the Component specified in one or more calls to
     *        <code>enqueueKeyEvents</code>
     * @see #enqueueKeyEvents
     * @see #dequeueKeyEvents
     */
    protected abstract void discardKeyEvents(Component comp);

    /**
     * Focuses the Component after aComponent, typically based on a
     * FocusTraversalPolicy.
     *
     * @param aComponent the Component that is the basis for the focus
     *        traversal operation
     * @see FocusTraversalPolicy
     */
    public abstract void focusNextComponent(Component aComponent);

    /**
     * Focuses the Component before aComponent, typically based on a
     * FocusTraversalPolicy.
     *
     * @param aComponent the Component that is the basis for the focus
     *        traversal operation
     * @see FocusTraversalPolicy
     */
    public abstract void focusPreviousComponent(Component aComponent);

    /**
     * Moves the focus up one focus traversal cycle. Typically, the focus owner
     * is set to aComponent's focus cycle root, and the current focus cycle
     * root is set to the new focus owner's focus cycle root. If, however,
     * aComponent's focus cycle root is a Window, then typically the focus
     * owner is set to the Window's default Component to focus, and the current
     * focus cycle root is unchanged.
     *
     * @param aComponent the Component that is the basis for the focus
     *        traversal operation
     */
    public abstract void upFocusCycle(Component aComponent);

    /**
     * Moves the focus down one focus traversal cycle. Typically, if
     * aContainer is a focus cycle root, then the focus owner is set to
     * aContainer's default Component to focus, and the current focus cycle
     * root is set to aContainer. If aContainer is not a focus cycle root, then
     * no focus traversal operation occurs.
     *
     * @param aContainer the Container that is the basis for the focus
     *        traversal operation
     */
    public abstract void downFocusCycle(Container aContainer);

    /**
     * Focuses the Component after the current focus owner.
     */
    public final void focusNextComponent() {
        Component focusOwner = getFocusOwner();
        if (focusOwner != null) {
            focusNextComponent(focusOwner);
        }
    }

    /**
     * Focuses the Component before the current focus owner.
     */
    public final void focusPreviousComponent() {
        Component focusOwner = getFocusOwner();
        if (focusOwner != null) {
            focusPreviousComponent(focusOwner);
        }
    }

    /**
     * Moves the focus up one focus traversal cycle from the current focus
     * owner. Typically, the new focus owner is set to the current focus
     * owner's focus cycle root, and the current focus cycle root is set to the
     * new focus owner's focus cycle root. If, however, the current focus
     * owner's focus cycle root is a Window, then typically the focus owner is
     * set to the focus cycle root's default Component to focus, and the
     * current focus cycle root is unchanged.
     */
    public final void upFocusCycle() {
        Component focusOwner = getFocusOwner();
        if (focusOwner != null) {
            upFocusCycle(focusOwner);
        }
    }

    /**
     * Moves the focus down one focus traversal cycle from the current focus
     * owner, if and only if the current focus owner is a Container that is a
     * focus cycle root. Typically, the focus owner is set to the current focus
     * owner's default Component to focus, and the current focus cycle root is
     * set to the current focus owner. If the current focus owner is not a
     * Container that is a focus cycle root, then no focus traversal operation
     * occurs.
     */
    public final void downFocusCycle() {
        Component focusOwner = getFocusOwner();
        if (focusOwner instanceof Container) {
            downFocusCycle((Container)focusOwner);
        }
    }

    /**
     * Dumps the list of focus requests to stderr
     */
    void dumpRequests() {
        System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
        synchronized (heavyweightRequests) {
            for (HeavyweightFocusRequest req : heavyweightRequests) {
                System.err.println(">>> Req: " + req);
            }
        }
        System.err.println("");
    }

    private static final class LightweightFocusRequest {
        final Component component;
        final boolean temporary;
        final CausedFocusEvent.Cause cause;

        LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
            this.component = component;
            this.temporary = temporary;
            this.cause = cause;
        }
        public String toString() {
            return "LightweightFocusRequest[component=" + component +
                ",temporary=" + temporary + ", cause=" + cause + "]";
        }
    }

    private static final class HeavyweightFocusRequest {
        final Component heavyweight;
        final LinkedList<LightweightFocusRequest> lightweightRequests;

        static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
            new HeavyweightFocusRequest();

        private HeavyweightFocusRequest() {
            heavyweight = null;
            lightweightRequests = null;
        }

        HeavyweightFocusRequest(Component heavyweight, Component descendant,
                                boolean temporary, CausedFocusEvent.Cause cause) {
            if (log.isLoggable(PlatformLogger.FINE)) {
                if (heavyweight == null) {
                    log.fine("Assertion (heavyweight != null) failed");
                }
            }

            this.heavyweight = heavyweight;
            this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
            addLightweightRequest(descendant, temporary, cause);
        }
        boolean addLightweightRequest(Component descendant,
                                      boolean temporary, CausedFocusEvent.Cause cause) {
            if (log.isLoggable(PlatformLogger.FINE)) {
                if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
                    log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
                }
                if (descendant == null) {
                    log.fine("Assertion (descendant != null) failed");
                }
            }

            Component lastDescendant = ((lightweightRequests.size() > 0)
                ? lightweightRequests.getLast().component
                : null);

            if (descendant != lastDescendant) {
                // Not a duplicate request
                lightweightRequests.add
                    (new LightweightFocusRequest(descendant, temporary, cause));
                return true;
            } else {
                return false;
            }
        }

        LightweightFocusRequest getFirstLightweightRequest() {
            if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
                return null;
            }
            return lightweightRequests.getFirst();
        }
        public String toString() {
            boolean first = true;
            String str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
                ",lightweightRequests=";
            if (lightweightRequests == null) {
                str += null;
            } else {
                str += "[";

                for (LightweightFocusRequest lwRequest : lightweightRequests) {
                    if (first) {
                        first = false;
                    } else {
                        str += ",";
                    }
                    str += lwRequest;
                }
                str += "]";
            }
            str += "]";
            return str;
        }
    }

    /*
     * heavyweightRequests is used as a monitor for synchronized changes of
     * currentLightweightRequests, clearingCurrentLightweightRequests and
     * newFocusOwner.
     */
    private static LinkedList<HeavyweightFocusRequest> heavyweightRequests =
        new LinkedList<HeavyweightFocusRequest>();
    private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
    private static boolean clearingCurrentLightweightRequests;
    private static boolean allowSyncFocusRequests = true;
    private static Component newFocusOwner = null;
    private static volatile boolean disableRestoreFocus;

    static final int SNFH_FAILURE = 0;
    static final int SNFH_SUCCESS_HANDLED = 1;
    static final int SNFH_SUCCESS_PROCEED = 2;

    static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
                                                  boolean temporary, boolean focusedWindowChangeAllowed,
                                                  long time)
    {
        Window parentWindow = SunToolkit.getContainingWindow(heavyweight);
        if (parentWindow == null || !parentWindow.syncLWRequests) {
            return false;
        }
        if (descendant == null) {
            // Focus transfers from a lightweight child back to the
            // heavyweight Container should be treated like lightweight
            // focus transfers.
            descendant = heavyweight;
        }

        KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));

        FocusEvent currentFocusOwnerEvent = null;
        FocusEvent newFocusOwnerEvent = null;
        Component currentFocusOwner = manager.getGlobalFocusOwner();

        synchronized (heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
            if (hwFocusRequest == null &&
                heavyweight == manager.getNativeFocusOwner() &&
                allowSyncFocusRequests)
            {

                if (descendant == currentFocusOwner) {
                    // Redundant request.
                    return true;
                }

                // 'heavyweight' owns the native focus and there are no pending
                // requests. 'heavyweight' must be a Container and
                // 'descendant' must not be the focus owner. Otherwise,
                // we would never have gotten this far.
                manager.enqueueKeyEvents(time, descendant);

                hwFocusRequest =
                    new HeavyweightFocusRequest(heavyweight, descendant,
                                                temporary, CausedFocusEvent.Cause.UNKNOWN);
                heavyweightRequests.add(hwFocusRequest);

                if (currentFocusOwner != null) {
                    currentFocusOwnerEvent =
                        new FocusEvent(currentFocusOwner,
                                       FocusEvent.FOCUS_LOST,
                                       temporary, descendant);
                }
                newFocusOwnerEvent =
                    new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
                                   temporary, currentFocusOwner);
            }
        }
        boolean result = false;
        final boolean clearing = clearingCurrentLightweightRequests;

        Throwable caughtEx = null;
        try {
            clearingCurrentLightweightRequests = false;
            synchronized(Component.LOCK) {

                if (currentFocusOwnerEvent != null && currentFocusOwner != null) {
                    ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
                    caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
                    result = true;
                }

                if (newFocusOwnerEvent != null && descendant != null) {
                    ((AWTEvent) newFocusOwnerEvent).isPosted = true;
                    caughtEx = dispatchAndCatchException(caughtEx, descendant, newFocusOwnerEvent);
                    result = true;
                }
            }
        } finally {
            clearingCurrentLightweightRequests = clearing;
        }
        if (caughtEx instanceof RuntimeException) {
            throw (RuntimeException)caughtEx;
        } else if (caughtEx instanceof Error) {
            throw (Error)caughtEx;
        }
        return result;
    }

    /**
     * Indicates whether the native implementation should proceed with a
     * pending, native focus request. Before changing the focus at the native
     * level, the AWT implementation should always call this function for
     * permission. This function will reject the request if a duplicate request
     * preceded it, or if the specified heavyweight Component already owns the
     * focus and no native focus changes are pending. Otherwise, the request
     * will be approved and the focus request list will be updated so that,
     * if necessary, the proper descendant will be focused when the
     * corresponding FOCUS_GAINED event on the heavyweight is received.
     *
     * An implementation must ensure that calls to this method and native
     * focus changes are atomic. If this is not guaranteed, then the ordering
     * of the focus request list may be incorrect, leading to errors in the
     * type-ahead mechanism. Typically this is accomplished by only calling
     * this function from the native event pumping thread, or by holding a
     * global, native lock during invocation.
     */
    static int shouldNativelyFocusHeavyweight
        (Component heavyweight, Component descendant, boolean temporary,
         boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
    {
        if (log.isLoggable(PlatformLogger.FINE)) {
            if (heavyweight == null) {
                log.fine("Assertion (heavyweight != null) failed");
            }
            if (time == 0) {
                log.fine("Assertion (time != 0) failed");
            }
        }

        if (descendant == null) {
            // Focus transfers from a lightweight child back to the
            // heavyweight Container should be treated like lightweight
            // focus transfers.
            descendant = heavyweight;
        }

        KeyboardFocusManager manager =
            getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
        KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();
        Component currentFocusOwner = thisManager.getGlobalFocusOwner();
        Component nativeFocusOwner = thisManager.getNativeFocusOwner();
        Window nativeFocusedWindow = thisManager.getNativeFocusedWindow();
        if (focusLog.isLoggable(PlatformLogger.FINER)) {
            focusLog.finer("SNFH for {0} in {1}",
                           String.valueOf(descendant), String.valueOf(heavyweight));
        }
        if (focusLog.isLoggable(PlatformLogger.FINEST)) {
            focusLog.finest("0. Current focus owner {0}",
                            String.valueOf(currentFocusOwner));
            focusLog.finest("0. Native focus owner {0}",
                            String.valueOf(nativeFocusOwner));
            focusLog.finest("0. Native focused window {0}",
                            String.valueOf(nativeFocusedWindow));
        }
        synchronized (heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
            if (focusLog.isLoggable(PlatformLogger.FINEST)) {
                focusLog.finest("Request {0}", String.valueOf(hwFocusRequest));
            }
            if (hwFocusRequest == null &&
                heavyweight == nativeFocusOwner)
            {
                if (descendant == currentFocusOwner) {
                    // Redundant request.
                    if (focusLog.isLoggable(PlatformLogger.FINEST))
                        focusLog.finest("1. SNFH_FAILURE for {0}",
                                        String.valueOf(descendant));
                    return SNFH_FAILURE;
                }

                // 'heavyweight' owns the native focus and there are no pending
                // requests. 'heavyweight' must be a Container and
                // 'descendant' must not be the focus owner. Otherwise,
                // we would never have gotten this far.
                manager.enqueueKeyEvents(time, descendant);

                hwFocusRequest =
                    new HeavyweightFocusRequest(heavyweight, descendant,
                                                temporary, cause);
                heavyweightRequests.add(hwFocusRequest);

                if (currentFocusOwner != null) {
                    FocusEvent currentFocusOwnerEvent =
                        new CausedFocusEvent(currentFocusOwner,
                                       FocusEvent.FOCUS_LOST,
                                       temporary, descendant, cause);
                    // Fix 5028014. Rolled out.
                    // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
                    SunToolkit.postEvent(currentFocusOwner.appContext,
                                         currentFocusOwnerEvent);
                }
                FocusEvent newFocusOwnerEvent =
                    new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
                                   temporary, currentFocusOwner, cause);
                // Fix 5028014. Rolled out.
                // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
                SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);

                if (focusLog.isLoggable(PlatformLogger.FINEST))
                    focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
                return SNFH_SUCCESS_HANDLED;
            } else if (hwFocusRequest != null &&
                       hwFocusRequest.heavyweight == heavyweight) {
                // 'heavyweight' doesn't have the native focus right now, but
                // if all pending requests were completed, it would. Add
                // descendant to the heavyweight's list of pending
                // lightweight focus transfers.
                if (hwFocusRequest.addLightweightRequest(descendant,
                                                         temporary, cause)) {
                    manager.enqueueKeyEvents(time, descendant);
                }

                if (focusLog.isLoggable(PlatformLogger.FINEST))
                    focusLog.finest("3. SNFH_HANDLED for lightweight" +
                                    descendant + " in " + heavyweight);
                return SNFH_SUCCESS_HANDLED;
            } else {
                if (!focusedWindowChangeAllowed) {
                    // For purposes of computing oldFocusedWindow, we should look at
                    // the second to last HeavyweightFocusRequest on the queue iff the
                    // last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If
                    // there is no second to last HeavyweightFocusRequest, null is an
                    // acceptable value.
                    if (hwFocusRequest ==
                        HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
                    {
                        int size = heavyweightRequests.size();
                        hwFocusRequest = (HeavyweightFocusRequest)((size >= 2)
                            ? heavyweightRequests.get(size - 2)
                            : null);
                    }
                    if (focusedWindowChanged(heavyweight,
                                             (hwFocusRequest != null)
                                             ? hwFocusRequest.heavyweight
                                             : nativeFocusedWindow)) {
                        if (focusLog.isLoggable(PlatformLogger.FINEST))
                            focusLog.finest("4. SNFH_FAILURE for " + descendant);
                        return SNFH_FAILURE;
                    }
                }

                manager.enqueueKeyEvents(time, descendant);
                heavyweightRequests.add
                    (new HeavyweightFocusRequest(heavyweight, descendant,
                                                 temporary, cause));
                if (focusLog.isLoggable(PlatformLogger.FINEST))
                    focusLog.finest("5. SNFH_PROCEED for " + descendant);
                return SNFH_SUCCESS_PROCEED;
            }
        }
    }

    /**
     * Returns the Window which will be active after processing this request,
     * or null if this is a duplicate request. The active Window is useful
     * because some native platforms do not support setting the native focus
     * owner to null. On these platforms, the obvious choice is to set the
     * focus owner to the focus proxy of the active Window.
     */
    static Window markClearGlobalFocusOwner() {
        // need to call this out of synchronized block to avoid possible deadlock
        // see 6454631.
        final Component nativeFocusedWindow =
                getCurrentKeyboardFocusManager().getNativeFocusedWindow();

        synchronized (heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
            if (hwFocusRequest ==
                HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
            {
                // duplicate request
                return null;
            }

            heavyweightRequests.add
                (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);

            Component activeWindow = ((hwFocusRequest != null)
                ? SunToolkit.getContainingWindow(hwFocusRequest.heavyweight)
                : nativeFocusedWindow);
            while (activeWindow != null &&
                   !((activeWindow instanceof Frame) ||
                     (activeWindow instanceof Dialog)))
            {
                activeWindow = activeWindow.getParent_NoClientCode();
            }

            return (Window) activeWindow;
        }
    }
    Component getCurrentWaitingRequest(Component parent) {
        synchronized (heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
            if (hwFocusRequest != null) {
                if (hwFocusRequest.heavyweight == parent) {
                    LightweightFocusRequest lwFocusRequest =
                        hwFocusRequest.lightweightRequests.getFirst();
                    if (lwFocusRequest != null) {
                        return lwFocusRequest.component;
                    }
                }
            }
        }
        return null;
    }

    static boolean isAutoFocusTransferEnabled() {
        synchronized (heavyweightRequests) {
            return (heavyweightRequests.size() == 0)
                    && !disableRestoreFocus
                    && (null == currentLightweightRequests);
        }
    }

    static boolean isAutoFocusTransferEnabledFor(Component comp) {
        return isAutoFocusTransferEnabled() && comp.isAutoFocusTransferOnDisposal();
    }

    /*
     * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
     * @param ex previously caught exception that may be processed right here, or null
     * @param comp the component to dispatch the event to
     * @param event the event to dispatch to the component
     */
    static private Throwable dispatchAndCatchException(Throwable ex, Component comp, FocusEvent event) {
        Throwable retEx = null;
        try {
            comp.dispatchEvent(event);
        } catch (RuntimeException re) {
            retEx = re;
        } catch (Error er) {
            retEx = er;
        }
        if (retEx != null) {
            if (ex != null) {
                handleException(ex);
            }
            return retEx;
        }
        return ex;
    }

    static private void handleException(Throwable ex) {
        ex.printStackTrace();
    }

    static void processCurrentLightweightRequests() {
        KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
        LinkedList<LightweightFocusRequest> localLightweightRequests = null;

        Component globalFocusOwner = manager.getGlobalFocusOwner();
        if ((globalFocusOwner != null) &&
            (globalFocusOwner.appContext != AppContext.getAppContext()))
        {
            // The current app context differs from the app context of a focus
            // owner (and all pending lightweight requests), so we do nothing
            // now and wait for a next event.
            return;
        }

        synchronized(heavyweightRequests) {
            if (currentLightweightRequests != null) {
                clearingCurrentLightweightRequests = true;
                disableRestoreFocus = true;
                localLightweightRequests = currentLightweightRequests;
                allowSyncFocusRequests = (localLightweightRequests.size() < 2);
                currentLightweightRequests = null;
            } else {
                // do nothing
                return;
            }
        }

        Throwable caughtEx = null;
        try {
            if (localLightweightRequests != null) {
                Component lastFocusOwner = null;
                Component currentFocusOwner = null;

                for (Iterator iter = localLightweightRequests.iterator(); iter.hasNext(); ) {

                    currentFocusOwner = manager.getGlobalFocusOwner();
                    LightweightFocusRequest lwFocusRequest =
                        (LightweightFocusRequest)iter.next();

                    /*
                     * WARNING: This is based on DKFM's logic solely!
                     *
                     * We allow to trigger restoreFocus() in the dispatching process
                     * only if we have the last request to dispatch. If the last request
                     * fails, focus will be restored to either the component of the last
                     * previously succedded request, or to to the focus owner that was
                     * before this clearing proccess.
                     */
                    if (!iter.hasNext()) {
                        disableRestoreFocus = false;
                    }

                    FocusEvent currentFocusOwnerEvent = null;
                    /*
                     * We're not dispatching FOCUS_LOST while the current focus owner is null.
                     * But regardless of whether it's null or not, we're clearing ALL the local
                     * lw requests.
                     */
                    if (currentFocusOwner != null) {
                        currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
                                       FocusEvent.FOCUS_LOST,
                                       lwFocusRequest.temporary,
                                       lwFocusRequest.component, lwFocusRequest.cause);
                    }
                    FocusEvent newFocusOwnerEvent =
                        new CausedFocusEvent(lwFocusRequest.component,
                                       FocusEvent.FOCUS_GAINED,
                                       lwFocusRequest.temporary,
                                       currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
                                       lwFocusRequest.cause);

                    if (currentFocusOwner != null) {
                        ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
                        caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
                    }

                    ((AWTEvent) newFocusOwnerEvent).isPosted = true;
                    caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);

                    if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
                        lastFocusOwner = lwFocusRequest.component;
                    }
                }
            }
        } finally {
            clearingCurrentLightweightRequests = false;
            disableRestoreFocus = false;
            localLightweightRequests = null;
            allowSyncFocusRequests = true;
        }
        if (caughtEx instanceof RuntimeException) {
            throw (RuntimeException)caughtEx;
        } else if (caughtEx instanceof Error) {
            throw (Error)caughtEx;
        }
    }

    static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
        synchronized (heavyweightRequests) {
            // Any other case represents a failure condition which we did
            // not expect. We need to clearFocusRequestList() and patch up
            // the event as best as possible.

            if (removeFirstRequest()) {
                return (FocusEvent)retargetFocusEvent(fe);
            }

            Component source = fe.getComponent();
            Component opposite = fe.getOppositeComponent();
            boolean temporary = false;
            if (fe.getID() == FocusEvent.FOCUS_LOST &&
                (opposite == null || isTemporary(opposite, source)))
            {
                temporary = true;
            }
            return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
                                        CausedFocusEvent.Cause.NATIVE_SYSTEM);
        }
    }

    static FocusEvent retargetFocusGained(FocusEvent fe) {
        assert (fe.getID() == FocusEvent.FOCUS_GAINED);

        Component currentFocusOwner = getCurrentKeyboardFocusManager().
            getGlobalFocusOwner();
        Component source = fe.getComponent();
        Component opposite = fe.getOppositeComponent();
        Component nativeSource = getHeavyweight(source);

        synchronized (heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();

            if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
            {
                return retargetUnexpectedFocusEvent(fe);
            }

            if (source != null && nativeSource == null && hwFocusRequest != null) {
                // if source w/o peer and
                // if source is equal to first lightweight
                // then we should correct source and nativeSource
                if (source == hwFocusRequest.getFirstLightweightRequest().component)
                {
                    source = hwFocusRequest.heavyweight;
                    nativeSource = source; // source is heavuweight itself
                }
            }
            if (hwFocusRequest != null &&
                nativeSource == hwFocusRequest.heavyweight)
            {
                // Focus change as a result of a known call to requestFocus(),
                // or known click on a peer focusable heavyweight Component.

                heavyweightRequests.removeFirst();

                LightweightFocusRequest lwFocusRequest =
                    hwFocusRequest.lightweightRequests.removeFirst();

                Component newSource = lwFocusRequest.component;
                if (currentFocusOwner != null) {
                    /*
                     * Since we receive FOCUS_GAINED when current focus
                     * owner is not null, correcponding FOCUS_LOST is supposed
                     * to be lost.  And so,  we keep new focus owner
                     * to determine synthetic FOCUS_LOST event which will be
                     * generated by KeyboardFocusManager for this FOCUS_GAINED.
                     *
                     * This code based on knowledge of
                     * DefaultKeyboardFocusManager's implementation and might
                     * be not applicable for another KeyboardFocusManager.
                     */
                    newFocusOwner = newSource;
                }

                boolean temporary = (opposite == null ||
                                     isTemporary(newSource, opposite))
                        ? false
                        : lwFocusRequest.temporary;

                if (hwFocusRequest.lightweightRequests.size() > 0) {
                    currentLightweightRequests =
                        hwFocusRequest.lightweightRequests;
                    EventQueue.invokeLater(new Runnable() {
                            public void run() {
                                processCurrentLightweightRequests();
                            }
                        });
                }

                // 'opposite' will be fixed by
                // DefaultKeyboardFocusManager.realOppositeComponent
                return new CausedFocusEvent(newSource,
                                      FocusEvent.FOCUS_GAINED, temporary,
                                      opposite, lwFocusRequest.cause);
            }

            if (currentFocusOwner != null
                && currentFocusOwner.getContainingWindow() == source
                && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
            {
                // Special case for FOCUS_GAINED in top-levels
                // If it arrives as the result of activation we should skip it
                // This event will not have appropriate request record and
                // on arrival there will be already some focus owner set.
                return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
                                            null, CausedFocusEvent.Cause.ACTIVATION);
            }

            return retargetUnexpectedFocusEvent(fe);
        } // end synchronized(heavyweightRequests)
    }

    static FocusEvent retargetFocusLost(FocusEvent fe) {
        assert (fe.getID() == FocusEvent.FOCUS_LOST);

        Component currentFocusOwner = getCurrentKeyboardFocusManager().
            getGlobalFocusOwner();
        Component opposite = fe.getOppositeComponent();
        Component nativeOpposite = getHeavyweight(opposite);

        synchronized (heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();

            if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
            {
                if (currentFocusOwner != null) {
                    // Call to KeyboardFocusManager.clearGlobalFocusOwner()
                    heavyweightRequests.removeFirst();
                    return new CausedFocusEvent(currentFocusOwner,
                                                FocusEvent.FOCUS_LOST, false, null,
                                                CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
                }

                // Otherwise, fall through to failure case below

            } else if (opposite == null)
            {
                // Focus leaving application
                if (currentFocusOwner != null) {
                    return new CausedFocusEvent(currentFocusOwner,
                                                FocusEvent.FOCUS_LOST,
                                                true, null, CausedFocusEvent.Cause.ACTIVATION);
                } else {
                    return fe;
                }
            } else if (hwFocusRequest != null &&
                       (nativeOpposite == hwFocusRequest.heavyweight ||
                        nativeOpposite == null &&
                        opposite == hwFocusRequest.getFirstLightweightRequest().component))
            {
                if (currentFocusOwner == null) {
                    return fe;
                }
                // Focus change as a result of a known call to requestFocus(),
                // or click on a peer focusable heavyweight Component.
                // If a focus transfer is made across top-levels, then the
                // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
                // event is always permanent. Otherwise, the stored temporary
                // value is honored.

                LightweightFocusRequest lwFocusRequest =
                    hwFocusRequest.lightweightRequests.getFirst();

                boolean temporary = isTemporary(opposite, currentFocusOwner)
                    ? true
                    : lwFocusRequest.temporary;

                return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
                                            temporary, lwFocusRequest.component, lwFocusRequest.cause);
            } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
                // If top-level changed there might be no focus request in a list
                // But we know the opposite, we now it is temporary - dispatch the event.
                if (!fe.isTemporary() && currentFocusOwner != null) {
                    // Create copy of the event with only difference in temporary parameter.
                    fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
                                              true, opposite, CausedFocusEvent.Cause.ACTIVATION);
                }
                return fe;
            }

            return retargetUnexpectedFocusEvent(fe);
        }  // end synchronized(heavyweightRequests)
    }

    static AWTEvent retargetFocusEvent(AWTEvent event) {
        if (clearingCurrentLightweightRequests) {
            return event;
        }

        KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
        if (focusLog.isLoggable(PlatformLogger.FINER)) {
            if (event instanceof FocusEvent || event instanceof WindowEvent) {
                focusLog.finer(">>> {0}", String.valueOf(event));
            }
            if (focusLog.isLoggable(PlatformLogger.FINER) && event instanceof KeyEvent) {
                focusLog.finer("    focus owner is {0}",
                               String.valueOf(manager.getGlobalFocusOwner()));
                focusLog.finer(">>> {0}", String.valueOf(event));
            }
        }

        synchronized(heavyweightRequests) {
            /*
             * This code handles FOCUS_LOST event which is generated by
             * DefaultKeyboardFocusManager for FOCUS_GAINED.
             *
             * This code based on knowledge of DefaultKeyboardFocusManager's
             * implementation and might be not applicable for another
             * KeyboardFocusManager.
             *
             * Fix for 4472032
             */
            if (newFocusOwner != null &&
                event.getID() == FocusEvent.FOCUS_LOST)
            {
                FocusEvent fe = (FocusEvent)event;

                if (manager.getGlobalFocusOwner() == fe.getComponent() &&
                    fe.getOppositeComponent() == newFocusOwner)
                {
                    newFocusOwner = null;
                    return event;
                }
            }
        }

        processCurrentLightweightRequests();

        switch (event.getID()) {
            case FocusEvent.FOCUS_GAINED: {
                event = retargetFocusGained((FocusEvent)event);
                break;
            }
            case FocusEvent.FOCUS_LOST: {
                event = retargetFocusLost((FocusEvent)event);
                break;
            }
            default:
                /* do nothing */
        }
        return event;
    }

    /**
     * Clears markers queue
     * This method is not intended to be overridden by KFM's.
     * Only DefaultKeyboardFocusManager can implement it.
     * @since 1.5
     */
    void clearMarkers() {
    }

    static boolean removeFirstRequest() {
        KeyboardFocusManager manager =
            KeyboardFocusManager.getCurrentKeyboardFocusManager();

        synchronized(heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();

            if (hwFocusRequest != null) {
                heavyweightRequests.removeFirst();
                if (hwFocusRequest.lightweightRequests != null) {
                    for (Iterator lwIter = hwFocusRequest.lightweightRequests.
                             iterator();
                         lwIter.hasNext(); )
                    {
                        manager.dequeueKeyEvents
                            (-1, ((LightweightFocusRequest)lwIter.next()).
                             component);
                    }
                }
            }
            // Fix for 4799136 - clear type-ahead markers if requests queue is empty
            // We do it here because this method is called only when problems happen
            if (heavyweightRequests.size() == 0) {
                manager.clearMarkers();
            }
            return (heavyweightRequests.size() > 0);
        }
    }
    static void removeLastFocusRequest(Component heavyweight) {
        if (log.isLoggable(PlatformLogger.FINE)) {
            if (heavyweight == null) {
                log.fine("Assertion (heavyweight != null) failed");
            }
        }

        KeyboardFocusManager manager =
            KeyboardFocusManager.getCurrentKeyboardFocusManager();
        synchronized(heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
            if (hwFocusRequest != null &&
                hwFocusRequest.heavyweight == heavyweight) {
                heavyweightRequests.removeLast();
            }
            // Fix for 4799136 - clear type-ahead markers if requests queue is empty
            // We do it here because this method is called only when problems happen
            if (heavyweightRequests.size() == 0) {
                manager.clearMarkers();
            }
        }
    }

    private static boolean focusedWindowChanged(Component to, Component from) {
        Window wto = SunToolkit.getContainingWindow(to);
        Window wfrom = SunToolkit.getContainingWindow(from);
        if (wto == null && wfrom == null) {
            return true;
        }
        if (wto == null) {
            return true;
        }
        if (wfrom == null) {
            return true;
        }
        return (wto != wfrom);
    }

    private static boolean isTemporary(Component to, Component from) {
        Window wto = SunToolkit.getContainingWindow(to);
        Window wfrom = SunToolkit.getContainingWindow(from);
        if (wto == null && wfrom == null) {
            return false;
        }
        if (wto == null) {
            return true;
        }
        if (wfrom == null) {
            return false;
        }
        return (wto != wfrom);
    }

    static Component getHeavyweight(Component comp) {
        if (comp == null || comp.getPeer() == null) {
            return null;
        } else if (comp.getPeer() instanceof LightweightPeer) {
            return comp.getNativeContainer();
        } else {
            return comp;
        }
    }

    static Field proxyActive;
    // Accessor to private field isProxyActive of KeyEvent
    private static boolean isProxyActiveImpl(KeyEvent e) {
        if (proxyActive == null) {
            proxyActive = (Field) AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        Field field = null;
                        try {
                            field = KeyEvent.class.getDeclaredField("isProxyActive");
                            if (field != null) {
                                field.setAccessible(true);
                            }
                        } catch (NoSuchFieldException nsf) {
                            assert(false);
                        }
                        return field;
                    }
                });
        }

        try {
            return proxyActive.getBoolean(e);
        } catch (IllegalAccessException iae) {
            assert(false);
        }
        return false;
    }

    // Returns the value of this KeyEvent's field isProxyActive
    static boolean isProxyActive(KeyEvent e) {
        if (!GraphicsEnvironment.isHeadless()) {
            return isProxyActiveImpl(e);
        } else {
            return false;
        }
    }

    private static HeavyweightFocusRequest getLastHWRequest() {
        synchronized(heavyweightRequests) {
            return (heavyweightRequests.size() > 0)
                ? heavyweightRequests.getLast()
                : null;
        }
    }

    private static HeavyweightFocusRequest getFirstHWRequest() {
        synchronized(heavyweightRequests) {
            return (heavyweightRequests.size() > 0)
                ? heavyweightRequests.getFirst()
                : null;
        }
    }
}
