- /*
- * @(#)KeyboardFocusManager.java 1.58 04/05/05
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package java.awt;
-
- import java.awt.event.FocusEvent;
- import java.awt.event.InputEvent;
- import java.awt.event.KeyEvent;
- import java.awt.event.WindowEvent;
-
- import java.awt.peer.LightweightPeer;
- import java.awt.peer.WindowPeer;
- import java.beans.*;
- import java.util.Set;
- import java.util.HashSet;
- import java.util.Collections;
- import java.util.Iterator;
- import java.util.LinkedList;
- import java.util.ListIterator;
- import java.util.StringTokenizer;
- import java.util.WeakHashMap;
- import java.lang.ref.WeakReference;
- import sun.awt.AppContext;
- import sun.awt.DebugHelper;
- import sun.awt.SunToolkit;
- import sun.awt.HeadlessToolkit;
- import java.util.logging.*;
- import java.awt.peer.KeyboardFocusManagerPeer;
- import java.lang.reflect.*;
- import java.security.AccessController;
- import java.security.PrivilegedAction;
-
- /**
- * The KeyboardFocusManager is responsible for managing the active and focused
- * Windows, and the current focus owner. The focus owner is defined as the
- * Component in an application that will typically receive all KeyEvents
- * generated by the user. The focused Window is the Window that is, or
- * contains, the focus owner. Only a Frame or a Dialog can be the active
- * Window. The native windowing system may denote the active Window or its
- * children with special decorations, such as a highlighted title bar. The
- * active Window is always either the focused Window, or the first Frame or
- * Dialog that is an owner of the focused Window.
- * <p>
- * The KeyboardFocusManager is both a centralized location for client code to
- * query for the focus owner and initiate focus changes, and an event
- * dispatcher for all FocusEvents, WindowEvents related to focus, and
- * KeyEvents.
- * <p>
- * Some browsers partition applets in different code bases into separate
- * contexts, and establish walls between these contexts. In such a scenario,
- * there will be one KeyboardFocusManager per context. Other browsers place all
- * applets into the same context, implying that there will be only a single,
- * global KeyboardFocusManager for all applets. This behavior is
- * implementation-dependent. Consult your browser's documentation for more
- * information. No matter how many contexts there may be, however, there can
- * never be more than one focus owner, focused Window, or active Window, per
- * ClassLoader.
- * <p>
- * Please see
- * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/focus.html">
- * How to Use the Focus Subsystem</a>,
- * a section in <em>The Java Tutorial</em>, and the
- * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
- * for more information.
- *
- * @author David Mendenhall
- * @version 1.58, 05/05/04
- *
- * @see Window
- * @see Frame
- * @see Dialog
- * @see java.awt.event.FocusEvent
- * @see java.awt.event.WindowEvent
- * @see java.awt.event.KeyEvent
- * @since 1.4
- */
- public abstract class KeyboardFocusManager
- implements KeyEventDispatcher, KeyEventPostProcessor
- {
-
- // Shared focus engine logger
- private static final Logger focusLog = Logger.getLogger("java.awt.focus.KeyboardFocusManager");
-
- static {
- /* ensure that the necessary native libraries are loaded */
- Toolkit.loadLibraries();
- if (!GraphicsEnvironment.isHeadless()) {
- initIDs();
- }
- }
-
- transient KeyboardFocusManagerPeer peer;
-
- /**
- * Initialize JNI field and method IDs
- */
- private static native void initIDs();
-
- private static final DebugHelper dbg =
- DebugHelper.create(KeyboardFocusManager.class);
-
- /**
- * The identifier for the Forward focus traversal keys.
- *
- * @see #setDefaultFocusTraversalKeys
- * @see #getDefaultFocusTraversalKeys
- * @see Component#setFocusTraversalKeys
- * @see Component#getFocusTraversalKeys
- */
- public static final int FORWARD_TRAVERSAL_KEYS = 0;
-
- /**
- * The identifier for the Backward focus traversal keys.
- *
- * @see #setDefaultFocusTraversalKeys
- * @see #getDefaultFocusTraversalKeys
- * @see Component#setFocusTraversalKeys
- * @see Component#getFocusTraversalKeys
- */
- public static final int BACKWARD_TRAVERSAL_KEYS = 1;
-
- /**
- * The identifier for the Up Cycle focus traversal keys.
- *
- * @see #setDefaultFocusTraversalKeys
- * @see #getDefaultFocusTraversalKeys
- * @see Component#setFocusTraversalKeys
- * @see Component#getFocusTraversalKeys
- */
- public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
-
- /**
- * The identifier for the Down Cycle focus traversal keys.
- *
- * @see #setDefaultFocusTraversalKeys
- * @see #getDefaultFocusTraversalKeys
- * @see Component#setFocusTraversalKeys
- * @see Component#getFocusTraversalKeys
- */
- public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
-
- static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
-
- /**
- * Returns the current KeyboardFocusManager instance for the calling
- * thread's context.
- *
- * @return this thread's context's KeyboardFocusManager
- * @see #setCurrentKeyboardFocusManager
- */
- public static KeyboardFocusManager getCurrentKeyboardFocusManager() {
- return getCurrentKeyboardFocusManager(AppContext.getAppContext());
- }
-
- synchronized static KeyboardFocusManager
- getCurrentKeyboardFocusManager(AppContext appcontext)
- {
- KeyboardFocusManager manager = (KeyboardFocusManager)
- appcontext.get(KeyboardFocusManager.class);
- if (manager == null) {
- manager = new DefaultKeyboardFocusManager();
- appcontext.put(KeyboardFocusManager.class, manager);
- }
- return manager;
- }
-
- /**
- * Sets the current KeyboardFocusManager instance for the calling thread's
- * context. If null is specified, then the current KeyboardFocusManager
- * is replaced with a new instance of DefaultKeyboardFocusManager.
- * <p>
- * If a SecurityManager is installed, the calling thread must be granted
- * the AWTPermission "replaceKeyboardFocusManager" in order to replace the
- * the current KeyboardFocusManager. If this permission is not granted,
- * this method will throw a SecurityException, and the current
- * KeyboardFocusManager will be unchanged.
- *
- * @param newManager the new KeyboardFocusManager for this thread's context
- * @see #getCurrentKeyboardFocusManager
- * @see DefaultKeyboardFocusManager
- * @throws SecurityException if the calling thread does not have permission
- * to replace the current KeyboardFocusManager
- */
- public static void setCurrentKeyboardFocusManager(
- KeyboardFocusManager newManager) throws SecurityException
- {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- if (replaceKeyboardFocusManagerPermission == null) {
- replaceKeyboardFocusManagerPermission =
- new AWTPermission("replaceKeyboardFocusManager");
- }
- security.
- checkPermission(replaceKeyboardFocusManagerPermission);
- }
-
- KeyboardFocusManager oldManager = null;
-
- synchronized (KeyboardFocusManager.class) {
- AppContext appcontext = AppContext.getAppContext();
-
- if (newManager != null) {
- oldManager = getCurrentKeyboardFocusManager(appcontext);
-
- appcontext.put(KeyboardFocusManager.class, newManager);
- } else {
- oldManager = getCurrentKeyboardFocusManager(appcontext);
- appcontext.remove(KeyboardFocusManager.class);
- }
- }
-
- if (oldManager != null) {
- oldManager.firePropertyChange("managingFocus",
- Boolean.TRUE,
- Boolean.FALSE);
- }
- if (newManager != null) {
- newManager.firePropertyChange("managingFocus",
- Boolean.FALSE,
- Boolean.TRUE);
- }
- }
-
- /**
- * The Component in an application that will typically receive all
- * KeyEvents generated by the user.
- */
- private static Component focusOwner;
-
- /**
- * The Component in an application that will regain focus when an
- * outstanding temporary focus transfer has completed, or the focus owner,
- * if no outstanding temporary transfer exists.
- */
- private static Component permanentFocusOwner;
-
- /**
- * The Window which is, or contains, the focus owner.
- */
- private static Window focusedWindow;
-
- /**
- * Only a Frame or a Dialog can be the active Window. The native windowing
- * system may denote the active Window with a special decoration, such as a
- * highlighted title bar. The active Window is always either the focused
- * Window, or the first Frame or Dialog which is an owner of the focused
- * Window.
- */
- private static Window activeWindow;
-
- /**
- * The default FocusTraversalPolicy for all Windows that have no policy of
- * their own set. If those Windows have focus-cycle-root children that have
- * no keyboard-traversal policy of their own, then those children will also
- * inherit this policy (as will, recursively, their focus-cycle-root
- * children).
- */
- private FocusTraversalPolicy defaultPolicy =
- new DefaultFocusTraversalPolicy();
-
- /**
- * The bound property names of each focus traversal key.
- */
- private static final String[] defaultFocusTraversalKeyPropertyNames = {
- "forwardDefaultFocusTraversalKeys",
- "backwardDefaultFocusTraversalKeys",
- "upCycleDefaultFocusTraversalKeys",
- "downCycleDefaultFocusTraversalKeys"
- };
-
- /**
- * The default strokes for initializing the default focus traversal keys.
- */
- private static final AWTKeyStroke[][] defaultFocusTraversalKeyStrokes = {
- {
- AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, 0, false),
- AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK, false),
- },
- {
- AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK, false),
- AWTKeyStroke.getAWTKeyStroke(KeyEvent.VK_TAB,
- InputEvent.SHIFT_DOWN_MASK | InputEvent.SHIFT_MASK | InputEvent.CTRL_DOWN_MASK | InputEvent.CTRL_MASK,
- false),
- },
- {},
- {},
- };
- /**
- * The default focus traversal keys. Each array of traversal keys will be
- * in effect on all Windows that have no such array of their own explicitly
- * set. Each array will also be inherited, recursively, by any child
- * Component of those Windows that has no such array of its own explicitly
- * set.
- */
- private Set[] defaultFocusTraversalKeys = new Set[4];
-
- /**
- * The current focus cycle root. If the focus owner is itself a focus cycle
- * root, then it may be ambiguous as to which Components represent the next
- * and previous Components to focus during normal focus traversal. In that
- * case, the current focus cycle root is used to differentiate among the
- * possibilities.
- */
- private static Container currentFocusCycleRoot;
-
- /**
- * A description of any VetoableChangeListeners which have been registered.
- */
- private VetoableChangeSupport vetoableSupport;
-
- /**
- * A description of any PropertyChangeListeners which have been registered.
- */
- private PropertyChangeSupport changeSupport;
-
- /**
- * This KeyboardFocusManager's KeyEventDispatcher chain. The List does not
- * include this KeyboardFocusManager unless it was explicitly re-registered
- * via a call to <code>addKeyEventDispatcher</code>. If no other
- * KeyEventDispatchers are registered, this field may be null or refer to
- * a List of length 0.
- */
- private java.util.LinkedList keyEventDispatchers;
-
- /**
- * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
- * not include this KeyboardFocusManager unless it was explicitly
- * re-registered via a call to <code>addKeyEventPostProcessor</code>.
- * If no other KeyEventPostProcessors are registered, this field may be
- * null or refer to a List of length 0.
- */
- private java.util.LinkedList keyEventPostProcessors;
-
- /**
- * Maps Windows to those Windows' most recent focus owners.
- */
- private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
-
- /**
- * Error String for initializing SecurityExceptions.
- */
- private static final String notPrivileged = "this KeyboardFocusManager is not installed in the current thread's context";
-
- /**
- * We cache the permission used to verify that the calling thread is
- * permitted to access the global focus state.
- */
- private static AWTPermission replaceKeyboardFocusManagerPermission;
-
- /*
- * SequencedEvent which is currently dispatched in AppContext.
- */
- transient SequencedEvent currentSequencedEvent = null;
-
- final void setCurrentSequencedEvent(SequencedEvent current) {
- synchronized (SequencedEvent.class) {
- assert(current == null || currentSequencedEvent == null);
- currentSequencedEvent = current;
- }
- }
-
- final SequencedEvent getCurrentSequencedEvent() {
- synchronized (SequencedEvent.class) {
- return currentSequencedEvent;
- }
- }
-
- static Set initFocusTraversalKeysSet(String value, Set targetSet) {
- StringTokenizer tokens = new StringTokenizer(value, ",");
- while (tokens.hasMoreTokens()) {
- targetSet.add(AWTKeyStroke.getAWTKeyStroke(tokens.nextToken()));
- }
- return (targetSet.isEmpty())
- ? Collections.EMPTY_SET
- : Collections.unmodifiableSet(targetSet);
- }
-
- /**
- * Initializes a KeyboardFocusManager.
- */
- public KeyboardFocusManager() {
- for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
- Set work_set = new HashSet();
- for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
- work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
- }
- defaultFocusTraversalKeys[i] = (work_set.isEmpty())
- ? Collections.EMPTY_SET
- : Collections.unmodifiableSet(work_set);
- }
- initPeer();
- }
-
- private void initPeer() {
- if (Toolkit.getDefaultToolkit() instanceof HeadlessToolkit){
- peer = ((HeadlessToolkit)Toolkit.getDefaultToolkit()).createKeyboardFocusManagerPeer(this);
- }
- if (Toolkit.getDefaultToolkit() instanceof SunToolkit){
- peer = ((SunToolkit)Toolkit.getDefaultToolkit()).createKeyboardFocusManagerPeer(this);
- }
- }
-
- /**
- * Returns the focus owner, if the focus owner is in the same context as
- * the calling thread. The focus owner is defined as the Component in an
- * application that will typically receive all KeyEvents generated by the
- * user. KeyEvents which map to the focus owner's focus traversal keys will
- * not be delivered if focus traversal keys are enabled for the focus
- * owner. In addition, KeyEventDispatchers may retarget or consume
- * KeyEvents before they reach the focus owner.
- *
- * @return the focus owner, or null if the focus owner is not a member of
- * the calling thread's context
- * @see #getGlobalFocusOwner
- * @see #setGlobalFocusOwner
- */
- public Component getFocusOwner() {
- synchronized (KeyboardFocusManager.class) {
- if (focusOwner == null) {
- return null;
- }
-
- return (focusOwner.appContext == AppContext.getAppContext())
- ? focusOwner
- : null;
- }
- }
-
- /**
- * Returns the focus owner, even if the calling thread is in a different
- * context than the focus owner. The focus owner is defined as the
- * Component in an application that will typically receive all KeyEvents
- * generated by the user. KeyEvents which map to the focus owner's focus
- * traversal keys will not be delivered if focus traversal keys are enabled
- * for the focus owner. In addition, KeyEventDispatchers may retarget or
- * consume KeyEvents before they reach the focus owner.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
- *
- * @return the focus owner
- * @see #getFocusOwner
- * @see #setGlobalFocusOwner
- * @throws SecurityException if this KeyboardFocusManager is not the
- * current KeyboardFocusManager for the calling thread's context
- */
- protected Component getGlobalFocusOwner() throws SecurityException {
- synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return focusOwner;
- } else {
- if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- throw new SecurityException(notPrivileged);
- }
- }
- }
-
- /**
- * Sets the focus owner. The operation will be cancelled if the Component
- * is not focusable. The focus owner is defined as the Component in an
- * application that will typically receive all KeyEvents generated by the
- * user. KeyEvents which map to the focus owner's focus traversal keys will
- * not be delivered if focus traversal keys are enabled for the focus
- * owner. In addition, KeyEventDispatchers may retarget or consume
- * KeyEvents before they reach the focus owner.
- * <p>
- * This method does not actually set the focus to the specified Component.
- * It merely stores the value to be subsequently returned by
- * <code>getFocusOwner()</code>. Use <code>Component.requestFocus()</code>
- * or <code>Component.requestFocusInWindow()</code> to change the focus
- * owner, subject to platform limitations.
- *
- * @param focusOwner the focus owner
- * @see #getFocusOwner
- * @see #getGlobalFocusOwner
- * @see Component#requestFocus()
- * @see Component#requestFocusInWindow()
- * @see Component#isFocusable
- * @beaninfo
- * bound: true
- */
- protected void setGlobalFocusOwner(Component focusOwner) {
- Component oldFocusOwner = null;
- boolean shouldFire = false;
-
- if (focusOwner == null || focusOwner.isFocusable()) {
- synchronized (KeyboardFocusManager.class) {
- oldFocusOwner = getFocusOwner();
-
- try {
- fireVetoableChange("focusOwner", oldFocusOwner,
- focusOwner);
- } catch (PropertyVetoException e) {
- // rejected
- return;
- }
-
- KeyboardFocusManager.focusOwner = focusOwner;
-
- if (focusOwner != null &&
- (getCurrentFocusCycleRoot() == null ||
- !focusOwner.isFocusCycleRoot(getCurrentFocusCycleRoot())))
- {
- Container rootAncestor =
- focusOwner.getFocusCycleRootAncestor();
- if (rootAncestor == null && (focusOwner instanceof Window))
- {
- rootAncestor = (Container)focusOwner;
- }
- if (rootAncestor != null) {
- setGlobalCurrentFocusCycleRoot(rootAncestor);
- }
- }
-
- shouldFire = true;
- }
- }
-
- if (shouldFire) {
- firePropertyChange("focusOwner", oldFocusOwner, focusOwner);
- }
- }
-
- /**
- * Clears the global focus owner at both the Java and native levels. If
- * there exists a focus owner, that Component will receive a permanent
- * FOCUS_LOST event. After this operation completes, the native windowing
- * system will discard all user-generated KeyEvents until the user selects
- * a new Component to receive focus, or a Component is given focus
- * explicitly via a call to <code>requestFocus()</code>. This operation
- * does not change the focused or active Windows.
- *
- * @see Component#requestFocus()
- * @see java.awt.event.FocusEvent#FOCUS_LOST
- */
- public void clearGlobalFocusOwner() {
- if (!GraphicsEnvironment.isHeadless()) {
- // Toolkit must be fully initialized, otherwise
- // _clearGlobalFocusOwner will crash or throw an exception
- Toolkit.getDefaultToolkit();
-
- _clearGlobalFocusOwner();
- }
- }
- private void _clearGlobalFocusOwner() {
- Window activeWindow = markClearGlobalFocusOwner();
- peer.clearGlobalFocusOwner(activeWindow);
- }
-
- Component getNativeFocusOwner() {
- return peer.getCurrentFocusOwner();
- }
-
- void setNativeFocusOwner(Component comp) {
- peer.setCurrentFocusOwner(comp);
- }
-
- Window getNativeFocusedWindow() {
- return peer.getCurrentFocusedWindow();
- }
-
- void setNativeFocusedWindow(Window win) {
- peer.setCurrentFocusedWindow(win);
- }
-
- /**
- * Returns the permanent focus owner, if the permanent focus owner is in
- * the same context as the calling thread. The permanent focus owner is
- * defined as the last Component in an application to receive a permanent
- * FOCUS_GAINED event. The focus owner and permanent focus owner are
- * equivalent unless a temporary focus change is currently in effect. In
- * such a situation, the permanent focus owner will again be the focus
- * owner when the temporary focus change ends.
- *
- * @return the permanent focus owner, or null if the permanent focus owner
- * is not a member of the calling thread's context
- * @see #getGlobalPermanentFocusOwner
- * @see #setGlobalPermanentFocusOwner
- */
- public Component getPermanentFocusOwner() {
- synchronized (KeyboardFocusManager.class) {
- if (permanentFocusOwner == null) {
- return null;
- }
-
- return (permanentFocusOwner.appContext ==
- AppContext.getAppContext())
- ? permanentFocusOwner
- : null;
- }
- }
-
- /**
- * Returns the permanent focus owner, even if the calling thread is in a
- * different context than the permanent focus owner. The permanent focus
- * owner is defined as the last Component in an application to receive a
- * permanent FOCUS_GAINED event. The focus owner and permanent focus owner
- * are equivalent unless a temporary focus change is currently in effect.
- * In such a situation, the permanent focus owner will again be the focus
- * owner when the temporary focus change ends.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
- *
- * @return the permanent focus owner
- * @see #getPermanentFocusOwner
- * @see #setGlobalPermanentFocusOwner
- * @throws SecurityException if this KeyboardFocusManager is not the
- * current KeyboardFocusManager for the calling thread's context
- */
- protected Component getGlobalPermanentFocusOwner()
- throws SecurityException
- {
- synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return permanentFocusOwner;
- } else {
- if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- throw new SecurityException(notPrivileged);
- }
- }
- }
-
- /**
- * Sets the permanent focus owner. The operation will be cancelled if the
- * Component is not focusable. The permanent focus owner is defined as the
- * last Component in an application to receive a permanent FOCUS_GAINED
- * event. The focus owner and permanent focus owner are equivalent unless
- * a temporary focus change is currently in effect. In such a situation,
- * the permanent focus owner will again be the focus owner when the
- * temporary focus change ends.
- * <p>
- * This method does not actually set the focus to the specified Component.
- * It merely stores the value to be subsequently returned by
- * <code>getPermanentFocusOwner()</code>. Use
- * <code>Component.requestFocus()</code> or
- * <code>Component.requestFocusInWindow()</code> to change the focus owner,
- * subject to platform limitations.
- *
- * @param permanentFocusOwner the permanent focus owner
- * @see #getPermanentFocusOwner
- * @see #getGlobalPermanentFocusOwner
- * @see Component#requestFocus()
- * @see Component#requestFocusInWindow()
- * @see Component#isFocusable
- * @beaninfo
- * bound: true
- */
- protected void setGlobalPermanentFocusOwner(Component permanentFocusOwner)
- {
- Component oldPermanentFocusOwner = null;
- boolean shouldFire = false;
-
- if (permanentFocusOwner == null || permanentFocusOwner.isFocusable()) {
- synchronized (KeyboardFocusManager.class) {
- oldPermanentFocusOwner = getPermanentFocusOwner();
-
- try {
- fireVetoableChange("permanentFocusOwner",
- oldPermanentFocusOwner,
- permanentFocusOwner);
- } catch (PropertyVetoException e) {
- // rejected
- return;
- }
-
- KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
-
- KeyboardFocusManager.
- setMostRecentFocusOwner(permanentFocusOwner);
-
- shouldFire = true;
- }
- }
-
- if (shouldFire) {
- firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
- permanentFocusOwner);
- }
- }
-
- /**
- * Returns the focused Window, if the focused Window is in the same context
- * as the calling thread. The focused Window is the Window that is or
- * contains the focus owner.
- *
- * @return the focused Window, or null if the focused Window is not a
- * member of the calling thread's context
- * @see #getGlobalFocusedWindow
- * @see #setGlobalFocusedWindow
- */
- public Window getFocusedWindow() {
- synchronized (KeyboardFocusManager.class) {
- if (focusedWindow == null) {
- return null;
- }
-
- return (focusedWindow.appContext == AppContext.getAppContext())
- ? focusedWindow
- : null;
- }
- }
-
- /**
- * Returns the focused Window, even if the calling thread is in a different
- * context than the focused Window. The focused Window is the Window that
- * is or contains the focus owner.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
- *
- * @return the focused Window
- * @see #getFocusedWindow
- * @see #setGlobalFocusedWindow
- * @throws SecurityException if this KeyboardFocusManager is not the
- * current KeyboardFocusManager for the calling thread's context
- */
- protected Window getGlobalFocusedWindow() throws SecurityException {
- synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return focusedWindow;
- } else {
- if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- throw new SecurityException(notPrivileged);
- }
- }
- }
-
- /**
- * Sets the focused Window. The focused Window is the Window that is or
- * contains the focus owner. The operation will be cancelled if the
- * specified Window to focus is not a focusable Window.
- * <p>
- * This method does not actually change the focused Window as far as the
- * native windowing system is concerned. It merely stores the value to be
- * subsequently returned by <code>getFocusedWindow()</code>. Use
- * <code>Component.requestFocus()</code> or
- * <code>Component.requestFocusInWindow()</code> to change the focused
- * Window, subject to platform limitations.
- *
- * @param focusedWindow the focused Window
- * @see #getFocusedWindow
- * @see #getGlobalFocusedWindow
- * @see Component#requestFocus()
- * @see Component#requestFocusInWindow()
- * @see Window#isFocusableWindow
- * @beaninfo
- * bound: true
- */
- protected void setGlobalFocusedWindow(Window focusedWindow) {
- Window oldFocusedWindow = null;
- boolean shouldFire = false;
-
- if (focusedWindow == null || focusedWindow.isFocusableWindow()) {
- synchronized (KeyboardFocusManager.class) {
- oldFocusedWindow = getFocusedWindow();
-
- try {
- fireVetoableChange("focusedWindow", oldFocusedWindow,
- focusedWindow);
- } catch (PropertyVetoException e) {
- // rejected
- return;
- }
-
- KeyboardFocusManager.focusedWindow = focusedWindow;
- shouldFire = true;
- }
- }
-
- if (shouldFire) {
- firePropertyChange("focusedWindow", oldFocusedWindow,
- focusedWindow);
- }
- }
-
- /**
- * Returns the active Window, if the active Window is in the same context
- * as the calling thread. Only a Frame or a Dialog can be the active
- * Window. The native windowing system may denote the active Window or its
- * children with special decorations, such as a highlighted title bar.
- * The active Window is always either the focused Window, or the first
- * Frame or Dialog that is an owner of the focused Window.
- *
- * @return the active Window, or null if the active Window is not a member
- * of the calling thread's context
- * @see #getGlobalActiveWindow
- * @see #setGlobalActiveWindow
- */
- public Window getActiveWindow() {
- synchronized (KeyboardFocusManager.class) {
- if (activeWindow == null) {
- return null;
- }
-
- return (activeWindow.appContext == AppContext.getAppContext())
- ? activeWindow
- : null;
- }
- }
-
- /**
- * Returns the active Window, even if the calling thread is in a different
- * context than the active Window. Only a Frame or a Dialog can be the
- * active Window. The native windowing system may denote the active Window
- * or its children with special decorations, such as a highlighted title
- * bar. The active Window is always either the focused Window, or the first
- * Frame or Dialog that is an owner of the focused Window.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
- *
- * @return the active Window
- * @see #getActiveWindow
- * @see #setGlobalActiveWindow
- * @throws SecurityException if this KeyboardFocusManager is not the
- * current KeyboardFocusManager for the calling thread's context
- */
- protected Window getGlobalActiveWindow() throws SecurityException {
- synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return activeWindow;
- } else {
- if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- throw new SecurityException(notPrivileged);
- }
- }
- }
-
- /**
- * Sets the active Window. Only a Frame or a Dialog can be the active
- * Window. The native windowing system may denote the active Window or its
- * children with special decorations, such as a highlighted title bar. The
- * active Window is always either the focused Window, or the first Frame or
- * Dialog that is an owner of the focused Window.
- * <p>
- * This method does not actually change the active Window as far as the
- * native windowing system is concerned. It merely stores the value to be
- * subsequently returned by <code>getActiveWindow()</code>. Use
- * <code>Component.requestFocus()</code> or
- * <code>Component.requestFocusInWindow()</code>to change the active
- * Window, subject to platform limitations.
- *
- * @param activeWindow the active Window
- * @see #getActiveWindow
- * @see #getGlobalActiveWindow
- * @see Component#requestFocus()
- * @see Component#requestFocusInWindow()
- * @beaninfo
- * bound: true
- */
- protected void setGlobalActiveWindow(Window activeWindow) {
- Window oldActiveWindow;
- synchronized (KeyboardFocusManager.class) {
- oldActiveWindow = getActiveWindow();
- if (focusLog.isLoggable(Level.FINER)) {
- focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
- }
-
- try {
- fireVetoableChange("activeWindow", oldActiveWindow,
- activeWindow);
- } catch (PropertyVetoException e) {
- // rejected
- return;
- }
-
- KeyboardFocusManager.activeWindow = activeWindow;
- }
-
- firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
- }
-
- /**
- * Returns the default FocusTraversalPolicy. Top-level components
- * use this value on their creation to initialize their own focus traversal
- * policy by explicit call to Container.setFocusTraversalPolicy.
- *
- * @return the default FocusTraversalPolicy. null will never be returned.
- * @see #setDefaultFocusTraversalPolicy
- * @see Container#setFocusTraversalPolicy
- * @see Container#getFocusTraversalPolicy
- */
- public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
- return defaultPolicy;
- }
-
- /**
- * Sets the default FocusTraversalPolicy. Top-level components
- * use this value on their creation to initialize their own focus traversal
- * policy by explicit call to Container.setFocusTraversalPolicy.
- * Note: this call doesn't affect already created components as they have
- * their policy initialized. Only new components will use this policy as
- * their default policy.
- *
- * @param defaultPolicy the new, default FocusTraversalPolicy
- * @see #getDefaultFocusTraversalPolicy
- * @see Container#setFocusTraversalPolicy
- * @see Container#getFocusTraversalPolicy
- * @throws IllegalArgumentException if defaultPolicy is null
- * @beaninfo
- * bound: true
- */
- public void setDefaultFocusTraversalPolicy(FocusTraversalPolicy
- defaultPolicy) {
- if (defaultPolicy == null) {
- throw new IllegalArgumentException("default focus traversal policy cannot be null");
- }
-
- FocusTraversalPolicy oldPolicy;
-
- synchronized (this) {
- oldPolicy = this.defaultPolicy;
- this.defaultPolicy = defaultPolicy;
- }
-
- firePropertyChange("defaultFocusTraversalPolicy", oldPolicy,
- defaultPolicy);
- }
-
- /**
- * Sets the default focus traversal keys for a given traversal operation.
- * This traversal key <code>Set</code> will be in effect on all
- * <code>Window</code>s that have no such <code>Set</code> of
- * their own explicitly defined. This <code>Set</code> will also be
- * inherited, recursively, by any child <code>Component</code> of
- * those <code>Windows</code> that has
- * no such <code>Set</code> of its own explicitly defined.
- * <p>
- * The default values for the default focus traversal keys are
- * implementation-dependent. Sun recommends that all implementations for a
- * particular native platform use the same default values. The
- * recommendations for Windows and Unix are listed below. These
- * recommendations are used in the Sun AWT implementations.
- *
- * <table border=1 summary="Recommended default values for focus traversal keys">
- * <tr>
- * <th>Identifier</th>
- * <th>Meaning</th>
- * <th>Default</th>
- * </tr>
- * <tr>
- * <td><code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code></td>
- * <td>Normal forward keyboard traversal</td>
- * <td><code>TAB</code> on <code>KEY_PRESSED</code>,
- * <code>CTRL-TAB</code> on <code>KEY_PRESSED</code></td>
- * </tr>
- * <tr>
- * <td><code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code></td>
- * <td>Normal reverse keyboard traversal</td>
- * <td><code>SHIFT-TAB</code> on <code>KEY_PRESSED</code>,
- * <code>CTRL-SHIFT-TAB</code> on <code>KEY_PRESSED</code></td>
- * </tr>
- * <tr>
- * <td><code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code></td>
- * <td>Go up one focus traversal cycle</td>
- * <td>none</td>
- * </tr>
- * <tr>
- * <td><code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code></td>
- * <td>Go down one focus traversal cycle</td>
- * <td>none</td>
- * </tr>
- * </table>
- *
- * To disable a traversal key, use an empty <code>Set</code>
- * <code>Collections.EMPTY_SET</code> is recommended.
- * <p>
- * Using the <code>AWTKeyStroke</code> API, client code can
- * specify on which of two
- * specific <code>KeyEvent</code>s, <code>KEY_PRESSED</code> or
- * <code>KEY_RELEASED</code>, the focus traversal operation will
- * occur. Regardless of which <code>KeyEvent</code> is specified,
- * however, all <code>KeyEvent</code>s related to the focus
- * traversal key, including the associated <code>KEY_TYPED</code>
- * event, will be consumed, and will not be dispatched
- * to any <code>Component</code>. It is a runtime error to
- * specify a <code>KEY_TYPED</code> event as
- * mapping to a focus traversal operation, or to map the same event to
- * multiple default focus traversal operations.
- *
- * @param id one of
- * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
- * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
- * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
- * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>
- * @param keystrokes the Set of <code>AWTKeyStroke</code>s for the
- * specified operation
- * @see #getDefaultFocusTraversalKeys
- * @see Component#setFocusTraversalKeys
- * @see Component#getFocusTraversalKeys
- * @throws IllegalArgumentException if id is not one of
- * <code>KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS</code>,
- * <code>KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS</code>,
- * <code>KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS</code>, or
- * <code>KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS</code>,
- * or if keystrokes is <code>null</code>,
- * or if keystrokes contains <code>null</code>,
- * or if any <code>Object</code> in
- * keystrokes is not an <code>AWTKeyStroke</code>,
- * or if any keystroke
- * represents a <code>KEY_TYPED</code> event,
- * or if any keystroke already maps
- * to another default focus traversal operation
- * @beaninfo
- * bound: true
- */
- public void
- setDefaultFocusTraversalKeys(int id,
- Set<? extends AWTKeyStroke> keystrokes)
- {
- if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
- throw new IllegalArgumentException("invalid focus traversal key identifier");
- }
- if (keystrokes == null) {
- throw new IllegalArgumentException("cannot set null Set of default focus traversal keys");
- }
-
- Set oldKeys;
-
- synchronized (this) {
- for (Iterator iter = keystrokes.iterator(); iter.hasNext(); ) {
- Object obj = iter.next();
-
- if (obj == null) {
- throw new IllegalArgumentException("cannot set null focus traversal key");
- }
-
- // Generates a ClassCastException if the element is not an
- // AWTKeyStroke. This is desirable.
- AWTKeyStroke keystroke = (AWTKeyStroke)obj;
-
- if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
- throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
- }
-
- // Check to see if key already maps to another traversal
- // operation
- for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
- if (i == id) {
- continue;
- }
-
- if (defaultFocusTraversalKeys[i].contains(keystroke)) {
- throw new IllegalArgumentException("focus traversal keys must be unique for a Component");
- }
- }
- }
-
- oldKeys = defaultFocusTraversalKeys[id];
- defaultFocusTraversalKeys[id] =
- Collections.unmodifiableSet(new HashSet(keystrokes));
- }
-
- firePropertyChange(defaultFocusTraversalKeyPropertyNames[id],
- oldKeys, keystrokes);
- }
-
- /**
- * Returns a Set of default focus traversal keys for a given traversal
- * operation. This traversal key Set will be in effect on all Windows that
- * have no such Set of their own explicitly defined. This Set will also be
- * inherited, recursively, by any child Component of those Windows that has
- * no such Set of its own explicitly defined. (See
- * <code>setDefaultFocusTraversalKeys</code> for a full description of each
- * operation.)
- *
- * @param id one of KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
- * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
- * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
- * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
- * @return the <code>Set</code> of <code>AWTKeyStroke</code>s
- * for the specified operation; the <code>Set</code>
- * will be unmodifiable, and may be empty; <code>null</code>
- * will never be returned
- * @see #setDefaultFocusTraversalKeys
- * @see Component#setFocusTraversalKeys
- * @see Component#getFocusTraversalKeys
- * @throws IllegalArgumentException if id is not one of
- * KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
- * KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
- * KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or
- * KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS
- */
- public Set<AWTKeyStroke> getDefaultFocusTraversalKeys(int id) {
- if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
- throw new IllegalArgumentException("invalid focus traversal key identifier");
- }
-
- // Okay to return Set directly because it is an unmodifiable view
- return defaultFocusTraversalKeys[id];
- }
-
- /**
- * Returns the current focus cycle root, if the current focus cycle root is
- * in the same context as the calling thread. If the focus owner is itself
- * a focus cycle root, then it may be ambiguous as to which Components
- * represent the next and previous Components to focus during normal focus
- * traversal. In that case, the current focus cycle root is used to
- * differentiate among the possibilities.
- * <p>
- * This method is intended to be used only by KeyboardFocusManagers and
- * focus implementations. It is not for general client use.
- *
- * @return the current focus cycle root, or null if the current focus cycle
- * root is not a member of the calling thread's context
- * @see #getGlobalCurrentFocusCycleRoot
- * @see #setGlobalCurrentFocusCycleRoot
- */
- public Container getCurrentFocusCycleRoot() {
- synchronized (KeyboardFocusManager.class) {
- if (currentFocusCycleRoot == null) {
- return null;
- }
-
- return (currentFocusCycleRoot.appContext ==
- AppContext.getAppContext())
- ? currentFocusCycleRoot
- : null;
- }
- }
-
- /**
- * Returns the current focus cycle root, even if the calling thread is in a
- * different context than the current focus cycle root. If the focus owner
- * is itself a focus cycle root, then it may be ambiguous as to which
- * Components represent the next and previous Components to focus during
- * normal focus traversal. In that case, the current focus cycle root is
- * used to differentiate among the possibilities.
- * <p>
- * This method will throw a SecurityException if this KeyboardFocusManager
- * is not the current KeyboardFocusManager for the calling thread's
- * context.
- *
- * @return the current focus cycle root, or null if the current focus cycle
- * root is not a member of the calling thread's context
- * @see #getCurrentFocusCycleRoot
- * @see #setGlobalCurrentFocusCycleRoot
- * @throws SecurityException if this KeyboardFocusManager is not the
- * current KeyboardFocusManager for the calling thread's context
- */
- protected Container getGlobalCurrentFocusCycleRoot()
- throws SecurityException
- {
- synchronized (KeyboardFocusManager.class) {
- if (this == getCurrentKeyboardFocusManager()) {
- return currentFocusCycleRoot;
- } else {
- if (focusLog.isLoggable(Level.FINE)) focusLog.fine("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
- throw new SecurityException(notPrivileged);
- }
- }
- }
-
- /**
- * Sets the current focus cycle root. If the focus owner is itself a focus
- * cycle root, then it may be ambiguous as to which Components represent
- * the next and previous Components to focus during normal focus traversal.
- * In that case, the current focus cycle root is used to differentiate
- * among the possibilities.
- * <p>
- * This method is intended to be used only by KeyboardFocusManagers and
- * focus implementations. It is not for general client use.
- *
- * @param newFocusCycleRoot the new focus cycle root
- * @see #getCurrentFocusCycleRoot
- * @see #getGlobalCurrentFocusCycleRoot
- * @beaninfo
- * bound: true
- */
- public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
- Container oldFocusCycleRoot;
-
- synchronized (KeyboardFocusManager.class) {
- oldFocusCycleRoot = getCurrentFocusCycleRoot();
- currentFocusCycleRoot = newFocusCycleRoot;
- }
-
- firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
- newFocusCycleRoot);
- }
-
- /**
- * Adds a PropertyChangeListener to the listener list. The listener is
- * registered for all bound properties of this class, including the
- * following:
- * <ul>
- * <li>whether the KeyboardFocusManager is currently managing focus
- * for this application or applet's browser context
- * ("managingFocus")</li>
- * <li>the focus owner ("focusOwner")</li>
- * <li>the permanent focus owner ("permanentFocusOwner")</li>
- * <li>the focused Window ("focusedWindow")</li>
- * <li>the active Window ("activeWindow")</li>
- * <li>the default focus traversal policy
- * ("defaultFocusTraversalPolicy")</li>
- * <li>the Set of default FORWARD_TRAVERSAL_KEYS
- * ("forwardDefaultFocusTraversalKeys")</li>
- * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
- * ("backwardDefaultFocusTraversalKeys")</li>
- * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
- * ("upCycleDefaultFocusTraversalKeys")</li>
- * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
- * ("downCycleDefaultFocusTraversalKeys")</li>
- * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
- * </ul>
- * If listener is null, no exception is thrown and no action is performed.
- *
- * @param listener the PropertyChangeListener to be added
- * @see #removePropertyChangeListener
- * @see #getPropertyChangeListeners
- * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
- */
- public void addPropertyChangeListener(PropertyChangeListener listener) {
- if (listener != null) {
- synchronized (this) {
- if (changeSupport == null) {
- changeSupport = new PropertyChangeSupport(this);
- }
- changeSupport.addPropertyChangeListener(listener);
- }
- }
- }
-
- /**
- * Removes a PropertyChangeListener from the listener list. This method
- * should be used to remove the PropertyChangeListeners that were
- * registered for all bound properties of this class.
- * <p>
- * If listener is null, no exception is thrown and no action is performed.
- *
- * @param listener the PropertyChangeListener to be removed
- * @see #addPropertyChangeListener
- * @see #getPropertyChangeListeners
- * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
- */
- public void removePropertyChangeListener(PropertyChangeListener listener) {
- if (listener != null) {
- synchronized (this) {
- if (changeSupport != null) {
- changeSupport.removePropertyChangeListener(listener);
- }
- }
- }
- }
-
- /**
- * Returns an array of all the property change listeners
- * registered on this keyboard focus manager.
- *
- * @return all of this keyboard focus manager's
- * <code>PropertyChangeListener</code>s
- * or an empty array if no property change
- * listeners are currently registered
- *
- * @see #addPropertyChangeListener
- * @see #removePropertyChangeListener
- * @see #getPropertyChangeListeners(java.lang.String)
- * @since 1.4
- */
- public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
- if (changeSupport == null) {
- changeSupport = new PropertyChangeSupport(this);
- }
- return changeSupport.getPropertyChangeListeners();
- }
-
- /**
- * Adds a PropertyChangeListener to the listener list for a specific
- * property. The specified property may be user-defined, or one of the
- * following:
- * <ul>
- * <li>whether the KeyboardFocusManager is currently managing focus
- * for this application or applet's browser context
- * ("managingFocus")</li>
- * <li>the focus owner ("focusOwner")</li>
- * <li>the permanent focus owner ("permanentFocusOwner")</li>
- * <li>the focused Window ("focusedWindow")</li>
- * <li>the active Window ("activeWindow")</li>
- * <li>the default focus traversal policy
- * ("defaultFocusTraversalPolicy")</li>
- * <li>the Set of default FORWARD_TRAVERSAL_KEYS
- * ("forwardDefaultFocusTraversalKeys")</li>
- * <li>the Set of default BACKWARD_TRAVERSAL_KEYS
- * ("backwardDefaultFocusTraversalKeys")</li>
- * <li>the Set of default UP_CYCLE_TRAVERSAL_KEYS
- * ("upCycleDefaultFocusTraversalKeys")</li>
- * <li>the Set of default DOWN_CYCLE_TRAVERSAL_KEYS
- * ("downCycleDefaultFocusTraversalKeys")</li>
- * <li>the current focus cycle root ("currentFocusCycleRoot")</li>
- * </ul>
- * If listener is null, no exception is thrown and no action is performed.
- *
- * @param propertyName one of the property names listed above
- * @param listener the PropertyChangeListener to be added
- * @see #addPropertyChangeListener(java.beans.PropertyChangeListener)
- * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
- * @see #getPropertyChangeListeners(java.lang.String)
- */
- public void addPropertyChangeListener(String propertyName,
- PropertyChangeListener listener) {
- if (listener != null) {
- synchronized (this) {
- if (changeSupport == null) {
- changeSupport = new PropertyChangeSupport(this);
- }
- changeSupport.addPropertyChangeListener(propertyName,
- listener);
- }
- }
- }
-
- /**
- * Removes a PropertyChangeListener from the listener list for a specific
- * property. This method should be used to remove PropertyChangeListeners
- * that were registered for a specific bound property.
- * <p>
- * If listener is null, no exception is thrown and no action is performed.
- *
- * @param propertyName a valid property name
- * @param listener the PropertyChangeListener to be removed
- * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
- * @see #getPropertyChangeListeners(java.lang.String)
- * @see #removePropertyChangeListener(java.beans.PropertyChangeListener)
- */
- public void removePropertyChangeListener(String propertyName,
- PropertyChangeListener listener) {
- if (listener != null) {
- synchronized (this) {
- if (changeSupport != null) {
- changeSupport.removePropertyChangeListener(propertyName,
- listener);
- }
- }
- }
- }
-
- /**
- * Returns an array of all the <code>PropertyChangeListener</code>s
- * associated with the named property.
- *
- * @return all of the <code>PropertyChangeListener</code>s associated with
- * the named property or an empty array if no such listeners have
- * been added.
- *
- * @see #addPropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
- * @see #removePropertyChangeListener(java.lang.String,java.beans.PropertyChangeListener)
- * @since 1.4
- */
- public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
- if (changeSupport == null) {
- changeSupport = new PropertyChangeSupport(this);
- }
- return changeSupport.getPropertyChangeListeners(propertyName);
- }
-
- /**
- * Fires a PropertyChangeEvent in response to a change in a bound property.
- * The event will be delivered to all registered PropertyChangeListeners.
- * No event will be delivered if oldValue and newValue are the same.
- *
- * @param propertyName the name of the property that has changed
- * @param oldValue the property's previous value
- * @param newValue the property's new value
- */
- protected void firePropertyChange(String propertyName, Object oldValue,
- Object newValue) {
- PropertyChangeSupport changeSupport = this.changeSupport;
- if (changeSupport != null) {
- changeSupport.firePropertyChange(propertyName, oldValue, newValue);
- }
- }
-
- /**
- * Adds a VetoableChangeListener to the listener list. The listener is
- * registered for all vetoable properties of this class, including the
- * following:
- * <ul>
- * <li>the focus owner ("focusOwner")</li>
- * <li>the permanent focus owner ("permanentFocusOwner")</li>
- * <li>the focused Window ("focusedWindow")</li>
- * <li>the active Window ("activeWindow")</li>
- * </ul>
- * If listener is null, no exception is thrown and no action is performed.
- *
- * @param listener the VetoableChangeListener to be added
- * @see #removeVetoableChangeListener
- * @see #getVetoableChangeListeners
- * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
- */
- public void addVetoableChangeListener(VetoableChangeListener listener) {
- if (listener != null) {
- synchronized (this) {
- if (vetoableSupport == null) {
- vetoableSupport =
- new VetoableChangeSupport(this);
- }
- vetoableSupport.addVetoableChangeListener(listener);
- }
- }
- }
-
- /**
- * Removes a VetoableChangeListener from the listener list. This method
- * should be used to remove the VetoableChangeListeners that were
- * registered for all vetoable properties of this class.
- * <p>
- * If listener is null, no exception is thrown and no action is performed.
- *
- * @param listener the VetoableChangeListener to be removed
- * @see #addVetoableChangeListener
- * @see #getVetoableChangeListeners
- * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
- */
- public void removeVetoableChangeListener(VetoableChangeListener listener) {
- if (listener != null) {
- synchronized (this) {
- if (vetoableSupport != null) {
- vetoableSupport.removeVetoableChangeListener(listener);
- }
- }
- }
- }
-
- /**
- * Returns an array of all the vetoable change listeners
- * registered on this keyboard focus manager.
- *
- * @return all of this keyboard focus manager's
- * <code>VetoableChangeListener</code>s
- * or an empty array if no vetoable change
- * listeners are currently registered
- *
- * @see #addVetoableChangeListener
- * @see #removeVetoableChangeListener
- * @see #getVetoableChangeListeners(java.lang.String)
- * @since 1.4
- */
- public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
- if (vetoableSupport == null) {
- vetoableSupport = new VetoableChangeSupport(this);
- }
- return vetoableSupport.getVetoableChangeListeners();
- }
-
- /**
- * Adds a VetoableChangeListener to the listener list for a specific
- * property. The specified property may be user-defined, or one of the
- * following:
- * <ul>
- * <li>the focus owner ("focusOwner")</li>
- * <li>the permanent focus owner ("permanentFocusOwner")</li>
- * <li>the focused Window ("focusedWindow")</li>
- * <li>the active Window ("activeWindow")</li>
- * </ul>
- * If listener is null, no exception is thrown and no action is performed.
- *
- * @param propertyName one of the property names listed above
- * @param listener the VetoableChangeListener to be added
- * @see #addVetoableChangeListener(java.beans.VetoableChangeListener)
- * @see #removeVetoableChangeListener
- * @see #getVetoableChangeListeners
- */
- public void addVetoableChangeListener(String propertyName,
- VetoableChangeListener listener) {
- if (listener != null) {
- synchronized (this) {
- if (vetoableSupport == null) {
- vetoableSupport =
- new VetoableChangeSupport(this);
- }
- vetoableSupport.addVetoableChangeListener(propertyName,
- listener);
- }
- }
- }
-
- /**
- * Removes a VetoableChangeListener from the listener list for a specific
- * property. This method should be used to remove VetoableChangeListeners
- * that were registered for a specific bound property.
- * <p>
- * If listener is null, no exception is thrown and no action is performed.
- *
- * @param propertyName a valid property name
- * @param listener the VetoableChangeListener to be removed
- * @see #addVetoableChangeListener
- * @see #getVetoableChangeListeners
- * @see #removeVetoableChangeListener(java.beans.VetoableChangeListener)
- */
- public void removeVetoableChangeListener(String propertyName,
- VetoableChangeListener listener) {
- if (listener != null) {
- synchronized (this) {
- if (vetoableSupport != null) {
- vetoableSupport.removeVetoableChangeListener(propertyName,
- listener);
- }
- }
- }
- }
-
- /**
- * Returns an array of all the <code>VetoableChangeListener</code>s
- * associated with the named property.
- *
- * @return all of the <code>VetoableChangeListener</code>s associated with
- * the named property or an empty array if no such listeners have
- * been added.
- *
- * @see #addVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
- * @see #removeVetoableChangeListener(java.lang.String,java.beans.VetoableChangeListener)
- * @see #getVetoableChangeListeners
- * @since 1.4
- */
- public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
- if (vetoableSupport == null) {
- vetoableSupport = new VetoableChangeSupport(this);
- }
- return vetoableSupport.getVetoableChangeListeners(propertyName);
- }
-
- /**
- * Fires a PropertyChangeEvent in response to a change in a vetoable
- * property. The event will be delivered to all registered
- * VetoableChangeListeners. If a VetoableChangeListener throws a
- * PropertyVetoException, a new event is fired reverting all
- * VetoableChangeListeners to the old value and the exception is then
- * rethrown. No event will be delivered if oldValue and newValue are the
- * same.
- *
- * @param propertyName the name of the property that has changed
- * @param oldValue the property's previous value
- * @param newValue the property's new value
- * @throws java.beans.PropertyVetoException if a
- * <code>VetoableChangeListener</code> threw
- * <code>PropertyVetoException</code>
- */
- protected void fireVetoableChange(String propertyName, Object oldValue,
- Object newValue)
- throws PropertyVetoException
- {
- VetoableChangeSupport vetoableSupport =
- this.vetoableSupport;
- if (vetoableSupport != null) {
- vetoableSupport.fireVetoableChange(propertyName, oldValue,
- newValue);
- }
- }
-
- /**
- * Adds a KeyEventDispatcher to this KeyboardFocusManager's dispatcher
- * chain. This KeyboardFocusManager will request that each
- * KeyEventDispatcher dispatch KeyEvents generated by the user before
- * finally dispatching the KeyEvent itself. KeyEventDispatchers will be
- * notified in the order in which they were added. Notifications will halt
- * as soon as one KeyEventDispatcher returns <code>true</code> from its
- * <code>dispatchKeyEvent</code> method. There is no limit to the total
- * number of KeyEventDispatchers which can be added, nor to the number of
- * times which a particular KeyEventDispatcher instance can be added.
- * <p>
- * If a null dispatcher is specified, no action is taken and no exception
- * is thrown.
- *
- * @param dispatcher the KeyEventDispatcher to add to the dispatcher chain
- * @see #removeKeyEventDispatcher
- */
- public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
- if (dispatcher != null) {
- synchronized (this) {
- if (keyEventDispatchers == null) {
- keyEventDispatchers = new java.util.LinkedList();
- }
- keyEventDispatchers.add(dispatcher);
- }
- }
- }
-
- /**
- * Removes a KeyEventDispatcher which was previously added to this
- * KeyboardFocusManager's dispatcher chain. This KeyboardFocusManager
- * cannot itself be removed, unless it was explicitly re-registered via a
- * call to <code>addKeyEventDispatcher</code>.
- * <p>
- * If a null dispatcher is specified, if the specified dispatcher is not
- * in the dispatcher chain, or if this KeyboardFocusManager is specified
- * without having been explicitly re-registered, no action is taken and no
- * exception is thrown.
- *
- * @param dispatcher the KeyEventDispatcher to remove from the dispatcher
- * chain
- * @see #addKeyEventDispatcher
- */
- public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
- if (dispatcher != null) {
- synchronized (this) {
- if (keyEventDispatchers != null) {
- keyEventDispatchers.remove(dispatcher);
- }
- }
- }
- }
-
- /**
- * Returns this KeyboardFocusManager's KeyEventDispatcher chain as a List.
- * The List will not include this KeyboardFocusManager unless it was
- * explicitly re-registered via a call to
- * <code>addKeyEventDispatcher</code>. If no other KeyEventDispatchers are
- * registered, implementations are free to return null or a List of length
- * 0. Client code should not assume one behavior over another, nor should
- * it assume that the behavior, once established, will not change.
- *
- * @return a possibly null or empty List of KeyEventDispatchers
- * @see #addKeyEventDispatcher
- * @see #removeKeyEventDispatcher
- */
- protected synchronized java.util.List<KeyEventDispatcher>
- getKeyEventDispatchers()
- {
- return (keyEventDispatchers != null)
- ? (java.util.List)keyEventDispatchers.clone()
- : null;
- }
-
- /**
- * Adds a KeyEventPostProcessor to this KeyboardFocusManager's post-
- * processor chain. After a KeyEvent has been dispatched to and handled by
- * its target, KeyboardFocusManager will request that each
- * KeyEventPostProcessor perform any necessary post-processing as part
- * of the KeyEvent's final resolution. KeyEventPostProcessors
- * will be notified in the order in which they were added; the current
- * KeyboardFocusManager will be notified last. Notifications will halt
- * as soon as one KeyEventPostProcessor returns <code>true</code> from its
- * <code>postProcessKeyEvent</code> method. There is no limit to the the
- * total number of KeyEventPostProcessors that can be added, nor to the
- * number of times that a particular KeyEventPostProcessor instance can be
- * added.
- * <p>
- * If a null post-processor is specified, no action is taken and no
- * exception is thrown.
- *
- * @param processor the KeyEventPostProcessor to add to the post-processor
- * chain
- * @see #removeKeyEventPostProcessor
- */
- public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
- if (processor != null) {
- synchronized (this) {
- if (keyEventPostProcessors == null) {
- keyEventPostProcessors = new java.util.LinkedList();
- }
- keyEventPostProcessors.add(processor);
- }
- }
- }
-
-
- /**
- * Removes a previously added KeyEventPostProcessor from this
- * KeyboardFocusManager's post-processor chain. This KeyboardFocusManager
- * cannot itself be entirely removed from the chain. Only additional
- * references added via <code>addKeyEventPostProcessor</code> can be
- * removed.
- * <p>
- * If a null post-processor is specified, if the specified post-processor
- * is not in the post-processor chain, or if this KeyboardFocusManager is
- * specified without having been explicitly added, no action is taken and
- * no exception is thrown.
- *
- * @param processor the KeyEventPostProcessor to remove from the post-
- * processor chain
- * @see #addKeyEventPostProcessor
- */
- public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
- if (processor != null) {
- synchronized (this) {
- if (keyEventPostProcessors != null) {
- keyEventPostProcessors.remove(processor);
- }
- }
- }
- }
-
-
- /**
- * Returns this KeyboardFocusManager's KeyEventPostProcessor chain as a
- * List. The List will not include this KeyboardFocusManager unless it was
- * explicitly added via a call to <code>addKeyEventPostProcessor</code>. If
- * no KeyEventPostProcessors are registered, implementations are free to
- * return null or a List of length 0. Client code should not assume one
- * behavior over another, nor should it assume that the behavior, once
- * established, will not change.
- *
- * @return a possibly null or empty List of KeyEventPostProcessors
- * @see #addKeyEventPostProcessor
- * @see #removeKeyEventPostProcessor
- */
- protected java.util.List<KeyEventPostProcessor>
- getKeyEventPostProcessors()
- {
- return (keyEventPostProcessors != null)
- ? (java.util.List)keyEventPostProcessors.clone()
- : null;
- }
-
-
-
- static void setMostRecentFocusOwner(Component component) {
- Component window = component;
- while (window != null && !(window instanceof Window)) {
- window = window.parent;
- }
- if (window != null) {
- setMostRecentFocusOwner((Window)window, component);
- }
- }
- static synchronized void setMostRecentFocusOwner(Window window,
- Component component) {
- // ATTN: component has a strong reference to window via chain
- // of Component.parent fields. Since WeakHasMap refers to its
- // values strongly, we need to break the strong link from the
- // value (component) back to its key (window).
- WeakReference weakValue = null;
- if (component != null) {
- weakValue = new WeakReference(component);
- }
- mostRecentFocusOwners.put(window, weakValue);
- }
- static void clearMostRecentFocusOwner(Component comp) {
- Container window;
-
- if (comp == null) {
- return;
- }
-
- synchronized (comp.getTreeLock()) {
- window = comp.getParent();
- while (window != null && !(window instanceof Window)) {
- window = window.getParent();
- }
- }
-
- synchronized (KeyboardFocusManager.class) {
- if ((window != null)
- && (getMostRecentFocusOwner((Window)window) == comp))
- {
- setMostRecentFocusOwner((Window)window, null);
- }
- // Also clear temporary lost component stored in Window
- if (window != null) {
- Window realWindow = (Window)window;
- if (realWindow.getTemporaryLostComponent() == comp) {
- realWindow.setTemporaryLostComponent(null);
- }
- }
- }
- }
- static synchronized Component getMostRecentFocusOwner(Window window) {
- WeakReference weakValue =
- (WeakReference)mostRecentFocusOwners.get(window);
- return weakValue == null ? null : (Component)weakValue.get();
- }
-
- /**
- * This method is called by the AWT event dispatcher requesting that the
- * current KeyboardFocusManager dispatch the specified event on its behalf.
- * It is expected that all KeyboardFocusManagers will dispatch all
- * FocusEvents, all WindowEvents related to focus, and all KeyEvents.
- * These events should be dispatched based on the KeyboardFocusManager's
- * notion of the focus owner and the focused and active Windows, sometimes
- * overriding the source of the specified AWTEvent. Dispatching must be
- * done using <code>redispatchEvent</code> to prevent the AWT event
- * dispatcher from recursively requesting that the KeyboardFocusManager
- * dispatch the event again. If this method returns <code>false</code>,
- * then the AWT event dispatcher will attempt to dispatch the event itself.
- *
- * @param e the AWTEvent to be dispatched
- * @return <code>true</code> if this method dispatched the event;
- * <code>false</code> otherwise
- * @see #redispatchEvent
- * @see #dispatchKeyEvent
- */
- public abstract boolean dispatchEvent(AWTEvent e);
-
- /**
- * Redispatches an AWTEvent in such a way that the AWT event dispatcher
- * will not recursively request that the KeyboardFocusManager, or any
- * installed KeyEventDispatchers, dispatch the event again. Client
- * implementations of <code>dispatchEvent</code> and client-defined
- * KeyEventDispatchers must call <code>redispatchEvent(target, e)</code>
- * instead of <code>target.dispatchEvent(e)</code> to dispatch an event.
- * <p>
- * This method is intended to be used only by KeyboardFocusManagers and
- * KeyEventDispatchers. It is not for general client use.
- *
- * @param target the Component to which the event should be dispatched
- * @param e the event to dispatch
- * @see #dispatchEvent
- * @see KeyEventDispatcher
- */
- public final void redispatchEvent(Component target, AWTEvent e) {
- e.focusManagerIsDispatching = true;
- target.dispatchEvent(e);
- e.focusManagerIsDispatching = false;
- }
-
- /**
- * Typically this method will be called by <code>dispatchEvent</code> if no
- * other KeyEventDispatcher in the dispatcher chain dispatched the
- * KeyEvent, or if no other KeyEventDispatchers are registered. If an
- * implementation of this method returns <code>false</code>,
- * <code>dispatchEvent</code> may try to dispatch the KeyEvent itself, or
- * may simply return <code>false</code>. If <code>true</code> is returned,
- * <code>dispatchEvent</code> should return <code>true</code> as well.
- *
- * @param e the KeyEvent which the current KeyboardFocusManager has
- * requested that this KeyEventDispatcher dispatch
- * @return <code>true</code> if the KeyEvent was dispatched;
- * <code>false</code> otherwise
- * @see #dispatchEvent
- */
- public abstract boolean dispatchKeyEvent(KeyEvent e);
-
- /**
- * This method will be called by <code>dispatchKeyEvent</code>.
- * By default, this method will handle any unconsumed KeyEvents that
- * map to an AWT <code>MenuShortcut</code> by consuming the event
- * and activating the shortcut.
- *
- * @param e the KeyEvent to post-process
- * @return <code>true</code> to indicate that no other
- * KeyEventPostProcessor will be notified of the KeyEvent.
- * @see #dispatchKeyEvent
- * @see MenuShortcut
- */
- public abstract boolean postProcessKeyEvent(KeyEvent e);
-
- /**
- * This method initiates a focus traversal operation if and only if the
- * KeyEvent represents a focus traversal key for the specified
- * focusedComponent. It is expected that focusedComponent is the current
- * focus owner, although this need not be the case. If it is not,
- * focus traversal will nevertheless proceed as if focusedComponent
- * were the current focus owner.
- *
- * @param focusedComponent the Component that will be the basis for a focus
- * traversal operation if the specified event represents a focus
- * traversal key for the Component
- * @param e the event that may represent a focus traversal key
- */
- public abstract void processKeyEvent(Component focusedComponent,
- KeyEvent e);
-
- /**
- * Called by the AWT to notify the KeyboardFocusManager that it should
- * delay dispatching of KeyEvents until the specified Component becomes
- * the focus owner. If client code requests a focus change, and the AWT
- * determines that this request might be granted by the native windowing
- * system, then the AWT will call this method. It is the responsibility of
- * the KeyboardFocusManager to delay dispatching of KeyEvents with
- * timestamps later than the specified time stamp until the specified
- * Component receives a FOCUS_GAINED event, or the AWT cancels the delay
- * request by invoking <code>dequeueKeyEvents</code> or
- * <code>discardKeyEvents</code>.
- *
- * @param after timestamp of current event, or the current, system time if
- * the current event has no timestamp, or the AWT cannot determine
- * which event is currently being handled
- * @param untilFocused Component which should receive a FOCUS_GAINED event
- * before any pending KeyEvents
- * @see #dequeueKeyEvents
- * @see #discardKeyEvents
- */
- protected abstract void enqueueKeyEvents(long after,
- Component untilFocused);
-
- /**
- * Called by the AWT to notify the KeyboardFocusManager that it should
- * cancel delayed dispatching of KeyEvents. All KeyEvents which were
- * enqueued because of a call to <code>enqueueKeyEvents</code> with the
- * same timestamp and Component should be released for normal dispatching
- * to the current focus owner. If the given timestamp is less than zero,
- * the outstanding enqueue request for the given Component with the <b>
- * oldest</b> timestamp (if any) should be cancelled.
- *
- * @param after the timestamp specified in the call to
- * <code>enqueueKeyEvents</code>, or any value < 0
- * @param untilFocused the Component specified in the call to
- * <code>enqueueKeyEvents</code>
- * @see #enqueueKeyEvents
- * @see #discardKeyEvents
- */
- protected abstract void dequeueKeyEvents(long after,
- Component untilFocused);
-
- /**
- * Called by the AWT to notify the KeyboardFocusManager that it should
- * cancel delayed dispatching of KeyEvents. All KeyEvents which were
- * enqueued because of one or more calls to <code>enqueueKeyEvents</code>
- * with the same Component should be discarded.
- *
- * @param comp the Component specified in one or more calls to
- * <code>enqueueKeyEvents</code>
- * @see #enqueueKeyEvents
- * @see #dequeueKeyEvents
- */
- protected abstract void discardKeyEvents(Component comp);
-
- /**
- * Focuses the Component after aComponent, typically based on a
- * FocusTraversalPolicy.
- *
- * @param aComponent the Component that is the basis for the focus
- * traversal operation
- * @see FocusTraversalPolicy
- */
- public abstract void focusNextComponent(Component aComponent);
-
- /**
- * Focuses the Component before aComponent, typically based on a
- * FocusTraversalPolicy.
- *
- * @param aComponent the Component that is the basis for the focus
- * traversal operation
- * @see FocusTraversalPolicy
- */
- public abstract void focusPreviousComponent(Component aComponent);
-
- /**
- * Moves the focus up one focus traversal cycle. Typically, the focus owner
- * is set to aComponent's focus cycle root, and the current focus cycle
- * root is set to the new focus owner's focus cycle root. If, however,
- * aComponent's focus cycle root is a Window, then typically the focus
- * owner is set to the Window's default Component to focus, and the current
- * focus cycle root is unchanged.
- *
- * @param aComponent the Component that is the basis for the focus
- * traversal operation
- */
- public abstract void upFocusCycle(Component aComponent);
-
- /**
- * Moves the focus down one focus traversal cycle. Typically, if
- * aContainer is a focus cycle root, then the focus owner is set to
- * aContainer's default Component to focus, and the current focus cycle
- * root is set to aContainer. If aContainer is not a focus cycle root, then
- * no focus traversal operation occurs.
- *
- * @param aContainer the Container that is the basis for the focus
- * traversal operation
- */
- public abstract void downFocusCycle(Container aContainer);
-
- /**
- * Focuses the Component after the current focus owner.
- */
- public final void focusNextComponent() {
- Component focusOwner = getFocusOwner();
- if (focusOwner != null) {
- focusNextComponent(focusOwner);
- }
- }
-
- /**
- * Focuses the Component before the current focus owner.
- */
- public final void focusPreviousComponent() {
- Component focusOwner = getFocusOwner();
- if (focusOwner != null) {
- focusPreviousComponent(focusOwner);
- }
- }
-
- /**
- * Moves the focus up one focus traversal cycle from the current focus
- * owner. Typically, the new focus owner is set to the current focus
- * owner's focus cycle root, and the current focus cycle root is set to the
- * new focus owner's focus cycle root. If, however, the current focus
- * owner's focus cycle root is a Window, then typically the focus owner is
- * set to the focus cycle root's default Component to focus, and the
- * current focus cycle root is unchanged.
- */
- public final void upFocusCycle() {
- Component focusOwner = getFocusOwner();
- if (focusOwner != null) {
- upFocusCycle(focusOwner);
- }
- }
-
- /**
- * Moves the focus down one focus traversal cycle from the current focus
- * owner, if and only if the current focus owner is a Container that is a
- * focus cycle root. Typically, the focus owner is set to the current focus
- * owner's default Component to focus, and the current focus cycle root is
- * set to the current focus owner. If the current focus owner is not a
- * Container that is a focus cycle root, then no focus traversal operation
- * occurs.
- */
- public final void downFocusCycle() {
- Component focusOwner = getFocusOwner();
- if (focusOwner instanceof Container) {
- downFocusCycle((Container)focusOwner);
- }
- }
-
- /**
- * Dumps the list of focus requests to stderr
- */
- void dumpRequests() {
- System.err.println(">>> Requests dump, time: " + System.currentTimeMillis());
- synchronized (heavyweightRequests) {
- Iterator iter = heavyweightRequests.iterator();
- while (iter.hasNext()) {
- HeavyweightFocusRequest req = (HeavyweightFocusRequest)iter.next();
- System.err.println(">>> Req: " + req);
- }
- }
- System.err.println("");
- }
-
- private static final class LightweightFocusRequest {
- final Component component;
- final boolean temporary;
-
- LightweightFocusRequest(Component component, boolean temporary) {
- this.component = component;
- this.temporary = temporary;
- }
- public String toString() {
- return "LightweightFocusRequest[component=" + component +
- ",temporary=" + temporary + "]";
- }
- }
-
- private static final class HeavyweightFocusRequest {
- final Component heavyweight;
- final LinkedList lightweightRequests;
-
- static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
- new HeavyweightFocusRequest();
-
- private HeavyweightFocusRequest() {
- heavyweight = null;
- lightweightRequests = null;
- }
-
- HeavyweightFocusRequest(Component heavyweight, Component descendant,
- boolean temporary) {
- if (dbg.on) {
- dbg.assertion(heavyweight != null);
- }
-
- this.heavyweight = heavyweight;
- this.lightweightRequests = new LinkedList();
- addLightweightRequest(descendant, temporary);
- }
- boolean addLightweightRequest(Component descendant,
- boolean temporary) {
- if (dbg.on) {
- dbg.assertion(this != HeavyweightFocusRequest.
- CLEAR_GLOBAL_FOCUS_OWNER);
- dbg.assertion(descendant != null);
- }
-
- Component lastDescendant = ((lightweightRequests.size() > 0)
- ? ((LightweightFocusRequest)lightweightRequests.getLast()).
- component
- : null);
-
- if (descendant != lastDescendant) {
- // Not a duplicate request
- lightweightRequests.add
- (new LightweightFocusRequest(descendant, temporary));
- return true;
- } else {
- return false;
- }
- }
-
- LightweightFocusRequest getFirstLightweightRequest() {
- if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
- return null;
- }
- return (LightweightFocusRequest)lightweightRequests.getFirst();
- }
- public String toString() {
- boolean first = true;
- String str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
- ",lightweightRequests=";
- if (lightweightRequests == null) {
- str += null;
- } else {
- str += "[";
- for (Iterator iter = lightweightRequests.iterator();
- iter.hasNext(); )
- {
- if (first) {
- first = false;
- } else {
- str += ",";
- }
- str += iter.next();
- }
- str += "]";
- }
- str += "]";
- return str;
- }
- }
-
- /*
- * heavyweightRequests is used as a monitor for synchronized changes of
- * currentLightweightRequests, clearingCurrentLightweightRequests and
- * newFocusOwner.
- */
- private static LinkedList heavyweightRequests = new LinkedList();
- private static LinkedList currentLightweightRequests;
- private static boolean clearingCurrentLightweightRequests;
- private static Component newFocusOwner = null;
-
- static final int SNFH_FAILURE = 0;
- static final int SNFH_SUCCESS_HANDLED = 1;
- static final int SNFH_SUCCESS_PROCEED = 2;
-
- static boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant,
- boolean temporary, boolean focusedWindowChangeAllowed,
- long time) {
- Window parentWindow = Component.getContainingWindow(heavyweight);
- if (parentWindow == null || !parentWindow.syncLWRequests) {
- return false;
- }
- if (descendant == null) {
- // Focus transfers from a lightweight child back to the
- // heavyweight Container should be treated like lightweight
- // focus transfers.
- descendant = heavyweight;
- }
-
- KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
-
- FocusEvent currentFocusOwnerEvent = null;
- FocusEvent newFocusOwnerEvent = null;
- Component currentFocusOwner = manager.getGlobalFocusOwner();
-
- synchronized (heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getLast() : null);
- if (hwFocusRequest == null &&
- heavyweight == manager.getNativeFocusOwner())
- {
-
- if (descendant == currentFocusOwner) {
- // Redundant request.
- return true;
- }
-
- // 'heavyweight' owns the native focus and there are no pending
- // requests. 'heavyweight' must be a Container and
- // 'descendant' must not be the focus owner. Otherwise,
- // we would never have gotten this far.
- manager.enqueueKeyEvents(time, descendant);
-
- hwFocusRequest =
- new HeavyweightFocusRequest(heavyweight, descendant,
- temporary);
- heavyweightRequests.add(hwFocusRequest);
-
- if (currentFocusOwner != null) {
- currentFocusOwnerEvent =
- new FocusEvent(currentFocusOwner,
- FocusEvent.FOCUS_LOST,
- temporary, descendant);
- }
- newFocusOwnerEvent =
- new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
- temporary, currentFocusOwner);
- }
- }
- boolean result = false;
- synchronized(Component.LOCK) {
- if (currentFocusOwnerEvent != null && currentFocusOwner != null) {
- ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
- currentFocusOwner.dispatchEvent(currentFocusOwnerEvent);
- result = true;
- }
- if (newFocusOwnerEvent != null && descendant != null) {
- ((AWTEvent) newFocusOwnerEvent).isPosted = true;
- descendant.dispatchEvent(newFocusOwnerEvent);
- result = true;
- }
- }
- return result;
- }
-
- /**
- * Indicates whether the native implementation should proceed with a
- * pending, native focus request. Before changing the focus at the native
- * level, the AWT implementation should always call this function for
- * permission. This function will reject the request if a duplicate request
- * preceded it, or if the specified heavyweight Component already owns the
- * focus and no native focus changes are pending. Otherwise, the request
- * will be approved and the focus request list will be updated so that,
- * if necessary, the proper descendant will be focused when the
- * corresponding FOCUS_GAINED event on the heavyweight is received.
- *
- * An implementation must ensure that calls to this method and native
- * focus changes are atomic. If this is not guaranteed, then the ordering
- * of the focus request list may be incorrect, leading to errors in the
- * type-ahead mechanism. Typically this is accomplished by only calling
- * this function from the native event pumping thread, or by holding a
- * global, native lock during invocation.
- */
- static int shouldNativelyFocusHeavyweight
- (Component heavyweight, Component descendant, boolean temporary,
- boolean focusedWindowChangeAllowed, long time)
- {
- if (dbg.on) {
- dbg.assertion(heavyweight != null);
- dbg.assertion(time != 0);
- }
-
- if (descendant == null) {
- // Focus transfers from a lightweight child back to the
- // heavyweight Container should be treated like lightweight
- // focus transfers.
- descendant = heavyweight;
- }
-
- KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(descendant));
- KeyboardFocusManager thisManager = getCurrentKeyboardFocusManager();
- Component currentFocusOwner = thisManager.getGlobalFocusOwner();
- if (focusLog.isLoggable(Level.FINER)) {
- focusLog.finer("SNFH for " + descendant + " in " + heavyweight);
- }
- if (focusLog.isLoggable(Level.FINEST)) {
- focusLog.finest("0. Current focus owner " + currentFocusOwner);
- focusLog.finest("0. Native focus owner " + thisManager.getNativeFocusOwner());
- }
- synchronized (heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getLast() : null);
- if (focusLog.isLoggable(Level.FINEST)) {
- focusLog.finest("Request " + hwFocusRequest);
- }
- if (hwFocusRequest == null &&
- heavyweight == thisManager.getNativeFocusOwner())
- {
- if (descendant == currentFocusOwner) {
- // Redundant request.
- if (focusLog.isLoggable(Level.FINEST)) focusLog.finest("1. SNFH_FAILURE for " + descendant);
- return SNFH_FAILURE;
- }
-
- // 'heavyweight' owns the native focus and there are no pending
- // requests. 'heavyweight' must be a Container and
- // 'descendant' must not be the focus owner. Otherwise,
- // we would never have gotten this far.
- manager.enqueueKeyEvents(time, descendant);
-
- hwFocusRequest =
- new HeavyweightFocusRequest(heavyweight, descendant,
- temporary);
- heavyweightRequests.add(hwFocusRequest);
-
- if (currentFocusOwner != null) {
- FocusEvent currentFocusOwnerEvent =
- new FocusEvent(currentFocusOwner,
- FocusEvent.FOCUS_LOST,
- temporary, descendant);
- SunToolkit.postEvent(currentFocusOwner.appContext,
- currentFocusOwnerEvent);
- }
- FocusEvent newFocusOwnerEvent =
- new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
- temporary, currentFocusOwner);
- SunToolkit.postEvent(descendant.appContext,
- newFocusOwnerEvent);
-
- if (focusLog.isLoggable(Level.FINEST)) focusLog.finest("2. SNFH_HANDLED for " + descendant);
- return SNFH_SUCCESS_HANDLED;
- } else if (hwFocusRequest != null &&
- hwFocusRequest.heavyweight == heavyweight) {
- // 'heavyweight' doesn't have the native focus right now, but
- // if all pending requests were completed, it would. Add
- // descendant to the heavyweight's list of pending
- // lightweight focus transfers.
- if (hwFocusRequest.addLightweightRequest(descendant,
- temporary)) {
- manager.enqueueKeyEvents(time, descendant);
- }
-
- if (focusLog.isLoggable(Level.FINEST)) focusLog.finest("3. SNFH_HANDLED for lightweight " + descendant + " in " + heavyweight);
- return SNFH_SUCCESS_HANDLED;
- } else {
- if (!focusedWindowChangeAllowed) {
- // For purposes of computing oldFocusedWindow, we should
- // look at the second to last HeavyweightFocusRequest on
- // the queue iff the last HeavyweightFocusRequest is
- // CLEAR_GLOBAL_FOCUS_OWNER. If there is no second to last
- // HeavyweightFocusRequest, null is an acceptable value.
- if (hwFocusRequest ==
- HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
- {
- int size = heavyweightRequests.size();
- hwFocusRequest = (HeavyweightFocusRequest)((size >= 2)
- ? heavyweightRequests.get(size - 2)
- : null);
- }
- if (focusedWindowChanged(heavyweight,
- (hwFocusRequest != null)
- ? hwFocusRequest.heavyweight
- : thisManager.getNativeFocusedWindow())) {
- if (focusLog.isLoggable(Level.FINEST)) focusLog.finest("4. SNFH_FAILURE for " + descendant);
- return SNFH_FAILURE;
- }
- }
-
- manager.enqueueKeyEvents(time, descendant);
- heavyweightRequests.add
- (new HeavyweightFocusRequest(heavyweight, descendant,
- temporary));
- if (focusLog.isLoggable(Level.FINEST)) focusLog.finest("5. SNFH_PROCEED for " + descendant);
- return SNFH_SUCCESS_PROCEED;
- }
- }
- }
- static void heavyweightButtonDown(Component heavyweight, long time) {
- heavyweightButtonDown(heavyweight, time, false);
- }
- static void heavyweightButtonDown(Component heavyweight, long time, boolean acceptDuplicates) {
- if (dbg.on) {
- dbg.assertion(heavyweight != null);
- dbg.assertion(time != 0);
- }
- KeyboardFocusManager manager = getCurrentKeyboardFocusManager(SunToolkit.targetToAppContext(heavyweight));
-
- synchronized (heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getLast() : null);
- Component currentNativeFocusOwner = (hwFocusRequest == null)
- ? manager.getNativeFocusOwner()
- : hwFocusRequest.heavyweight;
-
- // Behavior for all use cases:
- // 1. Heavyweight leaf Components (e.g., Button, Checkbox, Choice,
- // List, TextComponent, Canvas) that respond to button down.
- //
- // Native platform will generate a FOCUS_GAINED if and only if
- // the Component is not the focus owner (or, will not be the
- // focus owner when all outstanding focus requests are
- // processed).
- //
- // 2. Panel with no descendants.
- //
- // Same as (1).
- //
- // 3. Panel with at least one heavyweight descendant.
- //
- // This function should NOT be called for this case!
- //
- // 4. Panel with only lightweight descendants.
- //
- // Native platform will generate a FOCUS_GAINED if and only if
- // neither the Panel, nor any of its recursive, lightweight
- // descendants, is the focus owner. However, we want a
- // requestFocus() for any lightweight descendant to win out over
- // the focus request for the Panel. To accomplish this, we
- // differ from the algorithm for shouldNativelyFocusHeavyweight
- // as follows:
- // a. If the requestFocus() for a lightweight descendant has
- // been fully handled by the time this function is invoked,
- // then 'hwFocusRequest' will be null and 'heavyweight'
- // will be the native focus owner. Do *not* synthesize a
- // focus transfer to the Panel.
- // b. If the requestFocus() for a lightweight descendant has
- // been recorded, but not handled, then 'hwFocusRequest'
- // will be non-null and 'hwFocusRequest.heavyweight' will
- // equal 'heavyweight'. Do *not* append 'heavyweight' to
- // hwFocusRequest.lightweightRequests.
- // c. If the requestFocus() for a lightweight descendant is
- // yet to be made, then post a new HeavyweightFocusRequest.
- // If no lightweight descendant ever requests focus, then
- // the Panel will get focus. If some descendant does, then
- // the descendant will get focus by either a synthetic
- // focus transfer, or a lightweightRequests focus transfer.
-
- if (acceptDuplicates || heavyweight != currentNativeFocusOwner) {
- getCurrentKeyboardFocusManager
- (SunToolkit.targetToAppContext(heavyweight)).
- enqueueKeyEvents(time, heavyweight);
- heavyweightRequests.add
- (new HeavyweightFocusRequest(heavyweight, heavyweight,
- false));
- }
- }
- }
- /**
- * Returns the Window which will be active after processing this request,
- * or null if this is a duplicate request. The active Window is useful
- * because some native platforms do not support setting the native focus
- * owner to null. On these platforms, the obvious choice is to set the
- * focus owner to the focus proxy of the active Window.
- */
- static Window markClearGlobalFocusOwner() {
- synchronized (heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getLast() : null);
- if (hwFocusRequest ==
- HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
- {
- // duplicate request
- return null;
- }
-
- KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
- heavyweightRequests.add
- (HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
-
- Component activeWindow = ((hwFocusRequest != null)
- ? Component.getContainingWindow(hwFocusRequest.heavyweight)
- : manager.getNativeFocusedWindow());
- while (activeWindow != null &&
- !((activeWindow instanceof Frame) ||
- (activeWindow instanceof Dialog)))
- {
- activeWindow = activeWindow.getParent();
- }
-
- return (Window)activeWindow;
- }
- }
- Component getCurrentWaitingRequest(Component parent) {
- synchronized (heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getFirst() : null);
- if (hwFocusRequest != null) {
- if (hwFocusRequest.heavyweight == parent) {
- LightweightFocusRequest lwFocusRequest =
- (LightweightFocusRequest)hwFocusRequest.
- lightweightRequests.getFirst();
- if (lwFocusRequest != null) {
- return lwFocusRequest.component;
- }
- }
- }
- }
- return null;
- }
-
- static void processCurrentLightweightRequests() {
- KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
- LinkedList localLightweightRequests = null;
-
- synchronized(heavyweightRequests) {
- if (currentLightweightRequests != null) {
- clearingCurrentLightweightRequests = true;
- localLightweightRequests = currentLightweightRequests;
- currentLightweightRequests = null;
- } else {
- // do nothing
- return;
- }
- }
-
- try {
- if (localLightweightRequests != null) {
- for (Iterator iter = localLightweightRequests.iterator();
- iter.hasNext(); )
- {
- Component currentFocusOwner = manager.
- getGlobalFocusOwner();
- if (currentFocusOwner == null) {
- // If this ever happens, a focus change has been
- // rejected. Stop generating more focus changes.
- break;
- }
-
- LightweightFocusRequest lwFocusRequest =
- (LightweightFocusRequest)iter.next();
- FocusEvent currentFocusOwnerEvent =
- new FocusEvent(currentFocusOwner,
- FocusEvent.FOCUS_LOST,
- lwFocusRequest.temporary,
- lwFocusRequest.component);
- FocusEvent newFocusOwnerEvent =
- new FocusEvent(lwFocusRequest.component,
- FocusEvent.FOCUS_GAINED,
- lwFocusRequest.temporary,
- currentFocusOwner);
-
- ((AWTEvent) currentFocusOwnerEvent).isPosted = true;
- currentFocusOwner.dispatchEvent(currentFocusOwnerEvent);
- ((AWTEvent) newFocusOwnerEvent).isPosted = true;
- lwFocusRequest.component.
- dispatchEvent(newFocusOwnerEvent);
- }
- }
- } finally {
- clearingCurrentLightweightRequests = false;
- localLightweightRequests = null;
- }
- }
-
- static FocusEvent retargetUnexpectedFocusEvent(FocusEvent fe) {
- synchronized (heavyweightRequests) {
- // Any other case represents a failure condition which we did
- // not expect. We need to clearFocusRequestList() and patch up
- // the event as best as possible.
-
- if (removeFirstRequest()) {
- return (FocusEvent)retargetFocusEvent(fe);
- }
-
- Component source = fe.getComponent();
- Component opposite = fe.getOppositeComponent();
- boolean temporary = false;
- if (fe.getID() == FocusEvent.FOCUS_LOST &&
- (opposite == null || isTemporary(opposite, source)))
- {
- temporary = true;
- }
- return new FocusEvent(source, fe.getID(), temporary, opposite);
- }
- }
-
- static FocusEvent retargetFocusGained(FocusEvent fe) {
- assert (fe.getID() == FocusEvent.FOCUS_GAINED);
-
- Component currentFocusOwner = getCurrentKeyboardFocusManager().
- getGlobalFocusOwner();
- Component source = fe.getComponent();
- Component opposite = fe.getOppositeComponent();
- Component nativeSource = getHeavyweight(source);
-
- synchronized (heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getFirst() : null);
-
- if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
- {
- return retargetUnexpectedFocusEvent(fe);
- }
-
- if (source != null && nativeSource == null && hwFocusRequest != null) {
- // if source w/o peer and
- // if source is equal to first lightweight
- // then we should correct source and nativeSource
- if (source == hwFocusRequest.getFirstLightweightRequest().component)
- {
- source = hwFocusRequest.heavyweight;
- nativeSource = source; // source is heavuweight itself
- }
- }
- if (hwFocusRequest != null &&
- nativeSource == hwFocusRequest.heavyweight)
- {
- // Focus change as a result of a known call to requestFocus(),
- // or known click on a peer focusable heavyweight Component.
-
- heavyweightRequests.removeFirst();
-
- LightweightFocusRequest lwFocusRequest =
- (LightweightFocusRequest)hwFocusRequest.
- lightweightRequests.removeFirst();
-
- Component newSource = lwFocusRequest.component;
- if (currentFocusOwner != null) {
- /*
- * Since we receive FOCUS_GAINED when current focus
- * owner is not null, correcponding FOCUS_LOST is supposed
- * to be lost. And so, we keep new focus owner
- * to determine synthetic FOCUS_LOST event which will be
- * generated by KeyboardFocusManager for this FOCUS_GAINED.
- *
- * This code based on knowledge of
- * DefaultKeyboardFocusManager's implementation and might
- * be not applicable for another KeyboardFocusManager.
- */
- newFocusOwner = newSource;
- }
-
- boolean temporary = (opposite == null ||
- isTemporary(newSource, opposite))
- ? false
- : lwFocusRequest.temporary;
-
- if (hwFocusRequest.lightweightRequests.size() > 0) {
- currentLightweightRequests =
- hwFocusRequest.lightweightRequests;
- EventQueue.invokeLater(new Runnable() {
- public void run() {
- processCurrentLightweightRequests();
- }
- });
- }
-
- // 'opposite' will be fixed by
- // DefaultKeyboardFocusManager.realOppositeComponent
- return new FocusEvent(newSource,
- FocusEvent.FOCUS_GAINED, temporary,
- opposite);
- }
-
- if (currentFocusOwner != null
- && currentFocusOwner.getContainingWindow() == source
- && (hwFocusRequest == null || source != hwFocusRequest.heavyweight))
- {
- // Special case for FOCUS_GAINED in top-levels
- // If it arrives as the result of activation we should skip it
- // This event will not have appropriate request record and
- // on arrival there will be already some focus owner set.
- return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false, null);
- }
-
- return retargetUnexpectedFocusEvent(fe);
- } // end synchronized(heavyweightRequests)
- }
-
- static FocusEvent retargetFocusLost(FocusEvent fe) {
- assert (fe.getID() == FocusEvent.FOCUS_LOST);
-
- Component currentFocusOwner = getCurrentKeyboardFocusManager().
- getGlobalFocusOwner();
- Component opposite = fe.getOppositeComponent();
- Component nativeOpposite = getHeavyweight(opposite);
-
- synchronized (heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getFirst() : null);
-
- if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
- {
- if (currentFocusOwner != null) {
- // Call to KeyboardFocusManager.clearGlobalFocusOwner()
- heavyweightRequests.removeFirst();
- return new FocusEvent(currentFocusOwner,
- FocusEvent.FOCUS_LOST, false, null);
- }
-
- // Otherwise, fall through to failure case below
-
- } else if (opposite == null)
- {
- // Focus leaving application
- if (currentFocusOwner != null) {
- return new FocusEvent(currentFocusOwner,
- FocusEvent.FOCUS_LOST,
- true, null);
- } else {
- return fe;
- }
- } else if (hwFocusRequest != null &&
- (nativeOpposite == hwFocusRequest.heavyweight ||
- nativeOpposite == null &&
- opposite == hwFocusRequest.getFirstLightweightRequest().component))
- {
- if (currentFocusOwner == null) {
- return fe;
- }
- // Focus change as a result of a known call to requestFocus(),
- // or click on a peer focusable heavyweight Component.
-
- // If a focus transfer is made across top-levels, then the
- // FOCUS_LOST event is always temporary, and the FOCUS_GAINED
- // event is always permanent. Otherwise, the stored temporary
- // value is honored.
-
- LightweightFocusRequest lwFocusRequest =
- (LightweightFocusRequest)hwFocusRequest.
- lightweightRequests.getFirst();
-
- boolean temporary = isTemporary(opposite,
- currentFocusOwner)
- ? true
- : lwFocusRequest.temporary;
-
- return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
- temporary, lwFocusRequest.component);
- } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
- // If top-level changed there might be no focus request in a list
- // But we know the opposite, we now it is temporary - dispatch the event.
- if (!fe.isTemporary() && currentFocusOwner != null) {
- // Create copy of the event with only difference in temporary parameter.
- fe = new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
- true, opposite);
- }
- return fe;
- }
-
- return retargetUnexpectedFocusEvent(fe);
- } // end synchronized(heavyweightRequests)
- }
-
- static AWTEvent retargetFocusEvent(AWTEvent event) {
- if (clearingCurrentLightweightRequests) {
- return event;
- }
-
- KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
- if (focusLog.isLoggable(Level.FINE)) {
- if (event instanceof FocusEvent || event instanceof WindowEvent) {
- focusLog.log(Level.FINE, ">>> {0}", new Object[] {event});
- }
- if (focusLog.isLoggable(Level.FINER) && event instanceof KeyEvent) {
- focusLog.log(Level.FINER, " focus owner is {0}", new Object[] {manager.getGlobalFocusOwner()});
- focusLog.log(Level.FINER, ">>> {0}", new Object[] {event});
- }
- }
-
- synchronized(heavyweightRequests) {
- /*
- * This code handles FOCUS_LOST event which is generated by
- * DefaultKeyboardFocusManager for FOCUS_GAINED.
- *
- * This code based on knowledge of DefaultKeyboardFocusManager's
- * implementation and might be not applicable for another
- * KeyboardFocusManager.
- *
- * Fix for 4472032
- */
- if (newFocusOwner != null &&
- event.getID() == FocusEvent.FOCUS_LOST)
- {
- FocusEvent fe = (FocusEvent)event;
-
- if (manager.getGlobalFocusOwner() == fe.getComponent() &&
- fe.getOppositeComponent() == newFocusOwner)
- {
- newFocusOwner = null;
- return event;
- }
- }
- }
-
- processCurrentLightweightRequests();
-
- switch (event.getID()) {
- case FocusEvent.FOCUS_GAINED: {
- event = retargetFocusGained((FocusEvent)event);
- break;
- }
- case FocusEvent.FOCUS_LOST: {
- event = retargetFocusLost((FocusEvent)event);
- break;
- }
- default:
- /* do nothing */
- }
- return event;
- }
-
- /**
- * Clears markers queue
- * This method is not intended to be overridden by KFM's.
- * Only DefaultKeyboardFocusManager can implement it.
- * @since 1.5
- */
- void clearMarkers() {
- }
-
- static boolean removeFirstRequest() {
- KeyboardFocusManager manager =
- KeyboardFocusManager.getCurrentKeyboardFocusManager();
-
- synchronized(heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
-
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getFirst() : null);
- if (hwFocusRequest != null) {
- heavyweightRequests.removeFirst();
- if (hwFocusRequest.lightweightRequests != null) {
- for (Iterator lwIter = hwFocusRequest.lightweightRequests.
- iterator();
- lwIter.hasNext(); )
- {
- manager.dequeueKeyEvents
- (-1, ((LightweightFocusRequest)lwIter.next()).
- component);
- }
- }
- }
- // Fix for 4799136 - clear type-ahead markers if requests queue is empty
- // We do it here because this method is called only when problems happen
- if (heavyweightRequests.size() == 0) {
- manager.clearMarkers();
- }
- return (heavyweightRequests.size() > 0);
- }
- }
- static void removeLastFocusRequest(Component heavyweight) {
- if (dbg.on) {
- dbg.assertion(heavyweight != null);
- }
-
- KeyboardFocusManager manager =
- KeyboardFocusManager.getCurrentKeyboardFocusManager();
- synchronized(heavyweightRequests) {
- HeavyweightFocusRequest hwFocusRequest = (HeavyweightFocusRequest)
- ((heavyweightRequests.size() > 0)
- ? heavyweightRequests.getLast() : null);
- if (hwFocusRequest != null &&
- hwFocusRequest.heavyweight == heavyweight) {
- heavyweightRequests.removeLast();
- }
- // Fix for 4799136 - clear type-ahead markers if requests queue is empty
- // We do it here because this method is called only when problems happen
- if (heavyweightRequests.size() == 0) {
- manager.clearMarkers();
- }
- }
- }
-
- private static boolean focusedWindowChanged(Component to, Component from) {
- Window wto = Component.getContainingWindow(to);
- Window wfrom = Component.getContainingWindow(from);
- if (wto == null && wfrom == null) {
- return true;
- }
- if (wto == null) {
- return true;
- }
- if (wfrom == null) {
- return true;
- }
- return (wto != wfrom);
- }
-
- private static boolean isTemporary(Component to, Component from) {
- Window wto = Component.getContainingWindow(to);
- Window wfrom = Component.getContainingWindow(from);
- if (wto == null && wfrom == null) {
- return false;
- }
- if (wto == null) {
- return true;
- }
- if (wfrom == null) {
- return false;
- }
- return (wto != wfrom);
- }
-
- private static Component getHeavyweight(Component comp) {
- if (comp == null || comp.getPeer() == null) {
- return null;
- } else if (comp.getPeer() instanceof LightweightPeer) {
- return comp.getNativeContainer();
- } else {
- return comp;
- }
- }
-
- static Field proxyActive;
- // Accessor to private field isProxyActive of KeyEvent
- private static boolean isProxyActiveImpl(KeyEvent e) {
- if (proxyActive == null) {
- proxyActive = (Field) AccessController.doPrivileged(new PrivilegedAction() {
- public Object run() {
- Field field = null;
- try {
- field = KeyEvent.class.getDeclaredField("isProxyActive");
- if (field != null) {
- field.setAccessible(true);
- }
- } catch (NoSuchFieldException nsf) {
- assert(false);
- }
- return field;
- }
- });
- }
-
- try {
- return proxyActive.getBoolean(e);
- } catch (IllegalAccessException iae) {
- assert(false);
- }
- return false;
- }
-
- // Returns the value of this KeyEvent's field isProxyActive
- static boolean isProxyActive(KeyEvent e) {
- if (!GraphicsEnvironment.isHeadless()) {
- return isProxyActiveImpl(e);
- } else {
- return false;
- }
- }
- }