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