1 /*
2 * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 package java.awt;
26
27 import java.awt.event.FocusEvent;
28 import java.awt.event.InputEvent;
29 import java.awt.event.KeyEvent;
30 import java.awt.event.WindowEvent;
31
32 import java.awt.peer.KeyboardFocusManagerPeer;
33 import java.awt.peer.LightweightPeer;
34
35 import java.beans.PropertyChangeListener;
36 import java.beans.PropertyChangeSupport;
37 import java.beans.PropertyVetoException;
38 import java.beans.VetoableChangeListener;
39 import java.beans.VetoableChangeSupport;
40
41 import java.lang.ref.WeakReference;
42
43 import java.lang.reflect.Field;
44
45 import java.security.AccessController;
46 import java.security.PrivilegedAction;
47
48 import java.util.Collections;
49 import java.util.HashSet;
50 import java.util.Iterator;
51 import java.util.LinkedList;
52 import java.util.Set;
53 import java.util.StringTokenizer;
54 import java.util.WeakHashMap;
55
56 import java.util.logging.Level;
57 import java.util.logging.Logger;
58
59 import sun.awt.AppContext;
60 import sun.awt.HeadlessToolkit;
61 import sun.awt.SunToolkit;
62 import sun.awt.CausedFocusEvent;
63 import sun.awt.KeyboardFocusManagerPeerProvider;
64
65 /**
66 * The KeyboardFocusManager is responsible for managing the active and focused
67 * Windows, and the current focus owner. The focus owner is defined as the
68 * Component in an application that will typically receive all KeyEvents
69 * generated by the user. The focused Window is the Window that is, or
70 * contains, the focus owner. Only a Frame or a Dialog can be the active
71 * Window. The native windowing system may denote the active Window or its
72 * children with special decorations, such as a highlighted title bar. The
73 * active Window is always either the focused Window, or the first Frame or
74 * Dialog that is an owner of the focused Window.
75 * <p>
76 * The KeyboardFocusManager is both a centralized location for client code to
77 * query for the focus owner and initiate focus changes, and an event
78 * dispatcher for all FocusEvents, WindowEvents related to focus, and
79 * KeyEvents.
80 * <p>
81 * Some browsers partition applets in different code bases into separate
82 * contexts, and establish walls between these contexts. In such a scenario,
83 * there will be one KeyboardFocusManager per context. Other browsers place all
84 * applets into the same context, implying that there will be only a single,
85 * global KeyboardFocusManager for all applets. This behavior is
86 * implementation-dependent. Consult your browser's documentation for more
87 * information. No matter how many contexts there may be, however, there can
88 * never be more than one focus owner, focused Window, or active Window, per
89 * ClassLoader.
90 * <p>
91 * Please see
92 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
93 * How to Use the Focus Subsystem</a>,
94 * a section in <em>The Java Tutorial</em>, and the
95 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
96 * for more information.
97 *
98 * @author David Mendenhall
99 *
100 * @see Window
101 * @see Frame
102 * @see Dialog
103 * @see java.awt.event.FocusEvent
104 * @see java.awt.event.WindowEvent
105 * @see java.awt.event.KeyEvent
106 * @since 1.4
107 */
108 public abstract class KeyboardFocusManager
109 implements KeyEventDispatcher, KeyEventPostProcessor
110 {
111
112 // Shared focus engine logger
113 private static final Logger focusLog = Logger.getLogger("java.awt.focus.KeyboardFocusManager");
114
115 static {
116 /* ensure that the necessary native libraries are loaded */
117 Toolkit.loadLibraries();
118 if (!GraphicsEnvironment.isHeadless()) {
119 initIDs();
120 }
121 }
122
123 transient KeyboardFocusManagerPeer peer;
124
125 /**
126 * Initialize JNI field and method IDs
127 */
128 private static native void initIDs();
129
130 private static final Logger log = Logger.getLogger("java.awt.KeyboardFocusManager");
131
132 /**
133 * The identifier for the Forward focus traversal keys.
134 *
135 * @see #setDefaultFocusTraversalKeys
136 * @see #getDefaultFocusTraversalKeys
137 * @see Component#setFocusTraversalKeys
138 * @see Component#getFocusTraversalKeys
139 */
140 public static final int FORWARD_TRAVERSAL_KEYS = 0;
141
142 /**
143 * The identifier for the Backward focus traversal keys.
144 *
145 * @see #setDefaultFocusTraversalKeys
146 * @see #getDefaultFocusTraversalKeys
147 * @see Component#setFocusTraversalKeys
148 * @see Component#getFocusTraversalKeys
149 */
150 public static final int BACKWARD_TRAVERSAL_KEYS = 1;
151
152 /**
153 * The identifier for the Up Cycle focus traversal keys.
154 *
155 * @see #setDefaultFocusTraversalKeys
156 * @see #getDefaultFocusTraversalKeys
157 * @see Component#setFocusTraversalKeys
158 * @see Component#getFocusTraversalKeys
159 */
160 public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
161
162 /**
163 * The identifier for the Down Cycle focus traversal keys.
164 *
165 * @see #setDefaultFocusTraversalKeys
166 * @see #getDefaultFocusTraversalKeys
167 * @see Component#setFocusTraversalKeys
168 * @see Component#getFocusTraversalKeys
169 */
170 public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
171
172 static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
173
174 /**
175 * Returns the current KeyboardFocusManager instance for the calling
176 * thread's context.
177 *
178 * @return this thread's context's KeyboardFocusManager
179 * @see #setCurrentKeyboardFocusManager
180 */
181 public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
182 return getCurrentKeyboardFocusManager(AppContext.getAppContext());
183 }
184
185 synchronized static KeyboardFocusManager
186 getCurrentKeyboardFocusManager(AppContext appcontext)
187 {
188 KeyboardFocusManager manager = (KeyboardFocusManager)
189 appcontext.get(KeyboardFocusManager.class);
190 if (manager == null) {
191 manager = new DefaultKeyboardFocusManager();
192 appcontext.put(KeyboardFocusManager.class, manager);
193 }
194 return manager;
195 }
196
197 /**
198 * Sets the current KeyboardFocusManager instance for the calling thread's
199 * context. If null is specified, then the current KeyboardFocusManager
200 * is replaced with a new instance of DefaultKeyboardFocusManager.
201 * <p>
202 * If a SecurityManager is installed, the calling thread must be granted
203 * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
204 * the current KeyboardFocusManager. If this permission is not granted,
205 * this method will throw a SecurityException, and the current
206 * KeyboardFocusManager will be unchanged.
207 *
208 * @param newManager the new KeyboardFocusManager for this thread's context
209 * @see #getCurrentKeyboardFocusManager
210 * @see DefaultKeyboardFocusManager
211 * @throws SecurityException if the calling thread does not have permission
212 * to replace the current KeyboardFocusManager
213 */
214 public static void setCurrentKeyboardFocusManager(
215 KeyboardFocusManager newManager) throws SecurityException
216 {
217 SecurityManager security = System.getSecurityManager();
218 if (security != null) {
219 if (replaceKeyboardFocusManagerPermission == null) {
220 replaceKeyboardFocusManagerPermission =
221 new AWTPermission("replaceKeyboardFocusManager");
222 }
223 security.
224 checkPermission(replaceKeyboardFocusManagerPermission);
225 }
226
227 KeyboardFocusManager oldManager = null;
228
229 synchronized (KeyboardFocusManager.class) {
230 AppContext appcontext = AppContext.getAppContext();
231
232 if (newManager != null) {
233 oldManager = getCurrentKeyboardFocusManager(appcontext);
234
235 appcontext.put(KeyboardFocusManager.class, newManager);
236 } else {
237 oldManager = getCurrentKeyboardFocusManager(appcontext);
238 appcontext.remove(KeyboardFocusManager.class);
239 }
240 }
241
242 if (oldManager != null) {
243 oldManager.firePropertyChange("managingFocus",
244 Boolean.TRUE,
245 Boolean.FALSE);
246 }
247 if (newManager != null) {
248 newManager.firePropertyChange("managingFocus",
249 Boolean.FALSE,
250 Boolean.TRUE);
251 }
252 }
253
254 /**
255 * The Component in an application that will typically receive all
256 * KeyEvents generated by the user.
257 */
258 private static Component focusOwner;
259
260 /**
261 * The Component in an application that will regain focus when an
262 * outstanding temporary focus transfer has completed, or the focus owner,
263 * if no outstanding temporary transfer exists.
264 */
265 private static Component permanentFocusOwner;
266
267 /**
268 * The Window which is, or contains, the focus owner.
269 */
270 private static Window focusedWindow;
271
272 /**
273 * Only a Frame or a Dialog can be the active Window. The native windowing
274 * system may denote the active Window with a special decoration, such as a
275 * highlighted title bar. The active Window is always either the focused
276 * Window, or the first Frame or Dialog which is an owner of the focused
277 * Window.
278 */
279 private static Window activeWindow;
280
281 /**
282 * The default FocusTraversalPolicy for all Windows that have no policy of
283 * their own set. If those Windows have focus-cycle-root children that have
284 * no keyboard-traversal policy of their own, then those children will also
285 * inherit this policy (as will, recursively, their focus-cycle-root
286 * children).
287 */
288 private FocusTraversalPolicy defaultPolicy =
289 new DefaultFocusTraversalPolicy();
290
291 /**
292 * The bound property names of each focus traversal key.
293 */
294 private static final String[] defaultFocusTraversalKeyPropertyNames = {
295 "forwardDefaultFocusTraversalKeys",
296 "backwardDefaultFocusTraversalKeys",
297 "upCycleDefaultFocusTraversalKeys",
298 "downCycleDefaultFocusTraversalKeys"
299 };
300
301 /**
302 * The default strokes for initializing the default focus traversal keys.
303 */
304 private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
305 {
306 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false),
307 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false),
308 },
309 {
310 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false),
311 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
312 InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK,
313 false),
314 },
315 {},
316 {},
317 };
318 /**
319 * The default focus traversal keys. Each array of traversal keys will be
320 * in effect on all Windows that have no such array of their own explicitly
321 * set. Each array will also be inherited, recursively, by any child
322 * Component of those Windows that has no such array of its own explicitly
323 * set.
324 */
325 private Set[] defaultFocusTraversalKeys = new Set[4];
326
327 /**
328 * The current focus cycle root. If the focus owner is itself a focus cycle
329 * root, then it may be ambiguous as to which Components represent the next
330 * and previous Components to focus during normal focus traversal. In that
331 * case, the current focus cycle root is used to differentiate among the
332 * possibilities.
333 */
334 private static Container currentFocusCycleRoot;
335
336 /**
337 * A description of any VetoableChangeListeners which have been registered.
338 */
339 private VetoableChangeSupport vetoableSupport;
340
341 /**
342 * A description of any PropertyChangeListeners which have been registered.
343 */
344 private PropertyChangeSupport changeSupport;
345
346 /**
347 * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
348 * include this KeyboardFocusManager unless it was explicitly re-registered
349 * via a call to <code>addKeyEventDispatcher</code>. If no other
350 * KeyEventDispatchers are registered, this field may be null or refer to
351 * a List of length 0.
352 */
353 private java.util.LinkedList keyEventDispatchers;
354
355 /**
356 * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
357 * not include this KeyboardFocusManager unless it was explicitly
358 * re-registered via a call to <code>addKeyEventPostProcessor</code>.
359 * If no other KeyEventPostProcessors are registered, this field may be
360 * null or refer to a List of length 0.
361 */
362 private java.util.LinkedList keyEventPostProcessors;
363
364 /**
365 * Maps Windows to those Windows' most recent focus owners.
366 */
367 private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
368
369 /**
370 * Error String for initializing SecurityExceptions.
371 */
372 private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
373
374 /**
375 * We cache the permission used to verify that the calling thread is
376 * permitted to access the global focus state.
377 */
378 private static AWTPermission replaceKeyboardFocusManagerPermission;
379
380 /*
381 * SequencedEvent which is currently dispatched in AppContext.
382 */
383 transient SequencedEvent currentSequencedEvent = null;
384
385 final void setCurrentSequencedEvent(SequencedEvent current) {
386 synchronized (SequencedEvent.class) {
387 assert(current == null || currentSequencedEvent == null);
388 currentSequencedEvent = current;
389 }
390 }
391
392 final SequencedEvent getCurrentSequencedEvent() {
393 synchronized (SequencedEvent.class) {
394 return currentSequencedEvent;
395 }
396 }
397
398 static Set initFocusTraversalKeysSet(String value, Set targetSet) {
399 StringTokenizer tokens = new StringTokenizer(value, ",");
400 while (tokens.hasMoreTokens()) {
401 targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken()));
402 }
403 return (targetSet.isEmpty())
404 ? Collections.EMPTY_SET
405 : Collections.unmodifiableSet(targetSet);
406 }
407
408 /**
409 * Initializes a KeyboardFocusManager.
410 */
411 public KeyboardFocusManager() {
412 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
413 Set work_set = new HashSet();
414 for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
415 work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
416 }
417 defaultFocusTraversalKeys[i] = (work_set.isEmpty())
418 ? Collections.EMPTY_SET
419 : Collections.unmodifiableSet(work_set);
420 }
421 initPeer();
422 }
423
424 private void initPeer() {
425 Toolkit tk = Toolkit.getDefaultToolkit();
426 KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk;
427 peer = peerProvider.createKeyboardFocusManagerPeer(this);
428 }
429
430 /**
431 * Returns the focus owner, if the focus owner is in the same context as
432 * the calling thread. The focus owner is defined as the Component in an
433 * application that will typically receive all KeyEvents generated by the
434 * user. KeyEvents which map to the focus owner's focus traversal keys will
435 * not be delivered if focus traversal keys are enabled for the focus
436 * owner. In addition, KeyEventDispatchers may retarget or consume
437 * KeyEvents before they reach the focus owner.
438 *
439 * @return the focus owner, or null if the focus owner is not a member of
440 * the calling thread's context
441 * @see #getGlobalFocusOwner
442 * @see #setGlobalFocusOwner
443 */
444 public Component getFocusOwner() {
445 synchronized (KeyboardFocusManager.class) {
446 if (focusOwner == null) {
447 return null;
448 }
449
450 return (focusOwner.appContext == AppContext.getAppContext())
451 ? focusOwner
452 : null;
453 }
454 }
455
456 /**
457 * Returns the focus owner, even if the calling thread is in a different
458 * context than the focus owner. The focus owner is defined as the
459 * Component in an application that will typically receive all KeyEvents
460 * generated by the user. KeyEvents which map to the focus owner's focus
461 * traversal keys will not be delivered if focus traversal keys are enabled
462 * for the focus owner. In addition, KeyEventDispatchers may retarget or
463 * consume KeyEvents before they reach the focus owner.
464 * <p>
465 * This method will throw a SecurityException if this KeyboardFocusManager
466 * is not the current KeyboardFocusManager for the calling thread's
467 * context.
468 *
469 * @return the focus owner
470 * @see #getFocusOwner
471 * @see #setGlobalFocusOwner
472 * @throws SecurityException if this KeyboardFocusManager is not the
473 * current KeyboardFocusManager for the calling thread's context
474 */
475 protected Component getGlobalFocusOwner() throws SecurityException {
476 synchronized (KeyboardFocusManager.class) {
477 if (this == getCurrentKeyboardFocusManager()) {
478 return focusOwner;
479 } else {
480 if (focusLog.isLoggable(Level.FINER)) {
481 focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
482 }
483 throw new SecurityException(notPrivileged);
484 }
485 }
486 }
487
488 /**
489 * Sets the focus owner. The operation will be cancelled if the Component
490 * is not focusable. The focus owner is defined as the Component in an
491 * application that will typically receive all KeyEvents generated by the
492 * user. KeyEvents which map to the focus owner's focus traversal keys will
493 * not be delivered if focus traversal keys are enabled for the focus
494 * owner. In addition, KeyEventDispatchers may retarget or consume
495 * KeyEvents before they reach the focus owner.
496 * <p>
497 * This method does not actually set the focus to the specified Component.
498 * It merely stores the value to be subsequently returned by
499 * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
500 * or <code>Component.requestFocusInWindow()</code> to change the focus
501 * owner, subject to platform limitations.
502 *
503 * @param focusOwner the focus owner
504 * @see #getFocusOwner
505 * @see #getGlobalFocusOwner
506 * @see Component#requestFocus()
507 * @see Component#requestFocusInWindow()
508 * @see Component#isFocusable
509 * @beaninfo
510 * bound: true
511 */
512 protected void setGlobalFocusOwner(Component focusOwner) {
513 Component oldFocusOwner = null;
514 boolean shouldFire = false;
515
516 if (focusOwner == null || focusOwner.isFocusable()) {
517 synchronized (KeyboardFocusManager.class) {
518 oldFocusOwner = getFocusOwner();
519
520 try {
521 fireVetoableChange("focusOwner", oldFocusOwner,
522 focusOwner);
523 } catch (PropertyVetoException e) {
524 // rejected
525 return;
526 }
527
528 KeyboardFocusManager.focusOwner = focusOwner;
529
530 if (focusOwner != null &&
531 (getCurrentFocusCycleRoot() == null ||
532 !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot())))
533 {
534 Container rootAncestor =
535 focusOwner.getFocusCycleRootAncestor();
536 if (rootAncestor == null && (focusOwner instanceof Window))
537 {
538 rootAncestor = (Container)focusOwner;
539 }
540 if (rootAncestor != null) {
541 setGlobalCurrentFocusCycleRoot(rootAncestor);
542 }
543 }
544
545 shouldFire = true;
546 }
547 }
548
549 if (shouldFire) {
550 firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
551 }
552 }
553
554 /**
555 * Clears the global focus owner at both the Java and native levels. If
556 * there exists a focus owner, that Component will receive a permanent
557 * FOCUS_LOST event. After this operation completes, the native windowing
558 * system will discard all user-generated KeyEvents until the user selects
559 * a new Component to receive focus, or a Component is given focus
560 * explicitly via a call to <code>requestFocus()</code>. This operation
561 * does not change the focused or active Windows.
562 *
563 * @see Component#requestFocus()
564 * @see java.awt.event.FocusEvent#FOCUS_LOST
565 */
566 public void clearGlobalFocusOwner() {
567 if (!GraphicsEnvironment.isHeadless()) {
568 // Toolkit must be fully initialized, otherwise
569 // _clearGlobalFocusOwner will crash or throw an exception
570 Toolkit.getDefaultToolkit();
571
572 _clearGlobalFocusOwner();
573 }
574 }
575 private void _clearGlobalFocusOwner() {
576 Window activeWindow = markClearGlobalFocusOwner();
577 peer.clearGlobalFocusOwner(activeWindow);
578 }
579
580 Component getNativeFocusOwner() {
581 return peer.getCurrentFocusOwner();
582 }
583
584 void setNativeFocusOwner(Component comp) {
585 if (focusLog.isLoggable(Level.FINEST)) {
586 focusLog.log(Level.FINEST, "Calling peer {0} setCurrentFocusOwner for {1}",
587 new Object[] {peer, comp});
588 }
589 peer.setCurrentFocusOwner(comp);
590 }
591
592 Window getNativeFocusedWindow() {
593 return peer.getCurrentFocusedWindow();
594 }
595
596 /**
597 * Returns the permanent focus owner, if the permanent focus owner is in
598 * the same context as the calling thread. The permanent focus owner is
599 * defined as the last Component in an application to receive a permanent
600 * FOCUS_GAINED event. The focus owner and permanent focus owner are
601 * equivalent unless a temporary focus change is currently in effect. In
602 * such a situation, the permanent focus owner will again be the focus
603 * owner when the temporary focus change ends.
604 *
605 * @return the permanent focus owner, or null if the permanent focus owner
606 * is not a member of the calling thread's context
607 * @see #getGlobalPermanentFocusOwner
608 * @see #setGlobalPermanentFocusOwner
609 */
610 public Component getPermanentFocusOwner() {
611 synchronized (KeyboardFocusManager.class) {
612 if (permanentFocusOwner == null) {
613 return null;
614 }
615
616 return (permanentFocusOwner.appContext ==
617 AppContext.getAppContext())
618 ? permanentFocusOwner
619 : null;
620 }
621 }
622
623 /**
624 * Returns the permanent focus owner, even if the calling thread is in a
625 * different context than the permanent focus owner. The permanent focus
626 * owner is defined as the last Component in an application to receive a
627 * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
628 * are equivalent unless a temporary focus change is currently in effect.
629 * In such a situation, the permanent focus owner will again be the focus
630 * owner when the temporary focus change ends.
631 * <p>
632 * This method will throw a SecurityException if this KeyboardFocusManager
633 * is not the current KeyboardFocusManager for the calling thread's
634 * context.
635 *
636 * @return the permanent focus owner
637 * @see #getPermanentFocusOwner
638 * @see #setGlobalPermanentFocusOwner
639 * @throws SecurityException if this KeyboardFocusManager is not the
640 * current KeyboardFocusManager for the calling thread's context
641 */
642 protected Component getGlobalPermanentFocusOwner()
643 throws SecurityException
644 {
645 synchronized (KeyboardFocusManager.class) {
646 if (this == getCurrentKeyboardFocusManager()) {
647 return permanentFocusOwner;
648 } else {
649 if (focusLog.isLoggable(Level.FINER)) {
650 focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
651 }
652 throw new SecurityException(notPrivileged);
653 }
654 }
655 }
656
657 /**
658 * Sets the permanent focus owner. The operation will be cancelled if the
659 * Component is not focusable. The permanent focus owner is defined as the
660 * last Component in an application to receive a permanent FOCUS_GAINED
661 * event. The focus owner and permanent focus owner are equivalent unless
662 * a temporary focus change is currently in effect. In such a situation,
663 * the permanent focus owner will again be the focus owner when the
664 * temporary focus change ends.
665 * <p>
666 * This method does not actually set the focus to the specified Component.
667 * It merely stores the value to be subsequently returned by
668 * <code>getPermanentFocusOwner()</code>. Use
669 * <code>Component.requestFocus()</code> or
670 * <code>Component.requestFocusInWindow()</code> to change the focus owner,
671 * subject to platform limitations.
672 *
673 * @param permanentFocusOwner the permanent focus owner
674 * @see #getPermanentFocusOwner
675 * @see #getGlobalPermanentFocusOwner
676 * @see Component#requestFocus()
677 * @see Component#requestFocusInWindow()
678 * @see Component#isFocusable
679 * @beaninfo
680 * bound: true
681 */
682 protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner)
683 {
684 Component oldPermanentFocusOwner = null;
685 boolean shouldFire = false;
686
687 if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
688 synchronized (KeyboardFocusManager.class) {
689 oldPermanentFocusOwner = getPermanentFocusOwner();
690
691 try {
692 fireVetoableChange("permanentFocusOwner",
693 oldPermanentFocusOwner,
694 permanentFocusOwner);
695 } catch (PropertyVetoException e) {
696 // rejected
697 return;
698 }
699
700 KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
701
702 KeyboardFocusManager.
703 setMostRecentFocusOwner(permanentFocusOwner);
704
705 shouldFire = true;
706 }
707 }
708
709 if (shouldFire) {
710 firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
711 permanentFocusOwner);
712 }
713 }
714
715 /**
716 * Returns the focused Window, if the focused Window is in the same context
717 * as the calling thread. The focused Window is the Window that is or
718 * contains the focus owner.
719 *
720 * @return the focused Window, or null if the focused Window is not a
721 * member of the calling thread's context
722 * @see #getGlobalFocusedWindow
723 * @see #setGlobalFocusedWindow
724 */
725 public Window getFocusedWindow() {
726 synchronized (KeyboardFocusManager.class) {
727 if (focusedWindow == null) {
728 return null;
729 }
730
731 return (focusedWindow.appContext == AppContext.getAppContext())
732 ? focusedWindow
733 : null;
734 }
735 }
736
737 /**
738 * Returns the focused Window, even if the calling thread is in a different
739 * context than the focused Window. The focused Window is the Window that
740 * is or contains the focus owner.
741 * <p>
742 * This method will throw a SecurityException if this KeyboardFocusManager
743 * is not the current KeyboardFocusManager for the calling thread's
744 * context.
745 *
746 * @return the focused Window
747 * @see #getFocusedWindow
748 * @see #setGlobalFocusedWindow
749 * @throws SecurityException if this KeyboardFocusManager is not the
750 * current KeyboardFocusManager for the calling thread's context
751 */
752 protected Window getGlobalFocusedWindow() throws SecurityException {
753 synchronized (KeyboardFocusManager.class) {
754 if (this == getCurrentKeyboardFocusManager()) {
755 return focusedWindow;
756 } else {
757 if (focusLog.isLoggable(Level.FINER)) {
758 focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
759 }
760 throw new SecurityException(notPrivileged);
761 }
762 }
763 }
764
765 /**
766 * Sets the focused Window. The focused Window is the Window that is or
767 * contains the focus owner. The operation will be cancelled if the
768 * specified Window to focus is not a focusable Window.
769 * <p>
770 * This method does not actually change the focused Window as far as the
771 * native windowing system is concerned. It merely stores the value to be
772 * subsequently returned by <code>getFocusedWindow()</code>. Use
773 * <code>Component.requestFocus()</code> or
774 * <code>Component.requestFocusInWindow()</code> to change the focused
775 * Window, subject to platform limitations.
776 *
777 * @param focusedWindow the focused Window
778 * @see #getFocusedWindow
779 * @see #getGlobalFocusedWindow
780 * @see Component#requestFocus()
781 * @see Component#requestFocusInWindow()
782 * @see Window#isFocusableWindow
783 * @beaninfo
784 * bound: true
785 */
786 protected void setGlobalFocusedWindow(Window focusedWindow) {
787 Window oldFocusedWindow = null;
788 boolean shouldFire = false;
789
790 if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
791 synchronized (KeyboardFocusManager.class) {
792 oldFocusedWindow = getFocusedWindow();
793
794 try {
795 fireVetoableChange("focusedWindow", oldFocusedWindow,
796 focusedWindow);
797 } catch (PropertyVetoException e) {
798 // rejected
799 return;
800 }
801
802 KeyboardFocusManager.focusedWindow = focusedWindow;
803 shouldFire = true;
804 }
805 }
806
807 if (shouldFire) {
808 firePropertyChange("focusedWindow", oldFocusedWindow,
809 focusedWindow);
810 }
811 }
812
813 /**
814 * Returns the active Window, if the active Window is in the same context
815 * as the calling thread. Only a Frame or a Dialog can be the active
816 * Window. The native windowing system may denote the active Window or its
817 * children with special decorations, such as a highlighted title bar.
818 * The active Window is always either the focused Window, or the first
819 * Frame or Dialog that is an owner of the focused Window.
820 *
821 * @return the active Window, or null if the active Window is not a member
822 * of the calling thread's context
823 * @see #getGlobalActiveWindow
824 * @see #setGlobalActiveWindow
825 */
826 public Window getActiveWindow() {
827 synchronized (KeyboardFocusManager.class) {
828 if (activeWindow == null) {
829 return null;
830 }
831
832 return (activeWindow.appContext == AppContext.getAppContext())
833 ? activeWindow
834 : null;
835 }
836 }
837
838 /**
839 * Returns the active Window, even if the calling thread is in a different
840 * context than the active Window. Only a Frame or a Dialog can be the
841 * active Window. The native windowing system may denote the active Window
842 * or its children with special decorations, such as a highlighted title
843 * bar. The active Window is always either the focused Window, or the first
844 * Frame or Dialog that is an owner of the focused Window.
845 * <p>
846 * This method will throw a SecurityException if this KeyboardFocusManager
847 * is not the current KeyboardFocusManager for the calling thread's
848 * context.
849 *
850 * @return the active Window
851 * @see #getActiveWindow
852 * @see #setGlobalActiveWindow
853 * @throws SecurityException if this KeyboardFocusManager is not the
854 * current KeyboardFocusManager for the calling thread's context
855 */
856 protected Window getGlobalActiveWindow() throws SecurityException {
857 synchronized (KeyboardFocusManager.class) {
858 if (this == getCurrentKeyboardFocusManager()) {
859 return activeWindow;
860 } else {
861 if (focusLog.isLoggable(Level.FINER)) {
862 focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
863 }
864 throw new SecurityException(notPrivileged);
865 }
866 }
867 }
868
869 /**
870 * Sets the active Window. Only a Frame or a Dialog can be the active
871 * Window. The native windowing system may denote the active Window or its
872 * children with special decorations, such as a highlighted title bar. The
873 * active Window is always either the focused Window, or the first Frame or
874 * Dialog that is an owner of the focused Window.
875 * <p>
876 * This method does not actually change the active Window as far as the
877 * native windowing system is concerned. It merely stores the value to be
878 * subsequently returned by <code>getActiveWindow()</code>. Use
879 * <code>Component.requestFocus()</code> or
880 * <code>Component.requestFocusInWindow()</code>to change the active
881 * Window, subject to platform limitations.
882 *
883 * @param activeWindow the active Window
884 * @see #getActiveWindow
885 * @see #getGlobalActiveWindow
886 * @see Component#requestFocus()
887 * @see Component#requestFocusInWindow()
888 * @beaninfo
889 * bound: true
890 */
891 protected void setGlobalActiveWindow(Window activeWindow) {
892 Window oldActiveWindow;
893 synchronized (KeyboardFocusManager.class) {
894 oldActiveWindow = getActiveWindow();
895 if (focusLog.isLoggable(Level.FINER)) {
896 focusLog.log(Level.FINER, "Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
897 }
898
899 try {
900 fireVetoableChange("activeWindow", oldActiveWindow,
901 activeWindow);
902 } catch (PropertyVetoException e) {
903 // rejected
904 return;
905 }
906
907 KeyboardFocusManager.activeWindow = activeWindow;
908 }
909
910 firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
911 }
912
913 /**
914 * Returns the default FocusTraversalPolicy. Top-level components
915 * use this value on their creation to initialize their own focus traversal
916 * policy by explicit call to Container.setFocusTraversalPolicy.
917 *
918 * @return the default FocusTraversalPolicy. null will never be returned.
919 * @see #setDefaultFocusTraversalPolicy
920 * @see Container#setFocusTraversalPolicy
921 * @see Container#getFocusTraversalPolicy
922 */
923 public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
924 return defaultPolicy;
925 }
926
927 /**
928 * Sets the default FocusTraversalPolicy. Top-level components
929 * use this value on their creation to initialize their own focus traversal
930 * policy by explicit call to Container.setFocusTraversalPolicy.
931 * Note: this call doesn't affect already created components as they have
932 * their policy initialized. Only new components will use this policy as
933 * their default policy.
934 *
935 * @param defaultPolicy the new, default FocusTraversalPolicy
936 * @see #getDefaultFocusTraversalPolicy
937 * @see Container#setFocusTraversalPolicy
938 * @see Container#getFocusTraversalPolicy
939 * @throws IllegalArgumentException if defaultPolicy is null
940 * @beaninfo
941 * bound: true
942 */
943 public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy
944 defaultPolicy) {
945 if (defaultPolicy == null) {
946 throw new IllegalArgumentException("default focus traversal policy cannot be null");
947 }
948
949 FocusTraversalPolicy oldPolicy;
950
951 synchronized (this) {
952 oldPolicy = this.defaultPolicy;
953 this.defaultPolicy = defaultPolicy;
954 }
955
956 firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
957 defaultPolicy);
958 }
959
960 /**
961 * Sets the default focus traversal keys for a given traversal operation.
962 * This traversal key <code>Set</code> will be in effect on all
963 * <code>Window</code>s that have no such <code>Set</code> of
964 * their own explicitly defined. This <code>Set</code> will also be
965 * inherited, recursively, by any child <code>Component</code> of
966 * those <code>Windows</code> that has
967 * no such <code>Set</code> of its own explicitly defined.
968 * <p>
969 * The default values for the default focus traversal keys are
970 * implementation-dependent. Sun recommends that all implementations for a
971 * particular native platform use the same default values. The
972 * recommendations for Windows and Unix are listed below. These
973 * recommendations are used in the Sun AWT implementations.
974 *
975 * <table border=1 summary="Recommended default values for focus traversal keys">
976 * <tr>
977 * <th>Identifier</th>
978 * <th>Meaning</th>
979 * <th>Default</th>
980 * </tr>
981 * <tr>
982 * <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
983 * <td>Normal forward keyboard traversal</td>
984 * <td><code>TAB</code> on <code>KEY_PRESSED</code>,
985 * <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
986 * </tr>
987 * <tr>
988 * <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
989 * <td>Normal reverse keyboard traversal</td>
990 * <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
991 * <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
992 * </tr>
993 * <tr>
994 * <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
995 * <td>Go up one focus traversal cycle</td>
996 * <td>none</td>
997 * </tr>
998 * <tr>
999 * <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
1000 * <td>Go down one focus traversal cycle</td>
1001 * <td>none</td>
1002 * </tr>
1003 * </table>
1004 *
1005 * To disable a traversal key, use an empty <code>Set</code>;
1006 * <code>Collections.EMPTY_SET</code> is recommended.
1007 * <p>
1008 * Using the <code>AWTKeyStroke</code> API, client code can
1009 * specify on which of two
1010 * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
1011 * <code>KEY_RELEASED</code>, the focus traversal operation will
1012 * occur. Regardless of which <code>KeyEvent</code> is specified,
1013 * however, all <code>KeyEvent</code>s related to the focus
1014 * traversal key, including the associated <code>KEY_TYPED</code>
1015 * event, will be consumed, and will not be dispatched
1016 * to any <code>Component</code>. It is a runtime error to
1017 * specify a <code>KEY_TYPED</code> event as
1018 * mapping to a focus traversal operation, or to map the same event to
1019 * multiple default focus traversal operations.
1020 *
1021 * @param id one of
1022 * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1023 * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1024 * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1025 * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
1026 * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
1027 * specified operation
1028 * @see #getDefaultFocusTraversalKeys
1029 * @see Component#setFocusTraversalKeys
1030 * @see Component#getFocusTraversalKeys
1031 * @throws IllegalArgumentException if id is not one of
1032 * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1033 * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1034 * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1035 * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
1036 * or if keystrokes is <code>null</code>,
1037 * or if keystrokes contains <code>null</code>,
1038 * or if any <code>Object</code> in
1039 * keystrokes is not an <code>AWTKeyStroke</code>,
1040 * or if any keystroke
1041 * represents a <code>KEY_TYPED</code> event,
1042 * or if any keystroke already maps
1043 * to another default focus traversal operation
1044 * @beaninfo
1045 * bound: true
1046 */
1047 public void
1048 setDefaultFocusTraversalKeys(int id,
1049 Set<? extends AWTKeyStroke> keystrokes)
1050 {
1051 if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1052 throw new IllegalArgumentException("invalid focus traversal key identifier");
1053 }
1054 if (keystrokes == null) {
1055 throw new IllegalArgumentException("cannot set null Set of default focus traversal keys");
1056 }
1057
1058 Set oldKeys;
1059
1060 synchronized (this) {
1061 for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) {
1062 Object obj = iter.next();
1063
1064 if (obj == null) {
1065 throw new IllegalArgumentException("cannot set null focus traversal key");
1066 }
1067
1068 // Fix for 6195831:
1069 //According to javadoc this method should throw IAE instead of ClassCastException
1070 if (!(obj instanceof AWTKeyStroke)) {
1071 throw new IllegalArgumentException("object is expected to be AWTKeyStroke");
1072 }
1073 AWTKeyStroke keystroke = (AWTKeyStroke)obj;
1074
1075 if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1076 throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
1077 }
1078
1079 // Check to see if key already maps to another traversal
1080 // operation
1081 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
1082 if (i == id) {
1083 continue;
1084 }
1085
1086 if (defaultFocusTraversalKeys[i].contains(keystroke)) {
1087 throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
1088 }
1089 }
1090 }
1091
1092 oldKeys = defaultFocusTraversalKeys[id];
1093 defaultFocusTraversalKeys[id] =
1094 Collections.unmodifiableSet(new HashSet(keystrokes));
1095 }
1096
1097 firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
1098 oldKeys, keystrokes);
1099 }
1100
1101 /**
1102 * Returns a Set of default focus traversal keys for a given traversal
1103 * operation. This traversal key Set will be in effect on all Windows that
1104 * have no such Set of their own explicitly defined. This Set will also be
1105 * inherited, recursively, by any child Component of those Windows that has
1106 * no such Set of its own explicitly defined. (See
1107 * <code>setDefaultFocusTraversalKeys</code> for a full description of each
1108 * operation.)
1109 *
1110 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1111 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1112 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1113 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1114 * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
1115 * for the specified operation; the <code>Set</code>
1116 * will be unmodifiable, and may be empty; <code>null</code>
1117 * will never be returned
1118 * @see #setDefaultFocusTraversalKeys
1119 * @see Component#setFocusTraversalKeys
1120 * @see Component#getFocusTraversalKeys
1121 * @throws IllegalArgumentException if id is not one of
1122 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1123 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1124 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1125 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1126 */
1127 public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
1128 if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1129 throw new IllegalArgumentException("invalid focus traversal key identifier");
1130 }
1131
1132 // Okay to return Set directly because it is an unmodifiable view
1133 return defaultFocusTraversalKeys[id];
1134 }
1135
1136 /**
1137 * Returns the current focus cycle root, if the current focus cycle root is
1138 * in the same context as the calling thread. If the focus owner is itself
1139 * a focus cycle root, then it may be ambiguous as to which Components
1140 * represent the next and previous Components to focus during normal focus
1141 * traversal. In that case, the current focus cycle root is used to
1142 * differentiate among the possibilities.
1143 * <p>
1144 * This method is intended to be used only by KeyboardFocusManagers and
1145 * focus implementations. It is not for general client use.
1146 *
1147 * @return the current focus cycle root, or null if the current focus cycle
1148 * root is not a member of the calling thread's context
1149 * @see #getGlobalCurrentFocusCycleRoot
1150 * @see #setGlobalCurrentFocusCycleRoot
1151 */
1152 public Container getCurrentFocusCycleRoot() {
1153 synchronized (KeyboardFocusManager.class) {
1154 if (currentFocusCycleRoot == null) {
1155 return null;
1156 }
1157
1158 return (currentFocusCycleRoot.appContext ==
1159 AppContext.getAppContext())
1160 ? currentFocusCycleRoot
1161 : null;
1162 }
1163 }
1164
1165 /**
1166 * Returns the current focus cycle root, even if the calling thread is in a
1167 * different context than the current focus cycle root. If the focus owner
1168 * is itself a focus cycle root, then it may be ambiguous as to which
1169 * Components represent the next and previous Components to focus during
1170 * normal focus traversal. In that case, the current focus cycle root is
1171 * used to differentiate among the possibilities.
1172 * <p>
1173 * This method will throw a SecurityException if this KeyboardFocusManager
1174 * is not the current KeyboardFocusManager for the calling thread's
1175 * context.
1176 *
1177 * @return the current focus cycle root, or null if the current focus cycle
1178 * root is not a member of the calling thread's context
1179 * @see #getCurrentFocusCycleRoot
1180 * @see #setGlobalCurrentFocusCycleRoot
1181 * @throws SecurityException if this KeyboardFocusManager is not the
1182 * current KeyboardFocusManager for the calling thread's context
1183 */
1184 protected Container getGlobalCurrentFocusCycleRoot()
1185 throws SecurityException
1186 {
1187 synchronized (KeyboardFocusManager.class) {
1188 if (this == getCurrentKeyboardFocusManager()) {
1189 return currentFocusCycleRoot;
1190 } else {
1191 if (focusLog.isLoggable(Level.FINER)) {
1192 focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
1193 }
1194 throw new SecurityException(notPrivileged);
1195 }
1196 }
1197 }
1198
1199 /**
1200 * Sets the current focus cycle root. If the focus owner is itself a focus
1201 * cycle root, then it may be ambiguous as to which Components represent
1202 * the next and previous Components to focus during normal focus traversal.
1203 * In that case, the current focus cycle root is used to differentiate
1204 * among the possibilities.
1205 * <p>
1206 * This method is intended to be used only by KeyboardFocusManagers and
1207 * focus implementations. It is not for general client use.
1208 *
1209 * @param newFocusCycleRoot the new focus cycle root
1210 * @see #getCurrentFocusCycleRoot
1211 * @see #getGlobalCurrentFocusCycleRoot
1212 * @beaninfo
1213 * bound: true
1214 */
1215 public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
1216 Container oldFocusCycleRoot;
1217
1218 synchronized (KeyboardFocusManager.class) {
1219 oldFocusCycleRoot = getCurrentFocusCycleRoot();
1220 currentFocusCycleRoot = newFocusCycleRoot;
1221 }
1222
1223 firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
1224 newFocusCycleRoot);
1225 }
1226
1227 /**
1228 * Adds a PropertyChangeListener to the listener list. The listener is
1229 * registered for all bound properties of this class, including the
1230 * following:
1231 * <ul>
1232 * <li>whether the KeyboardFocusManager is currently managing focus
1233 * for this application or applet's browser context
1234 * ("managingFocus")</li>
1235 * <li>the focus owner ("focusOwner")</li>
1236 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1237 * <li>the focused Window ("focusedWindow")</li>
1238 * <li>the active Window ("activeWindow")</li>
1239 * <li>the default focus traversal policy
1240 * ("defaultFocusTraversalPolicy")</li>
1241 * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1242 * ("forwardDefaultFocusTraversalKeys")</li>
1243 * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1244 * ("backwardDefaultFocusTraversalKeys")</li>
1245 * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1246 * ("upCycleDefaultFocusTraversalKeys")</li>
1247 * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1248 * ("downCycleDefaultFocusTraversalKeys")</li>
1249 * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1250 * </ul>
1251 * If listener is null, no exception is thrown and no action is performed.
1252 *
1253 * @param listener the PropertyChangeListener to be added
1254 * @see #removePropertyChangeListener
1255 * @see #getPropertyChangeListeners
1256 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1257 */
1258 public void addPropertyChangeListener(PropertyChangeListener listener) {
1259 if (listener != null) {
1260 synchronized (this) {
1261 if (changeSupport == null) {
1262 changeSupport = new PropertyChangeSupport(this);
1263 }
1264 changeSupport.addPropertyChangeListener(listener);
1265 }
1266 }
1267 }
1268
1269 /**
1270 * Removes a PropertyChangeListener from the listener list. This method
1271 * should be used to remove the PropertyChangeListeners that were
1272 * registered for all bound properties of this class.
1273 * <p>
1274 * If listener is null, no exception is thrown and no action is performed.
1275 *
1276 * @param listener the PropertyChangeListener to be removed
1277 * @see #addPropertyChangeListener
1278 * @see #getPropertyChangeListeners
1279 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1280 */
1281 public void removePropertyChangeListener(PropertyChangeListener listener) {
1282 if (listener != null) {
1283 synchronized (this) {
1284 if (changeSupport != null) {
1285 changeSupport.removePropertyChangeListener(listener);
1286 }
1287 }
1288 }
1289 }
1290
1291 /**
1292 * Returns an array of all the property change listeners
1293 * registered on this keyboard focus manager.
1294 *
1295 * @return all of this keyboard focus manager's
1296 * <code>PropertyChangeListener</code>s
1297 * or an empty array if no property change
1298 * listeners are currently registered
1299 *
1300 * @see #addPropertyChangeListener
1301 * @see #removePropertyChangeListener
1302 * @see #getPropertyChangeListeners(java.lang.String)
1303 * @since 1.4
1304 */
1305 public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
1306 if (changeSupport == null) {
1307 changeSupport = new PropertyChangeSupport(this);
1308 }
1309 return changeSupport.getPropertyChangeListeners();
1310 }
1311
1312 /**
1313 * Adds a PropertyChangeListener to the listener list for a specific
1314 * property. The specified property may be user-defined, or one of the
1315 * following:
1316 * <ul>
1317 * <li>whether the KeyboardFocusManager is currently managing focus
1318 * for this application or applet's browser context
1319 * ("managingFocus")</li>
1320 * <li>the focus owner ("focusOwner")</li>
1321 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1322 * <li>the focused Window ("focusedWindow")</li>
1323 * <li>the active Window ("activeWindow")</li>
1324 * <li>the default focus traversal policy
1325 * ("defaultFocusTraversalPolicy")</li>
1326 * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1327 * ("forwardDefaultFocusTraversalKeys")</li>
1328 * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1329 * ("backwardDefaultFocusTraversalKeys")</li>
1330 * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1331 * ("upCycleDefaultFocusTraversalKeys")</li>
1332 * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1333 * ("downCycleDefaultFocusTraversalKeys")</li>
1334 * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1335 * </ul>
1336 * If listener is null, no exception is thrown and no action is performed.
1337 *
1338 * @param propertyName one of the property names listed above
1339 * @param listener the PropertyChangeListener to be added
1340 * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
1341 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1342 * @see #getPropertyChangeListeners(java.lang.String)
1343 */
1344 public void addPropertyChangeListener(String propertyName,
1345 PropertyChangeListener listener) {
1346 if (listener != null) {
1347 synchronized (this) {
1348 if (changeSupport == null) {
1349 changeSupport = new PropertyChangeSupport(this);
1350 }
1351 changeSupport.addPropertyChangeListener(propertyName,
1352 listener);
1353 }
1354 }
1355 }
1356
1357 /**
1358 * Removes a PropertyChangeListener from the listener list for a specific
1359 * property. This method should be used to remove PropertyChangeListeners
1360 * that were registered for a specific bound property.
1361 * <p>
1362 * If listener is null, no exception is thrown and no action is performed.
1363 *
1364 * @param propertyName a valid property name
1365 * @param listener the PropertyChangeListener to be removed
1366 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1367 * @see #getPropertyChangeListeners(java.lang.String)
1368 * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
1369 */
1370 public void removePropertyChangeListener(String propertyName,
1371 PropertyChangeListener listener) {
1372 if (listener != null) {
1373 synchronized (this) {
1374 if (changeSupport != null) {
1375 changeSupport.removePropertyChangeListener(propertyName,
1376 listener);
1377 }
1378 }
1379 }
1380 }
1381
1382 /**
1383 * Returns an array of all the <code>PropertyChangeListener</code>s
1384 * associated with the named property.
1385 *
1386 * @return all of the <code>PropertyChangeListener</code>s associated with
1387 * the named property or an empty array if no such listeners have
1388 * been added.
1389 *
1390 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1391 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1392 * @since 1.4
1393 */
1394 public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
1395 if (changeSupport == null) {
1396 changeSupport = new PropertyChangeSupport(this);
1397 }
1398 return changeSupport.getPropertyChangeListeners(propertyName);
1399 }
1400
1401 /**
1402 * Fires a PropertyChangeEvent in response to a change in a bound property.
1403 * The event will be delivered to all registered PropertyChangeListeners.
1404 * No event will be delivered if oldValue and newValue are the same.
1405 *
1406 * @param propertyName the name of the property that has changed
1407 * @param oldValue the property's previous value
1408 * @param newValue the property's new value
1409 */
1410 protected void firePropertyChange(String propertyName, Object oldValue,
1411 Object newValue)
1412 {
1413 if (oldValue == newValue) {
1414 return;
1415 }
1416 PropertyChangeSupport changeSupport = this.changeSupport;
1417 if (changeSupport != null) {
1418 changeSupport.firePropertyChange(propertyName, oldValue, newValue);
1419 }
1420 }
1421
1422 /**
1423 * Adds a VetoableChangeListener to the listener list. The listener is
1424 * registered for all vetoable properties of this class, including the
1425 * following:
1426 * <ul>
1427 * <li>the focus owner ("focusOwner")</li>
1428 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1429 * <li>the focused Window ("focusedWindow")</li>
1430 * <li>the active Window ("activeWindow")</li>
1431 * </ul>
1432 * If listener is null, no exception is thrown and no action is performed.
1433 *
1434 * @param listener the VetoableChangeListener to be added
1435 * @see #removeVetoableChangeListener
1436 * @see #getVetoableChangeListeners
1437 * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1438 */
1439 public void addVetoableChangeListener(VetoableChangeListener listener) {
1440 if (listener != null) {
1441 synchronized (this) {
1442 if (vetoableSupport == null) {
1443 vetoableSupport =
1444 new VetoableChangeSupport(this);
1445 }
1446 vetoableSupport.addVetoableChangeListener(listener);
1447 }
1448 }
1449 }
1450
1451 /**
1452 * Removes a VetoableChangeListener from the listener list. This method
1453 * should be used to remove the VetoableChangeListeners that were
1454 * registered for all vetoable properties of this class.
1455 * <p>
1456 * If listener is null, no exception is thrown and no action is performed.
1457 *
1458 * @param listener the VetoableChangeListener to be removed
1459 * @see #addVetoableChangeListener
1460 * @see #getVetoableChangeListeners
1461 * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1462 */
1463 public void removeVetoableChangeListener(VetoableChangeListener listener) {
1464 if (listener != null) {
1465 synchronized (this) {
1466 if (vetoableSupport != null) {
1467 vetoableSupport.removeVetoableChangeListener(listener);
1468 }
1469 }
1470 }
1471 }
1472
1473 /**
1474 * Returns an array of all the vetoable change listeners
1475 * registered on this keyboard focus manager.
1476 *
1477 * @return all of this keyboard focus manager's
1478 * <code>VetoableChangeListener</code>s
1479 * or an empty array if no vetoable change
1480 * listeners are currently registered
1481 *
1482 * @see #addVetoableChangeListener
1483 * @see #removeVetoableChangeListener
1484 * @see #getVetoableChangeListeners(java.lang.String)
1485 * @since 1.4
1486 */
1487 public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
1488 if (vetoableSupport == null) {
1489 vetoableSupport = new VetoableChangeSupport(this);
1490 }
1491 return vetoableSupport.getVetoableChangeListeners();
1492 }
1493
1494 /**
1495 * Adds a VetoableChangeListener to the listener list for a specific
1496 * property. The specified property may be user-defined, or one of the
1497 * following:
1498 * <ul>
1499 * <li>the focus owner ("focusOwner")</li>
1500 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1501 * <li>the focused Window ("focusedWindow")</li>
1502 * <li>the active Window ("activeWindow")</li>
1503 * </ul>
1504 * If listener is null, no exception is thrown and no action is performed.
1505 *
1506 * @param propertyName one of the property names listed above
1507 * @param listener the VetoableChangeListener to be added
1508 * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
1509 * @see #removeVetoableChangeListener
1510 * @see #getVetoableChangeListeners
1511 */
1512 public void addVetoableChangeListener(String propertyName,
1513 VetoableChangeListener listener) {
1514 if (listener != null) {
1515 synchronized (this) {
1516 if (vetoableSupport == null) {
1517 vetoableSupport =
1518 new VetoableChangeSupport(this);
1519 }
1520 vetoableSupport.addVetoableChangeListener(propertyName,
1521 listener);
1522 }
1523 }
1524 }
1525
1526 /**
1527 * Removes a VetoableChangeListener from the listener list for a specific
1528 * property. This method should be used to remove VetoableChangeListeners
1529 * that were registered for a specific bound property.
1530 * <p>
1531 * If listener is null, no exception is thrown and no action is performed.
1532 *
1533 * @param propertyName a valid property name
1534 * @param listener the VetoableChangeListener to be removed
1535 * @see #addVetoableChangeListener
1536 * @see #getVetoableChangeListeners
1537 * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
1538 */
1539 public void removeVetoableChangeListener(String propertyName,
1540 VetoableChangeListener listener) {
1541 if (listener != null) {
1542 synchronized (this) {
1543 if (vetoableSupport != null) {
1544 vetoableSupport.removeVetoableChangeListener(propertyName,
1545 listener);
1546 }
1547 }
1548 }
1549 }
1550
1551 /**
1552 * Returns an array of all the <code>VetoableChangeListener</code>s
1553 * associated with the named property.
1554 *
1555 * @return all of the <code>VetoableChangeListener</code>s associated with
1556 * the named property or an empty array if no such listeners have
1557 * been added.
1558 *
1559 * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1560 * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1561 * @see #getVetoableChangeListeners
1562 * @since 1.4
1563 */
1564 public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
1565 if (vetoableSupport == null) {
1566 vetoableSupport = new VetoableChangeSupport(this);
1567 }
1568 return vetoableSupport.getVetoableChangeListeners(propertyName);
1569 }
1570
1571 /**
1572 * Fires a PropertyChangeEvent in response to a change in a vetoable
1573 * property. The event will be delivered to all registered
1574 * VetoableChangeListeners. If a VetoableChangeListener throws a
1575 * PropertyVetoException, a new event is fired reverting all
1576 * VetoableChangeListeners to the old value and the exception is then
1577 * rethrown. No event will be delivered if oldValue and newValue are the
1578 * same.
1579 *
1580 * @param propertyName the name of the property that has changed
1581 * @param oldValue the property's previous value
1582 * @param newValue the property's new value
1583 * @throws java.beans.PropertyVetoException if a
1584 * <code>VetoableChangeListener</code> threw
1585 * <code>PropertyVetoException</code>
1586 */
1587 protected void fireVetoableChange(String propertyName, Object oldValue,
1588 Object newValue)
1589 throws PropertyVetoException
1590 {
1591 if (oldValue == newValue) {
1592 return;
1593 }
1594 VetoableChangeSupport vetoableSupport =
1595 this.vetoableSupport;
1596 if (vetoableSupport != null) {
1597 vetoableSupport.fireVetoableChange(propertyName, oldValue,
1598 newValue);
1599 }
1600 }
1601
1602 /**
1603 * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
1604 * chain. This KeyboardFocusManager will request that each
1605 * KeyEventDispatcher dispatch KeyEvents generated by the user before
1606 * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
1607 * notified in the order in which they were added. Notifications will halt
1608 * as soon as one KeyEventDispatcher returns <code>true</code> from its
1609 * <code>dispatchKeyEvent</code> method. There is no limit to the total
1610 * number of KeyEventDispatchers which can be added, nor to the number of
1611 * times which a particular KeyEventDispatcher instance can be added.
1612 * <p>
1613 * If a null dispatcher is specified, no action is taken and no exception
1614 * is thrown.
1615 * <p>
1616 * In a multithreaded application, {@link KeyEventDispatcher} behaves
1617 * the same as other AWT listeners. See
1618 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1619 * >AWT Threading Issues</a> for more details.
1620 *
1621 * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
1622 * @see #removeKeyEventDispatcher
1623 */
1624 public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1625 if (dispatcher != null) {
1626 synchronized (this) {
1627 if (keyEventDispatchers == null) {
1628 keyEventDispatchers = new java.util.LinkedList();
1629 }
1630 keyEventDispatchers.add(dispatcher);
1631 }
1632 }
1633 }
1634
1635 /**
1636 * Removes a KeyEventDispatcher which was previously added to this
1637 * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
1638 * cannot itself be removed, unless it was explicitly re-registered via a
1639 * call to <code>addKeyEventDispatcher</code>.
1640 * <p>
1641 * If a null dispatcher is specified, if the specified dispatcher is not
1642 * in the dispatcher chain, or if this KeyboardFocusManager is specified
1643 * without having been explicitly re-registered, no action is taken and no
1644 * exception is thrown.
1645 * <p>
1646 * In a multithreaded application, {@link KeyEventDispatcher} behaves
1647 * the same as other AWT listeners. See
1648 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1649 * >AWT Threading Issues</a> for more details.
1650 *
1651 * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
1652 * chain
1653 * @see #addKeyEventDispatcher
1654 */
1655 public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1656 if (dispatcher != null) {
1657 synchronized (this) {
1658 if (keyEventDispatchers != null) {
1659 keyEventDispatchers.remove(dispatcher);
1660 }
1661 }
1662 }
1663 }
1664
1665 /**
1666 * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
1667 * The List will not include this KeyboardFocusManager unless it was
1668 * explicitly re-registered via a call to
1669 * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
1670 * registered, implementations are free to return null or a List of length
1671 * 0. Client code should not assume one behavior over another, nor should
1672 * it assume that the behavior, once established, will not change.
1673 *
1674 * @return a possibly null or empty List of KeyEventDispatchers
1675 * @see #addKeyEventDispatcher
1676 * @see #removeKeyEventDispatcher
1677 */
1678 protected synchronized java.util.List<KeyEventDispatcher>
1679 getKeyEventDispatchers()
1680 {
1681 return (keyEventDispatchers != null)
1682 ? (java.util.List)keyEventDispatchers.clone()
1683 : null;
1684 }
1685
1686 /**
1687 * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
1688 * processor chain. After a KeyEvent has been dispatched to and handled by
1689 * its target, KeyboardFocusManager will request that each
1690 * KeyEventPostProcessor perform any necessary post-processing as part
1691 * of the KeyEvent's final resolution. KeyEventPostProcessors
1692 * will be notified in the order in which they were added; the current
1693 * KeyboardFocusManager will be notified last. Notifications will halt
1694 * as soon as one KeyEventPostProcessor returns <code>true</code> from its
1695 * <code>postProcessKeyEvent</code> method. There is no limit to the the
1696 * total number of KeyEventPostProcessors that can be added, nor to the
1697 * number of times that a particular KeyEventPostProcessor instance can be
1698 * added.
1699 * <p>
1700 * If a null post-processor is specified, no action is taken and no
1701 * exception is thrown.
1702 * <p>
1703 * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1704 * the same as other AWT listeners. See
1705 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1706 * >AWT Threading Issues</a> for more details.
1707 *
1708 * @param processor the KeyEventPostProcessor to add to the post-processor
1709 * chain
1710 * @see #removeKeyEventPostProcessor
1711 */
1712 public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
1713 if (processor != null) {
1714 synchronized (this) {
1715 if (keyEventPostProcessors == null) {
1716 keyEventPostProcessors = new java.util.LinkedList();
1717 }
1718 keyEventPostProcessors.add(processor);
1719 }
1720 }
1721 }
1722
1723
1724 /**
1725 * Removes a previously added KeyEventPostProcessor from this
1726 * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
1727 * cannot itself be entirely removed from the chain. Only additional
1728 * references added via <code>addKeyEventPostProcessor</code> can be
1729 * removed.
1730 * <p>
1731 * If a null post-processor is specified, if the specified post-processor
1732 * is not in the post-processor chain, or if this KeyboardFocusManager is
1733 * specified without having been explicitly added, no action is taken and
1734 * no exception is thrown.
1735 * <p>
1736 * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1737 * the same as other AWT listeners. See
1738 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1739 * >AWT Threading Issues</a> for more details.
1740 *
1741 * @param processor the KeyEventPostProcessor to remove from the post-
1742 * processor chain
1743 * @see #addKeyEventPostProcessor
1744 */
1745 public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
1746 if (processor != null) {
1747 synchronized (this) {
1748 if (keyEventPostProcessors != null) {
1749 keyEventPostProcessors.remove(processor);
1750 }
1751 }
1752 }
1753 }
1754
1755
1756 /**
1757 * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
1758 * List. The List will not include this KeyboardFocusManager unless it was
1759 * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
1760 * no KeyEventPostProcessors are registered, implementations are free to
1761 * return null or a List of length 0. Client code should not assume one
1762 * behavior over another, nor should it assume that the behavior, once
1763 * established, will not change.
1764 *
1765 * @return a possibly null or empty List of KeyEventPostProcessors
1766 * @see #addKeyEventPostProcessor
1767 * @see #removeKeyEventPostProcessor
1768 */
1769 protected java.util.List<KeyEventPostProcessor>
1770 getKeyEventPostProcessors()
1771 {
1772 return (keyEventPostProcessors != null)
1773 ? (java.util.List)keyEventPostProcessors.clone()
1774 : null;
1775 }
1776
1777
1778
1779 static void setMostRecentFocusOwner(Component component) {
1780 Component window = component;
1781 while (window != null && !(window instanceof Window)) {
1782 window = window.parent;
1783 }
1784 if (window != null) {
1785 setMostRecentFocusOwner((Window)window, component);
1786 }
1787 }
1788 static synchronized void setMostRecentFocusOwner(Window window,
1789 Component component) {
1790 // ATTN: component has a strong reference to window via chain
1791 // of Component.parent fields. Since WeakHasMap refers to its
1792 // values strongly, we need to break the strong link from the
1793 // value (component) back to its key (window).
1794 WeakReference weakValue = null;
1795 if (component != null) {
1796 weakValue = new WeakReference(component);
1797 }
1798 mostRecentFocusOwners.put(window, weakValue);
1799 }
1800 static void clearMostRecentFocusOwner(Component comp) {
1801 Container window;
1802
1803 if (comp == null) {
1804 return;
1805 }
1806
1807 synchronized (comp.getTreeLock()) {
1808 window = comp.getParent();
1809 while (window != null && !(window instanceof Window)) {
1810 window = window.getParent();
1811 }
1812 }
1813
1814 synchronized (KeyboardFocusManager.class) {
1815 if ((window != null)
1816 && (getMostRecentFocusOwner((Window)window) == comp))
1817 {
1818 setMostRecentFocusOwner((Window)window, null);
1819 }
1820 // Also clear temporary lost component stored in Window
1821 if (window != null) {
1822 Window realWindow = (Window)window;
1823 if (realWindow.getTemporaryLostComponent() == comp) {
1824 realWindow.setTemporaryLostComponent(null);
1825 }
1826 }
1827 }
1828 }
1829
1830 /*
1831 * Please be careful changing this method! It is called from
1832 * javax.swing.JComponent.runInputVerifier() using reflection.
1833 */
1834 static synchronized Component getMostRecentFocusOwner(Window window) {
1835 WeakReference weakValue =
1836 (WeakReference)mostRecentFocusOwners.get(window);
1837 return weakValue == null ? null : (Component)weakValue.get();
1838 }
1839
1840 /**
1841 * This method is called by the AWT event dispatcher requesting that the
1842 * current KeyboardFocusManager dispatch the specified event on its behalf.
1843 * It is expected that all KeyboardFocusManagers will dispatch all
1844 * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
1845 * These events should be dispatched based on the KeyboardFocusManager's
1846 * notion of the focus owner and the focused and active Windows, sometimes
1847 * overriding the source of the specified AWTEvent. Dispatching must be
1848 * done using <code>redispatchEvent</code> to prevent the AWT event
1849 * dispatcher from recursively requesting that the KeyboardFocusManager
1850 * dispatch the event again. If this method returns <code>false</code>,
1851 * then the AWT event dispatcher will attempt to dispatch the event itself.
1852 *
1853 * @param e the AWTEvent to be dispatched
1854 * @return <code>true</code> if this method dispatched the event;
1855 * <code>false</code> otherwise
1856 * @see #redispatchEvent
1857 * @see #dispatchKeyEvent
1858 */
1859 public abstract boolean dispatchEvent(AWTEvent e);
1860
1861 /**
1862 * Redispatches an AWTEvent in such a way that the AWT event dispatcher
1863 * will not recursively request that the KeyboardFocusManager, or any
1864 * installed KeyEventDispatchers, dispatch the event again. Client
1865 * implementations of <code>dispatchEvent</code> and client-defined
1866 * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
1867 * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
1868 * <p>
1869 * This method is intended to be used only by KeyboardFocusManagers and
1870 * KeyEventDispatchers. It is not for general client use.
1871 *
1872 * @param target the Component to which the event should be dispatched
1873 * @param e the event to dispatch
1874 * @see #dispatchEvent
1875 * @see KeyEventDispatcher
1876 */
1877 public final void redispatchEvent(Component target, AWTEvent e) {
1878 e.focusManagerIsDispatching = true;
1879 target.dispatchEvent(e);
1880 e.focusManagerIsDispatching = false;
1881 }
1882
1883 /**
1884 * Typically this method will be called by <code>dispatchEvent</code> if no
1885 * other KeyEventDispatcher in the dispatcher chain dispatched the
1886 * KeyEvent, or if no other KeyEventDispatchers are registered. If an
1887 * implementation of this method returns <code>false</code>,
1888 * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
1889 * may simply return <code>false</code>. If <code>true</code> is returned,
1890 * <code>dispatchEvent</code> should return <code>true</code> as well.
1891 *
1892 * @param e the KeyEvent which the current KeyboardFocusManager has
1893 * requested that this KeyEventDispatcher dispatch
1894 * @return <code>true</code> if the KeyEvent was dispatched;
1895 * <code>false</code> otherwise
1896 * @see #dispatchEvent
1897 */
1898 public abstract boolean dispatchKeyEvent(KeyEvent e);
1899
1900 /**
1901 * This method will be called by <code>dispatchKeyEvent</code>.
1902 * By default, this method will handle any unconsumed KeyEvents that
1903 * map to an AWT <code>MenuShortcut</code> by consuming the event
1904 * and activating the shortcut.
1905 *
1906 * @param e the KeyEvent to post-process
1907 * @return <code>true</code> to indicate that no other
1908 * KeyEventPostProcessor will be notified of the KeyEvent.
1909 * @see #dispatchKeyEvent
1910 * @see MenuShortcut
1911 */
1912 public abstract boolean postProcessKeyEvent(KeyEvent e);
1913
1914 /**
1915 * This method initiates a focus traversal operation if and only if the
1916 * KeyEvent represents a focus traversal key for the specified
1917 * focusedComponent. It is expected that focusedComponent is the current
1918 * focus owner, although this need not be the case. If it is not,
1919 * focus traversal will nevertheless proceed as if focusedComponent
1920 * were the current focus owner.
1921 *
1922 * @param focusedComponent the Component that will be the basis for a focus
1923 * traversal operation if the specified event represents a focus
1924 * traversal key for the Component
1925 * @param e the event that may represent a focus traversal key
1926 */
1927 public abstract void processKeyEvent(Component focusedComponent,
1928 KeyEvent e);
1929
1930 /**
1931 * Called by the AWT to notify the KeyboardFocusManager that it should
1932 * delay dispatching of KeyEvents until the specified Component becomes
1933 * the focus owner. If client code requests a focus change, and the AWT
1934 * determines that this request might be granted by the native windowing
1935 * system, then the AWT will call this method. It is the responsibility of
1936 * the KeyboardFocusManager to delay dispatching of KeyEvents with
1937 * timestamps later than the specified time stamp until the specified
1938 * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
1939 * request by invoking <code>dequeueKeyEvents</code> or
1940 * <code>discardKeyEvents</code>.
1941 *
1942 * @param after timestamp of current event, or the current, system time if
1943 * the current event has no timestamp, or the AWT cannot determine
1944 * which event is currently being handled
1945 * @param untilFocused Component which should receive a FOCUS_GAINED event
1946 * before any pending KeyEvents
1947 * @see #dequeueKeyEvents
1948 * @see #discardKeyEvents
1949 */
1950 protected abstract void enqueueKeyEvents(long after,
1951 Component untilFocused);
1952
1953 /**
1954 * Called by the AWT to notify the KeyboardFocusManager that it should
1955 * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1956 * enqueued because of a call to <code>enqueueKeyEvents</code> with the
1957 * same timestamp and Component should be released for normal dispatching
1958 * to the current focus owner. If the given timestamp is less than zero,
1959 * the outstanding enqueue request for the given Component with the <b>
1960 * oldest</b> timestamp (if any) should be cancelled.
1961 *
1962 * @param after the timestamp specified in the call to
1963 * <code>enqueueKeyEvents</code>, or any value < 0
1964 * @param untilFocused the Component specified in the call to
1965 * <code>enqueueKeyEvents</code>
1966 * @see #enqueueKeyEvents
1967 * @see #discardKeyEvents
1968 */
1969 protected abstract void dequeueKeyEvents(long after,
1970 Component untilFocused);
1971
1972 /**
1973 * Called by the AWT to notify the KeyboardFocusManager that it should
1974 * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1975 * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
1976 * with the same Component should be discarded.
1977 *
1978 * @param comp the Component specified in one or more calls to
1979 * <code>enqueueKeyEvents</code>
1980 * @see #enqueueKeyEvents
1981 * @see #dequeueKeyEvents
1982 */
1983 protected abstract void discardKeyEvents(Component comp);
1984
1985 /**
1986 * Focuses the Component after aComponent, typically based on a
1987 * FocusTraversalPolicy.
1988 *
1989 * @param aComponent the Component that is the basis for the focus
1990 * traversal operation
1991 * @see FocusTraversalPolicy
1992 */
1993 public abstract void focusNextComponent(Component aComponent);
1994
1995 /**
1996 * Focuses the Component before aComponent, typically based on a
1997 * FocusTraversalPolicy.
1998 *
1999 * @param aComponent the Component that is the basis for the focus
2000 * traversal operation
2001 * @see FocusTraversalPolicy
2002 */
2003 public abstract void focusPreviousComponent(Component aComponent);
2004
2005 /**
2006 * Moves the focus up one focus traversal cycle. Typically, the focus owner
2007 * is set to aComponent's focus cycle root, and the current focus cycle
2008 * root is set to the new focus owner's focus cycle root. If, however,
2009 * aComponent's focus cycle root is a Window, then typically the focus
2010 * owner is set to the Window's default Component to focus, and the current
2011 * focus cycle root is unchanged.
2012 *
2013 * @param aComponent the Component that is the basis for the focus
2014 * traversal operation
2015 */
2016 public abstract void upFocusCycle(Component aComponent);
2017
2018 /**
2019 * Moves the focus down one focus traversal cycle. Typically, if
2020 * aContainer is a focus cycle root, then the focus owner is set to
2021 * aContainer's default Component to focus, and the current focus cycle
2022 * root is set to aContainer. If aContainer is not a focus cycle root, then
2023 * no focus traversal operation occurs.
2024 *
2025 * @param aContainer the Container that is the basis for the focus
2026 * traversal operation
2027 */
2028 public abstract void downFocusCycle(Container aContainer);
2029
2030 /**
2031 * Focuses the Component after the current focus owner.
2032 */
2033 public final void focusNextComponent() {
2034 Component focusOwner = getFocusOwner();
2035 if (focusOwner != null) {
2036 focusNextComponent(focusOwner);
2037 }
2038 }
2039
2040 /**
2041 * Focuses the Component before the current focus owner.
2042 */
2043 public final void focusPreviousComponent() {
2044 Component focusOwner = getFocusOwner();
2045 if (focusOwner != null) {
2046 focusPreviousComponent(focusOwner);
2047 }
2048 }
2049
2050 /**
2051 * Moves the focus up one focus traversal cycle from the current focus
2052 * owner. Typically, the new focus owner is set to the current focus
2053 * owner's focus cycle root, and the current focus cycle root is set to the
2054 * new focus owner's focus cycle root. If, however, the current focus
2055 * owner's focus cycle root is a Window, then typically the focus owner is
2056 * set to the focus cycle root's default Component to focus, and the
2057 * current focus cycle root is unchanged.
2058 */
2059 public final void upFocusCycle() {
2060 Component focusOwner = getFocusOwner();
2061 if (focusOwner != null) {
2062 upFocusCycle(focusOwner);
2063 }
2064 }
2065
2066 /**
2067 * Moves the focus down one focus traversal cycle from the current focus
2068 * owner, if and only if the current focus owner is a Container that is a
2069 * focus cycle root. Typically, the focus owner is set to the current focus
2070 * owner's default Component to focus, and the current focus cycle root is
2071 * set to the current focus owner. If the current focus owner is not a
2072 * Container that is a focus cycle root, then no focus traversal operation
2073 * occurs.
2074 */
2075 public final void downFocusCycle() {
2076 Component focusOwner = getFocusOwner();
2077 if (focusOwner instanceof Container) {
2078 downFocusCycle((Container)focusOwner);
2079 }
2080 }
2081
2082 /**
2083 * Dumps the list of focus requests to stderr
2084 */
2085 void dumpRequests() {
2086 System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
2087 synchronized (heavyweightRequests) {
2088 for (HeavyweightFocusRequest req : heavyweightRequests) {
2089 System.err.println(">>> Req: " + req);
2090 }
2091 }
2092 System.err.println("");
2093 }
2094
2095 private static final class LightweightFocusRequest {
2096 final Component component;
2097 final boolean temporary;
2098 final CausedFocusEvent.Cause cause;
2099
2100 LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
2101 this.component = component;
2102 this.temporary = temporary;
2103 this.cause = cause;
2104 }
2105 public String toString() {
2106 return "LightweightFocusRequest[component=" + component +
2107 ",temporary=" + temporary + ", cause=" + cause + "]";
2108 }
2109 }
2110
2111 private static final class HeavyweightFocusRequest {
2112 final Component heavyweight;
2113 final LinkedList<LightweightFocusRequest> lightweightRequests;
2114
2115 static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
2116 new HeavyweightFocusRequest();
2117
2118 private HeavyweightFocusRequest() {
2119 heavyweight = null;
2120 lightweightRequests = null;
2121 }
2122
2123 HeavyweightFocusRequest(Component heavyweight, Component descendant,
2124 boolean temporary, CausedFocusEvent.Cause cause) {
2125 if (log.isLoggable(Level.FINE)) {
2126 if (heavyweight == null) {
2127 log.log(Level.FINE, "Assertion (heavyweight != null) failed");
2128 }
2129 }
2130
2131 this.heavyweight = heavyweight;
2132 this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
2133 addLightweightRequest(descendant, temporary, cause);
2134 }
2135 boolean addLightweightRequest(Component descendant,
2136 boolean temporary, CausedFocusEvent.Cause cause) {
2137 if (log.isLoggable(Level.FINE)) {
2138 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2139 log.log(Level.FINE, "Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
2140 }
2141 if (descendant == null) {
2142 log.log(Level.FINE, "Assertion (descendant != null) failed");
2143 }
2144 }
2145
2146 Component lastDescendant = ((lightweightRequests.size() > 0)
2147 ? lightweightRequests.getLast().component
2148 : null);
2149
2150 if (descendant != lastDescendant) {
2151 // Not a duplicate request
2152 lightweightRequests.add
2153 (new LightweightFocusRequest(descendant, temporary, cause));
2154 return true;
2155 } else {
2156 return false;
2157 }
2158 }
2159
2160 LightweightFocusRequest getFirstLightweightRequest() {
2161 if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
2162 return null;
2163 }
2164 return lightweightRequests.getFirst();
2165 }
2166 public String toString() {
2167 boolean first = true;
2168 String str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
2169 ",lightweightRequests=";
2170 if (lightweightRequests == null) {
2171 str += null;
2172 } else {
2173 str += "[";
2174
2175 for (LightweightFocusRequest lwRequest : lightweightRequests) {
2176 if (first) {
2177 first = false;
2178 } else {
2179 str += ",";
2180 }
2181 str += lwRequest;
2182 }
2183 str += "]";
2184 }
2185 str += "]";
2186 return str;
2187 }
2188 }
2189
2190 /*
2191 * heavyweightRequests is used as a monitor for synchronized changes of
2192 * currentLightweightRequests, clearingCurrentLightweightRequests and
2193 * newFocusOwner.
2194 */
2195 private static LinkedList<HeavyweightFocusRequest> heavyweightRequests =
2196 new LinkedList<HeavyweightFocusRequest>();
2197 private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
2198 private static boolean clearingCurrentLightweightRequests;
2199 private static boolean allowSyncFocusRequests = true;
2200 private static Component newFocusOwner = null;
2201 p