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