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