KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > awt > KeyboardFocusManager


1 /*
2  * @(#)KeyboardFocusManager.java 1.66 07/03/13
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package java.awt;
8
9 import java.awt.event.FocusEvent JavaDoc;
10 import java.awt.event.InputEvent JavaDoc;
11 import java.awt.event.KeyEvent JavaDoc;
12 import java.awt.event.WindowEvent JavaDoc;
13
14 import java.awt.peer.LightweightPeer;
15 import java.awt.peer.WindowPeer;
16 import java.beans.*;
17 import java.util.Set JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.Iterator JavaDoc;
21 import java.util.LinkedList JavaDoc;
22 import java.util.ListIterator JavaDoc;
23 import java.util.StringTokenizer JavaDoc;
24 import java.util.WeakHashMap JavaDoc;
25 import java.lang.ref.WeakReference JavaDoc;
26 import sun.awt.AppContext;
27 import sun.awt.DebugHelper;
28 import sun.awt.SunToolkit;
29 import sun.awt.HeadlessToolkit;
30 import java.util.logging.*;
31 import java.awt.peer.KeyboardFocusManagerPeer;
32 import java.lang.reflect.*;
33 import java.security.AccessController JavaDoc;
34 import java.security.PrivilegedAction JavaDoc;
35
36 /**
37  * The KeyboardFocusManager is responsible for managing the active and focused
38  * Windows, and the current focus owner. The focus owner is defined as the
39  * Component in an application that will typically receive all KeyEvents
40  * generated by the user. The focused Window is the Window that is, or
41  * contains, the focus owner. Only a Frame or a Dialog can be the active
42  * Window. The native windowing system may denote the active Window or its
43  * children with special decorations, such as a highlighted title bar. The
44  * active Window is always either the focused Window, or the first Frame or
45  * Dialog that is an owner of the focused Window.
46  * <p>
47  * The KeyboardFocusManager is both a centralized location for client code to
48  * query for the focus owner and initiate focus changes, and an event
49  * dispatcher for all FocusEvents, WindowEvents related to focus, and
50  * KeyEvents.
51  * <p>
52  * Some browsers partition applets in different code bases into separate
53  * contexts, and establish walls between these contexts. In such a scenario,
54  * there will be one KeyboardFocusManager per context. Other browsers place all
55  * applets into the same context, implying that there will be only a single,
56  * global KeyboardFocusManager for all applets. This behavior is
57  * implementation-dependent. Consult your browser's documentation for more
58  * information. No matter how many contexts there may be, however, there can
59  * never be more than one focus owner, focused Window, or active Window, per
60  * ClassLoader.
61  * <p>
62  * Please see
63  * <a HREF="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
64  * How to Use the Focus Subsystem</a>,
65  * a section in <em>The Java Tutorial</em>, and the
66  * <a HREF="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
67  * for more information.
68  *
69  * @author David Mendenhall
70  * @version 1.66, 03/13/07
71  *
72  * @see Window
73  * @see Frame
74  * @see Dialog
75  * @see java.awt.event.FocusEvent
76  * @see java.awt.event.WindowEvent
77  * @see java.awt.event.KeyEvent
78  * @since 1.4
79  */

80 public abstract class KeyboardFocusManager
81     implements KeyEventDispatcher JavaDoc, KeyEventPostProcessor JavaDoc
82 {
83
84     // Shared focus engine logger
85
private static final Logger focusLog = Logger.getLogger("java.awt.focus.KeyboardFocusManager");
86
87     static {
88         /* ensure that the necessary native libraries are loaded */
89         Toolkit.loadLibraries();
90         if (!GraphicsEnvironment.isHeadless()) {
91             initIDs();
92         }
93     }
94
95     transient KeyboardFocusManagerPeer peer;
96
97     /**
98      * Initialize JNI field and method IDs
99      */

100     private static native void initIDs();
101
102     private static final DebugHelper dbg =
103         DebugHelper.create(KeyboardFocusManager JavaDoc.class);
104
105     /**
106      * The identifier for the Forward focus traversal keys.
107      *
108      * @see #setDefaultFocusTraversalKeys
109      * @see #getDefaultFocusTraversalKeys
110      * @see Component#setFocusTraversalKeys
111      * @see Component#getFocusTraversalKeys
112      */

113     public static final int FORWARD_TRAVERSAL_KEYS = 0;
114
115     /**
116      * The identifier for the Backward focus traversal keys.
117      *
118      * @see #setDefaultFocusTraversalKeys
119      * @see #getDefaultFocusTraversalKeys
120      * @see Component#setFocusTraversalKeys
121      * @see Component#getFocusTraversalKeys
122      */

123     public static final int BACKWARD_TRAVERSAL_KEYS = 1;
124
125     /**
126      * The identifier for the Up Cycle focus traversal keys.
127      *
128      * @see #setDefaultFocusTraversalKeys
129      * @see #getDefaultFocusTraversalKeys
130      * @see Component#setFocusTraversalKeys
131      * @see Component#getFocusTraversalKeys
132      */

133     public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
134
135     /**
136      * The identifier for the Down Cycle focus traversal keys.
137      *
138      * @see #setDefaultFocusTraversalKeys
139      * @see #getDefaultFocusTraversalKeys
140      * @see Component#setFocusTraversalKeys
141      * @see Component#getFocusTraversalKeys
142      */

143     public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
144
145     static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
146
147     private transient boolean inActivation;
148
149     /*
150     * Please be careful changing this method! It is called from
151     * javax.swing.JComponent.runInputVerifier() using reflection.
152     */

153     synchronized boolean isInActivation() {
154         return inActivation;
155     }
156
157     synchronized void setInActivation(boolean inActivation) {
158         this.inActivation = inActivation;
159     }
160
161     /**
162      * Returns the current KeyboardFocusManager instance for the calling
163      * thread's context.
164      *
165      * @return this thread's context's KeyboardFocusManager
166      * @see #setCurrentKeyboardFocusManager
167      */

168     public static KeyboardFocusManager JavaDoc getCurrentKeyboardFocusManager() {
169     return getCurrentKeyboardFocusManager(AppContext.getAppContext());
170     }
171
172     synchronized static KeyboardFocusManager JavaDoc
173     getCurrentKeyboardFocusManager(AppContext appcontext)
174     {
175         KeyboardFocusManager JavaDoc manager = (KeyboardFocusManager JavaDoc)
176             appcontext.get(KeyboardFocusManager JavaDoc.class);
177         if (manager == null) {
178             manager = new DefaultKeyboardFocusManager JavaDoc();
179             appcontext.put(KeyboardFocusManager JavaDoc.class, manager);
180         }
181         return manager;
182     }
183
184     /**
185      * Sets the current KeyboardFocusManager instance for the calling thread's
186      * context. If null is specified, then the current KeyboardFocusManager
187      * is replaced with a new instance of DefaultKeyboardFocusManager.
188      * <p>
189      * If a SecurityManager is installed, the calling thread must be granted
190      * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
191      * the current KeyboardFocusManager. If this permission is not granted,
192      * this method will throw a SecurityException, and the current
193      * KeyboardFocusManager will be unchanged.
194      *
195      * @param newManager the new KeyboardFocusManager for this thread's context
196      * @see #getCurrentKeyboardFocusManager
197      * @see DefaultKeyboardFocusManager
198      * @throws SecurityException if the calling thread does not have permission
199      * to replace the current KeyboardFocusManager
200      */

201     public static void setCurrentKeyboardFocusManager(
202         KeyboardFocusManager JavaDoc newManager) throws SecurityException JavaDoc
203     {
204         SecurityManager JavaDoc security = System.getSecurityManager();
205         if (security != null) {
206             if (replaceKeyboardFocusManagerPermission == null) {
207                 replaceKeyboardFocusManagerPermission =
208                     new AWTPermission JavaDoc("replaceKeyboardFocusManager");
209             }
210             security.
211                 checkPermission(replaceKeyboardFocusManagerPermission);
212         }
213
214         KeyboardFocusManager JavaDoc oldManager = null;
215
216         synchronized (KeyboardFocusManager JavaDoc.class) {
217             AppContext appcontext = AppContext.getAppContext();
218
219             if (newManager != null) {
220                 oldManager = getCurrentKeyboardFocusManager(appcontext);
221
222                 appcontext.put(KeyboardFocusManager JavaDoc.class, newManager);
223             } else {
224                 oldManager = getCurrentKeyboardFocusManager(appcontext);
225                 appcontext.remove(KeyboardFocusManager JavaDoc.class);
226             }
227         }
228
229         if (oldManager != null) {
230             oldManager.firePropertyChange("managingFocus",
231                                           Boolean.TRUE,
232                                           Boolean.FALSE);
233         }
234         if (newManager != null) {
235             newManager.firePropertyChange("managingFocus",
236                                           Boolean.FALSE,
237                                           Boolean.TRUE);
238         }
239     }
240
241     /**
242      * The Component in an application that will typically receive all
243      * KeyEvents generated by the user.
244      */

245     private static Component JavaDoc focusOwner;
246
247     /**
248      * The Component in an application that will regain focus when an
249      * outstanding temporary focus transfer has completed, or the focus owner,
250      * if no outstanding temporary transfer exists.
251      */

252     private static Component JavaDoc permanentFocusOwner;
253
254     /**
255      * The Window which is, or contains, the focus owner.
256      */

257     private static Window JavaDoc focusedWindow;
258
259     /**
260      * Only a Frame or a Dialog can be the active Window. The native windowing
261      * system may denote the active Window with a special decoration, such as a
262      * highlighted title bar. The active Window is always either the focused
263      * Window, or the first Frame or Dialog which is an owner of the focused
264      * Window.
265      */

266     private static Window JavaDoc activeWindow;
267
268     /**
269      * The default FocusTraversalPolicy for all Windows that have no policy of
270      * their own set. If those Windows have focus-cycle-root children that have
271      * no keyboard-traversal policy of their own, then those children will also
272      * inherit this policy (as will, recursively, their focus-cycle-root
273      * children).
274      */

275     private FocusTraversalPolicy JavaDoc defaultPolicy =
276         new DefaultFocusTraversalPolicy JavaDoc();
277
278     /**
279      * The bound property names of each focus traversal key.
280      */

281     private static final String JavaDoc[] defaultFocusTraversalKeyPropertyNames = {
282         "forwardDefaultFocusTraversalKeys",
283         "backwardDefaultFocusTraversalKeys",
284         "upCycleDefaultFocusTraversalKeys",
285         "downCycleDefaultFocusTraversalKeys"
286     };
287
288     /**
289      * The default strokes for initializing the default focus traversal keys.
290      */

291     private static final AWTKeyStroke JavaDoc[][] defaultFocusTraversalKeyStrokes = {
292         {
293             AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false),
294             AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false),
295         },
296         {
297             AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false),
298             AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
299                                          InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK,
300                                          false),
301         },
302         {},
303         {},
304       };
305     /**
306      * The default focus traversal keys. Each array of traversal keys will be
307      * in effect on all Windows that have no such array of their own explicitly
308      * set. Each array will also be inherited, recursively, by any child
309      * Component of those Windows that has no such array of its own explicitly
310      * set.
311      */

312     private Set JavaDoc[] defaultFocusTraversalKeys = new Set JavaDoc[4];
313
314     /**
315      * The current focus cycle root. If the focus owner is itself a focus cycle
316      * root, then it may be ambiguous as to which Components represent the next
317      * and previous Components to focus during normal focus traversal. In that
318      * case, the current focus cycle root is used to differentiate among the
319      * possibilities.
320      */

321     private static Container JavaDoc currentFocusCycleRoot;
322
323     /**
324      * A description of any VetoableChangeListeners which have been registered.
325      */

326     private VetoableChangeSupport vetoableSupport;
327
328     /**
329      * A description of any PropertyChangeListeners which have been registered.
330      */

331     private PropertyChangeSupport changeSupport;
332
333     /**
334      * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
335      * include this KeyboardFocusManager unless it was explicitly re-registered
336      * via a call to <code>addKeyEventDispatcher</code>. If no other
337      * KeyEventDispatchers are registered, this field may be null or refer to
338      * a List of length 0.
339      */

340     private java.util.LinkedList JavaDoc keyEventDispatchers;
341
342     /**
343      * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
344      * not include this KeyboardFocusManager unless it was explicitly
345      * re-registered via a call to <code>addKeyEventPostProcessor</code>.
346      * If no other KeyEventPostProcessors are registered, this field may be
347      * null or refer to a List of length 0.
348      */

349     private java.util.LinkedList JavaDoc keyEventPostProcessors;
350
351     /**
352      * Maps Windows to those Windows' most recent focus owners.
353      */

354     private static java.util.Map JavaDoc mostRecentFocusOwners = new WeakHashMap JavaDoc();
355
356     /**
357      * Error String for initializing SecurityExceptions.
358      */

359     private static final String JavaDoc notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
360
361     /**
362      * We cache the permission used to verify that the calling thread is
363      * permitted to access the global focus state.
364      */

365     private static AWTPermission JavaDoc replaceKeyboardFocusManagerPermission;
366
367     /*
368      * SequencedEvent which is currently dispatched in AppContext.
369      */

370     transient SequencedEvent JavaDoc currentSequencedEvent = null;
371
372     final void setCurrentSequencedEvent(SequencedEvent JavaDoc current) {
373         synchronized (SequencedEvent JavaDoc.class) {
374             assert(current == null || currentSequencedEvent == null);
375             currentSequencedEvent = current;
376         }
377     }
378
379     final SequencedEvent JavaDoc getCurrentSequencedEvent() {
380         synchronized (SequencedEvent JavaDoc.class) {
381             return currentSequencedEvent;
382         }
383     }
384
385     static Set JavaDoc initFocusTraversalKeysSet(String JavaDoc value, Set JavaDoc targetSet) {
386     StringTokenizer JavaDoc tokens = new StringTokenizer JavaDoc(value, ",");
387     while (tokens.hasMoreTokens()) {
388         targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken()));
389     }
390     return (targetSet.isEmpty())
391         ? Collections.EMPTY_SET
392         : Collections.unmodifiableSet(targetSet);
393     }
394
395     /**
396      * Initializes a KeyboardFocusManager.
397      */

