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