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