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