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