1 /*
2  * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package java.awt;
26 
27 import java.awt.event.FocusEvent;
28 import java.awt.event.InputEvent;
29 import java.awt.event.KeyEvent;
30 import java.awt.event.WindowEvent;
31 
32 import java.awt.peer.KeyboardFocusManagerPeer;
33 import java.awt.peer.LightweightPeer;
34 
35 import java.beans.PropertyChangeListener;
36 import java.beans.PropertyChangeSupport;
37 import java.beans.PropertyVetoException;
38 import java.beans.VetoableChangeListener;
39 import java.beans.VetoableChangeSupport;
40 
41 import java.lang.ref.WeakReference;
42 
43 import java.security.AccessController;
44 import java.security.PrivilegedAction;
45 
46 import java.util.Collections;
47 import java.util.HashSet;
48 import java.util.Iterator;
49 import java.util.LinkedList;
50 import java.util.Set;
51 import java.util.StringTokenizer;
52 import java.util.WeakHashMap;
53 
54 import sun.util.logging.PlatformLogger;
55 
56 import sun.awt.AppContext;
57 import sun.awt.SunToolkit;
58 import sun.awt.KeyboardFocusManagerPeerProvider;
59 import sun.awt.AWTAccessor;
60 
61 /**
62  * The KeyboardFocusManager is responsible for managing the active and focused
63  * Windows, and the current focus owner. The focus owner is defined as the
64  * Component in an application that will typically receive all KeyEvents
65  * generated by the user. The focused Window is the Window that is, or
66  * contains, the focus owner. Only a Frame or a Dialog can be the active
67  * Window. The native windowing system may denote the active Window or its
68  * children with special decorations, such as a highlighted title bar. The
69  * active Window is always either the focused Window, or the first Frame or
70  * Dialog that is an owner of the focused Window.
71  * <p>
72  * The KeyboardFocusManager is both a centralized location for client code to
73  * query for the focus owner and initiate focus changes, and an event
74  * dispatcher for all FocusEvents, WindowEvents related to focus, and
75  * KeyEvents.
76  * <p>
77  * Some browsers partition applets in different code bases into separate
78  * contexts, and establish walls between these contexts. In such a scenario,
79  * there will be one KeyboardFocusManager per context. Other browsers place all
80  * applets into the same context, implying that there will be only a single,
81  * global KeyboardFocusManager for all applets. This behavior is
82  * implementation-dependent. Consult your browser's documentation for more
83  * information. No matter how many contexts there may be, however, there can
84  * never be more than one focus owner, focused Window, or active Window, per
85  * ClassLoader.
86  * <p>
87  * Please see
88  * <a href="https://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="doc-files/FocusSpec.html">Focus Specification</a>
92  * for more information.
93  *
94  * @author David Mendenhall
95  *
96  * @see Window
97  * @see Frame
98  * @see Dialog
99  * @see java.awt.event.FocusEvent
100  * @see java.awt.event.WindowEvent
101  * @see java.awt.event.KeyEvent
102  * @since 1.4
103  */
104 public abstract class KeyboardFocusManager
105     implements KeyEventDispatcher, KeyEventPostProcessor
106 {
107 
108     // Shared focus engine logger
109     private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
110 
111     static {
112         /* ensure that the necessary native libraries are loaded */
Toolkit.loadLibraries()113         Toolkit.loadLibraries();
114         if (!GraphicsEnvironment.isHeadless()) {
initIDs()115             initIDs();
116         }
AWTAccessor.setKeyboardFocusManagerAccessor( new AWTAccessor.KeyboardFocusManagerAccessor() { public int shouldNativelyFocusHeavyweight(Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause) { return KeyboardFocusManager.shouldNativelyFocusHeavyweight( heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause); } public boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time) { return KeyboardFocusManager.processSynchronousLightweightTransfer( heavyweight, descendant, temporary, focusedWindowChangeAllowed, time); } public void removeLastFocusRequest(Component heavyweight) { KeyboardFocusManager.removeLastFocusRequest(heavyweight); } @Override public Component getMostRecentFocusOwner(Window window) { return KeyboardFocusManager.getMostRecentFocusOwner(window); } public void setMostRecentFocusOwner(Window window, Component component) { KeyboardFocusManager.setMostRecentFocusOwner(window, component); } public KeyboardFocusManager getCurrentKeyboardFocusManager(AppContext ctx) { return KeyboardFocusManager.getCurrentKeyboardFocusManager(ctx); } public Container getCurrentFocusCycleRoot() { return KeyboardFocusManager.currentFocusCycleRoot; } } )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      */
initIDs()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      */
getCurrentKeyboardFocusManager()216     public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
217         return getCurrentKeyboardFocusManager(AppContext.getAppContext());
218     }
219 
220     static synchronized KeyboardFocusManager
getCurrentKeyboardFocusManager(AppContext appcontext)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      */
setCurrentKeyboardFocusManager( KeyboardFocusManager newManager)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 
setCurrentSequencedEvent(SequencedEvent current)391     final void setCurrentSequencedEvent(SequencedEvent current) {
392         synchronized (SequencedEvent.class) {
393             assert(current == null || currentSequencedEvent == null);
394             currentSequencedEvent = current;
395         }
396     }
397 
getCurrentSequencedEvent()398     final SequencedEvent getCurrentSequencedEvent() {
399         synchronized (SequencedEvent.class) {
400             return currentSequencedEvent;
401         }
402     }
403 
initFocusTraversalKeysSet(String value, Set<AWTKeyStroke> targetSet)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      */
KeyboardFocusManager()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 
initPeer()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      */
getFocusOwner()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      */
getGlobalFocusOwner()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      */
setGlobalFocusOwner(Component focusOwner)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      */
clearFocusOwner()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      */
clearGlobalFocusOwner()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     }
_clearGlobalFocusOwner()642     private void _clearGlobalFocusOwner() {
643         Window activeWindow = markClearGlobalFocusOwner();
644         peer.clearGlobalFocusOwner(activeWindow);
645     }
646 
clearGlobalFocusOwnerPriv()647     void clearGlobalFocusOwnerPriv() {
648         AccessController.doPrivileged(new PrivilegedAction<Void>() {
649             public Void run() {
650                 clearGlobalFocusOwner();
651                 return null;
652             }
653         });
654     }
655 
getNativeFocusOwner()656     Component getNativeFocusOwner() {
657         return peer.getCurrentFocusOwner();
658     }
659 
setNativeFocusOwner(Component comp)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 
getNativeFocusedWindow()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      */
getPermanentFocusOwner()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      */
getGlobalPermanentFocusOwner()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      */
setGlobalPermanentFocusOwner(Component permanentFocusOwner)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      */
getFocusedWindow()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      */
getGlobalFocusedWindow()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      */
setGlobalFocusedWindow(Window focusedWindow)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      */
getActiveWindow()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      */
getGlobalActiveWindow()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      */
setGlobalActiveWindow(Window activeWindow)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      */
getDefaultFocusTraversalPolicy()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      */
setDefaultFocusTraversalPolicy(FocusTraversalPolicy defaultPolicy)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 scope="col">Identifier
1047      *     <th scope="col">Meaning
1048      *     <th scope="col">Default
1049      * </thead>
1050      * <tbody>
1051      *   <tr>
1052      *     <th scope="row">{@code KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS}
1053      *     <td>Normal forward keyboard traversal
1054      *     <td>{@code TAB} on {@code KEY_PRESSED}, {@code CTRL-TAB} on
1055      *     {@code KEY_PRESSED}
1056      *   <tr>
1057      *     <th scope="row">{@code KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS}
1058      *     <td>Normal reverse keyboard traversal
1059      *     <td>{@code SHIFT-TAB} on {@code KEY_PRESSED}, {@code CTRL-SHIFT-TAB}
1060      *     on {@code KEY_PRESSED}
1061      *   <tr>
1062      *     <th scope="row">{@code KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS}
1063      *     <td>Go up one focus traversal cycle
1064      *     <td>none
1065      *   <tr>
1066      *     <th scope="row">{@code KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS}
1067      *     <td>Go down one focus traversal cycle
1068      *     <td>none
1069      * </tbody>
1070      * </table>
1071      *
1072      * To disable a traversal key, use an empty {@code Set};
1073      * {@code Collections.EMPTY_SET} is recommended.
1074      * <p>
1075      * Using the {@code AWTKeyStroke} API, client code can
1076      * specify on which of two
1077      * specific {@code KeyEvent}s, {@code KEY_PRESSED} or
1078      * {@code KEY_RELEASED}, the focus traversal operation will
1079      * occur. Regardless of which {@code KeyEvent} is specified,
1080      * however, all {@code KeyEvent}s related to the focus
1081      * traversal key, including the associated {@code KEY_TYPED}
1082      * event, will be consumed, and will not be dispatched
1083      * to any {@code Component}. It is a runtime error to
1084      * specify a {@code KEY_TYPED} event as
1085      * mapping to a focus traversal operation, or to map the same event to
1086      * multiple default focus traversal operations.
1087      * <p>
1088      * This method may throw a {@code ClassCastException} if any {@code Object}
1089      * in {@code keystrokes} is not an {@code AWTKeyStroke}.
1090      *
1091      * @param id one of
1092      *        {@code KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS},
1093      *        {@code KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS},
1094      *        {@code KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS}, or
1095      *        {@code KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS}
1096      * @param keystrokes the Set of {@code AWTKeyStroke}s for the
1097      *        specified operation
1098      * @see #getDefaultFocusTraversalKeys
1099      * @see Component#setFocusTraversalKeys
1100      * @see Component#getFocusTraversalKeys
1101      * @throws IllegalArgumentException if id is not one of
1102      *         {@code KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS},
1103      *         {@code KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS},
1104      *         {@code KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS}, or
1105      *         {@code KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS},
1106      *         or if keystrokes is {@code null},
1107      *         or if keystrokes contains {@code null},
1108      *         or if any keystroke
1109      *         represents a {@code KEY_TYPED} event,
1110      *         or if any keystroke already maps
1111      *         to another default focus traversal operation
1112      */
1113     public void
setDefaultFocusTraversalKeys(int id, Set<? extends AWTKeyStroke> keystrokes)1114         setDefaultFocusTraversalKeys(int id,
1115                                      Set<? extends AWTKeyStroke> keystrokes)
1116     {
1117         if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1118             throw new IllegalArgumentException("invalid focus traversal key identifier");
1119         }
1120         if (keystrokes == null) {
1121             throw new IllegalArgumentException("cannot set null Set of default focus traversal keys");
1122         }
1123 
1124         Set<AWTKeyStroke> oldKeys;
1125 
1126         synchronized (this) {
1127             for (AWTKeyStroke keystroke : keystrokes) {
1128 
1129                 if (keystroke == null) {
1130                     throw new IllegalArgumentException("cannot set null focus traversal key");
1131                 }
1132 
1133                 if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1134                     throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
1135                 }
1136 
1137                 // Check to see if key already maps to another traversal
1138                 // operation
1139                 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
1140                     if (i == id) {
1141                         continue;
1142                     }
1143 
1144                     if (defaultFocusTraversalKeys[i].contains(keystroke)) {
1145                         throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
1146                     }
1147                 }
1148             }
1149 
1150             oldKeys = defaultFocusTraversalKeys[id];
1151             defaultFocusTraversalKeys[id] =
1152                 Collections.unmodifiableSet(new HashSet<>(keystrokes));
1153         }
1154 
1155         firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
1156                            oldKeys, keystrokes);
1157     }
1158 
1159     /**
1160      * Returns a Set of default focus traversal keys for a given traversal
1161      * operation. This traversal key Set will be in effect on all Windows that
1162      * have no such Set of their own explicitly defined. This Set will also be
1163      * inherited, recursively, by any child Component of those Windows that has
1164      * no such Set of its own explicitly defined. (See
1165      * {@code setDefaultFocusTraversalKeys} for a full description of each
1166      * operation.)
1167      *
1168      * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1169      *        KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1170      *        KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1171      *        KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1172      * @return the {@code Set} of {@code AWTKeyStroke}s
1173      *         for the specified operation; the {@code Set}
1174      *         will be unmodifiable, and may be empty; {@code null}
1175      *         will never be returned
1176      * @see #setDefaultFocusTraversalKeys
1177      * @see Component#setFocusTraversalKeys
1178      * @see Component#getFocusTraversalKeys
1179      * @throws IllegalArgumentException if id is not one of
1180      *         KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1181      *         KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1182      *         KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1183      *         KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1184      */
getDefaultFocusTraversalKeys(int id)1185     public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
1186         if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1187             throw new IllegalArgumentException("invalid focus traversal key identifier");
1188         }
1189 
1190         // Okay to return Set directly because it is an unmodifiable view
1191         return defaultFocusTraversalKeys[id];
1192     }
1193 
1194     /**
1195      * Returns the current focus cycle root, if the current focus cycle root is
1196      * in the same context as the calling thread. If the focus owner is itself
1197      * a focus cycle root, then it may be ambiguous as to which Components
1198      * represent the next and previous Components to focus during normal focus
1199      * traversal. In that case, the current focus cycle root is used to
1200      * differentiate among the possibilities.
1201      * <p>
1202      * This method is intended to be used only by KeyboardFocusManagers and
1203      * focus implementations. It is not for general client use.
1204      *
1205      * @return the current focus cycle root, or null if the current focus cycle
1206      *         root is not a member of the calling thread's context
1207      * @see #getGlobalCurrentFocusCycleRoot
1208      * @see #setGlobalCurrentFocusCycleRoot
1209      */
getCurrentFocusCycleRoot()1210     public Container getCurrentFocusCycleRoot() {
1211         synchronized (KeyboardFocusManager.class) {
1212             if (currentFocusCycleRoot == null) {
1213                 return null;
1214             }
1215 
1216             return (currentFocusCycleRoot.appContext ==
1217                     AppContext.getAppContext())
1218                 ? currentFocusCycleRoot
1219                 : null;
1220         }
1221     }
1222 
1223     /**
1224      * Returns the current focus cycle root, even if the calling thread is in a
1225      * different context than the current focus cycle root. If the focus owner
1226      * is itself a focus cycle root, then it may be ambiguous as to which
1227      * Components represent the next and previous Components to focus during
1228      * normal focus traversal. In that case, the current focus cycle root is
1229      * used to differentiate among the possibilities.
1230      *
1231      * @return the current focus cycle root, or null if the current focus cycle
1232      *         root is not a member of the calling thread's context
1233      * @see #getCurrentFocusCycleRoot
1234      * @see #setGlobalCurrentFocusCycleRoot
1235      * @throws SecurityException if this KeyboardFocusManager is not the
1236      *         current KeyboardFocusManager for the calling thread's context
1237      *         and if the calling thread does not have "replaceKeyboardFocusManager"
1238      *         permission
1239      */
getGlobalCurrentFocusCycleRoot()1240     protected Container getGlobalCurrentFocusCycleRoot()
1241         throws SecurityException
1242     {
1243         synchronized (KeyboardFocusManager.class) {
1244             checkKFMSecurity();
1245             return currentFocusCycleRoot;
1246         }
1247     }
1248 
1249     /**
1250      * Sets the current focus cycle root. If the focus owner is itself a focus
1251      * cycle root, then it may be ambiguous as to which Components represent
1252      * the next and previous Components to focus during normal focus traversal.
1253      * In that case, the current focus cycle root is used to differentiate
1254      * among the possibilities.
1255      * <p>
1256      * If a SecurityManager is installed, the calling thread must be granted
1257      * the "replaceKeyboardFocusManager" AWTPermission. If this permission is
1258      * not granted, this method will throw a SecurityException, and the current
1259      * focus cycle root will not be changed.
1260      * <p>
1261      * This method is intended to be used only by KeyboardFocusManagers and
1262      * focus implementations. It is not for general client use.
1263      *
1264      * @param newFocusCycleRoot the new focus cycle root
1265      * @see #getCurrentFocusCycleRoot
1266      * @see #getGlobalCurrentFocusCycleRoot
1267      * @throws SecurityException if the calling thread does not have
1268      *         "replaceKeyboardFocusManager" permission
1269      */
setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot)1270     public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot)
1271         throws SecurityException
1272     {
1273         checkReplaceKFMPermission();
1274 
1275         Container oldFocusCycleRoot;
1276 
1277         synchronized (KeyboardFocusManager.class) {
1278             oldFocusCycleRoot  = getCurrentFocusCycleRoot();
1279             currentFocusCycleRoot = newFocusCycleRoot;
1280         }
1281 
1282         firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
1283                            newFocusCycleRoot);
1284     }
1285 
setGlobalCurrentFocusCycleRootPriv(final Container newFocusCycleRoot)1286     void setGlobalCurrentFocusCycleRootPriv(final Container newFocusCycleRoot) {
1287         AccessController.doPrivileged(new PrivilegedAction<Void>() {
1288             public Void run() {
1289                 setGlobalCurrentFocusCycleRoot(newFocusCycleRoot);
1290                 return null;
1291             }
1292         });
1293     }
1294 
1295     /**
1296      * Adds a PropertyChangeListener to the listener list. The listener is
1297      * registered for all bound properties of this class, including the
1298      * following:
1299      * <ul>
1300      *    <li>whether the KeyboardFocusManager is currently managing focus
1301      *        for this application or applet's browser context
1302      *        ("managingFocus")</li>
1303      *    <li>the focus owner ("focusOwner")</li>
1304      *    <li>the permanent focus owner ("permanentFocusOwner")</li>
1305      *    <li>the focused Window ("focusedWindow")</li>
1306      *    <li>the active Window ("activeWindow")</li>
1307      *    <li>the default focus traversal policy
1308      *        ("defaultFocusTraversalPolicy")</li>
1309      *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
1310      *        ("forwardDefaultFocusTraversalKeys")</li>
1311      *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1312      *        ("backwardDefaultFocusTraversalKeys")</li>
1313      *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1314      *        ("upCycleDefaultFocusTraversalKeys")</li>
1315      *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1316      *        ("downCycleDefaultFocusTraversalKeys")</li>
1317      *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1318      * </ul>
1319      * If listener is null, no exception is thrown and no action is performed.
1320      *
1321      * @param listener the PropertyChangeListener to be added
1322      * @see #removePropertyChangeListener
1323      * @see #getPropertyChangeListeners
1324      * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1325      */
addPropertyChangeListener(PropertyChangeListener listener)1326     public void addPropertyChangeListener(PropertyChangeListener listener) {
1327         if (listener != null) {
1328             synchronized (this) {
1329                 if (changeSupport == null) {
1330                     changeSupport = new PropertyChangeSupport(this);
1331                 }
1332                 changeSupport.addPropertyChangeListener(listener);
1333             }
1334         }
1335     }
1336 
1337     /**
1338      * Removes a PropertyChangeListener from the listener list. This method
1339      * should be used to remove the PropertyChangeListeners that were
1340      * registered for all bound properties of this class.
1341      * <p>
1342      * If listener is null, no exception is thrown and no action is performed.
1343      *
1344      * @param listener the PropertyChangeListener to be removed
1345      * @see #addPropertyChangeListener
1346      * @see #getPropertyChangeListeners
1347      * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1348      */
removePropertyChangeListener(PropertyChangeListener listener)1349     public void removePropertyChangeListener(PropertyChangeListener listener) {
1350         if (listener != null) {
1351             synchronized (this) {
1352                 if (changeSupport != null) {
1353                     changeSupport.removePropertyChangeListener(listener);
1354                 }
1355             }
1356         }
1357     }
1358 
1359     /**
1360      * Returns an array of all the property change listeners
1361      * registered on this keyboard focus manager.
1362      *
1363      * @return all of this keyboard focus manager's
1364      *         {@code PropertyChangeListener}s
1365      *         or an empty array if no property change
1366      *         listeners are currently registered
1367      *
1368      * @see #addPropertyChangeListener
1369      * @see #removePropertyChangeListener
1370      * @see #getPropertyChangeListeners(java.lang.String)
1371      * @since 1.4
1372      */
getPropertyChangeListeners()1373     public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
1374         if (changeSupport == null) {
1375             changeSupport = new PropertyChangeSupport(this);
1376         }
1377         return changeSupport.getPropertyChangeListeners();
1378     }
1379 
1380     /**
1381      * Adds a PropertyChangeListener to the listener list for a specific
1382      * property. The specified property may be user-defined, or one of the
1383      * following:
1384      * <ul>
1385      *    <li>whether the KeyboardFocusManager is currently managing focus
1386      *        for this application or applet's browser context
1387      *        ("managingFocus")</li>
1388      *    <li>the focus owner ("focusOwner")</li>
1389      *    <li>the permanent focus owner ("permanentFocusOwner")</li>
1390      *    <li>the focused Window ("focusedWindow")</li>
1391      *    <li>the active Window ("activeWindow")</li>
1392      *    <li>the default focus traversal policy
1393      *        ("defaultFocusTraversalPolicy")</li>
1394      *    <li>the Set of default FORWARD_TRAVERSAL_KEYS
1395      *        ("forwardDefaultFocusTraversalKeys")</li>
1396      *    <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1397      *        ("backwardDefaultFocusTraversalKeys")</li>
1398      *    <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1399      *        ("upCycleDefaultFocusTraversalKeys")</li>
1400      *    <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1401      *        ("downCycleDefaultFocusTraversalKeys")</li>
1402      *    <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1403      * </ul>
1404      * If listener is null, no exception is thrown and no action is performed.
1405      *
1406      * @param propertyName one of the property names listed above
1407      * @param listener the PropertyChangeListener to be added
1408      * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
1409      * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1410      * @see #getPropertyChangeListeners(java.lang.String)
1411      */
addPropertyChangeListener(String propertyName, PropertyChangeListener listener)1412     public void addPropertyChangeListener(String propertyName,
1413                                           PropertyChangeListener listener) {
1414         if (listener != null) {
1415             synchronized (this) {
1416                 if (changeSupport == null) {
1417                     changeSupport = new PropertyChangeSupport(this);
1418                 }
1419                 changeSupport.addPropertyChangeListener(propertyName,
1420                                                         listener);
1421             }
1422         }
1423     }
1424 
1425     /**
1426      * Removes a PropertyChangeListener from the listener list for a specific
1427      * property. This method should be used to remove PropertyChangeListeners
1428      * that were registered for a specific bound property.
1429      * <p>
1430      * If listener is null, no exception is thrown and no action is performed.
1431      *
1432      * @param propertyName a valid property name
1433      * @param listener the PropertyChangeListener to be removed
1434      * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1435      * @see #getPropertyChangeListeners(java.lang.String)
1436      * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
1437      */
removePropertyChangeListener(String propertyName, PropertyChangeListener listener)1438     public void removePropertyChangeListener(String propertyName,
1439                                              PropertyChangeListener listener) {
1440         if (listener != null) {
1441             synchronized (this) {
1442                 if (changeSupport != null) {
1443                     changeSupport.removePropertyChangeListener(propertyName,
1444                                                                listener);
1445                 }
1446             }
1447         }
1448     }
1449 
1450     /**
1451      * Returns an array of all the {@code PropertyChangeListener}s
1452      * associated with the named property.
1453      *
1454      * @param  propertyName the property name
1455      * @return all of the {@code PropertyChangeListener}s associated with
1456      *         the named property or an empty array if no such listeners have
1457      *         been added.
1458      *
1459      * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1460      * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1461      * @since 1.4
1462      */
getPropertyChangeListeners(String propertyName)1463     public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
1464         if (changeSupport == null) {
1465             changeSupport = new PropertyChangeSupport(this);
1466         }
1467         return changeSupport.getPropertyChangeListeners(propertyName);
1468     }
1469 
1470     /**
1471      * Fires a PropertyChangeEvent in response to a change in a bound property.
1472      * The event will be delivered to all registered PropertyChangeListeners.
1473      * No event will be delivered if oldValue and newValue are the same.
1474      *
1475      * @param propertyName the name of the property that has changed
1476      * @param oldValue the property's previous value
1477      * @param newValue the property's new value
1478      */
firePropertyChange(String propertyName, Object oldValue, Object newValue)1479     protected void firePropertyChange(String propertyName, Object oldValue,
1480                                       Object newValue)
1481     {
1482         if (oldValue == newValue) {
1483             return;
1484         }
1485         PropertyChangeSupport changeSupport = this.changeSupport;
1486         if (changeSupport != null) {
1487             changeSupport.firePropertyChange(propertyName, oldValue, newValue);
1488         }
1489     }
1490 
1491     /**
1492      * Adds a VetoableChangeListener to the listener list. The listener is
1493      * registered for all vetoable properties of this class, including the
1494      * following:
1495      * <ul>
1496      *    <li>the focus owner ("focusOwner")</li>
1497      *    <li>the permanent focus owner ("permanentFocusOwner")</li>
1498      *    <li>the focused Window ("focusedWindow")</li>
1499      *    <li>the active Window ("activeWindow")</li>
1500      * </ul>
1501      * If listener is null, no exception is thrown and no action is performed.
1502      *
1503      * @param listener the VetoableChangeListener to be added
1504      * @see #removeVetoableChangeListener
1505      * @see #getVetoableChangeListeners
1506      * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1507      */
addVetoableChangeListener(VetoableChangeListener listener)1508     public void addVetoableChangeListener(VetoableChangeListener listener) {
1509         if (listener != null) {
1510             synchronized (this) {
1511                 if (vetoableSupport == null) {
1512                     vetoableSupport =
1513                         new VetoableChangeSupport(this);
1514                 }
1515                 vetoableSupport.addVetoableChangeListener(listener);
1516             }
1517         }
1518     }
1519 
1520     /**
1521      * Removes a VetoableChangeListener from the listener list. This method
1522      * should be used to remove the VetoableChangeListeners that were
1523      * registered for all vetoable properties of this class.
1524      * <p>
1525      * If listener is null, no exception is thrown and no action is performed.
1526      *
1527      * @param listener the VetoableChangeListener to be removed
1528      * @see #addVetoableChangeListener
1529      * @see #getVetoableChangeListeners
1530      * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1531      */
removeVetoableChangeListener(VetoableChangeListener listener)1532     public void removeVetoableChangeListener(VetoableChangeListener listener) {
1533         if (listener != null) {
1534             synchronized (this) {
1535                 if (vetoableSupport != null) {
1536                     vetoableSupport.removeVetoableChangeListener(listener);
1537                 }
1538             }
1539         }
1540     }
1541 
1542     /**
1543      * Returns an array of all the vetoable change listeners
1544      * registered on this keyboard focus manager.
1545      *
1546      * @return all of this keyboard focus manager's
1547      *         {@code VetoableChangeListener}s
1548      *         or an empty array if no vetoable change
1549      *         listeners are currently registered
1550      *
1551      * @see #addVetoableChangeListener
1552      * @see #removeVetoableChangeListener
1553      * @see #getVetoableChangeListeners(java.lang.String)
1554      * @since 1.4
1555      */
getVetoableChangeListeners()1556     public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
1557         if (vetoableSupport == null) {
1558             vetoableSupport = new VetoableChangeSupport(this);
1559         }
1560         return vetoableSupport.getVetoableChangeListeners();
1561     }
1562 
1563     /**
1564      * Adds a VetoableChangeListener to the listener list for a specific
1565      * property. The specified property may be user-defined, or one of the
1566      * following:
1567      * <ul>
1568      *    <li>the focus owner ("focusOwner")</li>
1569      *    <li>the permanent focus owner ("permanentFocusOwner")</li>
1570      *    <li>the focused Window ("focusedWindow")</li>
1571      *    <li>the active Window ("activeWindow")</li>
1572      * </ul>
1573      * If listener is null, no exception is thrown and no action is performed.
1574      *
1575      * @param propertyName one of the property names listed above
1576      * @param listener the VetoableChangeListener to be added
1577      * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
1578      * @see #removeVetoableChangeListener
1579      * @see #getVetoableChangeListeners
1580      */
addVetoableChangeListener(String propertyName, VetoableChangeListener listener)1581     public void addVetoableChangeListener(String propertyName,
1582                                           VetoableChangeListener listener) {
1583         if (listener != null) {
1584             synchronized (this) {
1585                 if (vetoableSupport == null) {
1586                     vetoableSupport =
1587                         new VetoableChangeSupport(this);
1588                 }
1589                 vetoableSupport.addVetoableChangeListener(propertyName,
1590                                                           listener);
1591             }
1592         }
1593     }
1594 
1595     /**
1596      * Removes a VetoableChangeListener from the listener list for a specific
1597      * property. This method should be used to remove VetoableChangeListeners
1598      * that were registered for a specific bound property.
1599      * <p>
1600      * If listener is null, no exception is thrown and no action is performed.
1601      *
1602      * @param propertyName a valid property name
1603      * @param listener the VetoableChangeListener to be removed
1604      * @see #addVetoableChangeListener
1605      * @see #getVetoableChangeListeners
1606      * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
1607      */
removeVetoableChangeListener(String propertyName, VetoableChangeListener listener)1608     public void removeVetoableChangeListener(String propertyName,
1609                                              VetoableChangeListener listener) {
1610         if (listener != null) {
1611             synchronized (this) {
1612                 if (vetoableSupport != null) {
1613                     vetoableSupport.removeVetoableChangeListener(propertyName,
1614                                                                  listener);
1615                 }
1616             }
1617         }
1618     }
1619 
1620     /**
1621      * Returns an array of all the {@code VetoableChangeListener}s
1622      * associated with the named property.
1623      *
1624      * @param  propertyName the property name
1625      * @return all of the {@code VetoableChangeListener}s associated with
1626      *         the named property or an empty array if no such listeners have
1627      *         been added.
1628      *
1629      * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1630      * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1631      * @see #getVetoableChangeListeners
1632      * @since 1.4
1633      */
getVetoableChangeListeners(String propertyName)1634     public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
1635         if (vetoableSupport == null) {
1636             vetoableSupport = new VetoableChangeSupport(this);
1637         }
1638         return vetoableSupport.getVetoableChangeListeners(propertyName);
1639     }
1640 
1641     /**
1642      * Fires a PropertyChangeEvent in response to a change in a vetoable
1643      * property. The event will be delivered to all registered
1644      * VetoableChangeListeners. If a VetoableChangeListener throws a
1645      * PropertyVetoException, a new event is fired reverting all
1646      * VetoableChangeListeners to the old value and the exception is then
1647      * rethrown. No event will be delivered if oldValue and newValue are the
1648      * same.
1649      *
1650      * @param propertyName the name of the property that has changed
1651      * @param oldValue the property's previous value
1652      * @param newValue the property's new value
1653      * @throws java.beans.PropertyVetoException if a
1654      *         {@code VetoableChangeListener} threw
1655      *         {@code PropertyVetoException}
1656      */
fireVetoableChange(String propertyName, Object oldValue, Object newValue)1657     protected void fireVetoableChange(String propertyName, Object oldValue,
1658                                       Object newValue)
1659         throws PropertyVetoException
1660     {
1661         if (oldValue == newValue) {
1662             return;
1663         }
1664         VetoableChangeSupport vetoableSupport =
1665             this.vetoableSupport;
1666         if (vetoableSupport != null) {
1667             vetoableSupport.fireVetoableChange(propertyName, oldValue,
1668                                                newValue);
1669         }
1670     }
1671 
1672     /**
1673      * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
1674      * chain. This KeyboardFocusManager will request that each
1675      * KeyEventDispatcher dispatch KeyEvents generated by the user before
1676      * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
1677      * notified in the order in which they were added. Notifications will halt
1678      * as soon as one KeyEventDispatcher returns {@code true} from its
1679      * {@code dispatchKeyEvent} method. There is no limit to the total
1680      * number of KeyEventDispatchers which can be added, nor to the number of
1681      * times which a particular KeyEventDispatcher instance can be added.
1682      * <p>
1683      * If a null dispatcher is specified, no action is taken and no exception
1684      * is thrown.
1685      * <p>
1686      * In a multithreaded application, {@link KeyEventDispatcher} behaves
1687      * the same as other AWT listeners.  See
1688      * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1689      * >AWT Threading Issues</a> for more details.
1690      *
1691      * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
1692      * @see #removeKeyEventDispatcher
1693      */
addKeyEventDispatcher(KeyEventDispatcher dispatcher)1694     public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1695         if (dispatcher != null) {
1696             synchronized (this) {
1697                 if (keyEventDispatchers == null) {
1698                     keyEventDispatchers = new java.util.LinkedList<>();
1699                 }
1700                 keyEventDispatchers.add(dispatcher);
1701             }
1702         }
1703     }
1704 
1705     /**
1706      * Removes a KeyEventDispatcher which was previously added to this
1707      * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
1708      * cannot itself be removed, unless it was explicitly re-registered via a
1709      * call to {@code addKeyEventDispatcher}.
1710      * <p>
1711      * If a null dispatcher is specified, if the specified dispatcher is not
1712      * in the dispatcher chain, or if this KeyboardFocusManager is specified
1713      * without having been explicitly re-registered, no action is taken and no
1714      * exception is thrown.
1715      * <p>
1716      * In a multithreaded application, {@link KeyEventDispatcher} behaves
1717      * the same as other AWT listeners.  See
1718      * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1719      * >AWT Threading Issues</a> for more details.
1720      *
1721      * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
1722      *        chain
1723      * @see #addKeyEventDispatcher
1724      */
removeKeyEventDispatcher(KeyEventDispatcher dispatcher)1725     public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1726         if (dispatcher != null) {
1727             synchronized (this) {
1728                 if (keyEventDispatchers != null) {
1729                     keyEventDispatchers.remove(dispatcher);
1730                 }
1731             }
1732         }
1733     }
1734 
1735     /**
1736      * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
1737      * The List will not include this KeyboardFocusManager unless it was
1738      * explicitly re-registered via a call to
1739      * {@code addKeyEventDispatcher}. If no other KeyEventDispatchers are
1740      * registered, implementations are free to return null or a List of length
1741      * 0. Client code should not assume one behavior over another, nor should
1742      * it assume that the behavior, once established, will not change.
1743      *
1744      * @return a possibly null or empty List of KeyEventDispatchers
1745      * @see #addKeyEventDispatcher
1746      * @see #removeKeyEventDispatcher
1747      */
1748     @SuppressWarnings("unchecked") // Cast of result of clone
1749     protected synchronized java.util.List<KeyEventDispatcher>
getKeyEventDispatchers()1750         getKeyEventDispatchers()
1751     {
1752         return (keyEventDispatchers != null)
1753             ? (java.util.List<KeyEventDispatcher>)keyEventDispatchers.clone()
1754             : null;
1755     }
1756 
1757     /**
1758      * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
1759      * processor chain. After a KeyEvent has been dispatched to and handled by
1760      * its target, KeyboardFocusManager will request that each
1761      * KeyEventPostProcessor perform any necessary post-processing as part
1762      * of the KeyEvent's final resolution. KeyEventPostProcessors
1763      * will be notified in the order in which they were added; the current
1764      * KeyboardFocusManager will be notified last. Notifications will halt
1765      * as soon as one KeyEventPostProcessor returns {@code true} from its
1766      * {@code postProcessKeyEvent} method. There is no limit to the
1767      * total number of KeyEventPostProcessors that can be added, nor to the
1768      * number of times that a particular KeyEventPostProcessor instance can be
1769      * added.
1770      * <p>
1771      * If a null post-processor is specified, no action is taken and no
1772      * exception is thrown.
1773      * <p>
1774      * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1775      * the same as other AWT listeners.  See
1776      * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1777      * >AWT Threading Issues</a> for more details.
1778      *
1779      * @param processor the KeyEventPostProcessor to add to the post-processor
1780      *        chain
1781      * @see #removeKeyEventPostProcessor
1782      */
addKeyEventPostProcessor(KeyEventPostProcessor processor)1783     public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
1784         if (processor != null) {
1785             synchronized (this) {
1786                 if (keyEventPostProcessors == null) {
1787                     keyEventPostProcessors = new java.util.LinkedList<>();
1788                 }
1789                 keyEventPostProcessors.add(processor);
1790             }
1791         }
1792     }
1793 
1794 
1795     /**
1796      * Removes a previously added KeyEventPostProcessor from this
1797      * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
1798      * cannot itself be entirely removed from the chain. Only additional
1799      * references added via {@code addKeyEventPostProcessor} can be
1800      * removed.
1801      * <p>
1802      * If a null post-processor is specified, if the specified post-processor
1803      * is not in the post-processor chain, or if this KeyboardFocusManager is
1804      * specified without having been explicitly added, no action is taken and
1805      * no exception is thrown.
1806      * <p>
1807      * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1808      * the same as other AWT listeners.  See
1809      * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1810      * >AWT Threading Issues</a> for more details.
1811      *
1812      * @param processor the KeyEventPostProcessor to remove from the post-
1813      *        processor chain
1814      * @see #addKeyEventPostProcessor
1815      */
removeKeyEventPostProcessor(KeyEventPostProcessor processor)1816     public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
1817         if (processor != null) {
1818             synchronized (this) {
1819                 if (keyEventPostProcessors != null) {
1820                     keyEventPostProcessors.remove(processor);
1821                 }
1822             }
1823         }
1824     }
1825 
1826 
1827     /**
1828      * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
1829      * List. The List will not include this KeyboardFocusManager unless it was
1830      * explicitly added via a call to {@code addKeyEventPostProcessor}. If
1831      * no KeyEventPostProcessors are registered, implementations are free to
1832      * return null or a List of length 0. Client code should not assume one
1833      * behavior over another, nor should it assume that the behavior, once
1834      * established, will not change.
1835      *
1836      * @return a possibly null or empty List of KeyEventPostProcessors
1837      * @see #addKeyEventPostProcessor
1838      * @see #removeKeyEventPostProcessor
1839      */
1840     @SuppressWarnings("unchecked") // Cast of result of clone
1841     protected java.util.List<KeyEventPostProcessor>
getKeyEventPostProcessors()1842         getKeyEventPostProcessors()
1843     {
1844         return (keyEventPostProcessors != null)
1845             ? (java.util.List<KeyEventPostProcessor>)keyEventPostProcessors.clone()
1846             : null;
1847     }
1848 
1849 
1850 
setMostRecentFocusOwner(Component component)1851     static void setMostRecentFocusOwner(Component component) {
1852         Component window = component;
1853         while (window != null && !(window instanceof Window)) {
1854             window = window.parent;
1855         }
1856         if (window != null) {
1857             setMostRecentFocusOwner((Window)window, component);
1858         }
1859     }
setMostRecentFocusOwner(Window window, Component component)1860     static synchronized void setMostRecentFocusOwner(Window window,
1861                                                      Component component) {
1862         // ATTN: component has a strong reference to window via chain
1863         // of Component.parent fields.  Since WeakHasMap refers to its
1864         // values strongly, we need to break the strong link from the
1865         // value (component) back to its key (window).
1866         WeakReference<Component> weakValue = null;
1867         if (component != null) {
1868             weakValue = new WeakReference<>(component);
1869         }
1870         mostRecentFocusOwners.put(window, weakValue);
1871     }
clearMostRecentFocusOwner(Component comp)1872     static void clearMostRecentFocusOwner(Component comp) {
1873         Container window;
1874 
1875         if (comp == null) {
1876             return;
1877         }
1878 
1879         synchronized (comp.getTreeLock()) {
1880             window = comp.getParent();
1881             while (window != null && !(window instanceof Window)) {
1882                 window = window.getParent();
1883             }
1884         }
1885 
1886         synchronized (KeyboardFocusManager.class) {
1887             if ((window != null)
1888                 && (getMostRecentFocusOwner((Window)window) == comp))
1889             {
1890                 setMostRecentFocusOwner((Window)window, null);
1891             }
1892             // Also clear temporary lost component stored in Window
1893             if (window != null) {
1894                 Window realWindow = (Window)window;
1895                 if (realWindow.getTemporaryLostComponent() == comp) {
1896                     realWindow.setTemporaryLostComponent(null);
1897                 }
1898             }
1899         }
1900     }
1901 
1902     /*
1903      * Please be careful changing this method! It is called from
1904      * javax.swing.JComponent.runInputVerifier() using reflection.
1905      */
getMostRecentFocusOwner(Window window)1906     static synchronized Component getMostRecentFocusOwner(Window window) {
1907         WeakReference<Component> weakValue = mostRecentFocusOwners.get(window);
1908         return weakValue == null ? null : weakValue.get();
1909     }
1910 
1911     /**
1912      * This method is called by the AWT event dispatcher requesting that the
1913      * current KeyboardFocusManager dispatch the specified event on its behalf.
1914      * It is expected that all KeyboardFocusManagers will dispatch all
1915      * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
1916      * These events should be dispatched based on the KeyboardFocusManager's
1917      * notion of the focus owner and the focused and active Windows, sometimes
1918      * overriding the source of the specified AWTEvent. Dispatching must be
1919      * done using {@code redispatchEvent} to prevent the AWT event
1920      * dispatcher from recursively requesting that the KeyboardFocusManager
1921      * dispatch the event again. If this method returns {@code false},
1922      * then the AWT event dispatcher will attempt to dispatch the event itself.
1923      *
1924      * @param e the AWTEvent to be dispatched
1925      * @return {@code true} if this method dispatched the event;
1926      *         {@code false} otherwise
1927      * @see #redispatchEvent
1928      * @see #dispatchKeyEvent
1929      */
dispatchEvent(AWTEvent e)1930     public abstract boolean dispatchEvent(AWTEvent e);
1931 
1932     /**
1933      * Redispatches an AWTEvent in such a way that the AWT event dispatcher
1934      * will not recursively request that the KeyboardFocusManager, or any
1935      * installed KeyEventDispatchers, dispatch the event again. Client
1936      * implementations of {@code dispatchEvent} and client-defined
1937      * KeyEventDispatchers must call {@code redispatchEvent(target, e)}
1938      * instead of {@code target.dispatchEvent(e)} to dispatch an event.
1939      * <p>
1940      * This method is intended to be used only by KeyboardFocusManagers and
1941      * KeyEventDispatchers. It is not for general client use.
1942      *
1943      * @param target the Component to which the event should be dispatched
1944      * @param e the event to dispatch
1945      * @see #dispatchEvent
1946      * @see KeyEventDispatcher
1947      */
redispatchEvent(Component target, AWTEvent e)1948     public final void redispatchEvent(Component target, AWTEvent e) {
1949         e.focusManagerIsDispatching = true;
1950         target.dispatchEvent(e);
1951         e.focusManagerIsDispatching = false;
1952     }
1953 
1954     /**
1955      * Typically this method will be called by {@code dispatchEvent} if no
1956      * other KeyEventDispatcher in the dispatcher chain dispatched the
1957      * KeyEvent, or if no other KeyEventDispatchers are registered. If an
1958      * implementation of this method returns {@code false},
1959      * {@code dispatchEvent} may try to dispatch the KeyEvent itself, or
1960      * may simply return {@code false}. If {@code true} is returned,
1961      * {@code dispatchEvent} should return {@code true} as well.
1962      *
1963      * @param e the KeyEvent which the current KeyboardFocusManager has
1964      *        requested that this KeyEventDispatcher dispatch
1965      * @return {@code true} if the KeyEvent was dispatched;
1966      *         {@code false} otherwise
1967      * @see #dispatchEvent
1968      */
dispatchKeyEvent(KeyEvent e)1969     public abstract boolean dispatchKeyEvent(KeyEvent e);
1970 
1971     /**
1972      * This method will be called by {@code dispatchKeyEvent}.
1973      * By default, this method will handle any unconsumed KeyEvents that
1974      * map to an AWT {@code MenuShortcut} by consuming the event
1975      * and activating the shortcut.
1976      *
1977      * @param e the KeyEvent to post-process
1978      * @return {@code true} to indicate that no other
1979      *         KeyEventPostProcessor will be notified of the KeyEvent.
1980      * @see #dispatchKeyEvent
1981      * @see MenuShortcut
1982      */
postProcessKeyEvent(KeyEvent e)1983     public abstract boolean postProcessKeyEvent(KeyEvent e);
1984 
1985     /**
1986      * This method initiates a focus traversal operation if and only if the
1987      * KeyEvent represents a focus traversal key for the specified
1988      * focusedComponent. It is expected that focusedComponent is the current
1989      * focus owner, although this need not be the case. If it is not,
1990      * focus traversal will nevertheless proceed as if focusedComponent
1991      * were the current focus owner.
1992      *
1993      * @param focusedComponent the Component that will be the basis for a focus
1994      *        traversal operation if the specified event represents a focus
1995      *        traversal key for the Component
1996      * @param e the event that may represent a focus traversal key
1997      */
processKeyEvent(Component focusedComponent, KeyEvent e)1998     public abstract void processKeyEvent(Component focusedComponent,
1999                                          KeyEvent e);
2000 
2001     /**
2002      * Called by the AWT to notify the KeyboardFocusManager that it should
2003      * delay dispatching of KeyEvents until the specified Component becomes
2004      * the focus owner. If client code requests a focus change, and the AWT
2005      * determines that this request might be granted by the native windowing
2006      * system, then the AWT will call this method. It is the responsibility of
2007      * the KeyboardFocusManager to delay dispatching of KeyEvents with
2008      * timestamps later than the specified time stamp until the specified
2009      * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
2010      * request by invoking {@code dequeueKeyEvents} or
2011      * {@code discardKeyEvents}.
2012      *
2013      * @param after timestamp of current event, or the current, system time if
2014      *        the current event has no timestamp, or the AWT cannot determine
2015      *        which event is currently being handled
2016      * @param untilFocused Component which should receive a FOCUS_GAINED event
2017      *        before any pending KeyEvents
2018      * @see #dequeueKeyEvents
2019      * @see #discardKeyEvents
2020      */
enqueueKeyEvents(long after, Component untilFocused)2021     protected abstract void enqueueKeyEvents(long after,
2022                                              Component untilFocused);
2023 
2024     /**
2025      * Called by the AWT to notify the KeyboardFocusManager that it should
2026      * cancel delayed dispatching of KeyEvents. All KeyEvents which were
2027      * enqueued because of a call to {@code enqueueKeyEvents} with the
2028      * same timestamp and Component should be released for normal dispatching
2029      * to the current focus owner. If the given timestamp is less than zero,
2030      * the outstanding enqueue request for the given Component with the <b>
2031      * oldest</b> timestamp (if any) should be cancelled.
2032      *
2033      * @param after the timestamp specified in the call to
2034      *        {@code enqueueKeyEvents}, or any value &lt; 0
2035      * @param untilFocused the Component specified in the call to
2036      *        {@code enqueueKeyEvents}
2037      * @see #enqueueKeyEvents
2038      * @see #discardKeyEvents
2039      */
dequeueKeyEvents(long after, Component untilFocused)2040     protected abstract void dequeueKeyEvents(long after,
2041                                              Component untilFocused);
2042 
2043     /**
2044      * Called by the AWT to notify the KeyboardFocusManager that it should
2045      * cancel delayed dispatching of KeyEvents. All KeyEvents which were
2046      * enqueued because of one or more calls to {@code enqueueKeyEvents}
2047      * with the same Component should be discarded.
2048      *
2049      * @param comp the Component specified in one or more calls to
2050      *        {@code enqueueKeyEvents}
2051      * @see #enqueueKeyEvents
2052      * @see #dequeueKeyEvents
2053      */
discardKeyEvents(Component comp)2054     protected abstract void discardKeyEvents(Component comp);
2055 
2056     /**
2057      * Focuses the Component after aComponent, typically based on a
2058      * FocusTraversalPolicy.
2059      *
2060      * @param aComponent the Component that is the basis for the focus
2061      *        traversal operation
2062      * @see FocusTraversalPolicy
2063      */
focusNextComponent(Component aComponent)2064     public abstract void focusNextComponent(Component aComponent);
2065 
2066     /**
2067      * Focuses the Component before aComponent, typically based on a
2068      * FocusTraversalPolicy.
2069      *
2070      * @param aComponent the Component that is the basis for the focus
2071      *        traversal operation
2072      * @see FocusTraversalPolicy
2073      */
focusPreviousComponent(Component aComponent)2074     public abstract void focusPreviousComponent(Component aComponent);
2075 
2076     /**
2077      * Moves the focus up one focus traversal cycle. Typically, the focus owner
2078      * is set to aComponent's focus cycle root, and the current focus cycle
2079      * root is set to the new focus owner's focus cycle root. If, however,
2080      * aComponent's focus cycle root is a Window, then typically the focus
2081      * owner is set to the Window's default Component to focus, and the current
2082      * focus cycle root is unchanged.
2083      *
2084      * @param aComponent the Component that is the basis for the focus
2085      *        traversal operation
2086      */
upFocusCycle(Component aComponent)2087     public abstract void upFocusCycle(Component aComponent);
2088 
2089     /**
2090      * Moves the focus down one focus traversal cycle. Typically, if
2091      * aContainer is a focus cycle root, then the focus owner is set to
2092      * aContainer's default Component to focus, and the current focus cycle
2093      * root is set to aContainer. If aContainer is not a focus cycle root, then
2094      * no focus traversal operation occurs.
2095      *
2096      * @param aContainer the Container that is the basis for the focus
2097      *        traversal operation
2098      */
downFocusCycle(Container aContainer)2099     public abstract void downFocusCycle(Container aContainer);
2100 
2101     /**
2102      * Focuses the Component after the current focus owner.
2103      */
focusNextComponent()2104     public final void focusNextComponent() {
2105         Component focusOwner = getFocusOwner();
2106         if (focusOwner != null) {
2107             focusNextComponent(focusOwner);
2108         }
2109     }
2110 
2111     /**
2112      * Focuses the Component before the current focus owner.
2113      */
focusPreviousComponent()2114     public final void focusPreviousComponent() {
2115         Component focusOwner = getFocusOwner();
2116         if (focusOwner != null) {
2117             focusPreviousComponent(focusOwner);
2118         }
2119     }
2120 
2121     /**
2122      * Moves the focus up one focus traversal cycle from the current focus
2123      * owner. Typically, the new focus owner is set to the current focus
2124      * owner's focus cycle root, and the current focus cycle root is set to the
2125      * new focus owner's focus cycle root. If, however, the current focus
2126      * owner's focus cycle root is a Window, then typically the focus owner is
2127      * set to the focus cycle root's default Component to focus, and the
2128      * current focus cycle root is unchanged.
2129      */
upFocusCycle()2130     public final void upFocusCycle() {
2131         Component focusOwner = getFocusOwner();
2132         if (focusOwner != null) {
2133             upFocusCycle(focusOwner);
2134         }
2135     }
2136 
2137     /**
2138      * Moves the focus down one focus traversal cycle from the current focus
2139      * owner, if and only if the current focus owner is a Container that is a
2140      * focus cycle root. Typically, the focus owner is set to the current focus
2141      * owner's default Component to focus, and the current focus cycle root is
2142      * set to the current focus owner. If the current focus owner is not a
2143      * Container that is a focus cycle root, then no focus traversal operation
2144      * occurs.
2145      */
downFocusCycle()2146     public final void downFocusCycle() {
2147         Component focusOwner = getFocusOwner();
2148         if (focusOwner instanceof Container) {
2149             downFocusCycle((Container)focusOwner);
2150         }
2151     }
2152 
2153     /**
2154      * Dumps the list of focus requests to stderr
2155      */
dumpRequests()2156     void dumpRequests() {
2157         System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2158         synchronized (heavyweightRequests) {
2159             for (HeavyweightFocusRequest req : heavyweightRequests) {
2160                 System.err.println(">>> Req: " + req);
2161             }
2162         }
2163         System.err.println("");
2164     }
2165 
2166     private static final class LightweightFocusRequest {
2167         final Component component;
2168         final boolean temporary;
2169         final FocusEvent.Cause cause;
2170 
LightweightFocusRequest(Component component, boolean temporary, FocusEvent.Cause cause)2171         LightweightFocusRequest(Component component, boolean temporary, FocusEvent.Cause cause) {
2172             this.component = component;
2173             this.temporary = temporary;
2174             this.cause = cause;
2175         }
toString()2176         public String toString() {
2177             return "LightweightFocusRequest[component=" + component +
2178                 ",temporary=" + temporary + ", cause=" + cause + "]";
2179         }
2180     }
2181 
2182     private static final class HeavyweightFocusRequest {
2183         final Component heavyweight;
2184         final LinkedList<LightweightFocusRequest> lightweightRequests;
2185 
2186         static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2187             new HeavyweightFocusRequest();
2188 
HeavyweightFocusRequest()2189         private HeavyweightFocusRequest() {
2190             heavyweight = null;
2191             lightweightRequests = null;
2192         }
2193 
HeavyweightFocusRequest(Component heavyweight, Component descendant, boolean temporary, FocusEvent.Cause cause)2194         HeavyweightFocusRequest(Component heavyweight, Component descendant,
2195                                 boolean temporary, FocusEvent.Cause cause) {
2196             if (log.isLoggable(PlatformLogger.Level.FINE)) {
2197                 if (heavyweight == null) {
2198                     log.fine("Assertion (heavyweight != null) failed");
2199                 }
2200             }
2201 
2202             this.heavyweight = heavyweight;
2203             this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
2204             addLightweightRequest(descendant, temporary, cause);
2205         }
addLightweightRequest(Component descendant, boolean temporary, FocusEvent.Cause cause)2206         boolean addLightweightRequest(Component descendant,
2207                                       boolean temporary, FocusEvent.Cause cause) {
2208             if (log.isLoggable(PlatformLogger.Level.FINE)) {
2209                 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2210                     log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
2211                 }
2212                 if (descendant == null) {
2213                     log.fine("Assertion (descendant != null) failed");
2214                 }
2215             }
2216 
2217             Component lastDescendant = ((lightweightRequests.size() > 0)
2218                 ? lightweightRequests.getLast().component
2219                 : null);
2220 
2221             if (descendant != lastDescendant) {
2222                 // Not a duplicate request
2223                 lightweightRequests.add
2224                     (new LightweightFocusRequest(descendant, temporary, cause));
2225                 return true;
2226             } else {
2227                 return false;
2228             }
2229         }
2230 
getFirstLightweightRequest()2231         LightweightFocusRequest getFirstLightweightRequest() {
2232             if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
2233                 return null;
2234             }
2235             return lightweightRequests.getFirst();
2236         }
toString()2237         public String toString() {
2238             boolean first = true;
2239             String str = "HeavyweightFocusRequest[heavyweight=" + heavyweight +
2240                 ",lightweightRequests=";
2241             if (lightweightRequests == null) {
2242                 str += null;
2243             } else {
2244                 str += "[";
2245 
2246                 for (LightweightFocusRequest lwRequest : lightweightRequests) {
2247                     if (first) {
2248                         first = false;
2249                     } else {
2250                         str += ",";
2251                     }
2252                     str += lwRequest;
2253                 }
2254                 str += "]";
2255             }
2256             str += "]";
2257             return str;
2258         }
2259     }
2260 
2261     /*
2262      * heavyweightRequests is used as a monitor for synchronized changes of
2263      * currentLightweightRequests, clearingCurrentLightweightRequests and
2264      * newFocusOwner.
2265      */
2266     private static LinkedList<HeavyweightFocusRequest> heavyweightRequests =
2267         new LinkedList<HeavyweightFocusRequest>();
2268     private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
2269     private static boolean clearingCurrentLightweightRequests;
2270     private static boolean allowSyncFocusRequests = true;
2271     private static Component newFocusOwner = null;
2272     private static volatile boolean disableRestoreFocus;
2273 
2274     static final int SNFH_FAILURE = 0;
2275     static final int SNFH_SUCCESS_HANDLED = 1;
2276     static final int SNFH_SUCCESS_PROCEED = 2;
2277 
processSynchronousLightweightTransfer(Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time)2278     static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
2279                                                   boolean temporary, boolean focusedWindowChangeAllowed,
2280                                                   long time)
2281     {
2282         Window parentWindow = SunToolkit.getContainingWindow(heavyweight);
2283         if (parentWindow == null || !parentWindow.syncLWRequests) {
2284             return false;
2285         }
2286         if (descendant == null) {
2287             // Focus transfers from a lightweight child back to the
2288             // heavyweight Container should be treated like lightweight
2289             // focus transfers.
2290             descendant = heavyweight;
2291         }
2292 
2293         KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2294 
2295         FocusEvent currentFocusOwnerEvent = null;
2296         FocusEvent newFocusOwnerEvent = null;
2297         Component currentFocusOwner = manager.getGlobalFocusOwner();
2298 
2299         synchronized (heavyweightRequests) {
2300             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2301             if (hwFocusRequest == null &&
2302                 heavyweight == manager.getNativeFocusOwner() &&
2303                 allowSyncFocusRequests)
2304             {
2305 
2306                 if (descendant == currentFocusOwner) {
2307                     // Redundant request.
2308                     return true;
2309                 }
2310 
2311                 // 'heavyweight' owns the native focus and there are no pending
2312                 // requests. 'heavyweight' must be a Container and
2313                 // 'descendant' must not be the focus owner. Otherwise,
2314                 // we would never have gotten this far.
2315                 manager.enqueueKeyEvents(time, descendant);
2316 
2317                 hwFocusRequest =
2318                     new HeavyweightFocusRequest(heavyweight, descendant,
2319                                                 temporary, FocusEvent.Cause.UNKNOWN);
2320                 heavyweightRequests.add(hwFocusRequest);
2321 
2322                 if (currentFocusOwner != null) {
2323                     currentFocusOwnerEvent =
2324                         new FocusEvent(currentFocusOwner,
2325                                        FocusEvent.FOCUS_LOST,
2326                                        temporary, descendant);
2327                 }
2328                 newFocusOwnerEvent =
2329                     new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2330                                    temporary, currentFocusOwner);
2331             }
2332         }
2333         boolean result = false;
2334         final boolean clearing = clearingCurrentLightweightRequests;
2335 
2336         Throwable caughtEx = null;
2337         try {
2338             clearingCurrentLightweightRequests = false;
2339             synchronized(Component.LOCK) {
2340 
2341                 if (currentFocusOwnerEvent != null && currentFocusOwner != null) {
2342                     ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2343                     caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2344                     result = true;
2345                 }
2346 
2347                 if (newFocusOwnerEvent != null && descendant != null) {
2348                     ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2349                     caughtEx = dispatchAndCatchException(caughtEx, descendant, newFocusOwnerEvent);
2350                     result = true;
2351                 }
2352             }
2353         } finally {
2354             clearingCurrentLightweightRequests = clearing;
2355         }
2356         if (caughtEx instanceof RuntimeException) {
2357             throw (RuntimeException)caughtEx;
2358         } else if (caughtEx instanceof Error) {
2359             throw (Error)caughtEx;
2360         }
2361         return result;
2362     }
2363 
2364     /**
2365      * Indicates whether the native implementation should proceed with a
2366      * pending, native focus request. Before changing the focus at the native
2367      * level, the AWT implementation should always call this function for
2368      * permission. This function will reject the request if a duplicate request
2369      * preceded it, or if the specified heavyweight Component already owns the
2370      * focus and no native focus changes are pending. Otherwise, the request
2371      * will be approved and the focus request list will be updated so that,
2372      * if necessary, the proper descendant will be focused when the
2373      * corresponding FOCUS_GAINED event on the heavyweight is received.
2374      *
2375      * An implementation must ensure that calls to this method and native
2376      * focus changes are atomic. If this is not guaranteed, then the ordering
2377      * of the focus request list may be incorrect, leading to errors in the
2378      * type-ahead mechanism. Typically this is accomplished by only calling
2379      * this function from the native event pumping thread, or by holding a
2380      * global, native lock during invocation.
2381      */
shouldNativelyFocusHeavyweight(Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)2382     static int shouldNativelyFocusHeavyweight
2383         (Component heavyweight, Component descendant, boolean temporary,
2384          boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)
2385     {
2386         if (log.isLoggable(PlatformLogger.Level.FINE)) {
2387             if (heavyweight == null) {
2388                 log.fine("Assertion (heavyweight != null) failed");
2389             }
2390             if (time == 0) {
2391                 log.fine("Assertion (time != 0) failed");
2392             }
2393         }
2394 
2395         if (descendant == null) {
2396             // Focus transfers from a lightweight child back to the
2397             // heavyweight Container should be treated like lightweight
2398             // focus transfers.
2399             descendant = heavyweight;
2400         }
2401 
2402         KeyboardFocusManager manager =
2403             getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2404         KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();
2405         Component currentFocusOwner = thisManager.getGlobalFocusOwner();
2406         Component nativeFocusOwner = thisManager.getNativeFocusOwner();
2407         Window nativeFocusedWindow = thisManager.getNativeFocusedWindow();
2408         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
2409             focusLog.finer("SNFH for {0} in {1}",
2410                        String.valueOf(descendant), String.valueOf(heavyweight));
2411         }
2412         if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
2413             focusLog.finest("0. Current focus owner {0}",
2414                             String.valueOf(currentFocusOwner));
2415             focusLog.finest("0. Native focus owner {0}",
2416                             String.valueOf(nativeFocusOwner));
2417             focusLog.finest("0. Native focused window {0}",
2418                             String.valueOf(nativeFocusedWindow));
2419         }
2420         synchronized (heavyweightRequests) {
2421             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2422             if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
2423                 focusLog.finest("Request {0}", String.valueOf(hwFocusRequest));
2424             }
2425             if (hwFocusRequest == null &&
2426                 heavyweight == nativeFocusOwner &&
2427                 heavyweight.getContainingWindow() == nativeFocusedWindow)
2428             {
2429                 if (descendant == currentFocusOwner) {
2430                     // Redundant request.
2431                     if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2432                         focusLog.finest("1. SNFH_FAILURE for {0}",
2433                                         String.valueOf(descendant));
2434                     return SNFH_FAILURE;
2435                 }
2436 
2437                 // 'heavyweight' owns the native focus and there are no pending
2438                 // requests. 'heavyweight' must be a Container and
2439                 // 'descendant' must not be the focus owner. Otherwise,
2440                 // we would never have gotten this far.
2441                 manager.enqueueKeyEvents(time, descendant);
2442 
2443                 hwFocusRequest =
2444                     new HeavyweightFocusRequest(heavyweight, descendant,
2445                                                 temporary, cause);
2446                 heavyweightRequests.add(hwFocusRequest);
2447 
2448                 if (currentFocusOwner != null) {
2449                     FocusEvent currentFocusOwnerEvent =
2450                         new FocusEvent(currentFocusOwner,
2451                                        FocusEvent.FOCUS_LOST,
2452                                        temporary, descendant, cause);
2453                     // Fix 5028014. Rolled out.
2454                     // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2455                     SunToolkit.postEvent(currentFocusOwner.appContext,
2456                                          currentFocusOwnerEvent);
2457                 }
2458                 FocusEvent newFocusOwnerEvent =
2459                     new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
2460                                    temporary, currentFocusOwner, cause);
2461                 // Fix 5028014. Rolled out.
2462                 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2463                 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
2464 
2465                 if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
2466                     focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant));
2467                 return SNFH_SUCCESS_HANDLED;
2468             } else if (hwFocusRequest != null &&
2469                        hwFocusRequest.heavyweight == heavyweight) {
2470                 // 'heavyweight' doesn't have the native focus right now, but
2471                 // if all pending requests were completed, it would. Add
2472                 // descendant to the heavyweight's list of pending
2473                 // lightweight focus transfers.
2474                 if (hwFocusRequest.addLightweightRequest(descendant,
2475                                                          temporary, cause)) {
2476                     manager.enqueueKeyEvents(time, descendant);
2477                 }
2478 
2479                 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
2480                     focusLog.finest("3. SNFH_HANDLED for lightweight" +
2481                                     descendant + " in " + heavyweight);
2482                 }
2483                 return SNFH_SUCCESS_HANDLED;
2484             } else {
2485                 if (!focusedWindowChangeAllowed) {
2486                     // For purposes of computing oldFocusedWindow, we should look at
2487                     // the second to last HeavyweightFocusRequest on the queue iff the
2488                     // last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If
2489                     // there is no second to last HeavyweightFocusRequest, null is an
2490                     // acceptable value.
2491                     if (hwFocusRequest ==
2492                         HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2493                     {
2494                         int size = heavyweightRequests.size();
2495                         hwFocusRequest = (size >= 2)
2496                             ? heavyweightRequests.get(size - 2)
2497                             : null;
2498                     }
2499                     if (focusedWindowChanged(heavyweight,
2500                                              (hwFocusRequest != null)
2501                                              ? hwFocusRequest.heavyweight
2502                                              : nativeFocusedWindow)) {
2503                         if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
2504                             focusLog.finest("4. SNFH_FAILURE for " + descendant);
2505                         }
2506                         return SNFH_FAILURE;
2507                     }
2508                 }
2509 
2510                 manager.enqueueKeyEvents(time, descendant);
2511                 heavyweightRequests.add
2512                     (new HeavyweightFocusRequest(heavyweight, descendant,
2513                                                  temporary, cause));
2514                 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
2515                     focusLog.finest("5. SNFH_PROCEED for " + descendant);
2516                 }
2517                 return SNFH_SUCCESS_PROCEED;
2518             }
2519         }
2520     }
2521 
2522     /**
2523      * Returns the Window which will be active after processing this request,
2524      * or null if this is a duplicate request. The active Window is useful
2525      * because some native platforms do not support setting the native focus
2526      * owner to null. On these platforms, the obvious choice is to set the
2527      * focus owner to the focus proxy of the active Window.
2528      */
markClearGlobalFocusOwner()2529     static Window markClearGlobalFocusOwner() {
2530         // need to call this out of synchronized block to avoid possible deadlock
2531         // see 6454631.
2532         final Component nativeFocusedWindow =
2533                 getCurrentKeyboardFocusManager().getNativeFocusedWindow();
2534 
2535         synchronized (heavyweightRequests) {
2536             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2537             if (hwFocusRequest ==
2538                 HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2539             {
2540                 // duplicate request
2541                 return null;
2542             }
2543 
2544             heavyweightRequests.add
2545                 (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
2546 
2547             Component activeWindow = ((hwFocusRequest != null)
2548                 ? SunToolkit.getContainingWindow(hwFocusRequest.heavyweight)
2549                 : nativeFocusedWindow);
2550             while (activeWindow != null &&
2551                    !((activeWindow instanceof Frame) ||
2552                      (activeWindow instanceof Dialog)))
2553             {
2554                 activeWindow = activeWindow.getParent_NoClientCode();
2555             }
2556 
2557             return (Window) activeWindow;
2558         }
2559     }
getCurrentWaitingRequest(Component parent)2560     Component getCurrentWaitingRequest(Component parent) {
2561         synchronized (heavyweightRequests) {
2562             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2563             if (hwFocusRequest != null) {
2564                 if (hwFocusRequest.heavyweight == parent) {
2565                     LightweightFocusRequest lwFocusRequest =
2566                         hwFocusRequest.lightweightRequests.getFirst();
2567                     if (lwFocusRequest != null) {
2568                         return lwFocusRequest.component;
2569                     }
2570                 }
2571             }
2572         }
2573         return null;
2574     }
2575 
isAutoFocusTransferEnabled()2576     static boolean isAutoFocusTransferEnabled() {
2577         synchronized (heavyweightRequests) {
2578             return (heavyweightRequests.size() == 0)
2579                     && !disableRestoreFocus
2580                     && (null == currentLightweightRequests);
2581         }
2582     }
2583 
isAutoFocusTransferEnabledFor(Component comp)2584     static boolean isAutoFocusTransferEnabledFor(Component comp) {
2585         return isAutoFocusTransferEnabled() && comp.isAutoFocusTransferOnDisposal();
2586     }
2587 
2588     /*
2589      * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
2590      * @param ex previously caught exception that may be processed right here, or null
2591      * @param comp the component to dispatch the event to
2592      * @param event the event to dispatch to the component
2593      */
dispatchAndCatchException(Throwable ex, Component comp, FocusEvent event)2594     private static Throwable dispatchAndCatchException(Throwable ex, Component comp, FocusEvent event) {
2595         Throwable retEx = null;
2596         try {
2597             comp.dispatchEvent(event);
2598         } catch (RuntimeException re) {
2599             retEx = re;
2600         } catch (Error er) {
2601             retEx = er;
2602         }
2603         if (retEx != null) {
2604             if (ex != null) {
2605                 handleException(ex);
2606             }
2607             return retEx;
2608         }
2609         return ex;
2610     }
2611 
handleException(Throwable ex)2612     private static void handleException(Throwable ex) {
2613         ex.printStackTrace();
2614     }
2615 
processCurrentLightweightRequests()2616     static void processCurrentLightweightRequests() {
2617         KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2618         LinkedList<LightweightFocusRequest> localLightweightRequests = null;
2619 
2620         Component globalFocusOwner = manager.getGlobalFocusOwner();
2621         if ((globalFocusOwner != null) &&
2622             (globalFocusOwner.appContext != AppContext.getAppContext()))
2623         {
2624             // The current app context differs from the app context of a focus
2625             // owner (and all pending lightweight requests), so we do nothing
2626             // now and wait for a next event.
2627             return;
2628         }
2629 
2630         synchronized(heavyweightRequests) {
2631             if (currentLightweightRequests != null) {
2632                 clearingCurrentLightweightRequests = true;
2633                 disableRestoreFocus = true;
2634                 localLightweightRequests = currentLightweightRequests;
2635                 allowSyncFocusRequests = (localLightweightRequests.size() < 2);
2636                 currentLightweightRequests = null;
2637             } else {
2638                 // do nothing
2639                 return;
2640             }
2641         }
2642 
2643         Throwable caughtEx = null;
2644         try {
2645             if (localLightweightRequests != null) {
2646                 Component lastFocusOwner = null;
2647                 Component currentFocusOwner = null;
2648 
2649                 for (Iterator<KeyboardFocusManager.LightweightFocusRequest> iter = localLightweightRequests.iterator(); iter.hasNext(); ) {
2650 
2651                     currentFocusOwner = manager.getGlobalFocusOwner();
2652                     LightweightFocusRequest lwFocusRequest =
2653                         iter.next();
2654 
2655                     /*
2656                      * WARNING: This is based on DKFM's logic solely!
2657                      *
2658                      * We allow to trigger restoreFocus() in the dispatching process
2659                      * only if we have the last request to dispatch. If the last request
2660                      * fails, focus will be restored to either the component of the last
2661                      * previously succeeded request, or to the focus owner that was
2662                      * before this clearing process.
2663                      */
2664                     if (!iter.hasNext()) {
2665                         disableRestoreFocus = false;
2666                     }
2667 
2668                     FocusEvent currentFocusOwnerEvent = null;
2669                     /*
2670                      * We're not dispatching FOCUS_LOST while the current focus owner is null.
2671                      * But regardless of whether it's null or not, we're clearing ALL the local
2672                      * lw requests.
2673                      */
2674                     if (currentFocusOwner != null) {
2675                         currentFocusOwnerEvent = new FocusEvent(currentFocusOwner,
2676                                        FocusEvent.FOCUS_LOST,
2677                                        lwFocusRequest.temporary,
2678                                        lwFocusRequest.component, lwFocusRequest.cause);
2679                     }
2680                     FocusEvent newFocusOwnerEvent =
2681                         new FocusEvent(lwFocusRequest.component,
2682                                        FocusEvent.FOCUS_GAINED,
2683                                        lwFocusRequest.temporary,
2684                                        currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
2685                                        lwFocusRequest.cause);
2686 
2687                     if (currentFocusOwner != null) {
2688                         ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2689                         caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2690                     }
2691 
2692                     ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2693                     caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
2694 
2695                     if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2696                         lastFocusOwner = lwFocusRequest.component;
2697                     }
2698                 }
2699             }
2700         } finally {
2701             clearingCurrentLightweightRequests = false;
2702             disableRestoreFocus = false;
2703             localLightweightRequests = null;
2704             allowSyncFocusRequests = true;
2705         }
2706         if (caughtEx instanceof RuntimeException) {
2707             throw (RuntimeException)caughtEx;
2708         } else if (caughtEx instanceof Error) {
2709             throw (Error)caughtEx;
2710         }
2711     }
2712 
retargetUnexpectedFocusEvent(FocusEvent fe)2713     static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2714         synchronized (heavyweightRequests) {
2715             // Any other case represents a failure condition which we did
2716             // not expect. We need to clearFocusRequestList() and patch up
2717             // the event as best as possible.
2718 
2719             if (removeFirstRequest()) {
2720                 return (FocusEvent)retargetFocusEvent(fe);
2721             }
2722 
2723             Component source = fe.getComponent();
2724             Component opposite = fe.getOppositeComponent();
2725             boolean temporary = false;
2726             if (fe.getID() == FocusEvent.FOCUS_LOST &&
2727                 (opposite == null || isTemporary(opposite, source)))
2728             {
2729                 temporary = true;
2730             }
2731             return new FocusEvent(source, fe.getID(), temporary, opposite,
2732                                         FocusEvent.Cause.UNEXPECTED);
2733         }
2734     }
2735 
retargetFocusGained(FocusEvent fe)2736     static FocusEvent retargetFocusGained(FocusEvent fe) {
2737         assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2738 
2739         Component currentFocusOwner = getCurrentKeyboardFocusManager().
2740             getGlobalFocusOwner();
2741         Component source = fe.getComponent();
2742         Component opposite = fe.getOppositeComponent();
2743         Component nativeSource = getHeavyweight(source);
2744 
2745         synchronized (heavyweightRequests) {
2746             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2747 
2748             if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2749             {
2750                 return retargetUnexpectedFocusEvent(fe);
2751             }
2752 
2753             if (source != null && nativeSource == null && hwFocusRequest != null) {
2754                 // if source w/o peer and
2755                 // if source is equal to first lightweight
2756                 // then we should correct source and nativeSource
2757                 if (source == hwFocusRequest.getFirstLightweightRequest().component)
2758                 {
2759                     source = hwFocusRequest.heavyweight;
2760                     nativeSource = source; // source is heavyweight itself
2761                 }
2762             }
2763             if (hwFocusRequest != null &&
2764                 nativeSource == hwFocusRequest.heavyweight)
2765             {
2766                 // Focus change as a result of a known call to requestFocus(),
2767                 // or known click on a peer focusable heavyweight Component.
2768 
2769                 heavyweightRequests.removeFirst();
2770 
2771                 LightweightFocusRequest lwFocusRequest =
2772                     hwFocusRequest.lightweightRequests.removeFirst();
2773 
2774                 Component newSource = lwFocusRequest.component;
2775                 if (currentFocusOwner != null) {
2776                     /*
2777                      * Since we receive FOCUS_GAINED when current focus
2778                      * owner is not null, corresponding FOCUS_LOST is supposed
2779                      * to be lost.  And so,  we keep new focus owner
2780                      * to determine synthetic FOCUS_LOST event which will be
2781                      * generated by KeyboardFocusManager for this FOCUS_GAINED.
2782                      *
2783                      * This code based on knowledge of
2784                      * DefaultKeyboardFocusManager's implementation and might
2785                      * be not applicable for another KeyboardFocusManager.
2786                      */
2787                     newFocusOwner = newSource;
2788                 }
2789 
2790                 boolean temporary = (opposite == null ||
2791                                      isTemporary(newSource, opposite))
2792                         ? false
2793                         : lwFocusRequest.temporary;
2794 
2795                 if (hwFocusRequest.lightweightRequests.size() > 0) {
2796                     currentLightweightRequests =
2797                         hwFocusRequest.lightweightRequests;
2798                     EventQueue.invokeLater(new Runnable() {
2799                             public void run() {
2800                                 processCurrentLightweightRequests();
2801                             }
2802                         });
2803                 }
2804 
2805                 // 'opposite' will be fixed by
2806                 // DefaultKeyboardFocusManager.realOppositeComponent
2807                 return new FocusEvent(newSource,
2808                                       FocusEvent.FOCUS_GAINED, temporary,
2809                                       opposite, lwFocusRequest.cause);
2810             }
2811 
2812             if (currentFocusOwner != null
2813                 && currentFocusOwner.getContainingWindow() == source
2814                 && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
2815             {
2816                 // Special case for FOCUS_GAINED in top-levels
2817                 // If it arrives as the result of activation we should skip it
2818                 // This event will not have appropriate request record and
2819                 // on arrival there will be already some focus owner set.
2820                 return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
2821                                             null, FocusEvent.Cause.ACTIVATION);
2822             }
2823 
2824             return retargetUnexpectedFocusEvent(fe);
2825         } // end synchronized(heavyweightRequests)
2826     }
2827 
retargetFocusLost(FocusEvent fe)2828     static FocusEvent retargetFocusLost(FocusEvent fe) {
2829         assert (fe.getID() == FocusEvent.FOCUS_LOST);
2830 
2831         Component currentFocusOwner = getCurrentKeyboardFocusManager().
2832             getGlobalFocusOwner();
2833         Component opposite = fe.getOppositeComponent();
2834         Component nativeOpposite = getHeavyweight(opposite);
2835 
2836         synchronized (heavyweightRequests) {
2837             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2838 
2839             if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2840             {
2841                 if (currentFocusOwner != null) {
2842                     // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2843                     heavyweightRequests.removeFirst();
2844                     return new FocusEvent(currentFocusOwner,
2845                                                 FocusEvent.FOCUS_LOST, false, null,
2846                                                 FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
2847                 }
2848 
2849                 // Otherwise, fall through to failure case below
2850 
2851             } else if (opposite == null)
2852             {
2853                 // Focus leaving application
2854                 if (currentFocusOwner != null) {
2855                     return new FocusEvent(currentFocusOwner,
2856                                                 FocusEvent.FOCUS_LOST,
2857                                                 true, null, FocusEvent.Cause.ACTIVATION);
2858                 } else {
2859                     return fe;
2860                 }
2861             } else if (hwFocusRequest != null &&
2862                        (nativeOpposite == hwFocusRequest.heavyweight ||
2863                         nativeOpposite == null &&
2864                         opposite == hwFocusRequest.getFirstLightweightRequest().component))
2865             {
2866                 if (currentFocusOwner == null) {
2867                     return fe;
2868                 }
2869                 // Focus change as a result of a known call to requestFocus(),
2870                 // or click on a peer focusable heavyweight Component.
2871                 // If a focus transfer is made across top-levels, then the
2872                 // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2873                 // event is always permanent. Otherwise, the stored temporary
2874                 // value is honored.
2875 
2876                 LightweightFocusRequest lwFocusRequest =
2877                     hwFocusRequest.lightweightRequests.getFirst();
2878 
2879                 boolean temporary = isTemporary(opposite, currentFocusOwner)
2880                     ? true
2881                     : lwFocusRequest.temporary;
2882 
2883                 return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2884                                             temporary, lwFocusRequest.component, lwFocusRequest.cause);
2885             } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2886                 // If top-level changed there might be no focus request in a list
2887                 // But we know the opposite, we now it is temporary - dispatch the event.
2888                 if (!fe.isTemporary() && currentFocusOwner != null) {
2889                     // Create copy of the event with only difference in temporary parameter.
2890                     fe = new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
2891                                               true, opposite, FocusEvent.Cause.ACTIVATION);
2892                 }
2893                 return fe;
2894             }
2895 
2896             return retargetUnexpectedFocusEvent(fe);
2897         }  // end synchronized(heavyweightRequests)
2898     }
2899 
retargetFocusEvent(AWTEvent event)2900     static AWTEvent retargetFocusEvent(AWTEvent event) {
2901         if (clearingCurrentLightweightRequests) {
2902             return event;
2903         }
2904 
2905         KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2906         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
2907             if (event instanceof FocusEvent || event instanceof WindowEvent) {
2908                 focusLog.finer(">>> {0}", String.valueOf(event));
2909             }
2910             if (focusLog.isLoggable(PlatformLogger.Level.FINER) && event instanceof KeyEvent) {
2911                 focusLog.finer("    focus owner is {0}",
2912                                String.valueOf(manager.getGlobalFocusOwner()));
2913                 focusLog.finer(">>> {0}", String.valueOf(event));
2914             }
2915         }
2916 
2917         synchronized(heavyweightRequests) {
2918             /*
2919              * This code handles FOCUS_LOST event which is generated by
2920              * DefaultKeyboardFocusManager for FOCUS_GAINED.
2921              *
2922              * This code based on knowledge of DefaultKeyboardFocusManager's
2923              * implementation and might be not applicable for another
2924              * KeyboardFocusManager.
2925              *
2926              * Fix for 4472032
2927              */
2928             if (newFocusOwner != null &&
2929                 event.getID() == FocusEvent.FOCUS_LOST)
2930             {
2931                 FocusEvent fe = (FocusEvent)event;
2932 
2933                 if (manager.getGlobalFocusOwner() == fe.getComponent() &&
2934                     fe.getOppositeComponent() == newFocusOwner)
2935                 {
2936                     newFocusOwner = null;
2937                     return event;
2938                 }
2939             }
2940         }
2941 
2942         processCurrentLightweightRequests();
2943 
2944         switch (event.getID()) {
2945             case FocusEvent.FOCUS_GAINED: {
2946                 event = retargetFocusGained((FocusEvent)event);
2947                 break;
2948             }
2949             case FocusEvent.FOCUS_LOST: {
2950                 event = retargetFocusLost((FocusEvent)event);
2951                 break;
2952             }
2953             default:
2954                 /* do nothing */
2955         }
2956         return event;
2957     }
2958 
2959     /**
2960      * Clears markers queue
2961      * This method is not intended to be overridden by KFM's.
2962      * Only DefaultKeyboardFocusManager can implement it.
2963      * @since 1.5
2964      */
clearMarkers()2965     void clearMarkers() {
2966     }
2967 
removeFirstRequest()2968     static boolean removeFirstRequest() {
2969         KeyboardFocusManager manager =
2970             KeyboardFocusManager.getCurrentKeyboardFocusManager();
2971 
2972         synchronized(heavyweightRequests) {
2973             HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2974 
2975             if (hwFocusRequest != null) {
2976                 heavyweightRequests.removeFirst();
2977                 if (hwFocusRequest.lightweightRequests != null) {
2978                     for (Iterator<KeyboardFocusManager.LightweightFocusRequest> lwIter = hwFocusRequest.lightweightRequests.
2979                              iterator();
2980                          lwIter.hasNext(); )
2981                     {
2982                         manager.dequeueKeyEvents
2983                             (-1, lwIter.next().
2984                              component);
2985                     }
2986                 }
2987             }
2988             // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2989             // We do it here because this method is called only when problems happen
2990             if (heavyweightRequests.size() == 0) {
2991                 manager.clearMarkers();
2992             }
2993             return (heavyweightRequests.size() > 0);
2994         }
2995     }
removeLastFocusRequest(Component heavyweight)2996     static void removeLastFocusRequest(Component heavyweight) {
2997         if (log.isLoggable(PlatformLogger.Level.FINE)) {
2998             if (heavyweight == null) {
2999                 log.fine("Assertion (heavyweight != null) failed");
3000             }
3001         }
3002 
3003         KeyboardFocusManager manager =
3004             KeyboardFocusManager.getCurrentKeyboardFocusManager();
3005         synchronized(heavyweightRequests) {
3006             HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
3007             if (hwFocusRequest != null &&
3008                 hwFocusRequest.heavyweight == heavyweight) {
3009                 heavyweightRequests.removeLast();
3010             }
3011             // Fix for 4799136 - clear type-ahead markers if requests queue is empty
3012             // We do it here because this method is called only when problems happen
3013             if (heavyweightRequests.size() == 0) {
3014                 manager.clearMarkers();
3015             }
3016         }
3017     }
3018 
focusedWindowChanged(Component to, Component from)3019     private static boolean focusedWindowChanged(Component to, Component from) {
3020         Window wto = SunToolkit.getContainingWindow(to);
3021         Window wfrom = SunToolkit.getContainingWindow(from);
3022         if (wto == null && wfrom == null) {
3023             return true;
3024         }
3025         if (wto == null) {
3026             return true;
3027         }
3028         if (wfrom == null) {
3029             return true;
3030         }
3031         return (wto != wfrom);
3032     }
3033 
isTemporary(Component to, Component from)3034     private static boolean isTemporary(Component to, Component from) {
3035         Window wto = SunToolkit.getContainingWindow(to);
3036         Window wfrom = SunToolkit.getContainingWindow(from);
3037         if (wto == null && wfrom == null) {
3038             return false;
3039         }
3040         if (wto == null) {
3041             return true;
3042         }
3043         if (wfrom == null) {
3044             return false;
3045         }
3046         return (wto != wfrom);
3047     }
3048 
getHeavyweight(Component comp)3049     static Component getHeavyweight(Component comp) {
3050         if (comp == null || comp.peer == null) {
3051             return null;
3052         } else if (comp.peer instanceof LightweightPeer) {
3053             return comp.getNativeContainer();
3054         } else {
3055             return comp;
3056         }
3057     }
3058 
3059     // Accessor to private field isProxyActive of KeyEvent
isProxyActiveImpl(KeyEvent e)3060     private static boolean isProxyActiveImpl(KeyEvent e) {
3061         return AWTAccessor.getKeyEventAccessor().isProxyActive(e);
3062     }
3063 
3064     // Returns the value of this KeyEvent's field isProxyActive
isProxyActive(KeyEvent e)3065     static boolean isProxyActive(KeyEvent e) {
3066         if (!GraphicsEnvironment.isHeadless()) {
3067             return isProxyActiveImpl(e);
3068         } else {
3069             return false;
3070         }
3071     }
3072 
getLastHWRequest()3073     private static HeavyweightFocusRequest getLastHWRequest() {
3074         synchronized(heavyweightRequests) {
3075             return (heavyweightRequests.size() > 0)
3076                 ? heavyweightRequests.getLast()
3077                 : null;
3078         }
3079     }
3080 
getFirstHWRequest()3081     private static HeavyweightFocusRequest getFirstHWRequest() {
3082         synchronized(heavyweightRequests) {
3083             return (heavyweightRequests.size() > 0)
3084                 ? heavyweightRequests.getFirst()
3085                 : null;
3086         }
3087     }
3088 
checkReplaceKFMPermission()3089     private static void checkReplaceKFMPermission()
3090         throws SecurityException
3091     {
3092         SecurityManager security = System.getSecurityManager();
3093         if (security != null) {
3094             if (replaceKeyboardFocusManagerPermission == null) {
3095                 replaceKeyboardFocusManagerPermission =
3096                     new AWTPermission("replaceKeyboardFocusManager");
3097             }
3098             security.
3099                 checkPermission(replaceKeyboardFocusManagerPermission);
3100         }
3101     }
3102 
3103     // Checks if this KeyboardFocusManager instance is the current KFM,
3104     // or otherwise checks if the calling thread has "replaceKeyboardFocusManager"
3105     // permission. Here's the reasoning to do so:
3106     //
3107     // A system KFM instance (which is the current KFM by default) may have no
3108     // "replaceKFM" permission when a client code is on the call stack beneath,
3109     // but still it should be able to execute the methods protected by this check
3110     // due to the system KFM is trusted (and so it does like "privileged").
3111     //
3112     // If this KFM instance is not the current KFM but the client code has all
3113     // permissions we can't throw SecurityException because it would contradict
3114     // the security concepts. In this case the trusted client code is responsible
3115     // for calling the secured methods from KFM instance which is not current.
checkKFMSecurity()3116     private void checkKFMSecurity()
3117         throws SecurityException
3118     {
3119         if (this != getCurrentKeyboardFocusManager()) {
3120             checkReplaceKFMPermission();
3121         }
3122     }
3123 }
3124