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