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: }
|