398     public KeyboardFocusManager() {
399         for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
400             Set JavaDoc work_set = new HashSet JavaDoc();
401             for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
402                 work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
403             }
404             defaultFocusTraversalKeys[i] = (work_set.isEmpty())
405                 ? Collections.EMPTY_SET
406                 : Collections.unmodifiableSet(work_set);
407         }
408         initPeer();
409     }
410
411     private void initPeer() {
412         if (Toolkit.getDefaultToolkit() instanceof HeadlessToolkit){
413             peer = ((HeadlessToolkit)Toolkit.getDefaultToolkit()).createKeyboardFocusManagerPeer(this);
414         }
415         if (Toolkit.getDefaultToolkit() instanceof SunToolkit){
416             peer = ((SunToolkit)Toolkit.getDefaultToolkit()).createKeyboardFocusManagerPeer(this);
417         }
418     }
419
420     /**
421      * Returns the focus owner, if the focus owner is in the same context as
422      * the calling thread. The focus owner is defined as the Component in an
423      * application that will typically receive all KeyEvents generated by the
424      * user. KeyEvents which map to the focus owner's focus traversal keys will
425      * not be delivered if focus traversal keys are enabled for the focus
426      * owner. In addition, KeyEventDispatchers may retarget or consume
427      * KeyEvents before they reach the focus owner.
428      *
429      * @return the focus owner, or null if the focus owner is not a member of
430      * the calling thread's context
431      * @see #getGlobalFocusOwner
432      * @see #setGlobalFocusOwner
433      */

434     public Component JavaDoc getFocusOwner() {
435         synchronized (KeyboardFocusManager JavaDoc.class) {
436         if (focusOwner == null) {
437             return null;
438         }
439
440         return (focusOwner.appContext == AppContext.getAppContext())
441             ? focusOwner
442             : null;
443     }
444     }
445
446     /**
447      * Returns the focus owner, even if the calling thread is in a different
448      * context than the focus owner. The focus owner is defined as the
449      * Component in an application that will typically receive all KeyEvents
450      * generated by the user. KeyEvents which map to the focus owner's focus
451      * traversal keys will not be delivered if focus traversal keys are enabled
452      * for the focus owner. In addition, KeyEventDispatchers may retarget or
453      * consume KeyEvents before they reach the focus owner.
454      * <p>
455      * This method will throw a SecurityException if this KeyboardFocusManager
456      * is not the current KeyboardFocusManager for the calling thread's
457      * context.
458      *
459      * @return the focus owner
460      * @see #getFocusOwner
461      * @see #setGlobalFocusOwner
462      * @throws SecurityException if this KeyboardFocusManager is not the
463      * current KeyboardFocusManager for the calling thread's context
464      */

465     protected Component JavaDoc getGlobalFocusOwner() throws SecurityException JavaDoc {
466         synchronized (KeyboardFocusManager JavaDoc.class) {
467         if (this == getCurrentKeyboardFocusManager()) {
468             return focusOwner;
469         } else {
470                 if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
471             throw new SecurityException JavaDoc(notPrivileged);
472         }
473     }
474     }
475
476     /**
477      * Sets the focus owner. The operation will be cancelled if the Component
478      * is not focusable. The focus owner is defined as the Component in an
479      * application that will typically receive all KeyEvents generated by the
480      * user. KeyEvents which map to the focus owner's focus traversal keys will
481      * not be delivered if focus traversal keys are enabled for the focus
482      * owner. In addition, KeyEventDispatchers may retarget or consume
483      * KeyEvents before they reach the focus owner.
484      * <p>
485      * This method does not actually set the focus to the specified Component.
486      * It merely stores the value to be subsequently returned by
487      * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
488      * or <code>Component.requestFocusInWindow()</code> to change the focus
489      * owner, subject to platform limitations.
490      *
491      * @param focusOwner the focus owner
492      * @see #getFocusOwner
493      * @see #getGlobalFocusOwner
494      * @see Component#requestFocus()
495      * @see Component#requestFocusInWindow()
496      * @see Component#isFocusable
497      * @beaninfo
498      * bound: true
499      */

500     protected void setGlobalFocusOwner(Component JavaDoc focusOwner) {
501         Component JavaDoc oldFocusOwner = null;
502     boolean shouldFire = false;
503
504     if (focusOwner == null || focusOwner.isFocusable()) {
505         synchronized (KeyboardFocusManager JavaDoc.class) {
506             oldFocusOwner = getFocusOwner();
507
508         try {
509             fireVetoableChange("focusOwner", oldFocusOwner,
510                        focusOwner);
511         } catch (PropertyVetoException e) {
512             // rejected
513
return;
514         }
515
516         KeyboardFocusManager.focusOwner = focusOwner;
517
518         if (focusOwner != null &&
519                     (getCurrentFocusCycleRoot() == null ||
520              !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot())))
521         {
522             Container JavaDoc rootAncestor =
523                 focusOwner.getFocusCycleRootAncestor();
524             if (rootAncestor == null && (focusOwner instanceof Window JavaDoc))
525             {
526                 rootAncestor = (Container JavaDoc)focusOwner;
527             }
528                     if (rootAncestor != null) {
529                 setGlobalCurrentFocusCycleRoot(rootAncestor);
530             }
531                 }
532
533         shouldFire = true;
534         }
535     }
536
537     if (shouldFire) {
538         firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
539     }
540     }
541
542     /**
543      * Clears the global focus owner at both the Java and native levels. If
544      * there exists a focus owner, that Component will receive a permanent
545      * FOCUS_LOST event. After this operation completes, the native windowing
546      * system will discard all user-generated KeyEvents until the user selects
547      * a new Component to receive focus, or a Component is given focus
548      * explicitly via a call to <code>requestFocus()</code>. This operation
549      * does not change the focused or active Windows.
550      *
551      * @see Component#requestFocus()
552      * @see java.awt.event.FocusEvent#FOCUS_LOST
553      */

554     public void clearGlobalFocusOwner() {
555         if (!GraphicsEnvironment.isHeadless()) {
556             // Toolkit must be fully initialized, otherwise
557
// _clearGlobalFocusOwner will crash or throw an exception
558
Toolkit.getDefaultToolkit();
559
560             _clearGlobalFocusOwner();
561         }
562     }
563     private void _clearGlobalFocusOwner() {
564         Window JavaDoc activeWindow = markClearGlobalFocusOwner();
565         peer.clearGlobalFocusOwner(activeWindow);
566     }
567
568     Component JavaDoc getNativeFocusOwner() {
569         return peer.getCurrentFocusOwner();
570     }
571
572     void setNativeFocusOwner(Component JavaDoc comp) {
573         focusLog.log(Level.FINEST, "Calling peer {0} setCurrentFocusOwner for {1}",
574                      new Object JavaDoc[] {peer, comp});
575         peer.setCurrentFocusOwner(comp);
576     }
577       
578     Window JavaDoc getNativeFocusedWindow() {
579         return peer.getCurrentFocusedWindow();
580     }
581
582     void setNativeFocusedWindow(Window JavaDoc win) {
583         peer.setCurrentFocusedWindow(win);
584     }
585
586     /**
587      * Returns the permanent focus owner, if the permanent focus owner is in
588      * the same context as the calling thread. The permanent focus owner is
589      * defined as the last Component in an application to receive a permanent
590      * FOCUS_GAINED event. The focus owner and permanent focus owner are
591      * equivalent unless a temporary focus change is currently in effect. In
592      * such a situation, the permanent focus owner will again be the focus
593      * owner when the temporary focus change ends.
594      *
595      * @return the permanent focus owner, or null if the permanent focus owner
596      * is not a member of the calling thread's context
597      * @see #getGlobalPermanentFocusOwner
598      * @see #setGlobalPermanentFocusOwner
599      */

600     public Component JavaDoc getPermanentFocusOwner() {
601     synchronized (KeyboardFocusManager JavaDoc.class) {
602         if (permanentFocusOwner == null) {
603         return null;
604         }
605
606         return (permanentFocusOwner.appContext ==
607             AppContext.getAppContext())
608         ? permanentFocusOwner
609         : null;
610     }
611     }
612
613     /**
614      * Returns the permanent focus owner, even if the calling thread is in a
615      * different context than the permanent focus owner. The permanent focus
616      * owner is defined as the last Component in an application to receive a
617      * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
618      * are equivalent unless a temporary focus change is currently in effect.
619      * In such a situation, the permanent focus owner will again be the focus
620      * owner when the temporary focus change ends.
621      * <p>
622      * This method will throw a SecurityException if this KeyboardFocusManager
623      * is not the current KeyboardFocusManager for the calling thread's
624      * context.
625      *
626      * @return the permanent focus owner
627      * @see #getPermanentFocusOwner
628      * @see #setGlobalPermanentFocusOwner
629      * @throws SecurityException if this KeyboardFocusManager is not the
630      * current KeyboardFocusManager for the calling thread's context
631      */

632     protected Component JavaDoc getGlobalPermanentFocusOwner()
633     throws SecurityException JavaDoc
634     {
635     synchronized (KeyboardFocusManager JavaDoc.class) {
636         if (this == getCurrentKeyboardFocusManager()) {
637         return permanentFocusOwner;
638         } else {
639                 if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
640         throw new SecurityException JavaDoc(notPrivileged);
641         }
642     }
643     }
644
645     /**
646      * Sets the permanent focus owner. The operation will be cancelled if the
647      * Component is not focusable. The permanent focus owner is defined as the
648      * last Component in an application to receive a permanent FOCUS_GAINED
649      * event. The focus owner and permanent focus owner are equivalent unless
650      * a temporary focus change is currently in effect. In such a situation,
651      * the permanent focus owner will again be the focus owner when the
652      * temporary focus change ends.
653      * <p>
654      * This method does not actually set the focus to the specified Component.
655      * It merely stores the value to be subsequently returned by
656      * <code>getPermanentFocusOwner()</code>. Use
657      * <code>Component.requestFocus()</code> or
658      * <code>Component.requestFocusInWindow()</code> to change the focus owner,
659      * subject to platform limitations.
660      *
661      * @param permanentFocusOwner the permanent focus owner
662      * @see #getPermanentFocusOwner
663      * @see #getGlobalPermanentFocusOwner
664      * @see Component#requestFocus()
665      * @see Component#requestFocusInWindow()
666      * @see Component#isFocusable
667      * @beaninfo
668      * bound: true
669      */

670     protected void setGlobalPermanentFocusOwner(Component JavaDoc permanentFocusOwner)
671     {
672         Component JavaDoc oldPermanentFocusOwner = null;
673     boolean shouldFire = false;
674
675     if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
676         synchronized (KeyboardFocusManager JavaDoc.class) {
677             oldPermanentFocusOwner = getPermanentFocusOwner();
678
679         try {
680             fireVetoableChange("permanentFocusOwner",
681                        oldPermanentFocusOwner,
682                        permanentFocusOwner);
683         } catch (PropertyVetoException e) {
684             // rejected
685
return;
686         }
687
688         KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
689
690         KeyboardFocusManager.
691             setMostRecentFocusOwner(permanentFocusOwner);
692
693         shouldFire = true;
694         }
695     }
696
697     if (shouldFire) {
698         firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
699                    permanentFocusOwner);
700     }
701     }
702
703     /**
704      * Returns the focused Window, if the focused Window is in the same context
705      * as the calling thread. The focused Window is the Window that is or
706      * contains the focus owner.
707      *
708      * @return the focused Window, or null if the focused Window is not a
709      * member of the calling thread's context
710      * @see #getGlobalFocusedWindow
711      * @see #setGlobalFocusedWindow
712      */

713     public Window JavaDoc getFocusedWindow() {
714         synchronized (KeyboardFocusManager JavaDoc.class) {
715         if (focusedWindow == null) {
716             return null;
717         }
718
719         return (focusedWindow.appContext == AppContext.getAppContext())
720             ? focusedWindow
721             : null;
722     }
723     }
724
725     /**
726      * Returns the focused Window, even if the calling thread is in a different
727      * context than the focused Window. The focused Window is the Window that
728      * is or contains the focus owner.
729      * <p>
730      * This method will throw a SecurityException if this KeyboardFocusManager
731      * is not the current KeyboardFocusManager for the calling thread's
732      * context.
733      *
734      * @return the focused Window
735      * @see #getFocusedWindow
736      * @see #setGlobalFocusedWindow
737      * @throws SecurityException if this KeyboardFocusManager is not the
738      * current KeyboardFocusManager for the calling thread's context
739      */

740     protected Window JavaDoc getGlobalFocusedWindow() throws SecurityException JavaDoc {
741         synchronized (KeyboardFocusManager JavaDoc.class) {
742         if (this == getCurrentKeyboardFocusManager()) {
743            return focusedWindow;
744         } else {
745                 if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
746             throw new SecurityException JavaDoc(notPrivileged);
747         }
748     }
749     }
750
751     /**
752      * Sets the focused Window. The focused Window is the Window that is or
753      * contains the focus owner. The operation will be cancelled if the
754      * specified Window to focus is not a focusable Window.
755      * <p>
756      * This method does not actually change the focused Window as far as the
757      * native windowing system is concerned. It merely stores the value to be
758      * subsequently returned by <code>getFocusedWindow()</code>. Use
759      * <code>Component.requestFocus()</code> or
760      * <code>Component.requestFocusInWindow()</code> to change the focused
761      * Window, subject to platform limitations.
762      *
763      * @param focusedWindow the focused Window
764      * @see #getFocusedWindow
765      * @see #getGlobalFocusedWindow
766      * @see Component#requestFocus()
767      * @see Component#requestFocusInWindow()
768      * @see Window#isFocusableWindow
769      * @beaninfo
770      * bound: true
771      */

772     protected void setGlobalFocusedWindow(Window JavaDoc focusedWindow) {
773         Window JavaDoc oldFocusedWindow = null;
774     boolean shouldFire = false;
775
776     if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
777         synchronized (KeyboardFocusManager JavaDoc.class) {
778             oldFocusedWindow = getFocusedWindow();
779
780         try {
781             fireVetoableChange("focusedWindow", oldFocusedWindow,
782                        focusedWindow);
783         } catch (PropertyVetoException e) {
784             // rejected
785
return;
786         }
787
788         KeyboardFocusManager.focusedWindow = focusedWindow;
789         shouldFire = true;
790         }
791     }
792
793     if (shouldFire) {
794         firePropertyChange("focusedWindow", oldFocusedWindow,
795                    focusedWindow);
796     }
797     }
798
799     /**
800      * Returns the active Window, if the active Window is in the same context
801      * as the calling thread. Only a Frame or a Dialog can be the active
802      * Window. The native windowing system may denote the active Window or its
803      * children with special decorations, such as a highlighted title bar.
804      * The active Window is always either the focused Window, or the first
805      * Frame or Dialog that is an owner of the focused Window.
806      *
807      * @return the active Window, or null if the active Window is not a member
808      * of the calling thread's context
809      * @see #getGlobalActiveWindow
810      * @see #setGlobalActiveWindow
811      */

