/*
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program 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.
*
* This program 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 at /legal/license.txt).
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.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.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.SunToolkit;
import sun.awt.AppContext;
public abstract class KeyboardFocusManager implements KeyEventDispatcher,
KeyEventPostProcessor {
public static final int FORWARD_TRAVERSAL_KEYS = 0;
public static final int BACKWARD_TRAVERSAL_KEYS = 1;
public static final int UP_CYCLE_TRAVERSAL_KEYS = 2;
public static final int DOWN_CYCLE_TRAVERSAL_KEYS = 3;
static final int TRAVERSAL_KEY_LENGTH = DOWN_CYCLE_TRAVERSAL_KEYS + 1;
static Component focusOwner;
private static Component permanentFocusOwner;
private static Window focusedWindow;
private static Window activeWindow=null;
private FocusTraversalPolicy defaultPolicy =
new DefaultFocusTraversalPolicy();
private static final String[] defaultFocusTraversalKeyPropertyNames = {
"forwardDefaultFocusTraversalKeys",
"backwardDefaultFocusTraversalKeys",
"upCycleDefaultFocusTraversalKeys",
"downCycleDefaultFocusTraversalKeys"
};
private static final String[] defaultFocusTraversalKeyStrings = {
"TAB,ctrl TAB", "shift TAB,ctrl shift TAB", "", ""
};
private Set[] defaultFocusTraversalKeys = new Set[4];
private static Container currentFocusCycleRoot;
private VetoableChangeSupport vetoableSupport;
private PropertyChangeSupport changeSupport;
private java.util.LinkedList keyEventDispatchers;
private java.util.LinkedList keyEventPostProcessors;
private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
private static final String notPrivileged =
"this KeyboardFocusManager is not installed in the current thread's context";
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 void postSyntheticEvent(AWTEvent e) {
SunToolkit.postEvent(((Component)e.getSource()).appContext, e);
}
static void sendSyntheticEvent(AWTEvent e) {
Component target = (Component)e.getSource();
final AppContext targetAppContext = target.appContext;
final SentEvent se = new SentEvent(e, AppContext.getAppContext());
sendMessage(targetAppContext, se);
}
/**
* Sends a synthetic AWTEvent to a Component. If the Component is in
* the current AppContext, then the event is immediately dispatched.
* If the Component is in a different AppContext, then the event is
* posted to the other AppContext's EventQueue, and this method blocks
* until the event is handled or target AppContext is disposed.
* Returns true if successfuly dispatched event, false if failed
* to dispatch.
*/
static boolean sendMessage(final AppContext targetAppContext,
final SentEvent se) {
AppContext myAppContext = AppContext.getAppContext();
if (myAppContext == targetAppContext) {
se.dispatch();
}
else {
if (targetAppContext.isDisposed()) {
return false;
}
SunToolkit.postEvent(targetAppContext, se);
if (EventQueue.isDispatchThread()) {
EventDispatchThread edt = (EventDispatchThread)
Thread.currentThread();
edt.pumpEvents(SentEvent.ID, new Conditional() {
public boolean evaluate() {
return !se.dispatched &&
!targetAppContext.isDisposed();
}
});
} else {
synchronized (se) {
while (!se.dispatched && !targetAppContext.isDisposed()) {
try {
se.wait(1000);
} catch (InterruptedException ie) {
break;
}
}
}
}
}
return se.dispatched;
}
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;
}
private synchronized static void setCurrentKeyboardFocusManager(
KeyboardFocusManager newManager) throws SecurityException {
AppContext appcontext = AppContext.getAppContext();
if (newManager != null) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
if (replaceKeyboardFocusManagerPermission == null) {
replaceKeyboardFocusManagerPermission =
new AWTPermission("replaceKeyboardFocusManager");
}
security.
checkPermission(replaceKeyboardFocusManagerPermission);
}
appcontext.put(KeyboardFocusManager.class, newManager);
}
else {
appcontext.remove(KeyboardFocusManager.class);
}
}
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);
}
KeyboardFocusManager() {
for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
defaultFocusTraversalKeys[i] = initFocusTraversalKeysSet(defaultFocusTraversalKeyStrings[i],
new HashSet());
}
}
public Component getFocusOwner() {
synchronized (KeyboardFocusManager.class) {
if (focusOwner == null) {
return null;
}
return (focusOwner.appContext == AppContext.getAppContext())
? focusOwner : null;
}
}
Component getGlobalFocusOwner() throws SecurityException {
synchronized (KeyboardFocusManager.class) {
if (this == getCurrentKeyboardFocusManager()) {
return focusOwner;
} else {
throw new SecurityException(notPrivileged);
}
}
}
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) {
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);
}
}
public void clearGlobalFocusOwner() {
if (focusOwner != null) {
FocusEvent synthetic = new FocusEvent(focusOwner,
FocusEvent.FOCUS_LOST,
false, null);
// The DKFM.dispatchEvent() while handling this event will
// set the GlobalFocusOwner, setGlobalPermanentFocusOwner to
// null if required. We "send" an event (instead of "post"ing)
// so that the event is handled by DKFM before we exit this
// method.
sendSyntheticEvent(synthetic);
}
}
public Component getPermanentFocusOwner() {
synchronized (KeyboardFocusManager.class) {
if (permanentFocusOwner == null) {
return null;
}
return (permanentFocusOwner.appContext ==
AppContext.getAppContext()) ? permanentFocusOwner : null;
}
}
Component getGlobalPermanentFocusOwner()
throws SecurityException {
synchronized (KeyboardFocusManager.class) {
if (this == getCurrentKeyboardFocusManager()) {
return permanentFocusOwner;
} else {
throw new SecurityException(notPrivileged);
}
}
}
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) {
return;
}
KeyboardFocusManager.permanentFocusOwner = permanentFocusOwner;
KeyboardFocusManager.setMostRecentFocusOwner(permanentFocusOwner);
shouldFire = true;
}
}
if (shouldFire) {
firePropertyChange("permanentFocusOwner", oldPermanentFocusOwner,
permanentFocusOwner);
}
}
public Window getFocusedWindow() {
synchronized (KeyboardFocusManager.class) {
if (focusedWindow == null) {
return null;
}
return (focusedWindow.appContext == AppContext.getAppContext())
? focusedWindow : null;
}
}
Window getGlobalFocusedWindow() throws SecurityException {
synchronized (KeyboardFocusManager.class) {
if (this == getCurrentKeyboardFocusManager()) {
return focusedWindow;
} else {
throw new SecurityException(notPrivileged);
}
}
}
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) {
return;
}
KeyboardFocusManager.focusedWindow = focusedWindow;
shouldFire = true;
}
}
if (shouldFire) {
firePropertyChange("focusedWindow", oldFocusedWindow, focusedWindow);
}
}
public Window getActiveWindow() {
synchronized (KeyboardFocusManager.class) {
if (activeWindow == null) {
return null;
}
return (activeWindow.appContext == AppContext.getAppContext())
? activeWindow : null;
}
}
Window getGlobalActiveWindow() throws SecurityException {
synchronized (KeyboardFocusManager.class) {
if (this == getCurrentKeyboardFocusManager()) {
return activeWindow;
} else {
throw new SecurityException(notPrivileged);
}
}
}
void setGlobalActiveWindow(Window activeWindow) {
Window oldActiveWindow;
synchronized (KeyboardFocusManager.class) {
if ((activeWindow != null) && (!activeWindow.isFocusableWindow()))
return;
oldActiveWindow = getActiveWindow();
try {
fireVetoableChange("activeWindow", oldActiveWindow, activeWindow);
} catch (PropertyVetoException e) {
return;
}
KeyboardFocusManager.activeWindow = activeWindow;
}
firePropertyChange("activeWindow", oldActiveWindow, activeWindow);
}
public synchronized FocusTraversalPolicy getDefaultFocusTraversalPolicy() {
return defaultPolicy;
}
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);
}
public void setDefaultFocusTraversalKeys(int id, Set 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");
}
AWTKeyStroke keystroke = (AWTKeyStroke) obj;
if (keystroke.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
throw new IllegalArgumentException("focus traversal keys cannot map to KEY_TYPED events");
}
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);
}
public Set getDefaultFocusTraversalKeys(int id) {
if (id < 0 || id >= TRAVERSAL_KEY_LENGTH) {
throw new IllegalArgumentException("invalid focus traversal key identifier");
}
return defaultFocusTraversalKeys[id];
}
public Container getCurrentFocusCycleRoot() {
synchronized (KeyboardFocusManager.class) {
if (currentFocusCycleRoot == null) {
return null;
}
return (currentFocusCycleRoot.appContext ==
AppContext.getAppContext()) ? currentFocusCycleRoot:null;
}
}
Container getGlobalCurrentFocusCycleRoot()
throws SecurityException {
synchronized (KeyboardFocusManager.class) {
if (this == getCurrentKeyboardFocusManager()) {
return currentFocusCycleRoot;
} else {
throw new SecurityException(notPrivileged);
}
}
}
void setGlobalCurrentFocusCycleRoot(Container newFocusCycleRoot) {
Container oldFocusCycleRoot;
synchronized (KeyboardFocusManager.class) {
oldFocusCycleRoot = getCurrentFocusCycleRoot();
currentFocusCycleRoot = newFocusCycleRoot;
}
firePropertyChange("currentFocusCycleRoot", oldFocusCycleRoot,
newFocusCycleRoot);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
if (listener != null) {
synchronized (this) {
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(listener);
}
}
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
if (listener != null) {
synchronized (this) {
if (changeSupport != null) {
changeSupport.removePropertyChangeListener(listener);
}
}
}
}
public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
return changeSupport.getPropertyChangeListeners();
}
/*
public void addPropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
if (listener != null) {
synchronized (this) {
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
changeSupport.addPropertyChangeListener(propertyName, listener);
}
}
}
public void removePropertyChangeListener(String propertyName,
PropertyChangeListener listener) {
if (listener != null) {
synchronized (this) {
if (changeSupport != null) {
changeSupport.removePropertyChangeListener(propertyName,
listener);
}
}
}
}
public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
if (changeSupport == null) {
changeSupport = new PropertyChangeSupport(this);
}
return changeSupport.getPropertyChangeListeners(propertyName);
}
*/
void firePropertyChange(String propertyName, Object oldValue,
Object newValue) {
PropertyChangeSupport changeSupport = this.changeSupport;
if (changeSupport != null) {
changeSupport.firePropertyChange(propertyName, oldValue, newValue);
}
}
public void addVetoableChangeListener(VetoableChangeListener listener) {
if (listener != null) {
synchronized (this) {
if (vetoableSupport == null) {
vetoableSupport = new VetoableChangeSupport(this);
}
vetoableSupport.addVetoableChangeListener(listener);
}
}
}
public void removeVetoableChangeListener(VetoableChangeListener listener) {
if (listener != null) {
synchronized (this) {
if (vetoableSupport != null) {
vetoableSupport.removeVetoableChangeListener(listener);
}
}
}
}
public synchronized VetoableChangeListener[] getVetoableChangeListeners() {
if (vetoableSupport == null) {
vetoableSupport = new VetoableChangeSupport(this);
}
return vetoableSupport.getVetoableChangeListeners();
}
/*
public void addVetoableChangeListener(String propertyName,
VetoableChangeListener listener) {
if (listener != null) {
synchronized (this) {
if (vetoableSupport == null) {
vetoableSupport = new VetoableChangeSupport(this);
}
vetoableSupport.addVetoableChangeListener(propertyName, listener);
}
}
}
public void removeVetoableChangeListener(String propertyName,
VetoableChangeListener listener) {
if (listener != null) {
synchronized (this) {
if (vetoableSupport != null) {
vetoableSupport.removeVetoableChangeListener(propertyName,
listener);
}
}
}
}
public synchronized VetoableChangeListener[] getVetoableChangeListeners(String propertyName) {
if (vetoableSupport == null) {
vetoableSupport = new VetoableChangeSupport(this);
}
return vetoableSupport.getVetoableChangeListeners(propertyName);
}
*/
void fireVetoableChange(String propertyName, Object oldValue,
Object newValue)
throws PropertyVetoException {
VetoableChangeSupport vetoableSupport = this.vetoableSupport;
if (vetoableSupport != null) {
vetoableSupport.fireVetoableChange(propertyName, oldValue, newValue);
}
}
public void addKeyEventDispatcher(KeyEventDispatcher dispatcher) {
if (dispatcher != null) {
synchronized (this) {
if (keyEventDispatchers == null) {
keyEventDispatchers = new java.util.LinkedList();
}
keyEventDispatchers.add(dispatcher);
}
}
}
public void removeKeyEventDispatcher(KeyEventDispatcher dispatcher) {
if (dispatcher != null) {
synchronized (this) {
if (keyEventDispatchers != null) {
keyEventDispatchers.remove(dispatcher);
}
}
}
}
synchronized java.util.List getKeyEventDispatchers() {
return (keyEventDispatchers != null)
? (java.util.List) keyEventDispatchers.clone()
: null;
}
public void addKeyEventPostProcessor(KeyEventPostProcessor processor) {
if (processor != null) {
synchronized (this) {
if (keyEventPostProcessors == null) {
keyEventPostProcessors = new java.util.LinkedList();
}
keyEventPostProcessors.add(processor);
}
}
}
public void removeKeyEventPostProcessor(KeyEventPostProcessor processor) {
if (processor != null) {
synchronized (this) {
if (keyEventPostProcessors != null) {
keyEventPostProcessors.remove(processor);
}
}
}
}
java.util.List 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) {
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);
}
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();
}
public abstract boolean dispatchEvent(AWTEvent e);
public final void redispatchEvent(Component target, AWTEvent e) {
e.focusManagerIsDispatching = true;
target.dispatchEvent(e);
e.focusManagerIsDispatching = false;
}
public abstract boolean dispatchKeyEvent(KeyEvent e);
public abstract boolean postProcessKeyEvent(KeyEvent e);
public abstract void processKeyEvent(Component focusedComponent, KeyEvent e);
public abstract void focusNextComponent(Component aComponent);
public abstract void focusPreviousComponent(Component aComponent);
public abstract void upFocusCycle(Component aComponent);
public abstract void downFocusCycle(Container aContainer);
abstract void enqueueKeyEvents(long after, Component untilFocused);
abstract void dequeueKeyEvents(long after, Component untilFocused);
abstract void discardKeyEvents(Component comp);
public final void focusNextComponent() {
Component focusOwner = getFocusOwner();
if (focusOwner != null) {
focusNextComponent(focusOwner);
}
}
public final void focusPreviousComponent() {
Component focusOwner = getFocusOwner();
if (focusOwner != null) {
focusPreviousComponent(focusOwner);
}
}
public final void upFocusCycle() {
Component focusOwner = getFocusOwner();
if (focusOwner != null) {
upFocusCycle(focusOwner);
}
}
public final void downFocusCycle() {
Component focusOwner = getFocusOwner();
if (focusOwner instanceof Container) {
downFocusCycle((Container) focusOwner);
}
}
}