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