812     public Window JavaDoc getActiveWindow() {
813         synchronized (KeyboardFocusManager JavaDoc.class) {
814         if (activeWindow == null) {
815             return null;
816         }
817
818         return (activeWindow.appContext == AppContext.getAppContext())
819             ? activeWindow
820             : null;
821     }
822     }
823
824     /**
825      * Returns the active Window, even if the calling thread is in a different
826      * context than the active Window. Only a Frame or a Dialog can be the
827      * active Window. The native windowing system may denote the active Window
828      * or its children with special decorations, such as a highlighted title
829      * bar. The active Window is always either the focused Window, or the first
830      * Frame or Dialog that is an owner of the focused Window.
831      * <p>
832      * This method will throw a SecurityException if this KeyboardFocusManager
833      * is not the current KeyboardFocusManager for the calling thread's
834      * context.
835      *
836      * @return the active Window
837      * @see #getActiveWindow
838      * @see #setGlobalActiveWindow
839      * @throws SecurityException if this KeyboardFocusManager is not the
840      * current KeyboardFocusManager for the calling thread's context
841      */

842     protected Window JavaDoc getGlobalActiveWindow() throws SecurityException JavaDoc {
843         synchronized (KeyboardFocusManager JavaDoc.class) {
844         if (this == getCurrentKeyboardFocusManager()) {
845            return activeWindow;
846         } else {
847                 if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
848         throw new SecurityException JavaDoc(notPrivileged);
849         }
850     }
851     }
852
853     /**
854      * Sets the active Window. Only a Frame or a Dialog can be the active
855      * Window. The native windowing system may denote the active Window or its
856      * children with special decorations, such as a highlighted title bar. The
857      * active Window is always either the focused Window, or the first Frame or
858      * Dialog that is an owner of the focused Window.
859      * <p>
860      * This method does not actually change the active Window as far as the
861      * native windowing system is concerned. It merely stores the value to be
862      * subsequently returned by <code>getActiveWindow()</code>. Use
863      * <code>Component.requestFocus()</code> or
864      * <code>Component.requestFocusInWindow()</code>to change the active
865      * Window, subject to platform limitations.
866      *
867      * @param activeWindow the active Window
868      * @see #getActiveWindow
869      * @see #getGlobalActiveWindow
870      * @see Component#requestFocus()
871      * @see Component#requestFocusInWindow()
872      * @beaninfo
873      * bound: true
874      */

875     protected void setGlobalActiveWindow(Window JavaDoc activeWindow) {
876         Window JavaDoc oldActiveWindow;
877     synchronized (KeyboardFocusManager JavaDoc.class) {
878         oldActiveWindow = getActiveWindow();
879             if (focusLog.isLoggable(Level.FINER)) {
880                 focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
881             }
882
883         try {
884         fireVetoableChange("activeWindow", oldActiveWindow,
885                    activeWindow);
886         } catch (PropertyVetoException e) {
887         // rejected
888
return;
889         }
890
891         KeyboardFocusManager.activeWindow = activeWindow;
892     }
893
894     firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
895     }
896
897     /**
898      * Returns the default FocusTraversalPolicy. Top-level components
899      * use this value on their creation to initialize their own focus traversal
900      * policy by explicit call to Container.setFocusTraversalPolicy.
901      *
902      * @return the default FocusTraversalPolicy. null will never be returned.
903      * @see #setDefaultFocusTraversalPolicy
904      * @see Container#setFocusTraversalPolicy
905      * @see Container#getFocusTraversalPolicy
906      */

907     public synchronized FocusTraversalPolicy JavaDoc getDefaultFocusTraversalPolicy() {
908         return defaultPolicy;
909     }
910
911     /**
912      * Sets the default FocusTraversalPolicy. Top-level components
913      * use this value on their creation to initialize their own focus traversal
914      * policy by explicit call to Container.setFocusTraversalPolicy.
915      * Note: this call doesn't affect already created components as they have
916      * their policy initialized. Only new components will use this policy as
917      * their default policy.
918      *
919      * @param defaultPolicy the new, default FocusTraversalPolicy
920      * @see #getDefaultFocusTraversalPolicy
921      * @see Container#setFocusTraversalPolicy
922      * @see Container#getFocusTraversalPolicy
923      * @throws IllegalArgumentException if defaultPolicy is null
924      * @beaninfo
925      * bound: true
926      */

927     public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy JavaDoc
928                            defaultPolicy) {
929         if (defaultPolicy == null) {
930             throw new IllegalArgumentException JavaDoc("default focus traversal policy cannot be null");
931         }
932
933         FocusTraversalPolicy JavaDoc oldPolicy;
934
935     synchronized (this) {
936         oldPolicy = this.defaultPolicy;
937         this.defaultPolicy = defaultPolicy;
938     }
939
940         firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
941                            defaultPolicy);
942     }
943
944     /**
945      * Sets the default focus traversal keys for a given traversal operation.
946      * This traversal key <code>Set</code> will be in effect on all
947      * <code>Window</code>s that have no such <code>Set</code> of
948      * their own explicitly defined. This <code>Set</code> will also be
949      * inherited, recursively, by any child <code>Component</code> of
950      * those <code>Windows</code> that has
951      * no such <code>Set</code> of its own explicitly defined.
952      * <p>
953      * The default values for the default focus traversal keys are
954      * implementation-dependent. Sun recommends that all implementations for a
955      * particular native platform use the same default values. The
956      * recommendations for Windows and Unix are listed below. These
957      * recommendations are used in the Sun AWT implementations.
958      *
959      * <table border=1 summary="Recommended default values for focus traversal keys">
960      * <tr>
961      * <th>Identifier</th>
962      * <th>Meaning</th>
963      * <th>Default</th>
964      * </tr>
965      * <tr>
966      * <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
967      * <td>Normal forward keyboard traversal</td>
968      * <td><code>TAB</code> on <code>KEY_PRESSED</code>,
969      * <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
970      * </tr>
971      * <tr>
972      * <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
973      * <td>Normal reverse keyboard traversal</td>
974      * <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
975      * <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
976      * </tr>
977      * <tr>
978      * <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
979      * <td>Go up one focus traversal cycle</td>
980      * <td>none</td>
981      * </tr>
982      * <tr>
983      * <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
984      * <td>Go down one focus traversal cycle</td>
985      * <td>none</td>
986      * </tr>
987      * </table>
988      *
989      * To disable a traversal key, use an empty <code>Set</code>;
990      * <code>Collections.EMPTY_SET</code> is recommended.
991      * <p>
992      * Using the <code>AWTKeyStroke</code> API, client code can
993      * specify on which of two
994      * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
995      * <code>KEY_RELEASED</code>, the focus traversal operation will
996      * occur. Regardless of which <code>KeyEvent</code> is specified,
997      * however, all <code>KeyEvent</code>s related to the focus
998      * traversal key, including the associated <code>KEY_TYPED</code>
999      * event, will be consumed, and will not be dispatched
1000     * to any <code>Component</code>. It is a runtime error to
1001     * specify a <code>KEY_TYPED</code> event as
1002     * mapping to a focus traversal operation, or to map the same event to
1003     * multiple default focus traversal operations.
1004     *
1005     * @param id one of
1006     * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1007     * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1008     * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1009     * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
1010     * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
1011     * specified operation
1012     * @see #getDefaultFocusTraversalKeys
1013     * @see Component#setFocusTraversalKeys
1014     * @see Component#getFocusTraversalKeys
1015     * @throws IllegalArgumentException if id is not one of
1016     * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1017     * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1018     * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1019     * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
1020     * or if keystrokes is <code>null</code>,
1021     * or if keystrokes contains <code>null</code>,
1022     * or if any <code>Object</code> in
1023     * keystrokes is not an <code>AWTKeyStroke</code>,
1024     * or if any keystroke
1025     * represents a <code>KEY_TYPED</code> event,
1026     * or if any keystroke already maps
1027     * to another default focus traversal operation
1028     * @beaninfo
1029     * bound: true
1030     */

1031    public void
1032    setDefaultFocusTraversalKeys(int id,
1033                     Set JavaDoc<? extends AWTKeyStroke JavaDoc> keystrokes)
1034    {
1035        if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1036            throw new IllegalArgumentException JavaDoc("invalid focus traversal key identifier");
1037        }
1038        if (keystrokes == null) {
1039            throw new IllegalArgumentException JavaDoc("cannot set null Set of default focus traversal keys");
1040        }
1041
1042    Set JavaDoc oldKeys;
1043
1044    synchronized (this) {
1045        for (Iterator JavaDoc iter = keystrokes.iterator(); iter.hasNext(); ) {
1046        Object JavaDoc obj = iter.next();
1047
1048        if (obj == null) {
1049            throw new IllegalArgumentException JavaDoc("cannot set null focus traversal key");
1050        }
1051
1052        // Generates a ClassCastException if the element is not an
1053
// AWTKeyStroke. This is desirable.
1054
AWTKeyStroke JavaDoc keystroke = (AWTKeyStroke JavaDoc)obj;
1055
1056        if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1057            throw new IllegalArgumentException JavaDoc("focus traversal keys cannot map to KEY_TYPED events");
1058        }
1059        
1060        // Check to see if key already maps to another traversal
1061
// operation
1062
for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
1063            if (i == id) {
1064            continue;
1065            }
1066
1067            if (defaultFocusTraversalKeys[i].contains(keystroke)) {
1068            throw new IllegalArgumentException JavaDoc("focus traversal keys must be unique for a Component");
1069            }
1070        }
1071        }
1072
1073        oldKeys = defaultFocusTraversalKeys[id];
1074        defaultFocusTraversalKeys[id] =
1075        Collections.unmodifiableSet(new HashSet JavaDoc(keystrokes));
1076    }
1077
1078        firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
1079                           oldKeys, keystrokes);
1080    }
1081
1082    /**
1083     * Returns a Set of default focus traversal keys for a given traversal
1084     * operation. This traversal key Set will be in effect on all Windows that
1085     * have no such Set of their own explicitly defined. This Set will also be
1086     * inherited, recursively, by any child Component of those Windows that has
1087     * no such Set of its own explicitly defined. (See
1088     * <code>setDefaultFocusTraversalKeys</code> for a full description of each
1089     * operation.)
1090     *
1091     * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1092     * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1093     * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1094     * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1095     * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
1096     * for the specified operation; the <code>Set</code>
1097     * will be unmodifiable, and may be empty; <code>null</code>
1098     * will never be returned
1099     * @see #setDefaultFocusTraversalKeys
1100     * @see Component#setFocusTraversalKeys
1101     * @see Component#getFocusTraversalKeys
1102     * @throws IllegalArgumentException if id is not one of
1103     * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1104     * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1105     * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1106     * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1107     */

1108    public Set JavaDoc<AWTKeyStroke JavaDoc> getDefaultFocusTraversalKeys(int id) {
1109        if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1110            throw new IllegalArgumentException JavaDoc("invalid focus traversal key identifier");
1111        }
1112            
1113    // Okay to return Set directly because it is an unmodifiable view
1114
return defaultFocusTraversalKeys[id];
1115    }
1116
1117    /**
1118     * Returns the current focus cycle root, if the current focus cycle root is
1119     * in the same context as the calling thread. If the focus owner is itself
1120     * a focus cycle root, then it may be ambiguous as to which Components
1121     * represent the next and previous Components to focus during normal focus
1122     * traversal. In that case, the current focus cycle root is used to
1123     * differentiate among the possibilities.
1124     * <p>
1125     * This method is intended to be used only by KeyboardFocusManagers and
1126     * focus implementations. It is not for general client use.
1127     *
1128     * @return the current focus cycle root, or null if the current focus cycle
1129     * root is not a member of the calling thread's context
1130     * @see #getGlobalCurrentFocusCycleRoot
1131     * @see #setGlobalCurrentFocusCycleRoot
1132     */

1133    public Container JavaDoc getCurrentFocusCycleRoot() {
1134        synchronized (KeyboardFocusManager JavaDoc.class) {
1135        if (currentFocusCycleRoot == null) {
1136            return null;
1137        }
1138
1139        return (currentFocusCycleRoot.appContext ==
1140            AppContext.getAppContext())
1141            ? currentFocusCycleRoot
1142            : null;
1143    }
1144    }
1145
1146    /**
1147     * Returns the current focus cycle root, even if the calling thread is in a
1148     * different context than the current focus cycle root. If the focus owner
1149     * is itself a focus cycle root, then it may be ambiguous as to which
1150     * Components represent the next and previous Components to focus during
1151     * normal focus traversal. In that case, the current focus cycle root is
1152     * used to differentiate among the possibilities.
1153     * <p>
1154     * This method will throw a SecurityException if this KeyboardFocusManager
1155     * is not the current KeyboardFocusManager for the calling thread's
1156     * context.
1157     *
1158     * @return the current focus cycle root, or null if the current focus cycle
1159     * root is not a member of the calling thread's context
1160     * @see #getCurrentFocusCycleRoot
1161     * @see #setGlobalCurrentFocusCycleRoot
1162     * @throws SecurityException if this KeyboardFocusManager is not the
1163     * current KeyboardFocusManager for the calling thread's context
1164     */

1165    protected Container JavaDoc getGlobalCurrentFocusCycleRoot()
1166        throws SecurityException JavaDoc
1167    {
1168        synchronized (KeyboardFocusManager JavaDoc.class) {
1169        if (this == getCurrentKeyboardFocusManager()) {
1170            return currentFocusCycleRoot;
1171        } else {
1172                if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
1173            throw new SecurityException JavaDoc(notPrivileged);
1174        }
1175    }
1176    }
1177
1178    /**
1179     * Sets the current focus cycle root. If the focus owner is itself a focus
1180     * cycle root, then it may be ambiguous as to which Components represent
1181     * the next and previous Components to focus during normal focus traversal.
1182     * In that case, the current focus cycle root is used to differentiate
1183     * among the possibilities.
1184     * <p>
1185     * This method is intended to be used only by KeyboardFocusManagers and
1186     * focus implementations. It is not for general client use.
1187     *
1188     * @param newFocusCycleRoot the new focus cycle root
1189     * @see #getCurrentFocusCycleRoot
1190     * @see #getGlobalCurrentFocusCycleRoot
1191     * @beaninfo
1192     * bound: true
1193     */

