1 /* KeyboardFocusManager.java -- manage component focusing via the keyboard
2    Copyright (C) 2002, 2004, 2005 Free Software Foundation
3 
4 This file is part of GNU Classpath.
5 
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.
10 
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.
15 
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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
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.
25 
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. */
37 
38 
39 package java.awt;
40 
41 import java.applet.Applet;
42 import java.awt.FocusTraversalPolicy;
43 import java.awt.event.FocusEvent;
44 import java.awt.event.KeyEvent;
45 import java.awt.event.WindowEvent;
46 import java.beans.PropertyChangeListener;
47 import java.beans.PropertyChangeSupport;
48 import java.beans.PropertyVetoException;
49 import java.beans.VetoableChangeListener;
50 import java.beans.VetoableChangeSupport;
51 import java.util.ArrayList;
52 import java.util.Collection;
53 import java.util.Collections;
54 import java.util.HashMap;
55 import java.util.HashSet;
56 import java.util.Iterator;
57 import java.util.List;
58 import java.util.Map;
59 import java.util.Set;
60 
61 /**
62  * The <code>KeyboardFocusManager</code> handles the focusing of
63  * windows for receiving keyboard events.  The manager handles
64  * the dispatch of all <code>FocusEvent</code>s and
65  * <code>KeyEvent</code>s, along with <code>WindowEvent</code>s
66  * relating to the focused window.  Users can use the manager
67  * to ascertain the current focus owner and fire events.
68  * <br />
69  * <br />
70  * The focus owner is the <code>Component</code> that receives
71  * key events.  The focus owner is either the currently focused
72  * window or a component within this window.
73  * <br />
74  * <br />
75  * The underlying native windowing system may denote the active
76  * window or its children with special decorations (e.g. a highlighted
77  * title bar).  The active window is always either a <code>Frame</code>
78  * or <code>Dialog</code>, and is either the currently focused
79  * window or its owner.
80  * <br />
81  * <br />
82  * Applets may be partitioned into different applet contexts, according
83  * to their code base.  In this case, each context has its own
84  * <code>KeyboardFocusManager</code>, as opposed to the global
85  * manager maintained by applets which share the same context.
86  * Each context is insulated from the others, and they don't interact.
87  * The resulting behaviour, as with context division, depends on the browser
88  * supporting the applets.  Regardless, there can only ever be
89  * one focused window, one active window and one focus owner
90  * per <code>ClassLoader</code>.
91  * <br />
92  * <br />
93  * To support this separation of focus managers, the manager instances
94  * and the internal state information is grouped by the
95  * <code>ThreadGroup</code> to which it pertains.  With respect to
96  * applets, each code base has its own <code>ThreadGroup</code>, so the
97  * isolation of each context is enforced within the manager.
98  * <br />
99  * <br />
100  * By default, the manager defines TAB and Ctrl+TAB as the
101  * forward focus traversal keys and Shift+TAB and Ctrl+Shift+TAB
102  * as the backward focus traversal keys.  No up or down cycle
103  * traversal keys are defined by default.  Traversal takes effect
104  * on the firing of a relevant <code>KEY_PRESSED</code> event.
105  * However, all other key events related to the use of the
106  * defined focus traversal key sequence are consumed and not
107  * dispatched.
108  * <br />
109  * <br />
110  * These default traversal keys come into effect on all windows
111  * for which no alternative set of keys is defined.  This also
112  * applies recursively to any child components of such a window,
113  * which define no traversal keys of their own.
114  *
115  * @author Eric Blake (ebb9@email.byu.edu)
116  * @author Thomas Fitzsimmons (fitzsim@redhat.com)
117  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
118  * @since 1.4
119  */
120 public abstract class KeyboardFocusManager
121   implements KeyEventDispatcher, KeyEventPostProcessor
122 {
123   /** Identifies {@link AWTKeyStroke}s that move the focus forward in
124       the focus cycle. */
125   public static final int FORWARD_TRAVERSAL_KEYS = 0;
126 
127   /** Identifies {@link AWTKeyStroke}s that move the focus backward in
128       the focus cycle. */
129   public static final int BACKWARD_TRAVERSAL_KEYS = 1;
130 
131   /** Identifies {@link AWTKeyStroke}s that move the focus up to the
132       parent focus cycle root. */
133   public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
134 
135   /** Identifies {@link AWTKeyStroke}s that move the focus down to the
136       child focus cycle root. */
137   public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
138 
139   /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
140       the next focusable Component in the focus cycle. */
141   private static final Set DEFAULT_FORWARD_KEYS;
142 
143   /** The set of {@link AWTKeyStroke}s that cause focus to be moved to
144       the previous focusable Component in the focus cycle. */
145   private static final Set DEFAULT_BACKWARD_KEYS;
146 
147   /** Populate the DEFAULT_FORWARD_KEYS and DEFAULT_BACKWARD_KEYS
148       {@link java.util.Set}s. */
149   static
150   {
151     Set s = new HashSet();
AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0)152     s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, KeyEvent.CTRL_DOWN_MASK)153     s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
154                                        KeyEvent.CTRL_DOWN_MASK));
155     DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
156     s = new HashSet();
AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK)157     s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
158                                        KeyEvent.SHIFT_DOWN_MASK));
AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, KeyEvent.SHIFT_DOWN_MASK | KeyEvent.CTRL_DOWN_MASK)159     s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
160                                        KeyEvent.SHIFT_DOWN_MASK
161                                        | KeyEvent.CTRL_DOWN_MASK));
162     DEFAULT_BACKWARD_KEYS = Collections.unmodifiableSet(s);
163   }
164 
165   /** The global object {@link java.util.Map}s. */
166 
167   /** For security reasons, {@link java.applet.Applet}s in different
168       codebases must be insulated from one another.  Since {@link
169       KeyboardFocusManager}s have the ability to return {@link
170       Component}s from a given {@link java.applet.Applet}, each
171       codebase must have an independent {@link KeyboardFocusManager}.
172       Since each codebase has its own {@link ThreadGroup} in which its
173       {@link Applet}s run, it makes sense to partition {@link
174       KeyboardFocusManager}s according to {@link
175       java.lang.ThreadGroup}.  Thus, currentKeyboardFocusManagers is a
176       {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}. */
177   private static Map currentKeyboardFocusManagers = new HashMap ();
178 
179   /** {@link java.applet.Applet}s in one codebase must not be allowed
180       to access {@link Component}s in {@link java.applet.Applet}s in
181       other codebases.  To enforce this restriction, we key the
182       following {@link java.util.Map}s on {@link java.lang.ThreadGroup}s (which
183       are per-codebase).  For example, if {@link
184       java.lang.ThreadGroup} A calls {@link #setGlobalFocusOwner},
185       passing {@link Component} C, currentFocusOwners[A] is assigned
186       C, and all other currentFocusOwners values are nullified.  Then
187       if {@link java.lang.ThreadGroup} A subsequently calls {@link
188       #getGlobalFocusOwner}, it will return currentFocusOwners[A],
189       that is, {@link Component} C.  If another {@link
190       java.lang.ThreadGroup} K calls {@link #getGlobalFocusOwner}, it
191       will return currentFocusOwners[K], that is, null.
192 
193       Since this is a static field, we ensure that there is only one
194       focused {@link Component} per class loader. */
195   private static Map currentFocusOwners = new HashMap ();
196 
197   /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
198       that stores the {@link Component} that owns the permanent
199       keyboard focus. @see currentFocusOwners */
200   private static Map currentPermanentFocusOwners = new HashMap ();
201 
202   /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
203       that stores the focused {@link Window}. @see
204       currentFocusOwners */
205   private static Map currentFocusedWindows = new HashMap ();
206 
207   /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
208       that stores the active {@link Window}. @see
209       currentFocusOwners */
210   private static Map currentActiveWindows = new HashMap ();
211 
212   /** A {@link java.util.Map} keyed on {@link java.lang.ThreadGroup}s
213       that stores the focus cycle root {@link Container}. @see
214       currentFocusOwners */
215   private static Map currentFocusCycleRoots = new HashMap ();
216 
217   /** The default {@link FocusTraversalPolicy} that focus-managing
218       {@link Container}s will use to define their initial focus
219       traversal policy. */
220   private FocusTraversalPolicy defaultPolicy;
221 
222   /** An array that stores the {@link #FORWARD_TRAVERSAL_KEYS}, {@link
223       #BACKWARD_TRAVERSAL_KEYS}, {@link #UP_CYCLE_TRAVERSAL_KEYS} and
224       {@link #DOWN_CYCLE_TRAVERSAL_KEYS} {@link AWTKeyStroke}s {@link
225       java.util.Set}s. */
226   private Set[] defaultFocusKeys = new Set[]
227   {
228     DEFAULT_FORWARD_KEYS, DEFAULT_BACKWARD_KEYS,
229     Collections.EMPTY_SET, Collections.EMPTY_SET
230   };
231 
232   /**
233    * A utility class to support the handling of events relating to property changes.
234    */
235   private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this);
236 
237   /**
238    * A utility class to support the handling of events relating to vetoable changes.
239    */
240   private final VetoableChangeSupport vetoableChangeSupport = new VetoableChangeSupport (this);
241 
242   /** A list of {@link KeyEventDispatcher}s that process {@link
243       KeyEvent}s before they are processed the default keyboard focus
244       manager. */
245   private final ArrayList keyEventDispatchers = new ArrayList();
246 
247   /** A list of {@link KeyEventPostProcessor}s that process unconsumed
248       {@link KeyEvent}s. */
249   private final ArrayList keyEventPostProcessors = new ArrayList();
250 
251   /**
252    * Construct a KeyboardFocusManager.
253    */
KeyboardFocusManager()254   public KeyboardFocusManager ()
255   {
256   }
257 
258   /**
259    * Retrieve the keyboard focus manager associated with the {@link
260    * java.lang.ThreadGroup} to which the calling thread belongs.
261    *
262    * @return the keyboard focus manager associated with the current
263    * thread group
264    */
getCurrentKeyboardFocusManager()265   public static KeyboardFocusManager getCurrentKeyboardFocusManager ()
266   {
267     ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
268 
269     if (currentKeyboardFocusManagers.get (currentGroup) == null)
270       setCurrentKeyboardFocusManager (null);
271 
272     return (KeyboardFocusManager) currentKeyboardFocusManagers.get (currentGroup);
273   }
274 
275   /**
276    * Set the keyboard focus manager associated with the {@link
277    * java.lang.ThreadGroup} to which the calling thread belongs.
278    *
279    * @param m the keyboard focus manager for the current thread group
280    */
setCurrentKeyboardFocusManager(KeyboardFocusManager m)281   public static void setCurrentKeyboardFocusManager (KeyboardFocusManager m)
282   {
283     SecurityManager sm = System.getSecurityManager ();
284     if (sm != null)
285       sm.checkPermission (new AWTPermission ("replaceKeyboardFocusManager"));
286 
287     ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
288     KeyboardFocusManager manager;
289 
290     if (m == null)
291       manager = new DefaultKeyboardFocusManager();
292     else
293       manager = m;
294 
295     currentKeyboardFocusManagers.put (currentGroup, manager);
296   }
297 
298   /**
299    * Retrieve the {@link Component} that has the keyboard focus, or
300    * null if the focus owner was not set by a thread in the current
301    * {@link java.lang.ThreadGroup}.
302    *
303    * @return the keyboard focus owner or null
304    */
getFocusOwner()305   public Component getFocusOwner ()
306   {
307     return (Component) getObject (currentFocusOwners);
308   }
309 
310   /**
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}.
316    *
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}
320    */
getGlobalFocusOwner()321   protected Component getGlobalFocusOwner ()
322   {
323     return (Component) getGlobalObject(currentFocusOwners, true);
324   }
325 
326   /**
327    * Set the {@link Component} that will be returned by {@link
328    * #getFocusOwner} (when it is called from the current {@link
329    * java.lang.ThreadGroup}) and {@link #getGlobalFocusOwner}.  This
330    * method does not actually transfer the keyboard focus.
331    *
332    * @param owner the Component to return from getFocusOwner and
333    * getGlobalFocusOwner
334    *
335    * @see Component#requestFocus()
336    * @see Component#requestFocusInWindow()
337    */
setGlobalFocusOwner(Component owner)338   protected void setGlobalFocusOwner (Component owner)
339   {
340     if (owner == null || owner.focusable)
341       setGlobalObject (currentFocusOwners, owner, "focusOwner");
342   }
343 
344   /**
345    * Clear the global focus owner and deliver a FOCUS_LOST event to
346    * the previously-focused {@link Component}.  Until another {@link
347    * Component} becomes the keyboard focus owner, key events will be
348    * discarded by top-level windows.
349    */
clearGlobalFocusOwner()350   public void clearGlobalFocusOwner ()
351   {
352     synchronized (currentFocusOwners)
353       {
354         Component focusOwner = getGlobalFocusOwner ();
355         Component permanentFocusOwner = getGlobalPermanentFocusOwner ();
356 
357         setGlobalFocusOwner (null);
358         setGlobalPermanentFocusOwner (null);
359 
360         // Inform the old focus owner that it has lost permanent
361         // focus.
362         if (focusOwner != null)
363           {
364             // We can't cache the event queue, because of
365             // bootstrapping issues.  We need to set the default
366             // KeyboardFocusManager in EventQueue before the event
367             // queue is started.
368             EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
369             if (focusOwner != permanentFocusOwner)
370               q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, true));
371             else
372               q.postEvent (new FocusEvent (focusOwner, FocusEvent.FOCUS_LOST, false));
373           }
374 
375         if (focusOwner != permanentFocusOwner)
376           {
377             EventQueue q = Toolkit.getDefaultToolkit ().getSystemEventQueue ();
378             q.postEvent (new FocusEvent (permanentFocusOwner, FocusEvent.FOCUS_LOST, false));
379           }
380       }
381   }
382 
383   /**
384    * Retrieve the {@link Component} that has the permanent keyboard
385    * focus, or null if the focus owner was not set by a thread in the
386    * current {@link java.lang.ThreadGroup}.
387    *
388    * @return the keyboard focus owner or null
389    */
getPermanentFocusOwner()390   public Component getPermanentFocusOwner ()
391   {
392     return (Component) getObject (currentPermanentFocusOwners);
393   }
394 
395   /**
396    * Retrieve the {@link Component} that has the permanent keyboard
397    * focus, regardless of whether or not it was set by a thread in the
398    * current {@link java.lang.ThreadGroup}.
399    *
400    * @return the keyboard focus owner
401    * @throws SecurityException if this is not the keyboard focus
402    * manager associated with the current {@link java.lang.ThreadGroup}
403    */
getGlobalPermanentFocusOwner()404   protected Component getGlobalPermanentFocusOwner ()
405   {
406     return (Component) getGlobalObject (currentPermanentFocusOwners, true);
407   }
408 
409   /**
410    * Set the {@link Component} that will be returned by {@link
411    * #getPermanentFocusOwner} (when it is called from the current
412    * {@link java.lang.ThreadGroup}) and {@link
413    * #getGlobalPermanentFocusOwner}.  This method does not actually
414    * transfer the keyboard focus.
415    *
416    * @param focusOwner the Component to return from
417    * getPermanentFocusOwner and getGlobalPermanentFocusOwner
418    *
419    * @see Component#requestFocus()
420    * @see Component#requestFocusInWindow()
421    */
setGlobalPermanentFocusOwner(Component focusOwner)422   protected void setGlobalPermanentFocusOwner (Component focusOwner)
423   {
424     if (focusOwner == null || focusOwner.focusable)
425       setGlobalObject (currentPermanentFocusOwners, focusOwner,
426                        "permanentFocusOwner");
427   }
428 
429   /**
430    * Retrieve the {@link Window} that is or contains the keyboard
431    * focus owner, or null if the focused window was not set by a
432    * thread in the current {@link java.lang.ThreadGroup}.
433    *
434    * @return the focused window or null
435    */
getFocusedWindow()436   public Window getFocusedWindow ()
437   {
438     return (Window) getObject (currentFocusedWindows);
439   }
440 
441   /**
442    * Retrieve the {@link Window} that is or contains the focus owner,
443    * regardless of whether or not the {@link Window} was set focused
444    * by a thread in the current {@link java.lang.ThreadGroup}.
445    *
446    * @return the focused window
447    * @throws SecurityException if this is not the keyboard focus
448    * manager associated with the current {@link java.lang.ThreadGroup}
449    */
getGlobalFocusedWindow()450   protected Window getGlobalFocusedWindow ()
451   {
452     return (Window) getGlobalObject (currentFocusedWindows, true);
453   }
454 
455   /**
456    * Set the {@link Window} that will be returned by {@link
457    * #getFocusedWindow} (when it is called from the current {@link
458    * java.lang.ThreadGroup}) and {@link #getGlobalFocusedWindow}.
459    * This method does not actually cause <code>window</code> to become
460    * the focused {@link Window}.
461    *
462    * @param window the Window to return from getFocusedWindow and
463    * getGlobalFocusedWindow
464    */
setGlobalFocusedWindow(Window window)465   protected void setGlobalFocusedWindow (Window window)
466   {
467     if (window == null || window.focusable)
468       setGlobalObject (currentFocusedWindows, window, "focusedWindow");
469   }
470 
471   /**
472    * Retrieve the active {@link Window}, or null if the active window
473    * was not set by a thread in the current {@link
474    * java.lang.ThreadGroup}.
475    *
476    * @return the active window or null
477    */
getActiveWindow()478   public Window getActiveWindow()
479   {
480     return (Window) getObject (currentActiveWindows);
481   }
482 
483   /**
484    * Retrieve the active {@link Window}, regardless of whether or not
485    * the {@link Window} was made active by a thread in the current
486    * {@link java.lang.ThreadGroup}.
487    *
488    * @return the active window
489    * @throws SecurityException if this is not the keyboard focus
490    * manager associated with the current {@link java.lang.ThreadGroup}
491    */
getGlobalActiveWindow()492   protected Window getGlobalActiveWindow()
493   {
494     return (Window) getGlobalObject (currentActiveWindows, true);
495   }
496 
497   /**
498    * Set the {@link Window} that will be returned by {@link
499    * #getActiveWindow} (when it is called from the current {@link
500    * java.lang.ThreadGroup}) and {@link #getGlobalActiveWindow}.  This
501    * method does not actually cause <code>window</code> to be made
502    * active.
503    *
504    * @param window the Window to return from getActiveWindow and
505    * getGlobalActiveWindow
506    */
setGlobalActiveWindow(Window window)507   protected void setGlobalActiveWindow(Window window)
508   {
509     setGlobalObject (currentActiveWindows, window, "activeWindow");
510   }
511 
512   /**
513    * Retrieve the default {@link FocusTraversalPolicy}.
514    * Focus-managing {@link Container}s use the returned object to
515    * define their initial focus traversal policy.
516    *
517    * @return a non-null default FocusTraversalPolicy object
518    */
getDefaultFocusTraversalPolicy()519   public FocusTraversalPolicy getDefaultFocusTraversalPolicy ()
520   {
521     if (defaultPolicy == null)
522       defaultPolicy = new DefaultFocusTraversalPolicy ();
523     return defaultPolicy;
524   }
525 
526   /**
527    * Set the {@link FocusTraversalPolicy} returned by {@link
528    * #getDefaultFocusTraversalPolicy}.  Focus-managing {@link
529    * Container}s created after this call will use policy as their
530    * initial focus traversal policy.  Existing {@link Container}s'
531    * focus traversal policies will not be affected by calls to this
532    * method.
533    *
534    * @param policy the FocusTraversalPolicy that will be returned by
535    * subsequent calls to getDefaultFocusTraversalPolicy
536    * @throws IllegalArgumentException if policy is null
537    */
setDefaultFocusTraversalPolicy(FocusTraversalPolicy policy)538   public void setDefaultFocusTraversalPolicy (FocusTraversalPolicy policy)
539   {
540     if (policy == null)
541       throw new IllegalArgumentException ();
542     firePropertyChange ("defaultFocusTraversalPolicy", defaultPolicy, policy);
543     defaultPolicy = policy;
544   }
545 
546   /**
547    * Set the default {@link java.util.Set} of focus traversal keys for
548    * one of the focus traversal directions.
549    *
550    * @param id focus traversal direction identifier
551    * @param keystrokes set of AWTKeyStrokes
552    *
553    * @see #FORWARD_TRAVERSAL_KEYS
554    * @see #BACKWARD_TRAVERSAL_KEYS
555    * @see #UP_CYCLE_TRAVERSAL_KEYS
556    * @see #DOWN_CYCLE_TRAVERSAL_KEYS
557    */
setDefaultFocusTraversalKeys(int id, Set<? extends AWTKeyStroke> keystrokes)558   public void setDefaultFocusTraversalKeys (int id,
559                                             Set<? extends AWTKeyStroke>
560                                             keystrokes)
561   {
562     if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
563         id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
564         id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
565         id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
566       throw new IllegalArgumentException ();
567 
568     if (keystrokes == null)
569       throw new IllegalArgumentException ();
570 
571     Set sa;
572     Set sb;
573     Set sc;
574     String type;
575     switch (id)
576       {
577       case FORWARD_TRAVERSAL_KEYS:
578         sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
579         sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
580         sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
581         type = "forwardDefaultFocusTraversalKeys";
582         break;
583       case BACKWARD_TRAVERSAL_KEYS:
584         sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
585         sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
586         sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
587         type = "backwardDefaultFocusTraversalKeys";
588         break;
589       case UP_CYCLE_TRAVERSAL_KEYS:
590         sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
591         sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
592         sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
593         type = "upCycleDefaultFocusTraversalKeys";
594         break;
595       case DOWN_CYCLE_TRAVERSAL_KEYS:
596         sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
597         sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
598         sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
599         type = "downCycleDefaultFocusTraversalKeys";
600         break;
601       default:
602         throw new IllegalArgumentException ();
603       }
604     int i = keystrokes.size ();
605     Iterator iter = keystrokes.iterator ();
606     while (--i >= 0)
607       {
608         Object o = iter.next ();
609         if (!(o instanceof AWTKeyStroke)
610             || sa.contains (o) || sb.contains (o) || sc.contains (o)
611             || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
612           throw new IllegalArgumentException ();
613       }
614     keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
615     firePropertyChange (type, defaultFocusKeys[id], keystrokes);
616     defaultFocusKeys[id] = keystrokes;
617   }
618 
619   /**
620    * Retrieve the default {@link java.util.Set} of focus traversal
621    * keys for one of the focus traversal directions.
622    *
623    * @param id focus traversal direction identifier
624    *
625    * @return the default set of AWTKeyStrokes
626    *
627    * @see #FORWARD_TRAVERSAL_KEYS
628    * @see #BACKWARD_TRAVERSAL_KEYS
629    * @see #UP_CYCLE_TRAVERSAL_KEYS
630    * @see #DOWN_CYCLE_TRAVERSAL_KEYS
631    */
getDefaultFocusTraversalKeys(int id)632   public Set<AWTKeyStroke> getDefaultFocusTraversalKeys (int id)
633   {
634     if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
635       throw new IllegalArgumentException ();
636     return defaultFocusKeys[id];
637   }
638 
639   /**
640    * Retrieve the current focus cycle root, or null if the focus owner
641    * was not set by a thread in the current {@link
642    * java.lang.ThreadGroup}.
643    *
644    * @return the current focus cycle root or null
645    */
getCurrentFocusCycleRoot()646   public Container getCurrentFocusCycleRoot ()
647   {
648     return (Container) getObject (currentFocusCycleRoots);
649   }
650 
651   /**
652    * Retrieve the current focus cycle root, regardless of whether or
653    * not it was made set by a thread in the current {@link
654    * java.lang.ThreadGroup}.
655    *
656    * @return the current focus cycle root
657    * @throws SecurityException if this is not the keyboard focus
658    * manager associated with the current {@link java.lang.ThreadGroup}
659    */
getGlobalCurrentFocusCycleRoot()660   protected Container getGlobalCurrentFocusCycleRoot ()
661   {
662     return (Container) getGlobalObject (currentFocusCycleRoots, true);
663   }
664 
665   /**
666    * Set the {@link Container} that will be returned by {@link
667    * #getCurrentFocusCycleRoot} (when it is called from the current
668    * {@link java.lang.ThreadGroup}) and {@link
669    * #getGlobalCurrentFocusCycleRoot}.  This method does not actually
670    * make <code>cycleRoot</code> the current focus cycle root.
671    *
672    * @param cycleRoot the focus cycle root to return from
673    * getCurrentFocusCycleRoot and getGlobalCurrentFocusCycleRoot
674    */
setGlobalCurrentFocusCycleRoot(Container cycleRoot)675   public void setGlobalCurrentFocusCycleRoot (Container cycleRoot)
676   {
677     setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot");
678   }
679 
680   /**
681    * Registers the supplied property change listener for receiving
682    * events caused by the following property changes:
683    *
684    * <ul>
685    * <li>the current focus owner ("focusOwner")</li>
686    * <li>the permanent focus owner ("permanentFocusOwner")</li>
687    * <li>the focused window ("focusedWindow")</li>
688    * <li>the active window ("activeWindow")</li>
689    * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
690    * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
691    * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
692    * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
693    * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
694    * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
695    * </ul>
696    *
697    * If the supplied listener is null, nothing occurs.
698    *
699    * @param l the new listener to register.
700    * @see KeyboardFocusManager#addPropertyChangeListener(String, java.beans.PropertyChangeListener)
701    */
addPropertyChangeListener(PropertyChangeListener l)702   public void addPropertyChangeListener(PropertyChangeListener l)
703   {
704     if (l != null)
705       propertyChangeSupport.addPropertyChangeListener(l);
706   }
707 
708   /**
709    * Removes the supplied property change listener from the list
710    * of registered listeners.  If the supplied listener is null,
711    * nothing occurs.
712    *
713    * @param l the listener to remove.
714    */
removePropertyChangeListener(PropertyChangeListener l)715   public void removePropertyChangeListener(PropertyChangeListener l)
716   {
717     if (l != null)
718       propertyChangeSupport.removePropertyChangeListener(l);
719   }
720 
721   /**
722    * Returns the currently registered property change listeners
723    * in array form.  The returned array is empty if no listeners are
724    * currently registered.
725    *
726    * @return an array of registered property change listeners.
727    */
getPropertyChangeListeners()728   public PropertyChangeListener[] getPropertyChangeListeners()
729   {
730     return propertyChangeSupport.getPropertyChangeListeners();
731   }
732 
733   /**
734    * Registers a property change listener for receiving events relating
735    * to a change to a specified property.  The supplied property name can be
736    * either user-defined or one from the following list of properties
737    * relevant to this class:
738    *
739    * <ul>
740    * <li>the current focus owner ("focusOwner")</li>
741    * <li>the permanent focus owner ("permanentFocusOwner")</li>
742    * <li>the focused window ("focusedWindow")</li>
743    * <li>the active window ("activeWindow")</li>
744    * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
745    * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
746    * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
747    * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
748    * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
749    * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
750    * </ul>
751    *
752    * Nothing occurs if a null listener is supplied.  null is regarded as a valid property name.
753    *
754    * @param name the name of the property to handle change events for.
755    * @param l the listener to register for changes to the specified property.
756    * @see KeyboardFocusManager#addPropertyChangeListener(java.beans.PropertyChangeListener)
757    */
addPropertyChangeListener(String name, PropertyChangeListener l)758   public void addPropertyChangeListener(String name, PropertyChangeListener l)
759   {
760     if (l != null)
761       propertyChangeSupport.addPropertyChangeListener(name, l);
762   }
763 
764   /**
765    * Removes the supplied property change listener registered for the
766    * specified property from the list of registered listeners.  If the
767    * supplied listener is null, nothing occurs.
768    *
769    * @param name the name of the property the listener is
770    *        monitoring changes to.
771    * @param l the listener to remove.
772    */
removePropertyChangeListener(String name, PropertyChangeListener l)773   public void removePropertyChangeListener(String name,
774                                            PropertyChangeListener l)
775   {
776     if (l != null)
777       propertyChangeSupport.removePropertyChangeListener(name, l);
778   }
779 
780   /**
781    * Returns the currently registered property change listeners
782    * in array form, which listen for changes to the supplied property.
783    * The returned array is empty, if no listeners are currently registered
784    * for events pertaining to the supplied property.
785    *
786    * @param name The property the returned listeners monitor for changes.
787    * @return an array of registered property change listeners which
788    *         listen for changes to the supplied property.
789    */
getPropertyChangeListeners(String name)790   public PropertyChangeListener[] getPropertyChangeListeners(String name)
791   {
792     return propertyChangeSupport.getPropertyChangeListeners(name);
793   }
794 
795   /**
796    * Fires a property change event as a response to a change to
797    * to the specified property.  The event is only fired if a
798    * change has actually occurred (i.e. o and n are different).
799    *
800    * @param name The name of the property to which a change occurred.
801    * @param o The old value of the property.
802    * @param n The new value of the property.
803    */
firePropertyChange(String name, Object o, Object n)804   protected void firePropertyChange(String name, Object o, Object n)
805   {
806     propertyChangeSupport.firePropertyChange(name, o, n);
807   }
808 
809   /**
810    * Registers a vetoable property change listener for receiving events
811    * relating to the following properties:
812    *
813    * <ul>
814    * <li>the current focus owner ("focusOwner")</li>
815    * <li>the permanent focus owner ("permanentFocusOwner")</li>
816    * <li>the focused window ("focusedWindow")</li>
817    * <li>the active window ("activeWindow")</li>
818    * </ul>
819    *
820    * Nothing occurs if a null listener is supplied.
821    *
822    * @param l the listener to register.
823    * @see KeyboardFocusManager#addVetoableChangeListener(String, java.beans.VetoableChangeListener)
824    */
addVetoableChangeListener(VetoableChangeListener l)825   public void addVetoableChangeListener(VetoableChangeListener l)
826   {
827     if (l != null)
828       vetoableChangeSupport.addVetoableChangeListener(l);
829   }
830 
831   /**
832    * Removes the supplied vetoable property change listener from
833    * the list of registered listeners.  If the supplied listener
834    * is null, nothing occurs.
835    *
836    * @param l the listener to remove.
837    */
removeVetoableChangeListener(VetoableChangeListener l)838   public void removeVetoableChangeListener(VetoableChangeListener l)
839   {
840     if (l != null)
841       vetoableChangeSupport.removeVetoableChangeListener(l);
842   }
843 
844   /**
845    * Returns the currently registered vetoable property change listeners
846    * in array form.  The returned array is empty if no listeners are
847    * currently registered.
848    *
849    * @return an array of registered vetoable property change listeners.
850    * @since 1.4
851    */
getVetoableChangeListeners()852   public VetoableChangeListener[] getVetoableChangeListeners()
853   {
854     return vetoableChangeSupport.getVetoableChangeListeners();
855   }
856 
857   /**
858    * Registers a vetoable property change listener for receiving events relating
859    * to a vetoable change to a specified property.  The supplied property name can be
860    * either user-defined or one from the following list of properties
861    * relevant to this class:
862    *
863    * <ul>
864    * <li>the current focus owner ("focusOwner")</li>
865    * <li>the permanent focus owner ("permanentFocusOwner")</li>
866    * <li>the focused window ("focusedWindow")</li>
867    * <li>the active window ("activeWindow")</li>
868    * </ul>
869    *
870    * Nothing occurs if a null listener is supplied.  null is regarded as a valid property name.
871    *
872    * @param name the name of the property to handle change events for.
873    * @param l the listener to register for changes to the specified property.
874    * @see KeyboardFocusManager#addVetoableChangeListener(java.beans.VetoableChangeListener)
875    */
addVetoableChangeListener(String name, VetoableChangeListener l)876   public void addVetoableChangeListener(String name, VetoableChangeListener l)
877   {
878     if (l != null)
879       vetoableChangeSupport.addVetoableChangeListener(name, l);
880   }
881 
882   /**
883    * Removes the supplied vetoable property change listener registered
884    * for the specified property from the list of registered listeners.
885    * If the supplied listener is null, nothing occurs.
886    *
887    * @param name the name of the vetoable property the listener is
888    *        monitoring changes to.
889    * @param l the listener to remove.
890    */
removeVetoableChangeListener(String name, VetoableChangeListener l)891   public void removeVetoableChangeListener(String name,
892                                            VetoableChangeListener l)
893   {
894     if (l != null)
895       vetoableChangeSupport.removeVetoableChangeListener(name, l);
896   }
897 
898   /**
899    * Returns the currently registered vetoable property change listeners
900    * in array form, which listen for changes to the supplied property.
901    * The returned array is empty, if no listeners are currently registered
902    * for events pertaining to the supplied property.
903    *
904    * @param name The property the returned listeners monitor for changes.
905    * @return an array of registered property change listeners which
906    *         listen for changes to the supplied property.
907    * @since 1.4
908    */
getVetoableChangeListeners(String name)909   public VetoableChangeListener[] getVetoableChangeListeners(String name)
910   {
911     return vetoableChangeSupport.getVetoableChangeListeners(name);
912   }
913 
914   /**
915    * Fires a property change event as a response to a vetoable change to
916    * to the specified property.  The event is only fired if a
917    * change has actually occurred (i.e. o and n are different).
918    * In the event that the property change is vetoed, the following
919    * occurs:
920    *
921    * <ol>
922    * <li>
923    * This method throws a <code>PropertyVetoException</code> to
924    * the proposed change.
925    * </li>
926    * <li>
927    * A new event is fired to reverse the previous change.
928    * </li>
929    * <li>
930    * This method again throws a <code>PropertyVetoException</code>
931    * in response to the reversion.
932    * </li>
933    * </ol>
934    *
935    * @param name The name of the property to which a change occurred.
936    * @param o The old value of the property.
937    * @param n The new value of the property.
938    * @throws PropertyVetoException if one of the listeners vetos
939    *         the change by throwing this exception.
940    */
fireVetoableChange(String name, Object o, Object n)941   protected void fireVetoableChange(String name, Object o, Object n)
942     throws PropertyVetoException
943   {
944     vetoableChangeSupport.fireVetoableChange(name, o, n);
945   }
946 
947   /**
948    * Adds a key event dispatcher to the list of registered dispatchers.
949    * When a key event is fired, each dispatcher's <code>dispatchKeyEvent</code>
950    * method is called in the order that they were added, prior to the manager
951    * dispatching the event itself.  Notifications halt when one of the
952    * dispatchers returns true.
953    * <br />
954    * <br />
955    * The same dispatcher can exist multiple times within the list
956    * of registered dispatchers, and there is no limit on the length
957    * of this list.  A null dispatcher is simply ignored.
958    *
959    * @param dispatcher The dispatcher to register.
960    */
addKeyEventDispatcher(KeyEventDispatcher dispatcher)961   public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
962   {
963     if (dispatcher != null)
964       keyEventDispatchers.add(dispatcher);
965   }
966 
967   /**
968    * Removes the specified key event dispatcher from the list of
969    * registered dispatchers.  The manager always dispatches events,
970    * regardless of its existence within the list.  The manager
971    * can be added and removed from the list, as with any other
972    * dispatcher, but this does not affect its ability to dispatch
973    * key events.  Non-existent and null dispatchers are simply ignored
974    * by this method.
975    *
976    * @param dispatcher The dispatcher to remove.
977    */
removeKeyEventDispatcher(KeyEventDispatcher dispatcher)978   public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
979   {
980     keyEventDispatchers.remove(dispatcher);
981   }
982 
983   /**
984    * Returns the currently registered key event dispatchers in <code>List</code>
985    * form.  At present, this only includes dispatchers explicitly registered
986    * via the <code>addKeyEventDispatcher()</code> method, but this behaviour
987    * is subject to change and should not be depended on.  The manager itself
988    * may be a member of the list, but only if explicitly registered.  If no
989    * dispatchers have been registered, the list will be empty.
990    *
991    * @return A list of explicitly registered key event dispatchers.
992    * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
993    */
getKeyEventDispatchers()994   protected List<KeyEventDispatcher> getKeyEventDispatchers ()
995   {
996     return (List<KeyEventDispatcher>) keyEventDispatchers.clone ();
997   }
998 
999   /**
1000    * Adds a key event post processor to the list of registered post processors.
1001    * Post processors work in the same way as key event dispatchers, except
1002    * that they are invoked after the manager has dispatched the key event,
1003    * and not prior to this.  Each post processor's <code>postProcessKeyEvent</code>
1004    * method is called to see if any post processing needs to be performed.  THe
1005    * processors are called in the order in which they were added to the list,
1006    * and notifications continue until one returns true.  As with key event
1007    * dispatchers, the manager is implicitly called following this process,
1008    * regardless of whether or not it is present within the list.
1009    * <br />
1010    * <br />
1011    * The same post processor can exist multiple times within the list
1012    * of registered post processors, and there is no limit on the length
1013    * of this list.  A null post processor is simply ignored.
1014    *
1015    * @param postProcessor the post processor to register.
1016    * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
1017    */
addKeyEventPostProcessor(KeyEventPostProcessor postProcessor)1018   public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
1019   {
1020     if (postProcessor != null)
1021       keyEventPostProcessors.add (postProcessor);
1022   }
1023 
1024   /**
1025    * Removes the specified key event post processor from the list of
1026    * registered post processors.  The manager always post processes events,
1027    * regardless of its existence within the list.  The manager
1028    * can be added and removed from the list, as with any other
1029    * post processor, but this does not affect its ability to post process
1030    * key events.  Non-existent and null post processors are simply ignored
1031    * by this method.
1032    *
1033    * @param postProcessor the post processor to remove.
1034    */
removeKeyEventPostProcessor(KeyEventPostProcessor postProcessor)1035   public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
1036   {
1037     keyEventPostProcessors.remove (postProcessor);
1038   }
1039 
1040   /**
1041    * Returns the currently registered key event post processors in <code>List</code>
1042    * form.  At present, this only includes post processors explicitly registered
1043    * via the <code>addKeyEventPostProcessor()</code> method, but this behaviour
1044    * is subject to change and should not be depended on.  The manager itself
1045    * may be a member of the list, but only if explicitly registered.  If no
1046    * post processors have been registered, the list will be empty.
1047    *
1048    * @return A list of explicitly registered key event post processors.
1049    * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor)
1050    */
getKeyEventPostProcessors()1051   protected List<KeyEventPostProcessor> getKeyEventPostProcessors ()
1052   {
1053     return (List<KeyEventPostProcessor>) keyEventPostProcessors.clone ();
1054   }
1055 
1056   /**
1057    * The AWT event dispatcher uses this method to request that the manager
1058    * handle a particular event.  If the manager fails or refuses to
1059    * dispatch the supplied event (this method returns false), the
1060    * AWT event dispatcher will try to dispatch the event itself.
1061    * <br />
1062    * <br />
1063    * The manager is expected to handle all <code>FocusEvent</code>s
1064    * and <code>KeyEvent</code>s, and <code>WindowEvent</code>s
1065    * relating to the focus.  Dispatch is done with regard to the
1066    * the focus owner and the currently focused and active windows.
1067    * In handling the event, the source of the event may be overridden.
1068    * <br />
1069    * <br />
1070    * The actual dispatching is performed by calling
1071    * <code>redispatchEvent()</code>.  This avoids the infinite recursion
1072    * of dispatch requests which may occur if this method is called on
1073    * the target component.
1074    *
1075    * @param e the event to dispatch.
1076    * @return true if the event was dispatched.
1077    * @see KeyboardFocusManager#redispatchEvent(java.awt.Component, java.awt.AWTEvent)
1078    * @see KeyEvent
1079    * @see FocusEvent
1080    * @see WindowEvent
1081    */
dispatchEvent(AWTEvent e)1082   public abstract boolean dispatchEvent (AWTEvent e);
1083 
1084   /**
1085    * Handles redispatching of an event so that recursion of
1086    * dispatch requests does not occur.  Event dispatch methods
1087    * within this manager (<code>dispatchEvent()</code>) and
1088    * the key event dispatchers should use this method to handle
1089    * dispatching rather than the dispatch method of the target
1090    * component.
1091    * <br />
1092    * <br />
1093    * <strong>
1094    * This method is not intended for general consumption, and is
1095    * only for the use of the aforementioned classes.
1096    * </strong>
1097    *
1098    * @param target the target component to which the event is
1099    *        dispatched.
1100    * @param e the event to dispatch.
1101    */
redispatchEvent(Component target, AWTEvent e)1102   public final void redispatchEvent (Component target, AWTEvent e)
1103   {
1104     e.isFocusManagerEvent = true;
1105     target.dispatchEvent (e);
1106     e.isFocusManagerEvent = false;
1107   }
1108 
1109   /**
1110    * Attempts to dispatch key events for which no key event dispatcher
1111    * has so far succeeded.  This method is usually called by
1112    * <code>dispatchEvent()</code> following the sending of the key
1113    * event to any registered key event dispatchers.  If the key
1114    * event reaches this stage, none of the dispatchers returned
1115    * true.  This is, of course, always the case if there are no
1116    * registered dispatchers.
1117    * <br />
1118    * <br />
1119    * If this method also fails to handle the key event, then
1120    * false is returned to the caller.  In the case of
1121    * <code>dispatchEvent()</code>, the calling method may try
1122    * to handle the event itself or simply forward on the
1123    * false result to its caller.  When the event is dispatched
1124    * by this method, a true result is propogated through the
1125    * calling methods.
1126    *
1127    * @param e the key event to dispatch.
1128    * @return true if the event was dispatched successfully.
1129    */
dispatchKeyEvent(KeyEvent e)1130   public abstract boolean dispatchKeyEvent (KeyEvent e);
1131 
1132   /**
1133    * Handles the post processing of key events.  By default,
1134    * this method will map unhandled key events to appropriate
1135    * <code>MenuShortcut</code>s.  The event is consumed
1136    * in the process and the shortcut is activated.  This
1137    * method is usually called by <code>dispatchKeyEvent</code>.
1138    *
1139    * @param e the key event to post process.
1140    * @return true by default, as the event was handled.
1141    */
postProcessKeyEvent(KeyEvent e)1142   public abstract boolean postProcessKeyEvent (KeyEvent e);
1143 
1144   /**
1145    * Handles focus traversal operations for key events which
1146    * represent focus traversal keys in relation to the supplied
1147    * component.  The supplied component is assumed to have the
1148    * focus, whether it does so or not, and the operation is
1149    * carried out as appropriate, with this in mind.
1150    *
1151    * @param focused the component on which to perform focus traversal,
1152    *        on the assumption that this component has the focus.
1153    * @param e the possible focus traversal key event.
1154    */
processKeyEvent(Component focused, KeyEvent e)1155   public abstract void processKeyEvent (Component focused, KeyEvent e);
1156 
1157   /**
1158    * Delays all key events following the specified timestamp until the
1159    * supplied component has focus.  The AWT calls this method when it is
1160    * determined that a focus change may occur within the native windowing
1161    * system.  Any key events which occur following the time specified by
1162    * after are delayed until a <code>FOCUS_GAINED</code> event is received
1163    * for the untilFocused component.  The manager is responsible for ensuring
1164    * this takes place.
1165    *
1166    * @param after the timestamp beyond which all key events are delayed until
1167    *        the supplied component gains focus.
1168    * @param untilFocused the component to wait on gaining focus.
1169    */
enqueueKeyEvents(long after, Component untilFocused)1170   protected abstract void enqueueKeyEvents (long after, Component untilFocused);
1171 
1172   /**
1173    * Removes the key event block specified by the supplied timestamp and component.
1174    * All delayed key events are released for normal dispatching following its
1175    * removal and subsequent key events that would have been blocked are now
1176    * immediately dispatched.  If the specified timestamp is below 0, then
1177    * the request with the oldest timestamp is removed.
1178    *
1179    * @param after the timestamp of the key event block to be removed, or a
1180    *        value smaller than 0 if the oldest is to be removed.
1181    * @param untilFocused the component of the key event block to be removed.
1182    */
dequeueKeyEvents(long after, Component untilFocused)1183   protected abstract void dequeueKeyEvents (long after, Component untilFocused);
1184 
1185   /**
1186    * Discards all key event blocks relating to focus requirements for
1187    * the supplied component, regardless of timestamp.
1188    *
1189    * @param comp the component of the key event block(s) to be removed.
1190    */
discardKeyEvents(Component comp)1191   protected abstract void discardKeyEvents (Component comp);
1192 
1193   /**
1194    * Moves the current focus to the next component following
1195    * comp, based on the current focus traversal policy.  By
1196    * default, only visible, displayable, accepted components
1197    * can receive focus.  <code>Canvas</code>es, <code>Panel</code>s,
1198    * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1199    * <code>Window</code>s and lightweight components are judged
1200    * to be unacceptable by default.  See the
1201    * <code>DefaultFocusTraversalPolicy</code> for more details.
1202    *
1203    * @param comp the component prior to the one which will
1204    *        become the focus, following execution of this method.
1205    * @see DefaultFocusTraversalPolicy
1206    */
focusNextComponent(Component comp)1207   public abstract void focusNextComponent(Component comp);
1208 
1209   /**
1210    * Moves the current focus to the previous component, prior to
1211    * comp, based on the current focus traversal policy.  By
1212    * default, only visible, displayable, accepted components
1213    * can receive focus.  <code>Canvas</code>es, <code>Panel</code>s,
1214    * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1215    * <code>Window</code>s and lightweight components are judged
1216    * to be unacceptable by default.  See the
1217    * <code>DefaultFocusTraversalPolicy</code> for more details.
1218    *
1219    * @param comp the component following the one which will
1220    *        become the focus, following execution of this method.
1221    * @see DefaultFocusTraversalPolicy
1222    */
focusPreviousComponent(Component comp)1223   public abstract void focusPreviousComponent(Component comp);
1224 
1225   /**
1226    * Moves the current focus upwards by one focus cycle.
1227    * Both the current focus owner and current focus cycle root
1228    * become the focus cycle root of the supplied component.
1229    * However, in the case of a <code>Window</code>, the default
1230    * focus component becomes the focus owner and the focus cycle
1231    * root is not changed.
1232    *
1233    * @param comp the component used as part of the focus traversal.
1234    */
upFocusCycle(Component comp)1235   public abstract void upFocusCycle(Component comp);
1236 
1237   /**
1238    * Moves the current focus downwards by one focus cycle.
1239    * If the supplied container is a focus cycle root, then this
1240    * becomes the current focus cycle root and the focus goes
1241    * to the default component of the specified container.
1242    * Nothing happens for non-focus cycle root containers.
1243    *
1244    * @param cont the container used as part of the focus traversal.
1245    */
downFocusCycle(Container cont)1246   public abstract void downFocusCycle(Container cont);
1247 
1248   /**
1249    * Moves the current focus to the next component, based on the
1250    * current focus traversal policy.  By default, only visible,
1251    * displayable, accepted component can receive focus.
1252    * <code>Canvas</code>es, <code>Panel</code>s,
1253    * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1254    * <code>Window</code>s and lightweight components are judged
1255    * to be unacceptable by default.  See the
1256    * <code>DefaultFocusTraversalPolicy</code> for more details.
1257    *
1258    * @see DefaultFocusTraversalPolicy
1259    */
focusNextComponent()1260   public final void focusNextComponent()
1261   {
1262     focusNextComponent (null);
1263   }
1264 
1265   /**
1266    * Moves the current focus to the previous component, based on the
1267    * current focus traversal policy.  By default, only visible,
1268    * displayable, accepted component can receive focus.
1269    * <code>Canvas</code>es, <code>Panel</code>s,
1270    * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1271    * <code>Window</code>s and lightweight components are judged
1272    * to be unacceptable by default.  See the
1273    * <code>DefaultFocusTraversalPolicy</code> for more details.
1274    *
1275    * @see DefaultFocusTraversalPolicy
1276    */
focusPreviousComponent()1277   public final void focusPreviousComponent()
1278   {
1279     focusPreviousComponent (null);
1280   }
1281 
1282   /**
1283    * Moves the current focus upwards by one focus cycle,
1284    * so that the new focus owner is the focus cycle root
1285    * of the current owner.  The current focus cycle root then
1286    * becomes the focus cycle root of the new focus owner.
1287    * However, in the case of the focus cycle root of the
1288    * current focus owner being a <code>Window</code>, the default
1289    * component of this window becomes the focus owner and the
1290    * focus cycle root is not changed.
1291    */
upFocusCycle()1292   public final void upFocusCycle()
1293   {
1294     upFocusCycle (null);
1295   }
1296 
1297   /**
1298    * Moves the current focus downwards by one focus cycle,
1299    * iff the current focus cycle root is a <code>Container</code>.
1300    * Usually, the new focus owner is set to the default component
1301    * of the container and the current focus cycle root is set
1302    * to the current focus owner.  Nothing occurs if the current
1303    * focus cycle root is not a container.
1304    */
downFocusCycle()1305   public final void downFocusCycle()
1306   {
1307     Component focusOwner = getGlobalFocusOwner ();
1308     if (focusOwner instanceof Container
1309         && ((Container) focusOwner).isFocusCycleRoot ())
1310       downFocusCycle ((Container) focusOwner);
1311   }
1312 
1313   /**
1314    * Retrieve an object from one of the global object {@link
1315    * java.util.Map}s, if the object was set by the a thread in the
1316    * current {@link java.lang.ThreadGroup}.  Otherwise, return null.
1317    *
1318    * @param globalMap one of the global object Maps
1319    *
1320    * @return a global object set by the current ThreadGroup, or null
1321    *
1322    * @see #getFocusOwner()
1323    * @see #getPermanentFocusOwner()
1324    * @see #getFocusedWindow()
1325    * @see #getActiveWindow()
1326    * @see #getCurrentFocusCycleRoot()
1327    */
getObject(Map globalMap)1328   private Object getObject (Map globalMap)
1329   {
1330     ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1331     return globalMap.get (currentGroup);
1332   }
1333 
1334   /**
1335    * Retrieve an object from one of the global object {@link
1336    * java.util.Map}s, regardless of whether or not the object was set
1337    * by a thread in the current {@link java.lang.ThreadGroup}.
1338    *
1339    * @param globalMap one of the global object Maps
1340    *
1341    * @return a global object set by the current ThreadGroup, or null
1342    *
1343    * @throws SecurityException if this is not the keyboard focus
1344    * manager associated with the current {@link java.lang.ThreadGroup}
1345    *
1346    * @see #getGlobalFocusOwner()
1347    * @see #getGlobalPermanentFocusOwner()
1348    * @see #getGlobalFocusedWindow()
1349    * @see #getGlobalActiveWindow()
1350    * @see #getGlobalCurrentFocusCycleRoot()
1351    */
getGlobalObject(Map globalMap, boolean checkThread)1352   private Object getGlobalObject (Map globalMap, boolean checkThread)
1353   {
1354     if (checkThread)
1355       {
1356         ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1357         KeyboardFocusManager managerForCallingThread =
1358          (KeyboardFocusManager) currentKeyboardFocusManagers.get(currentGroup);
1359 
1360         if (this != managerForCallingThread)
1361           throw new SecurityException ("Attempted to retrieve an object from a "
1362                                        + "keyboard focus manager that isn't "
1363                                 + "associated with the current thread group.");
1364       }
1365     synchronized (globalMap)
1366       {
1367         Collection globalObjects = globalMap.values ();
1368         Iterator i = globalObjects.iterator ();
1369         Component globalObject;
1370 
1371         while (i.hasNext ())
1372           {
1373             globalObject = (Component) i.next ();
1374             if (globalObject != null)
1375               return globalObject;
1376           }
1377       }
1378 
1379     // No Object was found.
1380     return null;
1381   }
1382 
1383   /**
1384    * Set an object in one of the global object {@link java.util.Map}s,
1385    * that will be returned by subsequent calls to getGlobalObject on
1386    * the same {@link java.util.Map}.
1387    *
1388    * @param globalMap one of the global object Maps
1389    * @param newObject the object to set
1390    * @param property the property that will change
1391    *
1392    * @see #setGlobalFocusOwner(Component)
1393    * @see #setGlobalPermanentFocusOwner(Component)
1394    * @see #setGlobalFocusedWindow(Window)
1395    * @see #setGlobalActiveWindow(Window)
1396    * @see #setGlobalCurrentFocusCycleRoot(Container)
1397    */
setGlobalObject(Map globalMap, Object newObject, String property)1398   private void setGlobalObject (Map globalMap,
1399                                 Object newObject,
1400                                 String property)
1401   {
1402     synchronized (globalMap)
1403       {
1404         // Save old object.
1405         Object oldObject = getGlobalObject(globalMap, false);
1406 
1407         // Nullify old object.
1408         Collection threadGroups = globalMap.keySet ();
1409         Iterator i = threadGroups.iterator ();
1410         while (i.hasNext ())
1411           {
1412             ThreadGroup oldThreadGroup = (ThreadGroup) i.next ();
1413             if (globalMap.get (oldThreadGroup) != null)
1414               {
1415                 globalMap.put (oldThreadGroup, null);
1416                 // There should only be one object set at a time, so
1417                 // we can short circuit.
1418                 break;
1419               }
1420           }
1421 
1422         ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1423         firePropertyChange (property, oldObject, newObject);
1424         try
1425           {
1426             fireVetoableChange (property, oldObject, newObject);
1427             // Set new object.
1428             globalMap.put (currentGroup, newObject);
1429           }
1430         catch (PropertyVetoException e)
1431           {
1432           }
1433       }
1434   }
1435 
1436 
1437   /**
1438    * Maps focus requests from heavyweight to lightweight components.
1439    */
1440   private static HashMap focusRequests = new HashMap();
1441 
1442   /**
1443    * Retargets focus events that come from the peer (which only know about
1444    * heavyweight components) to go to the correct lightweight component
1445    * if appropriate.
1446    *
1447    * @param ev the event to check
1448    *
1449    * @return the retargetted event
1450    */
retargetFocusEvent(AWTEvent ev)1451   static AWTEvent retargetFocusEvent(AWTEvent ev)
1452   {
1453     if (ev instanceof FocusEvent)
1454       {
1455         FocusEvent fe = (FocusEvent) ev;
1456         Component target = fe.getComponent();
1457         if (focusRequests.containsKey(target))
1458           {
1459             Component lightweight = (Component) focusRequests.get(target);
1460             ev = new FocusEvent(lightweight, fe.id, fe.isTemporary());
1461             focusRequests.remove(target);
1462           }
1463       }
1464     return ev;
1465   }
1466 
1467   /**
1468    * Adds a lightweight focus request for a heavyweight component.
1469    *
1470    * @param heavyweight the heavyweight from which we will receive a focus
1471    *        event soon
1472    * @param lightweight the lightweight that ultimately receives the request
1473    */
addLightweightFocusRequest(Component heavyweight, Component lightweight)1474   static void addLightweightFocusRequest(Component heavyweight,
1475                                          Component lightweight)
1476   {
1477     focusRequests.put(heavyweight, lightweight);
1478   }
1479 }
1480