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