1194    public void setGlobalCurrentFocusCycleRoot(Container JavaDoc newFocusCycleRoot) {
1195        Container JavaDoc oldFocusCycleRoot;
1196
1197    synchronized (KeyboardFocusManager JavaDoc.class) {
1198        oldFocusCycleRoot = getCurrentFocusCycleRoot();
1199        currentFocusCycleRoot = newFocusCycleRoot;
1200    }
1201
1202        firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
1203                           newFocusCycleRoot);
1204    }
1205
1206    /**
1207     * Adds a PropertyChangeListener to the listener list. The listener is
1208     * registered for all bound properties of this class, including the
1209     * following:
1210     * <ul>
1211     * <li>whether the KeyboardFocusManager is currently managing focus
1212     * for this application or applet's browser context
1213     * ("managingFocus")</li>
1214     * <li>the focus owner ("focusOwner")</li>
1215     * <li>the permanent focus owner ("permanentFocusOwner")</li>
1216     * <li>the focused Window ("focusedWindow")</li>
1217     * <li>the active Window ("activeWindow")</li>
1218     * <li>the default focus traversal policy
1219     * ("defaultFocusTraversalPolicy")</li>
1220     * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1221     * ("forwardDefaultFocusTraversalKeys")</li>
1222     * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1223     * ("backwardDefaultFocusTraversalKeys")</li>
1224     * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1225     * ("upCycleDefaultFocusTraversalKeys")</li>
1226     * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1227     * ("downCycleDefaultFocusTraversalKeys")</li>
1228     * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1229     * </ul>
1230     * If listener is null, no exception is thrown and no action is performed.
1231     *
1232     * @param listener the PropertyChangeListener to be added
1233     * @see #removePropertyChangeListener
1234     * @see #getPropertyChangeListeners
1235     * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1236     */

1237    public void addPropertyChangeListener(PropertyChangeListener listener) {
1238        if (listener != null) {
1239        synchronized (this) {
1240            if (changeSupport == null) {
1241            changeSupport = new PropertyChangeSupport(this);
1242        }
1243        changeSupport.addPropertyChangeListener(listener);
1244        }
1245    }
1246    }
1247
1248    /**
1249     * Removes a PropertyChangeListener from the listener list. This method
1250     * should be used to remove the PropertyChangeListeners that were
1251     * registered for all bound properties of this class.
1252     * <p>
1253     * If listener is null, no exception is thrown and no action is performed.
1254     *
1255     * @param listener the PropertyChangeListener to be removed
1256     * @see #addPropertyChangeListener
1257     * @see #getPropertyChangeListeners
1258     * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1259     */

1260    public void removePropertyChangeListener(PropertyChangeListener listener) {
1261        if (listener != null) {
1262        synchronized (this) {
1263            if (changeSupport != null) {
1264            changeSupport.removePropertyChangeListener(listener);
1265        }
1266        }
1267    }
1268    }
1269
1270    /**
1271     * Returns an array of all the property change listeners
1272     * registered on this keyboard focus manager.
1273     *
1274     * @return all of this keyboard focus manager's
1275     * <code>PropertyChangeListener</code>s
1276     * or an empty array if no property change
1277     * listeners are currently registered
1278     *
1279     * @see #addPropertyChangeListener
1280     * @see #removePropertyChangeListener
1281     * @see #getPropertyChangeListeners(java.lang.String)
1282     * @since 1.4
1283     */

1284    public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
1285        if (changeSupport == null) {
1286            changeSupport = new PropertyChangeSupport(this);
1287        }
1288        return changeSupport.getPropertyChangeListeners();
1289    }
1290
1291    /**
1292     * Adds a PropertyChangeListener to the listener list for a specific
1293     * property. The specified property may be user-defined, or one of the
1294     * following:
1295     * <ul>
1296     * <li>whether the KeyboardFocusManager is currently managing focus
1297     * for this application or applet's browser context
1298     * ("managingFocus")</li>
1299     * <li>the focus owner ("focusOwner")</li>
1300     * <li>the permanent focus owner ("permanentFocusOwner")</li>
1301     * <li>the focused Window ("focusedWindow")</li>
1302     * <li>the active Window ("activeWindow")</li>
1303     * <li>the default focus traversal policy
1304     * ("defaultFocusTraversalPolicy")</li>
1305     * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1306     * ("forwardDefaultFocusTraversalKeys")</li>
1307     * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1308     * ("backwardDefaultFocusTraversalKeys")</li>
1309     * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1310     * ("upCycleDefaultFocusTraversalKeys")</li>
1311     * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1312     * ("downCycleDefaultFocusTraversalKeys")</li>
1313     * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1314     * </ul>
1315     * If listener is null, no exception is thrown and no action is performed.
1316     *
1317     * @param propertyName one of the property names listed above
1318     * @param listener the PropertyChangeListener to be added
1319     * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
1320     * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1321     * @see #getPropertyChangeListeners(java.lang.String)
1322     */

1323    public void addPropertyChangeListener(String JavaDoc propertyName,
1324                      PropertyChangeListener listener) {
1325        if (listener != null) {
1326        synchronized (this) {
1327            if (changeSupport == null) {
1328            changeSupport = new PropertyChangeSupport(this);
1329        }
1330        changeSupport.addPropertyChangeListener(propertyName,
1331                            listener);
1332        }
1333    }
1334    }
1335
1336    /**
1337     * Removes a PropertyChangeListener from the listener list for a specific
1338     * property. This method should be used to remove PropertyChangeListeners
1339     * that were registered for a specific bound property.
1340     * <p>
1341     * If listener is null, no exception is thrown and no action is performed.
1342     *
1343     * @param propertyName a valid property name
1344     * @param listener the PropertyChangeListener to be removed
1345     * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1346     * @see #getPropertyChangeListeners(java.lang.String)
1347     * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
1348     */

1349    public void removePropertyChangeListener(String JavaDoc propertyName,
1350                         PropertyChangeListener listener) {
1351        if (listener != null) {
1352        synchronized (this) {
1353            if (changeSupport != null) {
1354            changeSupport.removePropertyChangeListener(propertyName,
1355                                   listener);
1356        }
1357        }
1358    }
1359    }
1360
1361    /**
1362     * Returns an array of all the <code>PropertyChangeListener</code>s
1363     * associated with the named property.
1364     *
1365     * @return all of the <code>PropertyChangeListener</code>s associated with
1366     * the named property or an empty array if no such listeners have
1367     * been added.
1368     *
1369     * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1370     * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1371     * @since 1.4
1372     */

1373    public synchronized PropertyChangeListener[] getPropertyChangeListeners(String JavaDoc propertyName) {
1374        if (changeSupport == null) {
1375            changeSupport = new PropertyChangeSupport(this);
1376        }
1377        return changeSupport.getPropertyChangeListeners(propertyName);
1378    }
1379
1380    /**
1381     * Fires a PropertyChangeEvent in response to a change in a bound property.
1382     * The event will be delivered to all registered PropertyChangeListeners.
1383     * No event will be delivered if oldValue and newValue are the same.
1384     *
1385     * @param propertyName the name of the property that has changed
1386     * @param oldValue the property's previous value
1387     * @param newValue the property's new value
1388     */

1389    protected void firePropertyChange(String JavaDoc propertyName, Object JavaDoc oldValue,
1390                                      Object JavaDoc newValue) {
1391        PropertyChangeSupport changeSupport = this.changeSupport;
1392        if (changeSupport != null) {
1393        changeSupport.firePropertyChange(propertyName, oldValue, newValue);
1394    }
1395    }
1396
1397    /**
1398     * Adds a VetoableChangeListener to the listener list. The listener is
1399     * registered for all vetoable properties of this class, including the
1400     * following:
1401     * <ul>
1402     * <li>the focus owner ("focusOwner")</li>
1403     * <li>the permanent focus owner ("permanentFocusOwner")</li>
1404     * <li>the focused Window ("focusedWindow")</li>
1405     * <li>the active Window ("activeWindow")</li>
1406     * </ul>
1407     * If listener is null, no exception is thrown and no action is performed.
1408     *
1409     * @param listener the VetoableChangeListener to be added
1410     * @see #removeVetoableChangeListener
1411     * @see #getVetoableChangeListeners
1412     * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1413     */

1414    public void addVetoableChangeListener(VetoableChangeListener listener) {
1415        if (listener != null) {
1416        synchronized (this) {
1417            if (vetoableSupport == null) {
1418            vetoableSupport =
1419            new VetoableChangeSupport(this);
1420        }
1421        vetoableSupport.addVetoableChangeListener(listener);
1422        }
1423    }
1424    }
1425
1426    /**
1427     * Removes a VetoableChangeListener from the listener list. This method
1428     * should be used to remove the VetoableChangeListeners that were
1429     * registered for all vetoable properties of this class.
1430     * <p>
1431     * If listener is null, no exception is thrown and no action is performed.
1432     *
1433     * @param listener the VetoableChangeListener to be removed
1434     * @see #addVetoableChangeListener
1435     * @see #getVetoableChangeListeners
1436     * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1437     */

1438    public void removeVetoableChangeListener(VetoableChangeListener listener) {
1439        if (listener != null) {
1440        synchronized (this) {
1441            if (vetoableSupport != null) {
1442            vetoableSupport.removeVetoableChangeListener(listener);
1443        }
1444        }
1445    }
1446    }
1447
1448    /**
1449     * Returns an array of all the vetoable change listeners
1450     * registered on this keyboard focus manager.
1451     *
1452     * @return all of this keyboard focus manager's
1453     * <code>VetoableChangeListener</code>s
1454     * or an empty array if no vetoable change
1455     * listeners are currently registered
1456     *
1457     * @see #addVetoableChangeListener
1458     * @see #removeVetoableChangeListener
1459     * @see #getVetoableChangeListeners(java.lang.String)
1460     * @since 1.4
1461     */

1462    public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
1463        if (vetoableSupport == null) {
1464            vetoableSupport = new VetoableChangeSupport(this);
1465        }
1466        return vetoableSupport.getVetoableChangeListeners();
1467    }
1468
1469    /**
1470     * Adds a VetoableChangeListener to the listener list for a specific
1471     * property. The specified property may be user-defined, or one of the
1472     * following:
1473     * <ul>
1474     * <li>the focus owner ("focusOwner")</li>
1475     * <li>the permanent focus owner ("permanentFocusOwner")</li>
1476     * <li>the focused Window ("focusedWindow")</li>
1477     * <li>the active Window ("activeWindow")</li>
1478     * </ul>
1479     * If listener is null, no exception is thrown and no action is performed.
1480     *
1481     * @param propertyName one of the property names listed above
1482     * @param listener the VetoableChangeListener to be added
1483     * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
1484     * @see #removeVetoableChangeListener
1485     * @see #getVetoableChangeListeners
1486     */

1487    public void addVetoableChangeListener(String JavaDoc propertyName,
1488                      VetoableChangeListener listener) {
1489        if (listener != null) {
1490        synchronized (this) {
1491            if (vetoableSupport == null) {
1492            vetoableSupport =
1493            new VetoableChangeSupport(this);
1494        }
1495        vetoableSupport.addVetoableChangeListener(propertyName,
1496                              listener);
1497        }
1498    }
1499    }
1500
1501    /**
1502     * Removes a VetoableChangeListener from the listener list for a specific
1503     * property. This method should be used to remove VetoableChangeListeners
1504     * that were registered for a specific bound property.
1505     * <p>
1506     * If listener is null, no exception is thrown and no action is performed.
1507     *
1508     * @param propertyName a valid property name
1509     * @param listener the VetoableChangeListener to be removed
1510     * @see #addVetoableChangeListener
1511     * @see #getVetoableChangeListeners
1512     * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
1513     */

1514    public void removeVetoableChangeListener(String JavaDoc propertyName,
1515                         VetoableChangeListener listener) {
1516        if (listener != null) {
1517        synchronized (this) {
1518            if (vetoableSupport != null) {
1519            vetoableSupport.removeVetoableChangeListener(propertyName,
1520                                 listener);
1521        }
1522        }
1523    }
1524    }
1525
1526    /**
1527     * Returns an array of all the <code>VetoableChangeListener</code>s
1528     * associated with the named property.
1529     *
1530     * @return all of the <code>VetoableChangeListener</code>s associated with
1531     * the named property or an empty array if no such listeners have
1532     * been added.
1533     *
1534     * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1535     * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1536     * @see #getVetoableChangeListeners
1537     * @since 1.4
1538     */

1539    public synchronized VetoableChangeListener[] getVetoableChangeListeners(String JavaDoc propertyName) {
1540        if (vetoableSupport == null) {
1541            vetoableSupport = new VetoableChangeSupport(this);
1542        }
1543        return vetoableSupport.getVetoableChangeListeners(propertyName);
1544    }
1545
1546    /**
1547     * Fires a PropertyChangeEvent in response to a change in a vetoable
1548     * property. The event will be delivered to all registered
1549     * VetoableChangeListeners. If a VetoableChangeListener throws a
1550     * PropertyVetoException, a new event is fired reverting all
1551     * VetoableChangeListeners to the old value and the exception is then
1552     * rethrown. No event will be delivered if oldValue and newValue are the
1553     * same.
1554     *
1555     * @param propertyName the name of the property that has changed
1556     * @param oldValue the property's previous value
1557     * @param newValue the property's new value
1558     * @throws java.beans.PropertyVetoException if a
1559     * <code>VetoableChangeListener</code> threw
1560     * <code>PropertyVetoException</code>
1561     */

1562    protected void fireVetoableChange(String JavaDoc propertyName, Object JavaDoc oldValue,
1563                                      Object JavaDoc newValue)
1564    throws PropertyVetoException
1565    {
1566        VetoableChangeSupport vetoableSupport =
1567        this.vetoableSupport;
1568        if (vetoableSupport != null) {
1569        vetoableSupport.fireVetoableChange(propertyName, oldValue,
1570                           newValue);
1571    }
1572    }
1573
1574    /**
1575     * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
1576     * chain. This KeyboardFocusManager will request that each
1577     * KeyEventDispatcher dispatch KeyEvents generated by the user before
1578     * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
1579     * notified in the order in which they were added. Notifications will halt
1580     * as soon as one KeyEventDispatcher returns <code>true</code> from its
1581     * <code>dispatchKeyEvent</code> method. There is no limit to the total
1582     * number of KeyEventDispatchers which can be added, nor to the number of
1583     * times which a particular KeyEventDispatcher instance can be added.
1584     * <p>
1585     * If a null dispatcher is specified, no action is taken and no exception
1586     * is thrown.
1587     *
1588     * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
1589     * @see #removeKeyEventDispatcher
1590     */

