Source for java.awt.KeyboardFocusManager

   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();
 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,
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
 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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */ 
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:    */ 
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
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:    */
1474:   static void addLightweightFocusRequest(Component heavyweight,
1475:                                          Component lightweight)
1476:   {
1477:     focusRequests.put(heavyweight, lightweight);
1478:   }
1479: }