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