Source for java.awt.KeyboardFocusManager

   1: /* KeyboardFocusManager.java -- manage component focusing via the keyboard
   2:    Copyright (C) 2002, 2004  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();
 152:     s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0));
 153:     s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
 154:                                        KeyEvent.CTRL_DOWN_MASK));
 155:     DEFAULT_FORWARD_KEYS = Collections.unmodifiableSet(s);
 156:     s = new HashSet();
 157:     s.add(AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
 158:                                        KeyEvent.SHIFT_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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 558:   public void setDefaultFocusTraversalKeys (int id, Set keystrokes)
 559:   {
 560:     if (id != KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS &&
 561:         id != KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS &&
 562:         id != KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS &&
 563:         id != KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS)
 564:       throw new IllegalArgumentException ();
 565: 
 566:     if (keystrokes == null)
 567:       throw new IllegalArgumentException ();
 568: 
 569:     Set sa;
 570:     Set sb;
 571:     Set sc;
 572:     String type;
 573:     switch (id)
 574:       {
 575:       case FORWARD_TRAVERSAL_KEYS:
 576:         sa = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
 577:         sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
 578:         sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
 579:         type = "forwardDefaultFocusTraversalKeys";
 580:         break;
 581:       case BACKWARD_TRAVERSAL_KEYS:
 582:         sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
 583:         sb = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
 584:         sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
 585:         type = "backwardDefaultFocusTraversalKeys";
 586:         break;
 587:       case UP_CYCLE_TRAVERSAL_KEYS:
 588:         sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
 589:         sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
 590:         sc = defaultFocusKeys[DOWN_CYCLE_TRAVERSAL_KEYS];
 591:         type = "upCycleDefaultFocusTraversalKeys";
 592:         break;
 593:       case DOWN_CYCLE_TRAVERSAL_KEYS:
 594:         sa = defaultFocusKeys[FORWARD_TRAVERSAL_KEYS];
 595:         sb = defaultFocusKeys[BACKWARD_TRAVERSAL_KEYS];
 596:         sc = defaultFocusKeys[UP_CYCLE_TRAVERSAL_KEYS];
 597:         type = "downCycleDefaultFocusTraversalKeys";
 598:         break;
 599:       default:
 600:         throw new IllegalArgumentException ();
 601:       }
 602:     int i = keystrokes.size ();
 603:     Iterator iter = keystrokes.iterator ();
 604:     while (--i >= 0)
 605:       {
 606:         Object o = iter.next ();
 607:         if (!(o instanceof AWTKeyStroke)
 608:             || sa.contains (o) || sb.contains (o) || sc.contains (o)
 609:             || ((AWTKeyStroke) o).keyCode == KeyEvent.VK_UNDEFINED)
 610:           throw new IllegalArgumentException ();
 611:       }
 612:     keystrokes = Collections.unmodifiableSet (new HashSet (keystrokes));
 613:     firePropertyChange (type, defaultFocusKeys[id], keystrokes);
 614:     defaultFocusKeys[id] = keystrokes;
 615:   }
 616: 
 617:   /**
 618:    * Retrieve the default {@link java.util.Set} of focus traversal
 619:    * keys for one of the focus traversal directions.
 620:    *
 621:    * @param id focus traversal direction identifier
 622:    *
 623:    * @return the default set of AWTKeyStrokes
 624:    *
 625:    * @see #FORWARD_TRAVERSAL_KEYS
 626:    * @see #BACKWARD_TRAVERSAL_KEYS
 627:    * @see #UP_CYCLE_TRAVERSAL_KEYS
 628:    * @see #DOWN_CYCLE_TRAVERSAL_KEYS
 629:    */
 630:   public Set getDefaultFocusTraversalKeys (int id)
 631:   {
 632:     if (id < FORWARD_TRAVERSAL_KEYS || id > DOWN_CYCLE_TRAVERSAL_KEYS)
 633:       throw new IllegalArgumentException ();
 634:     return defaultFocusKeys[id];
 635:   }
 636: 
 637:   /**
 638:    * Retrieve the current focus cycle root, or null if the focus owner
 639:    * was not set by a thread in the current {@link
 640:    * java.lang.ThreadGroup}.
 641:    *
 642:    * @return the current focus cycle root or null
 643:    */
 644:   public Container getCurrentFocusCycleRoot ()
 645:   {
 646:     return (Container) getObject (currentFocusCycleRoots);
 647:   }
 648: 
 649:   /**
 650:    * Retrieve the current focus cycle root, regardless of whether or
 651:    * not it was made set by a thread in the current {@link
 652:    * java.lang.ThreadGroup}.
 653:    *
 654:    * @return the current focus cycle root
 655:    * @throws SecurityException if this is not the keyboard focus
 656:    * manager associated with the current {@link java.lang.ThreadGroup}
 657:    */
 658:   protected Container getGlobalCurrentFocusCycleRoot ()
 659:   {
 660:     return (Container) getGlobalObject (currentFocusCycleRoots, true);
 661:   }
 662: 
 663:   /**
 664:    * Set the {@link Container} that will be returned by {@link
 665:    * #getCurrentFocusCycleRoot} (when it is called from the current
 666:    * {@link java.lang.ThreadGroup}) and {@link
 667:    * #getGlobalCurrentFocusCycleRoot}.  This method does not actually
 668:    * make <code>cycleRoot</code> the current focus cycle root.
 669:    * 
 670:    * @param cycleRoot the focus cycle root to return from
 671:    * getCurrentFocusCycleRoot and getGlobalCurrentFocusCycleRoot
 672:    */
 673:   public void setGlobalCurrentFocusCycleRoot (Container cycleRoot)
 674:   {
 675:     setGlobalObject (currentFocusCycleRoots, cycleRoot, "currentFocusCycleRoot");
 676:   }
 677: 
 678:   /**
 679:    * Registers the supplied property change listener for receiving
 680:    * events caused by the following property changes:
 681:    *
 682:    * <ul>
 683:    * <li>the current focus owner ("focusOwner")</li>
 684:    * <li>the permanent focus owner ("permanentFocusOwner")</li>
 685:    * <li>the focused window ("focusedWindow")</li>
 686:    * <li>the active window ("activeWindow")</li>
 687:    * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
 688:    * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
 689:    * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
 690:    * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
 691:    * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
 692:    * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
 693:    * </ul>
 694:    *
 695:    * If the supplied listener is null, nothing occurs.
 696:    *
 697:    * @param l the new listener to register.
 698:    * @see KeyboardFocusManager#addPropertyChangeListener(String, java.beans.PropertyChangeListener)
 699:    */
 700:   public void addPropertyChangeListener(PropertyChangeListener l)
 701:   {
 702:     if (l != null)
 703:       propertyChangeSupport.addPropertyChangeListener(l);
 704:   }
 705: 
 706:   /**
 707:    * Removes the supplied property change listener from the list
 708:    * of registered listeners.  If the supplied listener is null,
 709:    * nothing occurs.
 710:    *
 711:    * @param l the listener to remove.
 712:    */
 713:   public void removePropertyChangeListener(PropertyChangeListener l)
 714:   {
 715:     if (l != null)
 716:       propertyChangeSupport.removePropertyChangeListener(l);
 717:   }
 718: 
 719:   /**
 720:    * Returns the currently registered property change listeners
 721:    * in array form.  The returned array is empty if no listeners are
 722:    * currently registered.
 723:    *
 724:    * @return an array of registered property change listeners.
 725:    */
 726:   public PropertyChangeListener[] getPropertyChangeListeners()
 727:   {
 728:     return propertyChangeSupport.getPropertyChangeListeners();
 729:   }
 730: 
 731:   /**
 732:    * Registers a property change listener for receiving events relating
 733:    * to a change to a specified property.  The supplied property name can be
 734:    * either user-defined or one from the following list of properties
 735:    * relevant to this class:
 736:    *
 737:    * <ul>
 738:    * <li>the current focus owner ("focusOwner")</li>
 739:    * <li>the permanent focus owner ("permanentFocusOwner")</li>
 740:    * <li>the focused window ("focusedWindow")</li>
 741:    * <li>the active window ("activeWindow")</li>
 742:    * <li>the default focus traversal policy ("defaultFocusTraversalPolicy")</li>
 743:    * <li>the default set of forward traversal keys ("forwardDefaultFocusTraversalKeys")</li>
 744:    * <li>the default set of backward traversal keys ("backwardDefaultFocusTraversalKeys")</li>
 745:    * <li>the default set of up cycle traversal keys ("upCycleDefaultFocusTraversalKeys")</li>
 746:    * <li>the default set of down cycle traversal keys ("downCycleDefaultFocusTraversalKeys")</li>
 747:    * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
 748:    * </ul>
 749:    *
 750:    * Nothing occurs if a null listener is supplied.  null is regarded as a valid property name.
 751:    *
 752:    * @param name the name of the property to handle change events for.
 753:    * @param l the listener to register for changes to the specified property. 
 754:    * @see KeyboardFocusManager#addPropertyChangeListener(java.beans.PropertyChangeListener)
 755:    */
 756:   public void addPropertyChangeListener(String name, PropertyChangeListener l)
 757:   {
 758:     if (l != null)
 759:       propertyChangeSupport.addPropertyChangeListener(name, l);
 760:   }
 761: 
 762:   /**
 763:    * Removes the supplied property change listener registered for the
 764:    * specified property from the list of registered listeners.  If the
 765:    * supplied listener is null, nothing occurs.
 766:    *
 767:    * @param name the name of the property the listener is
 768:    *        monitoring changes to.
 769:    * @param l the listener to remove.
 770:    */
 771:   public void removePropertyChangeListener(String name,
 772:                                            PropertyChangeListener l)
 773:   {
 774:     if (l != null)
 775:       propertyChangeSupport.removePropertyChangeListener(name, l);
 776:   }
 777: 
 778:   /**
 779:    * Returns the currently registered property change listeners
 780:    * in array form, which listen for changes to the supplied property.
 781:    * The returned array is empty, if no listeners are currently registered
 782:    * for events pertaining to the supplied property.
 783:    *
 784:    * @param name The property the returned listeners monitor for changes.
 785:    * @return an array of registered property change listeners which
 786:    *         listen for changes to the supplied property.
 787:    */
 788:   public PropertyChangeListener[] getPropertyChangeListeners(String name)
 789:   {
 790:     return propertyChangeSupport.getPropertyChangeListeners(name);
 791:   }
 792: 
 793:   /**
 794:    * Fires a property change event as a response to a change to
 795:    * to the specified property.  The event is only fired if a
 796:    * change has actually occurred (i.e. o and n are different).
 797:    *
 798:    * @param name The name of the property to which a change occurred.
 799:    * @param o The old value of the property.
 800:    * @param n The new value of the property.
 801:    */
 802:   protected void firePropertyChange(String name, Object o, Object n)
 803:   {
 804:     propertyChangeSupport.firePropertyChange(name, o, n);
 805:   }
 806: 
 807:   /**
 808:    * Registers a vetoable property change listener for receiving events
 809:    * relating to the following properties:
 810:    *
 811:    * <ul>
 812:    * <li>the current focus owner ("focusOwner")</li>
 813:    * <li>the permanent focus owner ("permanentFocusOwner")</li>
 814:    * <li>the focused window ("focusedWindow")</li>
 815:    * <li>the active window ("activeWindow")</li>
 816:    * </ul>
 817:    *
 818:    * Nothing occurs if a null listener is supplied.
 819:    *
 820:    * @param l the listener to register. 
 821:    * @see KeyboardFocusManager#addVetoableChangeListener(String, java.beans.VetoableChangeListener)
 822:    */
 823:   public void addVetoableChangeListener(VetoableChangeListener l)
 824:   {
 825:     if (l != null)
 826:       vetoableChangeSupport.addVetoableChangeListener(l);
 827:   }
 828: 
 829:   /**
 830:    * Removes the supplied vetoable property change listener from
 831:    * the list of registered listeners.  If the supplied listener
 832:    * is null, nothing occurs.
 833:    *
 834:    * @param l the listener to remove.
 835:    */
 836:   public void removeVetoableChangeListener(VetoableChangeListener l)
 837:   {
 838:     if (l != null)
 839:       vetoableChangeSupport.removeVetoableChangeListener(l);
 840:   }
 841: 
 842:   /**
 843:    * Returns the currently registered vetoable property change listeners
 844:    * in array form.  The returned array is empty if no listeners are
 845:    * currently registered.
 846:    *
 847:    * @return an array of registered vetoable property change listeners.
 848:    * @since 1.4
 849:    */
 850:   public VetoableChangeListener[] getVetoableChangeListeners()
 851:   {
 852:     return vetoableChangeSupport.getVetoableChangeListeners();
 853:   }
 854: 
 855:   /**
 856:    * Registers a vetoable property change listener for receiving events relating
 857:    * to a vetoable change to a specified property.  The supplied property name can be
 858:    * either user-defined or one from the following list of properties
 859:    * relevant to this class:
 860:    *
 861:    * <ul>
 862:    * <li>the current focus owner ("focusOwner")</li>
 863:    * <li>the permanent focus owner ("permanentFocusOwner")</li>
 864:    * <li>the focused window ("focusedWindow")</li>
 865:    * <li>the active window ("activeWindow")</li>
 866:    * </ul>
 867:    *
 868:    * Nothing occurs if a null listener is supplied.  null is regarded as a valid property name.
 869:    *
 870:    * @param name the name of the property to handle change events for.
 871:    * @param l the listener to register for changes to the specified property. 
 872:    * @see KeyboardFocusManager#addVetoableChangeListener(java.beans.VetoableChangeListener)
 873:    */
 874:   public void addVetoableChangeListener(String name, VetoableChangeListener l)
 875:   {
 876:     if (l != null)
 877:       vetoableChangeSupport.addVetoableChangeListener(name, l);
 878:   }
 879: 
 880:   /**
 881:    * Removes the supplied vetoable property change listener registered
 882:    * for the specified property from the list of registered listeners.
 883:    * If the supplied listener is null, nothing occurs.
 884:    *
 885:    * @param name the name of the vetoable property the listener is
 886:    *        monitoring changes to.
 887:    * @param l the listener to remove.
 888:    */
 889:   public void removeVetoableChangeListener(String name,
 890:                                            VetoableChangeListener l)
 891:   {
 892:     if (l != null)
 893:       vetoableChangeSupport.removeVetoableChangeListener(name, l);
 894:   }
 895: 
 896:   /**
 897:    * Returns the currently registered vetoable property change listeners
 898:    * in array form, which listen for changes to the supplied property.
 899:    * The returned array is empty, if no listeners are currently registered
 900:    * for events pertaining to the supplied property.
 901:    *
 902:    * @param name The property the returned listeners monitor for changes.
 903:    * @return an array of registered property change listeners which
 904:    *         listen for changes to the supplied property.
 905:    * @since 1.4
 906:    */
 907:   public VetoableChangeListener[] getVetoableChangeListeners(String name)
 908:   {
 909:     return vetoableChangeSupport.getVetoableChangeListeners(name);
 910:   }
 911: 
 912:   /**
 913:    * Fires a property change event as a response to a vetoable change to
 914:    * to the specified property.  The event is only fired if a
 915:    * change has actually occurred (i.e. o and n are different).
 916:    * In the event that the property change is vetoed, the following
 917:    * occurs:
 918:    *
 919:    * <ol>
 920:    * <li>
 921:    * This method throws a <code>PropertyVetoException</code> to
 922:    * the proposed change.
 923:    * </li>
 924:    * <li>
 925:    * A new event is fired to reverse the previous change.
 926:    * </li>
 927:    * <li>
 928:    * This method again throws a <code>PropertyVetoException</code>
 929:    * in response to the reversion.
 930:    * </li>
 931:    * </ol>
 932:    *
 933:    * @param name The name of the property to which a change occurred.
 934:    * @param o The old value of the property.
 935:    * @param n The new value of the property.
 936:    * @throws PropertyVetoException if one of the listeners vetos
 937:    *         the change by throwing this exception.
 938:    */
 939:   protected void fireVetoableChange(String name, Object o, Object n)
 940:     throws PropertyVetoException
 941:   {
 942:     vetoableChangeSupport.fireVetoableChange(name, o, n);
 943:   }
 944: 
 945:   /**
 946:    * Adds a key event dispatcher to the list of registered dispatchers.
 947:    * When a key event is fired, each dispatcher's <code>dispatchKeyEvent</code>
 948:    * method is called in the order that they were added, prior to the manager
 949:    * dispatching the event itself.  Notifications halt when one of the
 950:    * dispatchers returns true.
 951:    * <br />
 952:    * <br />
 953:    * The same dispatcher can exist multiple times within the list
 954:    * of registered dispatchers, and there is no limit on the length
 955:    * of this list.  A null dispatcher is simply ignored.
 956:    *
 957:    * @param dispatcher The dispatcher to register.
 958:    */
 959:   public void addKeyEventDispatcher(KeyEventDispatcher dispatcher)
 960:   {
 961:     if (dispatcher != null)
 962:       keyEventDispatchers.add(dispatcher);
 963:   }
 964: 
 965:   /**
 966:    * Removes the specified key event dispatcher from the list of
 967:    * registered dispatchers.  The manager always dispatches events,
 968:    * regardless of its existence within the list.  The manager
 969:    * can be added and removed from the list, as with any other
 970:    * dispatcher, but this does not affect its ability to dispatch
 971:    * key events.  Non-existent and null dispatchers are simply ignored
 972:    * by this method.
 973:    *
 974:    * @param dispatcher The dispatcher to remove.
 975:    */
 976:   public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher)
 977:   {
 978:     keyEventDispatchers.remove(dispatcher);
 979:   }
 980: 
 981:   /**
 982:    * Returns the currently registered key event dispatchers in <code>List</code>
 983:    * form.  At present, this only includes dispatchers explicitly registered
 984:    * via the <code>addKeyEventDispatcher()</code> method, but this behaviour
 985:    * is subject to change and should not be depended on.  The manager itself
 986:    * may be a member of the list, but only if explicitly registered.  If no
 987:    * dispatchers have been registered, the list will be empty.
 988:    *
 989:    * @return A list of explicitly registered key event dispatchers.
 990:    * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
 991:    */
 992:   protected List getKeyEventDispatchers ()
 993:   {
 994:     return (List) keyEventDispatchers.clone ();
 995:   }
 996: 
 997:   /**
 998:    * Adds a key event post processor to the list of registered post processors.
 999:    * Post processors work in the same way as key event dispatchers, except
1000:    * that they are invoked after the manager has dispatched the key event,
1001:    * and not prior to this.  Each post processor's <code>postProcessKeyEvent</code>
1002:    * method is called to see if any post processing needs to be performed.  THe
1003:    * processors are called in the order in which they were added to the list,
1004:    * and notifications continue until one returns true.  As with key event
1005:    * dispatchers, the manager is implicitly called following this process,
1006:    * regardless of whether or not it is present within the list.
1007:    * <br />
1008:    * <br />
1009:    * The same post processor can exist multiple times within the list
1010:    * of registered post processors, and there is no limit on the length
1011:    * of this list.  A null post processor is simply ignored.
1012:    *
1013:    * @param postProcessor the post processor to register.
1014:    * @see KeyboardFocusManager#addKeyEventDispatcher(java.awt.KeyEventDispatcher)
1015:    */
1016:   public void addKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
1017:   {
1018:     if (postProcessor != null)
1019:       keyEventPostProcessors.add (postProcessor);
1020:   }
1021: 
1022:   /**
1023:    * Removes the specified key event post processor from the list of
1024:    * registered post processors.  The manager always post processes events,
1025:    * regardless of its existence within the list.  The manager
1026:    * can be added and removed from the list, as with any other
1027:    * post processor, but this does not affect its ability to post process
1028:    * key events.  Non-existent and null post processors are simply ignored
1029:    * by this method.
1030:    *
1031:    * @param postProcessor the post processor to remove.
1032:    */
1033:   public void removeKeyEventPostProcessor (KeyEventPostProcessor postProcessor)
1034:   {
1035:     keyEventPostProcessors.remove (postProcessor);
1036:   }
1037: 
1038:   /**
1039:    * Returns the currently registered key event post processors in <code>List</code>
1040:    * form.  At present, this only includes post processors explicitly registered
1041:    * via the <code>addKeyEventPostProcessor()</code> method, but this behaviour
1042:    * is subject to change and should not be depended on.  The manager itself
1043:    * may be a member of the list, but only if explicitly registered.  If no
1044:    * post processors have been registered, the list will be empty.
1045:    *
1046:    * @return A list of explicitly registered key event post processors.
1047:    * @see KeyboardFocusManager#addKeyEventPostProcessor(java.awt.KeyEventPostProcessor)
1048:    */
1049:   protected List getKeyEventPostProcessors ()
1050:   {
1051:     return (List) keyEventPostProcessors.clone ();
1052:   }
1053: 
1054:   /**
1055:    * The AWT event dispatcher uses this method to request that the manager
1056:    * handle a particular event.  If the manager fails or refuses to
1057:    * dispatch the supplied event (this method returns false), the
1058:    * AWT event dispatcher will try to dispatch the event itself.
1059:    * <br />
1060:    * <br />
1061:    * The manager is expected to handle all <code>FocusEvent</code>s
1062:    * and <code>KeyEvent</code>s, and <code>WindowEvent</code>s
1063:    * relating to the focus.  Dispatch is done with regard to the
1064:    * the focus owner and the currently focused and active windows.
1065:    * In handling the event, the source of the event may be overridden.
1066:    * <br />
1067:    * <br />
1068:    * The actual dispatching is performed by calling
1069:    * <code>redispatchEvent()</code>.  This avoids the infinite recursion
1070:    * of dispatch requests which may occur if this method is called on
1071:    * the target component.  
1072:    *
1073:    * @param e the event to dispatch.
1074:    * @return true if the event was dispatched.
1075:    * @see KeyboardFocusManager#redispatchEvent(java.awt.Component, java.awt.AWTEvent)
1076:    * @see KeyEvent
1077:    * @see FocusEvent
1078:    * @see WindowEvent
1079:    */
1080:   public abstract boolean dispatchEvent (AWTEvent e);
1081: 
1082:   /**
1083:    * Handles redispatching of an event so that recursion of
1084:    * dispatch requests does not occur.  Event dispatch methods
1085:    * within this manager (<code>dispatchEvent()</code>) and
1086:    * the key event dispatchers should use this method to handle
1087:    * dispatching rather than the dispatch method of the target
1088:    * component.  
1089:    * <br />
1090:    * <br />
1091:    * <strong>
1092:    * This method is not intended for general consumption, and is
1093:    * only for the use of the aforementioned classes.
1094:    * </strong>
1095:    * 
1096:    * @param target the target component to which the event is
1097:    *        dispatched.
1098:    * @param e the event to dispatch.
1099:    */
1100:   public final void redispatchEvent (Component target, AWTEvent e)
1101:   {
1102:     e.isFocusManagerEvent = true;
1103:     target.dispatchEvent (e);
1104:     e.isFocusManagerEvent = false;
1105:   }
1106: 
1107:   /**
1108:    * Attempts to dispatch key events for which no key event dispatcher
1109:    * has so far succeeded.  This method is usually called by
1110:    * <code>dispatchEvent()</code> following the sending of the key
1111:    * event to any registered key event dispatchers.  If the key
1112:    * event reaches this stage, none of the dispatchers returned
1113:    * true.  This is, of course, always the case if there are no
1114:    * registered dispatchers.
1115:    * <br />
1116:    * <br />
1117:    * If this method also fails to handle the key event, then
1118:    * false is returned to the caller.  In the case of
1119:    * <code>dispatchEvent()</code>, the calling method may try
1120:    * to handle the event itself or simply forward on the
1121:    * false result to its caller.  When the event is dispatched
1122:    * by this method, a true result is propogated through the
1123:    * calling methods.
1124:    *
1125:    * @param e the key event to dispatch.
1126:    * @return true if the event was dispatched successfully.
1127:    */
1128:   public abstract boolean dispatchKeyEvent (KeyEvent e);
1129: 
1130:   /**
1131:    * Handles the post processing of key events.  By default,
1132:    * this method will map unhandled key events to appropriate
1133:    * <code>MenuShortcut</code>s.  The event is consumed
1134:    * in the process and the shortcut is activated.  This
1135:    * method is usually called by <code>dispatchKeyEvent</code>.
1136:    *
1137:    * @param e the key event to post process.
1138:    * @return true by default, as the event was handled.
1139:    */
1140:   public abstract boolean postProcessKeyEvent (KeyEvent e);
1141: 
1142:   /**
1143:    * Handles focus traversal operations for key events which
1144:    * represent focus traversal keys in relation to the supplied
1145:    * component.  The supplied component is assumed to have the
1146:    * focus, whether it does so or not, and the operation is
1147:    * carried out as appropriate, with this in mind.
1148:    *
1149:    * @param focused the component on which to perform focus traversal,
1150:    *        on the assumption that this component has the focus.
1151:    * @param e the possible focus traversal key event.
1152:    */
1153:   public abstract void processKeyEvent (Component focused, KeyEvent e);
1154: 
1155:   /**
1156:    * Delays all key events following the specified timestamp until the
1157:    * supplied component has focus.  The AWT calls this method when it is
1158:    * determined that a focus change may occur within the native windowing
1159:    * system.  Any key events which occur following the time specified by
1160:    * after are delayed until a <code>FOCUS_GAINED</code> event is received
1161:    * for the untilFocused component.  The manager is responsible for ensuring
1162:    * this takes place.
1163:    *
1164:    * @param after the timestamp beyond which all key events are delayed until
1165:    *        the supplied component gains focus.
1166:    * @param untilFocused the component to wait on gaining focus.
1167:    */
1168:   protected abstract void enqueueKeyEvents (long after, Component untilFocused);
1169: 
1170:   /**
1171:    * Removes the key event block specified by the supplied timestamp and component.
1172:    * All delayed key events are released for normal dispatching following its
1173:    * removal and subsequent key events that would have been blocked are now
1174:    * immediately dispatched.  If the specified timestamp is below 0, then
1175:    * the request with the oldest timestamp is removed.
1176:    *
1177:    * @param after the timestamp of the key event block to be removed, or a
1178:    *        value smaller than 0 if the oldest is to be removed.
1179:    * @param untilFocused the component of the key event block to be removed.
1180:    */
1181:   protected abstract void dequeueKeyEvents (long after, Component untilFocused);
1182: 
1183:   /**
1184:    * Discards all key event blocks relating to focus requirements for
1185:    * the supplied component, regardless of timestamp.
1186:    *
1187:    * @param comp the component of the key event block(s) to be removed.
1188:    */
1189:   protected abstract void discardKeyEvents (Component comp);
1190: 
1191:   /**
1192:    * Moves the current focus to the next component following
1193:    * comp, based on the current focus traversal policy.  By
1194:    * default, only visible, displayable, accepted components
1195:    * can receive focus.  <code>Canvas</code>es, <code>Panel</code>s,
1196:    * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1197:    * <code>Window</code>s and lightweight components are judged
1198:    * to be unacceptable by default.  See the
1199:    * <code>DefaultFocusTraversalPolicy</code> for more details.
1200:    *
1201:    * @param comp the component prior to the one which will
1202:    *        become the focus, following execution of this method.
1203:    * @see DefaultFocusTraversalPolicy
1204:    */
1205:   public abstract void focusNextComponent(Component comp);
1206: 
1207:   /**
1208:    * Moves the current focus to the previous component, prior to
1209:    * comp, based on the current focus traversal policy.  By
1210:    * default, only visible, displayable, accepted components
1211:    * can receive focus.  <code>Canvas</code>es, <code>Panel</code>s,
1212:    * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1213:    * <code>Window</code>s and lightweight components are judged
1214:    * to be unacceptable by default.  See the
1215:    * <code>DefaultFocusTraversalPolicy</code> for more details.
1216:    *
1217:    * @param comp the component following the one which will
1218:    *        become the focus, following execution of this method.
1219:    * @see DefaultFocusTraversalPolicy
1220:    */
1221:   public abstract void focusPreviousComponent(Component comp);
1222: 
1223:   /**
1224:    * Moves the current focus upwards by one focus cycle.
1225:    * Both the current focus owner and current focus cycle root
1226:    * become the focus cycle root of the supplied component.
1227:    * However, in the case of a <code>Window</code>, the default
1228:    * focus component becomes the focus owner and the focus cycle
1229:    * root is not changed.
1230:    * 
1231:    * @param comp the component used as part of the focus traversal.
1232:    */ 
1233:   public abstract void upFocusCycle(Component comp);
1234: 
1235:   /**
1236:    * Moves the current focus downwards by one focus cycle.
1237:    * If the supplied container is a focus cycle root, then this
1238:    * becomes the current focus cycle root and the focus goes
1239:    * to the default component of the specified container.
1240:    * Nothing happens for non-focus cycle root containers. 
1241:    * 
1242:    * @param cont the container used as part of the focus traversal.
1243:    */ 
1244:   public abstract void downFocusCycle(Container cont);
1245: 
1246:   /**
1247:    * Moves the current focus to the next component, based on the
1248:    * current focus traversal policy.  By default, only visible,
1249:    * displayable, accepted component can receive focus.
1250:    * <code>Canvas</code>es, <code>Panel</code>s,
1251:    * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1252:    * <code>Window</code>s and lightweight components are judged
1253:    * to be unacceptable by default.  See the
1254:    * <code>DefaultFocusTraversalPolicy</code> for more details.
1255:    *
1256:    * @see DefaultFocusTraversalPolicy
1257:    */
1258:   public final void focusNextComponent()
1259:   {
1260:     focusNextComponent (null);
1261:   }
1262: 
1263:   /**
1264:    * Moves the current focus to the previous component, based on the
1265:    * current focus traversal policy.  By default, only visible,
1266:    * displayable, accepted component can receive focus.
1267:    * <code>Canvas</code>es, <code>Panel</code>s,
1268:    * <code>Label</code>s, <code>ScrollPane</code>s, <code>Scrollbar</code>s,
1269:    * <code>Window</code>s and lightweight components are judged
1270:    * to be unacceptable by default.  See the
1271:    * <code>DefaultFocusTraversalPolicy</code> for more details.
1272:    *
1273:    * @see DefaultFocusTraversalPolicy
1274:    */
1275:   public final void focusPreviousComponent()
1276:   {
1277:     focusPreviousComponent (null);
1278:   }
1279: 
1280:   /**
1281:    * Moves the current focus upwards by one focus cycle,
1282:    * so that the new focus owner is the focus cycle root
1283:    * of the current owner.  The current focus cycle root then
1284:    * becomes the focus cycle root of the new focus owner.
1285:    * However, in the case of the focus cycle root of the
1286:    * current focus owner being a <code>Window</code>, the default
1287:    * component of this window becomes the focus owner and the
1288:    * focus cycle root is not changed.
1289:    */
1290:   public final void upFocusCycle()
1291:   {
1292:     upFocusCycle (null);
1293:   }
1294: 
1295:   /**
1296:    * Moves the current focus downwards by one focus cycle,
1297:    * iff the current focus cycle root is a <code>Container</code>.
1298:    * Usually, the new focus owner is set to the default component
1299:    * of the container and the current focus cycle root is set
1300:    * to the current focus owner.  Nothing occurs if the current
1301:    * focus cycle root is not a container.
1302:    */
1303:   public final void downFocusCycle()
1304:   {
1305:     Component focusOwner = getGlobalFocusOwner ();
1306:     if (focusOwner instanceof Container
1307:         && ((Container) focusOwner).isFocusCycleRoot ())
1308:       downFocusCycle ((Container) focusOwner);
1309:   }
1310: 
1311:   /**
1312:    * Retrieve an object from one of the global object {@link
1313:    * java.util.Map}s, if the object was set by the a thread in the
1314:    * current {@link java.lang.ThreadGroup}.  Otherwise, return null.
1315:    *
1316:    * @param globalMap one of the global object Maps
1317:    *
1318:    * @return a global object set by the current ThreadGroup, or null
1319:    *
1320:    * @see #getFocusOwner()
1321:    * @see #getPermanentFocusOwner()
1322:    * @see #getFocusedWindow()
1323:    * @see #getActiveWindow()
1324:    * @see #getCurrentFocusCycleRoot()
1325:    */
1326:   private Object getObject (Map globalMap)
1327:   {
1328:     ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1329:     return globalMap.get (currentGroup);
1330:   }
1331: 
1332:   /**
1333:    * Retrieve an object from one of the global object {@link
1334:    * java.util.Map}s, regardless of whether or not the object was set
1335:    * by a thread in the current {@link java.lang.ThreadGroup}.
1336:    *
1337:    * @param globalMap one of the global object Maps
1338:    *
1339:    * @return a global object set by the current ThreadGroup, or null
1340:    *
1341:    * @throws SecurityException if this is not the keyboard focus
1342:    * manager associated with the current {@link java.lang.ThreadGroup}
1343:    *
1344:    * @see #getGlobalFocusOwner()
1345:    * @see #getGlobalPermanentFocusOwner()
1346:    * @see #getGlobalFocusedWindow()
1347:    * @see #getGlobalActiveWindow()
1348:    * @see #getGlobalCurrentFocusCycleRoot()
1349:    */
1350:   private Object getGlobalObject (Map globalMap, boolean checkThread)
1351:   {
1352:     if (checkThread)
1353:       {
1354:         ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1355:         KeyboardFocusManager managerForCallingThread =
1356:          (KeyboardFocusManager) currentKeyboardFocusManagers.get(currentGroup);
1357: 
1358:         if (this != managerForCallingThread)
1359:           throw new SecurityException ("Attempted to retrieve an object from a "
1360:                                        + "keyboard focus manager that isn't "
1361:                                 + "associated with the current thread group.");
1362:       }
1363:     synchronized (globalMap)
1364:       {
1365:         Collection globalObjects = globalMap.values ();
1366:         Iterator i = globalObjects.iterator ();
1367:         Component globalObject;
1368: 
1369:         while (i.hasNext ())
1370:           {
1371:             globalObject = (Component) i.next ();
1372:             if (globalObject != null)
1373:               return globalObject;
1374:           }
1375:       }
1376: 
1377:     // No Object was found.
1378:     return null;
1379:   }
1380: 
1381:   /**
1382:    * Set an object in one of the global object {@link java.util.Map}s,
1383:    * that will be returned by subsequent calls to getGlobalObject on
1384:    * the same {@link java.util.Map}.
1385:    *
1386:    * @param globalMap one of the global object Maps
1387:    * @param newObject the object to set
1388:    * @param property the property that will change
1389:    *
1390:    * @see #setGlobalFocusOwner(Component)
1391:    * @see #setGlobalPermanentFocusOwner(Component)
1392:    * @see #setGlobalFocusedWindow(Window)
1393:    * @see #setGlobalActiveWindow(Window)
1394:    * @see #setGlobalCurrentFocusCycleRoot(Container)
1395:    */
1396:   private void setGlobalObject (Map globalMap,
1397:                                 Object newObject,
1398:                                 String property)
1399:   {
1400:     synchronized (globalMap)
1401:       {
1402:         // Save old object.
1403:         Object oldObject = getGlobalObject(globalMap, false);
1404: 
1405:         // Nullify old object.
1406:         Collection threadGroups = globalMap.keySet ();
1407:         Iterator i = threadGroups.iterator ();
1408:         while (i.hasNext ())
1409:           {
1410:             ThreadGroup oldThreadGroup = (ThreadGroup) i.next ();
1411:             if (globalMap.get (oldThreadGroup) != null)
1412:               {
1413:                 globalMap.put (oldThreadGroup, null);
1414:                 // There should only be one object set at a time, so
1415:                 // we can short circuit.
1416:                 break;
1417:               }
1418:           }
1419: 
1420:         ThreadGroup currentGroup = Thread.currentThread ().getThreadGroup ();
1421:         firePropertyChange (property, oldObject, newObject);
1422:         try
1423:           {
1424:             fireVetoableChange (property, oldObject, newObject);
1425:             // Set new object.
1426:             globalMap.put (currentGroup, newObject);
1427:           }
1428:         catch (PropertyVetoException e)
1429:           {
1430:           }
1431:       }
1432:   }
1433: 
1434:   
1435:   /**
1436:    * Maps focus requests from heavyweight to lightweight components.
1437:    */
1438:   private static HashMap focusRequests = new HashMap();
1439: 
1440:   /**
1441:    * Retargets focus events that come from the peer (which only know about
1442:    * heavyweight components) to go to the correct lightweight component
1443:    * if appropriate.
1444:    *
1445:    * @param ev the event to check
1446:    *
1447:    * @return the retargetted event
1448:    */
1449:   static AWTEvent retargetFocusEvent(AWTEvent ev)
1450:   {
1451:     if (ev instanceof FocusEvent)
1452:       {
1453:         FocusEvent fe = (FocusEvent) ev;
1454:         Component target = fe.getComponent();
1455:         if (focusRequests.containsKey(target))
1456:           {
1457:             Component lightweight = (Component) focusRequests.get(target);
1458:             ev = new FocusEvent(lightweight, fe.id, fe.isTemporary());
1459:             focusRequests.remove(target);
1460:           }
1461:       }
1462:     return ev;
1463:   }
1464: 
1465:   /**
1466:    * Adds a lightweight focus request for a heavyweight component.
1467:    *
1468:    * @param heavyweight the heavyweight from which we will receive a focus
1469:    *        event soon
1470:    * @param lightweight the lightweight that ultimately receives the request
1471:    */
1472:   static void addLightweightFocusRequest(Component heavyweight,
1473:                                          Component lightweight)
1474:   {
1475:     focusRequests.put(heavyweight, lightweight);
1476:   }
1477: }