/* KeyboardFocusManager.java -- manage component focusing via the keyboard
   Copyright (C) 2002, 2004, 2005 Free Software Foundation

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.awt;

import java.applet.Applet;
import java.awt.FocusTraversalPolicy;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * The <code>KeyboardFocusManager</code> handles the focusing of
 * windows for receiving keyboard events.  The manager handles
 * the dispatch of all <code>FocusEvent</code>s and
 * <code>KeyEvent</code>s, along with <code>WindowEvent</code>s
 * relating to the focused window.  Users can use the manager
 * to ascertain the current focus owner and fire events.
 * <br />
 * <br />
 * The focus owner is the <code>Component</code> that receives
 * key events.  The focus owner is either the currently focused
 * window or a component within this window.
 * <br />
 * <br />
 * The underlying native windowing system may denote the active
 * window or its children with special decorations (e.g. a highlighted
 * title bar).  The active window is always either a <code>Frame</code>
 * or <code>Dialog</code>, and is either the currently focused
 * window or its owner.
 * <br />
 * <br />
 * Applets may be partitioned into different applet contexts, according
 * to their code base.  In this case, each context has its own
 * <code>KeyboardFocusManager</code>, as opposed to the global
 * manager maintained by applets which share the same context.
 * Each context is insulated from the others, and they don't interact.
 * The resulting behaviour, as with context division, depends on the browser
 * supporting the applets.  Regardless, there can only ever be
 * one focused window, one active window and one focus owner
 * per <code>ClassLoader</code>.
 * <br />
 * <br />
 * To support this separation of focus managers, the manager instances
 * and the internal state information is grouped by the
 * <code>ThreadGroup</code> to which it pertains.  With respect to
 * applets, each code base has its own <code>ThreadGroup</code>, so the
 * isolation of each context is enforced within the manager.
 * <br />
 * <br />
 * By default, the manager defines TAB and Ctrl+TAB as the
 * forward focus traversal keys and Shift+TAB and Ctrl+Shift+TAB
 * as the backward focus traversal keys.  No up or down cycle
 * traversal keys are defined by default.  Traversal takes effect
 * on the firing of a relevant <code>KEY_PRESSED</code> event.
 * However, all other key events related to the use of the
 * defined focus traversal key sequence are consumed and not
 * dispatched.
 * <br />
 * <br />
 * These default traversal keys come into effect on all windows
 * for which no alternative set of keys is defined.  This also
 * applies recursively to any child components of such a window,
 * which define no traversal keys of their own.
 *
 * @author Eric Blake (ebb9@email.byu.edu)
 * @author Thomas Fitzsimmons (fitzsim@redhat.com)
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @since 1.4
 */
