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