1591    public void addKeyEventDispatcher(KeyEventDispatcher JavaDoc dispatcher) {
1592        if (dispatcher != null) {
1593        synchronized (this) {
1594            if (keyEventDispatchers == null) {
1595            keyEventDispatchers = new java.util.LinkedList JavaDoc();
1596        }
1597        keyEventDispatchers.add(dispatcher);
1598        }
1599    }
1600    }
1601
1602    /**
1603     * Removes a KeyEventDispatcher which was previously added to this
1604     * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
1605     * cannot itself be removed, unless it was explicitly re-registered via a
1606     * call to <code>addKeyEventDispatcher</code>.
1607     * <p>
1608     * If a null dispatcher is specified, if the specified dispatcher is not
1609     * in the dispatcher chain, or if this KeyboardFocusManager is specified
1610     * without having been explicitly re-registered, no action is taken and no
1611     * exception is thrown.
1612     *
1613     * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
1614     * chain
1615     * @see #addKeyEventDispatcher
1616     */

1617    public void removeKeyEventDispatcher(KeyEventDispatcher JavaDoc dispatcher) {
1618        if (dispatcher != null) {
1619        synchronized (this) {
1620            if (keyEventDispatchers != null) {
1621            keyEventDispatchers.remove(dispatcher);
1622        }
1623        }
1624    }
1625    }
1626
1627    /**
1628     * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
1629     * The List will not include this KeyboardFocusManager unless it was
1630     * explicitly re-registered via a call to
1631     * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
1632     * registered, implementations are free to return null or a List of length
1633     * 0. Client code should not assume one behavior over another, nor should
1634     * it assume that the behavior, once established, will not change.
1635     *
1636     * @return a possibly null or empty List of KeyEventDispatchers
1637     * @see #addKeyEventDispatcher
1638     * @see #removeKeyEventDispatcher
1639     */

1640    protected synchronized java.util.List JavaDoc<KeyEventDispatcher JavaDoc>
1641    getKeyEventDispatchers()
1642    {
1643        return (keyEventDispatchers != null)
1644        ? (java.util.List JavaDoc)keyEventDispatchers.clone()
1645        : null;
1646    }
1647
1648    /**
1649     * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
1650     * processor chain. After a KeyEvent has been dispatched to and handled by
1651     * its target, KeyboardFocusManager will request that each
1652     * KeyEventPostProcessor perform any necessary post-processing as part
1653     * of the KeyEvent's final resolution. KeyEventPostProcessors
1654     * will be notified in the order in which they were added; the current
1655     * KeyboardFocusManager will be notified last. Notifications will halt
1656     * as soon as one KeyEventPostProcessor returns <code>true</code> from its
1657     * <code>postProcessKeyEvent</code> method. There is no limit to the the
1658     * total number of KeyEventPostProcessors that can be added, nor to the
1659     * number of times that a particular KeyEventPostProcessor instance can be
1660     * added.
1661     * <p>
1662     * If a null post-processor is specified, no action is taken and no
1663     * exception is thrown.
1664     *
1665     * @param processor the KeyEventPostProcessor to add to the post-processor
1666     * chain
1667     * @see #removeKeyEventPostProcessor
1668     */

1669    public void addKeyEventPostProcessor(KeyEventPostProcessor JavaDoc processor) {
1670        if (processor != null) {
1671            synchronized (this) {
1672                if (keyEventPostProcessors == null) {
1673                    keyEventPostProcessors = new java.util.LinkedList JavaDoc();
1674                }
1675                keyEventPostProcessors.add(processor);
1676            }
1677        }
1678    }
1679
1680
1681    /**
1682     * Removes a previously added KeyEventPostProcessor from this
1683     * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
1684     * cannot itself be entirely removed from the chain. Only additional
1685     * references added via <code>addKeyEventPostProcessor</code> can be
1686     * removed.
1687     * <p>
1688     * If a null post-processor is specified, if the specified post-processor
1689     * is not in the post-processor chain, or if this KeyboardFocusManager is
1690     * specified without having been explicitly added, no action is taken and
1691     * no exception is thrown.
1692     *
1693     * @param processor the KeyEventPostProcessor to remove from the post-
1694     * processor chain
1695     * @see #addKeyEventPostProcessor
1696     */

1697    public void removeKeyEventPostProcessor(KeyEventPostProcessor JavaDoc processor) {
1698        if (processor != null) {
1699            synchronized (this) {
1700                if (keyEventPostProcessors != null) {
1701                    keyEventPostProcessors.remove(processor);
1702                }
1703            }
1704        }
1705    }
1706
1707
1708    /**
1709     * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
1710     * List. The List will not include this KeyboardFocusManager unless it was
1711     * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
1712     * no KeyEventPostProcessors are registered, implementations are free to
1713     * return null or a List of length 0. Client code should not assume one
1714     * behavior over another, nor should it assume that the behavior, once
1715     * established, will not change.
1716     *
1717     * @return a possibly null or empty List of KeyEventPostProcessors
1718     * @see #addKeyEventPostProcessor
1719     * @see #removeKeyEventPostProcessor
1720     */

1721    protected java.util.List JavaDoc<KeyEventPostProcessor JavaDoc>
1722    getKeyEventPostProcessors()
1723    {
1724        return (keyEventPostProcessors != null)
1725            ? (java.util.List JavaDoc)keyEventPostProcessors.clone()
1726            : null;
1727    }
1728
1729
1730
1731    static void setMostRecentFocusOwner(Component JavaDoc component) {
1732        Component JavaDoc window = component;
1733    while (window != null && !(window instanceof Window JavaDoc)) {
1734        window = window.parent;
1735    }
1736    if (window != null) {
1737        setMostRecentFocusOwner((Window JavaDoc)window, component);
1738    }
1739    }
1740    static synchronized void setMostRecentFocusOwner(Window JavaDoc window,
1741                                                     Component JavaDoc component) {
1742        // ATTN: component has a strong reference to window via chain
1743
// of Component.parent fields. Since WeakHasMap refers to its
1744
// values strongly, we need to break the strong link from the
1745
// value (component) back to its key (window).
1746
WeakReference JavaDoc weakValue = null;
1747        if (component != null) {
1748            weakValue = new WeakReference JavaDoc(component);
1749        }
1750        mostRecentFocusOwners.put(window, weakValue);
1751    }
1752    static void clearMostRecentFocusOwner(Component JavaDoc comp) {
1753        Container JavaDoc window;
1754
1755        if (comp == null) {
1756            return;
1757        }
1758
1759        synchronized (comp.getTreeLock()) {
1760            window = comp.getParent();
1761            while (window != null && !(window instanceof Window JavaDoc)) {
1762                window = window.getParent();
1763            }
1764        }
1765
1766        synchronized (KeyboardFocusManager JavaDoc.class) {
1767            if ((window != null)
1768                && (getMostRecentFocusOwner((Window JavaDoc)window) == comp))
1769            {
1770                setMostRecentFocusOwner((Window JavaDoc)window, null);
1771            }
1772            // Also clear temporary lost component stored in Window
1773
if (window != null) {
1774                Window JavaDoc realWindow = (Window JavaDoc)window;
1775                if (realWindow.getTemporaryLostComponent() == comp) {
1776                    realWindow.setTemporaryLostComponent(null);
1777                }
1778            }
1779        }
1780    }
1781    static synchronized Component JavaDoc getMostRecentFocusOwner(Window JavaDoc window) {
1782        WeakReference JavaDoc weakValue =
1783            (WeakReference JavaDoc)mostRecentFocusOwners.get(window);
1784        return weakValue == null ? null : (Component JavaDoc)weakValue.get();
1785    }
1786
1787    /**
1788     * This method is called by the AWT event dispatcher requesting that the
1789     * current KeyboardFocusManager dispatch the specified event on its behalf.
1790     * It is expected that all KeyboardFocusManagers will dispatch all
1791     * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
1792     * These events should be dispatched based on the KeyboardFocusManager's
1793     * notion of the focus owner and the focused and active Windows, sometimes
1794     * overriding the source of the specified AWTEvent. Dispatching must be
1795     * done using <code>redispatchEvent</code> to prevent the AWT event
1796     * dispatcher from recursively requesting that the KeyboardFocusManager
1797     * dispatch the event again. If this method returns <code>false</code>,
1798     * then the AWT event dispatcher will attempt to dispatch the event itself.
1799     *
1800     * @param e the AWTEvent to be dispatched
1801     * @return <code>true</code> if this method dispatched the event;
1802     * <code>false</code> otherwise
1803     * @see #redispatchEvent
1804     * @see #dispatchKeyEvent
1805     */

1806    public abstract boolean dispatchEvent(AWTEvent JavaDoc e);
1807
1808    /**
1809     * Redispatches an AWTEvent in such a way that the AWT event dispatcher
1810     * will not recursively request that the KeyboardFocusManager, or any
1811     * installed KeyEventDispatchers, dispatch the event again. Client
1812     * implementations of <code>dispatchEvent</code> and client-defined
1813     * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
1814     * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
1815     * <p>
1816     * This method is intended to be used only by KeyboardFocusManagers and
1817     * KeyEventDispatchers. It is not for general client use.
1818     *
1819     * @param target the Component to which the event should be dispatched
1820     * @param e the event to dispatch
1821     * @see #dispatchEvent
1822     * @see KeyEventDispatcher
1823     */

1824    public final void redispatchEvent(Component JavaDoc target, AWTEvent JavaDoc e) {
1825        e.focusManagerIsDispatching = true;
1826    target.dispatchEvent(e);
1827        e.focusManagerIsDispatching = false;
1828    }
1829
1830    /**
1831     * Typically this method will be called by <code>dispatchEvent</code> if no
1832     * other KeyEventDispatcher in the dispatcher chain dispatched the
1833     * KeyEvent, or if no other KeyEventDispatchers are registered. If an
1834     * implementation of this method returns <code>false</code>,
1835     * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
1836     * may simply return <code>false</code>. If <code>true</code> is returned,
1837     * <code>dispatchEvent</code> should return <code>true</code> as well.
1838     *
1839     * @param e the KeyEvent which the current KeyboardFocusManager has
1840     * requested that this KeyEventDispatcher dispatch
1841     * @return <code>true</code> if the KeyEvent was dispatched;
1842     * <code>false</code> otherwise
1843     * @see #dispatchEvent
1844     */

1845    public abstract boolean dispatchKeyEvent(KeyEvent JavaDoc e);
1846
1847    /**
1848     * This method will be called by <code>dispatchKeyEvent</code>.
1849     * By default, this method will handle any unconsumed KeyEvents that
1850     * map to an AWT <code>MenuShortcut</code> by consuming the event
1851     * and activating the shortcut.
1852     *
1853     * @param e the KeyEvent to post-process
1854     * @return <code>true</code> to indicate that no other
1855     * KeyEventPostProcessor will be notified of the KeyEvent.
1856     * @see #dispatchKeyEvent
1857     * @see MenuShortcut
1858     */

1859    public abstract boolean postProcessKeyEvent(KeyEvent JavaDoc e);
1860
1861    /**
1862     * This method initiates a focus traversal operation if and only if the
1863     * KeyEvent represents a focus traversal key for the specified
1864     * focusedComponent. It is expected that focusedComponent is the current
1865     * focus owner, although this need not be the case. If it is not,
1866     * focus traversal will nevertheless proceed as if focusedComponent
1867     * were the current focus owner.
1868     *
1869     * @param focusedComponent the Component that will be the basis for a focus
1870     * traversal operation if the specified event represents a focus
1871     * traversal key for the Component
1872     * @param e the event that may represent a focus traversal key
1873     */

1874    public abstract void processKeyEvent(Component JavaDoc focusedComponent,
1875                                         KeyEvent JavaDoc e);
1876
1877    /**
1878     * Called by the AWT to notify the KeyboardFocusManager that it should
1879     * delay dispatching of KeyEvents until the specified Component becomes
1880     * the focus owner. If client code requests a focus change, and the AWT
1881     * determines that this request might be granted by the native windowing
1882     * system, then the AWT will call this method. It is the responsibility of
1883     * the KeyboardFocusManager to delay dispatching of KeyEvents with
1884     * timestamps later than the specified time stamp until the specified
1885     * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
1886     * request by invoking <code>dequeueKeyEvents</code> or
1887     * <code>discardKeyEvents</code>.
1888     *
1889     * @param after timestamp of current event, or the current, system time if
1890     * the current event has no timestamp, or the AWT cannot determine
1891     * which event is currently being handled
1892     * @param untilFocused Component which should receive a FOCUS_GAINED event
1893     * before any pending KeyEvents
1894     * @see #dequeueKeyEvents
1895     * @see #discardKeyEvents
1896     */

1897    protected abstract void enqueueKeyEvents(long after,
1898                         Component JavaDoc untilFocused);
1899 
1900    /**
1901     * Called by the AWT to notify the KeyboardFocusManager that it should
1902     * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1903     * enqueued because of a call to <code>enqueueKeyEvents</code> with the
1904     * same timestamp and Component should be released for normal dispatching
1905     * to the current focus owner. If the given timestamp is less than zero,
1906     * the outstanding enqueue request for the given Component with the <b>
1907     * oldest</b> timestamp (if any) should be cancelled.
1908     *
1909     * @param after the timestamp specified in the call to
1910     * <code>enqueueKeyEvents</code>, or any value < 0
1911     * @param untilFocused the Component specified in the call to
1912     * <code>enqueueKeyEvents</code>
1913     * @see #enqueueKeyEvents
1914     * @see #discardKeyEvents
1915     */

1916    protected abstract void dequeueKeyEvents(long after,
1917                         Component JavaDoc untilFocused);
1918
1919    /**
1920     * Called by the AWT to notify the KeyboardFocusManager that it should
1921     * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1922     * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
1923     * with the same Component should be discarded.
1924     *
1925     * @param comp the Component specified in one or more calls to
1926     * <code>enqueueKeyEvents</code>
1927     * @see #enqueueKeyEvents
1928     * @see #dequeueKeyEvents
1929     */

1930    protected abstract void discardKeyEvents(Component JavaDoc comp);
1931
1932    /**
1933     * Focuses the Component after aComponent, typically based on a
1934     * FocusTraversalPolicy.
1935     *
1936     * @param aComponent the Component that is the basis for the focus
1937     * traversal operation
1938     * @see FocusTraversalPolicy
1939     */