public abstract class KeyboardFocusManager
  implements KeyEventDispatcher, KeyEventPostProcessor
{
  /** Identifies {@link AWTKeyStroke}s that move the focus forward in
      the focus cycle. */
  public static final int FORWARD_TRAVERSAL_KEYS = 0;

  /** Identifies {@link AWTKeyStroke}s that move the focus backward in
      the focus cycle. */
  public static final int BACKWARD_TRAVERSAL_KEYS = 1;

  /** Identifies {@link AWTKeyStroke}s that move the focus up to the
      parent focus cycle root. */
  public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;

  /** Identifies {@link AWTKeyStroke}s that move the focus down to the
      child focus cycle root. */
  public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;

  /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
      the next focusable Component in the focus cycle. */
  private static final Set DEFAULT_FORWARD_KEYS;

  /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
      the previous focusable Component in the focus cycle. */
  private static final Set DEFAULT_BACKWARD_KEYS;

  /** Populate the DEFAULT_FORWARD_KEYS and DEFAULT_BACKWARD_KEYS
      {@link java.util.Set}s. */
  static
  {
    Set s = new HashSet();
    s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
    s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
                                       KeyEvent.CTRL_DOWN_MASK));
    DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
    s = new HashSet();
    s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
                                       KeyEvent.SHIFT_DOWN_MASK));
    s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
                                       KeyEvent.SHIFT_DOWN_MASK
                                       | KeyEvent.CTRL_DOWN_MASK));
    DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
  }

  /** The global object {@link java.util.Map}s. */

  /** For security reasons, {@link java.applet.Applet}s in different
      codebases must be insulated from one another.  Since {@link
      KeyboardFocusManager}s have the ability to return {@link
      Component}s from a given {@link java.applet.Applet}, each
      codebase must have an independent {@link KeyboardFocusManager}.
      Since each codebase has its own {@link ThreadGroup} in which its
      {@link Applet}s run, it makes sense to partition {@link
      KeyboardFocusManager}s according to {@link
      java.lang.ThreadGroup}.  Thus, currentKeyboardFocusManagers is a
      {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}. */
  private static Map currentKeyboardFocusManagers = new HashMap ();

  /** {@link java.applet.Applet}s in one codebase must not be allowed
      to access {@link Component}s in {@link java.applet.Applet}s in
      other codebases.  To enforce this restriction, we key the
      following {@link java.util.Map}s on {@link java.lang.ThreadGroup}s (which
      are per-codebase).  For example, if {@link
      java.lang.ThreadGroup} A calls {@link #setGlobalFocusOwner},
      passing {@link Component} C, currentFocusOwners[A] is assigned
      C, and all other currentFocusOwners values are nullified.  Then
      if {@link java.lang.ThreadGroup} A subsequently calls {@link
      #getGlobalFocusOwner}, it will return currentFocusOwners[A],
      that is, {@link Component} C.  If another {@link
      java.lang.ThreadGroup} K calls {@link #getGlobalFocusOwner}, it
      will return currentFocusOwners[K], that is, null.

      Since this is a static field, we ensure that there is only one
      focused {@link Component} per class loader. */
  private static Map currentFocusOwners = new HashMap ();

  /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
      that stores the {@link Component} that owns the permanent
      keyboard focus. @see currentFocusOwners */
  private static Map currentPermanentFocusOwners = new HashMap ();

  /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
      that stores the focused {@link Window}. @see
      currentFocusOwners */
  private static Map currentFocusedWindows = new HashMap ();

  /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
      that stores the active {@link Window}. @see
      currentFocusOwners */
  private static Map currentActiveWindows = new HashMap ();

  /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
      that stores the focus cycle root {@link Container}. @see
      currentFocusOwners */
  private static Map currentFocusCycleRoots = new HashMap ();

  /** The default {@link FocusTraversalPolicy} that focus-managing
      {@link Container}s will use to define their initial focus
      traversal policy. */
  private FocusTraversalPolicy defaultPolicy;

  /** An array that stores the {@link #FORWARD_TRAVERSAL_KEYS}, {@link
      #BACKWARD_TRAVERSAL_KEYS}, {@link #UP_CYCLE_TRAVERSAL_KEYS} and
      {@link #DOWN_CYCLE_TRAVERSAL_KEYS} {@link AWTKeyStroke}s {@link
      java.util.Set}s. */
  private Set[] defaultFocusKeys = new Set[]
  {
    DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS,
    Collections.EMPTY_SET, Collections.EMPTY_SET
  };

  /**
   * A utility class to support the handling of events relating to property changes.
   */
  private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this);

  /**
   * A utility class to support the handling of events relating to vetoable changes.
   */
  private final VetoableChangeSupport vetoableChangeSupport = new VetoableChangeSupport (this);

  /** A list of {@link KeyEventDispatcher}s that process {@link
      KeyEvent}s before they are processed the default keyboard focus
      manager. */
  private final ArrayList keyEventDispatchers = new ArrayList();

  /** A list of {@link KeyEventPostProcessor}s that process unconsumed
      {@link KeyEvent}s. */
  private final ArrayList keyEventPostProcessors = new ArrayList();

  /**
   * Construct a KeyboardFocusManager.
   */
  public KeyboardFocusManager ()
  {
  }

  /**
   * Retrieve the keyboard focus manager associated with the {@link
   * java.lang.ThreadGroup} to which the calling thread belongs.
   *
   * @return the keyboard focus manager associated with the current
   * thread group
   */
  public static KeyboardFocusManager getCurrentKeyboardFocusManager ()
  {
    ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();

    if (currentKeyboardFocusManagers.get (currentGroup) == null)
      setCurrentKeyboardFocusManager (null);

    return (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
  }

  /**
   * Set the keyboard focus manager associated with the {@link
   * java.lang.ThreadGroup} to which the calling thread belongs.
   *
   * @param m the keyboard focus manager for the current thread group
   */
  public static void setCurrentKeyboardFocusManager (KeyboardFocusManager m)
  {
    SecurityManager sm = System.getSecurityManager ();
    if (sm != null)
      sm.checkPermission (new AWTPermission ("replaceKeyboardFocusManager"));

    ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
    KeyboardFocusManager manager;

    if (m == null)
      manager = new DefaultKeyboardFocusManager();
    else
      manager = m;

    currentKeyboardFocusManagers.put (currentGroup, manager);
  }

  /**
   * Retrieve the {@link Component} that has the keyboard focus, or
   * null if the focus owner was not set by a thread in the current
   * {@link java.lang.ThreadGroup}.
   *
   * @return the keyboard focus owner or null
   */
  public Component getFocusOwner ()
  {
    return (Component) getObject (currentFocusOwners);
  }

  /**
   * Retrieve the {@link Component} that has the keyboard focus,
   * regardless of whether or not it was set by a thread in the
   * current {@link java.lang.ThreadGroup}.  If there is no temporary
   * focus owner in effect then this method will return the same value
   * as {@link #getGlobalPermanentFocusOwner}.
   *
   * @return the keyboard focus owner
   * @throws SecurityException if this is not the keyboard focus
   * manager associated with the current {@link java.lang.ThreadGroup}
   */
  protected Component getGlobalFocusOwner ()
  {
    return (Component) getGlobalObject(currentFocusOwners, true);
  }

  /**
   * Set the {@link Component} that will be returned by {@link
   * #getFocusOwner} (when it is called from the current {@link
   * java.lang.ThreadGroup}) and {@link #getGlobalFocusOwner}.  This
   * method does not actually transfer the keyboard focus.
   *
   * @param owner the Component to return from getFocusOwner and
   * getGlobalFocusOwner
   *
   * @see Component#requestFocus()
   * @see Component#requestFocusInWindow()
   */
  protected void setGlobalFocusOwner (Component owner)
  {
    if (owner == null || owner.focusable)
      setGlobalObject (currentFocusOwners, owner, "focusOwner");
  }

  /**
   * Clear the global focus owner and deliver a FOCUS_LOST event to
   * the previously-focused {@link Component}.  Until another {@link
   * Component} becomes the keyboard focus owner, key events will be
   * discarded by top-level windows.
   */
  public void clearGlobalFocusOwner ()
  {
    synchronized (currentFocusOwners)
      {
        Component focusOwner = getGlobalFocusOwner ();
        Component permanentFocusOwner = getGlobalPermanentFocusOwner ();

        setGlobalFocusOwner (null);
        setGlobalPermanentFocusOwner (null);

        // Inform the old focus owner that it has lost permanent
        // focus.
        if (focusOwner != null)
          {
            // We can't cache the event queue, because of
            // bootstrapping issues.  We need to set the default
            // KeyboardFocusManager in EventQueue before the event
            // queue is started.
            EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
            if (focusOwner != permanentFocusOwner)
              q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, true));
            else
              q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, false));
          }

        if (focusOwner != permanentFocusOwner)
          {
            EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
            q.postEvent (new FocusEvent (permanentFocusOwner, FocusEvent.FOCUS_LOST, false));
          }
      }
  }

  /**
   * Retrieve the {@link Component} that has the permanent keyboard
   * focus, or null if the focus owner was not set by a thread in the
   * current {@link java.lang.ThreadGroup}.
   *
   * @return the keyboard focus owner or null
   */
  public Component getPermanentFocusOwner ()
  {
    return (Component) getObject (currentPermanentFocusOwners);
  }

  /**
   * Retrieve the {@link Component} that has the permanent keyboard
   * focus, regardless of whether or not it was set by a thread in the
   * current {@link java.lang.ThreadGroup}.
   *
   * @return the keyboard focus owner
   * @throws SecurityException if this is not the keyboard focus
   * manager associated with the current {@link java.lang.ThreadGroup}
   */
  protected Component getGlobalPermanentFocusOwner ()
  {
    return (Component) getGlobalObject (currentPermanentFocusOwners, true);
  }

  /**
   * Set the {@link Component} that will be returned by {@link
   * #getPermanentFocusOwner} (when it is called from the current
   * {@link java.lang.ThreadGroup}) and {@link
   * #getGlobalPermanentFocusOwner}.  This method does not actually
   * transfer the keyboard focus.
   *
   * @param focusOwner the Component to return from
   * getPermanentFocusOwner and getGlobalPermanentFocusOwner
   *
   * @see Component#requestFocus()
   * @see Component#requestFocusInWindow()
   */
  protected void setGlobalPermanentFocusOwner (Component focusOwner)
  {
    if (focusOwner == null || focusOwner.focusable)
      setGlobalObject (currentPermanentFocusOwners, focusOwner,
                       "permanentFocusOwner");
  }

  /**
   * Retrieve the {@link Window} that is or contains the keyboard
   * focus owner, or null if the focused window was not set by a
   * thread in the current {@link java.lang.ThreadGroup}.
   *
   * @return the focused window or null
   */
  public Window getFocusedWindow ()
  {
    return (Window) getObject (currentFocusedWindows);
  }

  /**
   * Retrieve the {@link Window} that is or contains the focus owner,
   * regardless of whether or not the {@link Window} was set focused
   * by a thread in the current {@link java.lang.ThreadGroup}.
   *
   * @return the focused window
   * @throws SecurityException if this is not the keyboard focus
   * manager associated with the current {@link java.lang.ThreadGroup}
   */
  protected Window getGlobalFocusedWindow ()
  {
    return (Window) getGlobalObject (currentFocusedWindows, true);
  }

  /**
   * Set the {@link Window} that will be returned by {@link
   * #getFocusedWindow} (when it is called from the current {@link
   * java.lang.ThreadGroup}) and {@link #getGlobalFocusedWindow}.
   * This method does not actually cause <code>window</code> to become
   * the focused {@link Window}.
   *
   * @param window the Window to return from getFocusedWindow and
   * getGlobalFocusedWindow
   */
  protected void setGlobalFocusedWindow (Window window)
  {
    if (window == null || window.focusable)
      setGlobalObject (currentFocusedWindows, window, "focusedWindow");
  }

  /**
   * Retrieve the active {@link Window}, or null if the active window
   * was not set by a thread in the current {@link
   * java.lang.ThreadGroup}.
   *
   * @return the active window or null
   */
  public Window getActiveWindow()
  {
    return (Window) getObject (currentActiveWindows);
  }

  /**
   * Retrieve the active {@link Window}, regardless of whether or not
   * the {@link Window} was made active by a thread in the current
   * {@link java.lang.ThreadGroup}.
   *
   * @return the active window
   * @throws SecurityException if this is not the keyboard focus
   * manager associated with the current {@link java.lang.ThreadGroup}
   */
  protected Window getGlobalActiveWindow()
  {
    return (Window) getGlobalObject (currentActiveWindows, true);
  }

  /**
   * Set the {@link Window} that will be returned by {@link
   * #getActiveWindow} (when it is called from the current {@link
   * java.lang.ThreadGroup}) and {@link #getGlobalActiveWindow}.  This
   * method does not actually cause <code>window</code> to be made
   * active.
   *
   * @param window the Window to return from getActiveWindow and
   * getGlobalActiveWindow
   */
  protected void setGlobalActiveWindow(Window window)
  {
    setGlobalObject (currentActiveWindows, window, "activeWindow");
  }

  /**
   * Retrieve the default {@link FocusTraversalPolicy}.
   * Focus-managing {@link Container}s use the returned object to
   * define their initial focus traversal policy.
   *
   * @return a non-null default FocusTraversalPolicy object
   */
  public FocusTraversalPolicy getDefaultFocusTraversalPolicy ()
  {
    if (defaultPolicy == null)
      defaultPolicy = new DefaultFocusTraversalPolicy ();
    return defaultPolicy;
  }

  /**
   * Set the {@link FocusTraversalPolicy} returned by {@link
   * #getDefaultFocusTraversalPolicy}.  Focus-managing {@link
   * Container}s created after this call will use policy as their
   * initial focus traversal policy.  Existing {@link Container}s'
   * focus traversal policies will not be affected by calls to this
   * method.
   *
   * @param policy the FocusTraversalPolicy that will be returned by
   * subsequent calls to getDefaultFocusTraversalPolicy
   * @throws IllegalArgumentException if policy is null
   */
  public void setDefaultFocusTraversalPolicy (FocusTraversalPolicy policy)
  {
    if (policy == null)
      throw new IllegalArgumentException ();
    firePropertyChange ("defaultFocusTraversalPolicy", defaultPolicy, policy);
    defaultPolicy = policy;
  }

  /**
   * Set the default {@link java.util.Set} of focus traversal keys for
   * one of the focus traversal directions.
   *
   * @param id focus traversal direction identifier
   * @param keystrokes set of AWTKeyStrokes
   *
   * @see #FORWARD_TRAVERSAL_KEYS
   * @see #BACKWARD_TRAVERSAL_KEYS
   * @see #UP_CYCLE_TRAVERSAL_KEYS
   * @see #DOWN_CYCLE_TRAVERSAL_KEYS
   */
  public void setDefaultFocusTraversalKeys (int id,
                                            Set<? extends AWTKeyStroke>
                                            keystrokes)
  {
    if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
        id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
      throw new IllegalArgumentException ();

    if (keystrokes == null)
      throw new IllegalArgumentException ();

    Set sa;
    Set sb;
    Set sc;
    String type;
    switch (id)
      {
      case FORWARD_TRAVERSAL_KEYS:
        sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
        sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
        sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
        type = "forwardDefaultFocusTraversalKeys";
        break;
      case BACKWARD_TRAVERSAL_KEYS:
        sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
        sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
        sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
        type = "backwardDefaultFocusTraversalKeys";
        break;
      case UP_CYCLE_TRAVERSAL_KEYS:
        sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
        sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
        sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
        type = "upCycleDefaultFocusTraversalKeys";
        break;
      case DOWN_CYCLE_TRAVERSAL_KEYS:
        sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
        sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
        sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
        type = "downCycleDefaultFocusTraversalKeys";
        break;
      default:
        throw new IllegalArgumentException ();
      }
    int i = keystrokes.size ();
    Iterator iter = keystrokes.iterator ();
    while (--i >= 0)
      {
        Object o = iter.next ();
        if (!(o instanceof AWTKeyStroke)
            || sa.contains (o) || sb.contains (o) || sc.contains (o)
            || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
          throw new IllegalArgumentException ();
      }
    keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
    firePropertyChange (type, defaultFocusKeys[id], keystrokes);
    defaultFocusKeys[id] = keystrokes;
  }

  /**
   * Retrieve the default {@link java.util.Set} of focus traversal
   * keys for one of the focus traversal directions.
   *
   * @param id focus traversal direction identifier
   *
   * @return the default set of AWTKeyStrokes
   *
   * @see #FORWARD_TRAVERSAL_KEYS
   * @see #BACKWARD_TRAVERSAL_KEYS
   * @see #UP_CYCLE_TRAVERSAL_KEYS
   * @see #DOWN_CYCLE_TRAVERSAL_KEYS
   */
  public Set<AWTKeyStroke> getDefaultFocusTraversalKeys (int id)
  {
    if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
      throw new IllegalArgumentException ();
    return defaultFocusKeys[id];
  }

  /**
   * Retrieve the current focus cycle root, or null if the focus owner
   * was not set by a thread in the current {@link
   * java.lang.ThreadGroup}.
   *
   * @return the current focus cycle root or null
   */
  public Container getCurrentFocusCycleRoot ()
  {
    return (Container) getObject (currentFocusCycleRoots);
  }

  /**
   * Retrieve the current focus cycle root, regardless of whether or
   * not it was made set by a thread in the current {@link
   * java.lang.ThreadGroup}.
   *
   * @return the current focus cycle root
   * @throws SecurityException if this is not the keyboard focus
   * manager associated with the current {@link java.lang.ThreadGroup}
   */
  protected Container getGlobalCurrentFocusCycleRoot ()
  {
    return (Container) getGlobalObject (currentFocusCycleRoots, true);
  }

  /**
   * Set the {@link Container} that will be returned by {@link
   * #getCurrentFocusCycleRoot} (when it is called from the current
   * {@link java.lang.ThreadGroup}) and {@link
   * #getGlobalCurrentFocusCycleRoot}.  This method does not actually
   * make <code>cycleRoot</code> the current focus cycle root.
   *
   * @param cycleRoot the focus cycle root to return from
   * getCurrentFocusCycleRoot and getGlobalCurrentFocusCycleRoot
   */
  public void setGlobalCurrentFocusCycleRoot (Container cycleRoot)
  {
    setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot");
  }

  /**
   * Registers the supplied property change listener for receiving
   * events caused by the following property changes:
   *
   * <ul>
   * <li>the current 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 default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
   * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
   * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
   * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
   * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
   * </ul>
   *
   * If the supplied listener is null, nothing occurs.
   *
   * @param l the new listener to register.
   * @see KeyboardFocusManager#addPropertyChangeListener(String, java.beans.PropertyChangeListener)
   */
  public void addPropertyChangeListener(PropertyChangeListener l)
  {
    if (l != null)
      propertyChangeSupport.addPropertyChangeListener(l);
  }

  /**
   * Removes the supplied property change listener from the list
   * of registered listeners.  If the supplied listener is null,
   * nothing occurs.
   *
   * @param l the listener to remove.
   */
  public void removePropertyChangeListener(PropertyChangeListener l)
  {
    if (l != null)
      propertyChangeSupport.removePropertyChangeListener(l);
  }

  /**
   * Returns the currently registered property change listeners
   * in array form.  The returned array is empty if no listeners are
   * currently registered.
   *
   * @return an array of registered property change listeners.
   */
  public PropertyChangeListener[] getPropertyChangeListeners()
  {
    return propertyChangeSupport.getPropertyChangeListeners();
  }

  /**
   * Registers a property change listener for receiving events relating
   * to a change to a specified property.  The supplied property name can be
   * either user-defined or one from the following list of properties
   * relevant to this class:
   *
   * <ul>
   * <li>the current 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 default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
   * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
   * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
   * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
   * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
   * </ul>
   *
   * Nothing occurs if a null listener is supplied.  null is regarded as a valid property name.
   *
   * @param name the name of the property to handle change events for.
   * @param l the listener to register for changes to the specified property.
   * @see KeyboardFocusManager#addPropertyChangeListener(java.beans.PropertyChangeListener)
   */
  public void addPropertyChangeListener(String name, PropertyChangeListener l)
  {
    if (l != null)
      propertyChangeSupport.addPropertyChangeListener(name, l);
  }

  /**
   * Removes the supplied property change listener registered for the
   * specified property from the list of registered listeners.  If the
   * supplied listener is null, nothing occurs.
   *
   * @param name the name of the property the listener is
   *        monitoring changes to.
   * @param l the listener to remove.
   */
  public void removePropertyChangeListener(String name,
                                           PropertyChangeListener l)
  {
    if (l != null)
      propertyChangeSupport.removePropertyChangeListener(name, l);
  }

  /**
   * Returns the currently registered property change listeners
   * in array form, which listen for changes to the supplied property.
   * The returned array is empty, if no listeners are currently registered
   * for events pertaining to the supplied property.
   *
   * @param name The property the returned listeners monitor for changes.
   * @return an array of registered property change listeners which
   *         listen for changes to the supplied property.
   */
  public PropertyChangeListener[] getPropertyChangeListeners(String name)
  {
    return propertyChangeSupport.getPropertyChangeListeners(name);
  }

  /**
   * Fires a property change event as a response to a change to
   * to the specified property.  The event is only fired if a
   * change has actually occurred (i.e. o and n are different).
   *
   * @param name The name of the property to which a change occurred.
   * @param o The old value of the property.
   * @param n The new value of the property.
   */
  protected void firePropertyChange(String name, Object o, Object n)
  {
    propertyChangeSupport.firePropertyChange(name, o, n);
  }

  /**
   * Registers a vetoable property change listener for receiving events
   * relating to the following properties:
   *
   * <ul>
   * <li>the current focus owner ("focusOwner")</li>
   * <li>the permanent focus owner ("permanentFocusOwner")</li>
   * <li>the focused window ("focusedWindow")</li>
   * <li>the active window ("activeWindow")</li>
   * </ul>
   *
   * Nothing occurs if a null listener is supplied.
   *
   * @param l the listener to register.
   * @see KeyboardFocusManager#addVetoableChangeListener(String, java.beans.VetoableChangeListener)
   */
  public void addVetoableChangeListener(VetoableChangeListener l)
  {
    if (l != null)
      vetoableChangeSupport.addVetoableChangeListener(l);
  }

  /**
   * Removes the supplied vetoable property change listener from
   * the list of registered listeners.  If the supplied listener
   * is null, nothing occurs.
   *
   * @param l the listener to remove.
   */
  public void removeVetoableChangeListener(VetoableChangeListener l)
  {
    if (l != null)
      vetoableChangeSupport.removeVetoableChangeListener(l);
  }

  /**
   * Returns the currently registered vetoable property change listeners
   * in array form.  The returned array is empty if no listeners are
   * currently registered.
   *
   * @return an array of registered vetoable property change listeners.
   * @since 1.4
   */
  public VetoableChangeListener[] getVetoableChangeListeners()
  {
    return vetoableChangeSupport.getVetoableChangeListeners();
  }

  /**
   * Registers a vetoable property change listener for receiving events relating
   * to a vetoable change to a specified property.  The supplied property name can be
   * either user-defined or one from the following list of properties
   * relevant to this class:
   *
   * <ul>
   * <li>the current focus owner ("focusOwner")</li>
   * <li>the permanent focus owner ("permanentFocusOwner")</li>
   * <li>the focused window ("focusedWindow")</li>
   * <li>the active window ("activeWindow")</li>
   * </ul>
   *
   * Nothing occurs if a null listener is supplied.  null is regarded as a valid property name.
   *
   * @param name the name of the property to handle change events for.
   * @param l the listener to register for changes to the specified property.
   * @see KeyboardFocusManager#addVetoableChangeListener(java.beans.VetoableChangeListener)
   */
  public void addVetoableChangeListener(String name, VetoableChangeListener l)
  {
    if (l != null)
      vetoableChangeSupport.addVetoableChangeListener(name, l);
  }

  /**
   * Removes the supplied vetoable property change listener registered
   * for the specified property from the list of registered listeners.
   * If the supplied listener is null, nothing occurs.
   *
   * @param name the name of the vetoable property the listener is
   *        monitoring changes to.
   * @param l the listener to remove.
   */
  public void removeVetoableChangeListener(String name,
                                           VetoableChangeListener l)
  {
    if (l != null)
      vetoableChangeSupport.removeVetoableChangeListener(name, l);
  }

  /**
   * Returns the currently registered vetoable property change listeners
   * in array form, which listen for changes to the supplied property.
   * The returned array is empty, if no listeners are currently registered
   * for events pertaining to the supplied property.
   *
   * @param name The property the returned listeners monitor for changes.
   * @return an array of registered property change listeners which
   *         listen for changes to the supplied property.
   * @since 1.4
   */
  public VetoableChangeListener[] getVetoableChangeListeners(String name)
  {
    return vetoableChangeSupport.getVetoableChangeListeners(name);
  }

  /**
   * Fires a property change event as a response to a vetoable change to
   * to the specified property.  The event is only fired if a
   * change has actually occurred (i.e. o and n are different).
   * In the event that the property change is vetoed, the following
   * occurs:
   *
   * <ol>
   * <li>
   * This method throws a <code>PropertyVetoException</code> to
   * the proposed change.
   * </li>
   * <li>
   * A new event is fired to reverse the previous change.
   * </li>
   * <li>
   * This method again throws a <code>PropertyVetoException</code>
   * in response to the reversion.
   * </li>
   * </ol>
   *
   * @param name The name of the property to which a change occurred.
   * @param o The old value of the property.
   * @param n The new value of the property.
   * @throws PropertyVetoException if one of the listeners vetos
   *         the change by throwing this exception.
   */
  protected void fireVetoableChange(String name, Object o, Object n)
    throws PropertyVetoException
  {
    vetoableChangeSupport.fireVetoableChange(name, o, n);
  }

  /**
   * Adds a key event dispatcher to the list of registered dispatchers.
   * When a key event is fired, each dispatcher's <code>dispatchKeyEvent</code>
   * method is called in the order that they were added, prior to the manager
   * dispatching the event itself.  Notifications halt when one of the
   * dispatchers returns true.
   * <br />
   * <br />
   * The same dispatcher can exist multiple times within the list
   * of registered dispatchers, and there is no limit on the length
   * of this list.  A null dispatcher is simply ignored.
   *
   * @param dispatcher The dispatcher to register.
   */
  public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
  {
    if (dispatcher != null)
      keyEventDispatchers.add(dispatcher);
  }

  /**
   * Removes the specified key event dispatcher from the list of
   * registered dispatchers.  The manager always dispatches events,
   * regardless of its existence within the list.  The manager
   * can be added and removed from the list, as with any other
   * dispatcher, but this does not affect its ability to dispatch
   * key events.  Non-existent and null dispatchers are simply ignored
   * by this method.
   *
   * @param dispatcher The dispatcher to remove.
   */
  public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
  {
    keyEventDispatchers.remove(dispatcher);
  }

  /**
   * Returns the currently registered key event dispatchers in <code>List</code>
   * form.  At present, this only includes dispatchers explicitly registered
   * via the <code>addKeyEventDispatcher()</code> method, but this behaviour
   * is subject to change and should not be depended on.  The manager itself
   * may be a member of the list, but only if explicitly registered.  If no
   * dispatchers have been registered, the list will be empty.
   *
   * @return A list of explicitly registered key event dispatchers.
   * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
   */
  protected List<KeyEventDispatcher> getKeyEventDispatchers ()
  {
    return (List<KeyEventDispatcher>) keyEventDispatchers.clone ();
  }

  /**
   * Adds a key event post processor to the list of registered post processors.
   * Post processors work in the same way as key event dispatchers, except
   * that they are invoked after the manager has dispatched the key event,
   * and not prior to this.  Each post processor's <code>postProcessKeyEvent</code>
   * method is called to see if any post processing needs to be performed.  THe
   * processors are called in the order in which they were added to the list,
   * and notifications continue until one returns true.  As with key event
   * dispatchers, the manager is implicitly called following this process,
   * regardless of whether or not it is present within the list.
   * <br />
   * <br />
   * The same post processor can exist multiple times within the list
   * of registered post processors, and there is no limit on the length
   * of this list.  A null post processor is simply ignored.
   *
   * @param postProcessor the post processor to register.
   * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
   */
  public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
  {
    if (postProcessor != null)
      keyEventPostProcessors.add (postProcessor);
  }

  /**
   * Removes the specified key event post processor from the list of
   * registered post processors.  The manager always post processes events,
   * regardless of its existence within the list.  The manager
   * can be added and removed from the list, as with any other
   * post processor, but this does not affect its ability to post process
   * key events.  Non-existent and null post processors are simply ignored
   * by this method.
   *
   * @param postProcessor the post processor to remove.
   */
  public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
  {
    keyEventPostProcessors.remove (postProcessor);
  }

  /**
   * Returns the currently registered key event post processors in <code>List</code>
   * form.  At present, this only includes post processors explicitly registered
   * via the <code>addKeyEventPostProcessor()</code> method, but this behaviour
   * is subject to change and should not be depended on.  The manager itself
   * may be a member of the list, but only if explicitly registered.  If no
   * post processors have been registered, the list will be empty.
   *
   * @return A list of explicitly registered key event post processors.
   * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor)
   */
  protected List<KeyEventPostProcessor> getKeyEventPostProcessors ()
  {
    return (List<KeyEventPostProcessor>) keyEventPostProcessors.clone ();
  }

  /**
   * The AWT event dispatcher uses this method to request that the manager
   * handle a particular event.  If the manager fails or refuses to
   * dispatch the supplied event (this method returns false), the
   * AWT event dispatcher will try to dispatch the event itself.
   * <br />
   * <br />
   * The manager is expected to handle all <code>FocusEvent</code>s
   * and <code>KeyEvent</code>s, and <code>WindowEvent</code>s
   * relating to the focus.  Dispatch is done with regard to the
   * the focus owner and the currently focused and active windows.
   * In handling the event, the source of the event may be overridden.
   * <br />
   * <br />
   * The actual dispatching is performed by calling
   * <code>redispatchEvent()</code>.  This avoids the infinite recursion
   * of dispatch requests which may occur if this method is called on
   * the target component.
   *
   * @param e the event to dispatch.
   * @return true if the event was dispatched.
   * @see KeyboardFocusManager#redispatchEvent(java.awt.Component, java.awt.AWTEvent)
   * @see KeyEvent
   * @see FocusEvent
   * @see WindowEvent
   */
  public abstract boolean dispatchEvent (AWTEvent e);

  /**
   * Handles redispatching of an event so that recursion of
   * dispatch requests does not occur.  Event dispatch methods
   * within this manager (<code>dispatchEvent()</code>) and
   * the key event dispatchers should use this method to handle
   * dispatching rather than the dispatch method of the target
   * component.
   * <br />
   * <br />
   * <strong>
   * This method is not intended for general consumption, and is
   * only for the use of the aforementioned classes.
   * </strong>
   *
   * @param target the target component to which the event is
   *        dispatched.
   * @param e the event to dispatch.
   */
  public final void redispatchEvent (Component target, AWTEvent e)
  {
    e.isFocusManagerEvent = true;
    target.dispatchEvent (e);
    e.isFocusManagerEvent = false;
  }

  /**
   * Attempts to dispatch key events for which no key event dispatcher
   * has so far succeeded.  This method is usually called by
   * <code>dispatchEvent()</code> following the sending of the key
   * event to any registered key event dispatchers.  If the key
   * event reaches this stage, none of the dispatchers returned
   * true.  This is, of course, always the case if there are no
   * registered dispatchers.
   * <br />
   * <br />
   * If this method also fails to handle the key event, then
   * false is returned to the caller.  In the case of
   * <code>dispatchEvent()</code>, the calling method may try
   * to handle the event itself or simply forward on the
   * false result to its caller.  When the event is dispatched
   * by this method, a true result is propogated through the
   * calling methods.
   *
   * @param e the key event to dispatch.
   * @return true if the event was dispatched successfully.
   */
  public abstract boolean dispatchKeyEvent (KeyEvent e);

  /**
   * Handles the post processing of key events.  By default,
   * this method will map unhandled key events to appropriate
   * <code>MenuShortcut</code>s.  The event is consumed
   * in the process and the shortcut is activated.  This
   * method is usually called by <code>dispatchKeyEvent</code>.
   *
   * @param e the key event to post process.
   * @return true by default, as the event was handled.
   */
  public abstract boolean postProcessKeyEvent (KeyEvent e);

  /**
   * Handles focus traversal operations for key events which
   * represent focus traversal keys in relation to the supplied
   * component.  The supplied component is assumed to have the
   * focus, whether it does so or not, and the operation is
   * carried out as appropriate, with this in mind.
   *
   * @param focused the component on which to perform focus traversal,
   *        on the assumption that this component has the focus.
   * @param e the possible focus traversal key event.
   */
  public abstract void processKeyEvent (Component focused, KeyEvent e);

  /**
   * Delays all key events following the specified timestamp until the
   * supplied component has focus.  The AWT calls this method when it is
   * determined that a focus change may occur within the native windowing
   * system.  Any key events which occur following the time specified by
   * after are delayed until a <code>FOCUS_GAINED</code> event is received
   * for the untilFocused component.  The manager is responsible for ensuring
   * this takes place.
   *
   * @param after the timestamp beyond which all key events are delayed until
   *        the supplied component gains focus.
   * @param untilFocused the component to wait on gaining focus.
   */
  protected abstract void enqueueKeyEvents (long after, Component untilFocused);

  /**
   * Removes the key event block specified by the supplied timestamp and component.
   * All delayed key events are released for normal dispatching following its
   * removal and subsequent key events that would have been blocked are now
   * immediately dispatched.  If the specified timestamp is below 0, then
   * the request with the oldest timestamp is removed.
   *
   * @param after the timestamp of the key event block to be removed, or a
   *        value smaller than 0 if the oldest is to be removed.
   * @param untilFocused the component of the key event block to be removed.
   */
  protected abstract void dequeueKeyEvents (long after, Component untilFocused);

  /**
   * Discards all key event blocks relating to focus requirements for
   * the supplied component, regardless of timestamp.
   *
   * @param comp the component of the key event block(s) to be removed.
   */
  protected abstract void discardKeyEvents (Component comp);

  /**
   * Moves the current focus to the next component following
   * comp, based on the current focus traversal policy.  By
   * default, only visible, displayable, accepted components
   * can receive focus.  <code>Canvas</code>es, <code>Panel</code>s,
   * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
   * <code>Window</code>s and lightweight components are judged
   * to be unacceptable by default.  See the
   * <code>DefaultFocusTraversalPolicy</code> for more details.
   *
   * @param comp the component prior to the one which will
   *        become the focus, following execution of this method.
   * @see DefaultFocusTraversalPolicy
   */
  public abstract void focusNextComponent(Component comp);

  /**
   * Moves the current focus to the previous component, prior to
   * comp, based on the current focus traversal policy.  By
   * default, only visible, displayable, accepted components
   * can receive focus.  <code>Canvas</code>es, <code>Panel</code>s,
   * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
   * <code>Window</code>s and lightweight components are judged
   * to be unacceptable by default.  See the
   * <code>DefaultFocusTraversalPolicy</code> for more details.
   *
   * @param comp the component following the one which will
   *        become the focus, following execution of this method.
   * @see DefaultFocusTraversalPolicy
   */
  public abstract void focusPreviousComponent(Component comp);

  /**
   * Moves the current focus upwards by one focus cycle.
   * Both the current focus owner and current focus cycle root
   * become the focus cycle root of the supplied component.
   * However, in the case of a <code>Window</code>, the default
   * focus component becomes the focus owner and the focus cycle
   * root is not changed.
   *
   * @param comp the component used as part of the focus traversal.
   */
  public abstract void upFocusCycle(Component comp);

  /**
   * Moves the current focus downwards by one focus cycle.
   * If the supplied container is a focus cycle root, then this
   * becomes the current focus cycle root and the focus goes
   * to the default component of the specified container.
   * Nothing happens for non-focus cycle root containers.
   *
   * @param cont the container used as part of the focus traversal.
   */
  public abstract void downFocusCycle(Container cont);

  /**
   * Moves the current focus to the next component, based on the
   * current focus traversal policy.  By default, only visible,
   * displayable, accepted component can receive focus.
   * <code>Canvas</code>es, <code>Panel</code>s,
   * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
   * <code>Window</code>s and lightweight components are judged
   * to be unacceptable by default.  See the
   * <code>DefaultFocusTraversalPolicy</code> for more details.
   *
   * @see DefaultFocusTraversalPolicy
   */
  public final void focusNextComponent()
  {
    focusNextComponent (null);
  }

  /**
   * Moves the current focus to the previous component, based on the
   * current focus traversal policy.  By default, only visible,
   * displayable, accepted component can receive focus.
   * <code>Canvas</code>es, <code>Panel</code>s,
   * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
   * <code>Window</code>s and lightweight components are judged
   * to be unacceptable by default.  See the
   * <code>DefaultFocusTraversalPolicy</code> for more details.
   *
   * @see DefaultFocusTraversalPolicy
   */
  public final void focusPreviousComponent()
  {
    focusPreviousComponent (null);
  }

  /**
   * Moves the current focus upwards by one focus cycle,
   * so that the new focus owner is the focus cycle root
   * of the current owner.  The current focus cycle root then
   * becomes the focus cycle root of the new focus owner.
   * However, in the case of the focus cycle root of the
   * current focus owner being a <code>Window</code>, the default
   * component of this window becomes the focus owner and the
   * focus cycle root is not changed.
   */
  public final void upFocusCycle()
  {
    upFocusCycle (null);
  }

  /**
   * Moves the current focus downwards by one focus cycle,
   * iff the current focus cycle root is a <code>Container</code>.
   * Usually, the new focus owner is set to the default component
   * of the container and the current focus cycle root is set
   * to the current focus owner.  Nothing occurs if the current
   * focus cycle root is not a container.
   */
  public final void downFocusCycle()
  {
    Component focusOwner = getGlobalFocusOwner ();
    if (focusOwner instanceof Container
        && ((Container) focusOwner).isFocusCycleRoot ())
      downFocusCycle ((Container) focusOwner);
  }

  /**
   * Retrieve an object from one of the global object {@link
   * java.util.Map}s, if the object was set by the a thread in the
   * current {@link java.lang.ThreadGroup}.  Otherwise, return null.
   *
   * @param globalMap one of the global object Maps
   *
   * @return a global object set by the current ThreadGroup, or null
   *
   * @see #getFocusOwner()
   * @see #getPermanentFocusOwner()
   * @see #getFocusedWindow()
   * @see #getActiveWindow()
   * @see #getCurrentFocusCycleRoot()
   */
  private Object getObject (Map globalMap)
  {
    ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
    return globalMap.get (currentGroup);
  }

  /**
   * Retrieve an object from one of the global object {@link
   * java.util.Map}s, regardless of whether or not the object was set
   * by a thread in the current {@link java.lang.ThreadGroup}.
   *
   * @param globalMap one of the global object Maps
   *
   * @return a global object set by the current ThreadGroup, or null
   *
   * @throws SecurityException if this is not the keyboard focus
   * manager associated with the current {@link java.lang.ThreadGroup}
   *
   * @see #getGlobalFocusOwner()
   * @see #getGlobalPermanentFocusOwner()
   * @see #getGlobalFocusedWindow()
   * @see #getGlobalActiveWindow()
   * @see #getGlobalCurrentFocusCycleRoot()
   */
  private Object getGlobalObject (Map globalMap, boolean checkThread)
  {
    if (checkThread)
      {
        ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
        KeyboardFocusManager managerForCallingThread =
         (KeyboardFocusManager) currentKeyboardFocusManagers.get(currentGroup);

        if (this != managerForCallingThread)
          throw new SecurityException ("Attempted to retrieve an object from a "
                                       + "keyboard focus manager that isn't "
                                + "associated with the current thread group.");
      }
    synchronized (globalMap)
      {
        Collection globalObjects = globalMap.values ();
        Iterator i = globalObjects.iterator ();
        Component globalObject;

        while (i.hasNext ())
          {
            globalObject = (Component) i.next ();
            if (globalObject != null)
              return globalObject;
          }
      }

    // No Object was found.
    return null;
  }

  /**
   * Set an object in one of the global object {@link java.util.Map}s,
   * that will be returned by subsequent calls to getGlobalObject on
   * the same {@link java.util.Map}.
   *
   * @param globalMap one of the global object Maps
   * @param newObject the object to set
   * @param property the property that will change
   *
   * @see #setGlobalFocusOwner(Component)
   * @see #setGlobalPermanentFocusOwner(Component)
   * @see #setGlobalFocusedWindow(Window)
   * @see #setGlobalActiveWindow(Window)
   * @see #setGlobalCurrentFocusCycleRoot(Container)
   */
  private void setGlobalObject (Map globalMap,
                                Object newObject,
                                String property)
  {
    synchronized (globalMap)
      {
        // Save old object.
        Object oldObject = getGlobalObject(globalMap, false);

        // Nullify old object.
        Collection threadGroups = globalMap.keySet ();
        Iterator i = threadGroups.iterator ();
        while (i.hasNext ())
          {
            ThreadGroup oldThreadGroup = (ThreadGroup) i.next ();
            if (globalMap.get (oldThreadGroup) != null)
              {
                globalMap.put (oldThreadGroup, null);
                // There should only be one object set at a time, so
                // we can short circuit.
                break;
              }
          }

        ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
        firePropertyChange (property, oldObject, newObject);
        try
          {
            fireVetoableChange (property, oldObject, newObject);
            // Set new object.
            globalMap.put (currentGroup, newObject);
          }
        catch (PropertyVetoException e)
          {
          }
      }
  }


  /**
   * Maps focus requests from heavyweight to lightweight components.
   */
  private static HashMap focusRequests = new HashMap();

  /**
   * Retargets focus events that come from the peer (which only know about
   * heavyweight components) to go to the correct lightweight component
   * if appropriate.
   *
   * @param ev the event to check
   *
   * @return the retargetted event
   */
  static AWTEvent retargetFocusEvent(AWTEvent ev)
  {
    if (ev instanceof FocusEvent)
      {
        FocusEvent fe = (FocusEvent) ev;
        Component target = fe.getComponent();
        if (focusRequests.containsKey(target))
          {
            Component lightweight = (Component) focusRequests.get(target);
            ev = new FocusEvent(lightweight, fe.id, fe.isTemporary());
            focusRequests.remove(target);
          }
      }
    return ev;
  }

  /**
   * Adds a lightweight focus request for a heavyweight component.
   *
   * @param heavyweight the heavyweight from which we will receive a focus
   *        event soon
   * @param lightweight the lightweight that ultimately receives the request
   */
  static void addLightweightFocusRequest(Component heavyweight,
                                         Component lightweight)
  {
    focusRequests.put(heavyweight, lightweight);
  }
}
