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