1940    public abstract void focusNextComponent(Component JavaDoc aComponent);
1941
1942    /**
1943     * Focuses the Component before aComponent, typically based on a
1944     * FocusTraversalPolicy.
1945     *
1946     * @param aComponent the Component that is the basis for the focus
1947     * traversal operation
1948     * @see FocusTraversalPolicy
1949     */

1950    public abstract void focusPreviousComponent(Component JavaDoc aComponent);
1951
1952    /**
1953     * Moves the focus up one focus traversal cycle. Typically, the focus owner
1954     * is set to aComponent's focus cycle root, and the current focus cycle
1955     * root is set to the new focus owner's focus cycle root. If, however,
1956     * aComponent's focus cycle root is a Window, then typically the focus
1957     * owner is set to the Window's default Component to focus, and the current
1958     * focus cycle root is unchanged.
1959     *
1960     * @param aComponent the Component that is the basis for the focus
1961     * traversal operation
1962     */

1963    public abstract void upFocusCycle(Component JavaDoc aComponent);
1964
1965    /**
1966     * Moves the focus down one focus traversal cycle. Typically, if
1967     * aContainer is a focus cycle root, then the focus owner is set to
1968     * aContainer's default Component to focus, and the current focus cycle
1969     * root is set to aContainer. If aContainer is not a focus cycle root, then
1970     * no focus traversal operation occurs.
1971     *
1972     * @param aContainer the Container that is the basis for the focus
1973     * traversal operation
1974     */

1975    public abstract void downFocusCycle(Container JavaDoc aContainer);
1976
1977    /**
1978     * Focuses the Component after the current focus owner.
1979     */

1980    public final void focusNextComponent() {
1981        Component JavaDoc focusOwner = getFocusOwner();
1982        if (focusOwner != null) {
1983            focusNextComponent(focusOwner);
1984        }
1985    }
1986
1987    /**
1988     * Focuses the Component before the current focus owner.
1989     */

1990    public final void focusPreviousComponent() {
1991        Component JavaDoc focusOwner = getFocusOwner();
1992        if (focusOwner != null) {
1993            focusPreviousComponent(focusOwner);
1994        }
1995    }
1996
1997    /**
1998     * Moves the focus up one focus traversal cycle from the current focus
1999     * owner. Typically, the new focus owner is set to the current focus
2000     * owner's focus cycle root, and the current focus cycle root is set to the
2001     * new focus owner's focus cycle root. If, however, the current focus
2002     * owner's focus cycle root is a Window, then typically the focus owner is
2003     * set to the focus cycle root's default Component to focus, and the
2004     * current focus cycle root is unchanged.
2005     */

2006    public final void upFocusCycle() {
2007        Component JavaDoc focusOwner = getFocusOwner();
2008        if (focusOwner != null) {
2009            upFocusCycle(focusOwner);
2010        }
2011    }
2012
2013    /**
2014     * Moves the focus down one focus traversal cycle from the current focus
2015     * owner, if and only if the current focus owner is a Container that is a
2016     * focus cycle root. Typically, the focus owner is set to the current focus
2017     * owner's default Component to focus, and the current focus cycle root is
2018     * set to the current focus owner. If the current focus owner is not a
2019     * Container that is a focus cycle root, then no focus traversal operation
2020     * occurs.
2021     */

2022    public final void downFocusCycle() {
2023        Component JavaDoc focusOwner = getFocusOwner();
2024    if (focusOwner instanceof Container JavaDoc) {
2025        downFocusCycle((Container JavaDoc)focusOwner);
2026    }
2027    }
2028
2029    /**
2030     * Dumps the list of focus requests to stderr
2031     */

2032    void dumpRequests() {
2033        System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2034        synchronized (heavyweightRequests) {
2035            Iterator JavaDoc iter = heavyweightRequests.iterator();
2036            while (iter.hasNext()) {
2037                HeavyweightFocusRequest req = (HeavyweightFocusRequest)iter.next();
2038                System.err.println(">>> Req: " + req);
2039            }
2040        }
2041        System.err.println("");
2042    }
2043
2044    private static final class LightweightFocusRequest {
2045        final Component JavaDoc component;
2046        final boolean temporary;
2047
2048        LightweightFocusRequest(Component JavaDoc component, boolean temporary) {
2049            this.component = component;
2050            this.temporary = temporary;
2051        }
2052        public String JavaDoc toString() {
2053            return "LightweightFocusRequest[component=" + component +
2054                ",temporary=" + temporary + "]";
2055        }
2056    }
2057
2058    private static final class HeavyweightFocusRequest {
2059        final Component JavaDoc heavyweight;
2060        final LinkedList JavaDoc lightweightRequests;
2061
2062        static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2063            new HeavyweightFocusRequest();
2064
2065        private HeavyweightFocusRequest() {
2066            heavyweight = null;
2067            lightweightRequests = null;
2068        }
2069
2070        HeavyweightFocusRequest(Component JavaDoc heavyweight, Component JavaDoc descendant,
2071                                boolean temporary) {
2072            if (dbg.on) {
2073                dbg.assertion(heavyweight != null);
2074            }
2075
2076            this.heavyweight = heavyweight;
2077            this.lightweightRequests = new LinkedList JavaDoc();
2078            addLightweightRequest(descendant, temporary);
2079        }
2080        boolean addLightweightRequest(Component JavaDoc descendant,
2081                                      boolean temporary) {
2082            if (dbg.on) {
2083                dbg.assertion(this != HeavyweightFocusRequest.
2084                              CLEAR_GLOBAL_FOCUS_OWNER);
2085                dbg.assertion(descendant != null);
2086            }
2087
2088            Component JavaDoc lastDescendant = ((lightweightRequests.size() > 0)
2089                ? ((LightweightFocusRequest)lightweightRequests.getLast()).
2090                  component
2091                : null);
2092
2093            if (descendant != lastDescendant) {
2094                // Not a duplicate request
2095
lightweightRequests.add
2096                    (new LightweightFocusRequest(descendant, temporary));
2097                return true;
2098            } else {
2099                return false;
2100            }
2101        }
2102
2103        LightweightFocusRequest getFirstLightweightRequest() {
2104            if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
2105                return null;
2106            }
2107            return (LightweightFocusRequest)lightweightRequests.getFirst();
2108        }
2109        public String JavaDoc toString() {
2110            boolean first = true;
2111            String JavaDoc str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
2112                ",lightweightRequests=";
2113            if (lightweightRequests == null) {
2114                str += null;
2115            } else {
2116                str += "[";
2117                for (Iterator JavaDoc iter = lightweightRequests.iterator();
2118                     iter.hasNext(); )
2119                {
2120                    if (first) {
2121                        first = false;
2122                    } else {
2123                        str += ",";
2124                    }
2125                    str += iter.next();
2126                }
2127                str += "]";
2128            }
2129            str += "]";
2130            return str;
2131        }
2132    }
2133
2134    /*
2135     * heavyweightRequests is used as a monitor for synchronized changes of
2136     * currentLightweightRequests, clearingCurrentLightweightRequests and
2137     * newFocusOwner.
2138     */

2139    private static LinkedList JavaDoc heavyweightRequests = new LinkedList JavaDoc();
2140    private static LinkedList JavaDoc currentLightweightRequests;
2141    private static boolean clearingCurrentLightweightRequests;
2142    private static boolean allowSyncFocusRequests = true;
2143    private static Component JavaDoc newFocusOwner = null;
2144
2145    static volatile boolean disableRestoreFocus;
2146
2147    static final int SNFH_FAILURE = 0;
2148    static final int SNFH_SUCCESS_HANDLED = 1;
2149    static final int SNFH_SUCCESS_PROCEED = 2;
2150
2151    static boolean processSynchronousLightweightTransfer(Component JavaDoc heavyweight, Component JavaDoc descendant,
2152                                                  boolean temporary, boolean focusedWindowChangeAllowed,
2153                                                  long time) {
2154        Window JavaDoc parentWindow = Component.getContainingWindow(heavyweight);
2155        if (parentWindow == null || !parentWindow.syncLWRequests) {
2156            return false;
2157        }
2158        if (descendant == null) {
2159            // Focus transfers from a lightweight child back to the
2160
// heavyweight Container should be treated like lightweight
2161
// focus transfers.
2162
descendant = heavyweight;
2163        }
2164
2165        KeyboardFocusManager JavaDoc manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2166
2167        FocusEvent JavaDoc currentFocusOwnerEvent = null;
2168        FocusEvent JavaDoc newFocusOwnerEvent = null;
2169        Component JavaDoc currentFocusOwner = manager.getGlobalFocusOwner();
2170
2171        synchronized (heavyweightRequests) {
2172            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2173                ((heavyweightRequests.size() > 0)
2174                 ? heavyweightRequests.getLast() : null);
2175            if (hwFocusRequest == null &&
2176                heavyweight == manager.getNativeFocusOwner() &&
2177                allowSyncFocusRequests)
2178            {
2179                if (descendant == currentFocusOwner) {
2180                    // Redundant request.
2181
return true;
2182                }
2183
2184                // 'heavyweight' owns the native focus and there are no pending
2185
// requests. 'heavyweight' must be a Container and
2186
// 'descendant' must not be the focus owner. Otherwise,
2187
// we would never have gotten this far.
2188
manager.enqueueKeyEvents(time, descendant);
2189
2190                hwFocusRequest =
2191                    new HeavyweightFocusRequest(heavyweight, descendant,
2192                                                temporary);
2193                heavyweightRequests.add(hwFocusRequest);
2194
2195                if (currentFocusOwner != null) {
2196                    currentFocusOwnerEvent =
2197                        new FocusEvent JavaDoc(currentFocusOwner,
2198                                       FocusEvent.FOCUS_LOST,
2199                                       temporary, descendant);
2200                }
2201                newFocusOwnerEvent =
2202                    new FocusEvent JavaDoc(descendant, FocusEvent.FOCUS_GAINED,
2203                                   temporary, currentFocusOwner);
2204            }
2205        }
2206        boolean result = false;
2207        final boolean clearing = clearingCurrentLightweightRequests;
2208
2209        Throwable JavaDoc caughtEx = null;
2210        try {
2211            clearingCurrentLightweightRequests = false;
2212            synchronized(Component.LOCK) {
2213                if (currentFocusOwnerEvent != null && currentFocusOwner != null) {
2214                    ((AWTEvent JavaDoc) currentFocusOwnerEvent).isPosted = true;
2215                    caughtEx=dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
2216                    result = true;
2217                }
2218                if (newFocusOwnerEvent != null && descendant != null) {
2219                    ((AWTEvent JavaDoc) newFocusOwnerEvent).isPosted = true;
2220                    caughtEx=dispatchAndCatchException(caughtEx, descendant, newFocusOwnerEvent);
2221                    result = true;
2222                }
2223            }
2224        } finally {
2225            clearingCurrentLightweightRequests = clearing;
2226        }
2227
2228        if (caughtEx instanceof RuntimeException JavaDoc){
2229            throw (RuntimeException JavaDoc) caughtEx;
2230        } else if (caughtEx instanceof Error JavaDoc) {
2231            throw (Error JavaDoc) caughtEx;
2232        }
2233
2234        return result;
2235    }
2236
2237    /**
2238     * Indicates whether the native implementation should proceed with a
2239     * pending, native focus request. Before changing the focus at the native
2240     * level, the AWT implementation should always call this function for
2241     * permission. This function will reject the request if a duplicate request
2242     * preceded it, or if the specified heavyweight Component already owns the
2243     * focus and no native focus changes are pending. Otherwise, the request
2244     * will be approved and the focus request list will be updated so that,
2245     * if necessary, the proper descendant will be focused when the
2246     * corresponding FOCUS_GAINED event on the heavyweight is received.
2247     *
2248     * An implementation must ensure that calls to this method and native
2249     * focus changes are atomic. If this is not guaranteed, then the ordering
2250     * of the focus request list may be incorrect, leading to errors in the
2251     * type-ahead mechanism. Typically this is accomplished by only calling
2252     * this function from the native event pumping thread, or by holding a
2253     * global, native lock during invocation.
2254     */

