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