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