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