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