0001 /*
0002 * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025 package java.awt;
0026
0027 import java.awt.event.FocusEvent;
0028 import java.awt.event.InputEvent;
0029 import java.awt.event.KeyEvent;
0030 import java.awt.event.WindowEvent;
0031
0032 import java.awt.peer.KeyboardFocusManagerPeer;
0033 import java.awt.peer.LightweightPeer;
0034
0035 import java.beans.PropertyChangeListener;
0036 import java.beans.PropertyChangeSupport;
0037 import java.beans.PropertyVetoException;
0038 import java.beans.VetoableChangeListener;
0039 import java.beans.VetoableChangeSupport;
0040
0041 import java.lang.ref.WeakReference;
0042
0043 import java.lang.reflect.Field;
0044
0045 import java.security.AccessController;
0046 import java.security.PrivilegedAction;
0047
0048 import java.util.Collections;
0049 import java.util.HashSet;
0050 import java.util.Iterator;
0051 import java.util.LinkedList;
0052 import java.util.Set;
0053 import java.util.StringTokenizer;
0054 import java.util.WeakHashMap;
0055
0056 import java.util.logging.Level;
0057 import java.util.logging.Logger;
0058
0059 import sun.awt.AppContext;
0060 import sun.awt.DebugHelper;
0061 import sun.awt.HeadlessToolkit;
0062 import sun.awt.SunToolkit;
0063 import sun.awt.CausedFocusEvent;
0064
0065 /**
0066 * The KeyboardFocusManager is responsible for managing the active and focused
0067 * Windows, and the current focus owner. The focus owner is defined as the
0068 * Component in an application that will typically receive all KeyEvents
0069 * generated by the user. The focused Window is the Window that is, or
0070 * contains, the focus owner. Only a Frame or a Dialog can be the active
0071 * Window. The native windowing system may denote the active Window or its
0072 * children with special decorations, such as a highlighted title bar. The
0073 * active Window is always either the focused Window, or the first Frame or
0074 * Dialog that is an owner of the focused Window.
0075 * <p>
0076 * The KeyboardFocusManager is both a centralized location for client code to
0077 * query for the focus owner and initiate focus changes, and an event
0078 * dispatcher for all FocusEvents, WindowEvents related to focus, and
0079 * KeyEvents.
0080 * <p>
0081 * Some browsers partition applets in different code bases into separate
0082 * contexts, and establish walls between these contexts. In such a scenario,
0083 * there will be one KeyboardFocusManager per context. Other browsers place all
0084 * applets into the same context, implying that there will be only a single,
0085 * global KeyboardFocusManager for all applets. This behavior is
0086 * implementation-dependent. Consult your browser's documentation for more
0087 * information. No matter how many contexts there may be, however, there can
0088 * never be more than one focus owner, focused Window, or active Window, per
0089 * ClassLoader.
0090 * <p>
0091 * Please see
0092 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
0093 * How to Use the Focus Subsystem</a>,
0094 * a section in <em>The Java Tutorial</em>, and the
0095 * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
0096 * for more information.
0097 *
0098 * @author David Mendenhall
0099 * @version 1.83, 06/25/07
0100 *
0101 * @see Window
0102 * @see Frame
0103 * @see Dialog
0104 * @see java.awt.event.FocusEvent
0105 * @see java.awt.event.WindowEvent
0106 * @see java.awt.event.KeyEvent
0107 * @since 1.4
0108 */
0109 public abstract class KeyboardFocusManager implements
0110 KeyEventDispatcher, KeyEventPostProcessor {
0111
0112 // Shared focus engine logger
0113 private static final Logger focusLog = Logger
0114 .getLogger("java.awt.focus.KeyboardFocusManager");
0115
0116 static {
0117 /* ensure that the necessary native libraries are loaded */
0118 Toolkit.loadLibraries();
0119 if (!GraphicsEnvironment.isHeadless()) {
0120 initIDs();
0121 }
0122 }
0123
0124 transient KeyboardFocusManagerPeer peer;
0125
0126 /**
0127 * Initialize JNI field and method IDs
0128 */
0129 private static native void initIDs();
0130
0131 private static final DebugHelper dbg = DebugHelper
0132 .create(KeyboardFocusManager.class);
0133
0134 /**
0135 * The identifier for the Forward focus traversal keys.
0136 *
0137 * @see #setDefaultFocusTraversalKeys
0138 * @see #getDefaultFocusTraversalKeys
0139 * @see Component#setFocusTraversalKeys
0140 * @see Component#getFocusTraversalKeys
0141 */
0142 public static final int FORWARD_TRAVERSAL_KEYS = 0;
0143
0144 /**
0145 * The identifier for the Backward focus traversal keys.
0146 *
0147 * @see #setDefaultFocusTraversalKeys
0148 * @see #getDefaultFocusTraversalKeys
0149 * @see Component#setFocusTraversalKeys
0150 * @see Component#getFocusTraversalKeys
0151 */
0152 public static final int BACKWARD_TRAVERSAL_KEYS = 1;
0153
0154 /**
0155 * The identifier for the Up Cycle focus traversal keys.
0156 *
0157 * @see #setDefaultFocusTraversalKeys
0158 * @see #getDefaultFocusTraversalKeys
0159 * @see Component#setFocusTraversalKeys
0160 * @see Component#getFocusTraversalKeys
0161 */
0162 public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
0163
0164 /**
0165 * The identifier for the Down Cycle focus traversal keys.
0166 *
0167 * @see #setDefaultFocusTraversalKeys
0168 * @see #getDefaultFocusTraversalKeys
0169 * @see Component#setFocusTraversalKeys
0170 * @see Component#getFocusTraversalKeys
0171 */
0172 public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
0173
0174 static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
0175
0176 /**
0177 * Returns the current KeyboardFocusManager instance for the calling
0178 * thread's context.
0179 *
0180 * @return this thread's context's KeyboardFocusManager
0181 * @see #setCurrentKeyboardFocusManager
0182 */
0183 public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
0184 return getCurrentKeyboardFocusManager(AppContext
0185 .getAppContext());
0186 }
0187
0188 synchronized static KeyboardFocusManager getCurrentKeyboardFocusManager(
0189 AppContext appcontext) {
0190 KeyboardFocusManager manager = (KeyboardFocusManager) appcontext
0191 .get(KeyboardFocusManager.class);
0192 if (manager == null) {
0193 manager = new DefaultKeyboardFocusManager();
0194 appcontext.put(KeyboardFocusManager.class, manager);
0195 }
0196 return manager;
0197 }
0198
0199 /**
0200 * Sets the current KeyboardFocusManager instance for the calling thread's
0201 * context. If null is specified, then the current KeyboardFocusManager
0202 * is replaced with a new instance of DefaultKeyboardFocusManager.
0203 * <p>
0204 * If a SecurityManager is installed, the calling thread must be granted
0205 * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
0206 * the current KeyboardFocusManager. If this permission is not granted,
0207 * this method will throw a SecurityException, and the current
0208 * KeyboardFocusManager will be unchanged.
0209 *
0210 * @param newManager the new KeyboardFocusManager for this thread's context
0211 * @see #getCurrentKeyboardFocusManager
0212 * @see DefaultKeyboardFocusManager
0213 * @throws SecurityException if the calling thread does not have permission
0214 * to replace the current KeyboardFocusManager
0215 */
0216 public static void setCurrentKeyboardFocusManager(
0217 KeyboardFocusManager newManager) throws SecurityException {
0218 SecurityManager security = System.getSecurityManager();
0219 if (security != null) {
0220 if (replaceKeyboardFocusManagerPermission == null) {
0221 replaceKeyboardFocusManagerPermission = new AWTPermission(
0222 "replaceKeyboardFocusManager");
0223 }
0224 security
0225 .checkPermission(replaceKeyboardFocusManagerPermission);
0226 }
0227
0228 KeyboardFocusManager oldManager = null;
0229
0230 synchronized (KeyboardFocusManager.class) {
0231 AppContext appcontext = AppContext.getAppContext();
0232
0233 if (newManager != null) {
0234 oldManager = getCurrentKeyboardFocusManager(appcontext);
0235
0236 appcontext.put(KeyboardFocusManager.class, newManager);
0237 } else {
0238 oldManager = getCurrentKeyboardFocusManager(appcontext);
0239 appcontext.remove(KeyboardFocusManager.class);
0240 }
0241 }
0242
0243 if (oldManager != null) {
0244 oldManager.firePropertyChange("managingFocus",
0245 Boolean.TRUE, Boolean.FALSE);
0246 }
0247 if (newManager != null) {
0248 newManager.firePropertyChange("managingFocus",
0249 Boolean.FALSE, Boolean.TRUE);
0250 }
0251 }
0252
0253 /**
0254 * The Component in an application that will typically receive all
0255 * KeyEvents generated by the user.
0256 */
0257 private static Component focusOwner;
0258
0259 /**
0260 * The Component in an application that will regain focus when an
0261 * outstanding temporary focus transfer has completed, or the focus owner,
0262 * if no outstanding temporary transfer exists.
0263 */
0264 private static Component permanentFocusOwner;
0265
0266 /**
0267 * The Window which is, or contains, the focus owner.
0268 */
0269 private static Window focusedWindow;
0270
0271 /**
0272 * Only a Frame or a Dialog can be the active Window. The native windowing
0273 * system may denote the active Window with a special decoration, such as a
0274 * highlighted title bar. The active Window is always either the focused
0275 * Window, or the first Frame or Dialog which is an owner of the focused
0276 * Window.
0277 */
0278 private static Window activeWindow;
0279
0280 /**
0281 * The default FocusTraversalPolicy for all Windows that have no policy of
0282 * their own set. If those Windows have focus-cycle-root children that have
0283 * no keyboard-traversal policy of their own, then those children will also
0284 * inherit this policy (as will, recursively, their focus-cycle-root
0285 * children).
0286 */
0287 private FocusTraversalPolicy defaultPolicy = new DefaultFocusTraversalPolicy();
0288
0289 /**
0290 * The bound property names of each focus traversal key.
0291 */
0292 private static final String[] defaultFocusTraversalKeyPropertyNames = {
0293 "forwardDefaultFocusTraversalKeys",
0294 "backwardDefaultFocusTraversalKeys",
0295 "upCycleDefaultFocusTraversalKeys",
0296 "downCycleDefaultFocusTraversalKeys" };
0297
0298 /**
0299 * The default strokes for initializing the default focus traversal keys.
0300 */
0301 private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
0302 {
0303 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0,
0304 false),
0305 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
0306 InputEvent.CTRL_DOWN_MASK
0307 | InputEvent.CTRL_MASK, false), },
0308 {
0309 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
0310 InputEvent.SHIFT_DOWN_MASK
0311 | InputEvent.SHIFT_MASK, false),
0312 AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
0313 InputEvent.SHIFT_DOWN_MASK
0314 | InputEvent.SHIFT_MASK
0315 | InputEvent.CTRL_DOWN_MASK
0316 | InputEvent.CTRL_MASK, false), },
0317 {}, {}, };
0318 /**
0319 * The default focus traversal keys. Each array of traversal keys will be
0320 * in effect on all Windows that have no such array of their own explicitly
0321 * set. Each array will also be inherited, recursively, by any child
0322 * Component of those Windows that has no such array of its own explicitly
0323 * set.
0324 */
0325 private Set[] defaultFocusTraversalKeys = new Set[4];
0326
0327 /**
0328 * The current focus cycle root. If the focus owner is itself a focus cycle
0329 * root, then it may be ambiguous as to which Components represent the next
0330 * and previous Components to focus during normal focus traversal. In that
0331 * case, the current focus cycle root is used to differentiate among the
0332 * possibilities.
0333 */
0334 private static Container currentFocusCycleRoot;
0335
0336 /**
0337 * A description of any VetoableChangeListeners which have been registered.
0338 */
0339 private VetoableChangeSupport vetoableSupport;
0340
0341 /**
0342 * A description of any PropertyChangeListeners which have been registered.
0343 */
0344 private PropertyChangeSupport changeSupport;
0345
0346 /**
0347 * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
0348 * include this KeyboardFocusManager unless it was explicitly re-registered
0349 * via a call to <code>addKeyEventDispatcher</code>. If no other
0350 * KeyEventDispatchers are registered, this field may be null or refer to
0351 * a List of length 0.
0352 */
0353 private java.util.LinkedList keyEventDispatchers;
0354
0355 /**
0356 * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
0357 * not include this KeyboardFocusManager unless it was explicitly
0358 * re-registered via a call to <code>addKeyEventPostProcessor</code>.
0359 * If no other KeyEventPostProcessors are registered, this field may be
0360 * null or refer to a List of length 0.
0361 */
0362 private java.util.LinkedList keyEventPostProcessors;
0363
0364 /**
0365 * Maps Windows to those Windows' most recent focus owners.
0366 */
0367 private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
0368
0369 /**
0370 * Error String for initializing SecurityExceptions.
0371 */
0372 private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
0373
0374 /**
0375 * We cache the permission used to verify that the calling thread is
0376 * permitted to access the global focus state.
0377 */
0378 private static AWTPermission replaceKeyboardFocusManagerPermission;
0379
0380 /*
0381 * SequencedEvent which is currently dispatched in AppContext.
0382 */
0383 transient SequencedEvent currentSequencedEvent = null;
0384
0385 final void setCurrentSequencedEvent(SequencedEvent current) {
0386 synchronized (SequencedEvent.class) {
0387 assert (current == null || currentSequencedEvent == null);
0388 currentSequencedEvent = current;
0389 }
0390 }
0391
0392 final SequencedEvent getCurrentSequencedEvent() {
0393 synchronized (SequencedEvent.class) {
0394 return currentSequencedEvent;
0395 }
0396 }
0397
0398 static Set initFocusTraversalKeysSet(String value, Set targetSet) {
0399 StringTokenizer tokens = new StringTokenizer(value, ",");
0400 while (tokens.hasMoreTokens()) {
0401 targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens
0402 .nextToken()));
0403 }
0404 return (targetSet.isEmpty()) ? Collections.EMPTY_SET
0405 : Collections.unmodifiableSet(targetSet);
0406 }
0407
0408 /**
0409 * Initializes a KeyboardFocusManager.
0410 */
0411 public KeyboardFocusManager() {
0412 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
0413 Set work_set = new HashSet();
0414 for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
0415 work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
0416 }
0417 defaultFocusTraversalKeys[i] = (work_set.isEmpty()) ? Collections.EMPTY_SET
0418 : Collections.unmodifiableSet(work_set);
0419 }
0420 initPeer();
0421 }
0422
0423 private void initPeer() {
0424 if (Toolkit.getDefaultToolkit() instanceof HeadlessToolkit) {
0425 peer = ((HeadlessToolkit) Toolkit.getDefaultToolkit())
0426 .createKeyboardFocusManagerPeer(this );
0427 }
0428 if (Toolkit.getDefaultToolkit() instanceof SunToolkit) {
0429 peer = ((SunToolkit) Toolkit.getDefaultToolkit())
0430 .createKeyboardFocusManagerPeer(this );
0431 }
0432 }
0433
0434 /**
0435 * Returns the focus owner, if the focus owner is in the same context as
0436 * the calling thread. The focus owner is defined as the Component in an
0437 * application that will typically receive all KeyEvents generated by the
0438 * user. KeyEvents which map to the focus owner's focus traversal keys will
0439 * not be delivered if focus traversal keys are enabled for the focus
0440 * owner. In addition, KeyEventDispatchers may retarget or consume
0441 * KeyEvents before they reach the focus owner.
0442 *
0443 * @return the focus owner, or null if the focus owner is not a member of
0444 * the calling thread's context
0445 * @see #getGlobalFocusOwner
0446 * @see #setGlobalFocusOwner
0447 */
0448 public Component getFocusOwner() {
0449 synchronized (KeyboardFocusManager.class) {
0450 if (focusOwner == null) {
0451 return null;
0452 }
0453
0454 return (focusOwner.appContext == AppContext.getAppContext()) ? focusOwner
0455 : null;
0456 }
0457 }
0458
0459 /**
0460 * Returns the focus owner, even if the calling thread is in a different
0461 * context than the focus owner. The focus owner is defined as the
0462 * Component in an application that will typically receive all KeyEvents
0463 * generated by the user. KeyEvents which map to the focus owner's focus
0464 * traversal keys will not be delivered if focus traversal keys are enabled
0465 * for the focus owner. In addition, KeyEventDispatchers may retarget or
0466 * consume KeyEvents before they reach the focus owner.
0467 * <p>
0468 * This method will throw a SecurityException if this KeyboardFocusManager
0469 * is not the current KeyboardFocusManager for the calling thread's
0470 * context.
0471 *
0472 * @return the focus owner
0473 * @see #getFocusOwner
0474 * @see #setGlobalFocusOwner
0475 * @throws SecurityException if this KeyboardFocusManager is not the
0476 * current KeyboardFocusManager for the calling thread's context
0477 */
0478 protected Component getGlobalFocusOwner() throws SecurityException {
0479 synchronized (KeyboardFocusManager.class) {
0480 if (this == getCurrentKeyboardFocusManager()) {
0481 return focusOwner;
0482 } else {
0483 if (focusLog.isLoggable(Level.FINE))
0484 focusLog.fine("This manager is " + this
0485 + ", current is "
0486 + getCurrentKeyboardFocusManager());
0487 throw new SecurityException(notPrivileged);
0488 }
0489 }
0490 }
0491
0492 /**
0493 * Sets the focus owner. The operation will be cancelled if the Component
0494 * is not focusable. The focus owner is defined as the Component in an
0495 * application that will typically receive all KeyEvents generated by the
0496 * user. KeyEvents which map to the focus owner's focus traversal keys will
0497 * not be delivered if focus traversal keys are enabled for the focus
0498 * owner. In addition, KeyEventDispatchers may retarget or consume
0499 * KeyEvents before they reach the focus owner.
0500 * <p>
0501 * This method does not actually set the focus to the specified Component.
0502 * It merely stores the value to be subsequently returned by
0503 * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
0504 * or <code>Component.requestFocusInWindow()</code> to change the focus
0505 * owner, subject to platform limitations.
0506 *
0507 * @param focusOwner the focus owner
0508 * @see #getFocusOwner
0509 * @see #getGlobalFocusOwner
0510 * @see Component#requestFocus()
0511 * @see Component#requestFocusInWindow()
0512 * @see Component#isFocusable
0513 * @beaninfo
0514 * bound: true
0515 */
0516 protected void setGlobalFocusOwner(Component focusOwner) {
0517 Component oldFocusOwner = null;
0518 boolean shouldFire = false;
0519
0520 if (focusOwner == null || focusOwner.isFocusable()) {
0521 synchronized (KeyboardFocusManager.class) {
0522 oldFocusOwner = getFocusOwner();
0523
0524 try {
0525 fireVetoableChange("focusOwner", oldFocusOwner,
0526 focusOwner);
0527 } catch (PropertyVetoException e) {
0528 // rejected
0529 return;
0530 }
0531
0532 KeyboardFocusManager.focusOwner = focusOwner;
0533
0534 if (focusOwner != null
0535 && (getCurrentFocusCycleRoot() == null || !focusOwner
0536 .isFocusCycleRoot(getCurrentFocusCycleRoot()))) {
0537 Container rootAncestor = focusOwner
0538 .getFocusCycleRootAncestor();
0539 if (rootAncestor == null
0540 && (focusOwner instanceof Window)) {
0541 rootAncestor = (Container) focusOwner;
0542 }
0543 if (rootAncestor != null) {
0544 setGlobalCurrentFocusCycleRoot(rootAncestor);
0545 }
0546 }
0547
0548 shouldFire = true;
0549 }
0550 }
0551
0552 if (shouldFire) {
0553 firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
0554 }
0555 }
0556
0557 /**
0558 * Clears the global focus owner at both the Java and native levels. If
0559 * there exists a focus owner, that Component will receive a permanent
0560 * FOCUS_LOST event. After this operation completes, the native windowing
0561 * system will discard all user-generated KeyEvents until the user selects
0562 * a new Component to receive focus, or a Component is given focus
0563 * explicitly via a call to <code>requestFocus()</code>. This operation
0564 * does not change the focused or active Windows.
0565 *
0566 * @see Component#requestFocus()
0567 * @see java.awt.event.FocusEvent#FOCUS_LOST
0568 */
0569 public void clearGlobalFocusOwner() {
0570 if (!GraphicsEnvironment.isHeadless()) {
0571 // Toolkit must be fully initialized, otherwise
0572 // _clearGlobalFocusOwner will crash or throw an exception
0573 Toolkit.getDefaultToolkit();
0574
0575 _clearGlobalFocusOwner();
0576 }
0577 }
0578
0579 private void _clearGlobalFocusOwner() {
0580 Window activeWindow = markClearGlobalFocusOwner();
0581 peer.clearGlobalFocusOwner(activeWindow);
0582 }
0583
0584 Component getNativeFocusOwner() {
0585 return peer.getCurrentFocusOwner();
0586 }
0587
0588 void setNativeFocusOwner(Component comp) {
0589 focusLog.log(Level.FINEST,
0590 "Calling peer {0} setCurrentFocusOwner for {1}",
0591 new Object[] { peer, comp });
0592 peer.setCurrentFocusOwner(comp);
0593 }
0594
0595 Window getNativeFocusedWindow() {
0596 return peer.getCurrentFocusedWindow();
0597 }
0598
0599 /**
0600 * Returns the permanent focus owner, if the permanent focus owner is in
0601 * the same context as the calling thread. The permanent focus owner is
0602 * defined as the last Component in an application to receive a permanent
0603 * FOCUS_GAINED event. The focus owner and permanent focus owner are
0604 * equivalent unless a temporary focus change is currently in effect. In
0605 * such a situation, the permanent focus owner will again be the focus
0606 * owner when the temporary focus change ends.
0607 *
0608 * @return the permanent focus owner, or null if the permanent focus owner
0609 * is not a member of the calling thread's context
0610 * @see #getGlobalPermanentFocusOwner
0611 * @see #setGlobalPermanentFocusOwner
0612 */
0613 public Component getPermanentFocusOwner() {
0614 synchronized (KeyboardFocusManager.class) {
0615 if (permanentFocusOwner == null) {
0616 return null;
0617 }
0618
0619 return (permanentFocusOwner.appContext == AppContext
0620 .getAppContext()) ? permanentFocusOwner : null;
0621 }
0622 }
0623
0624 /**
0625 * Returns the permanent focus owner, even if the calling thread is in a
0626 * different context than the permanent focus owner. The permanent focus
0627 * owner is defined as the last Component in an application to receive a
0628 * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
0629 * are equivalent unless a temporary focus change is currently in effect.
0630 * In such a situation, the permanent focus owner will again be the focus
0631 * owner when the temporary focus change ends.
0632 * <p>
0633 * This method will throw a SecurityException if this KeyboardFocusManager
0634 * is not the current KeyboardFocusManager for the calling thread's
0635 * context.
0636 *
0637 * @return the permanent focus owner
0638 * @see #getPermanentFocusOwner
0639 * @see #setGlobalPermanentFocusOwner
0640 * @throws SecurityException if this KeyboardFocusManager is not the
0641 * current KeyboardFocusManager for the calling thread's context
0642 */
0643 protected Component getGlobalPermanentFocusOwner()
0644 throws SecurityException {
0645 synchronized (KeyboardFocusManager.class) {
0646 if (this == getCurrentKeyboardFocusManager()) {
0647 return permanentFocusOwner;
0648 } else {
0649 if (focusLog.isLoggable(Level.FINE))
0650 focusLog.fine("This manager is " + this
0651 + ", current is "
0652 + getCurrentKeyboardFocusManager());
0653 throw new SecurityException(notPrivileged);
0654 }
0655 }
0656 }
0657
0658 /**
0659 * Sets the permanent focus owner. The operation will be cancelled if the
0660 * Component is not focusable. The permanent focus owner is defined as the
0661 * last Component in an application to receive a permanent FOCUS_GAINED
0662 * event. The focus owner and permanent focus owner are equivalent unless
0663 * a temporary focus change is currently in effect. In such a situation,
0664 * the permanent focus owner will again be the focus owner when the
0665 * temporary focus change ends.
0666 * <p>
0667 * This method does not actually set the focus to the specified Component.
0668 * It merely stores the value to be subsequently returned by
0669 * <code>getPermanentFocusOwner()</code>. Use
0670 * <code>Component.requestFocus()</code> or
0671 * <code>Component.requestFocusInWindow()</code> to change the focus owner,
0672 * subject to platform limitations.
0673 *
0674 * @param permanentFocusOwner the permanent focus owner
0675 * @see #getPermanentFocusOwner
0676 * @see #getGlobalPermanentFocusOwner
0677 * @see Component#requestFocus()
0678 * @see Component#requestFocusInWindow()
0679 * @see Component#isFocusable
0680 * @beaninfo
0681 * bound: true
0682 */
0683 protected void setGlobalPermanentFocusOwner(
0684 Component permanentFocusOwner) {
0685 Component oldPermanentFocusOwner = null;
0686 boolean shouldFire = false;
0687
0688 if (permanentFocusOwner == null
0689 || permanentFocusOwner.isFocusable()) {
0690 synchronized (KeyboardFocusManager.class) {
0691 oldPermanentFocusOwner = getPermanentFocusOwner();
0692
0693 try {
0694 fireVetoableChange("permanentFocusOwner",
0695 oldPermanentFocusOwner, permanentFocusOwner);
0696 } catch (PropertyVetoException e) {
0697 // rejected
0698 return;
0699 }
0700
0701 KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
0702
0703 KeyboardFocusManager
0704 .setMostRecentFocusOwner(permanentFocusOwner);
0705
0706 shouldFire = true;
0707 }
0708 }
0709
0710 if (shouldFire) {
0711 firePropertyChange("permanentFocusOwner",
0712 oldPermanentFocusOwner, permanentFocusOwner);
0713 }
0714 }
0715
0716 /**
0717 * Returns the focused Window, if the focused Window is in the same context
0718 * as the calling thread. The focused Window is the Window that is or
0719 * contains the focus owner.
0720 *
0721 * @return the focused Window, or null if the focused Window is not a
0722 * member of the calling thread's context
0723 * @see #getGlobalFocusedWindow
0724 * @see #setGlobalFocusedWindow
0725 */
0726 public Window getFocusedWindow() {
0727 synchronized (KeyboardFocusManager.class) {
0728 if (focusedWindow == null) {
0729 return null;
0730 }
0731
0732 return (focusedWindow.appContext == AppContext
0733 .getAppContext()) ? focusedWindow : null;
0734 }
0735 }
0736
0737 /**
0738 * Returns the focused Window, even if the calling thread is in a different
0739 * context than the focused Window. The focused Window is the Window that
0740 * is or contains the focus owner.
0741 * <p>
0742 * This method will throw a SecurityException if this KeyboardFocusManager
0743 * is not the current KeyboardFocusManager for the calling thread's
0744 * context.
0745 *
0746 * @return the focused Window
0747 * @see #getFocusedWindow
0748 * @see #setGlobalFocusedWindow
0749 * @throws SecurityException if this KeyboardFocusManager is not the
0750 * current KeyboardFocusManager for the calling thread's context
0751 */
0752 protected Window getGlobalFocusedWindow() throws SecurityException {
0753 synchronized (KeyboardFocusManager.class) {
0754 if (this == getCurrentKeyboardFocusManager()) {
0755 return focusedWindow;
0756 } else {
0757 if (focusLog.isLoggable(Level.FINE))
0758 focusLog.fine("This manager is " + this
0759 + ", current is "
0760 + getCurrentKeyboardFocusManager());
0761 throw new SecurityException(notPrivileged);
0762 }
0763 }
0764 }
0765
0766 /**
0767 * Sets the focused Window. The focused Window is the Window that is or
0768 * contains the focus owner. The operation will be cancelled if the
0769 * specified Window to focus is not a focusable Window.
0770 * <p>
0771 * This method does not actually change the focused Window as far as the
0772 * native windowing system is concerned. It merely stores the value to be
0773 * subsequently returned by <code>getFocusedWindow()</code>. Use
0774 * <code>Component.requestFocus()</code> or
0775 * <code>Component.requestFocusInWindow()</code> to change the focused
0776 * Window, subject to platform limitations.
0777 *
0778 * @param focusedWindow the focused Window
0779 * @see #getFocusedWindow
0780 * @see #getGlobalFocusedWindow
0781 * @see Component#requestFocus()
0782 * @see Component#requestFocusInWindow()
0783 * @see Window#isFocusableWindow
0784 * @beaninfo
0785 * bound: true
0786 */
0787 protected void setGlobalFocusedWindow(Window focusedWindow) {
0788 Window oldFocusedWindow = null;
0789 boolean shouldFire = false;
0790
0791 if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
0792 synchronized (KeyboardFocusManager.class) {
0793 oldFocusedWindow = getFocusedWindow();
0794
0795 try {
0796 fireVetoableChange("focusedWindow",
0797 oldFocusedWindow, focusedWindow);
0798 } catch (PropertyVetoException e) {
0799 // rejected
0800 return;
0801 }
0802
0803 KeyboardFocusManager.focusedWindow = focusedWindow;
0804 shouldFire = true;
0805 }
0806 }
0807
0808 if (shouldFire) {
0809 firePropertyChange("focusedWindow", oldFocusedWindow,
0810 focusedWindow);
0811 }
0812 }
0813
0814 /**
0815 * Returns the active Window, if the active Window is in the same context
0816 * as the calling thread. Only a Frame or a Dialog can be the active
0817 * Window. The native windowing system may denote the active Window or its
0818 * children with special decorations, such as a highlighted title bar.
0819 * The active Window is always either the focused Window, or the first
0820 * Frame or Dialog that is an owner of the focused Window.
0821 *
0822 * @return the active Window, or null if the active Window is not a member
0823 * of the calling thread's context
0824 * @see #getGlobalActiveWindow
0825 * @see #setGlobalActiveWindow
0826 */
0827 public Window getActiveWindow() {
0828 synchronized (KeyboardFocusManager.class) {
0829 if (activeWindow == null) {
0830 return null;
0831 }
0832
0833 return (activeWindow.appContext == AppContext
0834 .getAppContext()) ? activeWindow : null;
0835 }
0836 }
0837
0838 /**
0839 * Returns the active Window, even if the calling thread is in a different
0840 * context than the active Window. Only a Frame or a Dialog can be the
0841 * active Window. The native windowing system may denote the active Window
0842 * or its children with special decorations, such as a highlighted title
0843 * bar. The active Window is always either the focused Window, or the first
0844 * Frame or Dialog that is an owner of the focused Window.
0845 * <p>
0846 * This method will throw a SecurityException if this KeyboardFocusManager
0847 * is not the current KeyboardFocusManager for the calling thread's
0848 * context.
0849 *
0850 * @return the active Window
0851 * @see #getActiveWindow
0852 * @see #setGlobalActiveWindow
0853 * @throws SecurityException if this KeyboardFocusManager is not the
0854 * current KeyboardFocusManager for the calling thread's context
0855 */
0856 protected Window getGlobalActiveWindow() throws SecurityException {
0857 synchronized (KeyboardFocusManager.class) {
0858 if (this == getCurrentKeyboardFocusManager()) {
0859 return activeWindow;
0860 } else {
0861 if (focusLog.isLoggable(Level.FINE))
0862 focusLog.fine("This manager is " + this
0863 + ", current is "
0864 + getCurrentKeyboardFocusManager());
0865 throw new SecurityException(notPrivileged);
0866 }
0867 }
0868 }
0869
0870 /**
0871 * Sets the active Window. Only a Frame or a Dialog can be the active
0872 * Window. The native windowing system may denote the active Window or its
0873 * children with special decorations, such as a highlighted title bar. The
0874 * active Window is always either the focused Window, or the first Frame or
0875 * Dialog that is an owner of the focused Window.
0876 * <p>
0877 * This method does not actually change the active Window as far as the
0878 * native windowing system is concerned. It merely stores the value to be
0879 * subsequently returned by <code>getActiveWindow()</code>. Use
0880 * <code>Component.requestFocus()</code> or
0881 * <code>Component.requestFocusInWindow()</code>to change the active
0882 * Window, subject to platform limitations.
0883 *
0884 * @param activeWindow the active Window
0885 * @see #getActiveWindow
0886 * @see #getGlobalActiveWindow
0887 * @see Component#requestFocus()
0888 * @see Component#requestFocusInWindow()
0889 * @beaninfo
0890 * bound: true
0891 */
0892 protected void setGlobalActiveWindow(Window activeWindow) {
0893 Window oldActiveWindow;
0894 synchronized (KeyboardFocusManager.class) {
0895 oldActiveWindow = getActiveWindow();
0896 if (focusLog.isLoggable(Level.FINER)) {
0897 focusLog.finer("Setting global active window to "
0898 + activeWindow + ", old active "
0899 + oldActiveWindow);
0900 }
0901
0902 try {
0903 fireVetoableChange("activeWindow", oldActiveWindow,
0904 activeWindow);
0905 } catch (PropertyVetoException e) {
0906 // rejected
0907 return;
0908 }
0909
0910 KeyboardFocusManager.activeWindow = activeWindow;
0911 }
0912
0913 firePropertyChange("activeWindow", oldActiveWindow,
0914 activeWindow);
0915 }
0916
0917 /**
0918 * Returns the default FocusTraversalPolicy. Top-level components
0919 * use this value on their creation to initialize their own focus traversal
0920 * policy by explicit call to Container.setFocusTraversalPolicy.
0921 *
0922 * @return the default FocusTraversalPolicy. null will never be returned.
0923 * @see #setDefaultFocusTraversalPolicy
0924 * @see Container#setFocusTraversalPolicy
0925 * @see Container#getFocusTraversalPolicy
0926 */
0927 public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
0928 return defaultPolicy;
0929 }
0930
0931 /**
0932 * Sets the default FocusTraversalPolicy. Top-level components
0933 * use this value on their creation to initialize their own focus traversal
0934 * policy by explicit call to Container.setFocusTraversalPolicy.
0935 * Note: this call doesn't affect already created components as they have
0936 * their policy initialized. Only new components will use this policy as
0937 * their default policy.
0938 *
0939 * @param defaultPolicy the new, default FocusTraversalPolicy
0940 * @see #getDefaultFocusTraversalPolicy
0941 * @see Container#setFocusTraversalPolicy
0942 * @see Container#getFocusTraversalPolicy
0943 * @throws IllegalArgumentException if defaultPolicy is null
0944 * @beaninfo
0945 * bound: true
0946 */
0947 public void setDefaultFocusTraversalPolicy(
0948 FocusTraversalPolicy defaultPolicy) {
0949 if (defaultPolicy == null) {
0950 throw new IllegalArgumentException(
0951 "default focus traversal policy cannot be null");
0952 }
0953
0954 FocusTraversalPolicy oldPolicy;
0955
0956 synchronized (this ) {
0957 oldPolicy = this .defaultPolicy;
0958 this .defaultPolicy = defaultPolicy;
0959 }
0960
0961 firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
0962 defaultPolicy);
0963 }
0964
0965 /**
0966 * Sets the default focus traversal keys for a given traversal operation.
0967 * This traversal key <code>Set</code> will be in effect on all
0968 * <code>Window</code>s that have no such <code>Set</code> of
0969 * their own explicitly defined. This <code>Set</code> will also be
0970 * inherited, recursively, by any child <code>Component</code> of
0971 * those <code>Windows</code> that has
0972 * no such <code>Set</code> of its own explicitly defined.
0973 * <p>
0974 * The default values for the default focus traversal keys are
0975 * implementation-dependent. Sun recommends that all implementations for a
0976 * particular native platform use the same default values. The
0977 * recommendations for Windows and Unix are listed below. These
0978 * recommendations are used in the Sun AWT implementations.
0979 *
0980 * <table border=1 summary="Recommended default values for focus traversal keys">
0981 * <tr>
0982 * <th>Identifier</th>
0983 * <th>Meaning</th>
0984 * <th>Default</th>
0985 * </tr>
0986 * <tr>
0987 * <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
0988 * <td>Normal forward keyboard traversal</td>
0989 * <td><code>TAB</code> on <code>KEY_PRESSED</code>,
0990 * <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
0991 * </tr>
0992 * <tr>
0993 * <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
0994 * <td>Normal reverse keyboard traversal</td>
0995 * <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
0996 * <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
0997 * </tr>
0998 * <tr>
0999 * <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
1000 * <td>Go up one focus traversal cycle</td>
1001 * <td>none</td>
1002 * </tr>
1003 * <tr>
1004 * <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
1005 * <td>Go down one focus traversal cycle</td>
1006 * <td>none</td>
1007 * </tr>
1008 * </table>
1009 *
1010 * To disable a traversal key, use an empty <code>Set</code>;
1011 * <code>Collections.EMPTY_SET</code> is recommended.
1012 * <p>
1013 * Using the <code>AWTKeyStroke</code> API, client code can
1014 * specify on which of two
1015 * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
1016 * <code>KEY_RELEASED</code>, the focus traversal operation will
1017 * occur. Regardless of which <code>KeyEvent</code> is specified,
1018 * however, all <code>KeyEvent</code>s related to the focus
1019 * traversal key, including the associated <code>KEY_TYPED</code>
1020 * event, will be consumed, and will not be dispatched
1021 * to any <code>Component</code>. It is a runtime error to
1022 * specify a <code>KEY_TYPED</code> event as
1023 * mapping to a focus traversal operation, or to map the same event to
1024 * multiple default focus traversal operations.
1025 *
1026 * @param id one of
1027 * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1028 * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1029 * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1030 * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
1031 * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
1032 * specified operation
1033 * @see #getDefaultFocusTraversalKeys
1034 * @see Component#setFocusTraversalKeys
1035 * @see Component#getFocusTraversalKeys
1036 * @throws IllegalArgumentException if id is not one of
1037 * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
1038 * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
1039 * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
1040 * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
1041 * or if keystrokes is <code>null</code>,
1042 * or if keystrokes contains <code>null</code>,
1043 * or if any <code>Object</code> in
1044 * keystrokes is not an <code>AWTKeyStroke</code>,
1045 * or if any keystroke
1046 * represents a <code>KEY_TYPED</code> event,
1047 * or if any keystroke already maps
1048 * to another default focus traversal operation
1049 * @beaninfo
1050 * bound: true
1051 */
1052 public void setDefaultFocusTraversalKeys(int id,
1053 Set<? extends AWTKeyStroke> keystrokes) {
1054 if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1055 throw new IllegalArgumentException(
1056 "invalid focus traversal key identifier");
1057 }
1058 if (keystrokes == null) {
1059 throw new IllegalArgumentException(
1060 "cannot set null Set of default focus traversal keys");
1061 }
1062
1063 Set oldKeys;
1064
1065 synchronized (this ) {
1066 for (Iterator iter = keystrokes.iterator(); iter.hasNext();) {
1067 Object obj = iter.next();
1068
1069 if (obj == null) {
1070 throw new IllegalArgumentException(
1071 "cannot set null focus traversal key");
1072 }
1073
1074 // Fix for 6195831:
1075 //According to javadoc this method should throw IAE instead of ClassCastException
1076 if (!(obj instanceof AWTKeyStroke)) {
1077 throw new IllegalArgumentException(
1078 "object is expected to be AWTKeyStroke");
1079 }
1080 AWTKeyStroke keystroke = (AWTKeyStroke) obj;
1081
1082 if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
1083 throw new IllegalArgumentException(
1084 "focus traversal keys cannot map to KEY_TYPED events");
1085 }
1086
1087 // Check to see if key already maps to another traversal
1088 // operation
1089 for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
1090 if (i == id) {
1091 continue;
1092 }
1093
1094 if (defaultFocusTraversalKeys[i]
1095 .contains(keystroke)) {
1096 throw new IllegalArgumentException(
1097 "focus traversal keys must be unique for a Component");
1098 }
1099 }
1100 }
1101
1102 oldKeys = defaultFocusTraversalKeys[id];
1103 defaultFocusTraversalKeys[id] = Collections
1104 .unmodifiableSet(new HashSet(keystrokes));
1105 }
1106
1107 firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
1108 oldKeys, keystrokes);
1109 }
1110
1111 /**
1112 * Returns a Set of default focus traversal keys for a given traversal
1113 * operation. This traversal key Set will be in effect on all Windows that
1114 * have no such Set of their own explicitly defined. This Set will also be
1115 * inherited, recursively, by any child Component of those Windows that has
1116 * no such Set of its own explicitly defined. (See
1117 * <code>setDefaultFocusTraversalKeys</code> for a full description of each
1118 * operation.)
1119 *
1120 * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1121 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1122 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1123 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1124 * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
1125 * for the specified operation; the <code>Set</code>
1126 * will be unmodifiable, and may be empty; <code>null</code>
1127 * will never be returned
1128 * @see #setDefaultFocusTraversalKeys
1129 * @see Component#setFocusTraversalKeys
1130 * @see Component#getFocusTraversalKeys
1131 * @throws IllegalArgumentException if id is not one of
1132 * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
1133 * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
1134 * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
1135 * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
1136 */
1137 public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
1138 if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
1139 throw new IllegalArgumentException(
1140 "invalid focus traversal key identifier");
1141 }
1142
1143 // Okay to return Set directly because it is an unmodifiable view
1144 return defaultFocusTraversalKeys[id];
1145 }
1146
1147 /**
1148 * Returns the current focus cycle root, if the current focus cycle root is
1149 * in the same context as the calling thread. If the focus owner is itself
1150 * a focus cycle root, then it may be ambiguous as to which Components
1151 * represent the next and previous Components to focus during normal focus
1152 * traversal. In that case, the current focus cycle root is used to
1153 * differentiate among the possibilities.
1154 * <p>
1155 * This method is intended to be used only by KeyboardFocusManagers and
1156 * focus implementations. It is not for general client use.
1157 *
1158 * @return the current focus cycle root, or null if the current focus cycle
1159 * root is not a member of the calling thread's context
1160 * @see #getGlobalCurrentFocusCycleRoot
1161 * @see #setGlobalCurrentFocusCycleRoot
1162 */
1163 public Container getCurrentFocusCycleRoot() {
1164 synchronized (KeyboardFocusManager.class) {
1165 if (currentFocusCycleRoot == null) {
1166 return null;
1167 }
1168
1169 return (currentFocusCycleRoot.appContext == AppContext
1170 .getAppContext()) ? currentFocusCycleRoot : null;
1171 }
1172 }
1173
1174 /**
1175 * Returns the current focus cycle root, even if the calling thread is in a
1176 * different context than the current focus cycle root. If the focus owner
1177 * is itself a focus cycle root, then it may be ambiguous as to which
1178 * Components represent the next and previous Components to focus during
1179 * normal focus traversal. In that case, the current focus cycle root is
1180 * used to differentiate among the possibilities.
1181 * <p>
1182 * This method will throw a SecurityException if this KeyboardFocusManager
1183 * is not the current KeyboardFocusManager for the calling thread's
1184 * context.
1185 *
1186 * @return the current focus cycle root, or null if the current focus cycle
1187 * root is not a member of the calling thread's context
1188 * @see #getCurrentFocusCycleRoot
1189 * @see #setGlobalCurrentFocusCycleRoot
1190 * @throws SecurityException if this KeyboardFocusManager is not the
1191 * current KeyboardFocusManager for the calling thread's context
1192 */
1193 protected Container getGlobalCurrentFocusCycleRoot()
1194 throws SecurityException {
1195 synchronized (KeyboardFocusManager.class) {
1196 if (this == getCurrentKeyboardFocusManager()) {
1197 return currentFocusCycleRoot;
1198 } else {
1199 if (focusLog.isLoggable(Level.FINE))
1200 focusLog.fine("This manager is " + this
1201 + ", current is "
1202 + getCurrentKeyboardFocusManager());
1203 throw new SecurityException(notPrivileged);
1204 }
1205 }
1206 }
1207
1208 /**
1209 * Sets the current focus cycle root. If the focus owner is itself a focus
1210 * cycle root, then it may be ambiguous as to which Components represent
1211 * the next and previous Components to focus during normal focus traversal.
1212 * In that case, the current focus cycle root is used to differentiate
1213 * among the possibilities.
1214 * <p>
1215 * This method is intended to be used only by KeyboardFocusManagers and
1216 * focus implementations. It is not for general client use.
1217 *
1218 * @param newFocusCycleRoot the new focus cycle root
1219 * @see #getCurrentFocusCycleRoot
1220 * @see #getGlobalCurrentFocusCycleRoot
1221 * @beaninfo
1222 * bound: true
1223 */
1224 public void setGlobalCurrentFocusCycleRoot(
1225 Container newFocusCycleRoot) {
1226 Container oldFocusCycleRoot;
1227
1228 synchronized (KeyboardFocusManager.class) {
1229 oldFocusCycleRoot = getCurrentFocusCycleRoot();
1230 currentFocusCycleRoot = newFocusCycleRoot;
1231 }
1232
1233 firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
1234 newFocusCycleRoot);
1235 }
1236
1237 /**
1238 * Adds a PropertyChangeListener to the listener list. The listener is
1239 * registered for all bound properties of this class, including the
1240 * following:
1241 * <ul>
1242 * <li>whether the KeyboardFocusManager is currently managing focus
1243 * for this application or applet's browser context
1244 * ("managingFocus")</li>
1245 * <li>the focus owner ("focusOwner")</li>
1246 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1247 * <li>the focused Window ("focusedWindow")</li>
1248 * <li>the active Window ("activeWindow")</li>
1249 * <li>the default focus traversal policy
1250 * ("defaultFocusTraversalPolicy")</li>
1251 * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1252 * ("forwardDefaultFocusTraversalKeys")</li>
1253 * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1254 * ("backwardDefaultFocusTraversalKeys")</li>
1255 * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1256 * ("upCycleDefaultFocusTraversalKeys")</li>
1257 * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1258 * ("downCycleDefaultFocusTraversalKeys")</li>
1259 * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1260 * </ul>
1261 * If listener is null, no exception is thrown and no action is performed.
1262 *
1263 * @param listener the PropertyChangeListener to be added
1264 * @see #removePropertyChangeListener
1265 * @see #getPropertyChangeListeners
1266 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1267 */
1268 public void addPropertyChangeListener(
1269 PropertyChangeListener listener) {
1270 if (listener != null) {
1271 synchronized (this ) {
1272 if (changeSupport == null) {
1273 changeSupport = new PropertyChangeSupport(this );
1274 }
1275 changeSupport.addPropertyChangeListener(listener);
1276 }
1277 }
1278 }
1279
1280 /**
1281 * Removes a PropertyChangeListener from the listener list. This method
1282 * should be used to remove the PropertyChangeListeners that were
1283 * registered for all bound properties of this class.
1284 * <p>
1285 * If listener is null, no exception is thrown and no action is performed.
1286 *
1287 * @param listener the PropertyChangeListener to be removed
1288 * @see #addPropertyChangeListener
1289 * @see #getPropertyChangeListeners
1290 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1291 */
1292 public void removePropertyChangeListener(
1293 PropertyChangeListener listener) {
1294 if (listener != null) {
1295 synchronized (this ) {
1296 if (changeSupport != null) {
1297 changeSupport
1298 .removePropertyChangeListener(listener);
1299 }
1300 }
1301 }
1302 }
1303
1304 /**
1305 * Returns an array of all the property change listeners
1306 * registered on this keyboard focus manager.
1307 *
1308 * @return all of this keyboard focus manager's
1309 * <code>PropertyChangeListener</code>s
1310 * or an empty array if no property change
1311 * listeners are currently registered
1312 *
1313 * @see #addPropertyChangeListener
1314 * @see #removePropertyChangeListener
1315 * @see #getPropertyChangeListeners(java.lang.String)
1316 * @since 1.4
1317 */
1318 public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
1319 if (changeSupport == null) {
1320 changeSupport = new PropertyChangeSupport(this );
1321 }
1322 return changeSupport.getPropertyChangeListeners();
1323 }
1324
1325 /**
1326 * Adds a PropertyChangeListener to the listener list for a specific
1327 * property. The specified property may be user-defined, or one of the
1328 * following:
1329 * <ul>
1330 * <li>whether the KeyboardFocusManager is currently managing focus
1331 * for this application or applet's browser context
1332 * ("managingFocus")</li>
1333 * <li>the focus owner ("focusOwner")</li>
1334 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1335 * <li>the focused Window ("focusedWindow")</li>
1336 * <li>the active Window ("activeWindow")</li>
1337 * <li>the default focus traversal policy
1338 * ("defaultFocusTraversalPolicy")</li>
1339 * <li>the Set of default FORWARD_TRAVERSAL_KEYS
1340 * ("forwardDefaultFocusTraversalKeys")</li>
1341 * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
1342 * ("backwardDefaultFocusTraversalKeys")</li>
1343 * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
1344 * ("upCycleDefaultFocusTraversalKeys")</li>
1345 * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
1346 * ("downCycleDefaultFocusTraversalKeys")</li>
1347 * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
1348 * </ul>
1349 * If listener is null, no exception is thrown and no action is performed.
1350 *
1351 * @param propertyName one of the property names listed above
1352 * @param listener the PropertyChangeListener to be added
1353 * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
1354 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1355 * @see #getPropertyChangeListeners(java.lang.String)
1356 */
1357 public void addPropertyChangeListener(String propertyName,
1358 PropertyChangeListener listener) {
1359 if (listener != null) {
1360 synchronized (this ) {
1361 if (changeSupport == null) {
1362 changeSupport = new PropertyChangeSupport(this );
1363 }
1364 changeSupport.addPropertyChangeListener(propertyName,
1365 listener);
1366 }
1367 }
1368 }
1369
1370 /**
1371 * Removes a PropertyChangeListener from the listener list for a specific
1372 * property. This method should be used to remove PropertyChangeListeners
1373 * that were registered for a specific bound property.
1374 * <p>
1375 * If listener is null, no exception is thrown and no action is performed.
1376 *
1377 * @param propertyName a valid property name
1378 * @param listener the PropertyChangeListener to be removed
1379 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1380 * @see #getPropertyChangeListeners(java.lang.String)
1381 * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
1382 */
1383 public void removePropertyChangeListener(String propertyName,
1384 PropertyChangeListener listener) {
1385 if (listener != null) {
1386 synchronized (this ) {
1387 if (changeSupport != null) {
1388 changeSupport.removePropertyChangeListener(
1389 propertyName, listener);
1390 }
1391 }
1392 }
1393 }
1394
1395 /**
1396 * Returns an array of all the <code>PropertyChangeListener</code>s
1397 * associated with the named property.
1398 *
1399 * @return all of the <code>PropertyChangeListener</code>s associated with
1400 * the named property or an empty array if no such listeners have
1401 * been added.
1402 *
1403 * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1404 * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
1405 * @since 1.4
1406 */
1407 public synchronized PropertyChangeListener[] getPropertyChangeListeners(
1408 String propertyName) {
1409 if (changeSupport == null) {
1410 changeSupport = new PropertyChangeSupport(this );
1411 }
1412 return changeSupport.getPropertyChangeListeners(propertyName);
1413 }
1414
1415 /**
1416 * Fires a PropertyChangeEvent in response to a change in a bound property.
1417 * The event will be delivered to all registered PropertyChangeListeners.
1418 * No event will be delivered if oldValue and newValue are the same.
1419 *
1420 * @param propertyName the name of the property that has changed
1421 * @param oldValue the property's previous value
1422 * @param newValue the property's new value
1423 */
1424 protected void firePropertyChange(String propertyName,
1425 Object oldValue, Object newValue) {
1426 if (oldValue == newValue) {
1427 return;
1428 }
1429 PropertyChangeSupport changeSupport = this .changeSupport;
1430 if (changeSupport != null) {
1431 changeSupport.firePropertyChange(propertyName, oldValue,
1432 newValue);
1433 }
1434 }
1435
1436 /**
1437 * Adds a VetoableChangeListener to the listener list. The listener is
1438 * registered for all vetoable properties of this class, including the
1439 * following:
1440 * <ul>
1441 * <li>the focus owner ("focusOwner")</li>
1442 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1443 * <li>the focused Window ("focusedWindow")</li>
1444 * <li>the active Window ("activeWindow")</li>
1445 * </ul>
1446 * If listener is null, no exception is thrown and no action is performed.
1447 *
1448 * @param listener the VetoableChangeListener to be added
1449 * @see #removeVetoableChangeListener
1450 * @see #getVetoableChangeListeners
1451 * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1452 */
1453 public void addVetoableChangeListener(
1454 VetoableChangeListener listener) {
1455 if (listener != null) {
1456 synchronized (this ) {
1457 if (vetoableSupport == null) {
1458 vetoableSupport = new VetoableChangeSupport(this );
1459 }
1460 vetoableSupport.addVetoableChangeListener(listener);
1461 }
1462 }
1463 }
1464
1465 /**
1466 * Removes a VetoableChangeListener from the listener list. This method
1467 * should be used to remove the VetoableChangeListeners that were
1468 * registered for all vetoable properties of this class.
1469 * <p>
1470 * If listener is null, no exception is thrown and no action is performed.
1471 *
1472 * @param listener the VetoableChangeListener to be removed
1473 * @see #addVetoableChangeListener
1474 * @see #getVetoableChangeListeners
1475 * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1476 */
1477 public void removeVetoableChangeListener(
1478 VetoableChangeListener listener) {
1479 if (listener != null) {
1480 synchronized (this ) {
1481 if (vetoableSupport != null) {
1482 vetoableSupport
1483 .removeVetoableChangeListener(listener);
1484 }
1485 }
1486 }
1487 }
1488
1489 /**
1490 * Returns an array of all the vetoable change listeners
1491 * registered on this keyboard focus manager.
1492 *
1493 * @return all of this keyboard focus manager's
1494 * <code>VetoableChangeListener</code>s
1495 * or an empty array if no vetoable change
1496 * listeners are currently registered
1497 *
1498 * @see #addVetoableChangeListener
1499 * @see #removeVetoableChangeListener
1500 * @see #getVetoableChangeListeners(java.lang.String)
1501 * @since 1.4
1502 */
1503 public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
1504 if (vetoableSupport == null) {
1505 vetoableSupport = new VetoableChangeSupport(this );
1506 }
1507 return vetoableSupport.getVetoableChangeListeners();
1508 }
1509
1510 /**
1511 * Adds a VetoableChangeListener to the listener list for a specific
1512 * property. The specified property may be user-defined, or one of the
1513 * following:
1514 * <ul>
1515 * <li>the focus owner ("focusOwner")</li>
1516 * <li>the permanent focus owner ("permanentFocusOwner")</li>
1517 * <li>the focused Window ("focusedWindow")</li>
1518 * <li>the active Window ("activeWindow")</li>
1519 * </ul>
1520 * If listener is null, no exception is thrown and no action is performed.
1521 *
1522 * @param propertyName one of the property names listed above
1523 * @param listener the VetoableChangeListener to be added
1524 * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
1525 * @see #removeVetoableChangeListener
1526 * @see #getVetoableChangeListeners
1527 */
1528 public void addVetoableChangeListener(String propertyName,
1529 VetoableChangeListener listener) {
1530 if (listener != null) {
1531 synchronized (this ) {
1532 if (vetoableSupport == null) {
1533 vetoableSupport = new VetoableChangeSupport(this );
1534 }
1535 vetoableSupport.addVetoableChangeListener(propertyName,
1536 listener);
1537 }
1538 }
1539 }
1540
1541 /**
1542 * Removes a VetoableChangeListener from the listener list for a specific
1543 * property. This method should be used to remove VetoableChangeListeners
1544 * that were registered for a specific bound property.
1545 * <p>
1546 * If listener is null, no exception is thrown and no action is performed.
1547 *
1548 * @param propertyName a valid property name
1549 * @param listener the VetoableChangeListener to be removed
1550 * @see #addVetoableChangeListener
1551 * @see #getVetoableChangeListeners
1552 * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
1553 */
1554 public void removeVetoableChangeListener(String propertyName,
1555 VetoableChangeListener listener) {
1556 if (listener != null) {
1557 synchronized (this ) {
1558 if (vetoableSupport != null) {
1559 vetoableSupport.removeVetoableChangeListener(
1560 propertyName, listener);
1561 }
1562 }
1563 }
1564 }
1565
1566 /**
1567 * Returns an array of all the <code>VetoableChangeListener</code>s
1568 * associated with the named property.
1569 *
1570 * @return all of the <code>VetoableChangeListener</code>s associated with
1571 * the named property or an empty array if no such listeners have
1572 * been added.
1573 *
1574 * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1575 * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
1576 * @see #getVetoableChangeListeners
1577 * @since 1.4
1578 */
1579 public synchronized VetoableChangeListener[] getVetoableChangeListeners(
1580 String propertyName) {
1581 if (vetoableSupport == null) {
1582 vetoableSupport = new VetoableChangeSupport(this );
1583 }
1584 return vetoableSupport.getVetoableChangeListeners(propertyName);
1585 }
1586
1587 /**
1588 * Fires a PropertyChangeEvent in response to a change in a vetoable
1589 * property. The event will be delivered to all registered
1590 * VetoableChangeListeners. If a VetoableChangeListener throws a
1591 * PropertyVetoException, a new event is fired reverting all
1592 * VetoableChangeListeners to the old value and the exception is then
1593 * rethrown. No event will be delivered if oldValue and newValue are the
1594 * same.
1595 *
1596 * @param propertyName the name of the property that has changed
1597 * @param oldValue the property's previous value
1598 * @param newValue the property's new value
1599 * @throws java.beans.PropertyVetoException if a
1600 * <code>VetoableChangeListener</code> threw
1601 * <code>PropertyVetoException</code>
1602 */
1603 protected void fireVetoableChange(String propertyName,
1604 Object oldValue, Object newValue)
1605 throws PropertyVetoException {
1606 if (oldValue == newValue) {
1607 return;
1608 }
1609 VetoableChangeSupport vetoableSupport = this .vetoableSupport;
1610 if (vetoableSupport != null) {
1611 vetoableSupport.fireVetoableChange(propertyName, oldValue,
1612 newValue);
1613 }
1614 }
1615
1616 /**
1617 * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
1618 * chain. This KeyboardFocusManager will request that each
1619 * KeyEventDispatcher dispatch KeyEvents generated by the user before
1620 * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
1621 * notified in the order in which they were added. Notifications will halt
1622 * as soon as one KeyEventDispatcher returns <code>true</code> from its
1623 * <code>dispatchKeyEvent</code> method. There is no limit to the total
1624 * number of KeyEventDispatchers which can be added, nor to the number of
1625 * times which a particular KeyEventDispatcher instance can be added.
1626 * <p>
1627 * If a null dispatcher is specified, no action is taken and no exception
1628 * is thrown.
1629 * <p>
1630 * In a multithreaded application, {@link KeyEventDispatcher} behaves
1631 * the same as other AWT listeners. See
1632 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1633 * >AWT Threading Issues</a> for more details.
1634 *
1635 * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
1636 * @see #removeKeyEventDispatcher
1637 */
1638 public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1639 if (dispatcher != null) {
1640 synchronized (this ) {
1641 if (keyEventDispatchers == null) {
1642 keyEventDispatchers = new java.util.LinkedList();
1643 }
1644 keyEventDispatchers.add(dispatcher);
1645 }
1646 }
1647 }
1648
1649 /**
1650 * Removes a KeyEventDispatcher which was previously added to this
1651 * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
1652 * cannot itself be removed, unless it was explicitly re-registered via a
1653 * call to <code>addKeyEventDispatcher</code>.
1654 * <p>
1655 * If a null dispatcher is specified, if the specified dispatcher is not
1656 * in the dispatcher chain, or if this KeyboardFocusManager is specified
1657 * without having been explicitly re-registered, no action is taken and no
1658 * exception is thrown.
1659 * <p>
1660 * In a multithreaded application, {@link KeyEventDispatcher} behaves
1661 * the same as other AWT listeners. See
1662 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1663 * >AWT Threading Issues</a> for more details.
1664 *
1665 * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
1666 * chain
1667 * @see #addKeyEventDispatcher
1668 */
1669 public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
1670 if (dispatcher != null) {
1671 synchronized (this ) {
1672 if (keyEventDispatchers != null) {
1673 keyEventDispatchers.remove(dispatcher);
1674 }
1675 }
1676 }
1677 }
1678
1679 /**
1680 * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
1681 * The List will not include this KeyboardFocusManager unless it was
1682 * explicitly re-registered via a call to
1683 * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
1684 * registered, implementations are free to return null or a List of length
1685 * 0. Client code should not assume one behavior over another, nor should
1686 * it assume that the behavior, once established, will not change.
1687 *
1688 * @return a possibly null or empty List of KeyEventDispatchers
1689 * @see #addKeyEventDispatcher
1690 * @see #removeKeyEventDispatcher
1691 */
1692 protected synchronized java.util.List<KeyEventDispatcher> getKeyEventDispatchers() {
1693 return (keyEventDispatchers != null) ? (java.util.List) keyEventDispatchers
1694 .clone()
1695 : null;
1696 }
1697
1698 /**
1699 * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
1700 * processor chain. After a KeyEvent has been dispatched to and handled by
1701 * its target, KeyboardFocusManager will request that each
1702 * KeyEventPostProcessor perform any necessary post-processing as part
1703 * of the KeyEvent's final resolution. KeyEventPostProcessors
1704 * will be notified in the order in which they were added; the current
1705 * KeyboardFocusManager will be notified last. Notifications will halt
1706 * as soon as one KeyEventPostProcessor returns <code>true</code> from its
1707 * <code>postProcessKeyEvent</code> method. There is no limit to the the
1708 * total number of KeyEventPostProcessors that can be added, nor to the
1709 * number of times that a particular KeyEventPostProcessor instance can be
1710 * added.
1711 * <p>
1712 * If a null post-processor is specified, no action is taken and no
1713 * exception is thrown.
1714 * <p>
1715 * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1716 * the same as other AWT listeners. See
1717 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1718 * >AWT Threading Issues</a> for more details.
1719 *
1720 * @param processor the KeyEventPostProcessor to add to the post-processor
1721 * chain
1722 * @see #removeKeyEventPostProcessor
1723 */
1724 public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
1725 if (processor != null) {
1726 synchronized (this ) {
1727 if (keyEventPostProcessors == null) {
1728 keyEventPostProcessors = new java.util.LinkedList();
1729 }
1730 keyEventPostProcessors.add(processor);
1731 }
1732 }
1733 }
1734
1735 /**
1736 * Removes a previously added KeyEventPostProcessor from this
1737 * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
1738 * cannot itself be entirely removed from the chain. Only additional
1739 * references added via <code>addKeyEventPostProcessor</code> can be
1740 * removed.
1741 * <p>
1742 * If a null post-processor is specified, if the specified post-processor
1743 * is not in the post-processor chain, or if this KeyboardFocusManager is
1744 * specified without having been explicitly added, no action is taken and
1745 * no exception is thrown.
1746 * <p>
1747 * In a multithreaded application, {@link KeyEventPostProcessor} behaves
1748 * the same as other AWT listeners. See
1749 * <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
1750 * >AWT Threading Issues</a> for more details.
1751 *
1752 * @param processor the KeyEventPostProcessor to remove from the post-
1753 * processor chain
1754 * @see #addKeyEventPostProcessor
1755 */
1756 public void removeKeyEventPostProcessor(
1757 KeyEventPostProcessor processor) {
1758 if (processor != null) {
1759 synchronized (this ) {
1760 if (keyEventPostProcessors != null) {
1761 keyEventPostProcessors.remove(processor);
1762 }
1763 }
1764 }
1765 }
1766
1767 /**
1768 * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
1769 * List. The List will not include this KeyboardFocusManager unless it was
1770 * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
1771 * no KeyEventPostProcessors are registered, implementations are free to
1772 * return null or a List of length 0. Client code should not assume one
1773 * behavior over another, nor should it assume that the behavior, once
1774 * established, will not change.
1775 *
1776 * @return a possibly null or empty List of KeyEventPostProcessors
1777 * @see #addKeyEventPostProcessor
1778 * @see #removeKeyEventPostProcessor
1779 */
1780 protected java.util.List<KeyEventPostProcessor> getKeyEventPostProcessors() {
1781 return (keyEventPostProcessors != null) ? (java.util.List) keyEventPostProcessors
1782 .clone()
1783 : null;
1784 }
1785
1786 static void setMostRecentFocusOwner(Component component) {
1787 Component window = component;
1788 while (window != null && !(window instanceof Window)) {
1789 window = window.parent;
1790 }
1791 if (window != null) {
1792 setMostRecentFocusOwner((Window) window, component);
1793 }
1794 }
1795
1796 static synchronized void setMostRecentFocusOwner(Window window,
1797 Component component) {
1798 // ATTN: component has a strong reference to window via chain
1799 // of Component.parent fields. Since WeakHasMap refers to its
1800 // values strongly, we need to break the strong link from the
1801 // value (component) back to its key (window).
1802 WeakReference weakValue = null;
1803 if (component != null) {
1804 weakValue = new WeakReference(component);
1805 }
1806 mostRecentFocusOwners.put(window, weakValue);
1807 }
1808
1809 static void clearMostRecentFocusOwner(Component comp) {
1810 Container window;
1811
1812 if (comp == null) {
1813 return;
1814 }
1815
1816 synchronized (comp.getTreeLock()) {
1817 window = comp.getParent();
1818 while (window != null && !(window instanceof Window)) {
1819 window = window.getParent();
1820 }
1821 }
1822
1823 synchronized (KeyboardFocusManager.class) {
1824 if ((window != null)
1825 && (getMostRecentFocusOwner((Window) window) == comp)) {
1826 setMostRecentFocusOwner((Window) window, null);
1827 }
1828 // Also clear temporary lost component stored in Window
1829 if (window != null) {
1830 Window realWindow = (Window) window;
1831 if (realWindow.getTemporaryLostComponent() == comp) {
1832 realWindow.setTemporaryLostComponent(null);
1833 }
1834 }
1835 }
1836 }
1837
1838 /*
1839 * Please be careful changing this method! It is called from
1840 * javax.swing.JComponent.runInputVerifier() using reflection.
1841 */
1842 static synchronized Component getMostRecentFocusOwner(Window window) {
1843 WeakReference weakValue = (WeakReference) mostRecentFocusOwners
1844 .get(window);
1845 return weakValue == null ? null : (Component) weakValue.get();
1846 }
1847
1848 /**
1849 * This method is called by the AWT event dispatcher requesting that the
1850 * current KeyboardFocusManager dispatch the specified event on its behalf.
1851 * It is expected that all KeyboardFocusManagers will dispatch all
1852 * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
1853 * These events should be dispatched based on the KeyboardFocusManager's
1854 * notion of the focus owner and the focused and active Windows, sometimes
1855 * overriding the source of the specified AWTEvent. Dispatching must be
1856 * done using <code>redispatchEvent</code> to prevent the AWT event
1857 * dispatcher from recursively requesting that the KeyboardFocusManager
1858 * dispatch the event again. If this method returns <code>false</code>,
1859 * then the AWT event dispatcher will attempt to dispatch the event itself.
1860 *
1861 * @param e the AWTEvent to be dispatched
1862 * @return <code>true</code> if this method dispatched the event;
1863 * <code>false</code> otherwise
1864 * @see #redispatchEvent
1865 * @see #dispatchKeyEvent
1866 */
1867 public abstract boolean dispatchEvent(AWTEvent e);
1868
1869 /**
1870 * Redispatches an AWTEvent in such a way that the AWT event dispatcher
1871 * will not recursively request that the KeyboardFocusManager, or any
1872 * installed KeyEventDispatchers, dispatch the event again. Client
1873 * implementations of <code>dispatchEvent</code> and client-defined
1874 * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
1875 * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
1876 * <p>
1877 * This method is intended to be used only by KeyboardFocusManagers and
1878 * KeyEventDispatchers. It is not for general client use.
1879 *
1880 * @param target the Component to which the event should be dispatched
1881 * @param e the event to dispatch
1882 * @see #dispatchEvent
1883 * @see KeyEventDispatcher
1884 */
1885 public final void redispatchEvent(Component target, AWTEvent e) {
1886 e.focusManagerIsDispatching = true;
1887 target.dispatchEvent(e);
1888 e.focusManagerIsDispatching = false;
1889 }
1890
1891 /**
1892 * Typically this method will be called by <code>dispatchEvent</code> if no
1893 * other KeyEventDispatcher in the dispatcher chain dispatched the
1894 * KeyEvent, or if no other KeyEventDispatchers are registered. If an
1895 * implementation of this method returns <code>false</code>,
1896 * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
1897 * may simply return <code>false</code>. If <code>true</code> is returned,
1898 * <code>dispatchEvent</code> should return <code>true</code> as well.
1899 *
1900 * @param e the KeyEvent which the current KeyboardFocusManager has
1901 * requested that this KeyEventDispatcher dispatch
1902 * @return <code>true</code> if the KeyEvent was dispatched;
1903 * <code>false</code> otherwise
1904 * @see #dispatchEvent
1905 */
1906 public abstract boolean dispatchKeyEvent(KeyEvent e);
1907
1908 /**
1909 * This method will be called by <code>dispatchKeyEvent</code>.
1910 * By default, this method will handle any unconsumed KeyEvents that
1911 * map to an AWT <code>MenuShortcut</code> by consuming the event
1912 * and activating the shortcut.
1913 *
1914 * @param e the KeyEvent to post-process
1915 * @return <code>true</code> to indicate that no other
1916 * KeyEventPostProcessor will be notified of the KeyEvent.
1917 * @see #dispatchKeyEvent
1918 * @see MenuShortcut
1919 */
1920 public abstract boolean postProcessKeyEvent(KeyEvent e);
1921
1922 /**
1923 * This method initiates a focus traversal operation if and only if the
1924 * KeyEvent represents a focus traversal key for the specified
1925 * focusedComponent. It is expected that focusedComponent is the current
1926 * focus owner, although this need not be the case. If it is not,
1927 * focus traversal will nevertheless proceed as if focusedComponent
1928 * were the current focus owner.
1929 *
1930 * @param focusedComponent the Component that will be the basis for a focus
1931 * traversal operation if the specified event represents a focus
1932 * traversal key for the Component
1933 * @param e the event that may represent a focus traversal key
1934 */
1935 public abstract void processKeyEvent(Component focusedComponent,
1936 KeyEvent e);
1937
1938 /**
1939 * Called by the AWT to notify the KeyboardFocusManager that it should
1940 * delay dispatching of KeyEvents until the specified Component becomes
1941 * the focus owner. If client code requests a focus change, and the AWT
1942 * determines that this request might be granted by the native windowing
1943 * system, then the AWT will call this method. It is the responsibility of
1944 * the KeyboardFocusManager to delay dispatching of KeyEvents with
1945 * timestamps later than the specified time stamp until the specified
1946 * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
1947 * request by invoking <code>dequeueKeyEvents</code> or
1948 * <code>discardKeyEvents</code>.
1949 *
1950 * @param after timestamp of current event, or the current, system time if
1951 * the current event has no timestamp, or the AWT cannot determine
1952 * which event is currently being handled
1953 * @param untilFocused Component which should receive a FOCUS_GAINED event
1954 * before any pending KeyEvents
1955 * @see #dequeueKeyEvents
1956 * @see #discardKeyEvents
1957 */
1958 protected abstract void enqueueKeyEvents(long after,
1959 Component untilFocused);
1960
1961 /**
1962 * Called by the AWT to notify the KeyboardFocusManager that it should
1963 * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1964 * enqueued because of a call to <code>enqueueKeyEvents</code> with the
1965 * same timestamp and Component should be released for normal dispatching
1966 * to the current focus owner. If the given timestamp is less than zero,
1967 * the outstanding enqueue request for the given Component with the <b>
1968 * oldest</b> timestamp (if any) should be cancelled.
1969 *
1970 * @param after the timestamp specified in the call to
1971 * <code>enqueueKeyEvents</code>, or any value < 0
1972 * @param untilFocused the Component specified in the call to
1973 * <code>enqueueKeyEvents</code>
1974 * @see #enqueueKeyEvents
1975 * @see #discardKeyEvents
1976 */
1977 protected abstract void dequeueKeyEvents(long after,
1978 Component untilFocused);
1979
1980 /**
1981 * Called by the AWT to notify the KeyboardFocusManager that it should
1982 * cancel delayed dispatching of KeyEvents. All KeyEvents which were
1983 * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
1984 * with the same Component should be discarded.
1985 *
1986 * @param comp the Component specified in one or more calls to
1987 * <code>enqueueKeyEvents</code>
1988 * @see #enqueueKeyEvents
1989 * @see #dequeueKeyEvents
1990 */
1991 protected abstract void discardKeyEvents(Component comp);
1992
1993 /**
1994 * Focuses the Component after aComponent, typically based on a
1995 * FocusTraversalPolicy.
1996 *
1997 * @param aComponent the Component that is the basis for the focus
1998 * traversal operation
1999 * @see FocusTraversalPolicy
2000 */
2001 public abstract void focusNextComponent(Component aComponent);
2002
2003 /**
2004 * Focuses the Component before aComponent, typically based on a
2005 * FocusTraversalPolicy.
2006 *
2007 * @param aComponent the Component that is the basis for the focus
2008 * traversal operation
2009 * @see FocusTraversalPolicy
2010 */
2011 public abstract void focusPreviousComponent(Component aComponent);
2012
2013 /**
2014 * Moves the focus up one focus traversal cycle. Typically, the focus owner
2015 * is set to aComponent's focus cycle root, and the current focus cycle
2016 * root is set to the new focus owner's focus cycle root. If, however,
2017 * aComponent's focus cycle root is a Window, then typically the focus
2018 * owner is set to the Window's default Component to focus, and the current
2019 * focus cycle root is unchanged.
2020 *
2021 * @param aComponent the Component that is the basis for the focus
2022 * traversal operation
2023 */
2024 public abstract void upFocusCycle(Component aComponent);
2025
2026 /**
2027 * Moves the focus down one focus traversal cycle. Typically, if
2028 * aContainer is a focus cycle root, then the focus owner is set to
2029 * aContainer's default Component to focus, and the current focus cycle
2030 * root is set to aContainer. If aContainer is not a focus cycle root, then
2031 * no focus traversal operation occurs.
2032 *
2033 * @param aContainer the Container that is the basis for the focus
2034 * traversal operation
2035 */
2036 public abstract void downFocusCycle(Container aContainer);
2037
2038 /**
2039 * Focuses the Component after the current focus owner.
2040 */
2041 public final void focusNextComponent() {
2042 Component focusOwner = getFocusOwner();
2043 if (focusOwner != null) {
2044 focusNextComponent(focusOwner);
2045 }
2046 }
2047
2048 /**
2049 * Focuses the Component before the current focus owner.
2050 */
2051 public final void focusPreviousComponent() {
2052 Component focusOwner = getFocusOwner();
2053 if (focusOwner != null) {
2054 focusPreviousComponent(focusOwner);
2055 }
2056 }
2057
2058 /**
2059 * Moves the focus up one focus traversal cycle from the current focus
2060 * owner. Typically, the new focus owner is set to the current focus
2061 * owner's focus cycle root, and the current focus cycle root is set to the
2062 * new focus owner's focus cycle root. If, however, the current focus
2063 * owner's focus cycle root is a Window, then typically the focus owner is
2064 * set to the focus cycle root's default Component to focus, and the
2065 * current focus cycle root is unchanged.
2066 */
2067 public final void upFocusCycle() {
2068 Component focusOwner = getFocusOwner();
2069 if (focusOwner != null) {
2070 upFocusCycle(focusOwner);
2071 }
2072 }
2073
2074 /**
2075 * Moves the focus down one focus traversal cycle from the current focus
2076 * owner, if and only if the current focus owner is a Container that is a
2077 * focus cycle root. Typically, the focus owner is set to the current focus
2078 * owner's default Component to focus, and the current focus cycle root is
2079 * set to the current focus owner. If the current focus owner is not a
2080 * Container that is a focus cycle root, then no focus traversal operation
2081 * occurs.
2082 */
2083 public final void downFocusCycle() {
2084 Component focusOwner = getFocusOwner();
2085 if (focusOwner instanceof Container) {
2086 downFocusCycle((Container) focusOwner);
2087 }
2088 }
2089
2090 /**
2091 * Dumps the list of focus requests to stderr
2092 */
2093 void dumpRequests() {
2094 System.err.println(">>> Requests dump, time: "
2095 + System.currentTimeMillis());
2096 synchronized (heavyweightRequests) {
2097 for (HeavyweightFocusRequest req : heavyweightRequests) {
2098 System.err.println(">>> Req: " + req);
2099 }
2100 }
2101 System.err.println("");
2102 }
2103
2104 private static final class LightweightFocusRequest {
2105 final Component component;
2106 final boolean temporary;
2107 final CausedFocusEvent.Cause cause;
2108
2109 LightweightFocusRequest(Component component, boolean temporary,
2110 CausedFocusEvent.Cause cause) {
2111 this .component = component;
2112 this .temporary = temporary;
2113 this .cause = cause;
2114 }
2115
2116 public String toString() {
2117 return "LightweightFocusRequest[component=" + component
2118 + ",temporary=" + temporary + ", cause=" + cause
2119 + "]";
2120 }
2121 }
2122
2123 private static final class HeavyweightFocusRequest {
2124 final Component heavyweight;
2125 final LinkedList<LightweightFocusRequest> lightweightRequests;
2126
2127 static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER = new HeavyweightFocusRequest();
2128
2129 private HeavyweightFocusRequest() {
2130 heavyweight = null;
2131 lightweightRequests = null;
2132 }
2133
2134 HeavyweightFocusRequest(Component heavyweight,
2135 Component descendant, boolean temporary,
2136 CausedFocusEvent.Cause cause) {
2137 if (dbg.on) {
2138 dbg.assertion(heavyweight != null);
2139 }
2140
2141 this .heavyweight = heavyweight;
2142 this .lightweightRequests = new LinkedList<LightweightFocusRequest>();
2143 addLightweightRequest(descendant, temporary, cause);
2144 }
2145
2146 boolean addLightweightRequest(Component descendant,
2147 boolean temporary, CausedFocusEvent.Cause cause) {
2148 if (dbg.on) {
2149 dbg
2150 .assertion(this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
2151 dbg.assertion(descendant != null);
2152 }
2153
2154 Component lastDescendant = ((lightweightRequests.size() > 0) ? lightweightRequests
2155 .getLast().component
2156 : null);
2157
2158 if (descendant != lastDescendant) {
2159 // Not a duplicate request
2160 lightweightRequests.add(new LightweightFocusRequest(
2161 descendant, temporary, cause));
2162 return true;
2163 } else {
2164 return false;
2165 }
2166 }
2167
2168 LightweightFocusRequest getFirstLightweightRequest() {
2169 if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
2170 return null;
2171 }
2172 return lightweightRequests.getFirst();
2173 }
2174
2175 public String toString() {
2176 boolean first = true;
2177 String str = "HeavyweightFocusRequest[heavweight="
2178 + heavyweight + ",lightweightRequests=";
2179 if (lightweightRequests == null) {
2180 str += null;
2181 } else {
2182 str += "[";
2183
2184 for (LightweightFocusRequest lwRequest : lightweightRequests) {
2185 if (first) {
2186 first = false;
2187 } else {
2188 str += ",";
2189 }
2190 str += lwRequest;
2191 }
2192 str += "]";
2193 }
2194 str += "]";
2195 return str;
2196 }
2197 }
2198
2199 /*
2200 * heavyweightRequests is used as a monitor for synchronized changes of
2201 * currentLightweightRequests, clearingCurrentLightweightRequests and
2202 * newFocusOwner.
2203 */
2204 private static LinkedList<HeavyweightFocusRequest> heavyweightRequests = new LinkedList<HeavyweightFocusRequest>();
2205 private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
2206 private static boolean clearingCurrentLightweightRequests;
2207 private static boolean allowSyncFocusRequests = true;
2208 private static Component newFocusOwner = null;
2209 private static volatile boolean disableRestoreFocus;
2210
2211 static final int SNFH_FAILURE = 0;
2212 static final int SNFH_SUCCESS_HANDLED = 1;
2213 static final int SNFH_SUCCESS_PROCEED = 2;
2214
2215 static boolean processSynchronousLightweightTransfer(
2216 Component heavyweight, Component descendant,
2217 boolean temporary, boolean focusedWindowChangeAllowed,
2218 long time) {
2219 Window parentWindow = Component
2220 .getContainingWindow(heavyweight);
2221 if (parentWindow == null || !parentWindow.syncLWRequests) {
2222 return false;
2223 }
2224 if (descendant == null) {
2225 // Focus transfers from a lightweight child back to the
2226 // heavyweight Container should be treated like lightweight
2227 // focus transfers.
2228 descendant = heavyweight;
2229 }
2230
2231 KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit
2232 .targetToAppContext(descendant));
2233
2234 FocusEvent currentFocusOwnerEvent = null;
2235 FocusEvent newFocusOwnerEvent = null;
2236 Component currentFocusOwner = manager.getGlobalFocusOwner();
2237
2238 synchronized (heavyweightRequests) {
2239 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2240 if (hwFocusRequest == null
2241 && heavyweight == manager.getNativeFocusOwner()
2242 && allowSyncFocusRequests) {
2243
2244 if (descendant == currentFocusOwner) {
2245 // Redundant request.
2246 return true;
2247 }
2248
2249 // 'heavyweight' owns the native focus and there are no pending
2250 // requests. 'heavyweight' must be a Container and
2251 // 'descendant' must not be the focus owner. Otherwise,
2252 // we would never have gotten this far.
2253 manager.enqueueKeyEvents(time, descendant);
2254
2255 hwFocusRequest = new HeavyweightFocusRequest(
2256 heavyweight, descendant, temporary,
2257 CausedFocusEvent.Cause.UNKNOWN);
2258 heavyweightRequests.add(hwFocusRequest);
2259
2260 if (currentFocusOwner != null) {
2261 currentFocusOwnerEvent = new FocusEvent(
2262 currentFocusOwner, FocusEvent.FOCUS_LOST,
2263 temporary, descendant);
2264 }
2265 newFocusOwnerEvent = new FocusEvent(descendant,
2266 FocusEvent.FOCUS_GAINED, temporary,
2267 currentFocusOwner);
2268 }
2269 }
2270 boolean result = false;
2271 final boolean clearing = clearingCurrentLightweightRequests;
2272
2273 Throwable caughtEx = null;
2274 try {
2275 clearingCurrentLightweightRequests = false;
2276 synchronized (Component.LOCK) {
2277
2278 if (currentFocusOwnerEvent != null
2279 && currentFocusOwner != null) {
2280 ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2281 caughtEx = dispatchAndCatchException(caughtEx,
2282 currentFocusOwner, currentFocusOwnerEvent);
2283 result = true;
2284 }
2285
2286 if (newFocusOwnerEvent != null && descendant != null) {
2287 ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2288 caughtEx = dispatchAndCatchException(caughtEx,
2289 descendant, newFocusOwnerEvent);
2290 result = true;
2291 }
2292 }
2293 } finally {
2294 clearingCurrentLightweightRequests = clearing;
2295 }
2296 if (caughtEx instanceof RuntimeException) {
2297 throw (RuntimeException) caughtEx;
2298 } else if (caughtEx instanceof Error) {
2299 throw (Error) caughtEx;
2300 }
2301 return result;
2302 }
2303
2304 /**
2305 * Indicates whether the native implementation should proceed with a
2306 * pending, native focus request. Before changing the focus at the native
2307 * level, the AWT implementation should always call this function for
2308 * permission. This function will reject the request if a duplicate request
2309 * preceded it, or if the specified heavyweight Component already owns the
2310 * focus and no native focus changes are pending. Otherwise, the request
2311 * will be approved and the focus request list will be updated so that,
2312 * if necessary, the proper descendant will be focused when the
2313 * corresponding FOCUS_GAINED event on the heavyweight is received.
2314 *
2315 * An implementation must ensure that calls to this method and native
2316 * focus changes are atomic. If this is not guaranteed, then the ordering
2317 * of the focus request list may be incorrect, leading to errors in the
2318 * type-ahead mechanism. Typically this is accomplished by only calling
2319 * this function from the native event pumping thread, or by holding a
2320 * global, native lock during invocation.
2321 */
2322 static int shouldNativelyFocusHeavyweight(Component heavyweight,
2323 Component descendant, boolean temporary,
2324 boolean focusedWindowChangeAllowed, long time,
2325 CausedFocusEvent.Cause cause) {
2326 if (dbg.on) {
2327 dbg.assertion(heavyweight != null);
2328 dbg.assertion(time != 0);
2329 }
2330
2331 if (descendant == null) {
2332 // Focus transfers from a lightweight child back to the
2333 // heavyweight Container should be treated like lightweight
2334 // focus transfers.
2335 descendant = heavyweight;
2336 }
2337
2338 KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit
2339 .targetToAppContext(descendant));
2340 KeyboardFocusManager this Manager = getCurrentKeyboardFocusManager();
2341 Component currentFocusOwner = this Manager.getGlobalFocusOwner();
2342 Component nativeFocusOwner = this Manager.getNativeFocusOwner();
2343 Window nativeFocusedWindow = this Manager
2344 .getNativeFocusedWindow();
2345 if (focusLog.isLoggable(Level.FINER)) {
2346 focusLog.log(Level.FINER, "SNFH for {0} in {1}",
2347 new Object[] { descendant, heavyweight });
2348 }
2349 if (focusLog.isLoggable(Level.FINEST)) {
2350 focusLog.log(Level.FINEST, "0. Current focus owner {0}",
2351 currentFocusOwner);
2352 focusLog.log(Level.FINEST, "0. Native focus owner {0}",
2353 nativeFocusOwner);
2354 focusLog.log(Level.FINEST, "0. Native focused window {0}",
2355 nativeFocusedWindow);
2356 }
2357 synchronized (heavyweightRequests) {
2358 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2359 if (focusLog.isLoggable(Level.FINEST)) {
2360 focusLog.log(Level.FINEST, "Request {0}",
2361 hwFocusRequest);
2362 }
2363 if (hwFocusRequest == null
2364 && heavyweight == nativeFocusOwner) {
2365 if (descendant == currentFocusOwner) {
2366 // Redundant request.
2367 if (focusLog.isLoggable(Level.FINEST))
2368 focusLog.log(Level.FINEST,
2369 "1. SNFH_FAILURE for {0}", descendant);
2370 return SNFH_FAILURE;
2371 }
2372
2373 // 'heavyweight' owns the native focus and there are no pending
2374 // requests. 'heavyweight' must be a Container and
2375 // 'descendant' must not be the focus owner. Otherwise,
2376 // we would never have gotten this far.
2377 manager.enqueueKeyEvents(time, descendant);
2378
2379 hwFocusRequest = new HeavyweightFocusRequest(
2380 heavyweight, descendant, temporary, cause);
2381 heavyweightRequests.add(hwFocusRequest);
2382
2383 if (currentFocusOwner != null) {
2384 FocusEvent currentFocusOwnerEvent = new CausedFocusEvent(
2385 currentFocusOwner, FocusEvent.FOCUS_LOST,
2386 temporary, descendant, cause);
2387 // Fix 5028014. Rolled out.
2388 // SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
2389 SunToolkit.postEvent(currentFocusOwner.appContext,
2390 currentFocusOwnerEvent);
2391 }
2392 FocusEvent newFocusOwnerEvent = new CausedFocusEvent(
2393 descendant, FocusEvent.FOCUS_GAINED, temporary,
2394 currentFocusOwner, cause);
2395 // Fix 5028014. Rolled out.
2396 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
2397 SunToolkit.postEvent(descendant.appContext,
2398 newFocusOwnerEvent);
2399
2400 if (focusLog.isLoggable(Level.FINEST))
2401 focusLog.log(Level.FINEST,
2402 "2. SNFH_HANDLED for {0}", descendant);
2403 return SNFH_SUCCESS_HANDLED;
2404 } else if (hwFocusRequest != null
2405 && hwFocusRequest.heavyweight == heavyweight) {
2406 // 'heavyweight' doesn't have the native focus right now, but
2407 // if all pending requests were completed, it would. Add
2408 // descendant to the heavyweight's list of pending
2409 // lightweight focus transfers.
2410 if (hwFocusRequest.addLightweightRequest(descendant,
2411 temporary, cause)) {
2412 manager.enqueueKeyEvents(time, descendant);
2413 }
2414
2415 if (focusLog.isLoggable(Level.FINEST))
2416 focusLog.finest("3. SNFH_HANDLED for lightweight"
2417 + descendant + " in " + heavyweight);
2418 return SNFH_SUCCESS_HANDLED;
2419 } else {
2420 if (!focusedWindowChangeAllowed) {
2421 // For purposes of computing oldFocusedWindow, we should look at
2422 // the second to last HeavyweightFocusRequest on the queue iff the
2423 // last HeavyweightFocusRequest is CLEAR_GLOBAL_FOCUS_OWNER. If
2424 // there is no second to last HeavyweightFocusRequest, null is an
2425 // acceptable value.
2426 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2427 int size = heavyweightRequests.size();
2428 hwFocusRequest = (HeavyweightFocusRequest) ((size >= 2) ? heavyweightRequests
2429 .get(size - 2)
2430 : null);
2431 }
2432 if (focusedWindowChanged(
2433 heavyweight,
2434 (hwFocusRequest != null) ? hwFocusRequest.heavyweight
2435 : nativeFocusedWindow)) {
2436 if (focusLog.isLoggable(Level.FINEST))
2437 focusLog.finest("4. SNFH_FAILURE for "
2438 + descendant);
2439 return SNFH_FAILURE;
2440 }
2441 }
2442
2443 manager.enqueueKeyEvents(time, descendant);
2444 heavyweightRequests.add(new HeavyweightFocusRequest(
2445 heavyweight, descendant, temporary, cause));
2446 if (focusLog.isLoggable(Level.FINEST))
2447 focusLog
2448 .finest("5. SNFH_PROCEED for " + descendant);
2449 return SNFH_SUCCESS_PROCEED;
2450 }
2451 }
2452 }
2453
2454 static void heavyweightButtonDown(Component heavyweight, long time) {
2455 heavyweightButtonDown(heavyweight, time, false);
2456 }
2457
2458 static void heavyweightButtonDown(Component heavyweight, long time,
2459 boolean acceptDuplicates) {
2460 if (dbg.on) {
2461 dbg.assertion(heavyweight != null);
2462 dbg.assertion(time != 0);
2463 }
2464 KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit
2465 .targetToAppContext(heavyweight));
2466
2467 synchronized (heavyweightRequests) {
2468 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2469 Component currentNativeFocusOwner = (hwFocusRequest == null) ? manager
2470 .getNativeFocusOwner()
2471 : hwFocusRequest.heavyweight;
2472
2473 // Behavior for all use cases:
2474 // 1. Heavyweight leaf Components (e.g., Button, Checkbox, Choice,
2475 // List, TextComponent, Canvas) that respond to button down.
2476 //
2477 // Native platform will generate a FOCUS_GAINED if and only if
2478 // the Component is not the focus owner (or, will not be the
2479 // focus owner when all outstanding focus requests are
2480 // processed).
2481 //
2482 // 2. Panel with no descendants.
2483 //
2484 // Same as (1).
2485 //
2486 // 3. Panel with at least one heavyweight descendant.
2487 //
2488 // This function should NOT be called for this case!
2489 //
2490 // 4. Panel with only lightweight descendants.
2491 //
2492 // Native platform will generate a FOCUS_GAINED if and only if
2493 // neither the Panel, nor any of its recursive, lightweight
2494 // descendants, is the focus owner. However, we want a
2495 // requestFocus() for any lightweight descendant to win out over
2496 // the focus request for the Panel. To accomplish this, we
2497 // differ from the algorithm for shouldNativelyFocusHeavyweight
2498 // as follows:
2499 // a. If the requestFocus() for a lightweight descendant has
2500 // been fully handled by the time this function is invoked,
2501 // then 'hwFocusRequest' will be null and 'heavyweight'
2502 // will be the native focus owner. Do *not* synthesize a
2503 // focus transfer to the Panel.
2504 // b. If the requestFocus() for a lightweight descendant has
2505 // been recorded, but not handled, then 'hwFocusRequest'
2506 // will be non-null and 'hwFocusRequest.heavyweight' will
2507 // equal 'heavyweight'. Do *not* append 'heavyweight' to
2508 // hwFocusRequest.lightweightRequests.
2509 // c. If the requestFocus() for a lightweight descendant is
2510 // yet to be made, then post a new HeavyweightFocusRequest.
2511 // If no lightweight descendant ever requests focus, then
2512 // the Panel will get focus. If some descendant does, then
2513 // the descendant will get focus by either a synthetic
2514 // focus transfer, or a lightweightRequests focus transfer.
2515
2516 if (acceptDuplicates
2517 || heavyweight != currentNativeFocusOwner) {
2518 getCurrentKeyboardFocusManager(
2519 SunToolkit.targetToAppContext(heavyweight))
2520 .enqueueKeyEvents(time, heavyweight);
2521 heavyweightRequests.add(new HeavyweightFocusRequest(
2522 heavyweight, heavyweight, false,
2523 CausedFocusEvent.Cause.MOUSE_EVENT));
2524 }
2525 }
2526 }
2527
2528 /**
2529 * Returns the Window which will be active after processing this request,
2530 * or null if this is a duplicate request. The active Window is useful
2531 * because some native platforms do not support setting the native focus
2532 * owner to null. On these platforms, the obvious choice is to set the
2533 * focus owner to the focus proxy of the active Window.
2534 */
2535 static Window markClearGlobalFocusOwner() {
2536 // need to call this out of synchronized block to avoid possible deadlock
2537 // see 6454631.
2538 final Component nativeFocusedWindow = getCurrentKeyboardFocusManager()
2539 .getNativeFocusedWindow();
2540
2541 synchronized (heavyweightRequests) {
2542 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
2543 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2544 // duplicate request
2545 return null;
2546 }
2547
2548 heavyweightRequests
2549 .add(HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
2550
2551 Component activeWindow = ((hwFocusRequest != null) ? Component
2552 .getContainingWindow(hwFocusRequest.heavyweight)
2553 : nativeFocusedWindow);
2554 while (activeWindow != null
2555 && !((activeWindow instanceof Frame) || (activeWindow instanceof Dialog))) {
2556 activeWindow = activeWindow.getParent_NoClientCode();
2557 }
2558
2559 return (Window) activeWindow;
2560 }
2561 }
2562
2563 Component getCurrentWaitingRequest(Component parent) {
2564 synchronized (heavyweightRequests) {
2565 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2566 if (hwFocusRequest != null) {
2567 if (hwFocusRequest.heavyweight == parent) {
2568 LightweightFocusRequest lwFocusRequest = hwFocusRequest.lightweightRequests
2569 .getFirst();
2570 if (lwFocusRequest != null) {
2571 return lwFocusRequest.component;
2572 }
2573 }
2574 }
2575 }
2576 return null;
2577 }
2578
2579 static boolean isAutoFocusTransferEnabled() {
2580 synchronized (heavyweightRequests) {
2581 return (heavyweightRequests.size() == 0)
2582 && !disableRestoreFocus
2583 && (null == currentLightweightRequests);
2584 }
2585 }
2586
2587 /*
2588 * Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
2589 * @param ex previously caught exception that may be processed right here, or null
2590 * @param comp the component to dispatch the event to
2591 * @param event the event to dispatch to the component
2592 */
2593 static private Throwable dispatchAndCatchException(Throwable ex,
2594 Component comp, FocusEvent event) {
2595 Throwable retEx = null;
2596 try {
2597 comp.dispatchEvent(event);
2598 } catch (RuntimeException re) {
2599 retEx = re;
2600 } catch (Error er) {
2601 retEx = er;
2602 }
2603 if (retEx != null) {
2604 if (ex != null) {
2605 handleException(ex);
2606 }
2607 return retEx;
2608 }
2609 return ex;
2610 }
2611
2612 static private void handleException(Throwable ex) {
2613 ex.printStackTrace();
2614 }
2615
2616 static void processCurrentLightweightRequests() {
2617 KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2618 LinkedList<LightweightFocusRequest> localLightweightRequests = null;
2619
2620 Component globalFocusOwner = manager.getGlobalFocusOwner();
2621 if ((globalFocusOwner != null)
2622 && (globalFocusOwner.appContext != AppContext
2623 .getAppContext())) {
2624 // The current app context differs from the app context of a focus
2625 // owner (and all pending lightweight requests), so we do nothing
2626 // now and wait for a next event.
2627 return;
2628 }
2629
2630 synchronized (heavyweightRequests) {
2631 if (currentLightweightRequests != null) {
2632 clearingCurrentLightweightRequests = true;
2633 disableRestoreFocus = true;
2634 localLightweightRequests = currentLightweightRequests;
2635 allowSyncFocusRequests = (localLightweightRequests
2636 .size() < 2);
2637 currentLightweightRequests = null;
2638 } else {
2639 // do nothing
2640 return;
2641 }
2642 }
2643
2644 Throwable caughtEx = null;
2645 try {
2646 if (localLightweightRequests != null) {
2647 Component lastFocusOwner = null;
2648 Component currentFocusOwner = null;
2649
2650 for (Iterator iter = localLightweightRequests
2651 .iterator(); iter.hasNext();) {
2652
2653 currentFocusOwner = manager.getGlobalFocusOwner();
2654 LightweightFocusRequest lwFocusRequest = (LightweightFocusRequest) iter
2655 .next();
2656
2657 /*
2658 * WARNING: This is based on DKFM's logic solely!
2659 *
2660 * We allow to trigger restoreFocus() in the dispatching process
2661 * only if we have the last request to dispatch. If the last request
2662 * fails, focus will be restored to either the component of the last
2663 * previously succedded request, or to to the focus owner that was
2664 * before this clearing proccess.
2665 */
2666 if (!iter.hasNext()) {
2667 disableRestoreFocus = false;
2668 }
2669
2670 FocusEvent currentFocusOwnerEvent = null;
2671 /*
2672 * We're not dispatching FOCUS_LOST while the current focus owner is null.
2673 * But regardless of whether it's null or not, we're clearing ALL the local
2674 * lw requests.
2675 */
2676 if (currentFocusOwner != null) {
2677 currentFocusOwnerEvent = new CausedFocusEvent(
2678 currentFocusOwner,
2679 FocusEvent.FOCUS_LOST,
2680 lwFocusRequest.temporary,
2681 lwFocusRequest.component,
2682 lwFocusRequest.cause);
2683 }
2684 FocusEvent newFocusOwnerEvent = new CausedFocusEvent(
2685 lwFocusRequest.component,
2686 FocusEvent.FOCUS_GAINED,
2687 lwFocusRequest.temporary,
2688 currentFocusOwner == null ? lastFocusOwner
2689 : currentFocusOwner,
2690 lwFocusRequest.cause);
2691
2692 if (currentFocusOwner != null) {
2693 ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
2694 caughtEx = dispatchAndCatchException(caughtEx,
2695 currentFocusOwner,
2696 currentFocusOwnerEvent);
2697 }
2698
2699 ((AWTEvent) newFocusOwnerEvent).isPosted = true;
2700 caughtEx = dispatchAndCatchException(caughtEx,
2701 lwFocusRequest.component,
2702 newFocusOwnerEvent);
2703
2704 if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
2705 lastFocusOwner = lwFocusRequest.component;
2706 }
2707 }
2708 }
2709 } finally {
2710 clearingCurrentLightweightRequests = false;
2711 disableRestoreFocus = false;
2712 localLightweightRequests = null;
2713 allowSyncFocusRequests = true;
2714 }
2715 if (caughtEx instanceof RuntimeException) {
2716 throw (RuntimeException) caughtEx;
2717 } else if (caughtEx instanceof Error) {
2718 throw (Error) caughtEx;
2719 }
2720 }
2721
2722 static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
2723 synchronized (heavyweightRequests) {
2724 // Any other case represents a failure condition which we did
2725 // not expect. We need to clearFocusRequestList() and patch up
2726 // the event as best as possible.
2727
2728 if (removeFirstRequest()) {
2729 return (FocusEvent) retargetFocusEvent(fe);
2730 }
2731
2732 Component source = fe.getComponent();
2733 Component opposite = fe.getOppositeComponent();
2734 boolean temporary = false;
2735 if (fe.getID() == FocusEvent.FOCUS_LOST
2736 && (opposite == null || isTemporary(opposite,
2737 source))) {
2738 temporary = true;
2739 }
2740 return new CausedFocusEvent(source, fe.getID(), temporary,
2741 opposite, CausedFocusEvent.Cause.NATIVE_SYSTEM);
2742 }
2743 }
2744
2745 static FocusEvent retargetFocusGained(FocusEvent fe) {
2746 assert (fe.getID() == FocusEvent.FOCUS_GAINED);
2747
2748 Component currentFocusOwner = getCurrentKeyboardFocusManager()
2749 .getGlobalFocusOwner();
2750 Component source = fe.getComponent();
2751 Component opposite = fe.getOppositeComponent();
2752 Component nativeSource = getHeavyweight(source);
2753
2754 synchronized (heavyweightRequests) {
2755 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2756
2757 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2758 return retargetUnexpectedFocusEvent(fe);
2759 }
2760
2761 if (source != null && nativeSource == null
2762 && hwFocusRequest != null) {
2763 // if source w/o peer and
2764 // if source is equal to first lightweight
2765 // then we should correct source and nativeSource
2766 if (source == hwFocusRequest
2767 .getFirstLightweightRequest().component) {
2768 source = hwFocusRequest.heavyweight;
2769 nativeSource = source; // source is heavuweight itself
2770 }
2771 }
2772 if (hwFocusRequest != null
2773 && nativeSource == hwFocusRequest.heavyweight) {
2774 // Focus change as a result of a known call to requestFocus(),
2775 // or known click on a peer focusable heavyweight Component.
2776
2777 heavyweightRequests.removeFirst();
2778
2779 LightweightFocusRequest lwFocusRequest = hwFocusRequest.lightweightRequests
2780 .removeFirst();
2781
2782 Component newSource = lwFocusRequest.component;
2783 if (currentFocusOwner != null) {
2784 /*
2785 * Since we receive FOCUS_GAINED when current focus
2786 * owner is not null, correcponding FOCUS_LOST is supposed
2787 * to be lost. And so, we keep new focus owner
2788 * to determine synthetic FOCUS_LOST event which will be
2789 * generated by KeyboardFocusManager for this FOCUS_GAINED.
2790 *
2791 * This code based on knowledge of
2792 * DefaultKeyboardFocusManager's implementation and might
2793 * be not applicable for another KeyboardFocusManager.
2794 */
2795 newFocusOwner = newSource;
2796 }
2797
2798 boolean temporary = (opposite == null || isTemporary(
2799 newSource, opposite)) ? false
2800 : lwFocusRequest.temporary;
2801
2802 if (hwFocusRequest.lightweightRequests.size() > 0) {
2803 currentLightweightRequests = hwFocusRequest.lightweightRequests;
2804 EventQueue.invokeLater(new Runnable() {
2805 public void run() {
2806 processCurrentLightweightRequests();
2807 }
2808 });
2809 }
2810
2811 // 'opposite' will be fixed by
2812 // DefaultKeyboardFocusManager.realOppositeComponent
2813 return new CausedFocusEvent(newSource,
2814 FocusEvent.FOCUS_GAINED, temporary, opposite,
2815 lwFocusRequest.cause);
2816 }
2817
2818 if (currentFocusOwner != null
2819 && currentFocusOwner.getContainingWindow() == source
2820 && (hwFocusRequest == null || source != hwFocusRequest.heavyweight)) {
2821 // Special case for FOCUS_GAINED in top-levels
2822 // If it arrives as the result of activation we should skip it
2823 // This event will not have appropriate request record and
2824 // on arrival there will be already some focus owner set.
2825 return new CausedFocusEvent(currentFocusOwner,
2826 FocusEvent.FOCUS_GAINED, false, null,
2827 CausedFocusEvent.Cause.ACTIVATION);
2828 }
2829
2830 return retargetUnexpectedFocusEvent(fe);
2831 } // end synchronized(heavyweightRequests)
2832 }
2833
2834 static FocusEvent retargetFocusLost(FocusEvent fe) {
2835 assert (fe.getID() == FocusEvent.FOCUS_LOST);
2836
2837 Component currentFocusOwner = getCurrentKeyboardFocusManager()
2838 .getGlobalFocusOwner();
2839 Component opposite = fe.getOppositeComponent();
2840 Component nativeOpposite = getHeavyweight(opposite);
2841
2842 synchronized (heavyweightRequests) {
2843 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2844
2845 if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
2846 if (currentFocusOwner != null) {
2847 // Call to KeyboardFocusManager.clearGlobalFocusOwner()
2848 heavyweightRequests.removeFirst();
2849 return new CausedFocusEvent(
2850 currentFocusOwner,
2851 FocusEvent.FOCUS_LOST,
2852 false,
2853 null,
2854 CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
2855 }
2856
2857 // Otherwise, fall through to failure case below
2858
2859 } else if (opposite == null) {
2860 // Focus leaving application
2861 if (currentFocusOwner != null) {
2862 return new CausedFocusEvent(currentFocusOwner,
2863 FocusEvent.FOCUS_LOST, true, null,
2864 CausedFocusEvent.Cause.ACTIVATION);
2865 } else {
2866 return fe;
2867 }
2868 } else if (hwFocusRequest != null
2869 && (nativeOpposite == hwFocusRequest.heavyweight || nativeOpposite == null
2870 && opposite == hwFocusRequest
2871 .getFirstLightweightRequest().component)) {
2872 if (currentFocusOwner == null) {
2873 return fe;
2874 }
2875 // Focus change as a result of a known call to requestFocus(),
2876 // or click on a peer focusable heavyweight Component.
2877 // If a focus transfer is made across top-levels, then the
2878 // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
2879 // event is always permanent. Otherwise, the stored temporary
2880 // value is honored.
2881
2882 LightweightFocusRequest lwFocusRequest = hwFocusRequest.lightweightRequests
2883 .getFirst();
2884
2885 boolean temporary = isTemporary(opposite,
2886 currentFocusOwner) ? true
2887 : lwFocusRequest.temporary;
2888
2889 return new CausedFocusEvent(currentFocusOwner,
2890 FocusEvent.FOCUS_LOST, temporary,
2891 lwFocusRequest.component, lwFocusRequest.cause);
2892 } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
2893 // If top-level changed there might be no focus request in a list
2894 // But we know the opposite, we now it is temporary - dispatch the event.
2895 if (!fe.isTemporary() && currentFocusOwner != null) {
2896 // Create copy of the event with only difference in temporary parameter.
2897 fe = new CausedFocusEvent(currentFocusOwner,
2898 FocusEvent.FOCUS_LOST, true, opposite,
2899 CausedFocusEvent.Cause.ACTIVATION);
2900 }
2901 return fe;
2902 }
2903
2904 return retargetUnexpectedFocusEvent(fe);
2905 } // end synchronized(heavyweightRequests)
2906 }
2907
2908 static AWTEvent retargetFocusEvent(AWTEvent event) {
2909 if (clearingCurrentLightweightRequests) {
2910 return event;
2911 }
2912
2913 KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
2914 if (focusLog.isLoggable(Level.FINE)) {
2915 if (event instanceof FocusEvent
2916 || event instanceof WindowEvent) {
2917 focusLog.log(Level.FINE, ">>> {0}",
2918 new Object[] { event });
2919 }
2920 if (focusLog.isLoggable(Level.FINER)
2921 && event instanceof KeyEvent) {
2922 focusLog.log(Level.FINER, " focus owner is {0}",
2923 new Object[] { manager.getGlobalFocusOwner() });
2924 focusLog.log(Level.FINER, ">>> {0}",
2925 new Object[] { event });
2926 }
2927 }
2928
2929 synchronized (heavyweightRequests) {
2930 /*
2931 * This code handles FOCUS_LOST event which is generated by
2932 * DefaultKeyboardFocusManager for FOCUS_GAINED.
2933 *
2934 * This code based on knowledge of DefaultKeyboardFocusManager's
2935 * implementation and might be not applicable for another
2936 * KeyboardFocusManager.
2937 *
2938 * Fix for 4472032
2939 */
2940 if (newFocusOwner != null
2941 && event.getID() == FocusEvent.FOCUS_LOST) {
2942 FocusEvent fe = (FocusEvent) event;
2943
2944 if (manager.getGlobalFocusOwner() == fe.getComponent()
2945 && fe.getOppositeComponent() == newFocusOwner) {
2946 newFocusOwner = null;
2947 return event;
2948 }
2949 }
2950 }
2951
2952 processCurrentLightweightRequests();
2953
2954 switch (event.getID()) {
2955 case FocusEvent.FOCUS_GAINED: {
2956 event = retargetFocusGained((FocusEvent) event);
2957 break;
2958 }
2959 case FocusEvent.FOCUS_LOST: {
2960 event = retargetFocusLost((FocusEvent) event);
2961 break;
2962 }
2963 default:
2964 /* do nothing */
2965 }
2966 return event;
2967 }
2968
2969 /**
2970 * Clears markers queue
2971 * This method is not intended to be overridden by KFM's.
2972 * Only DefaultKeyboardFocusManager can implement it.
2973 * @since 1.5
2974 */
2975 void clearMarkers() {
2976 }
2977
2978 static boolean removeFirstRequest() {
2979 KeyboardFocusManager manager = KeyboardFocusManager
2980 .getCurrentKeyboardFocusManager();
2981
2982 synchronized (heavyweightRequests) {
2983 HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
2984
2985 if (hwFocusRequest != null) {
2986 heavyweightRequests.removeFirst();
2987 if (hwFocusRequest.lightweightRequests != null) {
2988 for (Iterator lwIter = hwFocusRequest.lightweightRequests
2989 .iterator(); lwIter.hasNext();) {
2990 manager.dequeueKeyEvents(-1,
2991 ((LightweightFocusRequest) lwIter
2992 .next()).component);
2993 }
2994 }
2995 }
2996 // Fix for 4799136 - clear type-ahead markers if requests queue is empty
2997 // We do it here because this method is called only when problems happen
2998 if (heavyweightRequests.size() == 0) {
2999 manager.clearMarkers();
3000 }
3001 return (heavyweightRequests.size() > 0);
3002 }
3003 }
3004
3005 static void removeLastFocusRequest(Component heavyweight) {
3006 if (dbg.on) {
3007 dbg.assertion(heavyweight != null);
3008 }
3009
3010 KeyboardFocusManager manager = KeyboardFocusManager
3011 .getCurrentKeyboardFocusManager();
3012 synchronized (heavyweightRequests) {
3013 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
3014 if (hwFocusRequest != null
3015 && hwFocusRequest.heavyweight == heavyweight) {
3016 heavyweightRequests.removeLast();
3017 }
3018 // Fix for 4799136 - clear type-ahead markers if requests queue is empty
3019 // We do it here because this method is called only when problems happen
3020 if (heavyweightRequests.size() == 0) {
3021 manager.clearMarkers();
3022 }
3023 }
3024 }
3025
3026 private static boolean focusedWindowChanged(Component to,
3027 Component from) {
3028 Window wto = Component.getContainingWindow(to);
3029 Window wfrom = Component.getContainingWindow(from);
3030 if (wto == null && wfrom == null) {
3031 return true;
3032 }
3033 if (wto == null) {
3034 return true;
3035 }
3036 if (wfrom == null) {
3037 return true;
3038 }
3039 return (wto != wfrom);
3040 }
3041
3042 private static boolean isTemporary(Component to, Component from) {
3043 Window wto = Component.getContainingWindow(to);
3044 Window wfrom = Component.getContainingWindow(from);
3045 if (wto == null && wfrom == null) {
3046 return false;
3047 }
3048 if (wto == null) {
3049 return true;
3050 }
3051 if (wfrom == null) {
3052 return false;
3053 }
3054 return (wto != wfrom);
3055 }
3056
3057 static Component getHeavyweight(Component comp) {
3058 if (comp == null || comp.getPeer() == null) {
3059 return null;
3060 } else if (comp.getPeer() instanceof LightweightPeer) {
3061 return comp.getNativeContainer();
3062 } else {
3063 return comp;
3064 }
3065 }
3066
3067 static Field proxyActive;
3068
3069 // Accessor to private field isProxyActive of KeyEvent
3070 private static boolean isProxyActiveImpl(KeyEvent e) {
3071 if (proxyActive == null) {
3072 proxyActive = (Field) AccessController
3073 .doPrivileged(new PrivilegedAction() {
3074 public Object run() {
3075 Field field = null;
3076 try {
3077 field = KeyEvent.class
3078 .getDeclaredField("isProxyActive");
3079 if (field != null) {
3080 field.setAccessible(true);
3081 }
3082 } catch (NoSuchFieldException nsf) {
3083 assert (false);
3084 }
3085 return field;
3086 }
3087 });
3088 }
3089
3090 try {
3091 return proxyActive.getBoolean(e);
3092 } catch (IllegalAccessException iae) {
3093 assert (false);
3094 }
3095 return false;
3096 }
3097
3098 // Returns the value of this KeyEvent's field isProxyActive
3099 static boolean isProxyActive(KeyEvent e) {
3100 if (!GraphicsEnvironment.isHeadless()) {
3101 return isProxyActiveImpl(e);
3102 } else {
3103 return false;
3104 }
3105 }
3106
3107 private static HeavyweightFocusRequest getLastHWRequest() {
3108 synchronized (heavyweightRequests) {
3109 return (heavyweightRequests.size() > 0) ? heavyweightRequests
3110 .getLast()
3111 : null;
3112 }
3113 }
3114
3115 private static HeavyweightFocusRequest getFirstHWRequest() {
3116 synchronized (heavyweightRequests) {
3117 return (heavyweightRequests.size() > 0) ? heavyweightRequests
3118 .getFirst()
3119 : null;
3120 }
3121 }
3122 }
|