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