2255    static int shouldNativelyFocusHeavyweight
2256        (Component JavaDoc heavyweight, Component JavaDoc descendant, boolean temporary,
2257         boolean focusedWindowChangeAllowed, long time)
2258    {
2259        if (dbg.on) {
2260            dbg.assertion(heavyweight != null);
2261            dbg.assertion(time != 0);
2262        }
2263
2264        if (descendant == null) {
2265            // Focus transfers from a lightweight child back to the
2266
// heavyweight Container should be treated like lightweight
2267
// focus transfers.
2268
descendant = heavyweight;
2269        }
2270
2271        KeyboardFocusManager JavaDoc manager =
2272            getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
2273        KeyboardFocusManager JavaDoc thisManager = getCurrentKeyboardFocusManager();
2274        Component JavaDoc currentFocusOwner = thisManager.getGlobalFocusOwner();
2275        Component JavaDoc nativeFocusOwner = thisManager.getNativeFocusOwner();
2276        Window JavaDoc nativeFocusedWindow = thisManager.getNativeFocusedWindow();
2277        if (focusLog.isLoggable(Level.FINER)) {
2278            focusLog.log(Level.FINER, "SNFH for {0} in {1}",
2279                         new Object JavaDoc[] {descendant, heavyweight});
2280        }
2281        if (focusLog.isLoggable(Level.FINEST)) {
2282            focusLog.log(Level.FINEST, "0. Current focus owner {0}",
2283                         currentFocusOwner);
2284            focusLog.log(Level.FINEST, "0. Native focus owner {0}",
2285                         nativeFocusOwner);
2286            focusLog.log(Level.FINEST, "0. Native focused window {0}",
2287                         nativeFocusedWindow);
2288        }
2289        synchronized (heavyweightRequests) {
2290            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2291                ((heavyweightRequests.size() > 0)
2292                 ? heavyweightRequests.getLast() : null);
2293            if (focusLog.isLoggable(Level.FINEST)) {
2294                focusLog.log(Level.FINEST, "Request {0}", hwFocusRequest);
2295            }
2296            if (hwFocusRequest == null &&
2297                heavyweight == nativeFocusOwner)
2298            {
2299                if (descendant == currentFocusOwner) {
2300                    // Redundant request.
2301
if (focusLog.isLoggable(Level.FINEST)) {
2302                        focusLog.log(Level.FINEST, "1. SNFH_FAILURE for {0}",
2303                                     descendant);
2304                    }
2305                    return SNFH_FAILURE;
2306                }
2307
2308                // 'heavyweight' owns the native focus and there are no pending
2309
// requests. 'heavyweight' must be a Container and
2310
// 'descendant' must not be the focus owner. Otherwise,
2311
// we would never have gotten this far.
2312
manager.enqueueKeyEvents(time, descendant);
2313
2314                hwFocusRequest =
2315                    new HeavyweightFocusRequest(heavyweight, descendant,
2316                                                temporary);
2317                heavyweightRequests.add(hwFocusRequest);
2318
2319                if (currentFocusOwner != null) {
2320                    FocusEvent JavaDoc currentFocusOwnerEvent =
2321                        new FocusEvent JavaDoc(currentFocusOwner,
2322                                       FocusEvent.FOCUS_LOST,
2323                                       temporary, descendant);
2324                    SunToolkit.postEvent(currentFocusOwner.appContext,
2325                                         currentFocusOwnerEvent);
2326                }
2327                FocusEvent JavaDoc newFocusOwnerEvent =
2328                    new FocusEvent JavaDoc(descendant, FocusEvent.FOCUS_GAINED,
2329                                   temporary, currentFocusOwner);
2330                SunToolkit.postEvent(descendant.appContext,
2331                                     newFocusOwnerEvent);
2332
2333                if (focusLog.isLoggable(Level.FINEST)) {
2334                    focusLog.log(Level.FINEST, "2. SNFH_HANDLED for {0}", descendant);
2335                }
2336                return SNFH_SUCCESS_HANDLED;
2337            } else if (hwFocusRequest != null &&
2338                       hwFocusRequest.heavyweight == heavyweight) {
2339                // 'heavyweight' doesn't have the native focus right now, but
2340
// if all pending requests were completed, it would. Add
2341
// descendant to the heavyweight's list of pending
2342
// lightweight focus transfers.
2343
if (hwFocusRequest.addLightweightRequest(descendant,
2344                                                         temporary)) {
2345                    manager.enqueueKeyEvents(time, descendant);
2346                }
2347                
2348                if (focusLog.isLoggable(Level.FINEST)) {
2349                    focusLog.finest("3. SNFH_HANDLED for lightweight" +
2350                                    descendant + " in " + heavyweight);
2351                }
2352                return SNFH_SUCCESS_HANDLED;
2353            } else {
2354                if (!focusedWindowChangeAllowed) {
2355                    // For purposes of computing oldFocusedWindow, we should look at
2356
// the second to last HeavyweightFocusRequest on the queue iff the
2357
// last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If
2358
// there is no second to last HeavyweightFocusRequest, null is an
2359
// acceptable value.
2360
if (hwFocusRequest ==
2361                        HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2362                    {
2363                        int size = heavyweightRequests.size();
2364                        hwFocusRequest = (HeavyweightFocusRequest)((size >= 2)
2365                            ? heavyweightRequests.get(size - 2)
2366                            : null);
2367                    }
2368                    if (focusedWindowChanged(heavyweight,
2369                                             (hwFocusRequest != null)
2370                                             ? hwFocusRequest.heavyweight
2371                                             : nativeFocusedWindow)) {
2372                        if (focusLog.isLoggable(Level.FINEST)) {
2373                            focusLog.finest("4. SNFH_FAILURE for " + descendant);
2374                        }
2375                        return SNFH_FAILURE;
2376                    }
2377                }
2378
2379                manager.enqueueKeyEvents(time, descendant);
2380                heavyweightRequests.add
2381                    (new HeavyweightFocusRequest(heavyweight, descendant,
2382                                                 temporary));
2383                if (focusLog.isLoggable(Level.FINEST)) {
2384                    focusLog.finest("5. SNFH_PROCEED for " + descendant);
2385                }
2386                return SNFH_SUCCESS_PROCEED;
2387            }
2388        }
2389    }
2390    static void heavyweightButtonDown(Component JavaDoc heavyweight, long time) {
2391        heavyweightButtonDown(heavyweight, time, false);
2392    }
2393    static void heavyweightButtonDown(Component JavaDoc heavyweight, long time, boolean acceptDuplicates) {
2394        if (dbg.on) {
2395            dbg.assertion(heavyweight != null);
2396            dbg.assertion(time != 0);
2397        }
2398        KeyboardFocusManager JavaDoc manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(heavyweight));
2399        
2400        synchronized (heavyweightRequests) {
2401            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2402                ((heavyweightRequests.size() > 0)
2403                 ? heavyweightRequests.getLast() : null);
2404            Component JavaDoc currentNativeFocusOwner = (hwFocusRequest == null)
2405                ? manager.getNativeFocusOwner()
2406                : hwFocusRequest.heavyweight;
2407                
2408            // Behavior for all use cases:
2409
// 1. Heavyweight leaf Components (e.g., Button, Checkbox, Choice,
2410
// List, TextComponent, Canvas) that respond to button down.
2411
//
2412
// Native platform will generate a FOCUS_GAINED if and only if
2413
// the Component is not the focus owner (or, will not be the
2414
// focus owner when all outstanding focus requests are
2415
// processed).
2416
//
2417
// 2. Panel with no descendants.
2418
//
2419
// Same as (1).
2420
//
2421
// 3. Panel with at least one heavyweight descendant.
2422
//
2423
// This function should NOT be called for this case!
2424
//
2425
// 4. Panel with only lightweight descendants.
2426
//
2427
// Native platform will generate a FOCUS_GAINED if and only if
2428
// neither the Panel, nor any of its recursive, lightweight
2429
// descendants, is the focus owner. However, we want a
2430
// requestFocus() for any lightweight descendant to win out over
2431
// the focus request for the Panel. To accomplish this, we
2432
// differ from the algorithm for shouldNativelyFocusHeavyweight
2433
// as follows:
2434
// a. If the requestFocus() for a lightweight descendant has
2435
// been fully handled by the time this function is invoked,
2436
// then 'hwFocusRequest' will be null and 'heavyweight'
2437
// will be the native focus owner. Do *not* synthesize a
2438
// focus transfer to the Panel.
2439
// b. If the requestFocus() for a lightweight descendant has
2440
// been recorded, but not handled, then 'hwFocusRequest'
2441
// will be non-null and 'hwFocusRequest.heavyweight' will
2442
// equal 'heavyweight'. Do *not* append 'heavyweight' to
2443
// hwFocusRequest.lightweightRequests.
2444
// c. If the requestFocus() for a lightweight descendant is
2445
// yet to be made, then post a new HeavyweightFocusRequest.
2446
// If no lightweight descendant ever requests focus, then
2447
// the Panel will get focus. If some descendant does, then
2448
// the descendant will get focus by either a synthetic
2449
// focus transfer, or a lightweightRequests focus transfer.
2450

2451            if (acceptDuplicates || heavyweight != currentNativeFocusOwner) {
2452                getCurrentKeyboardFocusManager
2453                    (SunToolkit.targetToAppContext(heavyweight)).
2454                    enqueueKeyEvents(time, heavyweight);
2455                heavyweightRequests.add
2456                    (new HeavyweightFocusRequest(heavyweight, heavyweight,
2457                                                 false));
2458            }
2459        }
2460    }
2461    /**
2462     * Returns the Window which will be active after processing this request,
2463     * or null if this is a duplicate request. The active Window is useful
2464     * because some native platforms do not support setting the native focus
2465     * owner to null. On these platforms, the obvious choice is to set the
2466     * focus owner to the focus proxy of the active Window.
2467     */

