/*
 * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
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 java.util.logging.Level;
import java.util.logging.Logger;

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

/**
 * 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 Logger focusLog = Logger.getLogger("java.awt.focus.KeyboardFocusManager");

    static {
        /* ensure that the necessary native libraries are loaded */
        Toolkit.loadLibraries();
        if (!GraphicsEnvironment.isHeadless()) {
            initIDs();
        }
    }

    transient KeyboardFocusManagerPeer peer;

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

    private static final Logger log = Logger.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(Level.FINER)) {
                    focusLog.log(Level.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(Level.FINEST)) {
            focusLog.log(Level.FINEST, "Calling peer {0} setCurrentFocusOwner for {1}",
                         new Object[] {peer, 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(Level.FINER)) {
                    focusLog.log(Level.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(Level.FINER)) {
                    focusLog.log(Level.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(Level.FINER)) {
                    focusLog.log(Level.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(Level.FINER)) {
                focusLog.log(Level.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(Level.FINER)) {
                    focusLog.log(Level.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(Level.FINE)) {
                if (heavyweight == null) {
                    log.log(Level.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(Level.FINE)) {
                if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
                    log.log(Level.FINE, "Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
                }
                if (descendant == null) {
                    log.log(Level.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 = Component.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(Level.FINE)) {
            if (heavyweight == null) {
                log.log(Level.FINE, "Assertion (heavyweight != null) failed");
            }
            if (time == 0) {
                log.log(Level.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(Level.FINER)) {
            focusLog.log(Level.FINER, "SNFH for {0} in {1}",
                         new Object[] {descendant, heavyweight});
        }
        if (focusLog.isLoggable(Level.FINEST)) {
            focusLog.log(Level.FINEST, "0. Current focus owner {0}",
                         currentFocusOwner);
            focusLog.log(Level.FINEST, "0. Native focus owner {0}",
                         nativeFocusOwner);
            focusLog.log(Level.FINEST, "0. Native focused window {0}",
                         nativeFocusedWindow);
        }
        synchronized (heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
            if (focusLog.isLoggable(Level.FINEST)) {
                focusLog.log(Level.FINEST, "Request {0}", hwFocusRequest);
            }
            if (hwFocusRequest == null &&
                heavyweight == nativeFocusOwner)
            {
                if (descendant == currentFocusOwner) {
                    // Redundant request.
                    if (focusLog.isLoggable(Level.FINEST))
                        focusLog.log(Level.FINEST, "1. SNFH_FAILURE for {0}",
                                     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(Level.FINEST))
                    focusLog.log(Level.FINEST, "2. SNFH_HANDLED for {0}", 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(Level.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(Level.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(Level.FINEST))
                    focusLog.finest("5. SNFH_PROCEED for " + descendant);
                return SNFH_SUCCESS_PROCEED;
            }
        }
    }
    static void heavyweightButtonDown(Component heavyweight, long time) {
        heavyweightButtonDown(heavyweight, time, false);
    }
    static void heavyweightButtonDown(Component heavyweight, long time, boolean acceptDuplicates) {
        if (log.isLoggable(Level.FINE)) {
            if (heavyweight == null) {
                log.log(Level.FINE, "Assertion (heavyweight != null) failed");
            }
            if (time == 0) {
                log.log(Level.FINE, "Assertion (time != 0) failed");
            }
        }
        KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(heavyweight));

        synchronized (heavyweightRequests) {
            HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
            Component currentNativeFocusOwner = (hwFocusRequest == null)
                ? manager.getNativeFocusOwner()
                : hwFocusRequest.heavyweight;

            // Behavior for all use cases:
            // 1. Heavyweight leaf Components (e.g., Button, Checkbox, Choice,
            //    List, TextComponent, Canvas) that respond to button down.
            //
            //    Native platform will generate a FOCUS_GAINED if and only if
            //    the Component is not the focus owner (or, will not be the
            //    focus owner when all outstanding focus requests are
            //    processed).
            //
            // 2. Panel with no descendants.
            //
            //    Same as (1).
            //
            // 3. Panel with at least one heavyweight descendant.
            //
            //    This function should NOT be called for this case!
            //
            // 4. Panel with only lightweight descendants.
            //
            //    Native platform will generate a FOCUS_GAINED if and only if
            //    neither the Panel, nor any of its recursive, lightweight
            //    descendants, is the focus owner. However, we want a
            //    requestFocus() for any lightweight descendant to win out over
            //    the focus request for the Panel. To accomplish this, we
            //    differ from the algorithm for shouldNativelyFocusHeavyweight
            //    as follows:
            //      a. If the requestFocus() for a lightweight descendant has
            //         been fully handled by the time this function is invoked,
            //         then 'hwFocusRequest' will be null and 'heavyweight'
            //         will be the native focus owner. Do *not* synthesize a
            //         focus transfer to the Panel.
            //      b. If the requestFocus() for a lightweight descendant has
            //         been recorded, but not handled, then 'hwFocusRequest'
            //         will be non-null and 'hwFocusRequest.heavyweight' will
            //         equal 'heavyweight'. Do *not* append 'heavyweight' to
            //         hwFocusRequest.lightweightRequests.
            //      c. If the requestFocus() for a lightweight descendant is
            //         yet to be made, then post a new HeavyweightFocusRequest.
            //         If no lightweight descendant ever requests focus, then
            //         the Panel will get focus. If some descendant does, then
            //         the descendant will get focus by either a synthetic
            //         focus transfer, or a lightweightRequests focus transfer.

            if (acceptDuplicates || heavyweight != currentNativeFocusOwner) {
                getCurrentKeyboardFocusManager
                    (SunToolkit.targetToAppContext(heavyweight)).
                    enqueueKeyEvents(time, heavyweight);
                heavyweightRequests.add
                    (new HeavyweightFocusRequest(heavyweight, heavyweight,
                                                 false, CausedFocusEvent.Cause.MOUSE_EVENT));
            }
        }
    }
    /**
     * 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)
                ? Component.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);
        }
    }

    /*
     * 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(Level.FINER)) {
            if (event instanceof FocusEvent || event instanceof WindowEvent) {
                focusLog.log(Level.FINER, ">>> {0}", new Object[] {event});
            }
            if (focusLog.isLoggable(Level.FINER) && event instanceof KeyEvent) {
                focusLog.log(Level.FINER, "    focus owner is {0}", new Object[] {manager.getGlobalFocusOwner()});
                focusLog.log(Level.FINER, ">>> {0}", new Object[] {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(Level.FINE)) {
            if (heavyweight == null) {
                log.log(Level.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 = Component.getContainingWindow(to);
        Window wfrom = Component.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 = Component.getContainingWindow(to);
        Window wfrom = Component.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;
        }
    }
}
