1 /* 2 * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.awt; 26 27 import java.awt.event.FocusEvent; 28 import java.awt.event.InputEvent; 29 import java.awt.event.KeyEvent; 30 import java.awt.event.WindowEvent; 31 32 import java.awt.peer.KeyboardFocusManagerPeer; 33 import java.awt.peer.LightweightPeer; 34 35 import java.beans.PropertyChangeListener; 36 import java.beans.PropertyChangeSupport; 37 import java.beans.PropertyVetoException; 38 import java.beans.VetoableChangeListener; 39 import java.beans.VetoableChangeSupport; 40 41 import java.lang.ref.WeakReference; 42 43 import java.lang.reflect.Field; 44 45 import java.security.AccessController; 46 import java.security.PrivilegedAction; 47 48 import java.util.Collections; 49 import java.util.HashSet; 50 import java.util.Iterator; 51 import java.util.LinkedList; 52 import java.util.Set; 53 import java.util.StringTokenizer; 54 import java.util.WeakHashMap; 55 56 import sun.util.logging.PlatformLogger; 57 58 import sun.awt.AppContext; 59 import sun.awt.SunToolkit; 60 import sun.awt.CausedFocusEvent; 61 import sun.awt.KeyboardFocusManagerPeerProvider; 62 import sun.awt.AWTAccessor; 63 64 /** 65 * The KeyboardFocusManager is responsible for managing the active and focused 66 * Windows, and the current focus owner. The focus owner is defined as the 67 * Component in an application that will typically receive all KeyEvents 68 * generated by the user. The focused Window is the Window that is, or 69 * contains, the focus owner. Only a Frame or a Dialog can be the active 70 * Window. The native windowing system may denote the active Window or its 71 * children with special decorations, such as a highlighted title bar. The 72 * active Window is always either the focused Window, or the first Frame or 73 * Dialog that is an owner of the focused Window. 74 * <p> 75 * The KeyboardFocusManager is both a centralized location for client code to 76 * query for the focus owner and initiate focus changes, and an event 77 * dispatcher for all FocusEvents, WindowEvents related to focus, and 78 * KeyEvents. 79 * <p> 80 * Some browsers partition applets in different code bases into separate 81 * contexts, and establish walls between these contexts. In such a scenario, 82 * there will be one KeyboardFocusManager per context. Other browsers place all 83 * applets into the same context, implying that there will be only a single, 84 * global KeyboardFocusManager for all applets. This behavior is 85 * implementation-dependent. Consult your browser's documentation for more 86 * information. No matter how many contexts there may be, however, there can 87 * never be more than one focus owner, focused Window, or active Window, per 88 * ClassLoader. 89 * <p> 90 * Please see 91 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html"> 92 * How to Use the Focus Subsystem</a>, 93 * a section in <em>The Java Tutorial</em>, and the 94 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a> 95 * for more information. 96 * 97 * @author David Mendenhall 98 * 99 * @see Window 100 * @see Frame 101 * @see Dialog 102 * @see java.awt.event.FocusEvent 103 * @see java.awt.event.WindowEvent 104 * @see java.awt.event.KeyEvent 105 * @since 1.4 106 */ 107 public abstract class KeyboardFocusManager 108 implements KeyEventDispatcher, KeyEventPostProcessor 109 { 110 111 // Shared focus engine logger 112 private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager"); 113 114 static { 115 /* ensure that the necessary native libraries are loaded */ 116 Toolkit.loadLibraries(); 117 if (!GraphicsEnvironment.isHeadless()) { 118 initIDs(); 119 } 120 AWTAccessor.setKeyboardFocusManagerAccessor( 121 new AWTAccessor.KeyboardFocusManagerAccessor() { 122 public int shouldNativelyFocusHeavyweight(Component heavyweight, 123 Component descendant, 124 boolean temporary, 125 boolean focusedWindowChangeAllowed, 126 long time, 127 CausedFocusEvent.Cause cause) 128 { 129 return KeyboardFocusManager.shouldNativelyFocusHeavyweight( 130 heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause); 131 } 132 public boolean processSynchronousLightweightTransfer(Component heavyweight, 133 Component descendant, 134 boolean temporary, 135 boolean focusedWindowChangeAllowed, 136 long time) 137 { 138 return KeyboardFocusManager.processSynchronousLightweightTransfer( 139 heavyweight, descendant, temporary, focusedWindowChangeAllowed, time); 140 } 141 public void removeLastFocusRequest(Component heavyweight) { 142 KeyboardFocusManager.removeLastFocusRequest(heavyweight); 143 } 144 public void setMostRecentFocusOwner(Window window, Component component) { 145 KeyboardFocusManager.setMostRecentFocusOwner(window, component); 146 } 147 public KeyboardFocusManager getCurrentKeyboardFocusManager(AppContext ctx) { 148 return KeyboardFocusManager.getCurrentKeyboardFocusManager(ctx); 149 } 150 } 151 ); 152 } 153 154 transient KeyboardFocusManagerPeer peer; 155 156 /** 157 * Initialize JNI field and method IDs 158 */ 159 private static native void initIDs(); 160 161 private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.KeyboardFocusManager"); 162 163 /** 164 * The identifier for the Forward focus traversal keys. 165 * 166 * @see #setDefaultFocusTraversalKeys 167 * @see #getDefaultFocusTraversalKeys 168 * @see Component#setFocusTraversalKeys 169 * @see Component#getFocusTraversalKeys 170 */ 171 public static final int FORWARD_TRAVERSAL_KEYS = 0; 172 173 /** 174 * The identifier for the Backward focus traversal keys. 175 * 176 * @see #setDefaultFocusTraversalKeys 177 * @see #getDefaultFocusTraversalKeys 178 * @see Component#setFocusTraversalKeys 179 * @see Component#getFocusTraversalKeys 180 */ 181 public static final int BACKWARD_TRAVERSAL_KEYS = 1; 182 183 /** 184 * The identifier for the Up Cycle focus traversal keys. 185 * 186 * @see #setDefaultFocusTraversalKeys 187 * @see #getDefaultFocusTraversalKeys 188 * @see Component#setFocusTraversalKeys 189 * @see Component#getFocusTraversalKeys 190 */ 191 public static final int UP_CYCLE_TRAVERSAL_KEYS = 2; 192 193 /** 194 * The identifier for the Down Cycle focus traversal keys. 195 * 196 * @see #setDefaultFocusTraversalKeys 197 * @see #getDefaultFocusTraversalKeys 198 * @see Component#setFocusTraversalKeys 199 * @see Component#getFocusTraversalKeys 200 */ 201 public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3; 202 203 static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1; 204 205 /** 206 * Returns the current KeyboardFocusManager instance for the calling 207 * thread's context. 208 * 209 * @return this thread's context's KeyboardFocusManager 210 * @see #setCurrentKeyboardFocusManager 211 */ 212 public static KeyboardFocusManager getCurrentKeyboardFocusManager() { 213 return getCurrentKeyboardFocusManager(AppContext.getAppContext()); 214 } 215 216 synchronized static KeyboardFocusManager 217 getCurrentKeyboardFocusManager(AppContext appcontext) 218 { 219 KeyboardFocusManager manager = (KeyboardFocusManager) 220 appcontext.get(KeyboardFocusManager.class); 221 if (manager == null) { 222 manager = new DefaultKeyboardFocusManager(); 223 appcontext.put(KeyboardFocusManager.class, manager); 224 } 225 return manager; 226 } 227 228 /** 229 * Sets the current KeyboardFocusManager instance for the calling thread's 230 * context. If null is specified, then the current KeyboardFocusManager 231 * is replaced with a new instance of DefaultKeyboardFocusManager. 232 * <p> 233 * If a SecurityManager is installed, the calling thread must be granted 234 * the AWTPermission "replaceKeyboardFocusManager" in order to replace the 235 * the current KeyboardFocusManager. If this permission is not granted, 236 * this method will throw a SecurityException, and the current 237 * KeyboardFocusManager will be unchanged. 238 * 239 * @param newManager the new KeyboardFocusManager for this thread's context 240 * @see #getCurrentKeyboardFocusManager 241 * @see DefaultKeyboardFocusManager 242 * @throws SecurityException if the calling thread does not have permission 243 * to replace the current KeyboardFocusManager 244 */ 245 public static void setCurrentKeyboardFocusManager( 246 KeyboardFocusManager newManager) throws SecurityException 247 { 248 SecurityManager security = System.getSecurityManager(); 249 if (security != null) { 250 if (replaceKeyboardFocusManagerPermission == null) { 251 replaceKeyboardFocusManagerPermission = 252 new AWTPermission("replaceKeyboardFocusManager"); 253 } 254 security. 255 checkPermission(replaceKeyboardFocusManagerPermission); 256 } 257 258 KeyboardFocusManager oldManager = null; 259 260 synchronized (KeyboardFocusManager.class) { 261 AppContext appcontext = AppContext.getAppContext(); 262 263 if (newManager != null) { 264 oldManager = getCurrentKeyboardFocusManager(appcontext); 265 266 appcontext.put(KeyboardFocusManager.class, newManager); 267 } else { 268 oldManager = getCurrentKeyboardFocusManager(appcontext); 269 appcontext.remove(KeyboardFocusManager.class); 270 } 271 } 272 273 if (oldManager != null) { 274 oldManager.firePropertyChange("managingFocus", 275 Boolean.TRUE, 276 Boolean.FALSE); 277 } 278 if (newManager != null) { 279 newManager.firePropertyChange("managingFocus", 280 Boolean.FALSE, 281 Boolean.TRUE); 282 } 283 } 284 285 /** 286 * The Component in an application that will typically receive all 287 * KeyEvents generated by the user. 288 */ 289 private static Component focusOwner; 290 291 /** 292 * The Component in an application that will regain focus when an 293 * outstanding temporary focus transfer has completed, or the focus owner, 294 * if no outstanding temporary transfer exists. 295 */ 296 private static Component permanentFocusOwner; 297 298 /** 299 * The Window which is, or contains, the focus owner. 300 */ 301 private static Window focusedWindow; 302 303 /** 304 * Only a Frame or a Dialog can be the active Window. The native windowing 305 * system may denote the active Window with a special decoration, such as a 306 * highlighted title bar. The active Window is always either the focused 307 * Window, or the first Frame or Dialog which is an owner of the focused 308 * Window. 309 */ 310 private static Window activeWindow; 311 312 /** 313 * The default FocusTraversalPolicy for all Windows that have no policy of 314 * their own set. If those Windows have focus-cycle-root children that have 315 * no keyboard-traversal policy of their own, then those children will also 316 * inherit this policy (as will, recursively, their focus-cycle-root 317 * children). 318 */ 319 private FocusTraversalPolicy defaultPolicy = 320 new DefaultFocusTraversalPolicy(); 321 322 /** 323 * The bound property names of each focus traversal key. 324 */ 325 private static final String[] defaultFocusTraversalKeyPropertyNames = { 326 "forwardDefaultFocusTraversalKeys", 327 "backwardDefaultFocusTraversalKeys", 328 "upCycleDefaultFocusTraversalKeys", 329 "downCycleDefaultFocusTraversalKeys" 330 }; 331 332 /** 333 * The default strokes for initializing the default focus traversal keys. 334 */ 335 private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = { 336 { 337 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false), 338 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false), 339 }, 340 { 341 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false), 342 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 343 InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, 344 false), 345 }, 346 {}, 347 {}, 348 }; 349 /** 350 * The default focus traversal keys. Each array of traversal keys will be 351 * in effect on all Windows that have no such array of their own explicitly 352 * set. Each array will also be inherited, recursively, by any child 353 * Component of those Windows that has no such array of its own explicitly 354 * set. 355 */ 356 private Set[] defaultFocusTraversalKeys = new Set[4]; 357 358 /** 359 * The current focus cycle root. If the focus owner is itself a focus cycle 360 * root, then it may be ambiguous as to which Components represent the next 361 * and previous Components to focus during normal focus traversal. In that 362 * case, the current focus cycle root is used to differentiate among the 363 * possibilities. 364 */ 365 private static Container currentFocusCycleRoot; 366 367 /** 368 * A description of any VetoableChangeListeners which have been registered. 369 */ 370 private VetoableChangeSupport vetoableSupport; 371 372 /** 373 * A description of any PropertyChangeListeners which have been registered. 374 */ 375 private PropertyChangeSupport changeSupport; 376 377 /** 378 * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not 379 * include this KeyboardFocusManager unless it was explicitly re-registered 380 * via a call to <code>addKeyEventDispatcher</code>. If no other 381 * KeyEventDispatchers are registered, this field may be null or refer to 382 * a List of length 0. 383 */ 384 private java.util.LinkedList keyEventDispatchers; 385 386 /** 387 * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does 388 * not include this KeyboardFocusManager unless it was explicitly 389 * re-registered via a call to <code>addKeyEventPostProcessor</code>. 390 * If no other KeyEventPostProcessors are registered, this field may be 391 * null or refer to a List of length 0. 392 */ 393 private java.util.LinkedList keyEventPostProcessors; 394 395 /** 396 * Maps Windows to those Windows' most recent focus owners. 397 */ 398 private static java.util.Map mostRecentFocusOwners = new WeakHashMap(); 399 400 /** 401 * Error String for initializing SecurityExceptions. 402 */ 403 private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context"; 404 405 /** 406 * We cache the permission used to verify that the calling thread is 407 * permitted to access the global focus state. 408 */ 409 private static AWTPermission replaceKeyboardFocusManagerPermission; 410 411 /* 412 * SequencedEvent which is currently dispatched in AppContext. 413 */ 414 transient SequencedEvent currentSequencedEvent = null; 415 416 final void setCurrentSequencedEvent(SequencedEvent current) { 417 synchronized (SequencedEvent.class) { 418 assert(current == null || currentSequencedEvent == null); 419 currentSequencedEvent = current; 420 } 421 } 422 423 final SequencedEvent getCurrentSequencedEvent() { 424 synchronized (SequencedEvent.class) { 425 return currentSequencedEvent; 426 } 427 } 428 429 static Set initFocusTraversalKeysSet(String value, Set targetSet) { 430 StringTokenizer tokens = new StringTokenizer(value, ","); 431 while (tokens.hasMoreTokens()) { 432 targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken())); 433 } 434 return (targetSet.isEmpty()) 435 ? Collections.EMPTY_SET 436 : Collections.unmodifiableSet(targetSet); 437 } 438 439 /** 440 * Initializes a KeyboardFocusManager. 441 */ 442 public KeyboardFocusManager() { 443 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) { 444 Set work_set = new HashSet(); 445 for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) { 446 work_set.add(defaultFocusTraversalKeyStrokes[i][j]); 447 } 448 defaultFocusTraversalKeys[i] = (work_set.isEmpty()) 449 ? Collections.EMPTY_SET 450 : Collections.unmodifiableSet(work_set); 451 } 452 initPeer(); 453 } 454 455 private void initPeer() { 456 Toolkit tk = Toolkit.getDefaultToolkit(); 457 KeyboardFocusManagerPeerProvider peerProvider = (KeyboardFocusManagerPeerProvider)tk; 458 peer = peerProvider.getKeyboardFocusManagerPeer(); 459 } 460 461 /** 462 * Returns the focus owner, if the focus owner is in the same context as 463 * the calling thread. The focus owner is defined as the Component in an 464 * application that will typically receive all KeyEvents generated by the 465 * user. KeyEvents which map to the focus owner's focus traversal keys will 466 * not be delivered if focus traversal keys are enabled for the focus 467 * owner. In addition, KeyEventDispatchers may retarget or consume 468 * KeyEvents before they reach the focus owner. 469 * 470 * @return the focus owner, or null if the focus owner is not a member of 471 * the calling thread's context 472 * @see #getGlobalFocusOwner 473 * @see #setGlobalFocusOwner 474 */ 475 public Component getFocusOwner() { 476 synchronized (KeyboardFocusManager.class) { 477 if (focusOwner == null) { 478 return null; 479 } 480 481 return (focusOwner.appContext == AppContext.getAppContext()) 482 ? focusOwner 483 : null; 484 } 485 } 486 487 /** 488 * Returns the focus owner, even if the calling thread is in a different 489 * context than the focus owner. The focus owner is defined as the 490 * Component in an application that will typically receive all KeyEvents 491 * generated by the user. KeyEvents which map to the focus owner's focus 492 * traversal keys will not be delivered if focus traversal keys are enabled 493 * for the focus owner. In addition, KeyEventDispatchers may retarget or 494 * consume KeyEvents before they reach the focus owner. 495 * <p> 496 * This method will throw a SecurityException if this KeyboardFocusManager 497 * is not the current KeyboardFocusManager for the calling thread's 498 * context. 499 * 500 * @return the focus owner 501 * @see #getFocusOwner 502 * @see #setGlobalFocusOwner 503 * @throws SecurityException if this KeyboardFocusManager is not the 504 * current KeyboardFocusManager for the calling thread's context 505 */ 506 protected Component getGlobalFocusOwner() throws SecurityException { 507 synchronized (KeyboardFocusManager.class) { 508 checkCurrentKFMSecurity(); 509 return focusOwner; 510 } 511 } 512 513 /** 514 * Sets the focus owner. The operation will be cancelled if the Component 515 * is not focusable. The focus owner is defined as the Component in an 516 * application that will typically receive all KeyEvents generated by the 517 * user. KeyEvents which map to the focus owner's focus traversal keys will 518 * not be delivered if focus traversal keys are enabled for the focus 519 * owner. In addition, KeyEventDispatchers may retarget or consume 520 * KeyEvents before they reach the focus owner. 521 * <p> 522 * This method does not actually set the focus to the specified Component. 523 * It merely stores the value to be subsequently returned by 524 * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code> 525 * or <code>Component.requestFocusInWindow()</code> to change the focus 526 * owner, subject to platform limitations. 527 * 528 * @param focusOwner the focus owner 529 * @see #getFocusOwner 530 * @see #getGlobalFocusOwner 531 * @see Component#requestFocus() 532 * @see Component#requestFocusInWindow() 533 * @see Component#isFocusable 534 * @beaninfo 535 * bound: true 536 */ 537 protected void setGlobalFocusOwner(Component focusOwner) { 538 Component oldFocusOwner = null; 539 boolean shouldFire = false; 540 541 if (focusOwner == null || focusOwner.isFocusable()) { 542 synchronized (KeyboardFocusManager.class) { 543 checkCurrentKFMSecurity(); 544 545 oldFocusOwner = getFocusOwner(); 546 547 try { 548 fireVetoableChange("focusOwner", oldFocusOwner, 549 focusOwner); 550 } catch (PropertyVetoException e) { 551 // rejected 552 return; 553 } 554 555 KeyboardFocusManager.focusOwner = focusOwner; 556 557 if (focusOwner != null && 558 (getCurrentFocusCycleRoot() == null || 559 !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot()))) 560 { 561 Container rootAncestor = 562 focusOwner.getFocusCycleRootAncestor(); 563 if (rootAncestor == null && (focusOwner instanceof Window)) 564 { 565 rootAncestor = (Container)focusOwner; 566 } 567 if (rootAncestor != null) { 568 setGlobalCurrentFocusCycleRoot(rootAncestor); 569 } 570 } 571 572 shouldFire = true; 573 } 574 } 575 576 if (shouldFire) { 577 firePropertyChange("focusOwner", oldFocusOwner, focusOwner); 578 } 579 } 580 581 /** 582 * Clears the global focus owner at both the Java and native levels. If 583 * there exists a focus owner, that Component will receive a permanent 584 * FOCUS_LOST event. After this operation completes, the native windowing 585 * system will discard all user-generated KeyEvents until the user selects 586 * a new Component to receive focus, or a Component is given focus 587 * explicitly via a call to <code>requestFocus()</code>. This operation 588 * does not change the focused or active Windows. 589 * 590 * @see Component#requestFocus() 591 * @see java.awt.event.FocusEvent#FOCUS_LOST 592 */ 593 public void clearGlobalFocusOwner() { 594 synchronized (KeyboardFocusManager.class) { 595 checkCurrentKFMSecurity(); 596 } 597 if (!GraphicsEnvironment.isHeadless()) { 598 // Toolkit must be fully initialized, otherwise 599 // _clearGlobalFocusOwner will crash or throw an exception 600 Toolkit.getDefaultToolkit(); 601 602 _clearGlobalFocusOwner(); 603 } 604 } 605 private void _clearGlobalFocusOwner() { 606 Window activeWindow = markClearGlobalFocusOwner(); 607 peer.clearGlobalFocusOwner(activeWindow); 608 } 609 610 Component getNativeFocusOwner() { 611 return peer.getCurrentFocusOwner(); 612 } 613 614 void setNativeFocusOwner(Component comp) { 615 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 616 focusLog.finest("Calling peer {0} setCurrentFocusOwner for {1}", 617 String.valueOf(peer), String.valueOf(comp)); 618 } 619 peer.setCurrentFocusOwner(comp); 620 } 621 622 Window getNativeFocusedWindow() { 623 return peer.getCurrentFocusedWindow(); 624 } 625 626 /** 627 * Returns the permanent focus owner, if the permanent focus owner is in 628 * the same context as the calling thread. The permanent focus owner is 629 * defined as the last Component in an application to receive a permanent 630 * FOCUS_GAINED event. The focus owner and permanent focus owner are 631 * equivalent unless a temporary focus change is currently in effect. In 632 * such a situation, the permanent focus owner will again be the focus 633 * owner when the temporary focus change ends. 634 * 635 * @return the permanent focus owner, or null if the permanent focus owner 636 * is not a member of the calling thread's context 637 * @see #getGlobalPermanentFocusOwner 638 * @see #setGlobalPermanentFocusOwner 639 */ 640 public Component getPermanentFocusOwner() { 641 synchronized (KeyboardFocusManager.class) { 642 if (permanentFocusOwner == null) { 643 return null; 644 } 645 646 return (permanentFocusOwner.appContext == 647 AppContext.getAppContext()) 648 ? permanentFocusOwner 649 : null; 650 } 651 } 652 653 /** 654 * Returns the permanent focus owner, even if the calling thread is in a 655 * different context than the permanent focus owner. The permanent focus 656 * owner is defined as the last Component in an application to receive a 657 * permanent FOCUS_GAINED event. The focus owner and permanent focus owner 658 * are equivalent unless a temporary focus change is currently in effect. 659 * In such a situation, the permanent focus owner will again be the focus 660 * owner when the temporary focus change ends. 661 * <p> 662 * This method will throw a SecurityException if this KeyboardFocusManager 663 * is not the current KeyboardFocusManager for the calling thread's 664 * context. 665 * 666 * @return the permanent focus owner 667 * @see #getPermanentFocusOwner 668 * @see #setGlobalPermanentFocusOwner 669 * @throws SecurityException if this KeyboardFocusManager is not the 670 * current KeyboardFocusManager for the calling thread's context 671 */ 672 protected Component getGlobalPermanentFocusOwner() 673 throws SecurityException 674 { 675 synchronized (KeyboardFocusManager.class) { 676 checkCurrentKFMSecurity(); 677 return permanentFocusOwner; 678 } 679 } 680 681 /** 682 * Sets the permanent focus owner. The operation will be cancelled if the 683 * Component is not focusable. The permanent focus owner is defined as the 684 * last Component in an application to receive a permanent FOCUS_GAINED 685 * event. The focus owner and permanent focus owner are equivalent unless 686 * a temporary focus change is currently in effect. In such a situation, 687 * the permanent focus owner will again be the focus owner when the 688 * temporary focus change ends. 689 * <p> 690 * This method does not actually set the focus to the specified Component. 691 * It merely stores the value to be subsequently returned by 692 * <code>getPermanentFocusOwner()</code>. Use 693 * <code>Component.requestFocus()</code> or 694 * <code>Component.requestFocusInWindow()</code> to change the focus owner, 695 * subject to platform limitations. 696 * 697 * @param permanentFocusOwner the permanent focus owner 698 * @see #getPermanentFocusOwner 699 * @see #getGlobalPermanentFocusOwner 700 * @see Component#requestFocus() 701 * @see Component#requestFocusInWindow() 702 * @see Component#isFocusable 703 * @beaninfo 704 * bound: true 705 */ 706 protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner) { 707 Component oldPermanentFocusOwner = null; 708 boolean shouldFire = false; 709 710 if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) { 711 synchronized (KeyboardFocusManager.class) { 712 checkCurrentKFMSecurity(); 713 714 oldPermanentFocusOwner = getPermanentFocusOwner(); 715 716 try { 717 fireVetoableChange("permanentFocusOwner", 718 oldPermanentFocusOwner, 719 permanentFocusOwner); 720 } catch (PropertyVetoException e) { 721 // rejected 722 return; 723 } 724 725 KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner; 726 727 KeyboardFocusManager. 728 setMostRecentFocusOwner(permanentFocusOwner); 729 730 shouldFire = true; 731 } 732 } 733 734 if (shouldFire) { 735 firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner, 736 permanentFocusOwner); 737 } 738 } 739 740 /** 741 * Returns the focused Window, if the focused Window is in the same context 742 * as the calling thread. The focused Window is the Window that is or 743 * contains the focus owner. 744 * 745 * @return the focused Window, or null if the focused Window is not a 746 * member of the calling thread's context 747 * @see #getGlobalFocusedWindow 748 * @see #setGlobalFocusedWindow 749 */ 750 public Window getFocusedWindow() { 751 synchronized (KeyboardFocusManager.class) { 752 if (focusedWindow == null) { 753 return null; 754 } 755 756 return (focusedWindow.appContext == AppContext.getAppContext()) 757 ? focusedWindow 758 : null; 759 } 760 } 761 762 /** 763 * Returns the focused Window, even if the calling thread is in a different 764 * context than the focused Window. The focused Window is the Window that 765 * is or contains the focus owner. 766 * <p> 767 * This method will throw a SecurityException if this KeyboardFocusManager 768 * is not the current KeyboardFocusManager for the calling thread's 769 * context. 770 * 771 * @return the focused Window 772 * @see #getFocusedWindow 773 * @see #setGlobalFocusedWindow 774 * @throws SecurityException if this KeyboardFocusManager is not the 775 * current KeyboardFocusManager for the calling thread's context 776 */ 777 protected Window getGlobalFocusedWindow() throws SecurityException { 778 synchronized (KeyboardFocusManager.class) { 779 checkCurrentKFMSecurity(); 780 return focusedWindow; 781 } 782 } 783 784 /** 785 * Sets the focused Window. The focused Window is the Window that is or 786 * contains the focus owner. The operation will be cancelled if the 787 * specified Window to focus is not a focusable Window. 788 * <p> 789 * This method does not actually change the focused Window as far as the 790 * native windowing system is concerned. It merely stores the value to be 791 * subsequently returned by <code>getFocusedWindow()</code>. Use 792 * <code>Component.requestFocus()</code> or 793 * <code>Component.requestFocusInWindow()</code> to change the focused 794 * Window, subject to platform limitations. 795 * 796 * @param focusedWindow the focused Window 797 * @see #getFocusedWindow 798 * @see #getGlobalFocusedWindow 799 * @see Component#requestFocus() 800 * @see Component#requestFocusInWindow() 801 * @see Window#isFocusableWindow 802 * @beaninfo 803 * bound: true 804 */ 805 protected void setGlobalFocusedWindow(Window focusedWindow) { 806 Window oldFocusedWindow = null; 807 boolean shouldFire = false; 808 809 if (focusedWindow == null || focusedWindow.isFocusableWindow()) { 810 synchronized (KeyboardFocusManager.class) { 811 checkCurrentKFMSecurity(); 812 813 oldFocusedWindow = getFocusedWindow(); 814 815 try { 816 fireVetoableChange("focusedWindow", oldFocusedWindow, 817 focusedWindow); 818 } catch (PropertyVetoException e) { 819 // rejected 820 return; 821 } 822 823 KeyboardFocusManager.focusedWindow = focusedWindow; 824 shouldFire = true; 825 } 826 } 827 828 if (shouldFire) { 829 firePropertyChange("focusedWindow", oldFocusedWindow, 830 focusedWindow); 831 } 832 } 833 834 /** 835 * Returns the active Window, if the active Window is in the same context 836 * as the calling thread. Only a Frame or a Dialog can be the active 837 * Window. The native windowing system may denote the active Window or its 838 * children with special decorations, such as a highlighted title bar. 839 * The active Window is always either the focused Window, or the first 840 * Frame or Dialog that is an owner of the focused Window. 841 * 842 * @return the active Window, or null if the active Window is not a member 843 * of the calling thread's context 844 * @see #getGlobalActiveWindow 845 * @see #setGlobalActiveWindow 846 */ 847 public Window getActiveWindow() { 848 synchronized (KeyboardFocusManager.class) { 849 if (activeWindow == null) { 850 return null; 851 } 852 853 return (activeWindow.appContext == AppContext.getAppContext()) 854 ? activeWindow 855 : null; 856 } 857 } 858 859 /** 860 * Returns the active Window, even if the calling thread is in a different 861 * context than the active Window. Only a Frame or a Dialog can be the 862 * active Window. The native windowing system may denote the active Window 863 * or its children with special decorations, such as a highlighted title 864 * bar. The active Window is always either the focused Window, or the first 865 * Frame or Dialog that is an owner of the focused Window. 866 * <p> 867 * This method will throw a SecurityException if this KeyboardFocusManager 868 * is not the current KeyboardFocusManager for the calling thread's 869 * context. 870 * 871 * @return the active Window 872 * @see #getActiveWindow 873 * @see #setGlobalActiveWindow 874 * @throws SecurityException if this KeyboardFocusManager is not the 875 * current KeyboardFocusManager for the calling thread's context 876 */ 877 protected Window getGlobalActiveWindow() throws SecurityException { 878 synchronized (KeyboardFocusManager.class) { 879 checkCurrentKFMSecurity(); 880 return activeWindow; 881 } 882 } 883 884 /** 885 * Sets the active Window. Only a Frame or a Dialog can be the active 886 * Window. The native windowing system may denote the active Window or its 887 * children with special decorations, such as a highlighted title bar. The 888 * active Window is always either the focused Window, or the first Frame or 889 * Dialog that is an owner of the focused Window. 890 * <p> 891 * This method does not actually change the active Window as far as the 892 * native windowing system is concerned. It merely stores the value to be 893 * subsequently returned by <code>getActiveWindow()</code>. Use 894 * <code>Component.requestFocus()</code> or 895 * <code>Component.requestFocusInWindow()</code>to change the active 896 * Window, subject to platform limitations. 897 * 898 * @param activeWindow the active Window 899 * @see #getActiveWindow 900 * @see #getGlobalActiveWindow 901 * @see Component#requestFocus() 902 * @see Component#requestFocusInWindow() 903 * @beaninfo 904 * bound: true 905 */ 906 protected void setGlobalActiveWindow(Window activeWindow) { 907 Window oldActiveWindow; 908 synchronized (KeyboardFocusManager.class) { 909 checkCurrentKFMSecurity(); 910 911 oldActiveWindow = getActiveWindow(); 912 if (focusLog.isLoggable(PlatformLogger.FINER)) { 913 focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow); 914 } 915 916 try { 917 fireVetoableChange("activeWindow", oldActiveWindow, 918 activeWindow); 919 } catch (PropertyVetoException e) { 920 // rejected 921 return; 922 } 923 924 KeyboardFocusManager.activeWindow = activeWindow; 925 } 926 927 firePropertyChange("activeWindow", oldActiveWindow, activeWindow); 928 } 929 930 /** 931 * Returns the default FocusTraversalPolicy. Top-level components 932 * use this value on their creation to initialize their own focus traversal 933 * policy by explicit call to Container.setFocusTraversalPolicy. 934 * 935 * @return the default FocusTraversalPolicy. null will never be returned. 936 * @see #setDefaultFocusTraversalPolicy 937 * @see Container#setFocusTraversalPolicy 938 * @see Container#getFocusTraversalPolicy 939 */ 940 public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() { 941 return defaultPolicy; 942 } 943 944 /** 945 * Sets the default FocusTraversalPolicy. Top-level components 946 * use this value on their creation to initialize their own focus traversal 947 * policy by explicit call to Container.setFocusTraversalPolicy. 948 * Note: this call doesn't affect already created components as they have 949 * their policy initialized. Only new components will use this policy as 950 * their default policy. 951 * 952 * @param defaultPolicy the new, default FocusTraversalPolicy 953 * @see #getDefaultFocusTraversalPolicy 954 * @see Container#setFocusTraversalPolicy 955 * @see Container#getFocusTraversalPolicy 956 * @throws IllegalArgumentException if defaultPolicy is null 957 * @beaninfo 958 * bound: true 959 */ 960 public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy 961 defaultPolicy) { 962 if (defaultPolicy == null) { 963 throw new IllegalArgumentException("default focus traversal policy cannot be null"); 964 } 965 966 FocusTraversalPolicy oldPolicy; 967 968 synchronized (this) { 969 oldPolicy = this.defaultPolicy; 970 this.defaultPolicy = defaultPolicy; 971 } 972 973 firePropertyChange("defaultFocusTraversalPolicy", oldPolicy, 974 defaultPolicy); 975 } 976 977 /** 978 * Sets the default focus traversal keys for a given traversal operation. 979 * This traversal key <code>Set</code> will be in effect on all 980 * <code>Window</code>s that have no such <code>Set</code> of 981 * their own explicitly defined. This <code>Set</code> will also be 982 * inherited, recursively, by any child <code>Component</code> of 983 * those <code>Windows</code> that has 984 * no such <code>Set</code> of its own explicitly defined. 985 * <p> 986 * The default values for the default focus traversal keys are 987 * implementation-dependent. Sun recommends that all implementations for a 988 * particular native platform use the same default values. The 989 * recommendations for Windows and Unix are listed below. These 990 * recommendations are used in the Sun AWT implementations. 991 * 992 * <table border=1 summary="Recommended default values for focus traversal keys"> 993 * <tr> 994 * <th>Identifier</th> 995 * <th>Meaning</th> 996 * <th>Default</th> 997 * </tr> 998 * <tr> 999 * <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td> 1000 * <td>Normal forward keyboard traversal</td> 1001 * <td><code>TAB</code> on <code>KEY_PRESSED</code>, 1002 * <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td> 1003 * </tr> 1004 * <tr> 1005 * <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td> 1006 * <td>Normal reverse keyboard traversal</td> 1007 * <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>, 1008 * <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td> 1009 * </tr> 1010 * <tr> 1011 * <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td> 1012 * <td>Go up one focus traversal cycle</td> 1013 * <td>none</td> 1014 * </tr> 1015 * <tr> 1016 * <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td> 1017 * <td>Go down one focus traversal cycle</td> 1018 * <td>none</td> 1019 * </tr> 1020 * </table> 1021 * 1022 * To disable a traversal key, use an empty <code>Set</code>; 1023 * <code>Collections.EMPTY_SET</code> is recommended. 1024 * <p> 1025 * Using the <code>AWTKeyStroke</code> API, client code can 1026 * specify on which of two 1027 * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or 1028 * <code>KEY_RELEASED</code>, the focus traversal operation will 1029 * occur. Regardless of which <code>KeyEvent</code> is specified, 1030 * however, all <code>KeyEvent</code>s related to the focus 1031 * traversal key, including the associated <code>KEY_TYPED</code> 1032 * event, will be consumed, and will not be dispatched 1033 * to any <code>Component</code>. It is a runtime error to 1034 * specify a <code>KEY_TYPED</code> event as 1035 * mapping to a focus traversal operation, or to map the same event to 1036 * multiple default focus traversal operations. 1037 * 1038 * @param id one of 1039 * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>, 1040 * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>, 1041 * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or 1042 * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code> 1043 * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the 1044 * specified operation 1045 * @see #getDefaultFocusTraversalKeys 1046 * @see Component#setFocusTraversalKeys 1047 * @see Component#getFocusTraversalKeys 1048 * @throws IllegalArgumentException if id is not one of 1049 * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>, 1050 * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>, 1051 * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or 1052 * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>, 1053 * or if keystrokes is <code>null</code>, 1054 * or if keystrokes contains <code>null</code>, 1055 * or if any <code>Object</code> in 1056 * keystrokes is not an <code>AWTKeyStroke</code>, 1057 * or if any keystroke 1058 * represents a <code>KEY_TYPED</code> event, 1059 * or if any keystroke already maps 1060 * to another default focus traversal operation 1061 * @beaninfo 1062 * bound: true 1063 */ 1064 public void 1065 setDefaultFocusTraversalKeys(int id, 1066 Set<? extends AWTKeyStroke> keystrokes) 1067 { 1068 if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) { 1069 throw new IllegalArgumentException("invalid focus traversal key identifier"); 1070 } 1071 if (keystrokes == null) { 1072 throw new IllegalArgumentException("cannot set null Set of default focus traversal keys"); 1073 } 1074 1075 Set oldKeys; 1076 1077 synchronized (this) { 1078 for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) { 1079 Object obj = iter.next(); 1080 1081 if (obj == null) { 1082 throw new IllegalArgumentException("cannot set null focus traversal key"); 1083 } 1084 1085 // Fix for 6195831: 1086 //According to javadoc this method should throw IAE instead of ClassCastException 1087 if (!(obj instanceof AWTKeyStroke)) { 1088 throw new IllegalArgumentException("object is expected to be AWTKeyStroke"); 1089 } 1090 AWTKeyStroke keystroke = (AWTKeyStroke)obj; 1091 1092 if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) { 1093 throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events"); 1094 } 1095 1096 // Check to see if key already maps to another traversal 1097 // operation 1098 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) { 1099 if (i == id) { 1100 continue; 1101 } 1102 1103 if (defaultFocusTraversalKeys[i].contains(keystroke)) { 1104 throw new IllegalArgumentException("focus traversal keys must be unique for a Component"); 1105 } 1106 } 1107 } 1108 1109 oldKeys = defaultFocusTraversalKeys[id]; 1110 defaultFocusTraversalKeys[id] = 1111 Collections.unmodifiableSet(new HashSet(keystrokes)); 1112 } 1113 1114 firePropertyChange(defaultFocusTraversalKeyPropertyNames[id], 1115 oldKeys, keystrokes); 1116 } 1117 1118 /** 1119 * Returns a Set of default focus traversal keys for a given traversal 1120 * operation. This traversal key Set will be in effect on all Windows that 1121 * have no such Set of their own explicitly defined. This Set will also be 1122 * inherited, recursively, by any child Component of those Windows that has 1123 * no such Set of its own explicitly defined. (See 1124 * <code>setDefaultFocusTraversalKeys</code> for a full description of each 1125 * operation.) 1126 * 1127 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 1128 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 1129 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or 1130 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS 1131 * @return the <code>Set</code> of <code>AWTKeyStroke</code>s 1132 * for the specified operation; the <code>Set</code> 1133 * will be unmodifiable, and may be empty; <code>null</code> 1134 * will never be returned 1135 * @see #setDefaultFocusTraversalKeys 1136 * @see Component#setFocusTraversalKeys 1137 * @see Component#getFocusTraversalKeys 1138 * @throws IllegalArgumentException if id is not one of 1139 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, 1140 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, 1141 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or 1142 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS 1143 */ 1144 public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) { 1145 if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) { 1146 throw new IllegalArgumentException("invalid focus traversal key identifier"); 1147 } 1148 1149 // Okay to return Set directly because it is an unmodifiable view 1150 return defaultFocusTraversalKeys[id]; 1151 } 1152 1153 /** 1154 * Returns the current focus cycle root, if the current focus cycle root is 1155 * in the same context as the calling thread. If the focus owner is itself 1156 * a focus cycle root, then it may be ambiguous as to which Components 1157 * represent the next and previous Components to focus during normal focus 1158 * traversal. In that case, the current focus cycle root is used to 1159 * differentiate among the possibilities. 1160 * <p> 1161 * This method is intended to be used only by KeyboardFocusManagers and 1162 * focus implementations. It is not for general client use. 1163 * 1164 * @return the current focus cycle root, or null if the current focus cycle 1165 * root is not a member of the calling thread's context 1166 * @see #getGlobalCurrentFocusCycleRoot 1167 * @see #setGlobalCurrentFocusCycleRoot 1168 */ 1169 public Container getCurrentFocusCycleRoot() { 1170 synchronized (KeyboardFocusManager.class) { 1171 if (currentFocusCycleRoot == null) { 1172 return null; 1173 } 1174 1175 return (currentFocusCycleRoot.appContext == 1176 AppContext.getAppContext()) 1177 ? currentFocusCycleRoot 1178 : null; 1179 } 1180 } 1181 1182 /** 1183 * Returns the current focus cycle root, even if the calling thread is in a 1184 * different context than the current focus cycle root. If the focus owner 1185 * is itself a focus cycle root, then it may be ambiguous as to which 1186 * Components represent the next and previous Components to focus during 1187 * normal focus traversal. In that case, the current focus cycle root is 1188 * used to differentiate among the possibilities. 1189 * <p> 1190 * This method will throw a SecurityException if this KeyboardFocusManager 1191 * is not the current KeyboardFocusManager for the calling thread's 1192 * context. 1193 * 1194 * @return the current focus cycle root, or null if the current focus cycle 1195 * root is not a member of the calling thread's context 1196 * @see #getCurrentFocusCycleRoot 1197 * @see #setGlobalCurrentFocusCycleRoot 1198 * @throws SecurityException if this KeyboardFocusManager is not the 1199 * current KeyboardFocusManager for the calling thread's context 1200 */ 1201 protected Container getGlobalCurrentFocusCycleRoot() 1202 throws SecurityException 1203 { 1204 synchronized (KeyboardFocusManager.class) { 1205 checkCurrentKFMSecurity(); 1206 return currentFocusCycleRoot; 1207 } 1208 } 1209 1210 /** 1211 * Sets the current focus cycle root. If the focus owner is itself a focus 1212 * cycle root, then it may be ambiguous as to which Components represent 1213 * the next and previous Components to focus during normal focus traversal. 1214 * In that case, the current focus cycle root is used to differentiate 1215 * among the possibilities. 1216 * <p> 1217 * This method is intended to be used only by KeyboardFocusManagers and 1218 * focus implementations. It is not for general client use. 1219 * 1220 * @param newFocusCycleRoot the new focus cycle root 1221 * @see #getCurrentFocusCycleRoot 1222 * @see #getGlobalCurrentFocusCycleRoot 1223 * @beaninfo 1224 * bound: true 1225 */ 1226 public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) { 1227 Container oldFocusCycleRoot; 1228 1229 synchronized (KeyboardFocusManager.class) { 1230 checkCurrentKFMSecurity(); 1231 1232 oldFocusCycleRoot = getCurrentFocusCycleRoot(); 1233 currentFocusCycleRoot = newFocusCycleRoot; 1234 } 1235 1236 firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot, 1237 newFocusCycleRoot); 1238 } 1239 1240 /** 1241 * Adds a PropertyChangeListener to the listener list. The listener is 1242 * registered for all bound properties of this class, including the 1243 * following: 1244 * <ul> 1245 * <li>whether the KeyboardFocusManager is currently managing focus 1246 * for this application or applet's browser context 1247 * ("managingFocus")</li> 1248 * <li>the focus owner ("focusOwner")</li> 1249 * <li>the permanent focus owner ("permanentFocusOwner")</li> 1250 * <li>the focused Window ("focusedWindow")</li> 1251 * <li>the active Window ("activeWindow")</li> 1252 * <li>the default focus traversal policy 1253 * ("defaultFocusTraversalPolicy")</li> 1254 * <li>the Set of default FORWARD_TRAVERSAL_KEYS 1255 * ("forwardDefaultFocusTraversalKeys")</li> 1256 * <li>the Set of default BACKWARD_TRAVERSAL_KEYS 1257 * ("backwardDefaultFocusTraversalKeys")</li> 1258 * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS 1259 * ("upCycleDefaultFocusTraversalKeys")</li> 1260 * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS 1261 * ("downCycleDefaultFocusTraversalKeys")</li> 1262 * <li>the current focus cycle root ("currentFocusCycleRoot")</li> 1263 * </ul> 1264 * If listener is null, no exception is thrown and no action is performed. 1265 * 1266 * @param listener the PropertyChangeListener to be added 1267 * @see #removePropertyChangeListener 1268 * @see #getPropertyChangeListeners 1269 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) 1270 */ 1271 public void addPropertyChangeListener(PropertyChangeListener listener) { 1272 if (listener != null) { 1273 synchronized (this) { 1274 if (changeSupport == null) { 1275 changeSupport = new PropertyChangeSupport(this); 1276 } 1277 changeSupport.addPropertyChangeListener(listener); 1278 } 1279 } 1280 } 1281 1282 /** 1283 * Removes a PropertyChangeListener from the listener list. This method 1284 * should be used to remove the PropertyChangeListeners that were 1285 * registered for all bound properties of this class. 1286 * <p> 1287 * If listener is null, no exception is thrown and no action is performed. 1288 * 1289 * @param listener the PropertyChangeListener to be removed 1290 * @see #addPropertyChangeListener 1291 * @see #getPropertyChangeListeners 1292 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) 1293 */ 1294 public void removePropertyChangeListener(PropertyChangeListener listener) { 1295 if (listener != null) { 1296 synchronized (this) { 1297 if (changeSupport != null) { 1298 changeSupport.removePropertyChangeListener(listener); 1299 } 1300 } 1301 } 1302 } 1303 1304 /** 1305 * Returns an array of all the property change listeners 1306 * registered on this keyboard focus manager. 1307 * 1308 * @return all of this keyboard focus manager's 1309 * <code>PropertyChangeListener</code>s 1310 * or an empty array if no property change 1311 * listeners are currently registered 1312 * 1313 * @see #addPropertyChangeListener 1314 * @see #removePropertyChangeListener 1315 * @see #getPropertyChangeListeners(java.lang.String) 1316 * @since 1.4 1317 */ 1318 public synchronized PropertyChangeListener[] getPropertyChangeListeners() { 1319 if (changeSupport == null) { 1320 changeSupport = new PropertyChangeSupport(this); 1321 } 1322 return changeSupport.getPropertyChangeListeners(); 1323 } 1324 1325 /** 1326 * Adds a PropertyChangeListener to the listener list for a specific 1327 * property. The specified property may be user-defined, or one of the 1328 * following: 1329 * <ul> 1330 * <li>whether the KeyboardFocusManager is currently managing focus 1331 * for this application or applet's browser context 1332 * ("managingFocus")</li> 1333 * <li>the focus owner ("focusOwner")</li> 1334 * <li>the permanent focus owner ("permanentFocusOwner")</li> 1335 * <li>the focused Window ("focusedWindow")</li> 1336 * <li>the active Window ("activeWindow")</li> 1337 * <li>the default focus traversal policy 1338 * ("defaultFocusTraversalPolicy")</li> 1339 * <li>the Set of default FORWARD_TRAVERSAL_KEYS 1340 * ("forwardDefaultFocusTraversalKeys")</li> 1341 * <li>the Set of default BACKWARD_TRAVERSAL_KEYS 1342 * ("backwardDefaultFocusTraversalKeys")</li> 1343 * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS 1344 * ("upCycleDefaultFocusTraversalKeys")</li> 1345 * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS 1346 * ("downCycleDefaultFocusTraversalKeys")</li> 1347 * <li>the current focus cycle root ("currentFocusCycleRoot")</li> 1348 * </ul> 1349 * If listener is null, no exception is thrown and no action is performed. 1350 * 1351 * @param propertyName one of the property names listed above 1352 * @param listener the PropertyChangeListener to be added 1353 * @see #addPropertyChangeListener(java.beans.PropertyChangeListener) 1354 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) 1355 * @see #getPropertyChangeListeners(java.lang.String) 1356 */ 1357 public void addPropertyChangeListener(String propertyName, 1358 PropertyChangeListener listener) { 1359 if (listener != null) { 1360 synchronized (this) { 1361 if (changeSupport == null) { 1362 changeSupport = new PropertyChangeSupport(this); 1363 } 1364 changeSupport.addPropertyChangeListener(propertyName, 1365 listener); 1366 } 1367 } 1368 } 1369 1370 /** 1371 * Removes a PropertyChangeListener from the listener list for a specific 1372 * property. This method should be used to remove PropertyChangeListeners 1373 * that were registered for a specific bound property. 1374 * <p> 1375 * If listener is null, no exception is thrown and no action is performed. 1376 * 1377 * @param propertyName a valid property name 1378 * @param listener the PropertyChangeListener to be removed 1379 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) 1380 * @see #getPropertyChangeListeners(java.lang.String) 1381 * @see #removePropertyChangeListener(java.beans.PropertyChangeListener) 1382 */ 1383 public void removePropertyChangeListener(String propertyName, 1384 PropertyChangeListener listener) { 1385 if (listener != null) { 1386 synchronized (this) { 1387 if (changeSupport != null) { 1388 changeSupport.removePropertyChangeListener(propertyName, 1389 listener); 1390 } 1391 } 1392 } 1393 } 1394 1395 /** 1396 * Returns an array of all the <code>PropertyChangeListener</code>s 1397 * associated with the named property. 1398 * 1399 * @return all of the <code>PropertyChangeListener</code>s associated with 1400 * the named property or an empty array if no such listeners have 1401 * been added. 1402 * 1403 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) 1404 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener) 1405 * @since 1.4 1406 */ 1407 public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { 1408 if (changeSupport == null) { 1409 changeSupport = new PropertyChangeSupport(this); 1410 } 1411 return changeSupport.getPropertyChangeListeners(propertyName); 1412 } 1413 1414 /** 1415 * Fires a PropertyChangeEvent in response to a change in a bound property. 1416 * The event will be delivered to all registered PropertyChangeListeners. 1417 * No event will be delivered if oldValue and newValue are the same. 1418 * 1419 * @param propertyName the name of the property that has changed 1420 * @param oldValue the property's previous value 1421 * @param newValue the property's new value 1422 */ 1423 protected void firePropertyChange(String propertyName, Object oldValue, 1424 Object newValue) 1425 { 1426 if (oldValue == newValue) { 1427 return; 1428 } 1429 PropertyChangeSupport changeSupport = this.changeSupport; 1430 if (changeSupport != null) { 1431 changeSupport.firePropertyChange(propertyName, oldValue, newValue); 1432 } 1433 } 1434 1435 /** 1436 * Adds a VetoableChangeListener to the listener list. The listener is 1437 * registered for all vetoable properties of this class, including the 1438 * following: 1439 * <ul> 1440 * <li>the focus owner ("focusOwner")</li> 1441 * <li>the permanent focus owner ("permanentFocusOwner")</li> 1442 * <li>the focused Window ("focusedWindow")</li> 1443 * <li>the active Window ("activeWindow")</li> 1444 * </ul> 1445 * If listener is null, no exception is thrown and no action is performed. 1446 * 1447 * @param listener the VetoableChangeListener to be added 1448 * @see #removeVetoableChangeListener 1449 * @see #getVetoableChangeListeners 1450 * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener) 1451 */ 1452 public void addVetoableChangeListener(VetoableChangeListener listener) { 1453 if (listener != null) { 1454 synchronized (this) { 1455 if (vetoableSupport == null) { 1456 vetoableSupport = 1457 new VetoableChangeSupport(this); 1458 } 1459 vetoableSupport.addVetoableChangeListener(listener); 1460 } 1461 } 1462 } 1463 1464 /** 1465 * Removes a VetoableChangeListener from the listener list. This method 1466 * should be used to remove the VetoableChangeListeners that were 1467 * registered for all vetoable properties of this class. 1468 * <p> 1469 * If listener is null, no exception is thrown and no action is performed. 1470 * 1471 * @param listener the VetoableChangeListener to be removed 1472 * @see #addVetoableChangeListener 1473 * @see #getVetoableChangeListeners 1474 * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener) 1475 */ 1476 public void removeVetoableChangeListener(VetoableChangeListener listener) { 1477 if (listener != null) { 1478 synchronized (this) { 1479 if (vetoableSupport != null) { 1480 vetoableSupport.removeVetoableChangeListener(listener); 1481 } 1482 } 1483 } 1484 } 1485 1486 /** 1487 * Returns an array of all the vetoable change listeners 1488 * registered on this keyboard focus manager. 1489 * 1490 * @return all of this keyboard focus manager's 1491 * <code>VetoableChangeListener</code>s 1492 * or an empty array if no vetoable change 1493 * listeners are currently registered 1494 * 1495 * @see #addVetoableChangeListener 1496 * @see #removeVetoableChangeListener 1497 * @see #getVetoableChangeListeners(java.lang.String) 1498 * @since 1.4 1499 */ 1500 public synchronized VetoableChangeListener[] getVetoableChangeListeners() { 1501 if (vetoableSupport == null) { 1502 vetoableSupport = new VetoableChangeSupport(this); 1503 } 1504 return vetoableSupport.getVetoableChangeListeners(); 1505 } 1506 1507 /** 1508 * Adds a VetoableChangeListener to the listener list for a specific 1509 * property. The specified property may be user-defined, or one of the 1510 * following: 1511 * <ul> 1512 * <li>the focus owner ("focusOwner")</li> 1513 * <li>the permanent focus owner ("permanentFocusOwner")</li> 1514 * <li>the focused Window ("focusedWindow")</li> 1515 * <li>the active Window ("activeWindow")</li> 1516 * </ul> 1517 * If listener is null, no exception is thrown and no action is performed. 1518 * 1519 * @param propertyName one of the property names listed above 1520 * @param listener the VetoableChangeListener to be added 1521 * @see #addVetoableChangeListener(java.beans.VetoableChangeListener) 1522 * @see #removeVetoableChangeListener 1523 * @see #getVetoableChangeListeners 1524 */ 1525 public void addVetoableChangeListener(String propertyName, 1526 VetoableChangeListener listener) { 1527 if (listener != null) { 1528 synchronized (this) { 1529 if (vetoableSupport == null) { 1530 vetoableSupport = 1531 new VetoableChangeSupport(this); 1532 } 1533 vetoableSupport.addVetoableChangeListener(propertyName, 1534 listener); 1535 } 1536 } 1537 } 1538 1539 /** 1540 * Removes a VetoableChangeListener from the listener list for a specific 1541 * property. This method should be used to remove VetoableChangeListeners 1542 * that were registered for a specific bound property. 1543 * <p> 1544 * If listener is null, no exception is thrown and no action is performed. 1545 * 1546 * @param propertyName a valid property name 1547 * @param listener the VetoableChangeListener to be removed 1548 * @see #addVetoableChangeListener 1549 * @see #getVetoableChangeListeners 1550 * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener) 1551 */ 1552 public void removeVetoableChangeListener(String propertyName, 1553 VetoableChangeListener listener) { 1554 if (listener != null) { 1555 synchronized (this) { 1556 if (vetoableSupport != null) { 1557 vetoableSupport.removeVetoableChangeListener(propertyName, 1558 listener); 1559 } 1560 } 1561 } 1562 } 1563 1564 /** 1565 * Returns an array of all the <code>VetoableChangeListener</code>s 1566 * associated with the named property. 1567 * 1568 * @return all of the <code>VetoableChangeListener</code>s associated with 1569 * the named property or an empty array if no such listeners have 1570 * been added. 1571 * 1572 * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener) 1573 * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener) 1574 * @see #getVetoableChangeListeners 1575 * @since 1.4 1576 */ 1577 public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) { 1578 if (vetoableSupport == null) { 1579 vetoableSupport = new VetoableChangeSupport(this); 1580 } 1581 return vetoableSupport.getVetoableChangeListeners(propertyName); 1582 } 1583 1584 /** 1585 * Fires a PropertyChangeEvent in response to a change in a vetoable 1586 * property. The event will be delivered to all registered 1587 * VetoableChangeListeners. If a VetoableChangeListener throws a 1588 * PropertyVetoException, a new event is fired reverting all 1589 * VetoableChangeListeners to the old value and the exception is then 1590 * rethrown. No event will be delivered if oldValue and newValue are the 1591 * same. 1592 * 1593 * @param propertyName the name of the property that has changed 1594 * @param oldValue the property's previous value 1595 * @param newValue the property's new value 1596 * @throws java.beans.PropertyVetoException if a 1597 * <code>VetoableChangeListener</code> threw 1598 * <code>PropertyVetoException</code> 1599 */ 1600 protected void fireVetoableChange(String propertyName, Object oldValue, 1601 Object newValue) 1602 throws PropertyVetoException 1603 { 1604 if (oldValue == newValue) { 1605 return; 1606 } 1607 VetoableChangeSupport vetoableSupport = 1608 this.vetoableSupport; 1609 if (vetoableSupport != null) { 1610 vetoableSupport.fireVetoableChange(propertyName, oldValue, 1611 newValue); 1612 } 1613 } 1614 1615 /** 1616 * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher 1617 * chain. This KeyboardFocusManager will request that each 1618 * KeyEventDispatcher dispatch KeyEvents generated by the user before 1619 * finally dispatching the KeyEvent itself. KeyEventDispatchers will be 1620 * notified in the order in which they were added. Notifications will halt 1621 * as soon as one KeyEventDispatcher returns <code>true</code> from its 1622 * <code>dispatchKeyEvent</code> method. There is no limit to the total 1623 * number of KeyEventDispatchers which can be added, nor to the number of 1624 * times which a particular KeyEventDispatcher instance can be added. 1625 * <p> 1626 * If a null dispatcher is specified, no action is taken and no exception 1627 * is thrown. 1628 * <p> 1629 * In a multithreaded application, {@link KeyEventDispatcher} behaves 1630 * the same as other AWT listeners. See 1631 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 1632 * >AWT Threading Issues</a> for more details. 1633 * 1634 * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain 1635 * @see #removeKeyEventDispatcher 1636 */ 1637 public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) { 1638 if (dispatcher != null) { 1639 synchronized (this) { 1640 if (keyEventDispatchers == null) { 1641 keyEventDispatchers = new java.util.LinkedList(); 1642 } 1643 keyEventDispatchers.add(dispatcher); 1644 } 1645 } 1646 } 1647 1648 /** 1649 * Removes a KeyEventDispatcher which was previously added to this 1650 * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager 1651 * cannot itself be removed, unless it was explicitly re-registered via a 1652 * call to <code>addKeyEventDispatcher</code>. 1653 * <p> 1654 * If a null dispatcher is specified, if the specified dispatcher is not 1655 * in the dispatcher chain, or if this KeyboardFocusManager is specified 1656 * without having been explicitly re-registered, no action is taken and no 1657 * exception is thrown. 1658 * <p> 1659 * In a multithreaded application, {@link KeyEventDispatcher} behaves 1660 * the same as other AWT listeners. See 1661 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 1662 * >AWT Threading Issues</a> for more details. 1663 * 1664 * @param dispatcher the KeyEventDispatcher to remove from the dispatcher 1665 * chain 1666 * @see #addKeyEventDispatcher 1667 */ 1668 public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) { 1669 if (dispatcher != null) { 1670 synchronized (this) { 1671 if (keyEventDispatchers != null) { 1672 keyEventDispatchers.remove(dispatcher); 1673 } 1674 } 1675 } 1676 } 1677 1678 /** 1679 * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List. 1680 * The List will not include this KeyboardFocusManager unless it was 1681 * explicitly re-registered via a call to 1682 * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are 1683 * registered, implementations are free to return null or a List of length 1684 * 0. Client code should not assume one behavior over another, nor should 1685 * it assume that the behavior, once established, will not change. 1686 * 1687 * @return a possibly null or empty List of KeyEventDispatchers 1688 * @see #addKeyEventDispatcher 1689 * @see #removeKeyEventDispatcher 1690 */ 1691 protected synchronized java.util.List<KeyEventDispatcher> 1692 getKeyEventDispatchers() 1693 { 1694 return (keyEventDispatchers != null) 1695 ? (java.util.List)keyEventDispatchers.clone() 1696 : null; 1697 } 1698 1699 /** 1700 * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post- 1701 * processor chain. After a KeyEvent has been dispatched to and handled by 1702 * its target, KeyboardFocusManager will request that each 1703 * KeyEventPostProcessor perform any necessary post-processing as part 1704 * of the KeyEvent's final resolution. KeyEventPostProcessors 1705 * will be notified in the order in which they were added; the current 1706 * KeyboardFocusManager will be notified last. Notifications will halt 1707 * as soon as one KeyEventPostProcessor returns <code>true</code> from its 1708 * <code>postProcessKeyEvent</code> method. There is no limit to the the 1709 * total number of KeyEventPostProcessors that can be added, nor to the 1710 * number of times that a particular KeyEventPostProcessor instance can be 1711 * added. 1712 * <p> 1713 * If a null post-processor is specified, no action is taken and no 1714 * exception is thrown. 1715 * <p> 1716 * In a multithreaded application, {@link KeyEventPostProcessor} behaves 1717 * the same as other AWT listeners. See 1718 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 1719 * >AWT Threading Issues</a> for more details. 1720 * 1721 * @param processor the KeyEventPostProcessor to add to the post-processor 1722 * chain 1723 * @see #removeKeyEventPostProcessor 1724 */ 1725 public void addKeyEventPostProcessor(KeyEventPostProcessor processor) { 1726 if (processor != null) { 1727 synchronized (this) { 1728 if (keyEventPostProcessors == null) { 1729 keyEventPostProcessors = new java.util.LinkedList(); 1730 } 1731 keyEventPostProcessors.add(processor); 1732 } 1733 } 1734 } 1735 1736 1737 /** 1738 * Removes a previously added KeyEventPostProcessor from this 1739 * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager 1740 * cannot itself be entirely removed from the chain. Only additional 1741 * references added via <code>addKeyEventPostProcessor</code> can be 1742 * removed. 1743 * <p> 1744 * If a null post-processor is specified, if the specified post-processor 1745 * is not in the post-processor chain, or if this KeyboardFocusManager is 1746 * specified without having been explicitly added, no action is taken and 1747 * no exception is thrown. 1748 * <p> 1749 * In a multithreaded application, {@link KeyEventPostProcessor} behaves 1750 * the same as other AWT listeners. See 1751 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads" 1752 * >AWT Threading Issues</a> for more details. 1753 * 1754 * @param processor the KeyEventPostProcessor to remove from the post- 1755 * processor chain 1756 * @see #addKeyEventPostProcessor 1757 */ 1758 public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) { 1759 if (processor != null) { 1760 synchronized (this) { 1761 if (keyEventPostProcessors != null) { 1762 keyEventPostProcessors.remove(processor); 1763 } 1764 } 1765 } 1766 } 1767 1768 1769 /** 1770 * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a 1771 * List. The List will not include this KeyboardFocusManager unless it was 1772 * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If 1773 * no KeyEventPostProcessors are registered, implementations are free to 1774 * return null or a List of length 0. Client code should not assume one 1775 * behavior over another, nor should it assume that the behavior, once 1776 * established, will not change. 1777 * 1778 * @return a possibly null or empty List of KeyEventPostProcessors 1779 * @see #addKeyEventPostProcessor 1780 * @see #removeKeyEventPostProcessor 1781 */ 1782 protected java.util.List<KeyEventPostProcessor> 1783 getKeyEventPostProcessors() 1784 { 1785 return (keyEventPostProcessors != null) 1786 ? (java.util.List)keyEventPostProcessors.clone() 1787 : null; 1788 } 1789 1790 1791 1792 static void setMostRecentFocusOwner(Component component) { 1793 Component window = component; 1794 while (window != null && !(window instanceof Window)) { 1795 window = window.parent; 1796 } 1797 if (window != null) { 1798 setMostRecentFocusOwner((Window)window, component); 1799 } 1800 } 1801 static synchronized void setMostRecentFocusOwner(Window window, 1802 Component component) { 1803 // ATTN: component has a strong reference to window via chain 1804 // of Component.parent fields. Since WeakHasMap refers to its 1805 // values strongly, we need to break the strong link from the 1806 // value (component) back to its key (window). 1807 WeakReference weakValue = null; 1808 if (component != null) { 1809 weakValue = new WeakReference(component); 1810 } 1811 mostRecentFocusOwners.put(window, weakValue); 1812 } 1813 static void clearMostRecentFocusOwner(Component comp) { 1814 Container window; 1815 1816 if (comp == null) { 1817 return; 1818 } 1819 1820 synchronized (comp.getTreeLock()) { 1821 window = comp.getParent(); 1822 while (window != null && !(window instanceof Window)) { 1823 window = window.getParent(); 1824 } 1825 } 1826 1827 synchronized (KeyboardFocusManager.class) { 1828 if ((window != null) 1829 && (getMostRecentFocusOwner((Window)window) == comp)) 1830 { 1831 setMostRecentFocusOwner((Window)window, null); 1832 } 1833 // Also clear temporary lost component stored in Window 1834 if (window != null) { 1835 Window realWindow = (Window)window; 1836 if (realWindow.getTemporaryLostComponent() == comp) { 1837 realWindow.setTemporaryLostComponent(null); 1838 } 1839 } 1840 } 1841 } 1842 1843 /* 1844 * Please be careful changing this method! It is called from 1845 * javax.swing.JComponent.runInputVerifier() using reflection. 1846 */ 1847 static synchronized Component getMostRecentFocusOwner(Window window) { 1848 WeakReference weakValue = 1849 (WeakReference)mostRecentFocusOwners.get(window); 1850 return weakValue == null ? null : (Component)weakValue.get(); 1851 } 1852 1853 /** 1854 * This method is called by the AWT event dispatcher requesting that the 1855 * current KeyboardFocusManager dispatch the specified event on its behalf. 1856 * It is expected that all KeyboardFocusManagers will dispatch all 1857 * FocusEvents, all WindowEvents related to focus, and all KeyEvents. 1858 * These events should be dispatched based on the KeyboardFocusManager's 1859 * notion of the focus owner and the focused and active Windows, sometimes 1860 * overriding the source of the specified AWTEvent. Dispatching must be 1861 * done using <code>redispatchEvent</code> to prevent the AWT event 1862 * dispatcher from recursively requesting that the KeyboardFocusManager 1863 * dispatch the event again. If this method returns <code>false</code>, 1864 * then the AWT event dispatcher will attempt to dispatch the event itself. 1865 * 1866 * @param e the AWTEvent to be dispatched 1867 * @return <code>true</code> if this method dispatched the event; 1868 * <code>false</code> otherwise 1869 * @see #redispatchEvent 1870 * @see #dispatchKeyEvent 1871 */ 1872 public abstract boolean dispatchEvent(AWTEvent e); 1873 1874 /** 1875 * Redispatches an AWTEvent in such a way that the AWT event dispatcher 1876 * will not recursively request that the KeyboardFocusManager, or any 1877 * installed KeyEventDispatchers, dispatch the event again. Client 1878 * implementations of <code>dispatchEvent</code> and client-defined 1879 * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code> 1880 * instead of <code>target.dispatchEvent(e)</code> to dispatch an event. 1881 * <p> 1882 * This method is intended to be used only by KeyboardFocusManagers and 1883 * KeyEventDispatchers. It is not for general client use. 1884 * 1885 * @param target the Component to which the event should be dispatched 1886 * @param e the event to dispatch 1887 * @see #dispatchEvent 1888 * @see KeyEventDispatcher 1889 */ 1890 public final void redispatchEvent(Component target, AWTEvent e) { 1891 e.focusManagerIsDispatching = true; 1892 target.dispatchEvent(e); 1893 e.focusManagerIsDispatching = false; 1894 } 1895 1896 /** 1897 * Typically this method will be called by <code>dispatchEvent</code> if no 1898 * other KeyEventDispatcher in the dispatcher chain dispatched the 1899 * KeyEvent, or if no other KeyEventDispatchers are registered. If an 1900 * implementation of this method returns <code>false</code>, 1901 * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or 1902 * may simply return <code>false</code>. If <code>true</code> is returned, 1903 * <code>dispatchEvent</code> should return <code>true</code> as well. 1904 * 1905 * @param e the KeyEvent which the current KeyboardFocusManager has 1906 * requested that this KeyEventDispatcher dispatch 1907 * @return <code>true</code> if the KeyEvent was dispatched; 1908 * <code>false</code> otherwise 1909 * @see #dispatchEvent 1910 */ 1911 public abstract boolean dispatchKeyEvent(KeyEvent e); 1912 1913 /** 1914 * This method will be called by <code>dispatchKeyEvent</code>. 1915 * By default, this method will handle any unconsumed KeyEvents that 1916 * map to an AWT <code>MenuShortcut</code> by consuming the event 1917 * and activating the shortcut. 1918 * 1919 * @param e the KeyEvent to post-process 1920 * @return <code>true</code> to indicate that no other 1921 * KeyEventPostProcessor will be notified of the KeyEvent. 1922 * @see #dispatchKeyEvent 1923 * @see MenuShortcut 1924 */ 1925 public abstract boolean postProcessKeyEvent(KeyEvent e); 1926 1927 /** 1928 * This method initiates a focus traversal operation if and only if the 1929 * KeyEvent represents a focus traversal key for the specified 1930 * focusedComponent. It is expected that focusedComponent is the current 1931 * focus owner, although this need not be the case. If it is not, 1932 * focus traversal will nevertheless proceed as if focusedComponent 1933 * were the current focus owner. 1934 * 1935 * @param focusedComponent the Component that will be the basis for a focus 1936 * traversal operation if the specified event represents a focus 1937 * traversal key for the Component 1938 * @param e the event that may represent a focus traversal key 1939 */ 1940 public abstract void processKeyEvent(Component focusedComponent, 1941 KeyEvent e); 1942 1943 /** 1944 * Called by the AWT to notify the KeyboardFocusManager that it should 1945 * delay dispatching of KeyEvents until the specified Component becomes 1946 * the focus owner. If client code requests a focus change, and the AWT 1947 * determines that this request might be granted by the native windowing 1948 * system, then the AWT will call this method. It is the responsibility of 1949 * the KeyboardFocusManager to delay dispatching of KeyEvents with 1950 * timestamps later than the specified time stamp until the specified 1951 * Component receives a FOCUS_GAINED event, or the AWT cancels the delay 1952 * request by invoking <code>dequeueKeyEvents</code> or 1953 * <code>discardKeyEvents</code>. 1954 * 1955 * @param after timestamp of current event, or the current, system time if 1956 * the current event has no timestamp, or the AWT cannot determine 1957 * which event is currently being handled 1958 * @param untilFocused Component which should receive a FOCUS_GAINED event 1959 * before any pending KeyEvents 1960 * @see #dequeueKeyEvents 1961 * @see #discardKeyEvents 1962 */ 1963 protected abstract void enqueueKeyEvents(long after, 1964 Component untilFocused); 1965 1966 /** 1967 * Called by the AWT to notify the KeyboardFocusManager that it should 1968 * cancel delayed dispatching of KeyEvents. All KeyEvents which were 1969 * enqueued because of a call to <code>enqueueKeyEvents</code> with the 1970 * same timestamp and Component should be released for normal dispatching 1971 * to the current focus owner. If the given timestamp is less than zero, 1972 * the outstanding enqueue request for the given Component with the <b> 1973 * oldest</b> timestamp (if any) should be cancelled. 1974 * 1975 * @param after the timestamp specified in the call to 1976 * <code>enqueueKeyEvents</code>, or any value < 0 1977 * @param untilFocused the Component specified in the call to 1978 * <code>enqueueKeyEvents</code> 1979 * @see #enqueueKeyEvents 1980 * @see #discardKeyEvents 1981 */ 1982 protected abstract void dequeueKeyEvents(long after, 1983 Component untilFocused); 1984 1985 /** 1986 * Called by the AWT to notify the KeyboardFocusManager that it should 1987 * cancel delayed dispatching of KeyEvents. All KeyEvents which were 1988 * enqueued because of one or more calls to <code>enqueueKeyEvents</code> 1989 * with the same Component should be discarded. 1990 * 1991 * @param comp the Component specified in one or more calls to 1992 * <code>enqueueKeyEvents</code> 1993 * @see #enqueueKeyEvents 1994 * @see #dequeueKeyEvents 1995 */ 1996 protected abstract void discardKeyEvents(Component comp); 1997 1998 /** 1999 * Focuses the Component after aComponent, typically based on a 2000 * FocusTraversalPolicy. 2001 * 2002 * @param aComponent the Component that is the basis for the focus 2003 * traversal operation 2004 * @see FocusTraversalPolicy 2005 */ 2006 public abstract void focusNextComponent(Component aComponent); 2007 2008 /** 2009 * Focuses the Component before aComponent, typically based on a 2010 * FocusTraversalPolicy. 2011 * 2012 * @param aComponent the Component that is the basis for the focus 2013 * traversal operation 2014 * @see FocusTraversalPolicy 2015 */ 2016 public abstract void focusPreviousComponent(Component aComponent); 2017 2018 /** 2019 * Moves the focus up one focus traversal cycle. Typically, the focus owner 2020 * is set to aComponent's focus cycle root, and the current focus cycle 2021 * root is set to the new focus owner's focus cycle root. If, however, 2022 * aComponent's focus cycle root is a Window, then typically the focus 2023 * owner is set to the Window's default Component to focus, and the current 2024 * focus cycle root is unchanged. 2025 * 2026 * @param aComponent the Component that is the basis for the focus 2027 * traversal operation 2028 */ 2029 public abstract void upFocusCycle(Component aComponent); 2030 2031 /** 2032 * Moves the focus down one focus traversal cycle. Typically, if 2033 * aContainer is a focus cycle root, then the focus owner is set to 2034 * aContainer's default Component to focus, and the current focus cycle 2035 * root is set to aContainer. If aContainer is not a focus cycle root, then 2036 * no focus traversal operation occurs. 2037 * 2038 * @param aContainer the Container that is the basis for the focus 2039 * traversal operation 2040 */ 2041 public abstract void downFocusCycle(Container aContainer); 2042 2043 /** 2044 * Focuses the Component after the current focus owner. 2045 */ 2046 public final void focusNextComponent() { 2047 Component focusOwner = getFocusOwner(); 2048 if (focusOwner != null) { 2049 focusNextComponent(focusOwner); 2050 } 2051 } 2052 2053 /** 2054 * Focuses the Component before the current focus owner. 2055 */ 2056 public final void focusPreviousComponent() { 2057 Component focusOwner = getFocusOwner(); 2058 if (focusOwner != null) { 2059 focusPreviousComponent(focusOwner); 2060 } 2061 } 2062 2063 /** 2064 * Moves the focus up one focus traversal cycle from the current focus 2065 * owner. Typically, the new focus owner is set to the current focus 2066 * owner's focus cycle root, and the current focus cycle root is set to the 2067 * new focus owner's focus cycle root. If, however, the current focus 2068 * owner's focus cycle root is a Window, then typically the focus owner is 2069 * set to the focus cycle root's default Component to focus, and the 2070 * current focus cycle root is unchanged. 2071 */ 2072 public final void upFocusCycle() { 2073 Component focusOwner = getFocusOwner(); 2074 if (focusOwner != null) { 2075 upFocusCycle(focusOwner); 2076 } 2077 } 2078 2079 /** 2080 * Moves the focus down one focus traversal cycle from the current focus 2081 * owner, if and only if the current focus owner is a Container that is a 2082 * focus cycle root. Typically, the focus owner is set to the current focus 2083 * owner's default Component to focus, and the current focus cycle root is 2084 * set to the current focus owner. If the current focus owner is not a 2085 * Container that is a focus cycle root, then no focus traversal operation 2086 * occurs. 2087 */ 2088 public final void downFocusCycle() { 2089 Component focusOwner = getFocusOwner(); 2090 if (focusOwner instanceof Container) { 2091 downFocusCycle((Container)focusOwner); 2092 } 2093 } 2094 2095 /** 2096 * Dumps the list of focus requests to stderr 2097 */ 2098 void dumpRequests() { 2099 System.err.println(">>> Requests dump, time: " + System.currentTimeMillis()); 2100 synchronized (heavyweightRequests) { 2101 for (HeavyweightFocusRequest req : heavyweightRequests) { 2102 System.err.println(">>> Req: " + req); 2103 } 2104 } 2105 System.err.println(""); 2106 } 2107 2108 private static final class LightweightFocusRequest { 2109 final Component component; 2110 final boolean temporary; 2111 final CausedFocusEvent.Cause cause; 2112 2113 LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) { 2114 this.component = component; 2115 this.temporary = temporary; 2116 this.cause = cause; 2117 } 2118 public String toString() { 2119 return "LightweightFocusRequest[component=" + component + 2120 ",temporary=" + temporary + ", cause=" + cause + "]"; 2121 } 2122 } 2123 2124 private static final class HeavyweightFocusRequest { 2125 final Component heavyweight; 2126 final LinkedList<LightweightFocusRequest> lightweightRequests; 2127 2128 static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER = 2129 new HeavyweightFocusRequest(); 2130 2131 private HeavyweightFocusRequest() { 2132 heavyweight = null; 2133 lightweightRequests = null; 2134 } 2135 2136 HeavyweightFocusRequest(Component heavyweight, Component descendant, 2137 boolean temporary, CausedFocusEvent.Cause cause) { 2138 if (log.isLoggable(PlatformLogger.FINE)) { 2139 if (heavyweight == null) { 2140 log.fine("Assertion (heavyweight != null) failed"); 2141 } 2142 } 2143 2144 this.heavyweight = heavyweight; 2145 this.lightweightRequests = new LinkedList<LightweightFocusRequest>(); 2146 addLightweightRequest(descendant, temporary, cause); 2147 } 2148 boolean addLightweightRequest(Component descendant, 2149 boolean temporary, CausedFocusEvent.Cause cause) { 2150 if (log.isLoggable(PlatformLogger.FINE)) { 2151 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) { 2152 log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed"); 2153 } 2154 if (descendant == null) { 2155 log.fine("Assertion (descendant != null) failed"); 2156 } 2157 } 2158 2159 Component lastDescendant = ((lightweightRequests.size() > 0) 2160 ? lightweightRequests.getLast().component 2161 : null); 2162 2163 if (descendant != lastDescendant) { 2164 // Not a duplicate request 2165 lightweightRequests.add 2166 (new LightweightFocusRequest(descendant, temporary, cause)); 2167 return true; 2168 } else { 2169 return false; 2170 } 2171 } 2172 2173 LightweightFocusRequest getFirstLightweightRequest() { 2174 if (this == CLEAR_GLOBAL_FOCUS_OWNER) { 2175 return null; 2176 } 2177 return lightweightRequests.getFirst(); 2178 } 2179 public String toString() { 2180 boolean first = true; 2181 String str = "HeavyweightFocusRequest[heavweight=" + heavyweight + 2182 ",lightweightRequests="; 2183 if (lightweightRequests == null) { 2184 str += null; 2185 } else { 2186 str += "["; 2187 2188 for (LightweightFocusRequest lwRequest : lightweightRequests) { 2189 if (first) { 2190 first = false; 2191 } else { 2192 str += ","; 2193 } 2194 str += lwRequest; 2195 } 2196 str += "]"; 2197 } 2198 str += "]"; 2199 return str; 2200 } 2201 } 2202 2203 /* 2204 * heavyweightRequests is used as a monitor for synchronized changes of 2205 * currentLightweightRequests, clearingCurrentLightweightRequests and 2206 * newFocusOwner. 2207 */ 2208 private static LinkedList<HeavyweightFocusRequest> heavyweightRequests = 2209 new LinkedList<HeavyweightFocusRequest>(); 2210 private static LinkedList<LightweightFocusRequest> currentLightweightRequests; 2211 private static boolean clearingCurrentLightweightRequests; 2212 private static boolean allowSyncFocusRequests = true; 2213 private static Component newFocusOwner = null; 2214 private static volatile boolean disableRestoreFocus; 2215 2216 static final int SNFH_FAILURE = 0; 2217 static final int SNFH_SUCCESS_HANDLED = 1; 2218 static final int SNFH_SUCCESS_PROCEED = 2; 2219 2220 static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant, 2221 boolean temporary, boolean focusedWindowChangeAllowed, 2222 long time) 2223 { 2224 Window parentWindow = SunToolkit.getContainingWindow(heavyweight); 2225 if (parentWindow == null || !parentWindow.syncLWRequests) { 2226 return false; 2227 } 2228 if (descendant == null) { 2229 // Focus transfers from a lightweight child back to the 2230 // heavyweight Container should be treated like lightweight 2231 // focus transfers. 2232 descendant = heavyweight; 2233 } 2234 2235 KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant)); 2236 2237 FocusEvent currentFocusOwnerEvent = null; 2238 FocusEvent newFocusOwnerEvent = null; 2239 Component currentFocusOwner = manager.getGlobalFocusOwner(); 2240 2241 synchronized (heavyweightRequests) { 2242 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest(); 2243 if (hwFocusRequest == null && 2244 heavyweight == manager.getNativeFocusOwner() && 2245 allowSyncFocusRequests) 2246 { 2247 2248 if (descendant == currentFocusOwner) { 2249 // Redundant request. 2250 return true; 2251 } 2252 2253 // 'heavyweight' owns the native focus and there are no pending 2254 // requests. 'heavyweight' must be a Container and 2255 // 'descendant' must not be the focus owner. Otherwise, 2256 // we would never have gotten this far. 2257 manager.enqueueKeyEvents(time, descendant); 2258 2259 hwFocusRequest = 2260 new HeavyweightFocusRequest(heavyweight, descendant, 2261 temporary, CausedFocusEvent.Cause.UNKNOWN); 2262 heavyweightRequests.add(hwFocusRequest); 2263 2264 if (currentFocusOwner != null) { 2265 currentFocusOwnerEvent = 2266 new FocusEvent(currentFocusOwner, 2267 FocusEvent.FOCUS_LOST, 2268 temporary, descendant); 2269 } 2270 newFocusOwnerEvent = 2271 new FocusEvent(descendant, FocusEvent.FOCUS_GAINED, 2272 temporary, currentFocusOwner); 2273 } 2274 } 2275 boolean result = false; 2276 final boolean clearing = clearingCurrentLightweightRequests; 2277 2278 Throwable caughtEx = null; 2279 try { 2280 clearingCurrentLightweightRequests = false; 2281 synchronized(Component.LOCK) { 2282 2283 if (currentFocusOwnerEvent != null && currentFocusOwner != null) { 2284 ((AWTEvent) currentFocusOwnerEvent).isPosted = true; 2285 caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent); 2286 result = true; 2287 } 2288 2289 if (newFocusOwnerEvent != null && descendant != null) { 2290 ((AWTEvent) newFocusOwnerEvent).isPosted = true; 2291 caughtEx = dispatchAndCatchException(caughtEx, descendant, newFocusOwnerEvent); 2292 result = true; 2293 } 2294 } 2295 } finally { 2296 clearingCurrentLightweightRequests = clearing; 2297 } 2298 if (caughtEx instanceof RuntimeException) { 2299 throw (RuntimeException)caughtEx; 2300 } else if (caughtEx instanceof Error) { 2301 throw (Error)caughtEx; 2302 } 2303 return result; 2304 } 2305 2306 /** 2307 * Indicates whether the native implementation should proceed with a 2308 * pending, native focus request. Before changing the focus at the native 2309 * level, the AWT implementation should always call this function for 2310 * permission. This function will reject the request if a duplicate request 2311 * preceded it, or if the specified heavyweight Component already owns the 2312 * focus and no native focus changes are pending. Otherwise, the request 2313 * will be approved and the focus request list will be updated so that, 2314 * if necessary, the proper descendant will be focused when the 2315 * corresponding FOCUS_GAINED event on the heavyweight is received. 2316 * 2317 * An implementation must ensure that calls to this method and native 2318 * focus changes are atomic. If this is not guaranteed, then the ordering 2319 * of the focus request list may be incorrect, leading to errors in the 2320 * type-ahead mechanism. Typically this is accomplished by only calling 2321 * this function from the native event pumping thread, or by holding a 2322 * global, native lock during invocation. 2323 */ 2324 static int shouldNativelyFocusHeavyweight 2325 (Component heavyweight, Component descendant, boolean temporary, 2326 boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) 2327 { 2328 if (log.isLoggable(PlatformLogger.FINE)) { 2329 if (heavyweight == null) { 2330 log.fine("Assertion (heavyweight != null) failed"); 2331 } 2332 if (time == 0) { 2333 log.fine("Assertion (time != 0) failed"); 2334 } 2335 } 2336 2337 if (descendant == null) { 2338 // Focus transfers from a lightweight child back to the 2339 // heavyweight Container should be treated like lightweight 2340 // focus transfers. 2341 descendant = heavyweight; 2342 } 2343 2344 KeyboardFocusManager manager = 2345 getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant)); 2346 KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager(); 2347 Component currentFocusOwner = thisManager.getGlobalFocusOwner(); 2348 Component nativeFocusOwner = thisManager.getNativeFocusOwner(); 2349 Window nativeFocusedWindow = thisManager.getNativeFocusedWindow(); 2350 if (focusLog.isLoggable(PlatformLogger.FINER)) { 2351 focusLog.finer("SNFH for {0} in {1}", 2352 String.valueOf(descendant), String.valueOf(heavyweight)); 2353 } 2354 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 2355 focusLog.finest("0. Current focus owner {0}", 2356 String.valueOf(currentFocusOwner)); 2357 focusLog.finest("0. Native focus owner {0}", 2358 String.valueOf(nativeFocusOwner)); 2359 focusLog.finest("0. Native focused window {0}", 2360 String.valueOf(nativeFocusedWindow)); 2361 } 2362 synchronized (heavyweightRequests) { 2363 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest(); 2364 if (focusLog.isLoggable(PlatformLogger.FINEST)) { 2365 focusLog.finest("Request {0}", String.valueOf(hwFocusRequest)); 2366 } 2367 if (hwFocusRequest == null && 2368 heavyweight == nativeFocusOwner) 2369 { 2370 if (descendant == currentFocusOwner) { 2371 // Redundant request. 2372 if (focusLog.isLoggable(PlatformLogger.FINEST)) 2373 focusLog.finest("1. SNFH_FAILURE for {0}", 2374 String.valueOf(descendant)); 2375 return SNFH_FAILURE; 2376 } 2377 2378 // 'heavyweight' owns the native focus and there are no pending 2379 // requests. 'heavyweight' must be a Container and 2380 // 'descendant' must not be the focus owner. Otherwise, 2381 // we would never have gotten this far. 2382 manager.enqueueKeyEvents(time, descendant); 2383 2384 hwFocusRequest = 2385 new HeavyweightFocusRequest(heavyweight, descendant, 2386 temporary, cause); 2387 heavyweightRequests.add(hwFocusRequest); 2388 2389 if (currentFocusOwner != null) { 2390 FocusEvent currentFocusOwnerEvent = 2391 new CausedFocusEvent(currentFocusOwner, 2392 FocusEvent.FOCUS_LOST, 2393 temporary, descendant, cause); 2394 // Fix 5028014. Rolled out. 2395 // SunToolkit.postPriorityEvent(currentFocusOwnerEvent); 2396 SunToolkit.postEvent(currentFocusOwner.appContext, 2397 currentFocusOwnerEvent); 2398 } 2399 FocusEvent newFocusOwnerEvent = 2400 new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED, 2401 temporary, currentFocusOwner, cause); 2402 // Fix 5028014. Rolled out. 2403 // SunToolkit.postPriorityEvent(newFocusOwnerEvent); 2404 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent); 2405 2406 if (focusLog.isLoggable(PlatformLogger.FINEST)) 2407 focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(descendant)); 2408 return SNFH_SUCCESS_HANDLED; 2409 } else if (hwFocusRequest != null && 2410 hwFocusRequest.heavyweight == heavyweight) { 2411 // 'heavyweight' doesn't have the native focus right now, but 2412 // if all pending requests were completed, it would. Add 2413 // descendant to the heavyweight's list of pending 2414 // lightweight focus transfers. 2415 if (hwFocusRequest.addLightweightRequest(descendant, 2416 temporary, cause)) { 2417 manager.enqueueKeyEvents(time, descendant); 2418 } 2419 2420 if (focusLog.isLoggable(PlatformLogger.FINEST)) 2421 focusLog.finest("3. SNFH_HANDLED for lightweight" + 2422 descendant + " in " + heavyweight); 2423 return SNFH_SUCCESS_HANDLED; 2424 } else { 2425 if (!focusedWindowChangeAllowed) { 2426 // For purposes of computing oldFocusedWindow, we should look at 2427 // the second to last HeavyweightFocusRequest on the queue iff the 2428 // last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If 2429 // there is no second to last HeavyweightFocusRequest, null is an 2430 // acceptable value. 2431 if (hwFocusRequest == 2432 HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) 2433 { 2434 int size = heavyweightRequests.size(); 2435 hwFocusRequest = (HeavyweightFocusRequest)((size >= 2) 2436 ? heavyweightRequests.get(size - 2) 2437 : null); 2438 } 2439 if (focusedWindowChanged(heavyweight, 2440 (hwFocusRequest != null) 2441 ? hwFocusRequest.heavyweight 2442 : nativeFocusedWindow)) { 2443 if (focusLog.isLoggable(PlatformLogger.FINEST)) 2444 focusLog.finest("4. SNFH_FAILURE for " + descendant); 2445 return SNFH_FAILURE; 2446 } 2447 } 2448 2449 manager.enqueueKeyEvents(time, descendant); 2450 heavyweightRequests.add 2451 (new HeavyweightFocusRequest(heavyweight, descendant, 2452 temporary, cause)); 2453 if (focusLog.isLoggable(PlatformLogger.FINEST)) 2454 focusLog.finest("5. SNFH_PROCEED for " + descendant); 2455 return SNFH_SUCCESS_PROCEED; 2456 } 2457 } 2458 } 2459 2460 /** 2461 * Returns the Window which will be active after processing this request, 2462 * or null if this is a duplicate request. The active Window is useful 2463 * because some native platforms do not support setting the native focus 2464 * owner to null. On these platforms, the obvious choice is to set the 2465 * focus owner to the focus proxy of the active Window. 2466 */ 2467 static Window markClearGlobalFocusOwner() { 2468 // need to call this out of synchronized block to avoid possible deadlock 2469 // see 6454631. 2470 final Component nativeFocusedWindow = 2471 getCurrentKeyboardFocusManager().getNativeFocusedWindow(); 2472 2473 synchronized (heavyweightRequests) { 2474 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest(); 2475 if (hwFocusRequest == 2476 HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) 2477 { 2478 // duplicate request 2479 return null; 2480 } 2481 2482 heavyweightRequests.add 2483 (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER); 2484 2485 Component activeWindow = ((hwFocusRequest != null) 2486 ? SunToolkit.getContainingWindow(hwFocusRequest.heavyweight) 2487 : nativeFocusedWindow); 2488 while (activeWindow != null && 2489 !((activeWindow instanceof Frame) || 2490 (activeWindow instanceof Dialog))) 2491 { 2492 activeWindow = activeWindow.getParent_NoClientCode(); 2493 } 2494 2495 return (Window) activeWindow; 2496 } 2497 } 2498 Component getCurrentWaitingRequest(Component parent) { 2499 synchronized (heavyweightRequests) { 2500 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest(); 2501 if (hwFocusRequest != null) { 2502 if (hwFocusRequest.heavyweight == parent) { 2503 LightweightFocusRequest lwFocusRequest = 2504 hwFocusRequest.lightweightRequests.getFirst(); 2505 if (lwFocusRequest != null) { 2506 return lwFocusRequest.component; 2507 } 2508 } 2509 } 2510 } 2511 return null; 2512 } 2513 2514 static boolean isAutoFocusTransferEnabled() { 2515 synchronized (heavyweightRequests) { 2516 return (heavyweightRequests.size() == 0) 2517 && !disableRestoreFocus 2518 && (null == currentLightweightRequests); 2519 } 2520 } 2521 2522 static boolean isAutoFocusTransferEnabledFor(Component comp) { 2523 return isAutoFocusTransferEnabled() && comp.isAutoFocusTransferOnDisposal(); 2524 } 2525 2526 /* 2527 * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks). 2528 * @param ex previously caught exception that may be processed right here, or null 2529 * @param comp the component to dispatch the event to 2530 * @param event the event to dispatch to the component 2531 */ 2532 static private Throwable dispatchAndCatchException(Throwable ex, Component comp, FocusEvent event) { 2533 Throwable retEx = null; 2534 try { 2535 comp.dispatchEvent(event); 2536 } catch (RuntimeException re) { 2537 retEx = re; 2538 } catch (Error er) { 2539 retEx = er; 2540 } 2541 if (retEx != null) { 2542 if (ex != null) { 2543 handleException(ex); 2544 } 2545 return retEx; 2546 } 2547 return ex; 2548 } 2549 2550 static private void handleException(Throwable ex) { 2551 ex.printStackTrace(); 2552 } 2553 2554 static void processCurrentLightweightRequests() { 2555 KeyboardFocusManager manager = getCurrentKeyboardFocusManager(); 2556 LinkedList<LightweightFocusRequest> localLightweightRequests = null; 2557 2558 Component globalFocusOwner = manager.getGlobalFocusOwner(); 2559 if ((globalFocusOwner != null) && 2560 (globalFocusOwner.appContext != AppContext.getAppContext())) 2561 { 2562 // The current app context differs from the app context of a focus 2563 // owner (and all pending lightweight requests), so we do nothing 2564 // now and wait for a next event. 2565 return; 2566 } 2567 2568 synchronized(heavyweightRequests) { 2569 if (currentLightweightRequests != null) { 2570 clearingCurrentLightweightRequests = true; 2571 disableRestoreFocus = true; 2572 localLightweightRequests = currentLightweightRequests; 2573 allowSyncFocusRequests = (localLightweightRequests.size() < 2); 2574 currentLightweightRequests = null; 2575 } else { 2576 // do nothing 2577 return; 2578 } 2579 } 2580 2581 Throwable caughtEx = null; 2582 try { 2583 if (localLightweightRequests != null) { 2584 Component lastFocusOwner = null; 2585 Component currentFocusOwner = null; 2586 2587 for (Iterator iter = localLightweightRequests.iterator(); iter.hasNext(); ) { 2588 2589 currentFocusOwner = manager.getGlobalFocusOwner(); 2590 LightweightFocusRequest lwFocusRequest = 2591 (LightweightFocusRequest)iter.next(); 2592 2593 /* 2594 * WARNING: This is based on DKFM's logic solely! 2595 * 2596 * We allow to trigger restoreFocus() in the dispatching process 2597 * only if we have the last request to dispatch. If the last request 2598 * fails, focus will be restored to either the component of the last 2599 * previously succedded request, or to to the focus owner that was 2600 * before this clearing proccess. 2601 */ 2602 if (!iter.hasNext()) { 2603 disableRestoreFocus = false; 2604 } 2605 2606 FocusEvent currentFocusOwnerEvent = null; 2607 /* 2608 * We're not dispatching FOCUS_LOST while the current focus owner is null. 2609 * But regardless of whether it's null or not, we're clearing ALL the local 2610 * lw requests. 2611 */ 2612 if (currentFocusOwner != null) { 2613 currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner, 2614 FocusEvent.FOCUS_LOST, 2615 lwFocusRequest.temporary, 2616 lwFocusRequest.component, lwFocusRequest.cause); 2617 } 2618 FocusEvent newFocusOwnerEvent = 2619 new CausedFocusEvent(lwFocusRequest.component, 2620 FocusEvent.FOCUS_GAINED, 2621 lwFocusRequest.temporary, 2622 currentFocusOwner == null ? lastFocusOwner : currentFocusOwner, 2623 lwFocusRequest.cause); 2624 2625 if (currentFocusOwner != null) { 2626 ((AWTEvent) currentFocusOwnerEvent).isPosted = true; 2627 caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent); 2628 } 2629 2630 ((AWTEvent) newFocusOwnerEvent).isPosted = true; 2631 caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent); 2632 2633 if (manager.getGlobalFocusOwner() == lwFocusRequest.component) { 2634 lastFocusOwner = lwFocusRequest.component; 2635 } 2636 } 2637 } 2638 } finally { 2639 clearingCurrentLightweightRequests = false; 2640 disableRestoreFocus = false; 2641 localLightweightRequests = null; 2642 allowSyncFocusRequests = true; 2643 } 2644 if (caughtEx instanceof RuntimeException) { 2645 throw (RuntimeException)caughtEx; 2646 } else if (caughtEx instanceof Error) { 2647 throw (Error)caughtEx; 2648 } 2649 } 2650 2651 static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) { 2652 synchronized (heavyweightRequests) { 2653 // Any other case represents a failure condition which we did 2654 // not expect. We need to clearFocusRequestList() and patch up 2655 // the event as best as possible. 2656 2657 if (removeFirstRequest()) { 2658 return (FocusEvent)retargetFocusEvent(fe); 2659 } 2660 2661 Component source = fe.getComponent(); 2662 Component opposite = fe.getOppositeComponent(); 2663 boolean temporary = false; 2664 if (fe.getID() == FocusEvent.FOCUS_LOST && 2665 (opposite == null || isTemporary(opposite, source))) 2666 { 2667 temporary = true; 2668 } 2669 return new CausedFocusEvent(source, fe.getID(), temporary, opposite, 2670 CausedFocusEvent.Cause.NATIVE_SYSTEM); 2671 } 2672 } 2673 2674 static FocusEvent retargetFocusGained(FocusEvent fe) { 2675 assert (fe.getID() == FocusEvent.FOCUS_GAINED); 2676 2677 Component currentFocusOwner = getCurrentKeyboardFocusManager(). 2678 getGlobalFocusOwner(); 2679 Component source = fe.getComponent(); 2680 Component opposite = fe.getOppositeComponent(); 2681 Component nativeSource = getHeavyweight(source); 2682 2683 synchronized (heavyweightRequests) { 2684 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest(); 2685 2686 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) 2687 { 2688 return retargetUnexpectedFocusEvent(fe); 2689 } 2690 2691 if (source != null && nativeSource == null && hwFocusRequest != null) { 2692 // if source w/o peer and 2693 // if source is equal to first lightweight 2694 // then we should correct source and nativeSource 2695 if (source == hwFocusRequest.getFirstLightweightRequest().component) 2696 { 2697 source = hwFocusRequest.heavyweight; 2698 nativeSource = source; // source is heavuweight itself 2699 } 2700 } 2701 if (hwFocusRequest != null && 2702 nativeSource == hwFocusRequest.heavyweight) 2703 { 2704 // Focus change as a result of a known call to requestFocus(), 2705 // or known click on a peer focusable heavyweight Component. 2706 2707 heavyweightRequests.removeFirst(); 2708 2709 LightweightFocusRequest lwFocusRequest = 2710 hwFocusRequest.lightweightRequests.removeFirst(); 2711 2712 Component newSource = lwFocusRequest.component; 2713 if (currentFocusOwner != null) { 2714 /* 2715 * Since we receive FOCUS_GAINED when current focus 2716 * owner is not null, correcponding FOCUS_LOST is supposed 2717 * to be lost. And so, we keep new focus owner 2718 * to determine synthetic FOCUS_LOST event which will be 2719 * generated by KeyboardFocusManager for this FOCUS_GAINED. 2720 * 2721 * This code based on knowledge of 2722 * DefaultKeyboardFocusManager's implementation and might 2723 * be not applicable for another KeyboardFocusManager. 2724 */ 2725 newFocusOwner = newSource; 2726 } 2727 2728 boolean temporary = (opposite == null || 2729 isTemporary(newSource, opposite)) 2730 ? false 2731 : lwFocusRequest.temporary; 2732 2733 if (hwFocusRequest.lightweightRequests.size() > 0) { 2734 currentLightweightRequests = 2735 hwFocusRequest.lightweightRequests; 2736 EventQueue.invokeLater(new Runnable() { 2737 public void run() { 2738 processCurrentLightweightRequests(); 2739 } 2740 }); 2741 } 2742 2743 // 'opposite' will be fixed by 2744 // DefaultKeyboardFocusManager.realOppositeComponent 2745 return new CausedFocusEvent(newSource, 2746 FocusEvent.FOCUS_GAINED, temporary, 2747 opposite, lwFocusRequest.cause); 2748 } 2749 2750 if (currentFocusOwner != null 2751 && currentFocusOwner.getContainingWindow() == source 2752 && (hwFocusRequest == null || source != hwFocusRequest.heavyweight)) 2753 { 2754 // Special case for FOCUS_GAINED in top-levels 2755 // If it arrives as the result of activation we should skip it 2756 // This event will not have appropriate request record and 2757 // on arrival there will be already some focus owner set. 2758 return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false, 2759 null, CausedFocusEvent.Cause.ACTIVATION); 2760 } 2761 2762 return retargetUnexpectedFocusEvent(fe); 2763 } // end synchronized(heavyweightRequests) 2764 } 2765 2766 static FocusEvent retargetFocusLost(FocusEvent fe) { 2767 assert (fe.getID() == FocusEvent.FOCUS_LOST); 2768 2769 Component currentFocusOwner = getCurrentKeyboardFocusManager(). 2770 getGlobalFocusOwner(); 2771 Component opposite = fe.getOppositeComponent(); 2772 Component nativeOpposite = getHeavyweight(opposite); 2773 2774 synchronized (heavyweightRequests) { 2775 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest(); 2776 2777 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) 2778 { 2779 if (currentFocusOwner != null) { 2780 // Call to KeyboardFocusManager.clearGlobalFocusOwner() 2781 heavyweightRequests.removeFirst(); 2782 return new CausedFocusEvent(currentFocusOwner, 2783 FocusEvent.FOCUS_LOST, false, null, 2784 CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER); 2785 } 2786 2787 // Otherwise, fall through to failure case below 2788 2789 } else if (opposite == null) 2790 { 2791 // Focus leaving application 2792 if (currentFocusOwner != null) { 2793 return new CausedFocusEvent(currentFocusOwner, 2794 FocusEvent.FOCUS_LOST, 2795 true, null, CausedFocusEvent.Cause.ACTIVATION); 2796 } else { 2797 return fe; 2798 } 2799 } else if (hwFocusRequest != null && 2800 (nativeOpposite == hwFocusRequest.heavyweight || 2801 nativeOpposite == null && 2802 opposite == hwFocusRequest.getFirstLightweightRequest().component)) 2803 { 2804 if (currentFocusOwner == null) { 2805 return fe; 2806 } 2807 // Focus change as a result of a known call to requestFocus(), 2808 // or click on a peer focusable heavyweight Component. 2809 // If a focus transfer is made across top-levels, then the 2810 // FOCUS_LOST event is always temporary, and the FOCUS_GAINED 2811 // event is always permanent. Otherwise, the stored temporary 2812 // value is honored. 2813 2814 LightweightFocusRequest lwFocusRequest = 2815 hwFocusRequest.lightweightRequests.getFirst(); 2816 2817 boolean temporary = isTemporary(opposite, currentFocusOwner) 2818 ? true 2819 : lwFocusRequest.temporary; 2820 2821 return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, 2822 temporary, lwFocusRequest.component, lwFocusRequest.cause); 2823 } else if (focusedWindowChanged(opposite, currentFocusOwner)) { 2824 // If top-level changed there might be no focus request in a list 2825 // But we know the opposite, we now it is temporary - dispatch the event. 2826 if (!fe.isTemporary() && currentFocusOwner != null) { 2827 // Create copy of the event with only difference in temporary parameter. 2828 fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST, 2829 true, opposite, CausedFocusEvent.Cause.ACTIVATION); 2830 } 2831 return fe; 2832 } 2833 2834 return retargetUnexpectedFocusEvent(fe); 2835 } // end synchronized(heavyweightRequests) 2836 } 2837 2838 static AWTEvent retargetFocusEvent(AWTEvent event) { 2839 if (clearingCurrentLightweightRequests) { 2840 return event; 2841 } 2842 2843 KeyboardFocusManager manager = getCurrentKeyboardFocusManager(); 2844 if (focusLog.isLoggable(PlatformLogger.FINER)) { 2845 if (event instanceof FocusEvent || event instanceof WindowEvent) { 2846 focusLog.finer(">>> {0}", String.valueOf(event)); 2847 } 2848 if (focusLog.isLoggable(PlatformLogger.FINER) && event instanceof KeyEvent) { 2849 focusLog.finer(" focus owner is {0}", 2850 String.valueOf(manager.getGlobalFocusOwner())); 2851 focusLog.finer(">>> {0}", String.valueOf(event)); 2852 } 2853 } 2854 2855 synchronized(heavyweightRequests) { 2856 /* 2857 * This code handles FOCUS_LOST event which is generated by 2858 * DefaultKeyboardFocusManager for FOCUS_GAINED. 2859 * 2860 * This code based on knowledge of DefaultKeyboardFocusManager's 2861 * implementation and might be not applicable for another 2862 * KeyboardFocusManager. 2863 * 2864 * Fix for 4472032 2865 */ 2866 if (newFocusOwner != null && 2867 event.getID() == FocusEvent.FOCUS_LOST) 2868 { 2869 FocusEvent fe = (FocusEvent)event; 2870 2871 if (manager.getGlobalFocusOwner() == fe.getComponent() && 2872 fe.getOppositeComponent() == newFocusOwner) 2873 { 2874 newFocusOwner = null; 2875 return event; 2876 } 2877 } 2878 } 2879 2880 processCurrentLightweightRequests(); 2881 2882 switch (event.getID()) { 2883 case FocusEvent.FOCUS_GAINED: { 2884 event = retargetFocusGained((FocusEvent)event); 2885 break; 2886 } 2887 case FocusEvent.FOCUS_LOST: { 2888 event = retargetFocusLost((FocusEvent)event); 2889 break; 2890 } 2891 default: 2892 /* do nothing */ 2893 } 2894 return event; 2895 } 2896 2897 /** 2898 * Clears markers queue 2899 * This method is not intended to be overridden by KFM's. 2900 * Only DefaultKeyboardFocusManager can implement it. 2901 * @since 1.5 2902 */ 2903 void clearMarkers() { 2904 } 2905 2906 static boolean removeFirstRequest() { 2907 KeyboardFocusManager manager = 2908 KeyboardFocusManager.getCurrentKeyboardFocusManager(); 2909 2910 synchronized(heavyweightRequests) { 2911 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest(); 2912 2913 if (hwFocusRequest != null) { 2914 heavyweightRequests.removeFirst(); 2915 if (hwFocusRequest.lightweightRequests != null) { 2916 for (Iterator lwIter = hwFocusRequest.lightweightRequests. 2917 iterator(); 2918 lwIter.hasNext(); ) 2919 { 2920 manager.dequeueKeyEvents 2921 (-1, ((LightweightFocusRequest)lwIter.next()). 2922 component); 2923 } 2924 } 2925 } 2926 // Fix for 4799136 - clear type-ahead markers if requests queue is empty 2927 // We do it here because this method is called only when problems happen 2928 if (heavyweightRequests.size() == 0) { 2929 manager.clearMarkers(); 2930 } 2931 return (heavyweightRequests.size() > 0); 2932 } 2933 } 2934 static void removeLastFocusRequest(Component heavyweight) { 2935 if (log.isLoggable(PlatformLogger.FINE)) { 2936 if (heavyweight == null) { 2937 log.fine("Assertion (heavyweight != null) failed"); 2938 } 2939 } 2940 2941 KeyboardFocusManager manager = 2942 KeyboardFocusManager.getCurrentKeyboardFocusManager(); 2943 synchronized(heavyweightRequests) { 2944 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest(); 2945 if (hwFocusRequest != null && 2946 hwFocusRequest.heavyweight == heavyweight) { 2947 heavyweightRequests.removeLast(); 2948 } 2949 // Fix for 4799136 - clear type-ahead markers if requests queue is empty 2950 // We do it here because this method is called only when problems happen 2951 if (heavyweightRequests.size() == 0) { 2952 manager.clearMarkers(); 2953 } 2954 } 2955 } 2956 2957 private static boolean focusedWindowChanged(Component to, Component from) { 2958 Window wto = SunToolkit.getContainingWindow(to); 2959 Window wfrom = SunToolkit.getContainingWindow(from); 2960 if (wto == null && wfrom == null) { 2961 return true; 2962 } 2963 if (wto == null) { 2964 return true; 2965 } 2966 if (wfrom == null) { 2967 return true; 2968 } 2969 return (wto != wfrom); 2970 } 2971 2972 private static boolean isTemporary(Component to, Component from) { 2973 Window wto = SunToolkit.getContainingWindow(to); 2974 Window wfrom = SunToolkit.getContainingWindow(from); 2975 if (wto == null && wfrom == null) { 2976 return false; 2977 } 2978 if (wto == null) { 2979 return true; 2980 } 2981 if (wfrom == null) { 2982 return false; 2983 } 2984 return (wto != wfrom); 2985 } 2986 2987 static Component getHeavyweight(Component comp) { 2988 if (comp == null || comp.getPeer() == null) { 2989 return null; 2990 } else if (comp.getPeer() instanceof LightweightPeer) { 2991 return comp.getNativeContainer(); 2992 } else { 2993 return comp; 2994 } 2995 } 2996 2997 static Field proxyActive; 2998 // Accessor to private field isProxyActive of KeyEvent 2999 private static boolean isProxyActiveImpl(KeyEvent e) { 3000 if (proxyActive == null) { 3001 proxyActive = (Field) AccessController.doPrivileged(new PrivilegedAction() { 3002 public Object run() { 3003 Field field = null; 3004 try { 3005 field = KeyEvent.class.getDeclaredField("isProxyActive"); 3006 if (field != null) { 3007 field.setAccessible(true); 3008 } 3009 } catch (NoSuchFieldException nsf) { 3010 assert(false); 3011 } 3012 return field; 3013 } 3014 }); 3015 } 3016 3017 try { 3018 return proxyActive.getBoolean(e); 3019 } catch (IllegalAccessException iae) { 3020 assert(false); 3021 } 3022 return false; 3023 } 3024 3025 // Returns the value of this KeyEvent's field isProxyActive 3026 static boolean isProxyActive(KeyEvent e) { 3027 if (!GraphicsEnvironment.isHeadless()) { 3028 return isProxyActiveImpl(e); 3029 } else { 3030 return false; 3031 } 3032 } 3033 3034 private static HeavyweightFocusRequest getLastHWRequest() { 3035 synchronized(heavyweightRequests) { 3036 return (heavyweightRequests.size() > 0) 3037 ? heavyweightRequests.getLast() 3038 : null; 3039 } 3040 } 3041 3042 private static HeavyweightFocusRequest getFirstHWRequest() { 3043 synchronized(heavyweightRequests) { 3044 return (heavyweightRequests.size() > 0) 3045 ? heavyweightRequests.getFirst() 3046 : null; 3047 } 3048 } 3049 3050 private void checkCurrentKFMSecurity() { 3051 if (this != getCurrentKeyboardFocusManager()) { 3052 if (focusLog.isLoggable(PlatformLogger.FINER)) { 3053 focusLog.finer("This manager is " + this + 3054 ", current is " + getCurrentKeyboardFocusManager()); 3055 } 3056 throw new SecurityException(notPrivileged); 3057 } 3058 } 3059 }