Save This Page
Home » openjdk-7 » java » awt » [javadoc | source]
    1   /*
    2    * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   package java.awt;
   26   
   27   import java.awt.event.FocusEvent;
   28   import java.awt.event.InputEvent;
   29   import java.awt.event.KeyEvent;
   30   import java.awt.event.WindowEvent;
   31   
   32   import java.awt.peer.KeyboardFocusManagerPeer;
   33   import java.awt.peer.LightweightPeer;
   34   
   35   import java.beans.PropertyChangeListener;
   36   import java.beans.PropertyChangeSupport;
   37   import java.beans.PropertyVetoException;
   38   import java.beans.VetoableChangeListener;
   39   import java.beans.VetoableChangeSupport;
   40   
   41   import java.lang.ref.WeakReference;
   42   
   43   import java.lang.reflect.Field;
   44   
   45   import java.security.AccessController;
   46   import java.security.PrivilegedAction;
   47   
   48   import java.util.Collections;
   49   import java.util.HashSet;
   50   import java.util.Iterator;
   51   import java.util.LinkedList;
   52   import java.util.Set;
   53   import java.util.StringTokenizer;
   54   import java.util.WeakHashMap;
   55   
   56   import java.util.logging.Level;
   57   import java.util.logging.Logger;
   58   
   59   import sun.awt.AppContext;
   60   import sun.awt.HeadlessToolkit;
   61   import sun.awt.SunToolkit;
   62   import sun.awt.CausedFocusEvent;
   63   import sun.awt.KeyboardFocusManagerPeerProvider;
   64   
   65   /**
   66    * The KeyboardFocusManager is responsible for managing the active and focused
   67    * Windows, and the current focus owner. The focus owner is defined as the
   68    * Component in an application that will typically receive all KeyEvents
   69    * generated by the user. The focused Window is the Window that is, or
   70    * contains, the focus owner. Only a Frame or a Dialog can be the active
   71    * Window. The native windowing system may denote the active Window or its
   72    * children with special decorations, such as a highlighted title bar. The
   73    * active Window is always either the focused Window, or the first Frame or
   74    * Dialog that is an owner of the focused Window.
   75    * <p>
   76    * The KeyboardFocusManager is both a centralized location for client code to
   77    * query for the focus owner and initiate focus changes, and an event
   78    * dispatcher for all FocusEvents, WindowEvents related to focus, and
   79    * KeyEvents.
   80    * <p>
   81    * Some browsers partition applets in different code bases into separate
   82    * contexts, and establish walls between these contexts. In such a scenario,
   83    * there will be one KeyboardFocusManager per context. Other browsers place all
   84    * applets into the same context, implying that there will be only a single,
   85    * global KeyboardFocusManager for all applets. This behavior is
   86    * implementation-dependent. Consult your browser's documentation for more
   87    * information. No matter how many contexts there may be, however, there can
   88    * never be more than one focus owner, focused Window, or active Window, per
   89    * ClassLoader.
   90    * <p>
   91    * Please see
   92    * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
   93    * How to Use the Focus Subsystem</a>,
   94    * a section in <em>The Java Tutorial</em>, and the
   95    * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
   96    * for more information.
   97    *
   98    * @author David Mendenhall
   99    *
  100    * @see Window
  101    * @see Frame
  102    * @see Dialog
  103    * @see java.awt.event.FocusEvent
  104    * @see java.awt.event.WindowEvent
  105    * @see java.awt.event.KeyEvent
  106    * @since 1.4
  107    */
  108   public abstract class KeyboardFocusManager
  109       implements KeyEventDispatcher, KeyEventPostProcessor
  110   {
  111   
  112       // Shared focus engine logger
  113       private static final Logger focusLog = Logger.getLogger("java.awt.focus.KeyboardFocusManager");
  114   
  115       static {
  116           /* ensure that the necessary native libraries are loaded */
  117           Toolkit.loadLibraries();
  118           if (!GraphicsEnvironment.isHeadless()) {
  119               initIDs();
  120           }
  121       }
  122   
  123       transient KeyboardFocusManagerPeer peer;
  124   
  125       /**
  126        * Initialize JNI field and method IDs
  127        */
  128       private static native void initIDs();
  129   
  130       private static final Logger log = Logger.getLogger("java.awt.KeyboardFocusManager");
  131   
  132       /**
  133        * The identifier for the Forward focus traversal keys.
  134        *
  135        * @see #setDefaultFocusTraversalKeys
  136        * @see #getDefaultFocusTraversalKeys
  137        * @see Component#setFocusTraversalKeys
  138        * @see Component#getFocusTraversalKeys
  139        */
  140       public static final int FORWARD_TRAVERSAL_KEYS = 0;
  141   
  142       /**
  143        * The identifier for the Backward focus traversal keys.
  144        *
  145        * @see #setDefaultFocusTraversalKeys
  146        * @see #getDefaultFocusTraversalKeys
  147        * @see Component#setFocusTraversalKeys
  148        * @see Component#getFocusTraversalKeys
  149        */
  150       public static final int BACKWARD_TRAVERSAL_KEYS = 1;
  151   
  152       /**
  153        * The identifier for the Up Cycle focus traversal keys.
  154        *
  155        * @see #setDefaultFocusTraversalKeys
  156        * @see #getDefaultFocusTraversalKeys
  157        * @see Component#setFocusTraversalKeys
  158        * @see Component#getFocusTraversalKeys
  159        */
  160       public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
  161   
  162       /**
  163        * The identifier for the Down Cycle focus traversal keys.
  164        *
  165        * @see #setDefaultFocusTraversalKeys
  166        * @see #getDefaultFocusTraversalKeys
  167        * @see Component#setFocusTraversalKeys
  168        * @see Component#getFocusTraversalKeys
  169        */
  170       public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
  171   
  172       static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
  173   
  174       /**
  175        * Returns the current KeyboardFocusManager instance for the calling
  176        * thread's context.
  177        *
  178        * @return this thread's context's KeyboardFocusManager
  179        * @see #setCurrentKeyboardFocusManager
  180        */
  181       public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
  182           return getCurrentKeyboardFocusManager(AppContext.getAppContext());
  183       }
  184   
  185       synchronized static KeyboardFocusManager
  186           getCurrentKeyboardFocusManager(AppContext appcontext)
  187       {
  188           KeyboardFocusManager manager = (KeyboardFocusManager)
  189               appcontext.get(KeyboardFocusManager.class);
  190           if (manager == null) {
  191               manager = new DefaultKeyboardFocusManager();
  192               appcontext.put(KeyboardFocusManager.class, manager);
  193           }
  194           return manager;
  195       }
  196   
  197       /**
  198        * Sets the current KeyboardFocusManager instance for the calling thread's
  199        * context. If null is specified, then the current KeyboardFocusManager
  200        * is replaced with a new instance of DefaultKeyboardFocusManager.
  201        * <p>
  202        * If a SecurityManager is installed, the calling thread must be granted
  203        * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
  204        * the current KeyboardFocusManager. If this permission is not granted,
  205        * this method will throw a SecurityException, and the current
  206        * KeyboardFocusManager will be unchanged.
  207        *
  208        * @param newManager the new KeyboardFocusManager for this thread's context
  209        * @see #getCurrentKeyboardFocusManager
  210        * @see DefaultKeyboardFocusManager
  211        * @throws SecurityException if the calling thread does not have permission
  212        *         to replace the current KeyboardFocusManager
  213        */
  214       public static void setCurrentKeyboardFocusManager(
  215           KeyboardFocusManager newManager) throws SecurityException
  216       {
  217           SecurityManager security = System.getSecurityManager();
  218           if (security != null) {
  219               if (replaceKeyboardFocusManagerPermission == null) {
  220                   replaceKeyboardFocusManagerPermission =
  221                       new AWTPermission("replaceKeyboardFocusManager");
  222               }
  223               security.
  224                   checkPermission(replaceKeyboardFocusManagerPermission);
  225           }
  226   
  227           KeyboardFocusManager oldManager = null;
  228   
  229           synchronized (KeyboardFocusManager.class) {
  230               AppContext appcontext = AppContext.getAppContext();
  231   
  232               if (newManager != null) {
  233                   oldManager = getCurrentKeyboardFocusManager(appcontext);
  234   
  235                   appcontext.put(KeyboardFocusManager.class, newManager);
  236               } else {
  237                   oldManager = getCurrentKeyboardFocusManager(appcontext);
  238                   appcontext.remove(KeyboardFocusManager.class);
  239               }
  240           }
  241   
  242           if (oldManager != null) {
  243               oldManager.firePropertyChange("managingFocus",
  244                                             Boolean.TRUE,
  245                                             Boolean.FALSE);
  246           }
  247           if (newManager != null) {
  248               newManager.firePropertyChange("managingFocus",
  249                                             Boolean.FALSE,
  250                                             Boolean.TRUE);
  251           }
  252       }
  253   
  254       /**
  255        * The Component in an application that will typically receive all
  256        * KeyEvents generated by the user.
  257        */
  258       private static Component focusOwner;
  259   
  260       /**
  261        * The Component in an application that will regain focus when an
  262        * outstanding temporary focus transfer has completed, or the focus owner,
  263        * if no outstanding temporary transfer exists.
  264        */
  265       private static Component permanentFocusOwner;
  266   
  267       /**
  268        * The Window which is, or contains, the focus owner.
  269        */
  270       private static Window focusedWindow;
  271   
  272       /**
  273        * Only a Frame or a Dialog can be the active Window. The native windowing
  274        * system may denote the active Window with a special decoration, such as a
  275        * highlighted title bar. The active Window is always either the focused
  276        * Window, or the first Frame or Dialog which is an owner of the focused
  277        * Window.
  278        */
  279       private static Window activeWindow;
  280   
  281       /**
  282        * The default FocusTraversalPolicy for all Windows that have no policy of
  283        * their own set. If those Windows have focus-cycle-root children that have
  284        * no keyboard-traversal policy of their own, then those children will also
  285        * inherit this policy (as will, recursively, their focus-cycle-root
  286        * children).
  287        */
  288       private FocusTraversalPolicy defaultPolicy =
  289           new DefaultFocusTraversalPolicy();
  290   
  291       /**
  292        * The bound property names of each focus traversal key.
  293        */
  294       private static final String[] defaultFocusTraversalKeyPropertyNames = {
  295           "forwardDefaultFocusTraversalKeys",
  296           "backwardDefaultFocusTraversalKeys",
  297           "upCycleDefaultFocusTraversalKeys",
  298           "downCycleDefaultFocusTraversalKeys"
  299       };
  300   
  301       /**
  302        * The default strokes for initializing the default focus traversal keys.
  303        */
  304       private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
  305           {
  306               AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false),
  307               AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false),
  308           },
  309           {
  310               AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false),
  311               AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
  312                                            InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK,
  313                                            false),
  314           },
  315           {},
  316           {},
  317         };
  318       /**
  319        * The default focus traversal keys. Each array of traversal keys will be
  320        * in effect on all Windows that have no such array of their own explicitly
  321        * set. Each array will also be inherited, recursively, by any child
  322        * Component of those Windows that has no such array of its own explicitly
  323        * set.
  324        */
  325       private Set[] defaultFocusTraversalKeys = new Set[4];
  326   
  327       /**
  328        * The current focus cycle root. If the focus owner is itself a focus cycle
  329        * root, then it may be ambiguous as to which Components represent the next
  330        * and previous Components to focus during normal focus traversal. In that
  331        * case, the current focus cycle root is used to differentiate among the
  332        * possibilities.
  333        */
  334       private static Container currentFocusCycleRoot;
  335   
  336       /**
  337        * A description of any VetoableChangeListeners which have been registered.
  338        */
  339       private VetoableChangeSupport vetoableSupport;
  340   
  341       /**
  342        * A description of any PropertyChangeListeners which have been registered.
  343        */
  344       private PropertyChangeSupport changeSupport;
  345   
  346       /**
  347        * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
  348        * include this KeyboardFocusManager unless it was explicitly re-registered
  349        * via a call to <code>addKeyEventDispatcher</code>. If no other
  350        * KeyEventDispatchers are registered, this field may be null or refer to
  351        * a List of length 0.
  352        */
  353       private java.util.LinkedList keyEventDispatchers;
  354   
  355       /**
  356        * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
  357        * not include this KeyboardFocusManager unless it was explicitly
  358        * re-registered via a call to <code>addKeyEventPostProcessor</code>.
  359        * If no other KeyEventPostProcessors are registered, this field may be
  360        * null or refer to a List of length 0.
  361        */
  362       private java.util.LinkedList keyEventPostProcessors;
  363   
  364       /**
  365        * Maps Windows to those Windows' most recent focus owners.
  366        */
  367       private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
  368   
  369       /**
  370        * Error String for initializing SecurityExceptions.
  371        */
  372       private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
  373   
  374       /**
  375        * We cache the permission used to verify that the calling thread is
  376        * permitted to access the global focus state.
  377        */
  378       private static AWTPermission replaceKeyboardFocusManagerPermission;
  379   
  380       /*
  381        * SequencedEvent which is currently dispatched in AppContext.
  382        */
  383       transient SequencedEvent currentSequencedEvent = null;
  384   
  385       final void setCurrentSequencedEvent(SequencedEvent current) {
  386           synchronized (SequencedEvent.class) {
  387               assert(current == null || currentSequencedEvent == null);
  388               currentSequencedEvent = current;
  389           }
  390       }
  391   
  392       final SequencedEvent getCurrentSequencedEvent() {
  393           synchronized (SequencedEvent.class) {
  394               return currentSequencedEvent;
  395           }
  396       }
  397   
  398       static Set initFocusTraversalKeysSet(String value, Set targetSet) {
  399           StringTokenizer tokens = new StringTokenizer(value, ",");
  400           while (tokens.hasMoreTokens()) {
  401               targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken()));
  402           }
  403           return (targetSet.isEmpty())
  404               ? Collections.EMPTY_SET
  405               : Collections.unmodifiableSet(targetSet);
  406       }
  407   
  408       /**
  409        * Initializes a KeyboardFocusManager.
  410        */
  411       public KeyboardFocusManager() {
  412           for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
  413               Set work_set = new HashSet();
  414               for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
  415                   work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
  416               }
  417               defaultFocusTraversalKeys[i] = (work_set.isEmpty())
  418                   ? Collections.EMPTY_SET
  419                   : Collections.unmodifiableSet(work_set);
  420           }
  421           initPeer();
  422       }
  423   
  424       private void initPeer() {
  425           Toolkit tk = Toolkit.getDefaultToolkit();
  426           KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk;
  427           peer = peerProvider.createKeyboardFocusManagerPeer(this);
  428       }
  429   
  430       /**
  431        * Returns the focus owner, if the focus owner is in the same context as
  432        * the calling thread. The focus owner is defined as the Component in an
  433        * application that will typically receive all KeyEvents generated by the
  434        * user. KeyEvents which map to the focus owner's focus traversal keys will
  435        * not be delivered if focus traversal keys are enabled for the focus
  436        * owner. In addition, KeyEventDispatchers may retarget or consume
  437        * KeyEvents before they reach the focus owner.
  438        *
  439        * @return the focus owner, or null if the focus owner is not a member of
  440        *         the calling thread's context
  441        * @see #getGlobalFocusOwner
  442        * @see #setGlobalFocusOwner
  443        */
  444       public Component getFocusOwner() {
  445           synchronized (KeyboardFocusManager.class) {
  446               if (focusOwner == null) {
  447                   return null;
  448               }
  449   
  450               return (focusOwner.appContext == AppContext.getAppContext())
  451                   ? focusOwner
  452                   : null;
  453           }
  454       }
  455   
  456       /**
  457        * Returns the focus owner, even if the calling thread is in a different
  458        * context than the focus owner. The focus owner is defined as the
  459        * Component in an application that will typically receive all KeyEvents
  460        * generated by the user. KeyEvents which map to the focus owner's focus
  461        * traversal keys will not be delivered if focus traversal keys are enabled
  462        * for the focus owner. In addition, KeyEventDispatchers may retarget or
  463        * consume KeyEvents before they reach the focus owner.
  464        * <p>
  465        * This method will throw a SecurityException if this KeyboardFocusManager
  466        * is not the current KeyboardFocusManager for the calling thread's
  467        * context.
  468        *
  469        * @return the focus owner
  470        * @see #getFocusOwner
  471        * @see #setGlobalFocusOwner
  472        * @throws SecurityException if this KeyboardFocusManager is not the
  473        *         current KeyboardFocusManager for the calling thread's context
  474        */
  475       protected Component getGlobalFocusOwner() throws SecurityException {
  476           synchronized (KeyboardFocusManager.class) {
  477               if (this == getCurrentKeyboardFocusManager()) {
  478                   return focusOwner;
  479               } else {
  480                   if (focusLog.isLoggable(Level.FINER)) {
  481                       focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
  482                   }
  483                   throw new SecurityException(notPrivileged);
  484               }
  485           }
  486       }
  487   
  488       /**
  489        * Sets the focus owner. The operation will be cancelled if the Component
  490        * is not focusable. The focus owner is defined as the Component in an
  491        * application that will typically receive all KeyEvents generated by the
  492        * user. KeyEvents which map to the focus owner's focus traversal keys will
  493        * not be delivered if focus traversal keys are enabled for the focus
  494        * owner. In addition, KeyEventDispatchers may retarget or consume
  495        * KeyEvents before they reach the focus owner.
  496        * <p>
  497        * This method does not actually set the focus to the specified Component.
  498        * It merely stores the value to be subsequently returned by
  499        * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
  500        * or <code>Component.requestFocusInWindow()</code> to change the focus
  501        * owner, subject to platform limitations.
  502        *
  503        * @param focusOwner the focus owner
  504        * @see #getFocusOwner
  505        * @see #getGlobalFocusOwner
  506        * @see Component#requestFocus()
  507        * @see Component#requestFocusInWindow()
  508        * @see Component#isFocusable
  509        * @beaninfo
  510        *       bound: true
  511        */
  512       protected void setGlobalFocusOwner(Component focusOwner) {
  513           Component oldFocusOwner = null;
  514           boolean shouldFire = false;
  515   
  516           if (focusOwner == null || focusOwner.isFocusable()) {
  517               synchronized (KeyboardFocusManager.class) {
  518                   oldFocusOwner = getFocusOwner();
  519   
  520                   try {
  521                       fireVetoableChange("focusOwner", oldFocusOwner,
  522                                          focusOwner);
  523                   } catch (PropertyVetoException e) {
  524                       // rejected
  525                       return;
  526                   }
  527   
  528                   KeyboardFocusManager.focusOwner = focusOwner;
  529   
  530                   if (focusOwner != null &&
  531                       (getCurrentFocusCycleRoot() == null ||
  532                        !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot())))
  533                   {
  534                       Container rootAncestor =
  535                           focusOwner.getFocusCycleRootAncestor();
  536                       if (rootAncestor == null && (focusOwner instanceof Window))
  537                       {
  538                           rootAncestor = (Container)focusOwner;
  539                       }
  540                       if (rootAncestor != null) {
  541                           setGlobalCurrentFocusCycleRoot(rootAncestor);
  542                       }
  543                   }
  544   
  545                   shouldFire = true;
  546               }
  547           }
  548   
  549           if (shouldFire) {
  550               firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
  551           }
  552       }
  553   
  554       /**
  555        * Clears the global focus owner at both the Java and native levels. If
  556        * there exists a focus owner, that Component will receive a permanent
  557        * FOCUS_LOST event. After this operation completes, the native windowing
  558        * system will discard all user-generated KeyEvents until the user selects
  559        * a new Component to receive focus, or a Component is given focus
  560        * explicitly via a call to <code>requestFocus()</code>. This operation
  561        * does not change the focused or active Windows.
  562        *
  563        * @see Component#requestFocus()
  564        * @see java.awt.event.FocusEvent#FOCUS_LOST
  565        */
  566       public void clearGlobalFocusOwner() {
  567           if (!GraphicsEnvironment.isHeadless()) {
  568               // Toolkit must be fully initialized, otherwise
  569               // _clearGlobalFocusOwner will crash or throw an exception
  570               Toolkit.getDefaultToolkit();
  571   
  572               _clearGlobalFocusOwner();
  573           }
  574       }
  575       private void _clearGlobalFocusOwner() {
  576           Window activeWindow = markClearGlobalFocusOwner();
  577           peer.clearGlobalFocusOwner(activeWindow);
  578       }
  579   
  580       Component getNativeFocusOwner() {
  581           return peer.getCurrentFocusOwner();
  582       }
  583   
  584       void setNativeFocusOwner(Component comp) {
  585           if (focusLog.isLoggable(Level.FINEST)) {
  586               focusLog.log(Level.FINEST, "Calling peer {0} setCurrentFocusOwner for {1}",
  587                            new Object[] {peer, comp});
  588           }
  589           peer.setCurrentFocusOwner(comp);
  590       }
  591   
  592       Window getNativeFocusedWindow() {
  593           return peer.getCurrentFocusedWindow();
  594       }
  595   
  596       /**
  597        * Returns the permanent focus owner, if the permanent focus owner is in
  598        * the same context as the calling thread. The permanent focus owner is
  599        * defined as the last Component in an application to receive a permanent
  600        * FOCUS_GAINED event. The focus owner and permanent focus owner are
  601        * equivalent unless a temporary focus change is currently in effect. In
  602        * such a situation, the permanent focus owner will again be the focus
  603        * owner when the temporary focus change ends.
  604        *
  605        * @return the permanent focus owner, or null if the permanent focus owner
  606        *         is not a member of the calling thread's context
  607        * @see #getGlobalPermanentFocusOwner
  608        * @see #setGlobalPermanentFocusOwner
  609        */
  610       public Component getPermanentFocusOwner() {
  611           synchronized (KeyboardFocusManager.class) {
  612               if (permanentFocusOwner == null) {
  613                   return null;
  614               }
  615   
  616               return (permanentFocusOwner.appContext ==
  617                       AppContext.getAppContext())
  618                   ? permanentFocusOwner
  619                   : null;
  620           }
  621       }
  622   
  623       /**
  624        * Returns the permanent focus owner, even if the calling thread is in a
  625        * different context than the permanent focus owner. The permanent focus
  626        * owner is defined as the last Component in an application to receive a
  627        * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
  628        * are equivalent unless a temporary focus change is currently in effect.
  629        * In such a situation, the permanent focus owner will again be the focus
  630        * owner when the temporary focus change ends.
  631        * <p>
  632        * This method will throw a SecurityException if this KeyboardFocusManager
  633        * is not the current KeyboardFocusManager for the calling thread's
  634        * context.
  635        *
  636        * @return the permanent focus owner
  637        * @see #getPermanentFocusOwner
  638        * @see #setGlobalPermanentFocusOwner
  639        * @throws SecurityException if this KeyboardFocusManager is not the
  640        *         current KeyboardFocusManager for the calling thread's context
  641        */
  642       protected Component getGlobalPermanentFocusOwner()
  643           throws SecurityException
  644       {
  645           synchronized (KeyboardFocusManager.class) {
  646               if (this == getCurrentKeyboardFocusManager()) {
  647                   return permanentFocusOwner;
  648               } else {
  649                   if (focusLog.isLoggable(Level.FINER)) {
  650                       focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
  651                   }
  652                   throw new SecurityException(notPrivileged);
  653               }
  654           }
  655       }
  656   
  657       /**
  658        * Sets the permanent focus owner. The operation will be cancelled if the
  659        * Component is not focusable. The permanent focus owner is defined as the
  660        * last Component in an application to receive a permanent FOCUS_GAINED
  661        * event. The focus owner and permanent focus owner are equivalent unless
  662        * a temporary focus change is currently in effect. In such a situation,
  663        * the permanent focus owner will again be the focus owner when the
  664        * temporary focus change ends.
  665        * <p>
  666        * This method does not actually set the focus to the specified Component.
  667        * It merely stores the value to be subsequently returned by
  668        * <code>getPermanentFocusOwner()</code>. Use
  669        * <code>Component.requestFocus()</code> or
  670        * <code>Component.requestFocusInWindow()</code> to change the focus owner,
  671        * subject to platform limitations.
  672        *
  673        * @param permanentFocusOwner the permanent focus owner
  674        * @see #getPermanentFocusOwner
  675        * @see #getGlobalPermanentFocusOwner
  676        * @see Component#requestFocus()
  677        * @see Component#requestFocusInWindow()
  678        * @see Component#isFocusable
  679        * @beaninfo
  680        *       bound: true
  681        */
  682       protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner)
  683       {
  684           Component oldPermanentFocusOwner = null;
  685           boolean shouldFire = false;
  686   
  687           if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
  688               synchronized (KeyboardFocusManager.class) {
  689                   oldPermanentFocusOwner = getPermanentFocusOwner();
  690   
  691                   try {
  692                       fireVetoableChange("permanentFocusOwner",
  693                                          oldPermanentFocusOwner,
  694                                          permanentFocusOwner);
  695                   } catch (PropertyVetoException e) {
  696                       // rejected
  697                       return;
  698                   }
  699   
  700                   KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
  701   
  702                   KeyboardFocusManager.
  703                       setMostRecentFocusOwner(permanentFocusOwner);
  704   
  705                   shouldFire = true;
  706               }
  707           }
  708   
  709           if (shouldFire) {
  710               firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
  711                                  permanentFocusOwner);
  712           }
  713       }
  714   
  715       /**
  716        * Returns the focused Window, if the focused Window is in the same context
  717        * as the calling thread. The focused Window is the Window that is or
  718        * contains the focus owner.
  719        *
  720        * @return the focused Window, or null if the focused Window is not a
  721        *         member of the calling thread's context
  722        * @see #getGlobalFocusedWindow
  723        * @see #setGlobalFocusedWindow
  724        */
  725       public Window getFocusedWindow() {
  726           synchronized (KeyboardFocusManager.class) {
  727               if (focusedWindow == null) {
  728                   return null;
  729               }
  730   
  731               return (focusedWindow.appContext == AppContext.getAppContext())
  732                   ? focusedWindow
  733                   : null;
  734           }
  735       }
  736   
  737       /**
  738        * Returns the focused Window, even if the calling thread is in a different
  739        * context than the focused Window. The focused Window is the Window that
  740        * is or contains the focus owner.
  741        * <p>
  742        * This method will throw a SecurityException if this KeyboardFocusManager
  743        * is not the current KeyboardFocusManager for the calling thread's
  744        * context.
  745        *
  746        * @return the focused Window
  747        * @see #getFocusedWindow
  748        * @see #setGlobalFocusedWindow
  749        * @throws SecurityException if this KeyboardFocusManager is not the
  750        *         current KeyboardFocusManager for the calling thread's context
  751        */
  752       protected Window getGlobalFocusedWindow() throws SecurityException {
  753           synchronized (KeyboardFocusManager.class) {
  754               if (this == getCurrentKeyboardFocusManager()) {
  755                  return focusedWindow;
  756               } else {
  757                   if (focusLog.isLoggable(Level.FINER)) {
  758                       focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
  759                   }
  760                   throw new SecurityException(notPrivileged);
  761               }
  762           }
  763       }
  764   
  765       /**
  766        * Sets the focused Window. The focused Window is the Window that is or
  767        * contains the focus owner. The operation will be cancelled if the
  768        * specified Window to focus is not a focusable Window.
  769        * <p>
  770        * This method does not actually change the focused Window as far as the
  771        * native windowing system is concerned. It merely stores the value to be
  772        * subsequently returned by <code>getFocusedWindow()</code>. Use
  773        * <code>Component.requestFocus()</code> or
  774        * <code>Component.requestFocusInWindow()</code> to change the focused
  775        * Window, subject to platform limitations.
  776        *
  777        * @param focusedWindow the focused Window
  778        * @see #getFocusedWindow
  779        * @see #getGlobalFocusedWindow
  780        * @see Component#requestFocus()
  781        * @see Component#requestFocusInWindow()
  782        * @see Window#isFocusableWindow
  783        * @beaninfo
  784        *       bound: true
  785        */
  786       protected void setGlobalFocusedWindow(Window focusedWindow) {
  787           Window oldFocusedWindow = null;
  788           boolean shouldFire = false;
  789   
  790           if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
  791               synchronized (KeyboardFocusManager.class) {
  792                   oldFocusedWindow = getFocusedWindow();
  793   
  794                   try {
  795                       fireVetoableChange("focusedWindow", oldFocusedWindow,
  796                                          focusedWindow);
  797                   } catch (PropertyVetoException e) {
  798                       // rejected
  799                       return;
  800                   }
  801   
  802                   KeyboardFocusManager.focusedWindow = focusedWindow;
  803                   shouldFire = true;
  804               }
  805           }
  806   
  807           if (shouldFire) {
  808               firePropertyChange("focusedWindow", oldFocusedWindow,
  809                                  focusedWindow);
  810           }
  811       }
  812   
  813       /**
  814        * Returns the active Window, if the active Window is in the same context
  815        * as the calling thread. Only a Frame or a Dialog can be the active
  816        * Window. The native windowing system may denote the active Window or its
  817        * children with special decorations, such as a highlighted title bar.
  818        * The active Window is always either the focused Window, or the first
  819        * Frame or Dialog that is an owner of the focused Window.
  820        *
  821        * @return the active Window, or null if the active Window is not a member
  822        *         of the calling thread's context
  823        * @see #getGlobalActiveWindow
  824        * @see #setGlobalActiveWindow
  825        */
  826       public Window getActiveWindow() {
  827           synchronized (KeyboardFocusManager.class) {
  828               if (activeWindow == null) {
  829                   return null;
  830               }
  831   
  832               return (activeWindow.appContext == AppContext.getAppContext())
  833                   ? activeWindow
  834                   : null;
  835           }
  836       }
  837   
  838       /**
  839        * Returns the active Window, even if the calling thread is in a different
  840        * context than the active Window. Only a Frame or a Dialog can be the
  841        * active Window. The native windowing system may denote the active Window
  842        * or its children with special decorations, such as a highlighted title
  843        * bar. The active Window is always either the focused Window, or the first
  844        * Frame or Dialog that is an owner of the focused Window.
  845        * <p>
  846        * This method will throw a SecurityException if this KeyboardFocusManager
  847        * is not the current KeyboardFocusManager for the calling thread's
  848        * context.
  849        *
  850        * @return the active Window
  851        * @see #getActiveWindow
  852        * @see #setGlobalActiveWindow
  853        * @throws SecurityException if this KeyboardFocusManager is not the
  854        *         current KeyboardFocusManager for the calling thread's context
  855        */
  856       protected Window getGlobalActiveWindow() throws SecurityException {
  857           synchronized (KeyboardFocusManager.class) {
  858               if (this == getCurrentKeyboardFocusManager()) {
  859                  return activeWindow;
  860               } else {
  861                   if (focusLog.isLoggable(Level.FINER)) {
  862                       focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
  863                   }
  864                   throw new SecurityException(notPrivileged);
  865               }
  866           }
  867       }
  868   
  869       /**
  870        * Sets the active Window. Only a Frame or a Dialog can be the active
  871        * Window. The native windowing system may denote the active Window or its
  872        * children with special decorations, such as a highlighted title bar. The
  873        * active Window is always either the focused Window, or the first Frame or
  874        * Dialog that is an owner of the focused Window.
  875        * <p>
  876        * This method does not actually change the active Window as far as the
  877        * native windowing system is concerned. It merely stores the value to be
  878        * subsequently returned by <code>getActiveWindow()</code>. Use
  879        * <code>Component.requestFocus()</code> or
  880        * <code>Component.requestFocusInWindow()</code>to change the active
  881        * Window, subject to platform limitations.
  882        *
  883        * @param activeWindow the active Window
  884        * @see #getActiveWindow
  885        * @see #getGlobalActiveWindow
  886        * @see Component#requestFocus()
  887        * @see Component#requestFocusInWindow()
  888        * @beaninfo
  889        *       bound: true
  890        */
  891       protected void setGlobalActiveWindow(Window activeWindow) {
  892           Window oldActiveWindow;
  893           synchronized (KeyboardFocusManager.class) {
  894               oldActiveWindow = getActiveWindow();
  895               if (focusLog.isLoggable(Level.FINER)) {
  896                   focusLog.log(Level.FINER, "Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
  897               }
  898   
  899               try {
  900                   fireVetoableChange("activeWindow", oldActiveWindow,
  901                                      activeWindow);
  902               } catch (PropertyVetoException e) {
  903                   // rejected
  904                   return;
  905               }
  906   
  907               KeyboardFocusManager.activeWindow = activeWindow;
  908           }
  909   
  910           firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
  911       }
  912   
  913       /**
  914        * Returns the default FocusTraversalPolicy. Top-level components
  915        * use this value on their creation to initialize their own focus traversal
  916        * policy by explicit call to Container.setFocusTraversalPolicy.
  917        *
  918        * @return the default FocusTraversalPolicy. null will never be returned.
  919        * @see #setDefaultFocusTraversalPolicy
  920        * @see Container#setFocusTraversalPolicy
  921        * @see Container#getFocusTraversalPolicy
  922        */
  923       public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
  924           return defaultPolicy;
  925       }
  926   
  927       /**
  928        * Sets the default FocusTraversalPolicy. Top-level components
  929        * use this value on their creation to initialize their own focus traversal
  930        * policy by explicit call to Container.setFocusTraversalPolicy.
  931        * Note: this call doesn't affect already created components as they have
  932        * their policy initialized. Only new components will use this policy as
  933        * their default policy.
  934        *
  935        * @param defaultPolicy the new, default FocusTraversalPolicy
  936        * @see #getDefaultFocusTraversalPolicy
  937        * @see Container#setFocusTraversalPolicy
  938        * @see Container#getFocusTraversalPolicy
  939        * @throws IllegalArgumentException if defaultPolicy is null
  940        * @beaninfo
  941        *       bound: true
  942        */
  943       public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy
  944                                                  defaultPolicy) {
  945           if (defaultPolicy == null) {
  946               throw new IllegalArgumentException("default focus traversal policy cannot be null");
  947           }
  948   
  949           FocusTraversalPolicy oldPolicy;
  950   
  951           synchronized (this) {
  952               oldPolicy = this.defaultPolicy;
  953               this.defaultPolicy = defaultPolicy;
  954           }
  955   
  956           firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
  957                              defaultPolicy);
  958       }
  959   
  960       /**
  961        * Sets the default focus traversal keys for a given traversal operation.
  962        * This traversal key <code>Set</code> will be in effect on all
  963        * <code>Window</code>s that have no such <code>Set</code> of
  964        * their own explicitly defined. This <code>Set</code> will also be
  965        * inherited, recursively, by any child <code>Component</code> of
  966        * those <code>Windows</code> that has
  967        * no such <code>Set</code> of its own explicitly defined.
  968        * <p>
  969        * The default values for the default focus traversal keys are
  970        * implementation-dependent. Sun recommends that all implementations for a
  971        * particular native platform use the same default values. The
  972        * recommendations for Windows and Unix are listed below. These
  973        * recommendations are used in the Sun AWT implementations.
  974        *
  975        * <table border=1 summary="Recommended default values for focus traversal keys">
  976        * <tr>
  977        *    <th>Identifier</th>
  978        *    <th>Meaning</th>
  979        *    <th>Default</th>
  980        * </tr>
  981        * <tr>
  982        *    <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
  983        *    <td>Normal forward keyboard traversal</td>
  984        *    <td><code>TAB</code> on <code>KEY_PRESSED</code>,
  985        *        <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
  986        * </tr>
  987        * <tr>
  988        *    <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
  989        *    <td>Normal reverse keyboard traversal</td>
  990        *    <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
  991        *        <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
  992        * </tr>
  993        * <tr>
  994        *    <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
  995        *    <td>Go up one focus traversal cycle</td>
  996        *    <td>none</td>
  997        * </tr>
  998        * <tr>
  999        *    <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
 1000        *    <td>Go down one focus traversal cycle</td>
 1001        *    <td>none</td>
 1002        * </tr>
 1003        * </table>
 1004        *
 1005        * To disable a traversal key, use an empty <code>Set</code>;
 1006        * <code>Collections.EMPTY_SET</code> is recommended.
 1007        * <p>
 1008        * Using the <code>AWTKeyStroke</code> API, client code can
 1009        * specify on which of two
 1010        * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
 1011        * <code>KEY_RELEASED</code>, the focus traversal operation will
 1012        * occur. Regardless of which <code>KeyEvent</code> is specified,
 1013        * however, all <code>KeyEvent</code>s related to the focus
 1014        * traversal key, including the associated <code>KEY_TYPED</code>
 1015        * event, will be consumed, and will not be dispatched
 1016        * to any <code>Component</code>. It is a runtime error to
 1017        * specify a <code>KEY_TYPED</code> event as
 1018        * mapping to a focus traversal operation, or to map the same event to
 1019        * multiple default focus traversal operations.
 1020        *
 1021        * @param id one of
 1022        *        <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
 1023        *        <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
 1024        *        <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
 1025        *        <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
 1026        * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
 1027        *        specified operation
 1028        * @see #getDefaultFocusTraversalKeys
 1029        * @see Component#setFocusTraversalKeys
 1030        * @see Component#getFocusTraversalKeys
 1031        * @throws IllegalArgumentException if id is not one of
 1032        *         <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
 1033        *         <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
 1034        *         <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
 1035        *         <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
 1036        *         or if keystrokes is <code>null</code>,
 1037        *         or if keystrokes contains <code>null</code>,
 1038        *         or if any <code>Object</code> in
 1039        *         keystrokes is not an <code>AWTKeyStroke</code>,
 1040        *         or if any keystroke
 1041        *         represents a <code>KEY_TYPED</code> event,
 1042        *         or if any keystroke already maps
 1043        *         to another default focus traversal operation
 1044        * @beaninfo
 1045        *       bound: true
 1046        */
 1047       public void
 1048           setDefaultFocusTraversalKeys(int id,
 1049                                        Set<? extends AWTKeyStroke> keystrokes)
 1050       {
 1051           if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
 1052               throw new IllegalArgumentException("invalid focus traversal key identifier");
 1053           }
 1054           if (keystrokes == null) {
 1055               throw new IllegalArgumentException("cannot set null Set of default focus traversal keys");
 1056           }
 1057   
 1058           Set oldKeys;
 1059   
 1060           synchronized (this) {
 1061               for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) {
 1062                   Object obj = iter.next();
 1063   
 1064                   if (obj == null) {
 1065                       throw new IllegalArgumentException("cannot set null focus traversal key");
 1066                   }
 1067   
 1068                   // Fix for 6195831:
 1069                   //According to javadoc this method should throw IAE instead of ClassCastException
 1070                   if (!(obj instanceof AWTKeyStroke)) {
 1071                       throw new IllegalArgumentException("object is expected to be AWTKeyStroke");
 1072                   }
 1073                   AWTKeyStroke keystroke = (AWTKeyStroke)obj;
 1074   
 1075                   if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
 1076                       throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
 1077                   }
 1078   
 1079                   // Check to see if key already maps to another traversal
 1080                   // operation
 1081                   for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
 1082                       if (i == id) {
 1083                           continue;
 1084                       }
 1085   
 1086                       if (defaultFocusTraversalKeys[i].contains(keystroke)) {
 1087                           throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
 1088                       }
 1089                   }
 1090               }
 1091   
 1092               oldKeys = defaultFocusTraversalKeys[id];
 1093               defaultFocusTraversalKeys[id] =
 1094                   Collections.unmodifiableSet(new HashSet(keystrokes));
 1095           }
 1096   
 1097           firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
 1098                              oldKeys, keystrokes);
 1099       }
 1100   
 1101       /**
 1102        * Returns a Set of default focus traversal keys for a given traversal
 1103        * operation. This traversal key Set will be in effect on all Windows that
 1104        * have no such Set of their own explicitly defined. This Set will also be
 1105        * inherited, recursively, by any child Component of those Windows that has
 1106        * no such Set of its own explicitly defined. (See
 1107        * <code>setDefaultFocusTraversalKeys</code> for a full description of each
 1108        * operation.)
 1109        *
 1110        * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 1111        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 1112        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 1113        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 1114        * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
 1115        *         for the specified operation; the <code>Set</code>
 1116        *         will be unmodifiable, and may be empty; <code>null</code>
 1117        *         will never be returned
 1118        * @see #setDefaultFocusTraversalKeys
 1119        * @see Component#setFocusTraversalKeys
 1120        * @see Component#getFocusTraversalKeys
 1121        * @throws IllegalArgumentException if id is not one of
 1122        *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 1123        *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 1124        *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 1125        *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 1126        */
 1127       public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
 1128           if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
 1129               throw new IllegalArgumentException("invalid focus traversal key identifier");
 1130           }
 1131   
 1132           // Okay to return Set directly because it is an unmodifiable view
 1133           return defaultFocusTraversalKeys[id];
 1134       }
 1135   
 1136       /**
 1137        * Returns the current focus cycle root, if the current focus cycle root is
 1138        * in the same context as the calling thread. If the focus owner is itself
 1139        * a focus cycle root, then it may be ambiguous as to which Components
 1140        * represent the next and previous Components to focus during normal focus
 1141        * traversal. In that case, the current focus cycle root is used to
 1142        * differentiate among the possibilities.
 1143        * <p>
 1144        * This method is intended to be used only by KeyboardFocusManagers and
 1145        * focus implementations. It is not for general client use.
 1146        *
 1147        * @return the current focus cycle root, or null if the current focus cycle
 1148        *         root is not a member of the calling thread's context
 1149        * @see #getGlobalCurrentFocusCycleRoot
 1150        * @see #setGlobalCurrentFocusCycleRoot
 1151        */
 1152       public Container getCurrentFocusCycleRoot() {
 1153           synchronized (KeyboardFocusManager.class) {
 1154               if (currentFocusCycleRoot == null) {
 1155                   return null;
 1156               }
 1157   
 1158               return (currentFocusCycleRoot.appContext ==
 1159                       AppContext.getAppContext())
 1160                   ? currentFocusCycleRoot
 1161                   : null;
 1162           }
 1163       }
 1164   
 1165       /**
 1166        * Returns the current focus cycle root, even if the calling thread is in a
 1167        * different context than the current focus cycle root. If the focus owner
 1168        * is itself a focus cycle root, then it may be ambiguous as to which
 1169        * Components represent the next and previous Components to focus during
 1170        * normal focus traversal. In that case, the current focus cycle root is
 1171        * used to differentiate among the possibilities.
 1172        * <p>
 1173        * This method will throw a SecurityException if this KeyboardFocusManager
 1174        * is not the current KeyboardFocusManager for the calling thread's
 1175        * context.
 1176        *
 1177        * @return the current focus cycle root, or null if the current focus cycle
 1178        *         root is not a member of the calling thread's context
 1179        * @see #getCurrentFocusCycleRoot
 1180        * @see #setGlobalCurrentFocusCycleRoot
 1181        * @throws SecurityException if this KeyboardFocusManager is not the
 1182        *         current KeyboardFocusManager for the calling thread's context
 1183        */
 1184       protected Container getGlobalCurrentFocusCycleRoot()
 1185           throws SecurityException
 1186       {
 1187           synchronized (KeyboardFocusManager.class) {
 1188               if (this == getCurrentKeyboardFocusManager()) {
 1189                   return currentFocusCycleRoot;
 1190               } else {
 1191                   if (focusLog.isLoggable(Level.FINER)) {
 1192                       focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
 1193                   }
 1194                   throw new SecurityException(notPrivileged);
 1195               }
 1196           }
 1197       }
 1198   
 1199       /**
 1200        * Sets the current focus cycle root. If the focus owner is itself a focus
 1201        * cycle root, then it may be ambiguous as to which Components represent
 1202        * the next and previous Components to focus during normal focus traversal.
 1203        * In that case, the current focus cycle root is used to differentiate
 1204        * among the possibilities.
 1205        * <p>
 1206        * This method is intended to be used only by KeyboardFocusManagers and
 1207        * focus implementations. It is not for general client use.
 1208        *
 1209        * @param newFocusCycleRoot the new focus cycle root
 1210        * @see #getCurrentFocusCycleRoot
 1211        * @see #getGlobalCurrentFocusCycleRoot
 1212        * @beaninfo
 1213        *       bound: true
 1214        */
 1215       public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
 1216           Container oldFocusCycleRoot;
 1217   
 1218           synchronized (KeyboardFocusManager.class) {
 1219               oldFocusCycleRoot  = getCurrentFocusCycleRoot();
 1220               currentFocusCycleRoot = newFocusCycleRoot;
 1221           }
 1222   
 1223           firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
 1224                              newFocusCycleRoot);
 1225       }
 1226   
 1227       /**
 1228        * Adds a PropertyChangeListener to the listener list. The listener is
 1229        * registered for all bound properties of this class, including the
 1230        * following:
 1231        * <ul>
 1232        *    <li>whether the KeyboardFocusManager is currently managing focus
 1233        *        for this application or applet's browser context
 1234        *        ("managingFocus")</li>
 1235        *    <li>the focus owner ("focusOwner")</li>
 1236        *    <li>the permanent focus owner ("permanentFocusOwner")</li>
 1237        *    <li>the focused Window ("focusedWindow")</li>
 1238        *    <li>the active Window ("activeWindow")</li>
 1239        *    <li>the default focus traversal policy
 1240        *        ("defaultFocusTraversalPolicy")</li>
 1241        *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
 1242        *        ("forwardDefaultFocusTraversalKeys")</li>
 1243        *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
 1244        *        ("backwardDefaultFocusTraversalKeys")</li>
 1245        *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
 1246        *        ("upCycleDefaultFocusTraversalKeys")</li>
 1247        *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
 1248        *        ("downCycleDefaultFocusTraversalKeys")</li>
 1249        *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
 1250        * </ul>
 1251        * If listener is null, no exception is thrown and no action is performed.
 1252        *
 1253        * @param listener the PropertyChangeListener to be added
 1254        * @see #removePropertyChangeListener
 1255        * @see #getPropertyChangeListeners
 1256        * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1257        */
 1258       public void addPropertyChangeListener(PropertyChangeListener listener) {
 1259           if (listener != null) {
 1260               synchronized (this) {
 1261                   if (changeSupport == null) {
 1262                       changeSupport = new PropertyChangeSupport(this);
 1263                   }
 1264                   changeSupport.addPropertyChangeListener(listener);
 1265               }
 1266           }
 1267       }
 1268   
 1269       /**
 1270        * Removes a PropertyChangeListener from the listener list. This method
 1271        * should be used to remove the PropertyChangeListeners that were
 1272        * registered for all bound properties of this class.
 1273        * <p>
 1274        * If listener is null, no exception is thrown and no action is performed.
 1275        *
 1276        * @param listener the PropertyChangeListener to be removed
 1277        * @see #addPropertyChangeListener
 1278        * @see #getPropertyChangeListeners
 1279        * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1280        */
 1281       public void removePropertyChangeListener(PropertyChangeListener listener) {
 1282           if (listener != null) {
 1283               synchronized (this) {
 1284                   if (changeSupport != null) {
 1285                       changeSupport.removePropertyChangeListener(listener);
 1286                   }
 1287               }
 1288           }
 1289       }
 1290   
 1291       /**
 1292        * Returns an array of all the property change listeners
 1293        * registered on this keyboard focus manager.
 1294        *
 1295        * @return all of this keyboard focus manager's
 1296        *         <code>PropertyChangeListener</code>s
 1297        *         or an empty array if no property change
 1298        *         listeners are currently registered
 1299        *
 1300        * @see #addPropertyChangeListener
 1301        * @see #removePropertyChangeListener
 1302        * @see #getPropertyChangeListeners(java.lang.String)
 1303        * @since 1.4
 1304        */
 1305       public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
 1306           if (changeSupport == null) {
 1307               changeSupport = new PropertyChangeSupport(this);
 1308           }
 1309           return changeSupport.getPropertyChangeListeners();
 1310       }
 1311   
 1312       /**
 1313        * Adds a PropertyChangeListener to the listener list for a specific
 1314        * property. The specified property may be user-defined, or one of the
 1315        * following:
 1316        * <ul>
 1317        *    <li>whether the KeyboardFocusManager is currently managing focus
 1318        *        for this application or applet's browser context
 1319        *        ("managingFocus")</li>
 1320        *    <li>the focus owner ("focusOwner")</li>
 1321        *    <li>the permanent focus owner ("permanentFocusOwner")</li>
 1322        *    <li>the focused Window ("focusedWindow")</li>
 1323        *    <li>the active Window ("activeWindow")</li>
 1324        *    <li>the default focus traversal policy
 1325        *        ("defaultFocusTraversalPolicy")</li>
 1326        *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
 1327        *        ("forwardDefaultFocusTraversalKeys")</li>
 1328        *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
 1329        *        ("backwardDefaultFocusTraversalKeys")</li>
 1330        *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
 1331        *        ("upCycleDefaultFocusTraversalKeys")</li>
 1332        *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
 1333        *        ("downCycleDefaultFocusTraversalKeys")</li>
 1334        *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
 1335        * </ul>
 1336        * If listener is null, no exception is thrown and no action is performed.
 1337        *
 1338        * @param propertyName one of the property names listed above
 1339        * @param listener the PropertyChangeListener to be added
 1340        * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
 1341        * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1342        * @see #getPropertyChangeListeners(java.lang.String)
 1343        */
 1344       public void addPropertyChangeListener(String propertyName,
 1345                                             PropertyChangeListener listener) {
 1346           if (listener != null) {
 1347               synchronized (this) {
 1348                   if (changeSupport == null) {
 1349                       changeSupport = new PropertyChangeSupport(this);
 1350                   }
 1351                   changeSupport.addPropertyChangeListener(propertyName,
 1352                                                           listener);
 1353               }
 1354           }
 1355       }
 1356   
 1357       /**
 1358        * Removes a PropertyChangeListener from the listener list for a specific
 1359        * property. This method should be used to remove PropertyChangeListeners
 1360        * that were registered for a specific bound property.
 1361        * <p>
 1362        * If listener is null, no exception is thrown and no action is performed.
 1363        *
 1364        * @param propertyName a valid property name
 1365        * @param listener the PropertyChangeListener to be removed
 1366        * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1367        * @see #getPropertyChangeListeners(java.lang.String)
 1368        * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
 1369        */
 1370       public void removePropertyChangeListener(String propertyName,
 1371                                                PropertyChangeListener listener) {
 1372           if (listener != null) {
 1373               synchronized (this) {
 1374                   if (changeSupport != null) {
 1375                       changeSupport.removePropertyChangeListener(propertyName,
 1376                                                                  listener);
 1377                   }
 1378               }
 1379           }
 1380       }
 1381   
 1382       /**
 1383        * Returns an array of all the <code>PropertyChangeListener</code>s
 1384        * associated with the named property.
 1385        *
 1386        * @return all of the <code>PropertyChangeListener</code>s associated with
 1387        *         the named property or an empty array if no such listeners have
 1388        *         been added.
 1389        *
 1390        * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1391        * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1392        * @since 1.4
 1393        */
 1394       public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
 1395           if (changeSupport == null) {
 1396               changeSupport = new PropertyChangeSupport(this);
 1397           }
 1398           return changeSupport.getPropertyChangeListeners(propertyName);
 1399       }
 1400   
 1401       /**
 1402        * Fires a PropertyChangeEvent in response to a change in a bound property.
 1403        * The event will be delivered to all registered PropertyChangeListeners.
 1404        * No event will be delivered if oldValue and newValue are the same.
 1405        *
 1406        * @param propertyName the name of the property that has changed
 1407        * @param oldValue the property's previous value
 1408        * @param newValue the property's new value
 1409        */
 1410       protected void firePropertyChange(String propertyName, Object oldValue,
 1411                                         Object newValue)
 1412       {
 1413           if (oldValue == newValue) {
 1414               return;
 1415           }
 1416           PropertyChangeSupport changeSupport = this.changeSupport;
 1417           if (changeSupport != null) {
 1418               changeSupport.firePropertyChange(propertyName, oldValue, newValue);
 1419           }
 1420       }
 1421   
 1422       /**
 1423        * Adds a VetoableChangeListener to the listener list. The listener is
 1424        * registered for all vetoable properties of this class, including the
 1425        * following:
 1426        * <ul>
 1427        *    <li>the focus owner ("focusOwner")</li>
 1428        *    <li>the permanent focus owner ("permanentFocusOwner")</li>
 1429        *    <li>the focused Window ("focusedWindow")</li>
 1430        *    <li>the active Window ("activeWindow")</li>
 1431        * </ul>
 1432        * If listener is null, no exception is thrown and no action is performed.
 1433        *
 1434        * @param listener the VetoableChangeListener to be added
 1435        * @see #removeVetoableChangeListener
 1436        * @see #getVetoableChangeListeners
 1437        * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
 1438        */
 1439       public void addVetoableChangeListener(VetoableChangeListener listener) {
 1440           if (listener != null) {
 1441               synchronized (this) {
 1442                   if (vetoableSupport == null) {
 1443                       vetoableSupport =
 1444                           new VetoableChangeSupport(this);
 1445                   }
 1446                   vetoableSupport.addVetoableChangeListener(listener);
 1447               }
 1448           }
 1449       }
 1450   
 1451       /**
 1452        * Removes a VetoableChangeListener from the listener list. This method
 1453        * should be used to remove the VetoableChangeListeners that were
 1454        * registered for all vetoable properties of this class.
 1455        * <p>
 1456        * If listener is null, no exception is thrown and no action is performed.
 1457        *
 1458        * @param listener the VetoableChangeListener to be removed
 1459        * @see #addVetoableChangeListener
 1460        * @see #getVetoableChangeListeners
 1461        * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
 1462        */
 1463       public void removeVetoableChangeListener(VetoableChangeListener listener) {
 1464           if (listener != null) {
 1465               synchronized (this) {
 1466                   if (vetoableSupport != null) {
 1467                       vetoableSupport.removeVetoableChangeListener(listener);
 1468                   }
 1469               }
 1470           }
 1471       }
 1472   
 1473       /**
 1474        * Returns an array of all the vetoable change listeners
 1475        * registered on this keyboard focus manager.
 1476        *
 1477        * @return all of this keyboard focus manager's
 1478        *         <code>VetoableChangeListener</code>s
 1479        *         or an empty array if no vetoable change
 1480        *         listeners are currently registered
 1481        *
 1482        * @see #addVetoableChangeListener
 1483        * @see #removeVetoableChangeListener
 1484        * @see #getVetoableChangeListeners(java.lang.String)
 1485        * @since 1.4
 1486        */
 1487       public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
 1488           if (vetoableSupport == null) {
 1489               vetoableSupport = new VetoableChangeSupport(this);
 1490           }
 1491           return vetoableSupport.getVetoableChangeListeners();
 1492       }
 1493   
 1494       /**
 1495        * Adds a VetoableChangeListener to the listener list for a specific
 1496        * property. The specified property may be user-defined, or one of the
 1497        * following:
 1498        * <ul>
 1499        *    <li>the focus owner ("focusOwner")</li>
 1500        *    <li>the permanent focus owner ("permanentFocusOwner")</li>
 1501        *    <li>the focused Window ("focusedWindow")</li>
 1502        *    <li>the active Window ("activeWindow")</li>
 1503        * </ul>
 1504        * If listener is null, no exception is thrown and no action is performed.
 1505        *
 1506        * @param propertyName one of the property names listed above
 1507        * @param listener the VetoableChangeListener to be added
 1508        * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
 1509        * @see #removeVetoableChangeListener
 1510        * @see #getVetoableChangeListeners
 1511        */
 1512       public void addVetoableChangeListener(String propertyName,
 1513                                             VetoableChangeListener listener) {
 1514           if (listener != null) {
 1515               synchronized (this) {
 1516                   if (vetoableSupport == null) {
 1517                       vetoableSupport =
 1518                           new VetoableChangeSupport(this);
 1519                   }
 1520                   vetoableSupport.addVetoableChangeListener(propertyName,
 1521                                                             listener);
 1522               }
 1523           }
 1524       }
 1525   
 1526       /**
 1527        * Removes a VetoableChangeListener from the listener list for a specific
 1528        * property. This method should be used to remove VetoableChangeListeners
 1529        * that were registered for a specific bound property.
 1530        * <p>
 1531        * If listener is null, no exception is thrown and no action is performed.
 1532        *
 1533        * @param propertyName a valid property name
 1534        * @param listener the VetoableChangeListener to be removed
 1535        * @see #addVetoableChangeListener
 1536        * @see #getVetoableChangeListeners
 1537        * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
 1538        */
 1539       public void removeVetoableChangeListener(String propertyName,
 1540                                                VetoableChangeListener listener) {
 1541           if (listener != null) {
 1542               synchronized (this) {
 1543                   if (vetoableSupport != null) {
 1544                       vetoableSupport.removeVetoableChangeListener(propertyName,
 1545                                                                    listener);
 1546                   }
 1547               }
 1548           }
 1549       }
 1550   
 1551       /**
 1552        * Returns an array of all the <code>VetoableChangeListener</code>s
 1553        * associated with the named property.
 1554        *
 1555        * @return all of the <code>VetoableChangeListener</code>s associated with
 1556        *         the named property or an empty array if no such listeners have
 1557        *         been added.
 1558        *
 1559        * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
 1560        * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
 1561        * @see #getVetoableChangeListeners
 1562        * @since 1.4
 1563        */
 1564       public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
 1565           if (vetoableSupport == null) {
 1566               vetoableSupport = new VetoableChangeSupport(this);
 1567           }
 1568           return vetoableSupport.getVetoableChangeListeners(propertyName);
 1569       }
 1570   
 1571       /**
 1572        * Fires a PropertyChangeEvent in response to a change in a vetoable
 1573        * property. The event will be delivered to all registered
 1574        * VetoableChangeListeners. If a VetoableChangeListener throws a
 1575        * PropertyVetoException, a new event is fired reverting all
 1576        * VetoableChangeListeners to the old value and the exception is then
 1577        * rethrown. No event will be delivered if oldValue and newValue are the
 1578        * same.
 1579        *
 1580        * @param propertyName the name of the property that has changed
 1581        * @param oldValue the property's previous value
 1582        * @param newValue the property's new value
 1583        * @throws java.beans.PropertyVetoException if a
 1584        *         <code>VetoableChangeListener</code> threw
 1585        *         <code>PropertyVetoException</code>
 1586        */
 1587       protected void fireVetoableChange(String propertyName, Object oldValue,
 1588                                         Object newValue)
 1589           throws PropertyVetoException
 1590       {
 1591           if (oldValue == newValue) {
 1592               return;
 1593           }
 1594           VetoableChangeSupport vetoableSupport =
 1595               this.vetoableSupport;
 1596           if (vetoableSupport != null) {
 1597               vetoableSupport.fireVetoableChange(propertyName, oldValue,
 1598                                                  newValue);
 1599           }
 1600       }
 1601   
 1602       /**
 1603        * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
 1604        * chain. This KeyboardFocusManager will request that each
 1605        * KeyEventDispatcher dispatch KeyEvents generated by the user before
 1606        * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
 1607        * notified in the order in which they were added. Notifications will halt
 1608        * as soon as one KeyEventDispatcher returns <code>true</code> from its
 1609        * <code>dispatchKeyEvent</code> method. There is no limit to the total
 1610        * number of KeyEventDispatchers which can be added, nor to the number of
 1611        * times which a particular KeyEventDispatcher instance can be added.
 1612        * <p>
 1613        * If a null dispatcher is specified, no action is taken and no exception
 1614        * is thrown.
 1615        * <p>
 1616        * In a multithreaded application, {@link KeyEventDispatcher} behaves
 1617        * the same as other AWT listeners.  See
 1618        * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1619        * >AWT Threading Issues</a> for more details.
 1620        *
 1621        * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
 1622        * @see #removeKeyEventDispatcher
 1623        */
 1624       public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
 1625           if (dispatcher != null) {
 1626               synchronized (this) {
 1627                   if (keyEventDispatchers == null) {
 1628                       keyEventDispatchers = new java.util.LinkedList();
 1629                   }
 1630                   keyEventDispatchers.add(dispatcher);
 1631               }
 1632           }
 1633       }
 1634   
 1635       /**
 1636        * Removes a KeyEventDispatcher which was previously added to this
 1637        * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
 1638        * cannot itself be removed, unless it was explicitly re-registered via a
 1639        * call to <code>addKeyEventDispatcher</code>.
 1640        * <p>
 1641        * If a null dispatcher is specified, if the specified dispatcher is not
 1642        * in the dispatcher chain, or if this KeyboardFocusManager is specified
 1643        * without having been explicitly re-registered, no action is taken and no
 1644        * exception is thrown.
 1645        * <p>
 1646        * In a multithreaded application, {@link KeyEventDispatcher} behaves
 1647        * the same as other AWT listeners.  See
 1648        * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1649        * >AWT Threading Issues</a> for more details.
 1650        *
 1651        * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
 1652        *        chain
 1653        * @see #addKeyEventDispatcher
 1654        */
 1655       public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
 1656           if (dispatcher != null) {
 1657               synchronized (this) {
 1658                   if (keyEventDispatchers != null) {
 1659                       keyEventDispatchers.remove(dispatcher);
 1660                   }
 1661               }
 1662           }
 1663       }
 1664   
 1665       /**
 1666        * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
 1667        * The List will not include this KeyboardFocusManager unless it was
 1668        * explicitly re-registered via a call to
 1669        * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
 1670        * registered, implementations are free to return null or a List of length
 1671        * 0. Client code should not assume one behavior over another, nor should
 1672        * it assume that the behavior, once established, will not change.
 1673        *
 1674        * @return a possibly null or empty List of KeyEventDispatchers
 1675        * @see #addKeyEventDispatcher
 1676        * @see #removeKeyEventDispatcher
 1677        */
 1678       protected synchronized java.util.List<KeyEventDispatcher>
 1679           getKeyEventDispatchers()
 1680       {
 1681           return (keyEventDispatchers != null)
 1682               ? (java.util.List)keyEventDispatchers.clone()
 1683               : null;
 1684       }
 1685   
 1686       /**
 1687        * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
 1688        * processor chain. After a KeyEvent has been dispatched to and handled by
 1689        * its target, KeyboardFocusManager will request that each
 1690        * KeyEventPostProcessor perform any necessary post-processing as part
 1691        * of the KeyEvent's final resolution. KeyEventPostProcessors
 1692        * will be notified in the order in which they were added; the current
 1693        * KeyboardFocusManager will be notified last. Notifications will halt
 1694        * as soon as one KeyEventPostProcessor returns <code>true</code> from its
 1695        * <code>postProcessKeyEvent</code> method. There is no limit to the the
 1696        * total number of KeyEventPostProcessors that can be added, nor to the
 1697        * number of times that a particular KeyEventPostProcessor instance can be
 1698        * added.
 1699        * <p>
 1700        * If a null post-processor is specified, no action is taken and no
 1701        * exception is thrown.
 1702        * <p>
 1703        * In a multithreaded application, {@link KeyEventPostProcessor} behaves
 1704        * the same as other AWT listeners.  See
 1705        * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1706        * >AWT Threading Issues</a> for more details.
 1707        *
 1708        * @param processor the KeyEventPostProcessor to add to the post-processor
 1709        *        chain
 1710        * @see #removeKeyEventPostProcessor
 1711        */
 1712       public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
 1713           if (processor != null) {
 1714               synchronized (this) {
 1715                   if (keyEventPostProcessors == null) {
 1716                       keyEventPostProcessors = new java.util.LinkedList();
 1717                   }
 1718                   keyEventPostProcessors.add(processor);
 1719               }
 1720           }
 1721       }
 1722   
 1723   
 1724       /**
 1725        * Removes a previously added KeyEventPostProcessor from this
 1726        * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
 1727        * cannot itself be entirely removed from the chain. Only additional
 1728        * references added via <code>addKeyEventPostProcessor</code> can be
 1729        * removed.
 1730        * <p>
 1731        * If a null post-processor is specified, if the specified post-processor
 1732        * is not in the post-processor chain, or if this KeyboardFocusManager is
 1733        * specified without having been explicitly added, no action is taken and
 1734        * no exception is thrown.
 1735        * <p>
 1736        * In a multithreaded application, {@link KeyEventPostProcessor} behaves
 1737        * the same as other AWT listeners.  See
 1738        * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1739        * >AWT Threading Issues</a> for more details.
 1740        *
 1741        * @param processor the KeyEventPostProcessor to remove from the post-
 1742        *        processor chain
 1743        * @see #addKeyEventPostProcessor
 1744        */
 1745       public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
 1746           if (processor != null) {
 1747               synchronized (this) {
 1748                   if (keyEventPostProcessors != null) {
 1749                       keyEventPostProcessors.remove(processor);
 1750                   }
 1751               }
 1752           }
 1753       }
 1754   
 1755   
 1756       /**
 1757        * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
 1758        * List. The List will not include this KeyboardFocusManager unless it was
 1759        * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
 1760        * no KeyEventPostProcessors are registered, implementations are free to
 1761        * return null or a List of length 0. Client code should not assume one
 1762        * behavior over another, nor should it assume that the behavior, once
 1763        * established, will not change.
 1764        *
 1765        * @return a possibly null or empty List of KeyEventPostProcessors
 1766        * @see #addKeyEventPostProcessor
 1767        * @see #removeKeyEventPostProcessor
 1768        */
 1769       protected java.util.List<KeyEventPostProcessor>
 1770           getKeyEventPostProcessors()
 1771       {
 1772           return (keyEventPostProcessors != null)
 1773               ? (java.util.List)keyEventPostProcessors.clone()
 1774               : null;
 1775       }
 1776   
 1777   
 1778   
 1779       static void setMostRecentFocusOwner(Component component) {
 1780           Component window = component;
 1781           while (window != null && !(window instanceof Window)) {
 1782               window = window.parent;
 1783           }
 1784           if (window != null) {
 1785               setMostRecentFocusOwner((Window)window, component);
 1786           }
 1787       }
 1788       static synchronized void setMostRecentFocusOwner(Window window,
 1789                                                        Component component) {
 1790           // ATTN: component has a strong reference to window via chain
 1791           // of Component.parent fields.  Since WeakHasMap refers to its
 1792           // values strongly, we need to break the strong link from the
 1793           // value (component) back to its key (window).
 1794           WeakReference weakValue = null;
 1795           if (component != null) {
 1796               weakValue = new WeakReference(component);
 1797           }
 1798           mostRecentFocusOwners.put(window, weakValue);
 1799       }
 1800       static void clearMostRecentFocusOwner(Component comp) {
 1801           Container window;
 1802   
 1803           if (comp == null) {
 1804               return;
 1805           }
 1806   
 1807           synchronized (comp.getTreeLock()) {
 1808               window = comp.getParent();
 1809               while (window != null && !(window instanceof Window)) {
 1810                   window = window.getParent();
 1811               }
 1812           }
 1813   
 1814           synchronized (KeyboardFocusManager.class) {
 1815               if ((window != null)
 1816                   && (getMostRecentFocusOwner((Window)window) == comp))
 1817               {
 1818                   setMostRecentFocusOwner((Window)window, null);
 1819               }
 1820               // Also clear temporary lost component stored in Window
 1821               if (window != null) {
 1822                   Window realWindow = (Window)window;
 1823                   if (realWindow.getTemporaryLostComponent() == comp) {
 1824                       realWindow.setTemporaryLostComponent(null);
 1825                   }
 1826               }
 1827           }
 1828       }
 1829   
 1830       /*
 1831        * Please be careful changing this method! It is called from
 1832        * javax.swing.JComponent.runInputVerifier() using reflection.
 1833        */
 1834       static synchronized Component getMostRecentFocusOwner(Window window) {
 1835           WeakReference weakValue =
 1836               (WeakReference)mostRecentFocusOwners.get(window);
 1837           return weakValue == null ? null : (Component)weakValue.get();
 1838       }
 1839   
 1840       /**
 1841        * This method is called by the AWT event dispatcher requesting that the
 1842        * current KeyboardFocusManager dispatch the specified event on its behalf.
 1843        * It is expected that all KeyboardFocusManagers will dispatch all
 1844        * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
 1845        * These events should be dispatched based on the KeyboardFocusManager's
 1846        * notion of the focus owner and the focused and active Windows, sometimes
 1847        * overriding the source of the specified AWTEvent. Dispatching must be
 1848        * done using <code>redispatchEvent</code> to prevent the AWT event
 1849        * dispatcher from recursively requesting that the KeyboardFocusManager
 1850        * dispatch the event again. If this method returns <code>false</code>,
 1851        * then the AWT event dispatcher will attempt to dispatch the event itself.
 1852        *
 1853        * @param e the AWTEvent to be dispatched
 1854        * @return <code>true</code> if this method dispatched the event;
 1855        *         <code>false</code> otherwise
 1856        * @see #redispatchEvent
 1857        * @see #dispatchKeyEvent
 1858        */
 1859       public abstract boolean dispatchEvent(AWTEvent e);
 1860   
 1861       /**
 1862        * Redispatches an AWTEvent in such a way that the AWT event dispatcher
 1863        * will not recursively request that the KeyboardFocusManager, or any
 1864        * installed KeyEventDispatchers, dispatch the event again. Client
 1865        * implementations of <code>dispatchEvent</code> and client-defined
 1866        * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
 1867        * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
 1868        * <p>
 1869        * This method is intended to be used only by KeyboardFocusManagers and
 1870        * KeyEventDispatchers. It is not for general client use.
 1871        *
 1872        * @param target the Component to which the event should be dispatched
 1873        * @param e the event to dispatch
 1874        * @see #dispatchEvent
 1875        * @see KeyEventDispatcher
 1876        */
 1877       public final void redispatchEvent(Component target, AWTEvent e) {
 1878           e.focusManagerIsDispatching = true;
 1879           target.dispatchEvent(e);
 1880           e.focusManagerIsDispatching = false;
 1881       }
 1882   
 1883       /**
 1884        * Typically this method will be called by <code>dispatchEvent</code> if no
 1885        * other KeyEventDispatcher in the dispatcher chain dispatched the
 1886        * KeyEvent, or if no other KeyEventDispatchers are registered. If an
 1887        * implementation of this method returns <code>false</code>,
 1888        * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
 1889        * may simply return <code>false</code>. If <code>true</code> is returned,
 1890        * <code>dispatchEvent</code> should return <code>true</code> as well.
 1891        *
 1892        * @param e the KeyEvent which the current KeyboardFocusManager has
 1893        *        requested that this KeyEventDispatcher dispatch
 1894        * @return <code>true</code> if the KeyEvent was dispatched;
 1895        *         <code>false</code> otherwise
 1896        * @see #dispatchEvent
 1897        */
 1898       public abstract boolean dispatchKeyEvent(KeyEvent e);
 1899   
 1900       /**
 1901        * This method will be called by <code>dispatchKeyEvent</code>.
 1902        * By default, this method will handle any unconsumed KeyEvents that
 1903        * map to an AWT <code>MenuShortcut</code> by consuming the event
 1904        * and activating the shortcut.
 1905        *
 1906        * @param e the KeyEvent to post-process
 1907        * @return <code>true</code> to indicate that no other
 1908        *         KeyEventPostProcessor will be notified of the KeyEvent.
 1909        * @see #dispatchKeyEvent
 1910        * @see MenuShortcut
 1911        */
 1912       public abstract boolean postProcessKeyEvent(KeyEvent e);
 1913   
 1914       /**
 1915        * This method initiates a focus traversal operation if and only if the
 1916        * KeyEvent represents a focus traversal key for the specified
 1917        * focusedComponent. It is expected that focusedComponent is the current
 1918        * focus owner, although this need not be the case. If it is not,
 1919        * focus traversal will nevertheless proceed as if focusedComponent
 1920        * were the current focus owner.
 1921        *
 1922        * @param focusedComponent the Component that will be the basis for a focus
 1923        *        traversal operation if the specified event represents a focus
 1924        *        traversal key for the Component
 1925        * @param e the event that may represent a focus traversal key
 1926        */
 1927       public abstract void processKeyEvent(Component focusedComponent,
 1928                                            KeyEvent e);
 1929   
 1930       /**
 1931        * Called by the AWT to notify the KeyboardFocusManager that it should
 1932        * delay dispatching of KeyEvents until the specified Component becomes
 1933        * the focus owner. If client code requests a focus change, and the AWT
 1934        * determines that this request might be granted by the native windowing
 1935        * system, then the AWT will call this method. It is the responsibility of
 1936        * the KeyboardFocusManager to delay dispatching of KeyEvents with
 1937        * timestamps later than the specified time stamp until the specified
 1938        * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
 1939        * request by invoking <code>dequeueKeyEvents</code> or
 1940        * <code>discardKeyEvents</code>.
 1941        *
 1942        * @param after timestamp of current event, or the current, system time if
 1943        *        the current event has no timestamp, or the AWT cannot determine
 1944        *        which event is currently being handled
 1945        * @param untilFocused Component which should receive a FOCUS_GAINED event
 1946        *        before any pending KeyEvents
 1947        * @see #dequeueKeyEvents
 1948        * @see #discardKeyEvents
 1949        */
 1950       protected abstract void enqueueKeyEvents(long after,
 1951                                                Component untilFocused);
 1952   
 1953       /**
 1954        * Called by the AWT to notify the KeyboardFocusManager that it should
 1955        * cancel delayed dispatching of KeyEvents. All KeyEvents which were
 1956        * enqueued because of a call to <code>enqueueKeyEvents</code> with the
 1957        * same timestamp and Component should be released for normal dispatching
 1958        * to the current focus owner. If the given timestamp is less than zero,
 1959        * the outstanding enqueue request for the given Component with the <b>
 1960        * oldest</b> timestamp (if any) should be cancelled.
 1961        *
 1962        * @param after the timestamp specified in the call to
 1963        *        <code>enqueueKeyEvents</code>, or any value < 0
 1964        * @param untilFocused the Component specified in the call to
 1965        *        <code>enqueueKeyEvents</code>
 1966        * @see #enqueueKeyEvents
 1967        * @see #discardKeyEvents
 1968        */
 1969       protected abstract void dequeueKeyEvents(long after,
 1970                                                Component untilFocused);
 1971   
 1972       /**
 1973        * Called by the AWT to notify the KeyboardFocusManager that it should
 1974        * cancel delayed dispatching of KeyEvents. All KeyEvents which were
 1975        * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
 1976        * with the same Component should be discarded.
 1977        *
 1978        * @param comp the Component specified in one or more calls to
 1979        *        <code>enqueueKeyEvents</code>
 1980        * @see #enqueueKeyEvents
 1981        * @see #dequeueKeyEvents
 1982        */
 1983       protected abstract void discardKeyEvents(Component comp);
 1984   
 1985       /**
 1986        * Focuses the Component after aComponent, typically based on a
 1987        * FocusTraversalPolicy.
 1988        *
 1989        * @param aComponent the Component that is the basis for the focus
 1990        *        traversal operation
 1991        * @see FocusTraversalPolicy
 1992        */
 1993       public abstract void focusNextComponent(Component aComponent);
 1994   
 1995       /**
 1996        * Focuses the Component before aComponent, typically based on a
 1997        * FocusTraversalPolicy.
 1998        *
 1999        * @param aComponent the Component that is the basis for the focus
 2000        *        traversal operation
 2001        * @see FocusTraversalPolicy
 2002        */
 2003       public abstract void focusPreviousComponent(Component aComponent);
 2004   
 2005       /**
 2006        * Moves the focus up one focus traversal cycle. Typically, the focus owner
 2007        * is set to aComponent's focus cycle root, and the current focus cycle
 2008        * root is set to the new focus owner's focus cycle root. If, however,
 2009        * aComponent's focus cycle root is a Window, then typically the focus
 2010        * owner is set to the Window's default Component to focus, and the current
 2011        * focus cycle root is unchanged.
 2012        *
 2013        * @param aComponent the Component that is the basis for the focus
 2014        *        traversal operation
 2015        */
 2016       public abstract void upFocusCycle(Component aComponent);
 2017   
 2018       /**
 2019        * Moves the focus down one focus traversal cycle. Typically, if
 2020        * aContainer is a focus cycle root, then the focus owner is set to
 2021        * aContainer's default Component to focus, and the current focus cycle
 2022        * root is set to aContainer. If aContainer is not a focus cycle root, then
 2023        * no focus traversal operation occurs.
 2024        *
 2025        * @param aContainer the Container that is the basis for the focus
 2026        *        traversal operation
 2027        */
 2028       public abstract void downFocusCycle(Container aContainer);
 2029   
 2030       /**
 2031        * Focuses the Component after the current focus owner.
 2032        */
 2033       public final void focusNextComponent() {
 2034           Component focusOwner = getFocusOwner();
 2035           if (focusOwner != null) {
 2036               focusNextComponent(focusOwner);
 2037           }
 2038       }
 2039   
 2040       /**
 2041        * Focuses the Component before the current focus owner.
 2042        */
 2043       public final void focusPreviousComponent() {
 2044           Component focusOwner = getFocusOwner();
 2045           if (focusOwner != null) {
 2046               focusPreviousComponent(focusOwner);
 2047           }
 2048       }
 2049   
 2050       /**
 2051        * Moves the focus up one focus traversal cycle from the current focus
 2052        * owner. Typically, the new focus owner is set to the current focus
 2053        * owner's focus cycle root, and the current focus cycle root is set to the
 2054        * new focus owner's focus cycle root. If, however, the current focus
 2055        * owner's focus cycle root is a Window, then typically the focus owner is
 2056        * set to the focus cycle root's default Component to focus, and the
 2057        * current focus cycle root is unchanged.
 2058        */
 2059       public final void upFocusCycle() {
 2060           Component focusOwner = getFocusOwner();
 2061           if (focusOwner != null) {
 2062               upFocusCycle(focusOwner);
 2063           }
 2064       }
 2065   
 2066       /**
 2067        * Moves the focus down one focus traversal cycle from the current focus
 2068        * owner, if and only if the current focus owner is a Container that is a
 2069        * focus cycle root. Typically, the focus owner is set to the current focus
 2070        * owner's default Component to focus, and the current focus cycle root is
 2071        * set to the current focus owner. If the current focus owner is not a
 2072        * Container that is a focus cycle root, then no focus traversal operation
 2073        * occurs.
 2074        */
 2075       public final void downFocusCycle() {
 2076           Component focusOwner = getFocusOwner();
 2077           if (focusOwner instanceof Container) {
 2078               downFocusCycle((Container)focusOwner);
 2079           }
 2080       }
 2081   
 2082       /**
 2083        * Dumps the list of focus requests to stderr
 2084        */
 2085       void dumpRequests() {
 2086           System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
 2087           synchronized (heavyweightRequests) {
 2088               for (HeavyweightFocusRequest req : heavyweightRequests) {
 2089                   System.err.println(">>> Req: " + req);
 2090               }
 2091           }
 2092           System.err.println("");
 2093       }
 2094   
 2095       private static final class LightweightFocusRequest {
 2096           final Component component;
 2097           final boolean temporary;
 2098           final CausedFocusEvent.Cause cause;
 2099   
 2100           LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
 2101               this.component = component;
 2102               this.temporary = temporary;
 2103               this.cause = cause;
 2104           }
 2105           public String toString() {
 2106               return "LightweightFocusRequest[component=" + component +
 2107                   ",temporary=" + temporary + ", cause=" + cause + "]";
 2108           }
 2109       }
 2110   
 2111       private static final class HeavyweightFocusRequest {
 2112           final Component heavyweight;
 2113           final LinkedList<LightweightFocusRequest> lightweightRequests;
 2114   
 2115           static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
 2116               new HeavyweightFocusRequest();
 2117   
 2118           private HeavyweightFocusRequest() {
 2119               heavyweight = null;
 2120               lightweightRequests = null;
 2121           }
 2122   
 2123           HeavyweightFocusRequest(Component heavyweight, Component descendant,
 2124                                   boolean temporary, CausedFocusEvent.Cause cause) {
 2125               if (log.isLoggable(Level.FINE)) {
 2126                   if (heavyweight == null) {
 2127                       log.log(Level.FINE, "Assertion (heavyweight != null) failed");
 2128                   }
 2129               }
 2130   
 2131               this.heavyweight = heavyweight;
 2132               this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
 2133               addLightweightRequest(descendant, temporary, cause);
 2134           }
 2135           boolean addLightweightRequest(Component descendant,
 2136                                         boolean temporary, CausedFocusEvent.Cause cause) {
 2137               if (log.isLoggable(Level.FINE)) {
 2138                   if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
 2139                       log.log(Level.FINE, "Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
 2140                   }
 2141                   if (descendant == null) {
 2142                       log.log(Level.FINE, "Assertion (descendant != null) failed");
 2143                   }
 2144               }
 2145   
 2146               Component lastDescendant = ((lightweightRequests.size() > 0)
 2147                   ? lightweightRequests.getLast().component
 2148                   : null);
 2149   
 2150               if (descendant != lastDescendant) {
 2151                   // Not a duplicate request
 2152                   lightweightRequests.add
 2153                       (new LightweightFocusRequest(descendant, temporary, cause));
 2154                   return true;
 2155               } else {
 2156                   return false;
 2157               }
 2158           }
 2159   
 2160           LightweightFocusRequest getFirstLightweightRequest() {
 2161               if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
 2162                   return null;
 2163               }
 2164               return lightweightRequests.getFirst();
 2165           }
 2166           public String toString() {
 2167               boolean first = true;
 2168               String str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
 2169                   ",lightweightRequests=";
 2170               if (lightweightRequests == null) {
 2171                   str += null;
 2172               } else {
 2173                   str += "[";
 2174   
 2175                   for (LightweightFocusRequest lwRequest : lightweightRequests) {
 2176                       if (first) {
 2177                           first = false;
 2178                       } else {
 2179                           str += ",";
 2180                       }
 2181                       str += lwRequest;
 2182                   }
 2183                   str += "]";
 2184               }
 2185               str += "]";
 2186               return str;
 2187           }
 2188       }
 2189   
 2190       /*
 2191        * heavyweightRequests is used as a monitor for synchronized changes of
 2192        * currentLightweightRequests, clearingCurrentLightweightRequests and
 2193        * newFocusOwner.
 2194        */
 2195       private static LinkedList<HeavyweightFocusRequest> heavyweightRequests =
 2196           new LinkedList<HeavyweightFocusRequest>();
 2197       private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
 2198       private static boolean clearingCurrentLightweightRequests;
 2199       private static boolean allowSyncFocusRequests = true;
 2200       private static Component newFocusOwner = null;
 2201       p