|
AWTKeyStroke
s
* for the specified operation; the <code>Set
* will be unmodifiable, and may be empty; <code>null
* 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.
*
* @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
* and if the calling thread does not have "replaceKeyboardFocusManager"
* permission
*/
protected Container getGlobalCurrentFocusCycleRoot()
throws SecurityException
{
synchronized (KeyboardFocusManager.class) {
checkKFMSecurity();
return currentFocusCycleRoot;
}
}
/**
* 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>
* If a SecurityManager is installed, the calling thread must be granted
* the "replaceKeyboardFocusManager" AWTPermission. If this permission is
* not granted, this method will throw a SecurityException, and the current
* focus cycle root will not be changed.
* <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
* @throws SecurityException if the calling thread does not have
* "replaceKeyboardFocusManager" permission
* @beaninfo
* bound: true
*/
public void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot)
throws SecurityException
{
checkReplaceKFMPermission();
Container oldFocusCycleRoot;
synchronized (KeyboardFocusManager.class) {
oldFocusCycleRoot = getCurrentFocusCycleRoot();
currentFocusCycleRoot = newFocusCycleRoot;
}
firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
newFocusCycleRoot);
}
void setGlobalCurrentFocusCycleRootPriv(final Container newFocusCycleRoot) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
setGlobalCurrentFocusCycleRoot(newFocusCycleRoot);
return null;
}
});
}
/**
* 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>the permanent focus owner ("permanentFocusOwner")
* <li>the focused Window ("focusedWindow")
* <li>the active Window ("activeWindow")
* <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")
* </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>PropertyChangeListeners
* 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>the permanent focus owner ("permanentFocusOwner")
* <li>the focused Window ("focusedWindow")
* <li>the active Window ("activeWindow")
* <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")
* </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>PropertyChangeListeners
* associated with the named property.
*
* @return all of the <code>PropertyChangeListeners 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)
{
if (oldValue == newValue) {
return;
}
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>the permanent focus owner ("permanentFocusOwner")
* <li>the focused Window ("focusedWindow")
* <li>the active Window ("activeWindow")
* </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>VetoableChangeListeners
* 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>the permanent focus owner ("permanentFocusOwner")
* <li>the focused Window ("focusedWindow")
* <li>the active Window ("activeWindow")
* </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>VetoableChangeListeners
* associated with the named property.
*
* @return all of the <code>VetoableChangeListeners 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 threw
* <code>PropertyVetoException
*/
protected void fireVetoableChange(String propertyName, Object oldValue,
Object newValue)
throws PropertyVetoException
{
if (oldValue == newValue) {
return;
}
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 from its
* <code>dispatchKeyEvent 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.
* <p>
* In a multithreaded application, {@link KeyEventDispatcher} behaves
* the same as other AWT listeners. See
* <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for more details.
*
* @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.
* <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.
* <p>
* In a multithreaded application, {@link KeyEventDispatcher} behaves
* the same as other AWT listeners. See
* <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for more details.
*
* @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. 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 from its
* <code>postProcessKeyEvent 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.
* <p>
* In a multithreaded application, {@link KeyEventPostProcessor} behaves
* the same as other AWT listeners. See
* <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for more details.
*
* @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 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.
* <p>
* In a multithreaded application, {@link KeyEventPostProcessor} behaves
* the same as other AWT listeners. See
* <a href="doc-files/AWTThreadIssues.html#ListenersThreads"
* >AWT Threading Issues</a> for more details.
*
* @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. 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<Component> 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);
}
}
}
}
/*
* Please be careful changing this method! It is called from
* javax.swing.JComponent.runInputVerifier() using reflection.
*/
static synchronized Component getMostRecentFocusOwner(Window window) {
WeakReference<Component> 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 to prevent the AWT event
* dispatcher from recursively requesting that the KeyboardFocusManager
* dispatch the event again. If this method returns <code>false,
* then the AWT event dispatcher will attempt to dispatch the event itself.
*
* @param e the AWTEvent to be dispatched
* @return <code>true if this method dispatched the event;
* <code>false 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 and client-defined
* KeyEventDispatchers must call <code>redispatchEvent(target, e)
* instead of <code>target.dispatchEvent(e) 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 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>dispatchEvent may try to dispatch the KeyEvent itself, or
* may simply return <code>false. If true
is returned,
* <code>dispatchEvent should return true
as well.
*
* @param e the KeyEvent which the current KeyboardFocusManager has
* requested that this KeyEventDispatcher dispatch
* @return <code>true if the KeyEvent was dispatched;
* <code>false otherwise
* @see #dispatchEvent
*/
public abstract boolean dispatchKeyEvent(KeyEvent e);
/**
* This method will be called by <code>dispatchKeyEvent.
* By default, this method will handle any unconsumed KeyEvents that
* map to an AWT <code>MenuShortcut by consuming the event
* and activating the shortcut.
*
* @param e the KeyEvent to post-process
* @return <code>true 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 or
* <code>discardKeyEvents.
*
* @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 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, or any value < 0
* @param untilFocused the Component specified in the call to
* <code>enqueueKeyEvents
* @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
* with the same Component should be discarded.
*
* @param comp the Component specified in one or more calls to
* <code>enqueueKeyEvents
* @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) {
for (HeavyweightFocusRequest req : heavyweightRequests) {
System.err.println(">>> Req: " + req);
}
}
System.err.println("");
}
private static final class LightweightFocusRequest {
final Component component;
final boolean temporary;
final CausedFocusEvent.Cause cause;
LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
this.component = component;
this.temporary = temporary;
this.cause = cause;
}
public String toString() {
return "LightweightFocusRequest[component=" + component +
",temporary=" + temporary + ", cause=" + cause + "]";
}
}
private static final class HeavyweightFocusRequest {
final Component heavyweight;
final LinkedList<LightweightFocusRequest> lightweightRequests;
static final HeavyweightFocusRequest CLEAR_GLOBAL_FOCUS_OWNER =
new HeavyweightFocusRequest();
private HeavyweightFocusRequest() {
heavyweight = null;
lightweightRequests = null;
}
HeavyweightFocusRequest(Component heavyweight, Component descendant,
boolean temporary, CausedFocusEvent.Cause cause) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (heavyweight == null) {
log.fine("Assertion (heavyweight != null) failed");
}
}
this.heavyweight = heavyweight;
this.lightweightRequests = new LinkedList<LightweightFocusRequest>();
addLightweightRequest(descendant, temporary, cause);
}
boolean addLightweightRequest(Component descendant,
boolean temporary, CausedFocusEvent.Cause cause) {
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
}
if (descendant == null) {
log.fine("Assertion (descendant != null) failed");
}
}
Component lastDescendant = ((lightweightRequests.size() > 0)
? lightweightRequests.getLast().component
: null);
if (descendant != lastDescendant) {
// Not a duplicate request
lightweightRequests.add
(new LightweightFocusRequest(descendant, temporary, cause));
return true;
} else {
return false;
}
}
LightweightFocusRequest getFirstLightweightRequest() {
if (this == CLEAR_GLOBAL_FOCUS_OWNER) {
return null;
}
return lightweightRequests.getFirst();
}
public String toString() {
boolean first = true;
String str = "HeavyweightFocusRequest[heavweight=" + heavyweight +
",lightweightRequests=";
if (lightweightRequests == null) {
str += null;
} else {
str += "[";
for (LightweightFocusRequest lwRequest : lightweightRequests) {
if (first) {
first = false;
} else {
str += ",";
}
str += lwRequest;
}
str += "]";
}
str += "]";
return str;
}
}
/*
* heavyweightRequests is used as a monitor for synchronized changes of
* currentLightweightRequests, clearingCurrentLightweightRequests and
* newFocusOwner.
*/
private static LinkedList<HeavyweightFocusRequest> heavyweightRequests =
new LinkedList<HeavyweightFocusRequest>();
private static LinkedList<LightweightFocusRequest> currentLightweightRequests;
private static boolean clearingCurrentLightweightRequests;
private static boolean allowSyncFocusRequests = true;
private static Component newFocusOwner = null;
private static volatile boolean disableRestoreFocus;
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 = SunToolkit.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 = getLastHWRequest();
if (hwFocusRequest == null &&
heavyweight == manager.getNativeFocusOwner() &&
allowSyncFocusRequests)
{
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, CausedFocusEvent.Cause.UNKNOWN);
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;
final boolean clearing = clearingCurrentLightweightRequests;
Throwable caughtEx = null;
try {
clearingCurrentLightweightRequests = false;
synchronized(Component.LOCK) {
if (currentFocusOwnerEvent != null && currentFocusOwner != null) {
((AWTEvent) currentFocusOwnerEvent).isPosted = true;
caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
result = true;
}
if (newFocusOwnerEvent != null && descendant != null) {
((AWTEvent) newFocusOwnerEvent).isPosted = true;
caughtEx = dispatchAndCatchException(caughtEx, descendant, newFocusOwnerEvent);
result = true;
}
}
} finally {
clearingCurrentLightweightRequests = clearing;
}
if (caughtEx instanceof RuntimeException) {
throw (RuntimeException)caughtEx;
} else if (caughtEx instanceof Error) {
throw (Error)caughtEx;
}
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, CausedFocusEvent.Cause cause)
{
if (log.isLoggable(PlatformLogger.Level.FINE)) {
if (heavyweight == null) {
log.fine("Assertion (heavyweight != null) failed");
}
if (time == 0) {
log.fine("Assertion (time != 0) failed");
}
}
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();
Component nativeFocusOwner = thisManager.getNativeFocusOwner();
Window nativeFocusedWindow = thisManager.getNativeFocusedWindow();
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
focusLog.finer("SNFH for {0} in {1}",
String.valueOf(descendant), String.valueOf(heavyweight));
}
if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
focusLog.finest("0. Current focus owner {0}",
String.valueOf(currentFocusOwner));
focusLog.finest("0. Native focus owner {0}",
String.valueOf(nativeFocusOwner));
focusLog.finest("0. Native focused window {0}",
String.valueOf(nativeFocusedWindow));
}
synchronized (heavyweightRequests) {
HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
focusLog.finest("Request {0}", String.valueOf(hwFocusRequest));
}
if (hwFocusRequest == null &&
heavyweight == nativeFocusOwner &&
heavyweight.getContainingWindow() == nativeFocusedWindow)
{
if (descendant == currentFocusOwner) {
// Redundant request.
if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
focusLog.finest("1. SNFH_FAILURE for {0}",
String.valueOf(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, cause);
heavyweightRequests.add(hwFocusRequest);
if (currentFocusOwner != null) {
FocusEvent currentFocusOwnerEvent =
new CausedFocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST,
temporary, descendant, cause);
// Fix 5028014. Rolled out.
// SunToolkit.postPriorityEvent(currentFocusOwnerEvent);
SunToolkit.postEvent(currentFocusOwner.appContext,
currentFocusOwnerEvent);
}
FocusEvent newFocusOwnerEvent =
new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
temporary, currentFocusOwner, cause);
// Fix 5028014. Rolled out.
// SunToolkit.postPriorityEvent(newFocusOwnerEvent);
SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
if (focusLog.isLoggable(PlatformLogger.Level.FINEST))
focusLog.finest("2. SNFH_HANDLED for {0}", String.valueOf(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, cause)) {
manager.enqueueKeyEvents(time, descendant);
}
if (focusLog.isLoggable(PlatformLogger.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
: nativeFocusedWindow)) {
if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
focusLog.finest("4. SNFH_FAILURE for " + descendant);
}
return SNFH_FAILURE;
}
}
manager.enqueueKeyEvents(time, descendant);
heavyweightRequests.add
(new HeavyweightFocusRequest(heavyweight, descendant,
temporary, cause));
if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
focusLog.finest("5. SNFH_PROCEED for " + descendant);
}
return SNFH_SUCCESS_PROCEED;
}
}
}
/**
* 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() {
// need to call this out of synchronized block to avoid possible deadlock
// see 6454631.
final Component nativeFocusedWindow =
getCurrentKeyboardFocusManager().getNativeFocusedWindow();
synchronized (heavyweightRequests) {
HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
if (hwFocusRequest ==
HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
{
// duplicate request
return null;
}
heavyweightRequests.add
(HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER);
Component activeWindow = ((hwFocusRequest != null)
? SunToolkit.getContainingWindow(hwFocusRequest.heavyweight)
: nativeFocusedWindow);
while (activeWindow != null &&
!((activeWindow instanceof Frame) ||
(activeWindow instanceof Dialog)))
{
activeWindow = activeWindow.getParent_NoClientCode();
}
return (Window) activeWindow;
}
}
Component getCurrentWaitingRequest(Component parent) {
synchronized (heavyweightRequests) {
HeavyweightFocusRequest hwFocusRequest = getFirstHWRequest();
if (hwFocusRequest != null) {
if (hwFocusRequest.heavyweight == parent) {
LightweightFocusRequest lwFocusRequest =
hwFocusRequest.lightweightRequests.getFirst();
if (lwFocusRequest != null) {
return lwFocusRequest.component;
}
}
}
}
return null;
}
static boolean isAutoFocusTransferEnabled() {
synchronized (heavyweightRequests) {
return (heavyweightRequests.size() == 0)
&& !disableRestoreFocus
&& (null == currentLightweightRequests);
}
}
static boolean isAutoFocusTransferEnabledFor(Component comp) {
return isAutoFocusTransferEnabled() && comp.isAutoFocusTransferOnDisposal();
}
/*
* Used to process exceptions in dispatching focus event (in focusLost/focusGained callbacks).
* @param ex previously caught exception that may be processed right here, or null
* @param comp the component to dispatch the event to
* @param event the event to dispatch to the component
*/
static private Throwable dispatchAndCatchException(Throwable ex, Component comp, FocusEvent event) {
Throwable retEx = null;
try {
comp.dispatchEvent(event);
} catch (RuntimeException re) {
retEx = re;
} catch (Error er) {
retEx = er;
}
if (retEx != null) {
if (ex != null) {
handleException(ex);
}
return retEx;
}
return ex;
}
static private void handleException(Throwable ex) {
ex.printStackTrace();
}
static void processCurrentLightweightRequests() {
KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
LinkedList<LightweightFocusRequest> localLightweightRequests = null;
Component globalFocusOwner = manager.getGlobalFocusOwner();
if ((globalFocusOwner != null) &&
(globalFocusOwner.appContext != AppContext.getAppContext()))
{
// The current app context differs from the app context of a focus
// owner (and all pending lightweight requests), so we do nothing
// now and wait for a next event.
return;
}
synchronized(heavyweightRequests) {
if (currentLightweightRequests != null) {
clearingCurrentLightweightRequests = true;
disableRestoreFocus = true;
localLightweightRequests = currentLightweightRequests;
allowSyncFocusRequests = (localLightweightRequests.size() < 2);
currentLightweightRequests = null;
} else {
// do nothing
return;
}
}
Throwable caughtEx = null;
try {
if (localLightweightRequests != null) {
Component lastFocusOwner = null;
Component currentFocusOwner = null;
for (Iterator<KeyboardFocusManager.LightweightFocusRequest> iter = localLightweightRequests.iterator(); iter.hasNext(); ) {
currentFocusOwner = manager.getGlobalFocusOwner();
LightweightFocusRequest lwFocusRequest =
iter.next();
/*
* WARNING: This is based on DKFM's logic solely!
*
* We allow to trigger restoreFocus() in the dispatching process
* only if we have the last request to dispatch. If the last request
* fails, focus will be restored to either the component of the last
* previously succedded request, or to to the focus owner that was
* before this clearing process.
*/
if (!iter.hasNext()) {
disableRestoreFocus = false;
}
FocusEvent currentFocusOwnerEvent = null;
/*
* We're not dispatching FOCUS_LOST while the current focus owner is null.
* But regardless of whether it's null or not, we're clearing ALL the local
* lw requests.
*/
if (currentFocusOwner != null) {
currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST,
lwFocusRequest.temporary,
lwFocusRequest.component, lwFocusRequest.cause);
}
FocusEvent newFocusOwnerEvent =
new CausedFocusEvent(lwFocusRequest.component,
FocusEvent.FOCUS_GAINED,
lwFocusRequest.temporary,
currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
lwFocusRequest.cause);
if (currentFocusOwner != null) {
((AWTEvent) currentFocusOwnerEvent).isPosted = true;
caughtEx = dispatchAndCatchException(caughtEx, currentFocusOwner, currentFocusOwnerEvent);
}
((AWTEvent) newFocusOwnerEvent).isPosted = true;
caughtEx = dispatchAndCatchException(caughtEx, lwFocusRequest.component, newFocusOwnerEvent);
if (manager.getGlobalFocusOwner() == lwFocusRequest.component) {
lastFocusOwner = lwFocusRequest.component;
}
}
}
} finally {
clearingCurrentLightweightRequests = false;
disableRestoreFocus = false;
localLightweightRequests = null;
allowSyncFocusRequests = true;
}
if (caughtEx instanceof RuntimeException) {
throw (RuntimeException)caughtEx;
} else if (caughtEx instanceof Error) {
throw (Error)caughtEx;
}
}
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 CausedFocusEvent(source, fe.getID(), temporary, opposite,
CausedFocusEvent.Cause.NATIVE_SYSTEM);
}
}
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 = getFirstHWRequest();
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 =
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 CausedFocusEvent(newSource,
FocusEvent.FOCUS_GAINED, temporary,
opposite, lwFocusRequest.cause);
}
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 CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
null, CausedFocusEvent.Cause.ACTIVATION);
}
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 = getFirstHWRequest();
if (hwFocusRequest == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER)
{
if (currentFocusOwner != null) {
// Call to KeyboardFocusManager.clearGlobalFocusOwner()
heavyweightRequests.removeFirst();
return new CausedFocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST, false, null,
CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
}
// Otherwise, fall through to failure case below
} else if (opposite == null)
{
// Focus leaving application
if (currentFocusOwner != null) {
return new CausedFocusEvent(currentFocusOwner,
FocusEvent.FOCUS_LOST,
true, null, CausedFocusEvent.Cause.ACTIVATION);
} 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 =
hwFocusRequest.lightweightRequests.getFirst();
boolean temporary = isTemporary(opposite, currentFocusOwner)
? true
: lwFocusRequest.temporary;
return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
temporary, lwFocusRequest.component, lwFocusRequest.cause);
} 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 CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
true, opposite, CausedFocusEvent.Cause.ACTIVATION);
}
return fe;
}
return retargetUnexpectedFocusEvent(fe);
} // end synchronized(heavyweightRequests)
}
static AWTEvent retargetFocusEvent(AWTEvent event) {
if (clearingCurrentLightweightRequests) {
return event;
}
KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
if (event instanceof FocusEvent || event instanceof WindowEvent) {
focusLog.finer(">>> {0}", String.valueOf(event));
}
if (focusLog.isLoggable(PlatformLogger.Level.FINER) && event instanceof KeyEvent) {
focusLog.finer(" focus owner is {0}",
String.valueOf(manager.getGlobalFocusOwner()));
focusLog.finer(">>> {0}", String.valueOf(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 = getFirstHWRequest();
if (hwFocusRequest != null) {
heavyweightRequests.removeFirst();
if (hwFocusRequest.lightweightRequests != null) {
for (Iterator<KeyboardFocusManager.LightweightFocusRequest> lwIter = hwFocusRequest.lightweightRequests.
iterator();
lwIter.hasNext(); )
{
manager.dequeueKeyEvents
(-1, 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 (log.isLoggable(PlatformLogger.Level.FINE)) {
if (heavyweight == null) {
log.fine("Assertion (heavyweight != null) failed");
}
}
KeyboardFocusManager manager =
KeyboardFocusManager.getCurrentKeyboardFocusManager();
synchronized(heavyweightRequests) {
HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
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 = SunToolkit.getContainingWindow(to);
Window wfrom = SunToolkit.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 = SunToolkit.getContainingWindow(to);
Window wfrom = SunToolkit.getContainingWindow(from);
if (wto == null && wfrom == null) {
return false;
}
if (wto == null) {
return true;
}
if (wfrom == null) {
return false;
}
return (wto != wfrom);
}
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 = AccessController.doPrivileged(new PrivilegedAction<Field>() {
public Field 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;
}
}
private static HeavyweightFocusRequest getLastHWRequest() {
synchronized(heavyweightRequests) {
return (heavyweightRequests.size() > 0)
? heavyweightRequests.getLast()
: null;
}
}
private static HeavyweightFocusRequest getFirstHWRequest() {
synchronized(heavyweightRequests) {
return (heavyweightRequests.size() > 0)
? heavyweightRequests.getFirst()
: null;
}
}
private static void checkReplaceKFMPermission()
throws SecurityException
{
SecurityManager security = System.getSecurityManager();
if (security != null) {
if (replaceKeyboardFocusManagerPermission == null) {
replaceKeyboardFocusManagerPermission =
new AWTPermission("replaceKeyboardFocusManager");
}
security.
checkPermission(replaceKeyboardFocusManagerPermission);
}
}
// Checks if this KeyboardFocusManager instance is the current KFM,
// or otherwise checks if the calling thread has "replaceKeyboardFocusManager"
// permission. Here's the reasoning to do so:
//
// A system KFM instance (which is the current KFM by default) may have no
// "replaceKFM" permission when a client code is on the call stack beneath,
// but still it should be able to execute the methods protected by this check
// due to the system KFM is trusted (and so it does like "privileged").
//
// If this KFM instance is not the current KFM but the client code has all
// permissions we can't throw SecurityException because it would contradict
// the security concepts. In this case the trusted client code is responsible
// for calling the secured methods from KFM instance which is not current.
private void checkKFMSecurity()
throws SecurityException
{
if (this != getCurrentKeyboardFocusManager()) {
checkReplaceKFMPermission();
}
}
}
Here is a short list of links related to this Java KeyboardFocusManager.java source code file:
Java example source code file (KeyboardFocusManager.java)
The KeyboardFocusManager.java Java example source code/* * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ 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.KeyboardFocusManagerPeer; import java.awt.peer.LightweightPeer; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.beans.PropertyVetoException; import java.beans.VetoableChangeListener; import java.beans.VetoableChangeSupport; import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Set; import java.util.StringTokenizer; import java.util.WeakHashMap; import sun.util.logging.PlatformLogger; import sun.awt.AppContext; import sun.awt.SunToolkit; import sun.awt.CausedFocusEvent; import sun.awt.KeyboardFocusManagerPeerProvider; import sun.awt.AWTAccessor; /** * 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://docs.oracle.com/javase/tutorial/uiswing/misc/focus.html"> * How to Use the Focus Subsystem</a>, * a section in <em>The Java Tutorial, and the * <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification * for more information. * * @author David Mendenhall * * @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 PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager"); static { /* ensure that the necessary native libraries are loaded */ Toolkit.loadLibraries(); if (!GraphicsEnvironment.isHeadless()) { initIDs(); } AWTAccessor.setKeyboardFocusManagerAccessor( new AWTAccessor.KeyboardFocusManagerAccessor() { public int shouldNativelyFocusHeavyweight(Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) { return KeyboardFocusManager.shouldNativelyFocusHeavyweight( heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause); } public boolean processSynchronousLightweightTransfer(Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time) { return KeyboardFocusManager.processSynchronousLightweightTransfer( heavyweight, descendant, temporary, focusedWindowChangeAllowed, time); } public void removeLastFocusRequest(Component heavyweight) { KeyboardFocusManager.removeLastFocusRequest(heavyweight); } public void setMostRecentFocusOwner(Window window, Component component) { KeyboardFocusManager.setMostRecentFocusOwner(window, component); } public KeyboardFocusManager getCurrentKeyboardFocusManager(AppContext ctx) { return KeyboardFocusManager.getCurrentKeyboardFocusManager(ctx); } public Container getCurrentFocusCycleRoot() { return KeyboardFocusManager.currentFocusCycleRoot; } } ); } transient KeyboardFocusManagerPeer peer; /** * Initialize JNI field and method IDs */ private static native void initIDs(); private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.KeyboardFocusManager"); /** * 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 { checkReplaceKFMPermission(); 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<AWTKeyStroke>[] 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. If no other * KeyEventDispatchers are registered, this field may be null or refer to * a List of length 0. */ private java.util.LinkedList<KeyEventDispatcher> 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. * If no other KeyEventPostProcessors are registered, this field may be * null or refer to a List of length 0. */ private java.util.LinkedList<KeyEventPostProcessor> keyEventPostProcessors; /** * Maps Windows to those Windows' most recent focus owners. */ private static java.util.Map<Window, WeakReference |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.