2468    static Window JavaDoc markClearGlobalFocusOwner() {
2469        synchronized (heavyweightRequests) {
2470            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2471                ((heavyweightRequests.size() > 0)
2472                 ? heavyweightRequests.getLast() : null);
2473            if (hwFocusRequest ==
2474                HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2475            {
2476                // duplicate request
2477
return null;
2478            }
2479            
2480            KeyboardFocusManager JavaDoc manager = getCurrentKeyboardFocusManager();
2481            heavyweightRequests.add
2482                (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
2483
2484            Component JavaDoc activeWindow = ((hwFocusRequest != null)
2485                ? Component.getContainingWindow(hwFocusRequest.heavyweight)
2486                : manager.getNativeFocusedWindow());
2487            while (activeWindow != null &&
2488                   !((activeWindow instanceof Frame JavaDoc) ||
2489                     (activeWindow instanceof Dialog JavaDoc)))
2490            {
2491                activeWindow = activeWindow.getParent();
2492            }
2493
2494            return (Window JavaDoc)activeWindow;
2495        }
2496    }
2497    Component JavaDoc getCurrentWaitingRequest(Component JavaDoc parent) {
2498        synchronized (heavyweightRequests) {
2499            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2500                ((heavyweightRequests.size() > 0)
2501                 ? heavyweightRequests.getFirst() : null);
2502            if (hwFocusRequest != null) {
2503                if (hwFocusRequest.heavyweight == parent) {
2504                    LightweightFocusRequest lwFocusRequest =
2505                        (LightweightFocusRequest)hwFocusRequest.
2506                        lightweightRequests.getFirst();
2507                    if (lwFocusRequest != null) {
2508                        return lwFocusRequest.component;
2509                    }
2510                }
2511            }
2512        }
2513        return null;
2514    }
2515    
2516   /*
2517    * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
2518    * @param ex previously caught exception that may be processed right here, or null
2519    * @param comp the component to dispatch the event to
2520    * @param event the event to dispatch to the component
2521    */

2522    static private Throwable JavaDoc dispatchAndCatchException(Throwable JavaDoc ex, Component JavaDoc comp, FocusEvent JavaDoc event) {
2523       Throwable JavaDoc retEx = null;
2524       try {
2525          comp.dispatchEvent(event);
2526       } catch (RuntimeException JavaDoc re) {
2527          retEx = re;
2528       } catch (Error JavaDoc er) {
2529          retEx = er;
2530       }
2531       if (retEx != null) {
2532         if (ex != null) {
2533             handleException(ex);
2534          }
2535          return retEx;
2536        }
2537        return ex;
2538    }
2539    
2540    static private void handleException(Throwable JavaDoc ex) {
2541             ex.printStackTrace();
2542    }
2543
2544    static boolean hasFocusRequests() {
2545         synchronized (heavyweightRequests) {
2546             return heavyweightRequests.size() > 0;
2547         }
2548    }
2549
2550    static void processCurrentLightweightRequests() {
2551        KeyboardFocusManager JavaDoc manager = getCurrentKeyboardFocusManager();
2552        LinkedList JavaDoc localLightweightRequests = null;
2553
2554        Component JavaDoc globalFocusOwner = manager.getGlobalFocusOwner();
2555        if ((globalFocusOwner != null) &&
2556            (globalFocusOwner.appContext != AppContext.getAppContext()))
2557        {
2558            // The current app context differs from the app context of a focus
2559
// owner (and all pending lightweight requests), so we do nothing
2560
// now and wait for a next event.
2561
return;
2562        }
2563
2564        synchronized(heavyweightRequests) {
2565            if (currentLightweightRequests != null) {
2566                clearingCurrentLightweightRequests = true;
2567                disableRestoreFocus=true;
2568                localLightweightRequests = currentLightweightRequests;
2569                allowSyncFocusRequests = (localLightweightRequests.size() < 2);
2570                currentLightweightRequests = null;
2571            } else {
2572                // do nothing
2573
return;
2574            }
2575        }
2576
2577        Throwable JavaDoc caughtEx=null;
2578        try {
2579            if (localLightweightRequests != null) {
2580                Component JavaDoc lastFocusOwner = null;
2581                Component JavaDoc currentFocusOwner = null;
2582
2583                for (Iterator JavaDoc iter = localLightweightRequests.iterator(); iter.hasNext(); )
2584                {
2585                    currentFocusOwner = manager.getGlobalFocusOwner();
2586                    LightweightFocusRequest lwFocusRequest = (LightweightFocusRequest)iter.next();
2587                
2588                    /*
2589                     * WARNING: This is based on DKFM's logic solely!
2590                     *
2591                     * We allow to trigger restoreFocus() in the dispatching process
2592                     * only if we have the last request to dispatch. If the last request
2593                     * fails, focus will be restored to either the component of the last
2594                     * previously succedded request, or to to the focus owner that was
2595                     * before this clearing proccess.
2596                     */

2597                     if (!iter.hasNext()) {
2598                           disableRestoreFocus = false;
2599                     }
2600                     
2601                    FocusEvent JavaDoc currentFocusOwnerEvent = null;
2602                    if ( currentFocusOwner != null ){
2603                        currentFocusOwnerEvent = new FocusEvent JavaDoc(currentFocusOwner,
2604                                                                FocusEvent.FOCUS_LOST,
2605                                                                lwFocusRequest.temporary, lwFocusRequest.component);
2606                    }
2607
2608                    FocusEvent JavaDoc newFocusOwnerEvent = new FocusEvent JavaDoc(lwFocusRequest.component,
2609                                       FocusEvent.FOCUS_GAINED,
2610                                       lwFocusRequest.temporary,
2611                                       currentFocusOwner == null? lastFocusOwner : currentFocusOwner);
2612
2613                    if (currentFocusOwner != null){
2614                        ((AWTEvent JavaDoc) currentFocusOwnerEvent).isPosted = true;
2615                         caughtEx=dispatchAndCatchException(caughtEx,currentFocusOwner,currentFocusOwnerEvent);
2616                     }
2617
2618                    ((AWTEvent JavaDoc) newFocusOwnerEvent).isPosted = true;
2619                     caughtEx=dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
2620
2621                     if (manager.getGlobalFocusOwner() == lwFocusRequest.component){
2622                        lastFocusOwner = lwFocusRequest.component;
2623                     }
2624                }
2625            }
2626        } finally {
2627            clearingCurrentLightweightRequests = false;
2628            disableRestoreFocus=false;
2629            localLightweightRequests = null;
2630            allowSyncFocusRequests = true;
2631        }
2632
2633        if (caughtEx instanceof RuntimeException JavaDoc) {
2634            throw (RuntimeException JavaDoc)caughtEx;
2635        } else if (caughtEx instanceof Error JavaDoc) {
2636            throw (Error JavaDoc)caughtEx;
2637        }
2638
2639    }
2640
2641    static FocusEvent JavaDoc retargetUnexpectedFocusEvent(FocusEvent JavaDoc fe) {
2642        synchronized (heavyweightRequests) {
2643            // Any other case represents a failure condition which we did
2644
// not expect. We need to clearFocusRequestList() and patch up
2645
// the event as best as possible.
2646

2647            if (removeFirstRequest()) {
2648                return (FocusEvent JavaDoc)retargetFocusEvent(fe);
2649            }
2650
2651            Component JavaDoc source = fe.getComponent();
2652            Component JavaDoc opposite = fe.getOppositeComponent();
2653            boolean temporary = false;
2654            if (fe.getID() == FocusEvent.FOCUS_LOST &&
2655                (opposite == null || isTemporary(opposite, source)))
2656            {
2657                temporary = true;
2658            }
2659            return new FocusEvent JavaDoc(source, fe.getID(), temporary, opposite);
2660        }
2661    }
2662
2663    static FocusEvent JavaDoc retargetFocusGained(FocusEvent JavaDoc fe) {
2664        assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2665
2666        Component JavaDoc currentFocusOwner = getCurrentKeyboardFocusManager().
2667            getGlobalFocusOwner();
2668        Component JavaDoc source = fe.getComponent();
2669        Component JavaDoc opposite = fe.getOppositeComponent();
2670        Component JavaDoc nativeSource = getHeavyweight(source);
2671
2672        synchronized (heavyweightRequests) {
2673            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2674                ((heavyweightRequests.size() > 0)
2675                 ? heavyweightRequests.getFirst() : null);
2676
2677            if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2678            {
2679                return retargetUnexpectedFocusEvent(fe);
2680            }
2681
2682            if (source != null && nativeSource == null && hwFocusRequest != null) {
2683                // if source w/o peer and
2684
// if source is equal to first lightweight
2685
// then we should correct source and nativeSource
2686
if (source == hwFocusRequest.getFirstLightweightRequest().component)
2687                {
2688                    source = hwFocusRequest.heavyweight;
2689                    nativeSource = source; // source is heavuweight itself
2690
}
2691            }
2692            if (hwFocusRequest != null &&
2693                nativeSource == hwFocusRequest.heavyweight)
2694            {
2695                // Focus change as a result of a known call to requestFocus(),
2696
// or known click on a peer focusable heavyweight Component.
2697

2698                heavyweightRequests.removeFirst();
2699
2700                LightweightFocusRequest lwFocusRequest =
2701                    (LightweightFocusRequest)hwFocusRequest.
2702                    lightweightRequests.removeFirst();
2703
2704                Component JavaDoc newSource = lwFocusRequest.component;
2705                if (currentFocusOwner != null) {
2706                    /*
2707                     * Since we receive FOCUS_GAINED when current focus
2708                     * owner is not null, correcponding FOCUS_LOST is supposed
2709                     * to be lost. And so, we keep new focus owner
2710                     * to determine synthetic FOCUS_LOST event which will be
2711                     * generated by KeyboardFocusManager for this FOCUS_GAINED.
2712                     *
2713                     * This code based on knowledge of
2714                     * DefaultKeyboardFocusManager's implementation and might
2715                     * be not applicable for another KeyboardFocusManager.
2716                     */

2717                    newFocusOwner = newSource;
2718                }
2719
2720                boolean temporary = (opposite == null ||
2721                                     isTemporary(newSource, opposite))
2722                        ? false
2723                        : lwFocusRequest.temporary;
2724
2725                if (hwFocusRequest.lightweightRequests.size() > 0) {
2726                    currentLightweightRequests =
2727                        hwFocusRequest.lightweightRequests;
2728                    EventQueue.invokeLater(new Runnable JavaDoc() {
2729                            public void run() {
2730                                processCurrentLightweightRequests();
2731                            }
2732                        });
2733                }
2734
2735                // 'opposite' will be fixed by
2736
// DefaultKeyboardFocusManager.realOppositeComponent
2737
return new FocusEvent JavaDoc(newSource,
2738                                      FocusEvent.FOCUS_GAINED, temporary,
2739                                      opposite);
2740            }
2741
2742            if (currentFocusOwner != null
2743                && currentFocusOwner.getContainingWindow() == source
2744                && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
2745            {
2746                // Special case for FOCUS_GAINED in top-levels
2747
// If it arrives as the result of activation we should skip it
2748
// This event will not have appropriate request record and
2749
// on arrival there will be already some focus owner set.
2750
return new FocusEvent JavaDoc(currentFocusOwner, FocusEvent.FOCUS_GAINED, false, null);
2751            }
2752
2753            return retargetUnexpectedFocusEvent(fe);
2754        } // end synchronized(heavyweightRequests)
2755
}
2756
2757    static FocusEvent JavaDoc retargetFocusLost(FocusEvent JavaDoc fe) {
2758        assert (fe.getID() == FocusEvent.FOCUS_LOST);
2759
2760        Component JavaDoc currentFocusOwner = getCurrentKeyboardFocusManager().
2761            getGlobalFocusOwner();
2762        Component JavaDoc opposite = fe.getOppositeComponent();
2763        Component JavaDoc nativeOpposite = getHeavyweight(opposite);
2764
2765        synchronized (heavyweightRequests) {
2766            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2767                ((heavyweightRequests.size() > 0)
2768                 ? heavyweightRequests.getFirst() : null);
2769
2770            if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
2771            {
2772                if (currentFocusOwner != null) {
2773                    // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2774
heavyweightRequests.removeFirst();
2775                    return new FocusEvent JavaDoc(currentFocusOwner,
2776                                          FocusEvent.FOCUS_LOST, false, null);
2777                }
2778
2779                // Otherwise, fall through to failure case below
2780

2781            } else if (opposite == null)
2782            {
2783                // Focus leaving application
2784
if (currentFocusOwner != null) {
2785                    return new FocusEvent JavaDoc(currentFocusOwner,
2786                                          FocusEvent.FOCUS_LOST,
2787                                          true, null);
2788                } else {
2789                    return fe;
2790                }
2791            } else if (hwFocusRequest != null &&
2792                       (nativeOpposite == hwFocusRequest.heavyweight ||
2793                        nativeOpposite == null &&
2794                        opposite == hwFocusRequest.getFirstLightweightRequest().component))
2795            {
2796                if (currentFocusOwner == null) {
2797                    return fe;
2798                }
2799                // Focus change as a result of a known call to requestFocus(),
2800
// or click on a peer focusable heavyweight Component.
2801

2802                // If a focus transfer is made across top-levels, then the
2803
// FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2804
// event is always permanent. Otherwise, the stored temporary
2805
// value is honored.
2806

2807                LightweightFocusRequest lwFocusRequest =
2808                    (LightweightFocusRequest)hwFocusRequest.
2809                    lightweightRequests.getFirst();
2810
2811                boolean temporary = isTemporary(opposite,
2812                                                         currentFocusOwner)
2813                    ? true
2814                    : lwFocusRequest.temporary;
2815
2816                return new FocusEvent JavaDoc(currentFocusOwner, FocusEvent.FOCUS_LOST,
2817                                      temporary, lwFocusRequest.component);
2818            } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2819                // If top-level changed there might be no focus request in a list
2820
// But we know the opposite, we now it is temporary - dispatch the event.
2821
if (!fe.isTemporary() && currentFocusOwner != null) {
2822                    // Create copy of the event with only difference in temporary parameter.
2823
fe = new FocusEvent JavaDoc(currentFocusOwner, FocusEvent.FOCUS_LOST,
2824                                        true, opposite);
2825                }
2826                return fe;
2827            }
2828
2829            return retargetUnexpectedFocusEvent(fe);
2830        } // end synchronized(heavyweightRequests)
2831
}
2832
2833    static AWTEvent JavaDoc retargetFocusEvent(AWTEvent JavaDoc event) {
2834        if (clearingCurrentLightweightRequests) {
2835            return event;
2836        }
2837
2838        KeyboardFocusManager JavaDoc manager = getCurrentKeyboardFocusManager();
2839        if (focusLog.isLoggable(Level.FINE)) {
2840            if (event instanceof FocusEvent JavaDoc || event instanceof WindowEvent JavaDoc) {
2841                focusLog.log(Level.FINE, ">>> {0}", new Object JavaDoc[] {event});
2842            }
2843            if (focusLog.isLoggable(Level.FINER) && event instanceof KeyEvent JavaDoc) {
2844                focusLog.log(Level.FINER, " focus owner is {0}", new Object JavaDoc[] {manager.getGlobalFocusOwner()});
2845                focusLog.log(Level.FINER, ">>> {0}", new Object JavaDoc[] {event});
2846            }
2847        }
2848
2849        synchronized(heavyweightRequests) {
2850            /*
2851             * This code handles FOCUS_LOST event which is generated by
2852             * DefaultKeyboardFocusManager for FOCUS_GAINED.
2853             *
2854             * This code based on knowledge of DefaultKeyboardFocusManager's
2855             * implementation and might be not applicable for another
2856             * KeyboardFocusManager.
2857             *
2858             * Fix for 4472032
2859             */

2860            if (newFocusOwner != null &&
2861                event.getID() == FocusEvent.FOCUS_LOST)
2862            {
2863                FocusEvent JavaDoc fe = (FocusEvent JavaDoc)event;
2864
2865                if (manager.getGlobalFocusOwner() == fe.getComponent() &&
2866                    fe.getOppositeComponent() == newFocusOwner)
2867                {
2868                    newFocusOwner = null;
2869                    return event;
2870                }
2871            }
2872        }
2873
2874        processCurrentLightweightRequests();
2875
2876        switch (event.getID()) {
2877            case FocusEvent.FOCUS_GAINED: {
2878                event = retargetFocusGained((FocusEvent JavaDoc)event);
2879                break;
2880            }
2881            case FocusEvent.FOCUS_LOST: {
2882                event = retargetFocusLost((FocusEvent JavaDoc)event);
2883                break;
2884            }
2885            default:
2886                /* do nothing */
2887        }
2888        return event;
2889    }
2890
2891    /**
2892     * Clears markers queue
2893     * This method is not intended to be overridden by KFM's.
2894     * Only DefaultKeyboardFocusManager can implement it.
2895     * @since 1.5
2896     */

2897    void clearMarkers() {
2898    }
2899        
2900    static boolean removeFirstRequest() {
2901        KeyboardFocusManager JavaDoc manager =
2902            KeyboardFocusManager.getCurrentKeyboardFocusManager();
2903
2904        synchronized(heavyweightRequests) {
2905            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2906
2907                ((heavyweightRequests.size() > 0)
2908                 ? heavyweightRequests.getFirst() : null);
2909            if (hwFocusRequest != null) {
2910                heavyweightRequests.removeFirst();
2911                if (hwFocusRequest.lightweightRequests != null) {
2912                    for (Iterator JavaDoc lwIter = hwFocusRequest.lightweightRequests.
2913                             iterator();
2914                         lwIter.hasNext(); )
2915                    {
2916                        manager.dequeueKeyEvents
2917                            (-1, ((LightweightFocusRequest)lwIter.next()).
2918                             component);
2919                    }
2920                }
2921            }
2922            // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2923
// We do it here because this method is called only when problems happen
2924
if (heavyweightRequests.size() == 0) {
2925                manager.clearMarkers();
2926            }
2927            return (heavyweightRequests.size() > 0);
2928        }
2929    }
2930    static void removeLastFocusRequest(Component JavaDoc heavyweight) {
2931        if (dbg.on) {
2932            dbg.assertion(heavyweight != null);
2933        }
2934
2935        KeyboardFocusManager JavaDoc manager =
2936            KeyboardFocusManager.getCurrentKeyboardFocusManager();
2937        synchronized(heavyweightRequests) {
2938            HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
2939                ((heavyweightRequests.size() > 0)
2940                 ? heavyweightRequests.getLast() : null);
2941            if (hwFocusRequest != null &&
2942                hwFocusRequest.heavyweight == heavyweight) {
2943                heavyweightRequests.removeLast();
2944            }
2945            // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2946
// We do it here because this method is called only when problems happen
2947
if (heavyweightRequests.size() == 0) {
2948                manager.clearMarkers();
2949            }
2950        }
2951    }
2952
2953    private static boolean focusedWindowChanged(Component JavaDoc to, Component JavaDoc from) {
2954        Window JavaDoc wto = Component.getContainingWindow(to);
2955        Window JavaDoc wfrom = Component.getContainingWindow(from);
2956        if (wto == null && wfrom == null) {
2957            return true;
2958        }
2959        if (wto == null) {
2960            return true;
2961        }
2962        if (wfrom == null) {
2963            return true;
2964        }
2965        return (wto != wfrom);
2966    }
2967
2968    private static boolean isTemporary(Component JavaDoc to, Component JavaDoc from) {
2969        Window JavaDoc wto = Component.getContainingWindow(to);
2970        Window JavaDoc wfrom = Component.getContainingWindow(from);
2971        if (wto == null && wfrom == null) {
2972            return false;
2973        }
2974        if (wto == null) {
2975            return true;
2976        }
2977        if (wfrom == null) {
2978            return false;
2979        }
2980        return (wto != wfrom);
2981    }
2982
2983    static Component JavaDoc getHeavyweight(Component JavaDoc comp) {
2984        if (comp == null || comp.getPeer() == null) {
2985            return null;
2986        } else if (comp.getPeer() instanceof LightweightPeer) {
2987            return comp.getNativeContainer();
2988        } else {
2989            return comp;
2990        }
2991    }
2992
2993    static Field proxyActive;
2994    // Accessor to private field isProxyActive of KeyEvent
2995
private static boolean isProxyActiveImpl(KeyEvent JavaDoc e) {
2996        if (proxyActive == null) {
2997            proxyActive = (Field) AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
2998                    public Object JavaDoc run() {
2999                        Field field = null;
3000                        try {
3001                            field = KeyEvent JavaDoc.class.getDeclaredField("isProxyActive");
3002                            if (field != null) {
3003                                field.setAccessible(true);
3004                            }
3005                        } catch (NoSuchFieldException JavaDoc nsf) {
3006                            assert(false);
3007                        }
3008                        return field;
3009                    }
3010                });
3011        }
3012
3013        try {
3014            return proxyActive.getBoolean(e);
3015        } catch (IllegalAccessException JavaDoc iae) {
3016            assert(false);
3017        }
3018        return false;
3019    }
3020
3021    // Returns the value of this KeyEvent's field isProxyActive
3022
static boolean isProxyActive(KeyEvent JavaDoc e) {
3023        if (!GraphicsEnvironment.isHeadless()) {
3024            return isProxyActiveImpl(e);
3025        } else {
3026            return false;
3027        }
3028    }
3029}
3030
Popular Tags