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