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