Home » openjdk-7 » java » awt » [javadoc | source]

    1   /*
    2    * Copyright (c) 2000, 2010, Oracle and/or its affiliates. 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.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * 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 sun.util.logging.PlatformLogger;
   57   
   58   import sun.awt.AppContext;
   59   import sun.awt.HeadlessToolkit;
   60   import sun.awt.SunToolkit;
   61   import sun.awt.CausedFocusEvent;
   62   import sun.awt.KeyboardFocusManagerPeerProvider;
   63   import sun.awt.AWTAccessor;
   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 PlatformLogger focusLog = PlatformLogger.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           AWTAccessor.setKeyboardFocusManagerAccessor(
  122               new AWTAccessor.KeyboardFocusManagerAccessor() {
  123                   public int shouldNativelyFocusHeavyweight(Component heavyweight,
  124                                                      Component descendant,
  125                                                      boolean temporary,
  126                                                      boolean focusedWindowChangeAllowed,
  127                                                      long time,
  128                                                      CausedFocusEvent.Cause cause)
  129                   {
  130                       return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
  131                           heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
  132                   }
  133                   public boolean processSynchronousLightweightTransfer(Component heavyweight,
  134                                                                 Component descendant,
  135                                                                 boolean temporary,
  136                                                                 boolean focusedWindowChangeAllowed,
  137                                                                 long time)
  138                   {
  139                       return KeyboardFocusManager.processSynchronousLightweightTransfer(
  140                           heavyweight, descendant, temporary, focusedWindowChangeAllowed, time);
  141                   }
  142                   public void removeLastFocusRequest(Component heavyweight) {
  143                       KeyboardFocusManager.removeLastFocusRequest(heavyweight);
  144                   }
  145                   public void setMostRecentFocusOwner(Window window, Component component) {
  146                       KeyboardFocusManager.setMostRecentFocusOwner(window, component);
  147                   }
  148               }
  149           );
  150       }
  151   
  152       transient KeyboardFocusManagerPeer peer;
  153   
  154       /**
  155        * Initialize JNI field and method IDs
  156        */
  157       private static native void initIDs();
  158   
  159       private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.KeyboardFocusManager");
  160   
  161       /**
  162        * The identifier for the Forward focus traversal keys.
  163        *
  164        * @see #setDefaultFocusTraversalKeys
  165        * @see #getDefaultFocusTraversalKeys
  166        * @see Component#setFocusTraversalKeys
  167        * @see Component#getFocusTraversalKeys
  168        */
  169       public static final int FORWARD_TRAVERSAL_KEYS = 0;
  170   
  171       /**
  172        * The identifier for the Backward focus traversal keys.
  173        *
  174        * @see #setDefaultFocusTraversalKeys
  175        * @see #getDefaultFocusTraversalKeys
  176        * @see Component#setFocusTraversalKeys
  177        * @see Component#getFocusTraversalKeys
  178        */
  179       public static final int BACKWARD_TRAVERSAL_KEYS = 1;
  180   
  181       /**
  182        * The identifier for the Up Cycle focus traversal keys.
  183        *
  184        * @see #setDefaultFocusTraversalKeys
  185        * @see #getDefaultFocusTraversalKeys
  186        * @see Component#setFocusTraversalKeys
  187        * @see Component#getFocusTraversalKeys
  188        */
  189       public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
  190   
  191       /**
  192        * The identifier for the Down Cycle focus traversal keys.
  193        *
  194        * @see #setDefaultFocusTraversalKeys
  195        * @see #getDefaultFocusTraversalKeys
  196        * @see Component#setFocusTraversalKeys
  197        * @see Component#getFocusTraversalKeys
  198        */
  199       public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
  200   
  201       static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
  202   
  203       /**
  204        * Returns the current KeyboardFocusManager instance for the calling
  205        * thread's context.
  206        *
  207        * @return this thread's context's KeyboardFocusManager
  208        * @see #setCurrentKeyboardFocusManager
  209        */
  210       public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
  211           return getCurrentKeyboardFocusManager(AppContext.getAppContext());
  212       }
  213   
  214       synchronized static KeyboardFocusManager
  215           getCurrentKeyboardFocusManager(AppContext appcontext)
  216       {
  217           KeyboardFocusManager manager = (KeyboardFocusManager)
  218               appcontext.get(KeyboardFocusManager.class);
  219           if (manager == null) {
  220               manager = new DefaultKeyboardFocusManager();
  221               appcontext.put(KeyboardFocusManager.class, manager);
  222           }
  223           return manager;
  224       }
  225   
  226       /**
  227        * Sets the current KeyboardFocusManager instance for the calling thread's
  228        * context. If null is specified, then the current KeyboardFocusManager
  229        * is replaced with a new instance of DefaultKeyboardFocusManager.
  230        * <p>
  231        * If a SecurityManager is installed, the calling thread must be granted
  232        * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
  233        * the current KeyboardFocusManager. If this permission is not granted,
  234        * this method will throw a SecurityException, and the current
  235        * KeyboardFocusManager will be unchanged.
  236        *
  237        * @param newManager the new KeyboardFocusManager for this thread's context
  238        * @see #getCurrentKeyboardFocusManager
  239        * @see DefaultKeyboardFocusManager
  240        * @throws SecurityException if the calling thread does not have permission
  241        *         to replace the current KeyboardFocusManager
  242        */
  243       public static void setCurrentKeyboardFocusManager(
  244           KeyboardFocusManager newManager) throws SecurityException
  245       {
  246           SecurityManager security = System.getSecurityManager();
  247           if (security != null) {
  248               if (replaceKeyboardFocusManagerPermission == null) {
  249                   replaceKeyboardFocusManagerPermission =
  250                       new AWTPermission("replaceKeyboardFocusManager");
  251               }
  252               security.
  253                   checkPermission(replaceKeyboardFocusManagerPermission);
  254           }
  255   
  256           KeyboardFocusManager oldManager = null;
  257   
  258           synchronized (KeyboardFocusManager.class) {
  259               AppContext appcontext = AppContext.getAppContext();
  260   
  261               if (newManager != null) {
  262                   oldManager = getCurrentKeyboardFocusManager(appcontext);
  263   
  264                   appcontext.put(KeyboardFocusManager.class, newManager);
  265               } else {
  266                   oldManager = getCurrentKeyboardFocusManager(appcontext);
  267                   appcontext.remove(KeyboardFocusManager.class);
  268               }
  269           }
  270   
  271           if (oldManager != null) {
  272               oldManager.firePropertyChange("managingFocus",
  273                                             Boolean.TRUE,
  274                                             Boolean.FALSE);
  275           }
  276           if (newManager != null) {
  277               newManager.firePropertyChange("managingFocus",
  278                                             Boolean.FALSE,
  279                                             Boolean.TRUE);
  280           }
  281       }
  282   
  283       /**
  284        * The Component in an application that will typically receive all
  285        * KeyEvents generated by the user.
  286        */
  287       private static Component focusOwner;
  288   
  289       /**
  290        * The Component in an application that will regain focus when an
  291        * outstanding temporary focus transfer has completed, or the focus owner,
  292        * if no outstanding temporary transfer exists.
  293        */
  294       private static Component permanentFocusOwner;
  295   
  296       /**
  297        * The Window which is, or contains, the focus owner.
  298        */
  299       private static Window focusedWindow;
  300   
  301       /**
  302        * Only a Frame or a Dialog can be the active Window. The native windowing
  303        * system may denote the active Window with a special decoration, such as a
  304        * highlighted title bar. The active Window is always either the focused
  305        * Window, or the first Frame or Dialog which is an owner of the focused
  306        * Window.
  307        */
  308       private static Window activeWindow;
  309   
  310       /**
  311        * The default FocusTraversalPolicy for all Windows that have no policy of
  312        * their own set. If those Windows have focus-cycle-root children that have
  313        * no keyboard-traversal policy of their own, then those children will also
  314        * inherit this policy (as will, recursively, their focus-cycle-root
  315        * children).
  316        */
  317       private FocusTraversalPolicy defaultPolicy =
  318           new DefaultFocusTraversalPolicy();
  319   
  320       /**
  321        * The bound property names of each focus traversal key.
  322        */
  323       private static final String[] defaultFocusTraversalKeyPropertyNames = {
  324           "forwardDefaultFocusTraversalKeys",
  325           "backwardDefaultFocusTraversalKeys",
  326           "upCycleDefaultFocusTraversalKeys",
  327           "downCycleDefaultFocusTraversalKeys"
  328       };
  329   
  330       /**
  331        * The default strokes for initializing the default focus traversal keys.
  332        */
  333       private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
  334           {
  335               AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false),
  336               AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false),
  337           },
  338           {
  339               AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false),
  340               AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
  341                                            InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK,
  342                                            false),
  343           },
  344           {},
  345           {},
  346         };
  347       /**
  348        * The default focus traversal keys. Each array of traversal keys will be
  349        * in effect on all Windows that have no such array of their own explicitly
  350        * set. Each array will also be inherited, recursively, by any child
  351        * Component of those Windows that has no such array of its own explicitly
  352        * set.
  353        */
  354       private Set[] defaultFocusTraversalKeys = new Set[4];
  355   
  356       /**
  357        * The current focus cycle root. If the focus owner is itself a focus cycle
  358        * root, then it may be ambiguous as to which Components represent the next
  359        * and previous Components to focus during normal focus traversal. In that
  360        * case, the current focus cycle root is used to differentiate among the
  361        * possibilities.
  362        */
  363       private static Container currentFocusCycleRoot;
  364   
  365       /**
  366        * A description of any VetoableChangeListeners which have been registered.
  367        */
  368       private VetoableChangeSupport vetoableSupport;
  369   
  370       /**
  371        * A description of any PropertyChangeListeners which have been registered.
  372        */
  373       private PropertyChangeSupport changeSupport;
  374   
  375       /**
  376        * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
  377        * include this KeyboardFocusManager unless it was explicitly re-registered
  378        * via a call to <code>addKeyEventDispatcher</code>. If no other
  379        * KeyEventDispatchers are registered, this field may be null or refer to
  380        * a List of length 0.
  381        */
  382       private java.util.LinkedList keyEventDispatchers;
  383   
  384       /**
  385        * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
  386        * not include this KeyboardFocusManager unless it was explicitly
  387        * re-registered via a call to <code>addKeyEventPostProcessor</code>.
  388        * If no other KeyEventPostProcessors are registered, this field may be
  389        * null or refer to a List of length 0.
  390        */
  391       private java.util.LinkedList keyEventPostProcessors;
  392   
  393       /**
  394        * Maps Windows to those Windows' most recent focus owners.
  395        */
  396       private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
  397   
  398       /**
  399        * Error String for initializing SecurityExceptions.
  400        */
  401       private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
  402   
  403       /**
  404        * We cache the permission used to verify that the calling thread is
  405        * permitted to access the global focus state.
  406        */
  407       private static AWTPermission replaceKeyboardFocusManagerPermission;
  408   
  409       /*
  410        * SequencedEvent which is currently dispatched in AppContext.
  411        */
  412       transient SequencedEvent currentSequencedEvent = null;
  413   
  414       final void setCurrentSequencedEvent(SequencedEvent current) {
  415           synchronized (SequencedEvent.class) {
  416               assert(current == null || currentSequencedEvent == null);
  417               currentSequencedEvent = current;
  418           }
  419       }
  420   
  421       final SequencedEvent getCurrentSequencedEvent() {
  422           synchronized (SequencedEvent.class) {
  423               return currentSequencedEvent;
  424           }
  425       }
  426   
  427       static Set initFocusTraversalKeysSet(String value, Set targetSet) {
  428           StringTokenizer tokens = new StringTokenizer(value, ",");
  429           while (tokens.hasMoreTokens()) {
  430               targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken()));
  431           }
  432           return (targetSet.isEmpty())
  433               ? Collections.EMPTY_SET
  434               : Collections.unmodifiableSet(targetSet);
  435       }
  436   
  437       /**
  438        * Initializes a KeyboardFocusManager.
  439        */
  440       public KeyboardFocusManager() {
  441           for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
  442               Set work_set = new HashSet();
  443               for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
  444                   work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
  445               }
  446               defaultFocusTraversalKeys[i] = (work_set.isEmpty())
  447                   ? Collections.EMPTY_SET
  448                   : Collections.unmodifiableSet(work_set);
  449           }
  450           initPeer();
  451       }
  452   
  453       private void initPeer() {
  454           Toolkit tk = Toolkit.getDefaultToolkit();
  455           KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk;
  456           peer = peerProvider.createKeyboardFocusManagerPeer(this);
  457       }
  458   
  459       /**
  460        * Returns the focus owner, if the focus owner is in the same context as
  461        * the calling thread. The focus owner is defined as the Component in an
  462        * application that will typically receive all KeyEvents generated by the
  463        * user. KeyEvents which map to the focus owner's focus traversal keys will
  464        * not be delivered if focus traversal keys are enabled for the focus
  465        * owner. In addition, KeyEventDispatchers may retarget or consume
  466        * KeyEvents before they reach the focus owner.
  467        *
  468        * @return the focus owner, or null if the focus owner is not a member of
  469        *         the calling thread's context
  470        * @see #getGlobalFocusOwner
  471        * @see #setGlobalFocusOwner
  472        */
  473       public Component getFocusOwner() {
  474           synchronized (KeyboardFocusManager.class) {
  475               if (focusOwner == null) {
  476                   return null;
  477               }
  478   
  479               return (focusOwner.appContext == AppContext.getAppContext())
  480                   ? focusOwner
  481                   : null;
  482           }
  483       }
  484   
  485       /**
  486        * Returns the focus owner, even if the calling thread is in a different
  487        * context than the focus owner. The focus owner is defined as the
  488        * Component in an application that will typically receive all KeyEvents
  489        * generated by the user. KeyEvents which map to the focus owner's focus
  490        * traversal keys will not be delivered if focus traversal keys are enabled
  491        * for the focus owner. In addition, KeyEventDispatchers may retarget or
  492        * consume KeyEvents before they reach the focus owner.
  493        * <p>
  494        * This method will throw a SecurityException if this KeyboardFocusManager
  495        * is not the current KeyboardFocusManager for the calling thread's
  496        * context.
  497        *
  498        * @return the focus owner
  499        * @see #getFocusOwner
  500        * @see #setGlobalFocusOwner
  501        * @throws SecurityException if this KeyboardFocusManager is not the
  502        *         current KeyboardFocusManager for the calling thread's context
  503        */
  504       protected Component getGlobalFocusOwner() throws SecurityException {
  505           synchronized (KeyboardFocusManager.class) {
  506               if (this == getCurrentKeyboardFocusManager()) {
  507                   return focusOwner;
  508               } else {
  509                   if (focusLog.isLoggable(PlatformLogger.FINER)) {
  510                       focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
  511                   }
  512                   throw new SecurityException(notPrivileged);
  513               }
  514           }
  515       }
  516   
  517       /**
  518        * Sets the focus owner. The operation will be cancelled if the Component
  519        * is not focusable. The focus owner is defined as the Component in an
  520        * application that will typically receive all KeyEvents generated by the
  521        * user. KeyEvents which map to the focus owner's focus traversal keys will
  522        * not be delivered if focus traversal keys are enabled for the focus
  523        * owner. In addition, KeyEventDispatchers may retarget or consume
  524        * KeyEvents before they reach the focus owner.
  525        * <p>
  526        * This method does not actually set the focus to the specified Component.
  527        * It merely stores the value to be subsequently returned by
  528        * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
  529        * or <code>Component.requestFocusInWindow()</code> to change the focus
  530        * owner, subject to platform limitations.
  531        *
  532        * @param focusOwner the focus owner
  533        * @see #getFocusOwner
  534        * @see #getGlobalFocusOwner
  535        * @see Component#requestFocus()
  536        * @see Component#requestFocusInWindow()
  537        * @see Component#isFocusable
  538        * @beaninfo
  539        *       bound: true
  540        */
  541       protected void setGlobalFocusOwner(Component focusOwner) {
  542           Component oldFocusOwner = null;
  543           boolean shouldFire = false;
  544   
  545           if (focusOwner == null || focusOwner.isFocusable()) {
  546               synchronized (KeyboardFocusManager.class) {
  547                   oldFocusOwner = getFocusOwner();
  548   
  549                   try {
  550                       fireVetoableChange("focusOwner", oldFocusOwner,
  551                                          focusOwner);
  552                   } catch (PropertyVetoException e) {
  553                       // rejected
  554                       return;
  555                   }
  556   
  557                   KeyboardFocusManager.focusOwner = focusOwner;
  558   
  559                   if (focusOwner != null &&
  560                       (getCurrentFocusCycleRoot() == null ||
  561                        !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot())))
  562                   {
  563                       Container rootAncestor =
  564                           focusOwner.getFocusCycleRootAncestor();
  565                       if (rootAncestor == null && (focusOwner instanceof Window))
  566                       {
  567                           rootAncestor = (Container)focusOwner;
  568                       }
  569                       if (rootAncestor != null) {
  570                           setGlobalCurrentFocusCycleRoot(rootAncestor);
  571                       }
  572                   }
  573   
  574                   shouldFire = true;
  575               }
  576           }
  577   
  578           if (shouldFire) {
  579               firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
  580           }
  581       }
  582   
  583       /**
  584        * Clears the global focus owner at both the Java and native levels. If
  585        * there exists a focus owner, that Component will receive a permanent
  586        * FOCUS_LOST event. After this operation completes, the native windowing
  587        * system will discard all user-generated KeyEvents until the user selects
  588        * a new Component to receive focus, or a Component is given focus
  589        * explicitly via a call to <code>requestFocus()</code>. This operation
  590        * does not change the focused or active Windows.
  591        *
  592        * @see Component#requestFocus()
  593        * @see java.awt.event.FocusEvent#FOCUS_LOST
  594        */
  595       public void clearGlobalFocusOwner() {
  596           if (!GraphicsEnvironment.isHeadless()) {
  597               // Toolkit must be fully initialized, otherwise
  598               // _clearGlobalFocusOwner will crash or throw an exception
  599               Toolkit.getDefaultToolkit();
  600   
  601               _clearGlobalFocusOwner();
  602           }
  603       }
  604       private void _clearGlobalFocusOwner() {
  605           Window activeWindow = markClearGlobalFocusOwner();
  606           peer.clearGlobalFocusOwner(activeWindow);
  607       }
  608   
  609       Component getNativeFocusOwner() {
  610           return peer.getCurrentFocusOwner();
  611       }
  612   
  613       void setNativeFocusOwner(Component comp) {
  614           if (focusLog.isLoggable(PlatformLogger.FINEST)) {
  615               focusLog.finest("Calling peer {0} setCurrentFocusOwner for {1}",
  616                               String.valueOf(peer), String.valueOf(comp));
  617           }
  618           peer.setCurrentFocusOwner(comp);
  619       }
  620   
  621       Window getNativeFocusedWindow() {
  622           return peer.getCurrentFocusedWindow();
  623       }
  624   
  625       /**
  626        * Returns the permanent focus owner, if the permanent focus owner is in
  627        * the same context as the calling thread. The permanent focus owner is
  628        * defined as the last Component in an application to receive a permanent
  629        * FOCUS_GAINED event. The focus owner and permanent focus owner are
  630        * equivalent unless a temporary focus change is currently in effect. In
  631        * such a situation, the permanent focus owner will again be the focus
  632        * owner when the temporary focus change ends.
  633        *
  634        * @return the permanent focus owner, or null if the permanent focus owner
  635        *         is not a member of the calling thread's context
  636        * @see #getGlobalPermanentFocusOwner
  637        * @see #setGlobalPermanentFocusOwner
  638        */
  639       public Component getPermanentFocusOwner() {
  640           synchronized (KeyboardFocusManager.class) {
  641               if (permanentFocusOwner == null) {
  642                   return null;
  643               }
  644   
  645               return (permanentFocusOwner.appContext ==
  646                       AppContext.getAppContext())
  647                   ? permanentFocusOwner
  648                   : null;
  649           }
  650       }
  651   
  652       /**
  653        * Returns the permanent focus owner, even if the calling thread is in a
  654        * different context than the permanent focus owner. The permanent focus
  655        * owner is defined as the last Component in an application to receive a
  656        * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
  657        * are equivalent unless a temporary focus change is currently in effect.
  658        * In such a situation, the permanent focus owner will again be the focus
  659        * owner when the temporary focus change ends.
  660        * <p>
  661        * This method will throw a SecurityException if this KeyboardFocusManager
  662        * is not the current KeyboardFocusManager for the calling thread's
  663        * context.
  664        *
  665        * @return the permanent focus owner
  666        * @see #getPermanentFocusOwner
  667        * @see #setGlobalPermanentFocusOwner
  668        * @throws SecurityException if this KeyboardFocusManager is not the
  669        *         current KeyboardFocusManager for the calling thread's context
  670        */
  671       protected Component getGlobalPermanentFocusOwner()
  672           throws SecurityException
  673       {
  674           synchronized (KeyboardFocusManager.class) {
  675               if (this == getCurrentKeyboardFocusManager()) {
  676                   return permanentFocusOwner;
  677               } else {
  678                   if (focusLog.isLoggable(PlatformLogger.FINER)) {
  679                       focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
  680                   }
  681                   throw new SecurityException(notPrivileged);
  682               }
  683           }
  684       }
  685   
  686       /**
  687        * Sets the permanent focus owner. The operation will be cancelled if the
  688        * Component is not focusable. The permanent focus owner is defined as the
  689        * last Component in an application to receive a permanent FOCUS_GAINED
  690        * event. The focus owner and permanent focus owner are equivalent unless
  691        * a temporary focus change is currently in effect. In such a situation,
  692        * the permanent focus owner will again be the focus owner when the
  693        * temporary focus change ends.
  694        * <p>
  695        * This method does not actually set the focus to the specified Component.
  696        * It merely stores the value to be subsequently returned by
  697        * <code>getPermanentFocusOwner()</code>. Use
  698        * <code>Component.requestFocus()</code> or
  699        * <code>Component.requestFocusInWindow()</code> to change the focus owner,
  700        * subject to platform limitations.
  701        *
  702        * @param permanentFocusOwner the permanent focus owner
  703        * @see #getPermanentFocusOwner
  704        * @see #getGlobalPermanentFocusOwner
  705        * @see Component#requestFocus()
  706        * @see Component#requestFocusInWindow()
  707        * @see Component#isFocusable
  708        * @beaninfo
  709        *       bound: true
  710        */
  711       protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner)
  712       {
  713           Component oldPermanentFocusOwner = null;
  714           boolean shouldFire = false;
  715   
  716           if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
  717               synchronized (KeyboardFocusManager.class) {
  718                   oldPermanentFocusOwner = getPermanentFocusOwner();
  719   
  720                   try {
  721                       fireVetoableChange("permanentFocusOwner",
  722                                          oldPermanentFocusOwner,
  723                                          permanentFocusOwner);
  724                   } catch (PropertyVetoException e) {
  725                       // rejected
  726                       return;
  727                   }
  728   
  729                   KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
  730   
  731                   KeyboardFocusManager.
  732                       setMostRecentFocusOwner(permanentFocusOwner);
  733   
  734                   shouldFire = true;
  735               }
  736           }
  737   
  738           if (shouldFire) {
  739               firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
  740                                  permanentFocusOwner);
  741           }
  742       }
  743   
  744       /**
  745        * Returns the focused Window, if the focused Window is in the same context
  746        * as the calling thread. The focused Window is the Window that is or
  747        * contains the focus owner.
  748        *
  749        * @return the focused Window, or null if the focused Window is not a
  750        *         member of the calling thread's context
  751        * @see #getGlobalFocusedWindow
  752        * @see #setGlobalFocusedWindow
  753        */
  754       public Window getFocusedWindow() {
  755           synchronized (KeyboardFocusManager.class) {
  756               if (focusedWindow == null) {
  757                   return null;
  758               }
  759   
  760               return (focusedWindow.appContext == AppContext.getAppContext())
  761                   ? focusedWindow
  762                   : null;
  763           }
  764       }
  765   
  766       /**
  767        * Returns the focused Window, even if the calling thread is in a different
  768        * context than the focused Window. The focused Window is the Window that
  769        * is or contains the focus owner.
  770        * <p>
  771        * This method will throw a SecurityException if this KeyboardFocusManager
  772        * is not the current KeyboardFocusManager for the calling thread's
  773        * context.
  774        *
  775        * @return the focused Window
  776        * @see #getFocusedWindow
  777        * @see #setGlobalFocusedWindow
  778        * @throws SecurityException if this KeyboardFocusManager is not the
  779        *         current KeyboardFocusManager for the calling thread's context
  780        */
  781       protected Window getGlobalFocusedWindow() throws SecurityException {
  782           synchronized (KeyboardFocusManager.class) {
  783               if (this == getCurrentKeyboardFocusManager()) {
  784                  return focusedWindow;
  785               } else {
  786                   if (focusLog.isLoggable(PlatformLogger.FINER)) {
  787                       focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
  788                   }
  789                   throw new SecurityException(notPrivileged);
  790               }
  791           }
  792       }
  793   
  794       /**
  795        * Sets the focused Window. The focused Window is the Window that is or
  796        * contains the focus owner. The operation will be cancelled if the
  797        * specified Window to focus is not a focusable Window.
  798        * <p>
  799        * This method does not actually change the focused Window as far as the
  800        * native windowing system is concerned. It merely stores the value to be
  801        * subsequently returned by <code>getFocusedWindow()</code>. Use
  802        * <code>Component.requestFocus()</code> or
  803        * <code>Component.requestFocusInWindow()</code> to change the focused
  804        * Window, subject to platform limitations.
  805        *
  806        * @param focusedWindow the focused Window
  807        * @see #getFocusedWindow
  808        * @see #getGlobalFocusedWindow
  809        * @see Component#requestFocus()
  810        * @see Component#requestFocusInWindow()
  811        * @see Window#isFocusableWindow
  812        * @beaninfo
  813        *       bound: true
  814        */
  815       protected void setGlobalFocusedWindow(Window focusedWindow) {
  816           Window oldFocusedWindow = null;
  817           boolean shouldFire = false;
  818   
  819           if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
  820               synchronized (KeyboardFocusManager.class) {
  821                   oldFocusedWindow = getFocusedWindow();
  822   
  823                   try {
  824                       fireVetoableChange("focusedWindow", oldFocusedWindow,
  825                                          focusedWindow);
  826                   } catch (PropertyVetoException e) {
  827                       // rejected
  828                       return;
  829                   }
  830   
  831                   KeyboardFocusManager.focusedWindow = focusedWindow;
  832                   shouldFire = true;
  833               }
  834           }
  835   
  836           if (shouldFire) {
  837               firePropertyChange("focusedWindow", oldFocusedWindow,
  838                                  focusedWindow);
  839           }
  840       }
  841   
  842       /**
  843        * Returns the active Window, if the active Window is in the same context
  844        * as the calling thread. Only a Frame or a Dialog can be the active
  845        * Window. The native windowing system may denote the active Window or its
  846        * children with special decorations, such as a highlighted title bar.
  847        * The active Window is always either the focused Window, or the first
  848        * Frame or Dialog that is an owner of the focused Window.
  849        *
  850        * @return the active Window, or null if the active Window is not a member
  851        *         of the calling thread's context
  852        * @see #getGlobalActiveWindow
  853        * @see #setGlobalActiveWindow
  854        */
  855       public Window getActiveWindow() {
  856           synchronized (KeyboardFocusManager.class) {
  857               if (activeWindow == null) {
  858                   return null;
  859               }
  860   
  861               return (activeWindow.appContext == AppContext.getAppContext())
  862                   ? activeWindow
  863                   : null;
  864           }
  865       }
  866   
  867       /**
  868        * Returns the active Window, even if the calling thread is in a different
  869        * context than the active Window. Only a Frame or a Dialog can be the
  870        * active Window. The native windowing system may denote the active Window
  871        * or its children with special decorations, such as a highlighted title
  872        * bar. The active Window is always either the focused Window, or the first
  873        * Frame or Dialog that is an owner of the focused Window.
  874        * <p>
  875        * This method will throw a SecurityException if this KeyboardFocusManager
  876        * is not the current KeyboardFocusManager for the calling thread's
  877        * context.
  878        *
  879        * @return the active Window
  880        * @see #getActiveWindow
  881        * @see #setGlobalActiveWindow
  882        * @throws SecurityException if this KeyboardFocusManager is not the
  883        *         current KeyboardFocusManager for the calling thread's context
  884        */
  885       protected Window getGlobalActiveWindow() throws SecurityException {
  886           synchronized (KeyboardFocusManager.class) {
  887               if (this == getCurrentKeyboardFocusManager()) {
  888                  return activeWindow;
  889               } else {
  890                   if (focusLog.isLoggable(PlatformLogger.FINER)) {
  891                       focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
  892                   }
  893                   throw new SecurityException(notPrivileged);
  894               }
  895           }
  896       }
  897   
  898       /**
  899        * Sets the active Window. Only a Frame or a Dialog can be the active
  900        * Window. The native windowing system may denote the active Window or its
  901        * children with special decorations, such as a highlighted title bar. The
  902        * active Window is always either the focused Window, or the first Frame or
  903        * Dialog that is an owner of the focused Window.
  904        * <p>
  905        * This method does not actually change the active Window as far as the
  906        * native windowing system is concerned. It merely stores the value to be
  907        * subsequently returned by <code>getActiveWindow()</code>. Use
  908        * <code>Component.requestFocus()</code> or
  909        * <code>Component.requestFocusInWindow()</code>to change the active
  910        * Window, subject to platform limitations.
  911        *
  912        * @param activeWindow the active Window
  913        * @see #getActiveWindow
  914        * @see #getGlobalActiveWindow
  915        * @see Component#requestFocus()
  916        * @see Component#requestFocusInWindow()
  917        * @beaninfo
  918        *       bound: true
  919        */
  920       protected void setGlobalActiveWindow(Window activeWindow) {
  921           Window oldActiveWindow;
  922           synchronized (KeyboardFocusManager.class) {
  923               oldActiveWindow = getActiveWindow();
  924               if (focusLog.isLoggable(PlatformLogger.FINER)) {
  925                   focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
  926               }
  927   
  928               try {
  929                   fireVetoableChange("activeWindow", oldActiveWindow,
  930                                      activeWindow);
  931               } catch (PropertyVetoException e) {
  932                   // rejected
  933                   return;
  934               }
  935   
  936               KeyboardFocusManager.activeWindow = activeWindow;
  937           }
  938   
  939           firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
  940       }
  941   
  942       /**
  943        * Returns the default FocusTraversalPolicy. Top-level components
  944        * use this value on their creation to initialize their own focus traversal
  945        * policy by explicit call to Container.setFocusTraversalPolicy.
  946        *
  947        * @return the default FocusTraversalPolicy. null will never be returned.
  948        * @see #setDefaultFocusTraversalPolicy
  949        * @see Container#setFocusTraversalPolicy
  950        * @see Container#getFocusTraversalPolicy
  951        */
  952       public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
  953           return defaultPolicy;
  954       }
  955   
  956       /**
  957        * Sets the default FocusTraversalPolicy. Top-level components
  958        * use this value on their creation to initialize their own focus traversal
  959        * policy by explicit call to Container.setFocusTraversalPolicy.
  960        * Note: this call doesn't affect already created components as they have
  961        * their policy initialized. Only new components will use this policy as
  962        * their default policy.
  963        *
  964        * @param defaultPolicy the new, default FocusTraversalPolicy
  965        * @see #getDefaultFocusTraversalPolicy
  966        * @see Container#setFocusTraversalPolicy
  967        * @see Container#getFocusTraversalPolicy
  968        * @throws IllegalArgumentException if defaultPolicy is null
  969        * @beaninfo
  970        *       bound: true
  971        */
  972       public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy
  973                                                  defaultPolicy) {
  974           if (defaultPolicy == null) {
  975               throw new IllegalArgumentException("default focus traversal policy cannot be null");
  976           }
  977   
  978           FocusTraversalPolicy oldPolicy;
  979   
  980           synchronized (this) {
  981               oldPolicy = this.defaultPolicy;
  982               this.defaultPolicy = defaultPolicy;
  983           }
  984   
  985           firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
  986                              defaultPolicy);
  987       }
  988   
  989       /**
  990        * Sets the default focus traversal keys for a given traversal operation.
  991        * This traversal key <code>Set</code> will be in effect on all
  992        * <code>Window</code>s that have no such <code>Set</code> of
  993        * their own explicitly defined. This <code>Set</code> will also be
  994        * inherited, recursively, by any child <code>Component</code> of
  995        * those <code>Windows</code> that has
  996        * no such <code>Set</code> of its own explicitly defined.
  997        * <p>
  998        * The default values for the default focus traversal keys are
  999        * implementation-dependent. Sun recommends that all implementations for a
 1000        * particular native platform use the same default values. The
 1001        * recommendations for Windows and Unix are listed below. These
 1002        * recommendations are used in the Sun AWT implementations.
 1003        *
 1004        * <table border=1 summary="Recommended default values for focus traversal keys">
 1005        * <tr>
 1006        *    <th>Identifier</th>
 1007        *    <th>Meaning</th>
 1008        *    <th>Default</th>
 1009        * </tr>
 1010        * <tr>
 1011        *    <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
 1012        *    <td>Normal forward keyboard traversal</td>
 1013        *    <td><code>TAB</code> on <code>KEY_PRESSED</code>,
 1014        *        <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
 1015        * </tr>
 1016        * <tr>
 1017        *    <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
 1018        *    <td>Normal reverse keyboard traversal</td>
 1019        *    <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
 1020        *        <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
 1021        * </tr>
 1022        * <tr>
 1023        *    <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
 1024        *    <td>Go up one focus traversal cycle</td>
 1025        *    <td>none</td>
 1026        * </tr>
 1027        * <tr>
 1028        *    <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
 1029        *    <td>Go down one focus traversal cycle</td>
 1030        *    <td>none</td>
 1031        * </tr>
 1032        * </table>
 1033        *
 1034        * To disable a traversal key, use an empty <code>Set</code>;
 1035        * <code>Collections.EMPTY_SET</code> is recommended.
 1036        * <p>
 1037        * Using the <code>AWTKeyStroke</code> API, client code can
 1038        * specify on which of two
 1039        * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
 1040        * <code>KEY_RELEASED</code>, the focus traversal operation will
 1041        * occur. Regardless of which <code>KeyEvent</code> is specified,
 1042        * however, all <code>KeyEvent</code>s related to the focus
 1043        * traversal key, including the associated <code>KEY_TYPED</code>
 1044        * event, will be consumed, and will not be dispatched
 1045        * to any <code>Component</code>. It is a runtime error to
 1046        * specify a <code>KEY_TYPED</code> event as
 1047        * mapping to a focus traversal operation, or to map the same event to
 1048        * multiple default focus traversal operations.
 1049        *
 1050        * @param id one of
 1051        *        <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
 1052        *        <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
 1053        *        <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
 1054        *        <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
 1055        * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
 1056        *        specified operation
 1057        * @see #getDefaultFocusTraversalKeys
 1058        * @see Component#setFocusTraversalKeys
 1059        * @see Component#getFocusTraversalKeys
 1060        * @throws IllegalArgumentException if id is not one of
 1061        *         <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
 1062        *         <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
 1063        *         <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
 1064        *         <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
 1065        *         or if keystrokes is <code>null</code>,
 1066        *         or if keystrokes contains <code>null</code>,
 1067        *         or if any <code>Object</code> in
 1068        *         keystrokes is not an <code>AWTKeyStroke</code>,
 1069        *         or if any keystroke
 1070        *         represents a <code>KEY_TYPED</code> event,
 1071        *         or if any keystroke already maps
 1072        *         to another default focus traversal operation
 1073        * @beaninfo
 1074        *       bound: true
 1075        */
 1076       public void
 1077           setDefaultFocusTraversalKeys(int id,
 1078                                        Set<? extends AWTKeyStroke> keystrokes)
 1079       {
 1080           if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
 1081               throw new IllegalArgumentException("invalid focus traversal key identifier");
 1082           }
 1083           if (keystrokes == null) {
 1084               throw new IllegalArgumentException("cannot set null Set of default focus traversal keys");
 1085           }
 1086   
 1087           Set oldKeys;
 1088   
 1089           synchronized (this) {
 1090               for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) {
 1091                   Object obj = iter.next();
 1092   
 1093                   if (obj == null) {
 1094                       throw new IllegalArgumentException("cannot set null focus traversal key");
 1095                   }
 1096   
 1097                   // Fix for 6195831:
 1098                   //According to javadoc this method should throw IAE instead of ClassCastException
 1099                   if (!(obj instanceof AWTKeyStroke)) {
 1100                       throw new IllegalArgumentException("object is expected to be AWTKeyStroke");
 1101                   }
 1102                   AWTKeyStroke keystroke = (AWTKeyStroke)obj;
 1103   
 1104                   if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
 1105                       throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
 1106                   }
 1107   
 1108                   // Check to see if key already maps to another traversal
 1109                   // operation
 1110                   for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
 1111                       if (i == id) {
 1112                           continue;
 1113                       }
 1114   
 1115                       if (defaultFocusTraversalKeys[i].contains(keystroke)) {
 1116                           throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
 1117                       }
 1118                   }
 1119               }
 1120   
 1121               oldKeys = defaultFocusTraversalKeys[id];
 1122               defaultFocusTraversalKeys[id] =
 1123                   Collections.unmodifiableSet(new HashSet(keystrokes));
 1124           }
 1125   
 1126           firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
 1127                              oldKeys, keystrokes);
 1128       }
 1129   
 1130       /**
 1131        * Returns a Set of default focus traversal keys for a given traversal
 1132        * operation. This traversal key Set will be in effect on all Windows that
 1133        * have no such Set of their own explicitly defined. This Set will also be
 1134        * inherited, recursively, by any child Component of those Windows that has
 1135        * no such Set of its own explicitly defined. (See
 1136        * <code>setDefaultFocusTraversalKeys</code> for a full description of each
 1137        * operation.)
 1138        *
 1139        * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 1140        *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 1141        *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 1142        *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 1143        * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
 1144        *         for the specified operation; the <code>Set</code>
 1145        *         will be unmodifiable, and may be empty; <code>null</code>
 1146        *         will never be returned
 1147        * @see #setDefaultFocusTraversalKeys
 1148        * @see Component#setFocusTraversalKeys
 1149        * @see Component#getFocusTraversalKeys
 1150        * @throws IllegalArgumentException if id is not one of
 1151        *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
 1152        *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
 1153        *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
 1154        *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
 1155        */
 1156       public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
 1157           if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
 1158               throw new IllegalArgumentException("invalid focus traversal key identifier");
 1159           }
 1160   
 1161           // Okay to return Set directly because it is an unmodifiable view
 1162           return defaultFocusTraversalKeys[id];
 1163       }
 1164   
 1165       /**
 1166        * Returns the current focus cycle root, if the current focus cycle root is
 1167        * in the same context as the calling thread. If the focus owner is itself
 1168        * a focus cycle root, then it may be ambiguous as to which Components
 1169        * represent the next and previous Components to focus during normal focus
 1170        * traversal. In that case, the current focus cycle root is used to
 1171        * differentiate among the possibilities.
 1172        * <p>
 1173        * This method is intended to be used only by KeyboardFocusManagers and
 1174        * focus implementations. It is not for general client use.
 1175        *
 1176        * @return the current focus cycle root, or null if the current focus cycle
 1177        *         root is not a member of the calling thread's context
 1178        * @see #getGlobalCurrentFocusCycleRoot
 1179        * @see #setGlobalCurrentFocusCycleRoot
 1180        */
 1181       public Container getCurrentFocusCycleRoot() {
 1182           synchronized (KeyboardFocusManager.class) {
 1183               if (currentFocusCycleRoot == null) {
 1184                   return null;
 1185               }
 1186   
 1187               return (currentFocusCycleRoot.appContext ==
 1188                       AppContext.getAppContext())
 1189                   ? currentFocusCycleRoot
 1190                   : null;
 1191           }
 1192       }
 1193   
 1194       /**
 1195        * Returns the current focus cycle root, even if the calling thread is in a
 1196        * different context than the current focus cycle root. If the focus owner
 1197        * is itself a focus cycle root, then it may be ambiguous as to which
 1198        * Components represent the next and previous Components to focus during
 1199        * normal focus traversal. In that case, the current focus cycle root is
 1200        * used to differentiate among the possibilities.
 1201        * <p>
 1202        * This method will throw a SecurityException if this KeyboardFocusManager
 1203        * is not the current KeyboardFocusManager for the calling thread's
 1204        * context.
 1205        *
 1206        * @return the current focus cycle root, or null if the current focus cycle
 1207        *         root is not a member of the calling thread's context
 1208        * @see #getCurrentFocusCycleRoot
 1209        * @see #setGlobalCurrentFocusCycleRoot
 1210        * @throws SecurityException if this KeyboardFocusManager is not the
 1211        *         current KeyboardFocusManager for the calling thread's context
 1212        */
 1213       protected Container getGlobalCurrentFocusCycleRoot()
 1214           throws SecurityException
 1215       {
 1216           synchronized (KeyboardFocusManager.class) {
 1217               if (this == getCurrentKeyboardFocusManager()) {
 1218                   return currentFocusCycleRoot;
 1219               } else {
 1220                   if (focusLog.isLoggable(PlatformLogger.FINER)) {
 1221                       focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
 1222                   }
 1223                   throw new SecurityException(notPrivileged);
 1224               }
 1225           }
 1226       }
 1227   
 1228       /**
 1229        * Sets the current focus cycle root. If the focus owner is itself a focus
 1230        * cycle root, then it may be ambiguous as to which Components represent
 1231        * the next and previous Components to focus during normal focus traversal.
 1232        * In that case, the current focus cycle root is used to differentiate
 1233        * among the possibilities.
 1234        * <p>
 1235        * This method is intended to be used only by KeyboardFocusManagers and
 1236        * focus implementations. It is not for general client use.
 1237        *
 1238        * @param newFocusCycleRoot the new focus cycle root
 1239        * @see #getCurrentFocusCycleRoot
 1240        * @see #getGlobalCurrentFocusCycleRoot
 1241        * @beaninfo
 1242        *       bound: true
 1243        */
 1244       public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
 1245           Container oldFocusCycleRoot;
 1246   
 1247           synchronized (KeyboardFocusManager.class) {
 1248               oldFocusCycleRoot  = getCurrentFocusCycleRoot();
 1249               currentFocusCycleRoot = newFocusCycleRoot;
 1250           }
 1251   
 1252           firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
 1253                              newFocusCycleRoot);
 1254       }
 1255   
 1256       /**
 1257        * Adds a PropertyChangeListener to the listener list. The listener is
 1258        * registered for all bound properties of this class, including the
 1259        * following:
 1260        * <ul>
 1261        *    <li>whether the KeyboardFocusManager is currently managing focus
 1262        *        for this application or applet's browser context
 1263        *        ("managingFocus")</li>
 1264        *    <li>the focus owner ("focusOwner")</li>
 1265        *    <li>the permanent focus owner ("permanentFocusOwner")</li>
 1266        *    <li>the focused Window ("focusedWindow")</li>
 1267        *    <li>the active Window ("activeWindow")</li>
 1268        *    <li>the default focus traversal policy
 1269        *        ("defaultFocusTraversalPolicy")</li>
 1270        *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
 1271        *        ("forwardDefaultFocusTraversalKeys")</li>
 1272        *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
 1273        *        ("backwardDefaultFocusTraversalKeys")</li>
 1274        *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
 1275        *        ("upCycleDefaultFocusTraversalKeys")</li>
 1276        *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
 1277        *        ("downCycleDefaultFocusTraversalKeys")</li>
 1278        *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
 1279        * </ul>
 1280        * If listener is null, no exception is thrown and no action is performed.
 1281        *
 1282        * @param listener the PropertyChangeListener to be added
 1283        * @see #removePropertyChangeListener
 1284        * @see #getPropertyChangeListeners
 1285        * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1286        */
 1287       public void addPropertyChangeListener(PropertyChangeListener listener) {
 1288           if (listener != null) {
 1289               synchronized (this) {
 1290                   if (changeSupport == null) {
 1291                       changeSupport = new PropertyChangeSupport(this);
 1292                   }
 1293                   changeSupport.addPropertyChangeListener(listener);
 1294               }
 1295           }
 1296       }
 1297   
 1298       /**
 1299        * Removes a PropertyChangeListener from the listener list. This method
 1300        * should be used to remove the PropertyChangeListeners that were
 1301        * registered for all bound properties of this class.
 1302        * <p>
 1303        * If listener is null, no exception is thrown and no action is performed.
 1304        *
 1305        * @param listener the PropertyChangeListener to be removed
 1306        * @see #addPropertyChangeListener
 1307        * @see #getPropertyChangeListeners
 1308        * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1309        */
 1310       public void removePropertyChangeListener(PropertyChangeListener listener) {
 1311           if (listener != null) {
 1312               synchronized (this) {
 1313                   if (changeSupport != null) {
 1314                       changeSupport.removePropertyChangeListener(listener);
 1315                   }
 1316               }
 1317           }
 1318       }
 1319   
 1320       /**
 1321        * Returns an array of all the property change listeners
 1322        * registered on this keyboard focus manager.
 1323        *
 1324        * @return all of this keyboard focus manager's
 1325        *         <code>PropertyChangeListener</code>s
 1326        *         or an empty array if no property change
 1327        *         listeners are currently registered
 1328        *
 1329        * @see #addPropertyChangeListener
 1330        * @see #removePropertyChangeListener
 1331        * @see #getPropertyChangeListeners(java.lang.String)
 1332        * @since 1.4
 1333        */
 1334       public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
 1335           if (changeSupport == null) {
 1336               changeSupport = new PropertyChangeSupport(this);
 1337           }
 1338           return changeSupport.getPropertyChangeListeners();
 1339       }
 1340   
 1341       /**
 1342        * Adds a PropertyChangeListener to the listener list for a specific
 1343        * property. The specified property may be user-defined, or one of the
 1344        * following:
 1345        * <ul>
 1346        *    <li>whether the KeyboardFocusManager is currently managing focus
 1347        *        for this application or applet's browser context
 1348        *        ("managingFocus")</li>
 1349        *    <li>the focus owner ("focusOwner")</li>
 1350        *    <li>the permanent focus owner ("permanentFocusOwner")</li>
 1351        *    <li>the focused Window ("focusedWindow")</li>
 1352        *    <li>the active Window ("activeWindow")</li>
 1353        *    <li>the default focus traversal policy
 1354        *        ("defaultFocusTraversalPolicy")</li>
 1355        *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
 1356        *        ("forwardDefaultFocusTraversalKeys")</li>
 1357        *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
 1358        *        ("backwardDefaultFocusTraversalKeys")</li>
 1359        *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
 1360        *        ("upCycleDefaultFocusTraversalKeys")</li>
 1361        *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
 1362        *        ("downCycleDefaultFocusTraversalKeys")</li>
 1363        *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
 1364        * </ul>
 1365        * If listener is null, no exception is thrown and no action is performed.
 1366        *
 1367        * @param propertyName one of the property names listed above
 1368        * @param listener the PropertyChangeListener to be added
 1369        * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
 1370        * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1371        * @see #getPropertyChangeListeners(java.lang.String)
 1372        */
 1373       public void addPropertyChangeListener(String propertyName,
 1374                                             PropertyChangeListener listener) {
 1375           if (listener != null) {
 1376               synchronized (this) {
 1377                   if (changeSupport == null) {
 1378                       changeSupport = new PropertyChangeSupport(this);
 1379                   }
 1380                   changeSupport.addPropertyChangeListener(propertyName,
 1381                                                           listener);
 1382               }
 1383           }
 1384       }
 1385   
 1386       /**
 1387        * Removes a PropertyChangeListener from the listener list for a specific
 1388        * property. This method should be used to remove PropertyChangeListeners
 1389        * that were registered for a specific bound property.
 1390        * <p>
 1391        * If listener is null, no exception is thrown and no action is performed.
 1392        *
 1393        * @param propertyName a valid property name
 1394        * @param listener the PropertyChangeListener to be removed
 1395        * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1396        * @see #getPropertyChangeListeners(java.lang.String)
 1397        * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
 1398        */
 1399       public void removePropertyChangeListener(String propertyName,
 1400                                                PropertyChangeListener listener) {
 1401           if (listener != null) {
 1402               synchronized (this) {
 1403                   if (changeSupport != null) {
 1404                       changeSupport.removePropertyChangeListener(propertyName,
 1405                                                                  listener);
 1406                   }
 1407               }
 1408           }
 1409       }
 1410   
 1411       /**
 1412        * Returns an array of all the <code>PropertyChangeListener</code>s
 1413        * associated with the named property.
 1414        *
 1415        * @return all of the <code>PropertyChangeListener</code>s associated with
 1416        *         the named property or an empty array if no such listeners have
 1417        *         been added.
 1418        *
 1419        * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1420        * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
 1421        * @since 1.4
 1422        */
 1423       public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
 1424           if (changeSupport == null) {
 1425               changeSupport = new PropertyChangeSupport(this);
 1426           }
 1427           return changeSupport.getPropertyChangeListeners(propertyName);
 1428       }
 1429   
 1430       /**
 1431        * Fires a PropertyChangeEvent in response to a change in a bound property.
 1432        * The event will be delivered to all registered PropertyChangeListeners.
 1433        * No event will be delivered if oldValue and newValue are the same.
 1434        *
 1435        * @param propertyName the name of the property that has changed
 1436        * @param oldValue the property's previous value
 1437        * @param newValue the property's new value
 1438        */
 1439       protected void firePropertyChange(String propertyName, Object oldValue,
 1440                                         Object newValue)
 1441       {
 1442           if (oldValue == newValue) {
 1443               return;
 1444           }
 1445           PropertyChangeSupport changeSupport = this.changeSupport;
 1446           if (changeSupport != null) {
 1447               changeSupport.firePropertyChange(propertyName, oldValue, newValue);
 1448           }
 1449       }
 1450   
 1451       /**
 1452        * Adds a VetoableChangeListener to the listener list. The listener is
 1453        * registered for all vetoable properties of this class, including the
 1454        * following:
 1455        * <ul>
 1456        *    <li>the focus owner ("focusOwner")</li>
 1457        *    <li>the permanent focus owner ("permanentFocusOwner")</li>
 1458        *    <li>the focused Window ("focusedWindow")</li>
 1459        *    <li>the active Window ("activeWindow")</li>
 1460        * </ul>
 1461        * If listener is null, no exception is thrown and no action is performed.
 1462        *
 1463        * @param listener the VetoableChangeListener to be added
 1464        * @see #removeVetoableChangeListener
 1465        * @see #getVetoableChangeListeners
 1466        * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
 1467        */
 1468       public void addVetoableChangeListener(VetoableChangeListener listener) {
 1469           if (listener != null) {
 1470               synchronized (this) {
 1471                   if (vetoableSupport == null) {
 1472                       vetoableSupport =
 1473                           new VetoableChangeSupport(this);
 1474                   }
 1475                   vetoableSupport.addVetoableChangeListener(listener);
 1476               }
 1477           }
 1478       }
 1479   
 1480       /**
 1481        * Removes a VetoableChangeListener from the listener list. This method
 1482        * should be used to remove the VetoableChangeListeners that were
 1483        * registered for all vetoable properties of this class.
 1484        * <p>
 1485        * If listener is null, no exception is thrown and no action is performed.
 1486        *
 1487        * @param listener the VetoableChangeListener to be removed
 1488        * @see #addVetoableChangeListener
 1489        * @see #getVetoableChangeListeners
 1490        * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
 1491        */
 1492       public void removeVetoableChangeListener(VetoableChangeListener listener) {
 1493           if (listener != null) {
 1494               synchronized (this) {
 1495                   if (vetoableSupport != null) {
 1496                       vetoableSupport.removeVetoableChangeListener(listener);
 1497                   }
 1498               }
 1499           }
 1500       }
 1501   
 1502       /**
 1503        * Returns an array of all the vetoable change listeners
 1504        * registered on this keyboard focus manager.
 1505        *
 1506        * @return all of this keyboard focus manager's
 1507        *         <code>VetoableChangeListener</code>s
 1508        *         or an empty array if no vetoable change
 1509        *         listeners are currently registered
 1510        *
 1511        * @see #addVetoableChangeListener
 1512        * @see #removeVetoableChangeListener
 1513        * @see #getVetoableChangeListeners(java.lang.String)
 1514        * @since 1.4
 1515        */
 1516       public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
 1517           if (vetoableSupport == null) {
 1518               vetoableSupport = new VetoableChangeSupport(this);
 1519           }
 1520           return vetoableSupport.getVetoableChangeListeners();
 1521       }
 1522   
 1523       /**
 1524        * Adds a VetoableChangeListener to the listener list for a specific
 1525        * property. The specified property may be user-defined, or one of the
 1526        * following:
 1527        * <ul>
 1528        *    <li>the focus owner ("focusOwner")</li>
 1529        *    <li>the permanent focus owner ("permanentFocusOwner")</li>
 1530        *    <li>the focused Window ("focusedWindow")</li>
 1531        *    <li>the active Window ("activeWindow")</li>
 1532        * </ul>
 1533        * If listener is null, no exception is thrown and no action is performed.
 1534        *
 1535        * @param propertyName one of the property names listed above
 1536        * @param listener the VetoableChangeListener to be added
 1537        * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
 1538        * @see #removeVetoableChangeListener
 1539        * @see #getVetoableChangeListeners
 1540        */
 1541       public void addVetoableChangeListener(String propertyName,
 1542                                             VetoableChangeListener listener) {
 1543           if (listener != null) {
 1544               synchronized (this) {
 1545                   if (vetoableSupport == null) {
 1546                       vetoableSupport =
 1547                           new VetoableChangeSupport(this);
 1548                   }
 1549                   vetoableSupport.addVetoableChangeListener(propertyName,
 1550                                                             listener);
 1551               }
 1552           }
 1553       }
 1554   
 1555       /**
 1556        * Removes a VetoableChangeListener from the listener list for a specific
 1557        * property. This method should be used to remove VetoableChangeListeners
 1558        * that were registered for a specific bound property.
 1559        * <p>
 1560        * If listener is null, no exception is thrown and no action is performed.
 1561        *
 1562        * @param propertyName a valid property name
 1563        * @param listener the VetoableChangeListener to be removed
 1564        * @see #addVetoableChangeListener
 1565        * @see #getVetoableChangeListeners
 1566        * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
 1567        */
 1568       public void removeVetoableChangeListener(String propertyName,
 1569                                                VetoableChangeListener listener) {
 1570           if (listener != null) {
 1571               synchronized (this) {
 1572                   if (vetoableSupport != null) {
 1573                       vetoableSupport.removeVetoableChangeListener(propertyName,
 1574                                                                    listener);
 1575                   }
 1576               }
 1577           }
 1578       }
 1579   
 1580       /**
 1581        * Returns an array of all the <code>VetoableChangeListener</code>s
 1582        * associated with the named property.
 1583        *
 1584        * @return all of the <code>VetoableChangeListener</code>s associated with
 1585        *         the named property or an empty array if no such listeners have
 1586        *         been added.
 1587        *
 1588        * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
 1589        * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
 1590        * @see #getVetoableChangeListeners
 1591        * @since 1.4
 1592        */
 1593       public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
 1594           if (vetoableSupport == null) {
 1595               vetoableSupport = new VetoableChangeSupport(this);
 1596           }
 1597           return vetoableSupport.getVetoableChangeListeners(propertyName);
 1598       }
 1599   
 1600       /**
 1601        * Fires a PropertyChangeEvent in response to a change in a vetoable
 1602        * property. The event will be delivered to all registered
 1603        * VetoableChangeListeners. If a VetoableChangeListener throws a
 1604        * PropertyVetoException, a new event is fired reverting all
 1605        * VetoableChangeListeners to the old value and the exception is then
 1606        * rethrown. No event will be delivered if oldValue and newValue are the
 1607        * same.
 1608        *
 1609        * @param propertyName the name of the property that has changed
 1610        * @param oldValue the property's previous value
 1611        * @param newValue the property's new value
 1612        * @throws java.beans.PropertyVetoException if a
 1613        *         <code>VetoableChangeListener</code> threw
 1614        *         <code>PropertyVetoException</code>
 1615        */
 1616       protected void fireVetoableChange(String propertyName, Object oldValue,
 1617                                         Object newValue)
 1618           throws PropertyVetoException
 1619       {
 1620           if (oldValue == newValue) {
 1621               return;
 1622           }
 1623           VetoableChangeSupport vetoableSupport =
 1624               this.vetoableSupport;
 1625           if (vetoableSupport != null) {
 1626               vetoableSupport.fireVetoableChange(propertyName, oldValue,
 1627                                                  newValue);
 1628           }
 1629       }
 1630   
 1631       /**
 1632        * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
 1633        * chain. This KeyboardFocusManager will request that each
 1634        * KeyEventDispatcher dispatch KeyEvents generated by the user before
 1635        * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
 1636        * notified in the order in which they were added. Notifications will halt
 1637        * as soon as one KeyEventDispatcher returns <code>true</code> from its
 1638        * <code>dispatchKeyEvent</code> method. There is no limit to the total
 1639        * number of KeyEventDispatchers which can be added, nor to the number of
 1640        * times which a particular KeyEventDispatcher instance can be added.
 1641        * <p>
 1642        * If a null dispatcher is specified, no action is taken and no exception
 1643        * is thrown.
 1644        * <p>
 1645        * In a multithreaded application, {@link KeyEventDispatcher} behaves
 1646        * the same as other AWT listeners.  See
 1647        * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1648        * >AWT Threading Issues</a> for more details.
 1649        *
 1650        * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
 1651        * @see #removeKeyEventDispatcher
 1652        */
 1653       public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
 1654           if (dispatcher != null) {
 1655               synchronized (this) {
 1656                   if (keyEventDispatchers == null) {
 1657                       keyEventDispatchers = new java.util.LinkedList();
 1658                   }
 1659                   keyEventDispatchers.add(dispatcher);
 1660               }
 1661           }
 1662       }
 1663   
 1664       /**
 1665        * Removes a KeyEventDispatcher which was previously added to this
 1666        * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
 1667        * cannot itself be removed, unless it was explicitly re-registered via a
 1668        * call to <code>addKeyEventDispatcher</code>.
 1669        * <p>
 1670        * If a null dispatcher is specified, if the specified dispatcher is not
 1671        * in the dispatcher chain, or if this KeyboardFocusManager is specified
 1672        * without having been explicitly re-registered, no action is taken and no
 1673        * exception is thrown.
 1674        * <p>
 1675        * In a multithreaded application, {@link KeyEventDispatcher} behaves
 1676        * the same as other AWT listeners.  See
 1677        * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1678        * >AWT Threading Issues</a> for more details.
 1679        *
 1680        * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
 1681        *        chain
 1682        * @see #addKeyEventDispatcher
 1683        */
 1684       public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
 1685           if (dispatcher != null) {
 1686               synchronized (this) {
 1687                   if (keyEventDispatchers != null) {
 1688                       keyEventDispatchers.remove(dispatcher);
 1689                   }
 1690               }
 1691           }
 1692       }
 1693   
 1694       /**
 1695        * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
 1696        * The List will not include this KeyboardFocusManager unless it was
 1697        * explicitly re-registered via a call to
 1698        * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
 1699        * registered, implementations are free to return null or a List of length
 1700        * 0. Client code should not assume one behavior over another, nor should
 1701        * it assume that the behavior, once established, will not change.
 1702        *
 1703        * @return a possibly null or empty List of KeyEventDispatchers
 1704        * @see #addKeyEventDispatcher
 1705        * @see #removeKeyEventDispatcher
 1706        */
 1707       protected synchronized java.util.List<KeyEventDispatcher>
 1708           getKeyEventDispatchers()
 1709       {
 1710           return (keyEventDispatchers != null)
 1711               ? (java.util.List)keyEventDispatchers.clone()
 1712               : null;
 1713       }
 1714   
 1715       /**
 1716        * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
 1717        * processor chain. After a KeyEvent has been dispatched to and handled by
 1718        * its target, KeyboardFocusManager will request that each
 1719        * KeyEventPostProcessor perform any necessary post-processing as part
 1720        * of the KeyEvent's final resolution. KeyEventPostProcessors
 1721        * will be notified in the order in which they were added; the current
 1722        * KeyboardFocusManager will be notified last. Notifications will halt
 1723        * as soon as one KeyEventPostProcessor returns <code>true</code> from its
 1724        * <code>postProcessKeyEvent</code> method. There is no limit to the the
 1725        * total number of KeyEventPostProcessors that can be added, nor to the
 1726        * number of times that a particular KeyEventPostProcessor instance can be
 1727        * added.
 1728        * <p>
 1729        * If a null post-processor is specified, no action is taken and no
 1730        * exception is thrown.
 1731        * <p>
 1732        * In a multithreaded application, {@link KeyEventPostProcessor} behaves
 1733        * the same as other AWT listeners.  See
 1734        * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1735        * >AWT Threading Issues</a> for more details.
 1736        *
 1737        * @param processor the KeyEventPostProcessor to add to the post-processor
 1738        *        chain
 1739        * @see #removeKeyEventPostProcessor
 1740        */
 1741       public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
 1742           if (processor != null) {
 1743               synchronized (this) {
 1744                   if (keyEventPostProcessors == null) {
 1745                       keyEventPostProcessors = new java.util.LinkedList();
 1746                   }
 1747                   keyEventPostProcessors.add(processor);
 1748               }
 1749           }
 1750       }
 1751   
 1752   
 1753       /**
 1754        * Removes a previously added KeyEventPostProcessor from this
 1755        * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
 1756        * cannot itself be entirely removed from the chain. Only additional
 1757        * references added via <code>addKeyEventPostProcessor</code> can be
 1758        * removed.
 1759        * <p>
 1760        * If a null post-processor is specified, if the specified post-processor
 1761        * is not in the post-processor chain, or if this KeyboardFocusManager is
 1762        * specified without having been explicitly added, no action is taken and
 1763        * no exception is thrown.
 1764        * <p>
 1765        * In a multithreaded application, {@link KeyEventPostProcessor} behaves
 1766        * the same as other AWT listeners.  See
 1767        * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
 1768        * >AWT Threading Issues</a> for more details.
 1769        *
 1770        * @param processor the KeyEventPostProcessor to remove from the post-
 1771        *        processor chain
 1772        * @see #addKeyEventPostProcessor
 1773        */
 1774       public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
 1775           if (processor != null) {
 1776               synchronized (this) {
 1777                   if (keyEventPostProcessors != null) {
 1778                       keyEventPostProcessors.remove(processor);
 1779                   }
 1780               }
 1781           }
 1782       }
 1783   
 1784   
 1785       /**
 1786        * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
 1787        * List. The List will not include this KeyboardFocusManager unless it was
 1788        * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
 1789        * no KeyEventPostProcessors are registered, implementations are free to
 1790        * return null or a List of length 0. Client code should not assume one
 1791        * behavior over another, nor should it assume that the behavior, once
 1792        * established, will not change.
 1793        *
 1794        * @return a possibly null or empty List of KeyEventPostProcessors
 1795        * @see #addKeyEventPostProcessor
 1796        * @see #removeKeyEventPostProcessor
 1797        */
 1798       protected java.util.List<KeyEventPostProcessor>
 1799           getKeyEventPostProcessors()
 1800       {
 1801           return (keyEventPostProcessors != null)
 1802               ? (java.util.List)keyEventPostProcessors.clone()
 1803               : null;
 1804       }
 1805   
 1806   
 1807   
 1808       static void setMostRecentFocusOwner(Component component) {
 1809           Component window = component;
 1810           while (window != null && !(window instanceof Window)) {
 1811               window = window.parent;
 1812           }
 1813           if (window != null) {
 1814               setMostRecentFocusOwner((Window)window, component);
 1815           }
 1816       }
 1817       static synchronized void setMostRecentFocusOwner(Window window,
 1818                                                        Component component) {
 1819           // ATTN: component has a strong reference to window via chain
 1820           // of Component.parent fields.  Since WeakHasMap refers to its
 1821           // values strongly, we need to break the strong link from the
 1822           // value (component) back to its key (window).
 1823           WeakReference weakValue = null;
 1824           if (component != null) {
 1825               weakValue = new WeakReference(component);
 1826           }
 1827           mostRecentFocusOwners.put(window, weakValue);
 1828       }
 1829       static void clearMostRecentFocusOwner(Component comp) {
 1830           Container window;
 1831   
 1832           if (comp == null) {
 1833               return;
 1834           }
 1835   
 1836           synchronized (comp.getTreeLock()) {
 1837               window = comp.getParent();
 1838               while (window != null && !(window instanceof Window)) {
 1839                   window = window.getParent();
 1840               }
 1841           }
 1842   
 1843           synchronized (KeyboardFocusManager.class) {
 1844               if ((window != null)
 1845                   && (getMostRecentFocusOwner((Window)window) == comp))
 1846               {
 1847                   setMostRecentFocusOwner((Window)window, null);
 1848               }
 1849               // Also clear temporary lost component stored in Window
 1850               if (window != null) {
 1851                   Window realWindow = (Window)window;
 1852                   if (realWindow.getTemporaryLostComponent() == comp) {
 1853                       realWindow.setTemporaryLostComponent(null);
 1854                   }
 1855               }
 1856           }
 1857       }
 1858   
 1859       /*
 1860        * Please be careful changing this method! It is called from
 1861        * javax.swing.JComponent.runInputVerifier() using reflection.
 1862        */
 1863       static synchronized Component getMostRecentFocusOwner(Window window) {
 1864           WeakReference weakValue =
 1865               (WeakReference)mostRecentFocusOwners.get(window);
 1866           return weakValue == null ? null : (Component)weakValue.get();
 1867       }
 1868   
 1869       /**
 1870        * This method is called by the AWT event dispatcher requesting that the
 1871        * current KeyboardFocusManager dispatch the specified event on its behalf.
 1872        * It is expected that all KeyboardFocusManagers will dispatch all
 1873        * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
 1874        * These events should be dispatched based on the KeyboardFocusManager's
 1875        * notion of the focus owner and the focused and active Windows, sometimes
 1876        * overriding the source of the specified AWTEvent. Dispatching must be
 1877        * done using <code>redispatchEvent</code> to prevent the AWT event
 1878        * dispatcher from recursively requesting that the KeyboardFocusManager
 1879        * dispatch the event again. If this method returns <code>false</code>,
 1880        * then the AWT event dispatcher will attempt to dispatch the event itself.
 1881        *
 1882        * @param e the AWTEvent to be dispatched
 1883        * @return <code>true</code> if this method dispatched the event;
 1884        *         <code>false</code> otherwise
 1885        * @see #redispatchEvent
 1886        * @see #dispatchKeyEvent
 1887        */
 1888       public abstract boolean dispatchEvent(AWTEvent e);
 1889   
 1890       /**
 1891        * Redispatches an AWTEvent in such a way that the AWT event dispatcher
 1892        * will not recursively request that the KeyboardFocusManager, or any
 1893        * installed KeyEventDispatchers, dispatch the event again. Client
 1894        * implementations of <code>dispatchEvent</code> and client-defined
 1895        * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
 1896        * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
 1897        * <p>
 1898        * This method is intended to be used only by KeyboardFocusManagers and
 1899        * KeyEventDispatchers. It is not for general client use.
 1900        *
 1901        * @param target the Component to which the event should be dispatched
 1902        * @param e the event to dispatch
 1903        * @see #dispatchEvent
 1904        * @see KeyEventDispatcher
 1905        */
 1906       public final void redispatchEvent(Component target, AWTEvent e) {
 1907           e.focusManagerIsDispatching = true;
 1908           target.dispatchEvent(e);
 1909           e.focusManagerIsDispatching = false;
 1910       }
 1911   
 1912       /**
 1913        * Typically this method will be called by <code>dispatchEvent</code> if no
 1914        * other KeyEventDispatcher in the dispatcher chain dispatched the
 1915        * KeyEvent, or if no other KeyEventDispatchers are registered. If an
 1916        * implementation of this method returns <code>false</code>,
 1917        * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
 1918        * may simply return <code>false</code>. If <code>true</code> is returned,
 1919        * <code>dispatchEvent</code> should return <code>true</code> as well.
 1920        *
 1921        * @param e the KeyEvent which the current KeyboardFocusManager has
 1922        *        requested that this KeyEventDispatcher dispatch
 1923        * @return <code>true</code> if the KeyEvent was dispatched;
 1924        *         <code>false</code> otherwise
 1925        * @see #dispatchEvent
 1926        */
 1927       public abstract boolean dispatchKeyEvent(KeyEvent e);
 1928   
 1929       /**
 1930        * This method will be called by <code>dispatchKeyEvent</code>.
 1931        * By default, this method will handle any unconsumed KeyEvents that
 1932        * map to an AWT <code>MenuShortcut</code> by consuming the event
 1933        * and activating the shortcut.
 1934        *
 1935        * @param e the KeyEvent to post-process
 1936        * @return <code>true</code> to indicate that no other
 1937        *         KeyEventPostProcessor will be notified of the KeyEvent.
 1938        * @see #dispatchKeyEvent
 1939        * @see MenuShortcut
 1940        */
 1941       public abstract boolean postProcessKeyEvent(KeyEvent e);
 1942   
 1943       /**
 1944        * This method initiates a focus traversal operation if and only if the
 1945        * KeyEvent represents a focus traversal key for the specified
 1946        * focusedComponent. It is expected that focusedComponent is the current
 1947        * focus owner, although this need not be the case. If it is not,
 1948        * focus traversal will nevertheless proceed as if focusedComponent
 1949        * were the current focus owner.
 1950        *
 1951        * @param focusedComponent the Component that will be the basis for a focus
 1952        *        traversal operation if the specified event represents a focus
 1953        *        traversal key for the Component
 1954        * @param e the event that may represent a focus traversal key
 1955        */
 1956       public abstract void processKeyEvent(Component focusedComponent,
 1957                                            KeyEvent e);
 1958   
 1959       /**
 1960        * Called by the AWT to notify the KeyboardFocusManager that it should
 1961        * delay dispatching of KeyEvents until the specified Component becomes
 1962        * the focus owner. If client code requests a focus change, and the AWT
 1963        * determines that this request might be granted by the native windowing
 1964        * system, then the AWT will call this method. It is the responsibility of
 1965        * the KeyboardFocusManager to delay dispatching of KeyEvents with
 1966        * timestamps later than the specified time stamp until the specified
 1967        * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
 1968        * request by invoking <code>dequeueKeyEvents</code> or
 1969        * <code>discardKeyEvents</code>.
 1970        *
 1971        * @param after timestamp of current event, or the current, system time if
 1972        *        the current event has no timestamp, or the AWT cannot determine
 1973        *        which event is currently being handled
 1974        * @param untilFocused Component which should receive a FOCUS_GAINED event
 1975        *        before any pending KeyEvents
 1976        * @see #dequeueKeyEvents
 1977        * @see #discardKeyEvents
 1978        */
 1979       protected abstract void enqueueKeyEvents(long after,
 1980                                                Component untilFocused);
 1981   
 1982       /**
 1983        * Called by the AWT to notify the KeyboardFocusManager that it should
 1984        * cancel delayed dispatching of KeyEvents. All KeyEvents which were
 1985        * enqueued because of a call to <code>enqueueKeyEvents</code> with the
 1986        * same timestamp and Component should be released for normal dispatching
 1987        * to the current focus owner. If the given timestamp is less than zero,
 1988        * the outstanding enqueue request for the given Component with the <b>
 1989        * oldest</b> timestamp (if any) should be cancelled.
 1990        *
 1991        * @param after the timestamp specified in the call to
 1992        *        <code>enqueueKeyEvents</code>, or any value < 0
 1993        * @param untilFocused the Component specified in the call to
 1994        *        <code>enqueueKeyEvents</code>
 1995        * @see #enqueueKeyEvents
 1996        * @see #discardKeyEvents
 1997        */
 1998       protected abstract void dequeueKeyEvents(long after,
 1999                                                Component untilFocused);
 2000   
 2001       /**
 2002        * Called by the AWT to notify the KeyboardFocusManager that it should
 2003        * cancel delayed dispatching of KeyEvents. All KeyEvents which were
 2004        * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
 2005        * with the same Component should be discarded.
 2006        *
 2007        * @param comp the Component specified in one or more calls to
 2008        *        <code>enqueueKeyEvents</code>
 2009        * @see #enqueueKeyEvents
 2010        * @see #dequeueKeyEvents
 2011        */
 2012       protected abstract void discardKeyEvents(Component comp);
 2013   
 2014       /**
 2015        * Focuses the Component after aComponent, typically based on a
 2016        * FocusTraversalPolicy.
 2017        *
 2018        * @param aComponent the Component that is the basis for the focus
 2019        *        traversal operation
 2020        * @see FocusTraversalPolicy
 2021        */
 2022       public abstract void focusNextComponent(Component aComponent);
 2023   
 2024       /**
 2025        * Focuses the Component before aComponent, typically based on a
 2026        * FocusTraversalPolicy.
 2027        *
 2028        * @param aComponent the Component that is the basis for the focus
 2029        *        traversal operation
 2030        * @see FocusTraversalPolicy
 2031        */
 2032       public abstract void focusPreviousComponent(Component aComponent);
 2033   
 2034       /**
 2035        * Moves the focus up one focus traversal cycle. Typically, the focus owner
 2036        * is set to aComponent's focus cycle root, and the current focus cycle
 2037        * root is set to the new focus owner's focus cycle root. If, however,
 2038        * aComponent's focus cycle root is a Window, then typically the focus
 2039        * owner is set to the Window's default Component to focus, and the current
 2040        * focus cycle root is unchanged.
 2041        *
 2042        * @param aComponent the Component that is the basis for the focus
 2043        *        traversal operation
 2044        */
 2045       public abstract void upFocusCycle(Component aComponent);
 2046   
 2047       /**
 2048        * Moves the focus down one focus traversal cycle. Typically, if
 2049        * aContainer is a focus cycle root, then the focus owner is set to
 2050        * aContainer's default Component to focus, and the current focus cycle
 2051        * root is set to aContainer. If aContainer is not a focus cycle root, then
 2052        * no focus traversal operation occurs.
 2053        *
 2054        * @param aContainer the Container that is the basis for the focus
 2055        *        traversal operation
 2056        */
 2057       public abstract void downFocusCycle(Container aContainer);
 2058   
 2059       /**
 2060        * Focuses the Component after the current focus owner.
 2061        */
 2062       public final void focusNextComponent() {
 2063           Component focusOwner = getFocusOwner();
 2064           if (focusOwner != null) {
 2065               focusNextComponent(focusOwner);
 2066           }
 2067       }
 2068   
 2069       /**
 2070        * Focuses the Component before the current focus owner.
 2071        */
 2072       public final void focusPreviousComponent() {
 2073           Component focusOwner = getFocusOwner();
 2074           if (focusOwner != null) {
 2075               focusPreviousComponent(focusOwner);
 2076           }
 2077       }
 2078   
 2079       /**
 2080        * Moves the focus up one focus traversal cycle from the current focus
 2081        * owner. Typically, the new focus owner is set to the current focus
 2082        * owner's focus cycle root, and the current focus cycle root is set to the
 2083        * new focus owner's focus cycle root. If, however, the current focus
 2084        * owner's focus cycle root is a Window, then typically the focus owner is
 2085        * set to the focus cycle root's default Component to focus, and the
 2086        * current focus cycle root is unchanged.
 2087        */
 2088       public final void upFocusCycle() {
 2089           Component focusOwner = getFocusOwner();
 2090           if (focusOwner != null) {
 2091               upFocusCycle(focusOwner);
 2092           }
 2093       }
 2094   
 2095       /**
 2096        * Moves the focus down one focus traversal cycle from the current focus
 2097        * owner, if and only if the current focus owner is a Container that is a
 2098        * focus cycle root. Typically, the focus owner is set to the current focus
 2099        * owner's default Component to focus, and the current focus cycle root is
 2100        * set to the current focus owner. If the current focus owner is not a
 2101        * Container that is a focus cycle root, then no focus traversal operation
 2102        * occurs.
 2103        */
 2104       public final void downFocusCycle() {
 2105           Component focusOwner = getFocusOwner();
 2106           if (focusOwner instanceof Container) {
 2107               downFocusCycle((Container)focusOwner);
 2108           }
 2109       }
 2110   
 2111       /**
 2112        * Dumps the list of focus requests to stderr
 2113        */
 2114       void dumpRequests() {
 2115           System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
 2116           synchronized (heavyweightRequests) {
 2117               for (HeavyweightFocusRequest req : heavyweightRequests) {
 2118                   System.err.println(">>> Req: " + req);
 2119               }
 2120           }
 2121           System.err.println("");
 2122       }
 2123   
 2124       private static final class LightweightFocusRequest {
 2125           final Component component;
 2126           final boolean temporary;
 2127           final CausedFocusEvent.Cause cause;
 2128   
 2129           LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
 2130               this.component = component;
 2131               this.temporary = temporary;
 2132               this.cause = cause;
 2133           }
 2134           public String toString() {
 2135               return "LightweightFocusRequest[component=" + component +
 2136                   ",temporary=" + temporary + ", cause=" + cause + "]";
 2137           }
 2138       }
 2139   
 2140       private static final class HeavyweightFocusRequest {
 2141           final Component heavyweight;
 2142           final LinkedList<LightweightFocusRequest> lightweightRequests;
 2143   
 2144           static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
 2145               new HeavyweightFocusRequest();
 2146   
 2147           private HeavyweightFocusRequest() {
 2148               heavyweight = null;
 2149               lightweightRequests = null;
 2150           }
 2151   
 2152           HeavyweightFocusRequest(Component heavyweight, Component descendant,
 2153                                   boolean temporary, CausedFocusEvent.Cause cause) {
 2154               if (log.isLoggable(PlatformLogger.FINE)) {
 2155                   if (heavyweight == null) {
 2156                       log.fine("Assertion (heavyweight != null) failed");
 2157                   }
 2158               }
 2159   
 2160               this.heavyweight = heavyweight;
 2161               this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
 2162               addLightweightRequest(descendant, temporary, cause);
 2163           }
 2164           boolean addLightweightRequest(Component descendant,
 2165                                         boolean temporary, CausedFocusEvent.Cause cause) {
 2166               if (log.isLoggable(PlatformLogger.FINE)) {
 2167                   if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
 2168                       log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
 2169                   }
 2170                   if (descendant == null) {
 2171                       log.fine("Assertion (descendant != null) failed");
 2172                   }
 2173               }
 2174   
 2175               Component lastDescendant = ((lightweightRequests.size() > 0)
 2176                   ? lightweightRequests.getLast().component
 2177                   : null);
 2178   
 2179               if (descendant != lastDescendant) {
 2180                   // Not a duplicate request
 2181                   lightweightRequests.add
 2182                       (new LightweightFocusRequest(descendant, temporary, cause));
 2183                   return true;
 2184               } else {
 2185                   return false;
 2186               }
 2187           }
 2188   
 2189           LightweightFocusRequest getFirstLightweightRequest() {
 2190               if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
 2191                   return null;
 2192               }
 2193               return lightweightRequests.getFirst();
 2194           }
 2195           public String toString() {
 2196               boolean first = true;
 2197               String str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
 2198                   ",lightweightRequests=";
 2199               if (lightweightRequests == null) {
 2200                   str += null;
 2201               } else {
 2202                   str += "[";
 2203   
 2204                   for (LightweightFocusRequest lwRequest : lightweightRequests) {
 2205                       if (first) {
 2206                           first = false;
 2207                       } else {
 2208                           str += ",";
 2209                       }
 2210                       str += lwRequest;
 2211                   }
 2212                   str += "]";
 2213               }
 2214               str += "]";
 2215               return str;
 2216           }
 2217       }
 2218   
 2219       /*
 2220        * heavyweightRequests is used as a monitor for synchronized changes of
 2221        * currentLightweightRequests, clearingCurrentLightweightRequests and
 2222        * newFocusOwner.
 2223        */
 2224       private static LinkedList<HeavyweightFocusRequest> heavyweightRequests =
 2225           new LinkedList<HeavyweightFocusRequest>();
 2226       private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
 2227       private static boolean clearingCurrentLightweightRequests;
 2228       private static boolean allowSyncFocusRequests = true;
 2229       private static Component newFocusOwner = null;
 2230       private static volatile boolean disableRestoreFocus;
 2231   
 2232       static final int SNFH_FAILURE = 0;
 2233       static final int SNFH_SUCCESS_HANDLED = 1;
 2234       static final int SNFH_SUCCESS_PROCEED = 2;
 2235   
 2236       static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
 2237                                                     boolean temporary, boolean focusedWindowChangeAllowed,
 2238                                                     long time)
 2239       {
 2240           Window parentWindow = SunToolkit.getContainingWindow(heavyweight);
 2241           if (parentWindow == null || !parentWindow.syncLWRequests) {
 2242               return false;
 2243           }
 2244           if (descendant == null) {
 2245               // Focus transfers from a lightweight child back to the
 2246               // heavyweight Container should be treated like lightweight
 2247               // focus transfers.
 2248               descendant = heavyweight;
 2249           }
 2250   
 2251           KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
 2252   
 2253           FocusEvent currentFocusOwnerEvent = null;
 2254           FocusEvent newFocusOwnerEvent = null;
 2255           Component currentFocusOwner = manager.getGlobalFocusOwner();
 2256   
 2257           synchronized (heavyweightRequests) {
 2258               HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
 2259               if (hwFocusRequest == null &&
 2260                   heavyweight == manager.getNativeFocusOwner() &&
 2261                   allowSyncFocusRequests)
 2262               {
 2263   
 2264                   if (descendant == currentFocusOwner) {
 2265                       // Redundant request.
 2266                       return true;
 2267                   }
 2268   
 2269                   // 'heavyweight' owns the native focus and there are no pending
 2270                   // requests. 'heavyweight' must be a Container and
 2271                   // 'descendant' must not be the focus owner. Otherwise,
 2272                   // we would never have gotten this far.
 2273                   manager.enqueueKeyEvents(time, descendant);
 2274   
 2275                   hwFocusRequest =
 2276                       new HeavyweightFocusRequest(heavyweight, descendant,
 2277                                                   temporary, CausedFocusEvent.Cause.UNKNOWN);
 2278                   heavyweightRequests.add(hwFocusRequest);
 2279   
 2280                   if (currentFocusOwner != null) {
 2281                       currentFocusOwnerEvent =
 2282                           new FocusEvent(currentFocusOwner,
 2283                                          FocusEvent.FOCUS_LOST,
 2284                                          temporary, descendant);
 2285                   }
 2286                   newFocusOwnerEvent =
 2287                       new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
 2288                                      temporary, currentFocusOwner);
 2289               }
 2290           }
 2291           boolean result = false;
 2292           final boolean clearing = clearingCurrentLightweightRequests;
 2293   
 2294           Throwable caughtEx = null;
 2295           try {
 2296               clearingCurrentLightweightRequests = false;
 2297               synchronized(Component.LOCK) {
 2298   
 2299                   if (currentFocusOwnerEvent != null && currentFocusOwner != null) {
 2300                       ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
 2301                       caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
 2302                       result = true;
 2303                   }
 2304   
 2305                   if (newFocusOwnerEvent != null && descendant != null) {
 2306                       ((AWTEvent) newFocusOwnerEvent).isPosted = true;
 2307                       caughtEx = dispatchAndCatchException(caughtEx, descendant, newFocusOwnerEvent);
 2308                       result = true;
 2309                   }
 2310               }
 2311           } finally {
 2312               clearingCurrentLightweightRequests = clearing;
 2313           }
 2314           if (caughtEx instanceof RuntimeException) {
 2315               throw (RuntimeException)caughtEx;
 2316           } else if (caughtEx instanceof Error) {
 2317               throw (Error)caughtEx;
 2318           }
 2319           return result;
 2320       }
 2321   
 2322       /**
 2323        * Indicates whether the native implementation should proceed with a
 2324        * pending, native focus request. Before changing the focus at the native
 2325        * level, the AWT implementation should always call this function for
 2326        * permission. This function will reject the request if a duplicate request
 2327        * preceded it, or if the specified heavyweight Component already owns the
 2328        * focus and no native focus changes are pending. Otherwise, the request
 2329        * will be approved and the focus request list will be updated so that,
 2330        * if necessary, the proper descendant will be focused when the
 2331        * corresponding FOCUS_GAINED event on the heavyweight is received.
 2332        *
 2333        * An implementation must ensure that calls to this method and native
 2334        * focus changes are atomic. If this is not guaranteed, then the ordering
 2335        * of the focus request list may be incorrect, leading to errors in the
 2336        * type-ahead mechanism. Typically this is accomplished by only calling
 2337        * this function from the native event pumping thread, or by holding a
 2338        * global, native lock during invocation.
 2339        */
 2340       static int shouldNativelyFocusHeavyweight
 2341           (Component heavyweight, Component descendant, boolean temporary,
 2342            boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
 2343       {
 2344           if (log.isLoggable(PlatformLogger.FINE)) {
 2345               if (heavyweight == null) {
 2346                   log.fine("Assertion (heavyweight != null) failed");
 2347               }
 2348               if (time == 0) {
 2349                   log.fine("Assertion (time != 0) failed");
 2350               }
 2351           }
 2352   
 2353           if (descendant == null) {
 2354               // Focus transfers from a lightweight child back to the
 2355               // heavyweight Container should be treated like lightweight
 2356               // focus transfers.
 2357               descendant = heavyweight;
 2358           }
 2359   
 2360           KeyboardFocusManager manager =
 2361               getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
 2362           KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();
 2363           Component currentFocusOwner = thisManager.getGlobalFocusOwner();
 2364           Component nativeFocusOwner = thisManager.getNativeFocusOwner();
 2365           Window nativeFocusedWindow = thisManager.getNativeFocusedWindow();
 2366           if (focusLog.isLoggable(PlatformLogger.FINER)) {
 2367               focusLog.finer("SNFH for {0} in {1}",
 2368                              String.valueOf(descendant), String.valueOf(heavyweight));
 2369           }
 2370           if (focusLog.isLoggable(PlatformLogger.FINEST)) {
 2371               focusLog.finest("0. Current focus owner {0}",
 2372                               String.valueOf(currentFocusOwner));
 2373               focusLog.finest("0. Native focus owner {0}",
 2374                               String.valueOf(nativeFocusOwner));
 2375               focusLog.finest("0. Native focused window {0}",
 2376                               String.valueOf(nativeFocusedWindow));
 2377           }
 2378           synchronized (heavyweightRequests) {
 2379               HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
 2380               if (focusLog.isLoggable(PlatformLogger.FINEST)) {
 2381                   focusLog.finest("Request {0}", String.valueOf(hwFocusRequest));
 2382               }
 2383               if (hwFocusRequest == null &&
 2384                   heavyweight == nativeFocusOwner)
 2385               {
 2386                   if (descendant == currentFocusOwner) {
 2387                       // Redundant request.
 2388                       if (focusLog.isLoggable(PlatformLogger.FINEST))
 2389                           focusLog.finest("1. SNFH_FAILURE for {0}",
 2390                                           String.valueOf(descendant));
 2391                       return SNFH_FAILURE;
 2392                   }
 2393   
 2394                   // 'heavyweight' owns the native focus and there are no pending
 2395                   // requests. 'heavyweight' must be a Container and
 2396                   // 'descendant' must not be the focus owner. Otherwise,
 2397                   // we would never have gotten this far.
 2398                   manager.enqueueKeyEvents(time, descendant);
 2399   
 2400                   hwFocusRequest =
 2401                       new HeavyweightFocusRequest(heavyweight, descendant,
 2402                                                   temporary, cause);
 2403                   heavyweightRequests.add(hwFocusRequest);
 2404   
 2405                   if (currentFocusOwner != null) {
 2406                       FocusEvent currentFocusOwnerEvent =
 2407                           new CausedFocusEvent(currentFocusOwner,
 2408                                          FocusEvent.FOCUS_LOST,
 2409                                          temporary, descendant, cause);
 2410                       // Fix 5028014. Rolled out.
 2411                       // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
 2412                       SunToolkit.postEvent(currentFocusOwner.appContext,
 2413                                            currentFocusOwnerEvent);
 2414                   }
 2415                   FocusEvent newFocusOwnerEvent =
 2416                       new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
 2417                                      temporary, currentFocusOwner, cause);
 2418                   // Fix 5028014. Rolled out.
 2419                   // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
 2420                   SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
 2421   
 2422                   if (focusLog.isLoggable(PlatformLogger.FINEST))
 2423                       focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
 2424                   return SNFH_SUCCESS_HANDLED;
 2425               } else if (hwFocusRequest != null &&
 2426                          hwFocusRequest.heavyweight == heavyweight) {
 2427                   // 'heavyweight' doesn't have the native focus right now, but
 2428                   // if all pending requests were completed, it would. Add
 2429                   // descendant to the heavyweight's list of pending
 2430                   // lightweight focus transfers.
 2431                   if (hwFocusRequest.addLightweightRequest(descendant,
 2432                                                            temporary, cause)) {
 2433                       manager.enqueueKeyEvents(time, descendant);
 2434                   }
 2435   
 2436                   if (focusLog.isLoggable(PlatformLogger.FINEST))
 2437                       focusLog.finest("3. SNFH_HANDLED for lightweight" +
 2438                                       descendant + " in " + heavyweight);
 2439                   return SNFH_SUCCESS_HANDLED;
 2440               } else {
 2441                   if (!focusedWindowChangeAllowed) {
 2442                       // For purposes of computing oldFocusedWindow, we should look at
 2443                       // the second to last HeavyweightFocusRequest on the queue iff the
 2444                       // last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If
 2445                       // there is no second to last HeavyweightFocusRequest, null is an
 2446                       // acceptable value.
 2447                       if (hwFocusRequest ==
 2448                           HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
 2449                       {
 2450                           int size = heavyweightRequests.size();
 2451                           hwFocusRequest = (HeavyweightFocusRequest)((size >= 2)
 2452                               ? heavyweightRequests.get(size - 2)
 2453                               : null);
 2454                       }
 2455                       if (focusedWindowChanged(heavyweight,
 2456                                                (hwFocusRequest != null)
 2457                                                ? hwFocusRequest.heavyweight
 2458                                                : nativeFocusedWindow)) {
 2459                           if (focusLog.isLoggable(PlatformLogger.FINEST))
 2460                               focusLog.finest("4. SNFH_FAILURE for " + descendant);
 2461                           return SNFH_FAILURE;
 2462                       }
 2463                   }
 2464   
 2465                   manager.enqueueKeyEvents(time, descendant);
 2466                   heavyweightRequests.add
 2467                       (new HeavyweightFocusRequest(heavyweight, descendant,
 2468                                                    temporary, cause));
 2469                   if (focusLog.isLoggable(PlatformLogger.FINEST))
 2470                       focusLog.finest("5. SNFH_PROCEED for " + descendant);
 2471                   return SNFH_SUCCESS_PROCEED;
 2472               }
 2473           }
 2474       }
 2475   
 2476       /**
 2477        * Returns the Window which will be active after processing this request,
 2478        * or null if this is a duplicate request. The active Window is useful
 2479        * because some native platforms do not support setting the native focus
 2480        * owner to null. On these platforms, the obvious choice is to set the
 2481        * focus owner to the focus proxy of the active Window.
 2482        */
 2483       static Window markClearGlobalFocusOwner() {
 2484           // need to call this out of synchronized block to avoid possible deadlock
 2485           // see 6454631.
 2486           final Component nativeFocusedWindow =
 2487                   getCurrentKeyboardFocusManager().getNativeFocusedWindow();
 2488   
 2489           synchronized (heavyweightRequests) {
 2490               HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
 2491               if (hwFocusRequest ==
 2492                   HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
 2493               {
 2494                   // duplicate request
 2495                   return null;
 2496               }
 2497   
 2498               heavyweightRequests.add
 2499                   (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
 2500   
 2501               Component activeWindow = ((hwFocusRequest != null)
 2502                   ? SunToolkit.getContainingWindow(hwFocusRequest.heavyweight)
 2503                   : nativeFocusedWindow);
 2504               while (activeWindow != null &&
 2505                      !((activeWindow instanceof Frame) ||
 2506                        (activeWindow instanceof Dialog)))
 2507               {
 2508                   activeWindow = activeWindow.getParent_NoClientCode();
 2509               }
 2510   
 2511               return (Window) activeWindow;
 2512           }
 2513       }
 2514       Component getCurrentWaitingRequest(Component parent) {
 2515           synchronized (heavyweightRequests) {
 2516               HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
 2517               if (hwFocusRequest != null) {
 2518                   if (hwFocusRequest.heavyweight == parent) {
 2519                       LightweightFocusRequest lwFocusRequest =
 2520                           hwFocusRequest.lightweightRequests.getFirst();
 2521                       if (lwFocusRequest != null) {
 2522                           return lwFocusRequest.component;
 2523                       }
 2524                   }
 2525               }
 2526           }
 2527           return null;
 2528       }
 2529   
 2530       static boolean isAutoFocusTransferEnabled() {
 2531           synchronized (heavyweightRequests) {
 2532               return (heavyweightRequests.size() == 0)
 2533                       && !disableRestoreFocus
 2534                       && (null == currentLightweightRequests);
 2535           }
 2536       }
 2537   
 2538       static boolean isAutoFocusTransferEnabledFor(Component comp) {
 2539           return isAutoFocusTransferEnabled() && comp.isAutoFocusTransferOnDisposal();
 2540       }
 2541   
 2542       /*
 2543        * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
 2544        * @param ex previously caught exception that may be processed right here, or null
 2545        * @param comp the component to dispatch the event to
 2546        * @param event the event to dispatch to the component
 2547        */
 2548       static private Throwable dispatchAndCatchException(Throwable ex, Component comp, FocusEvent event) {
 2549           Throwable retEx = null;
 2550           try {
 2551               comp.dispatchEvent(event);
 2552           } catch (RuntimeException re) {
 2553               retEx = re;
 2554           } catch (Error er) {
 2555               retEx = er;
 2556           }
 2557           if (retEx != null) {
 2558               if (ex != null) {
 2559                   handleException(ex);
 2560               }
 2561               return retEx;
 2562           }
 2563           return ex;
 2564       }
 2565   
 2566       static private void handleException(Throwable ex) {
 2567           ex.printStackTrace();
 2568       }
 2569   
 2570       static void processCurrentLightweightRequests() {
 2571           KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
 2572           LinkedList<LightweightFocusRequest> localLightweightRequests = null;
 2573   
 2574           Component globalFocusOwner = manager.getGlobalFocusOwner();
 2575           if ((globalFocusOwner != null) &&
 2576               (globalFocusOwner.appContext != AppContext.getAppContext()))
 2577           {
 2578               // The current app context differs from the app context of a focus
 2579               // owner (and all pending lightweight requests), so we do nothing
 2580               // now and wait for a next event.
 2581               return;
 2582           }
 2583   
 2584           synchronized(heavyweightRequests) {
 2585               if (currentLightweightRequests != null) {
 2586                   clearingCurrentLightweightRequests = true;
 2587                   disableRestoreFocus = true;
 2588                   localLightweightRequests = currentLightweightRequests;
 2589                   allowSyncFocusRequests = (localLightweightRequests.size() < 2);
 2590                   currentLightweightRequests = null;
 2591               } else {
 2592                   // do nothing
 2593                   return;
 2594               }
 2595           }
 2596   
 2597           Throwable caughtEx = null;
 2598           try {
 2599               if (localLightweightRequests != null) {
 2600                   Component lastFocusOwner = null;
 2601                   Component currentFocusOwner = null;
 2602   
 2603                   for (Iterator iter = localLightweightRequests.iterator(); iter.hasNext(); ) {
 2604   
 2605                       currentFocusOwner = manager.getGlobalFocusOwner();
 2606                       LightweightFocusRequest lwFocusRequest =
 2607                           (LightweightFocusRequest)iter.next();
 2608   
 2609                       /*
 2610                        * WARNING: This is based on DKFM's logic solely!
 2611                        *
 2612                        * We allow to trigger restoreFocus() in the dispatching process
 2613                        * only if we have the last request to dispatch. If the last request
 2614                        * fails, focus will be restored to either the component of the last
 2615                        * previously succedded request, or to to the focus owner that was
 2616                        * before this clearing proccess.
 2617                        */
 2618                       if (!iter.hasNext()) {
 2619                           disableRestoreFocus = false;
 2620                       }
 2621   
 2622                       FocusEvent currentFocusOwnerEvent = null;
 2623                       /*
 2624                        * We're not dispatching FOCUS_LOST while the current focus owner is null.
 2625                        * But regardless of whether it's null or not, we're clearing ALL the local
 2626                        * lw requests.
 2627                        */
 2628                       if (currentFocusOwner != null) {
 2629                           currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
 2630                                          FocusEvent.FOCUS_LOST,
 2631                                          lwFocusRequest.temporary,
 2632                                          lwFocusRequest.component, lwFocusRequest.cause);
 2633                       }
 2634                       FocusEvent newFocusOwnerEvent =
 2635                           new CausedFocusEvent(lwFocusRequest.component,
 2636                                          FocusEvent.FOCUS_GAINED,
 2637                                          lwFocusRequest.temporary,
 2638                                          currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
 2639                                          lwFocusRequest.cause);
 2640   
 2641                       if (currentFocusOwner != null) {
 2642                           ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
 2643                           caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
 2644                       }
 2645   
 2646                       ((AWTEvent) newFocusOwnerEvent).isPosted = true;
 2647                       caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
 2648   
 2649                       if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
 2650                           lastFocusOwner = lwFocusRequest.component;
 2651                       }
 2652                   }
 2653               }
 2654           } finally {
 2655               clearingCurrentLightweightRequests = false;
 2656               disableRestoreFocus = false;
 2657               localLightweightRequests = null;
 2658               allowSyncFocusRequests = true;
 2659           }
 2660           if (caughtEx instanceof RuntimeException) {
 2661               throw (RuntimeException)caughtEx;
 2662           } else if (caughtEx instanceof Error) {
 2663               throw (Error)caughtEx;
 2664           }
 2665       }
 2666   
 2667       static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
 2668           synchronized (heavyweightRequests) {
 2669               // Any other case represents a failure condition which we did
 2670               // not expect. We need to clearFocusRequestList() and patch up
 2671               // the event as best as possible.
 2672   
 2673               if (removeFirstRequest()) {
 2674                   return (FocusEvent)retargetFocusEvent(fe);
 2675               }
 2676   
 2677               Component source = fe.getComponent();
 2678               Component opposite = fe.getOppositeComponent();
 2679               boolean temporary = false;
 2680               if (fe.getID() == FocusEvent.FOCUS_LOST &&
 2681                   (opposite == null || isTemporary(opposite, source)))
 2682               {
 2683                   temporary = true;
 2684               }
 2685               return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
 2686                                           CausedFocusEvent.Cause.NATIVE_SYSTEM);
 2687           }
 2688       }
 2689   
 2690       static FocusEvent retargetFocusGained(FocusEvent fe) {
 2691           assert (fe.getID() == FocusEvent.FOCUS_GAINED);
 2692   
 2693           Component currentFocusOwner = getCurrentKeyboardFocusManager().
 2694               getGlobalFocusOwner();
 2695           Component source = fe.getComponent();
 2696           Component opposite = fe.getOppositeComponent();
 2697           Component nativeSource = getHeavyweight(source);
 2698   
 2699           synchronized (heavyweightRequests) {
 2700               HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
 2701   
 2702               if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
 2703               {
 2704                   return retargetUnexpectedFocusEvent(fe);
 2705               }
 2706   
 2707               if (source != null && nativeSource == null && hwFocusRequest != null) {
 2708                   // if source w/o peer and
 2709                   // if source is equal to first lightweight
 2710                   // then we should correct source and nativeSource
 2711                   if (source == hwFocusRequest.getFirstLightweightRequest().component)
 2712                   {
 2713                       source = hwFocusRequest.heavyweight;
 2714                       nativeSource = source; // source is heavuweight itself
 2715                   }
 2716               }
 2717               if (hwFocusRequest != null &&
 2718                   nativeSource == hwFocusRequest.heavyweight)
 2719               {
 2720                   // Focus change as a result of a known call to requestFocus(),
 2721                   // or known click on a peer focusable heavyweight Component.
 2722   
 2723                   heavyweightRequests.removeFirst();
 2724   
 2725                   LightweightFocusRequest lwFocusRequest =
 2726                       hwFocusRequest.lightweightRequests.removeFirst();
 2727   
 2728                   Component newSource = lwFocusRequest.component;
 2729                   if (currentFocusOwner != null) {
 2730                       /*
 2731                        * Since we receive FOCUS_GAINED when current focus
 2732                        * owner is not null, correcponding FOCUS_LOST is supposed
 2733                        * to be lost.  And so,  we keep new focus owner
 2734                        * to determine synthetic FOCUS_LOST event which will be
 2735                        * generated by KeyboardFocusManager for this FOCUS_GAINED.
 2736                        *
 2737                        * This code based on knowledge of
 2738                        * DefaultKeyboardFocusManager's implementation and might
 2739                        * be not applicable for another KeyboardFocusManager.
 2740                        */
 2741                       newFocusOwner = newSource;
 2742                   }
 2743   
 2744                   boolean temporary = (opposite == null ||
 2745                                        isTemporary(newSource, opposite))
 2746                           ? false
 2747                           : lwFocusRequest.temporary;
 2748   
 2749                   if (hwFocusRequest.lightweightRequests.size() > 0) {
 2750                       currentLightweightRequests =
 2751                           hwFocusRequest.lightweightRequests;
 2752                       EventQueue.invokeLater(new Runnable() {
 2753                               public void run() {
 2754                                   processCurrentLightweightRequests();
 2755                               }
 2756                           });
 2757                   }
 2758   
 2759                   // 'opposite' will be fixed by
 2760                   // DefaultKeyboardFocusManager.realOppositeComponent
 2761                   return new CausedFocusEvent(newSource,
 2762                                         FocusEvent.FOCUS_GAINED, temporary,
 2763                                         opposite, lwFocusRequest.cause);
 2764               }
 2765   
 2766               if (currentFocusOwner != null
 2767                   && currentFocusOwner.getContainingWindow() == source
 2768                   && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
 2769               {
 2770                   // Special case for FOCUS_GAINED in top-levels
 2771                   // If it arrives as the result of activation we should skip it
 2772                   // This event will not have appropriate request record and
 2773                   // on arrival there will be already some focus owner set.
 2774                   return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
 2775                                               null, CausedFocusEvent.Cause.ACTIVATION);
 2776               }
 2777   
 2778               return retargetUnexpectedFocusEvent(fe);
 2779           } // end synchronized(heavyweightRequests)
 2780       }
 2781   
 2782       static FocusEvent retargetFocusLost(FocusEvent fe) {
 2783           assert (fe.getID() == FocusEvent.FOCUS_LOST);
 2784   
 2785           Component currentFocusOwner = getCurrentKeyboardFocusManager().
 2786               getGlobalFocusOwner();
 2787           Component opposite = fe.getOppositeComponent();
 2788           Component nativeOpposite = getHeavyweight(opposite);
 2789   
 2790           synchronized (heavyweightRequests) {
 2791               HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
 2792   
 2793               if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
 2794               {
 2795                   if (currentFocusOwner != null) {
 2796                       // Call to KeyboardFocusManager.clearGlobalFocusOwner()
 2797                       heavyweightRequests.removeFirst();
 2798                       return new CausedFocusEvent(currentFocusOwner,
 2799                                                   FocusEvent.FOCUS_LOST, false, null,
 2800                                                   CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
 2801                   }
 2802   
 2803                   // Otherwise, fall through to failure case below
 2804   
 2805               } else if (opposite == null)
 2806               {
 2807                   // Focus leaving application
 2808                   if (currentFocusOwner != null) {
 2809                       return new CausedFocusEvent(currentFocusOwner,
 2810                                                   FocusEvent.FOCUS_LOST,
 2811                                                   true, null, CausedFocusEvent.Cause.ACTIVATION);
 2812                   } else {
 2813                       return fe;
 2814                   }
 2815               } else if (hwFocusRequest != null &&
 2816                          (nativeOpposite == hwFocusRequest.heavyweight ||
 2817                           nativeOpposite == null &&
 2818                           opposite == hwFocusRequest.getFirstLightweightRequest().component))
 2819               {
 2820                   if (currentFocusOwner == null) {
 2821                       return fe;
 2822                   }
 2823                   // Focus change as a result of a known call to requestFocus(),
 2824                   // or click on a peer focusable heavyweight Component.
 2825                   // If a focus transfer is made across top-levels, then the
 2826                   // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
 2827                   // event is always permanent. Otherwise, the stored temporary
 2828                   // value is honored.
 2829   
 2830                   LightweightFocusRequest lwFocusRequest =
 2831                       hwFocusRequest.lightweightRequests.getFirst();
 2832   
 2833                   boolean temporary = isTemporary(opposite, currentFocusOwner)
 2834                       ? true
 2835                       : lwFocusRequest.temporary;
 2836   
 2837                   return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
 2838                                               temporary, lwFocusRequest.component, lwFocusRequest.cause);
 2839               } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
 2840                   // If top-level changed there might be no focus request in a list
 2841                   // But we know the opposite, we now it is temporary - dispatch the event.
 2842                   if (!fe.isTemporary() && currentFocusOwner != null) {
 2843                       // Create copy of the event with only difference in temporary parameter.
 2844                       fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
 2845                                                 true, opposite, CausedFocusEvent.Cause.ACTIVATION);
 2846                   }
 2847                   return fe;
 2848               }
 2849   
 2850               return retargetUnexpectedFocusEvent(fe);
 2851           }  // end synchronized(heavyweightRequests)
 2852       }
 2853   
 2854       static AWTEvent retargetFocusEvent(AWTEvent event) {
 2855           if (clearingCurrentLightweightRequests) {
 2856               return event;
 2857           }
 2858   
 2859           KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
 2860           if (focusLog.isLoggable(PlatformLogger.FINER)) {
 2861               if (event instanceof FocusEvent || event instanceof WindowEvent) {
 2862                   focusLog.finer(">>> {0}", String.valueOf(event));
 2863               }
 2864               if (focusLog.isLoggable(PlatformLogger.FINER) && event instanceof KeyEvent) {
 2865                   focusLog.finer("    focus owner is {0}",
 2866                                  String.valueOf(manager.getGlobalFocusOwner()));
 2867                   focusLog.finer(">>> {0}", String.valueOf(event));
 2868               }
 2869           }
 2870   
 2871           synchronized(heavyweightRequests) {
 2872               /*
 2873                * This code handles FOCUS_LOST event which is generated by
 2874                * DefaultKeyboardFocusManager for FOCUS_GAINED.
 2875                *
 2876                * This code based on knowledge of DefaultKeyboardFocusManager's
 2877                * implementation and might be not applicable for another
 2878                * KeyboardFocusManager.
 2879                *
 2880                * Fix for 4472032
 2881                */
 2882               if (newFocusOwner != null &&
 2883                   event.getID() == FocusEvent.FOCUS_LOST)
 2884               {
 2885                   FocusEvent fe = (FocusEvent)event;
 2886   
 2887                   if (manager.getGlobalFocusOwner() == fe.getComponent() &&
 2888                       fe.getOppositeComponent() == newFocusOwner)
 2889                   {
 2890                       newFocusOwner = null;
 2891                       return event;
 2892                   }
 2893               }
 2894           }
 2895   
 2896           processCurrentLightweightRequests();
 2897   
 2898           switch (event.getID()) {
 2899               case FocusEvent.FOCUS_GAINED: {
 2900                   event = retargetFocusGained((FocusEvent)event);
 2901                   break;
 2902               }
 2903               case FocusEvent.FOCUS_LOST: {
 2904                   event = retargetFocusLost((FocusEvent)event);
 2905                   break;
 2906               }
 2907               default:
 2908                   /* do nothing */
 2909           }
 2910           return event;
 2911       }
 2912   
 2913       /**
 2914        * Clears markers queue
 2915        * This method is not intended to be overridden by KFM's.
 2916        * Only DefaultKeyboardFocusManager can implement it.
 2917        * @since 1.5
 2918        */
 2919       void clearMarkers() {
 2920       }
 2921   
 2922       static boolean removeFirstRequest() {
 2923           KeyboardFocusManager manager =
 2924               KeyboardFocusManager.getCurrentKeyboardFocusManager();
 2925   
 2926           synchronized(heavyweightRequests) {
 2927               HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
 2928   
 2929               if (hwFocusRequest != null) {
 2930                   heavyweightRequests.removeFirst();
 2931                   if (hwFocusRequest.lightweightRequests != null) {
 2932                       for (Iterator lwIter = hwFocusRequest.lightweightRequests.
 2933                                iterator();
 2934                            lwIter.hasNext(); )
 2935                       {
 2936                           manager.dequeueKeyEvents
 2937                               (-1, ((LightweightFocusRequest)lwIter.next()).
 2938                                component);
 2939                       }
 2940                   }
 2941               }
 2942               // Fix for 4799136 - clear type-ahead markers if requests queue is empty
 2943               // We do it here because this method is called only when problems happen
 2944               if (heavyweightRequests.size() == 0) {
 2945                   manager.clearMarkers();
 2946               }
 2947               return (heavyweightRequests.size() > 0);
 2948           }
 2949       }
 2950       static void removeLastFocusRequest(Component heavyweight) {
 2951           if (log.isLoggable(PlatformLogger.FINE)) {
 2952               if (heavyweight == null) {
 2953                   log.fine("Assertion (heavyweight != null) failed");
 2954               }
 2955           }
 2956   
 2957           KeyboardFocusManager manager =
 2958               KeyboardFocusManager.getCurrentKeyboardFocusManager();
 2959           synchronized(heavyweightRequests) {
 2960               HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
 2961               if (hwFocusRequest != null &&
 2962                   hwFocusRequest.heavyweight == heavyweight) {
 2963                   heavyweightRequests.removeLast();
 2964               }
 2965               // Fix for 4799136 - clear type-ahead markers if requests queue is empty
 2966               // We do it here because this method is called only when problems happen
 2967               if (heavyweightRequests.size() == 0) {
 2968                   manager.clearMarkers();
 2969               }
 2970           }
 2971       }
 2972   
 2973       private static boolean focusedWindowChanged(Component to, Component from) {
 2974           Window wto = SunToolkit.getContainingWindow(to);
 2975           Window wfrom = SunToolkit.getContainingWindow(from);
 2976           if (wto == null && wfrom == null) {
 2977               return true;
 2978           }
 2979           if (wto == null) {
 2980               return true;
 2981           }
 2982           if (wfrom == null) {
 2983               return true;
 2984           }
 2985           return (wto != wfrom);
 2986       }
 2987   
 2988       private static boolean isTemporary(Component to, Component from) {
 2989           Window wto = SunToolkit.getContainingWindow(to);
 2990           Window wfrom = SunToolkit.getContainingWindow(from);
 2991           if (wto == null && wfrom == null) {
 2992               return false;
 2993           }
 2994           if (wto == null) {
 2995               return true;
 2996           }
 2997           if (wfrom == null) {
 2998               return false;
 2999           }
 3000           return (wto != wfrom);
 3001       }
 3002   
 3003       static Component getHeavyweight(Component comp) {
 3004           if (comp == null || comp.getPeer() == null) {
 3005               return null;
 3006           } else if (comp.getPeer() instanceof LightweightPeer) {
 3007               return comp.getNativeContainer();
 3008           } else {
 3009               return comp;
 3010           }
 3011       }
 3012   
 3013       static Field proxyActive;
 3014       // Accessor to private field isProxyActive of KeyEvent
 3015       private static boolean isProxyActiveImpl(KeyEvent e) {
 3016           if (proxyActive == null) {
 3017               proxyActive = (Field) AccessController.doPrivileged(new PrivilegedAction() {
 3018                       public Object run() {
 3019                           Field field = null;
 3020                           try {
 3021                               field = KeyEvent.class.getDeclaredField("isProxyActive");
 3022                               if (field != null) {
 3023                                   field.setAccessible(true);
 3024                               }
 3025                           } catch (NoSuchFieldException nsf) {
 3026                               assert(false);
 3027                           }
 3028                           return field;
 3029                       }
 3030                   });
 3031           }
 3032   
 3033           try {
 3034               return proxyActive.getBoolean(e);
 3035           } catch (IllegalAccessException iae) {
 3036               assert(false);
 3037           }
 3038           return false;
 3039       }
 3040   
 3041       // Returns the value of this KeyEvent's field isProxyActive
 3042       static boolean isProxyActive(KeyEvent e) {
 3043           if (!GraphicsEnvironment.isHeadless()) {
 3044               return isProxyActiveImpl(e);
 3045           } else {
 3046               return false;
 3047           }
 3048       }
 3049   
 3050       private static HeavyweightFocusRequest getLastHWRequest() {
 3051           synchronized(heavyweightRequests) {
 3052               return (heavyweightRequests.size() > 0)
 3053                   ? heavyweightRequests.getLast()
 3054                   : null;
 3055           }
 3056       }
 3057   
 3058       private static HeavyweightFocusRequest getFirstHWRequest() {
 3059           synchronized(heavyweightRequests) {
 3060               return (heavyweightRequests.size() > 0)
 3061                   ? heavyweightRequests.getFirst()
 3062                   : null;
 3063           }
 3064       }
 3065   }

Home » openjdk-7 » java » awt » [javadoc | source]