Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / java / awt / KeyboardFocusManager.java
blob6ea213e3a786bbcde88807bb84ce69c7ae869d5e
1 /* KeyboardFocusManager.java -- manage component focusing via the keyboard
2 Copyright (C) 2002, 2004 Free Software Foundation
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package java.awt;
41 import java.awt.event.FocusEvent;
42 import java.awt.event.KeyEvent;
43 import java.beans.PropertyChangeListener;
44 import java.beans.PropertyChangeSupport;
45 import java.beans.PropertyVetoException;
46 import java.beans.VetoableChangeListener;
47 import java.beans.VetoableChangeSupport;
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.Collections;
51 import java.util.HashMap;
52 import java.util.HashSet;
53 import java.util.Iterator;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Set;
58 /**
59 * The <code>KeyboardFocusManager</code> handles the focusing of
60 * windows for receiving keyboard events. The manager handles
61 * the dispatch of all <code>FocusEvent</code>s and
62 * <code>KeyEvent</code>s, along with <code>WindowEvent</code>s
63 * relating to the focused window. Users can use the manager
64 * to ascertain the current focus owner and fire events.
65 * <br />
66 * <br />
67 * The focus owner is the <code>Component</code> that receives
68 * key events. The focus owner is either the currently focused
69 * window or a component within this window.
70 * <br />
71 * <br />
72 * The underlying native windowing system may denote the active
73 * window or its children with special decorations (e.g. a highlighted
74 * title bar). The active window is always either a <code>Frame</code>
75 * or <code>Dialog</code>, and is either the currently focused
76 * window or its owner.
77 * <br />
78 * <br />
79 * Applets may be partitioned into different applet contexts, according
80 * to their code base. In this case, each context has its own
81 * <code>KeyboardFocusManager</code>, as opposed to the global
82 * manager maintained by applets which share the same context.
83 * Each context is insulated from the others, and they don't interact.
84 * The resulting behaviour, as with context division, depends on the browser
85 * supporting the applets. Regardless, there can only ever be
86 * one focused window, one active window and one focus owner
87 * per <code>ClassLoader</code>.
88 * <br />
89 * <br />
90 * To support this separation of focus managers, the manager instances
91 * and the internal state information is grouped by the
92 * <code>ThreadGroup</code> to which it pertains. With respect to
93 * applets, each code base has its own <code>ThreadGroup</code>, so the
94 * isolation of each context is enforced within the manager.
95 * <br />
96 * <br />
97 * By default, the manager defines TAB and Ctrl+TAB as the
98 * forward focus traversal keys and Shift+TAB and Ctrl+Shift+TAB
99 * as the backward focus traversal keys. No up or down cycle
100 * traversal keys are defined by default. Traversal takes effect
101 * on the firing of a relevant <code>KEY_PRESSED</code> event.
102 * However, all other key events related to the use of the
103 * defined focus traversal key sequence are consumed and not
104 * dispatched.
105 * <br />
106 * <br />
107 * These default traversal keys come into effect on all windows
108 * for which no alternative set of keys is defined. This also
109 * applies recursively to any child components of such a window,
110 * which define no traversal keys of their own.
112 * @author Eric Blake (ebb9@email.byu.edu)
113 * @author Thomas Fitzsimmons (fitzsim@redhat.com)
114 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
115 * @since 1.4
117 public abstract class KeyboardFocusManager
118 implements KeyEventDispatcher, KeyEventPostProcessor
120 /** Identifies {@link AWTKeyStroke}s that move the focus forward in
121 the focus cycle. */
122 public static final int FORWARD_TRAVERSAL_KEYS = 0;
124 /** Identifies {@link AWTKeyStroke}s that move the focus backward in
125 the focus cycle. */
126 public static final int BACKWARD_TRAVERSAL_KEYS = 1;
128 /** Identifies {@link AWTKeyStroke}s that move the focus up to the
129 parent focus cycle root. */
130 public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
132 /** Identifies {@link AWTKeyStroke}s that move the focus down to the
133 child focus cycle root. */
134 public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
136 /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
137 the next focusable Component in the focus cycle. */
138 private static final Set DEFAULT_FORWARD_KEYS;
140 /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
141 the previous focusable Component in the focus cycle. */
142 private static final Set DEFAULT_BACKWARD_KEYS;
144 /** Populate the DEFAULT_FORWARD_KEYS and DEFAULT_BACKWARD_KEYS
145 {@link java.util.Set}s. */
146 static
148 Set s = new HashSet();
149 s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
150 s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
151 KeyEvent.CTRL_DOWN_MASK));
152 DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
153 s = new HashSet();
154 s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
155 KeyEvent.SHIFT_DOWN_MASK));
156 s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
157 KeyEvent.SHIFT_DOWN_MASK
158 | KeyEvent.CTRL_DOWN_MASK));
159 DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
162 /** The global object {@link java.util.Map}s. */
164 /** For security reasons, {@link java.applet.Applet}s in different
165 codebases must be insulated from one another. Since {@link
166 KeyboardFocusManager}s have the ability to return {@link
167 Component}s from a given {@link java.applet.Applet}, each
168 codebase must have an independent {@link KeyboardFocusManager}.
169 Since each codebase has its own {@link ThreadGroup} in which its
170 {@link Applet}s run, it makes sense to partition {@link
171 KeyboardFocusManager}s according to {@link
172 java.lang.ThreadGroup}. Thus, currentKeyboardFocusManagers is a
173 {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}. */
174 private static Map currentKeyboardFocusManagers = new HashMap ();
176 /** {@link java.applet.Applet}s in one codebase must not be allowed
177 to access {@link Component}s in {@link java.applet.Applet}s in
178 other codebases. To enforce this restriction, we key the
179 following {@link java.util.Map}s on {@link java.lang.ThreadGroup}s (which
180 are per-codebase). For example, if {@link
181 java.lang.ThreadGroup} A calls {@link #setGlobalFocusOwner},
182 passing {@link Component} C, currentFocusOwners[A] is assigned
183 C, and all other currentFocusOwners values are nullified. Then
184 if {@link java.lang.ThreadGroup} A subsequently calls {@link
185 #getGlobalFocusOwner}, it will return currentFocusOwners[A],
186 that is, {@link Component} C. If another {@link
187 java.lang.ThreadGroup} K calls {@link #getGlobalFocusOwner}, it
188 will return currentFocusOwners[K], that is, null.
190 Since this is a static field, we ensure that there is only one
191 focused {@link Component} per class loader. */
192 private static Map currentFocusOwners = new HashMap ();
194 /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
195 that stores the {@link Component} that owns the permanent
196 keyboard focus. @see currentFocusOwners */
197 private static Map currentPermanentFocusOwners = new HashMap ();
199 /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
200 that stores the focused {@link Window}. @see
201 currentFocusOwners */
202 private static Map currentFocusedWindows = new HashMap ();
204 /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
205 that stores the active {@link Window}. @see
206 currentFocusOwners */
207 private static Map currentActiveWindows = new HashMap ();
209 /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
210 that stores the focus cycle root {@link Container}. @see
211 currentFocusOwners */
212 private static Map currentFocusCycleRoots = new HashMap ();
214 /** The default {@link FocusTraveralPolicy} that focus-managing
215 {@link Container}s will use to define their initial focus
216 traversal policy. */
217 private FocusTraversalPolicy defaultPolicy;
219 /** An array that stores the {@link #FORWARD_TRAVERSAL_KEYS}, {@link
220 #BACKWARD_TRAVERSAL_KEYS}, {@link #UP_CYCLE_TRAVERSAL_KEYS} and
221 {@link #DOWN_CYCLE_TRAVERSAL_KEYS} {@link AWTKeyStroke}s {@link
222 java.util.Set}s. */
223 private Set[] defaultFocusKeys = new Set[]
225 DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS,
226 Collections.EMPTY_SET, Collections.EMPTY_SET
230 * A utility class to support the handling of events relating to property changes.
232 private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this);
235 * A utility class to support the handling of events relating to vetoable changes.
237 private final VetoableChangeSupport vetoableChangeSupport = new VetoableChangeSupport (this);
239 /** A list of {@link KeyEventDispatcher}s that process {@link
240 KeyEvent}s before they are processed the default keyboard focus
241 manager. */
242 private final ArrayList keyEventDispatchers = new ArrayList();
244 /** A list of {@link KeyEventPostProcessor}s that process unconsumed
245 {@link KeyEvent}s. */
246 private final ArrayList keyEventPostProcessors = new ArrayList();
249 * Construct a KeyboardFocusManager.
251 public KeyboardFocusManager ()
256 * Retrieve the keyboard focus manager associated with the {@link
257 * java.lang.ThreadGroup} to which the calling thread belongs.
259 * @return the keyboard focus manager associated with the current
260 * thread group
262 public static KeyboardFocusManager getCurrentKeyboardFocusManager ()
264 ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
266 if (currentKeyboardFocusManagers.get (currentGroup) == null)
267 setCurrentKeyboardFocusManager (null);
269 return (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
273 * Set the keyboard focus manager associated with the {@link
274 * java.lang.ThreadGroup} to which the calling thread belongs.
276 * @param m the keyboard focus manager for the current thread group
278 public static void setCurrentKeyboardFocusManager (KeyboardFocusManager m)
280 SecurityManager sm = System.getSecurityManager ();
281 if (sm != null)
282 sm.checkPermission (new AWTPermission ("replaceKeyboardFocusManager"));
284 ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
285 KeyboardFocusManager manager;
287 if (m == null)
288 manager = new DefaultKeyboardFocusManager ();
289 else
290 manager = m;
292 currentKeyboardFocusManagers.put (currentGroup, manager);
296 * Retrieve the {@link Component} that has the keyboard focus, or
297 * null if the focus owner was not set by a thread in the current
298 * {@link java.lang.ThreadGroup}.
300 * @return the keyboard focus owner or null
302 public Component getFocusOwner ()
304 Component owner = (Component) getObject (currentFocusOwners);
305 if (owner == null)
306 owner = (Component) getObject (currentPermanentFocusOwners);
307 return owner;
311 * Retrieve the {@link Component} that has the keyboard focus,
312 * regardless of whether or not it was set by a thread in the
313 * current {@link java.lang.ThreadGroup}. If there is no temporary
314 * focus owner in effect then this method will return the same value
315 * as {@link #getGlobalPermanentFocusOwner}.
317 * @return the keyboard focus owner
318 * @throws SecurityException if this is not the keyboard focus
319 * manager associated with the current {@link java.lang.ThreadGroup}
321 protected Component getGlobalFocusOwner ()
323 // Check if there is a temporary focus owner.
324 Component focusOwner = (Component) getGlobalObject (currentFocusOwners);
326 return (focusOwner == null) ? getGlobalPermanentFocusOwner () : focusOwner;
330 * Set the {@link Component} that will be returned by {@link
331 * #getFocusOwner} (when it is called from the current {@link
332 * java.lang.ThreadGroup}) and {@link #getGlobalFocusOwner}. This
333 * method does not actually transfer the keyboard focus.
335 * @param owner the Component to return from getFocusOwner and
336 * getGlobalFocusOwner
338 * @see Component.requestFocus ()
339 * @see Component.requestFocusInWindow ()
341 protected void setGlobalFocusOwner (Component owner)
343 if (owner == null || owner.focusable)
344 setGlobalObject (currentFocusOwners, owner, "focusOwner");
348 * Clear the global focus owner and deliver a FOCUS_LOST event to
349 * the previously-focused {@link Component}. Until another {@link
350 * Component} becomes the keyboard focus owner, key events will be
351 * discarded by top-level windows.
353 public void clearGlobalFocusOwner ()
355 synchronized (currentFocusOwners)
357 Component focusOwner = getGlobalFocusOwner ();
358 Component permanentFocusOwner = getGlobalPermanentFocusOwner ();
360 setGlobalFocusOwner (null);
361 setGlobalPermanentFocusOwner (null);
363 // Inform the old focus owner that it has lost permanent
364 // focus.
365 if (focusOwner != null)
367 // We can't cache the event queue, because of
368 // bootstrapping issues. We need to set the default
369 // KeyboardFocusManager in EventQueue before the event
370 // queue is started.
371 EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
372 if (focusOwner != permanentFocusOwner)
373 q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, true));
374 else
375 q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, false));
378 if (focusOwner != permanentFocusOwner)
380 EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
381 q.postEvent (new FocusEvent (permanentFocusOwner, FocusEvent.FOCUS_LOST, false));
387 * Retrieve the {@link Component} that has the permanent keyboard
388 * focus, or null if the focus owner was not set by a thread in the
389 * current {@link java.lang.ThreadGroup}.
391 * @return the keyboard focus owner or null
393 public Component getPermanentFocusOwner ()
395 return (Component) getObject (currentPermanentFocusOwners);
399 * Retrieve the {@link Component} that has the permanent keyboard
400 * focus, regardless of whether or not it was set by a thread in the
401 * current {@link java.lang.ThreadGroup}.
403 * @return the keyboard focus owner
404 * @throws SecurityException if this is not the keyboard focus
405 * manager associated with the current {@link java.lang.ThreadGroup}
407 protected Component getGlobalPermanentFocusOwner ()
409 return (Component) getGlobalObject (currentPermanentFocusOwners);
413 * Set the {@link Component} that will be returned by {@link
414 * #getPermanentFocusOwner} (when it is called from the current
415 * {@link java.lang.ThreadGroup}) and {@link
416 * #getGlobalPermanentFocusOwner}. This method does not actually
417 * transfer the keyboard focus.
419 * @param focusOwner the Component to return from
420 * getPermanentFocusOwner and getGlobalPermanentFocusOwner
422 * @see Component.requestFocus ()
423 * @see Component.requestFocusInWindow ()
425 protected void setGlobalPermanentFocusOwner (Component focusOwner)
427 if (focusOwner == null || focusOwner.focusable)
428 setGlobalObject (currentPermanentFocusOwners, focusOwner,
429 "permanentFocusOwner");
433 * Retrieve the {@link Window} that is or contains the keyboard
434 * focus owner, or null if the focused window was not set by a
435 * thread in the current {@link java.lang.ThreadGroup}.
437 * @return the focused window or null
439 public Window getFocusedWindow ()
441 return (Window) getObject (currentFocusedWindows);
445 * Retrieve the {@link Window} that is or contains the focus owner,
446 * regardless of whether or not the {@link Window} was set focused
447 * by a thread in the current {@link java.lang.ThreadGroup}.
449 * @return the focused window
450 * @throws SecurityException if this is not the keyboard focus
451 * manager associated with the current {@link java.lang.ThreadGroup}
453 protected Window getGlobalFocusedWindow ()
455 return (Window) getGlobalObject (currentFocusedWindows);
459 * Set the {@link Window} that will be returned by {@link
460 * #getFocusedWindow} (when it is called from the current {@link
461 * java.lang.ThreadGroup}) and {@link #getGlobalFocusedWindow}.
462 * This method does not actually cause <code>window</code> to become
463 * the focused {@link Window}.
465 * @param window the Window to return from getFocusedWindow and
466 * getGlobalFocusedWindow
468 protected void setGlobalFocusedWindow (Window window)
470 if (window == null || window.focusable)
471 setGlobalObject (currentFocusedWindows, window, "focusedWindow");
475 * Retrieve the active {@link Window}, or null if the active window
476 * was not set by a thread in the current {@link
477 * java.lang.ThreadGroup}.
479 * @return the active window or null
481 public Window getActiveWindow()
483 return (Window) getObject (currentActiveWindows);
487 * Retrieve the active {@link Window}, regardless of whether or not
488 * the {@link Window} was made active by a thread in the current
489 * {@link java.lang.ThreadGroup}.
491 * @return the active window
492 * @throws SecurityException if this is not the keyboard focus
493 * manager associated with the current {@link java.lang.ThreadGroup}
495 protected Window getGlobalActiveWindow()
497 return (Window) getGlobalObject (currentActiveWindows);
501 * Set the {@link Window} that will be returned by {@link
502 * #getActiveWindow} (when it is called from the current {@link
503 * java.lang.ThreadGroup}) and {@link #getGlobalActiveWindow}. This
504 * method does not actually cause <code>window</code> to be made
505 * active.
507 * @param window the Window to return from getActiveWindow and
508 * getGlobalActiveWindow
510 protected void setGlobalActiveWindow(Window window)
512 setGlobalObject (currentActiveWindows, window, "activeWindow");
516 * Retrieve the default {@link FocusTraversalPolicy}.
517 * Focus-managing {@link Container}s use the returned object to
518 * define their initial focus traversal policy.
520 * @return a non-null default FocusTraversalPolicy object
522 public FocusTraversalPolicy getDefaultFocusTraversalPolicy ()
524 if (defaultPolicy == null)
525 defaultPolicy = new DefaultFocusTraversalPolicy ();
526 return defaultPolicy;
530 * Set the {@link FocusTraversalPolicy} returned by {@link
531 * #getDefaultFocusTraversalPolicy}. Focus-managing {@link
532 * Container}s created after this call will use policy as their
533 * initial focus traversal policy. Existing {@link Container}s'
534 * focus traversal policies will not be affected by calls to this
535 * method.
537 * @param policy the FocusTraversalPolicy that will be returned by
538 * subsequent calls to getDefaultFocusTraversalPolicy
539 * @throws IllegalArgumentException if policy is null
541 public void setDefaultFocusTraversalPolicy (FocusTraversalPolicy policy)
543 if (policy == null)
544 throw new IllegalArgumentException ();
545 firePropertyChange ("defaultFocusTraversalPolicy", defaultPolicy, policy);
546 defaultPolicy = policy;
550 * Set the default {@link java.util.Set} of focus traversal keys for
551 * one of the focus traversal directions.
553 * @param id focus traversal direction identifier
554 * @param keystrokes set of AWTKeyStrokes
556 * @see #FORWARD_TRAVERSAL_KEYS
557 * @see #BACKWARD_TRAVERSAL_KEYS
558 * @see #UP_CYCLE_TRAVERSAL_KEYS
559 * @see #DOWN_CYCLE_TRAVERSAL_KEYS
561 public void setDefaultFocusTraversalKeys (int id, Set keystrokes)
563 if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
564 id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
565 id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
566 id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
567 throw new IllegalArgumentException ();
569 if (keystrokes == null)
570 throw new IllegalArgumentException ();
572 Set sa;
573 Set sb;
574 Set sc;
575 String type;
576 switch (id)
578 case FORWARD_TRAVERSAL_KEYS:
579 sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
580 sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
581 sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
582 type = "forwardDefaultFocusTraversalKeys";
583 break;
584 case BACKWARD_TRAVERSAL_KEYS:
585 sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
586 sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
587 sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
588 type = "backwardDefaultFocusTraversalKeys";
589 break;
590 case UP_CYCLE_TRAVERSAL_KEYS:
591 sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
592 sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
593 sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
594 type = "upCycleDefaultFocusTraversalKeys";
595 break;
596 case DOWN_CYCLE_TRAVERSAL_KEYS:
597 sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
598 sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
599 sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
600 type = "downCycleDefaultFocusTraversalKeys";
601 break;
602 default:
603 throw new IllegalArgumentException ();
605 int i = keystrokes.size ();
606 Iterator iter = keystrokes.iterator ();
607 while (--i >= 0)
609 Object o = iter.next ();
610 if (!(o instanceof AWTKeyStroke)
611 || sa.contains (o) || sb.contains (o) || sc.contains (o)
612 || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
613 throw new IllegalArgumentException ();
615 keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
616 firePropertyChange (type, defaultFocusKeys[id], keystrokes);
617 defaultFocusKeys[id] = keystrokes;
621 * Retrieve the default {@link java.util.Set} of focus traversal
622 * keys for one of the focus traversal directions.
624 * @param id focus traversal direction identifier
626 * @return the default set of AWTKeyStrokes
628 * @see #FORWARD_TRAVERSAL_KEYS
629 * @see #BACKWARD_TRAVERSAL_KEYS
630 * @see #UP_CYCLE_TRAVERSAL_KEYS
631 * @see #DOWN_CYCLE_TRAVERSAL_KEYS
633 public Set getDefaultFocusTraversalKeys (int id)
635 if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
636 throw new IllegalArgumentException ();
637 return defaultFocusKeys[id];
641 * Retrieve the current focus cycle root, or null if the focus owner
642 * was not set by a thread in the current {@link
643 * java.lang.ThreadGroup}.
645 * @return the current focus cycle root or null
647 public Container getCurrentFocusCycleRoot ()
649 return (Container) getObject (currentFocusCycleRoots);
653 * Retrieve the current focus cycle root, regardless of whether or
654 * not it was made set by a thread in the current {@link
655 * java.lang.ThreadGroup}.
657 * @return the current focus cycle root
658 * @throws SecurityException if this is not the keyboard focus
659 * manager associated with the current {@link java.lang.ThreadGroup}
661 protected Container getGlobalCurrentFocusCycleRoot ()
663 return (Container) getGlobalObject (currentFocusCycleRoots);
667 * Set the {@link Container} that will be returned by {@link
668 * #getCurrentFocusCycleRoot} (when it is called from the current
669 * {@link java.lang.ThreadGroup}) and {@link
670 * #getGlobalCurrentFocusCycleRoot}. This method does not actually
671 * make <code>cycleRoot</code> the current focus cycle root.
673 * @param cycleRoot the focus cycle root to return from
674 * getCurrentFocusCycleRoot and getGlobalCurrentFocusCycleRoot
676 public void setGlobalCurrentFocusCycleRoot (Container cycleRoot)
678 setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot");
682 * Registers the supplied property change listener for receiving
683 * events caused by the following property changes:
685 * <ul>
686 * <li>the current focus owner ("focusOwner")</li>
687 * <li>the permanent focus owner ("permanentFocusOwner")</li>
688 * <li>the focused window ("focusedWindow")</li>
689 * <li>the active window ("activeWindow")</li>
690 * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
691 * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
692 * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
693 * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
694 * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
695 * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
696 * </ul>
698 * If the supplied listener is null, nothing occurs.
700 * @param l the new listener to register.
701 * @see KeyboardFocusManager#addPropertyChangeListener(String, java.beans.PropertyChangeListener)
703 public void addPropertyChangeListener(PropertyChangeListener l)
705 if (l != null)
706 propertyChangeSupport.addPropertyChangeListener(l);
710 * Removes the supplied property change listener from the list
711 * of registered listeners. If the supplied listener is null,
712 * nothing occurs.
714 * @param l the listener to remove.
716 public void removePropertyChangeListener(PropertyChangeListener l)
718 if (l != null)
719 propertyChangeSupport.removePropertyChangeListener(l);
723 * Returns the currently registered property change listeners
724 * in array form. The returned array is empty if no listeners are
725 * currently registered.
727 * @return an array of registered property change listeners.
729 public PropertyChangeListener[] getPropertyChangeListeners()
731 return propertyChangeSupport.getPropertyChangeListeners();
735 * Registers a property change listener for receiving events relating
736 * to a change to a specified property. The supplied property name can be
737 * either user-defined or one from the following list of properties
738 * relevant to this class:
740 * <ul>
741 * <li>the current focus owner ("focusOwner")</li>
742 * <li>the permanent focus owner ("permanentFocusOwner")</li>
743 * <li>the focused window ("focusedWindow")</li>
744 * <li>the active window ("activeWindow")</li>
745 * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
746 * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
747 * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
748 * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
749 * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
750 * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
751 * </ul>
753 * Nothing occurs if a null listener is supplied. null is regarded as a valid property name.
755 * @param name the name of the property to handle change events for.
756 * @param l the listener to register for changes to the specified property.
757 * @see KeyboardFocusManager#addPropertyChangeListener(java.beans.PropertyChangeListener)
759 public void addPropertyChangeListener(String name, PropertyChangeListener l)
761 if (l != null)
762 propertyChangeSupport.addPropertyChangeListener(name, l);
766 * Removes the supplied property change listener registered for the
767 * specified property from the list of registered listeners. If the
768 * supplied listener is null, nothing occurs.
770 * @param name the name of the property the listener is
771 * monitoring changes to.
772 * @param l the listener to remove.
774 public void removePropertyChangeListener(String name,
775 PropertyChangeListener l)
777 if (l != null)
778 propertyChangeSupport.removePropertyChangeListener(name, l);
782 * Returns the currently registered property change listeners
783 * in array form, which listen for changes to the supplied property.
784 * The returned array is empty, if no listeners are currently registered
785 * for events pertaining to the supplied property.
787 * @param name The property the returned listeners monitor for changes.
788 * @return an array of registered property change listeners which
789 * listen for changes to the supplied property.
791 public PropertyChangeListener[] getPropertyChangeListeners(String name)
793 return propertyChangeSupport.getPropertyChangeListeners(name);
797 * Fires a property change event as a response to a change to
798 * to the specified property. The event is only fired if a
799 * change has actually occurred (i.e. o and n are different).
801 * @param name The name of the property to which a change occurred.
802 * @param o The old value of the property.
803 * @param n The new value of the property.
805 protected void firePropertyChange(String name, Object o, Object n)
807 propertyChangeSupport.firePropertyChange(name, o, n);
811 * Registers a vetoable property change listener for receiving events
812 * relating to the following properties:
814 * <ul>
815 * <li>the current focus owner ("focusOwner")</li>
816 * <li>the permanent focus owner ("permanentFocusOwner")</li>
817 * <li>the focused window ("focusedWindow")</li>
818 * <li>the active window ("activeWindow")</li>
819 * </ul>
821 * Nothing occurs if a null listener is supplied.
823 * @param l the listener to register.
824 * @see KeyboardFocusManager#addVetoableChangeListener(String, java.beans.VetoableChangeListener)
826 public void addVetoableChangeListener(VetoableChangeListener l)
828 if (l != null)
829 vetoableChangeSupport.addVetoableChangeListener(l);
833 * Removes the supplied vetoable property change listener from
834 * the list of registered listeners. If the supplied listener
835 * is null, nothing occurs.
837 * @param l the listener to remove.
839 public void removeVetoableChangeListener(VetoableChangeListener l)
841 if (l != null)
842 vetoableChangeSupport.removeVetoableChangeListener(l);
846 * Returns the currently registered vetoable property change listeners
847 * in array form. The returned array is empty if no listeners are
848 * currently registered.
850 * @return an array of registered vetoable property change listeners.
851 * @since 1.4
853 public VetoableChangeListener[] getVetoableChangeListeners()
855 return vetoableChangeSupport.getVetoableChangeListeners();
859 * Registers a vetoable property change listener for receiving events relating
860 * to a vetoable change to a specified property. The supplied property name can be
861 * either user-defined or one from the following list of properties
862 * relevant to this class:
864 * <ul>
865 * <li>the current focus owner ("focusOwner")</li>
866 * <li>the permanent focus owner ("permanentFocusOwner")</li>
867 * <li>the focused window ("focusedWindow")</li>
868 * <li>the active window ("activeWindow")</li>
869 * </ul>
871 * Nothing occurs if a null listener is supplied. null is regarded as a valid property name.
873 * @param name the name of the property to handle change events for.
874 * @param l the listener to register for changes to the specified property.
875 * @see KeyboardFocusManager#addVetoableChangeListener(java.beans.VetoableChangeListener)
877 public void addVetoableChangeListener(String name, VetoableChangeListener l)
879 if (l != null)
880 vetoableChangeSupport.addVetoableChangeListener(name, l);
884 * Removes the supplied vetoable property change listener registered
885 * for the specified property from the list of registered listeners.
886 * If the supplied listener is null, nothing occurs.
888 * @param name the name of the vetoable property the listener is
889 * monitoring changes to.
890 * @param l the listener to remove.
892 public void removeVetoableChangeListener(String name,
893 VetoableChangeListener l)
895 if (l != null)
896 vetoableChangeSupport.removeVetoableChangeListener(name, l);
900 * Returns the currently registered vetoable property change listeners
901 * in array form, which listen for changes to the supplied property.
902 * The returned array is empty, if no listeners are currently registered
903 * for events pertaining to the supplied property.
905 * @param name The property the returned listeners monitor for changes.
906 * @return an array of registered property change listeners which
907 * listen for changes to the supplied property.
908 * @since 1.4
910 public VetoableChangeListener[] getVetoableChangeListeners(String name)
912 return vetoableChangeSupport.getVetoableChangeListeners(name);
916 * Fires a property change event as a response to a vetoable change to
917 * to the specified property. The event is only fired if a
918 * change has actually occurred (i.e. o and n are different).
919 * In the event that the property change is vetoed, the following
920 * occurs:
922 * <ol>
923 * <li>
924 * This method throws a <code>PropertyVetoException</code> to
925 * the proposed change.
926 * </li>
927 * <li>
928 * A new event is fired to reverse the previous change.
929 * </li>
930 * <li>
931 * This method again throws a <code>PropertyVetoException</code>
932 * in response to the reversion.
933 * </li>
934 * </ol>
936 * @param name The name of the property to which a change occurred.
937 * @param o The old value of the property.
938 * @param n The new value of the property.
939 * @throws PropertyVetoException if one of the listeners vetos
940 * the change by throwing this exception.
942 protected void fireVetoableChange(String name, Object o, Object n)
943 throws PropertyVetoException
945 vetoableChangeSupport.fireVetoableChange(name, o, n);
949 * Adds a key event dispatcher to the list of registered dispatchers.
950 * When a key event is fired, each dispatcher's <code>dispatchKeyEvent</code>
951 * method is called in the order that they were added, prior to the manager
952 * dispatching the event itself. Notifications halt when one of the
953 * dispatchers returns true.
954 * <br />
955 * <br />
956 * The same dispatcher can exist multiple times within the list
957 * of registered dispatchers, and there is no limit on the length
958 * of this list. A null dispatcher is simply ignored.
960 * @param dispatcher The dispatcher to register.
962 public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
964 if (dispatcher != null)
965 keyEventDispatchers.add(dispatcher);
969 * Removes the specified key event dispatcher from the list of
970 * registered dispatchers. The manager always dispatches events,
971 * regardless of its existence within the list. The manager
972 * can be added and removed from the list, as with any other
973 * dispatcher, but this does not affect its ability to dispatch
974 * key events. Non-existent and null dispatchers are simply ignored
975 * by this method.
977 * @param dispatcher The dispatcher to remove.
979 public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
981 keyEventDispatchers.remove(dispatcher);
985 * Returns the currently registered key event dispatchers in <code>List</code>
986 * form. At present, this only includes dispatchers explicitly registered
987 * via the <code>addKeyEventDispatcher()</code> method, but this behaviour
988 * is subject to change and should not be depended on. The manager itself
989 * may be a member of the list, but only if explicitly registered. If no
990 * dispatchers have been registered, the list will be empty.
992 * @return A list of explicitly registered key event dispatchers.
993 * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
995 protected List getKeyEventDispatchers ()
997 return (List) keyEventDispatchers.clone ();
1001 * Adds a key event post processor to the list of registered post processors.
1002 * Post processors work in the same way as key event dispatchers, except
1003 * that they are invoked after the manager has dispatched the key event,
1004 * and not prior to this. Each post processor's <code>postProcessKeyEvent</code>
1005 * method is called to see if any post processing needs to be performed. THe
1006 * processors are called in the order in which they were added to the list,
1007 * and notifications continue until one returns true. As with key event
1008 * dispatchers, the manager is implicitly called following this process,
1009 * regardless of whether or not it is present within the list.
1010 * <br />
1011 * <br />
1012 * The same post processor can exist multiple times within the list
1013 * of registered post processors, and there is no limit on the length
1014 * of this list. A null post processor is simply ignored.
1016 * @param postProcessor the post processor to register.
1017 * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
1019 public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
1021 if (postProcessor != null)
1022 keyEventPostProcessors.add (postProcessor);
1026 * Removes the specified key event post processor from the list of
1027 * registered post processors. The manager always post processes events,
1028 * regardless of its existence within the list. The manager
1029 * can be added and removed from the list, as with any other
1030 * post processor, but this does not affect its ability to post process
1031 * key events. Non-existent and null post processors are simply ignored
1032 * by this method.
1034 * @param postProcessor the post processor to remove.
1036 public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
1038 keyEventPostProcessors.remove (postProcessor);
1042 * Returns the currently registered key event post processors in <code>List</code>
1043 * form. At present, this only includes post processors explicitly registered
1044 * via the <code>addKeyEventPostProcessor()</code> method, but this behaviour
1045 * is subject to change and should not be depended on. The manager itself
1046 * may be a member of the list, but only if explicitly registered. If no
1047 * post processors have been registered, the list will be empty.
1049 * @return A list of explicitly registered key event post processors.
1050 * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor)
1052 protected List getKeyEventPostProcessors ()
1054 return (List) keyEventPostProcessors.clone ();
1058 * The AWT event dispatcher uses this method to request that the manager
1059 * handle a particular event. If the manager fails or refuses to
1060 * dispatch the supplied event (this method returns false), the
1061 * AWT event dispatcher will try to dispatch the event itself.
1062 * <br />
1063 * <br />
1064 * The manager is expected to handle all <code>FocusEvent</code>s
1065 * and <code>KeyEvent</code>s, and <code>WindowEvent</code>s
1066 * relating to the focus. Dispatch is done with regard to the
1067 * the focus owner and the currently focused and active windows.
1068 * In handling the event, the source of the event may be overridden.
1069 * <br />
1070 * <br />
1071 * The actual dispatching is performed by calling
1072 * <code>redispatchEvent()</code>. This avoids the infinite recursion
1073 * of dispatch requests which may occur if this method is called on
1074 * the target component.
1076 * @param e the event to dispatch.
1077 * @return true if the event was dispatched.
1078 * @see KeyboardFocusManager#redispatchEvent(java.awt.Component, java.awt.AWTEvent)
1079 * @see KeyEvent
1080 * @see FocusEvent
1081 * @see WindowEvent
1083 public abstract boolean dispatchEvent (AWTEvent e);
1086 * Handles redispatching of an event so that recursion of
1087 * dispatch requests does not occur. Event dispatch methods
1088 * within this manager (<code>dispatchEvent()</code>) and
1089 * the key event dispatchers should use this method to handle
1090 * dispatching rather than the dispatch method of the target
1091 * component.
1092 * <br />
1093 * <br />
1094 * <strong>
1095 * This method is not intended for general consumption, and is
1096 * only for the use of the aforementioned classes.
1097 * </strong>
1099 * @param target the target component to which the event is
1100 * dispatched.
1101 * @param e the event to dispatch.
1103 public final void redispatchEvent (Component target, AWTEvent e)
1105 synchronized (e)
1107 e.setSource (target);
1108 target.dispatchEvent (e);
1113 * Attempts to dispatch key events for which no key event dispatcher
1114 * has so far succeeded. This method is usually called by
1115 * <code>dispatchEvent()</code> following the sending of the key
1116 * event to any registered key event dispatchers. If the key
1117 * event reaches this stage, none of the dispatchers returned
1118 * true. This is, of course, always the case if there are no
1119 * registered dispatchers.
1120 * <br />
1121 * <br />
1122 * If this method also fails to handle the key event, then
1123 * false is returned to the caller. In the case of
1124 * <code>dispatchEvent()</code>, the calling method may try
1125 * to handle the event itself or simply forward on the
1126 * false result to its caller. When the event is dispatched
1127 * by this method, a true result is propogated through the
1128 * calling methods.
1130 * @param e the key event to dispatch.
1131 * @return true if the event was dispatched successfully.
1133 public abstract boolean dispatchKeyEvent (KeyEvent e);
1136 * Handles the post processing of key events. By default,
1137 * this method will map unhandled key events to appropriate
1138 * <code>MenuShortcut</code>s. The event is consumed
1139 * in the process and the shortcut is activated. This
1140 * method is usually called by <code>dispatchKeyEvent</code>.
1142 * @param e the key event to post process.
1143 * @return true by default, as the event was handled.
1145 public abstract boolean postProcessKeyEvent (KeyEvent e);
1148 * Handles focus traversal operations for key events which
1149 * represent focus traversal keys in relation to the supplied
1150 * component. The supplied component is assumed to have the
1151 * focus, whether it does so or not, and the operation is
1152 * carried out as appropriate, with this in mind.
1154 * @param focused the component on which to perform focus traversal,
1155 * on the assumption that this component has the focus.
1156 * @param e the possible focus traversal key event.
1158 public abstract void processKeyEvent (Component focused, KeyEvent e);
1161 * Delays all key events following the specified timestamp until the
1162 * supplied component has focus. The AWT calls this method when it is
1163 * determined that a focus change may occur within the native windowing
1164 * system. Any key events which occur following the time specified by
1165 * after are delayed until a <code>FOCUS_GAINED</code> event is received
1166 * for the untilFocused component. The manager is responsible for ensuring
1167 * this takes place.
1169 * @param after the timestamp beyond which all key events are delayed until
1170 * the supplied component gains focus.
1171 * @param untilFocused the component to wait on gaining focus.
1173 protected abstract void enqueueKeyEvents (long after, Component untilFocused);
1176 * Removes the key event block specified by the supplied timestamp and component.
1177 * All delayed key events are released for normal dispatching following its
1178 * removal and subsequent key events that would have been blocked are now
1179 * immediately dispatched. If the specified timestamp is below 0, then
1180 * the request with the oldest timestamp is removed.
1182 * @param after the timestamp of the key event block to be removed, or a
1183 * value smaller than 0 if the oldest is to be removed.
1184 * @param untilFocused the component of the key event block to be removed.
1186 protected abstract void dequeueKeyEvents (long after, Component untilFocused);
1189 * Discards all key event blocks relating to focus requirements for
1190 * the supplied component, regardless of timestamp.
1192 * @param comp the component of the key event block(s) to be removed.
1194 protected abstract void discardKeyEvents (Component comp);
1197 * Moves the current focus to the next component following
1198 * comp, based on the current focus traversal policy. By
1199 * default, only visible, displayable, accepted components
1200 * can receive focus. <code>Canvas</code>es, <code>Panel</code>s,
1201 * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1202 * <code>Window</code>s and lightweight components are judged
1203 * to be unacceptable by default. See the
1204 * <code>DefaultFocusTraversalPolicy</code> for more details.
1206 * @param comp the component prior to the one which will
1207 * become the focus, following execution of this method.
1208 * @see DefaultFocusTraversalPolicy
1210 public abstract void focusNextComponent(Component comp);
1213 * Moves the current focus to the previous component, prior to
1214 * comp, based on the current focus traversal policy. By
1215 * default, only visible, displayable, accepted components
1216 * can receive focus. <code>Canvas</code>es, <code>Panel</code>s,
1217 * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1218 * <code>Window</code>s and lightweight components are judged
1219 * to be unacceptable by default. See the
1220 * <code>DefaultFocusTraversalPolicy</code> for more details.
1222 * @param comp the component following the one which will
1223 * become the focus, following execution of this method.
1224 * @see DefaultFocusTraversalPolicy
1226 public abstract void focusPreviousComponent(Component comp);
1229 * Moves the current focus upwards by one focus cycle.
1230 * Both the current focus owner and current focus cycle root
1231 * become the focus cycle root of the supplied component.
1232 * However, in the case of a <code>Window</code>, the default
1233 * focus component becomes the focus owner and the focus cycle
1234 * root is not changed.
1236 * @param comp the component used as part of the focus traversal.
1238 public abstract void upFocusCycle(Component comp);
1241 * Moves the current focus downwards by one focus cycle.
1242 * If the supplied container is a focus cycle root, then this
1243 * becomes the current focus cycle root and the focus goes
1244 * to the default component of the specified container.
1245 * Nothing happens for non-focus cycle root containers.
1247 * @param cont the container used as part of the focus traversal.
1249 public abstract void downFocusCycle(Container cont);
1252 * Moves the current focus to the next component, based on the
1253 * current focus traversal policy. By default, only visible,
1254 * displayable, accepted component can receive focus.
1255 * <code>Canvas</code>es, <code>Panel</code>s,
1256 * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1257 * <code>Window</code>s and lightweight components are judged
1258 * to be unacceptable by default. See the
1259 * <code>DefaultFocusTraversalPolicy</code> for more details.
1261 * @see DefaultFocusTraversalPolicy
1263 public final void focusNextComponent()
1265 focusNextComponent (null);
1269 * Moves the current focus to the previous component, based on the
1270 * current focus traversal policy. By default, only visible,
1271 * displayable, accepted component can receive focus.
1272 * <code>Canvas</code>es, <code>Panel</code>s,
1273 * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1274 * <code>Window</code>s and lightweight components are judged
1275 * to be unacceptable by default. See the
1276 * <code>DefaultFocusTraversalPolicy</code> for more details.
1278 * @see DefaultFocusTraversalPolicy
1280 public final void focusPreviousComponent()
1282 focusPreviousComponent (null);
1286 * Moves the current focus upwards by one focus cycle,
1287 * so that the new focus owner is the focus cycle root
1288 * of the current owner. The current focus cycle root then
1289 * becomes the focus cycle root of the new focus owner.
1290 * However, in the case of the focus cycle root of the
1291 * current focus owner being a <code>Window</code>, the default
1292 * component of this window becomes the focus owner and the
1293 * focus cycle root is not changed.
1295 public final void upFocusCycle()
1297 upFocusCycle (null);
1301 * Moves the current focus downwards by one focus cycle,
1302 * iff the current focus cycle root is a <code>Container</code>.
1303 * Usually, the new focus owner is set to the default component
1304 * of the container and the current focus cycle root is set
1305 * to the current focus owner. Nothing occurs if the current
1306 * focus cycle root is not a container.
1308 public final void downFocusCycle()
1310 Component focusOwner = getGlobalFocusOwner ();
1311 if (focusOwner instanceof Container
1312 && ((Container) focusOwner).isFocusCycleRoot ())
1313 downFocusCycle ((Container) focusOwner);
1317 * Retrieve an object from one of the global object {@link
1318 * java.util.Map}s, if the object was set by the a thread in the
1319 * current {@link java.lang.ThreadGroup}. Otherwise, return null.
1321 * @param globalMap one of the global object Maps
1323 * @return a global object set by the current ThreadGroup, or null
1325 * @see getFocusOwner
1326 * @see getPermanentFocusOwner
1327 * @see getFocusedWindow
1328 * @see getActiveWindow
1329 * @see getCurrentFocusCycleRoot
1331 private Object getObject (Map globalMap)
1333 ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1334 return globalMap.get (currentGroup);
1338 * Retrieve an object from one of the global object {@link
1339 * java.util.Map}s, regardless of whether or not the object was set
1340 * by a thread in the current {@link java.lang.ThreadGroup}.
1342 * @param globalMap one of the global object Maps
1344 * @return a global object set by the current ThreadGroup, or null
1346 * @throws SecurityException if this is not the keyboard focus
1347 * manager associated with the current {@link java.lang.ThreadGroup}
1349 * @see getGlobalFocusOwner
1350 * @see getGlobalPermanentFocusOwner
1351 * @see getGlobalFocusedWindow
1352 * @see getGlobalActiveWindow
1353 * @see getGlobalCurrentFocusCycleRoot
1355 private Object getGlobalObject (Map globalMap)
1357 ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1358 KeyboardFocusManager managerForCallingThread
1359 = (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
1361 if (this != managerForCallingThread)
1362 throw new SecurityException ("Attempted to retrieve an object from a "
1363 + "keyboard focus manager that isn't "
1364 + "associated with the current thread group.");
1366 synchronized (globalMap)
1368 Collection globalObjects = globalMap.values ();
1369 Iterator i = globalObjects.iterator ();
1370 Component globalObject;
1372 while (i.hasNext ())
1374 globalObject = (Component) i.next ();
1375 if (globalObject != null)
1376 return globalObject;
1380 // No Object was found.
1381 return null;
1385 * Set an object in one of the global object {@link java.util.Map}s,
1386 * that will be returned by subsequent calls to getGlobalObject on
1387 * the same {@link java.util.Map}.
1389 * @param globalMap one of the global object Maps
1390 * @param newObject the object to set
1391 * @param property the property that will change
1393 * @see setGlobalFocusOwner
1394 * @see setGlobalPermanentFocusOwner
1395 * @see setGlobalFocusedWindow
1396 * @see setGlobalActiveWindow
1397 * @see setGlobalCurrentFocusCycleRoot
1399 private void setGlobalObject (Map globalMap,
1400 Object newObject,
1401 String property)
1403 synchronized (globalMap)
1405 // Save old object.
1406 Object oldObject = getGlobalObject (globalMap);
1408 // Nullify old object.
1409 Collection threadGroups = globalMap.keySet ();
1410 Iterator i = threadGroups.iterator ();
1411 while (i.hasNext ())
1413 ThreadGroup oldThreadGroup = (ThreadGroup) i.next ();
1414 if (globalMap.get (oldThreadGroup) != null)
1416 globalMap.put (oldThreadGroup, null);
1417 // There should only be one object set at a time, so
1418 // we can short circuit.
1419 break;
1423 ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1424 firePropertyChange (property, oldObject, newObject);
1427 fireVetoableChange (property, oldObject, newObject);
1428 // Set new object.
1429 globalMap.put (currentGroup, newObject);
1431 catch (PropertyVetoException e)