Reworked focus handling so that the keyboard manager only loses focus when
(a) the target component is removed, or (b) the window containing the target component loses focus. Moreover, the keyboard manager now steals keys from any other components (explicitly irrespective of the AWT or Swing notion of keyboard focus) via the KeyboardFocusManager as long as it's enabled and has the focus as previously defined. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@875 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,18 +1,24 @@
|
|||||||
//
|
//
|
||||||
// $Id: KeyboardManager.java,v 1.8 2002/01/18 23:32:14 shaper Exp $
|
// $Id: KeyboardManager.java,v 1.9 2002/01/19 01:19:56 shaper Exp $
|
||||||
|
|
||||||
package com.threerings.util;
|
package com.threerings.util;
|
||||||
|
|
||||||
import java.awt.Component;
|
|
||||||
import java.awt.KeyEventDispatcher;
|
import java.awt.KeyEventDispatcher;
|
||||||
import java.awt.KeyboardFocusManager;
|
import java.awt.KeyboardFocusManager;
|
||||||
import java.awt.event.FocusAdapter;
|
import java.awt.Window;
|
||||||
import java.awt.event.FocusEvent;
|
|
||||||
import java.awt.event.KeyAdapter;
|
import java.awt.event.KeyAdapter;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.WindowAdapter;
|
||||||
|
import java.awt.event.WindowEvent;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.event.AncestorEvent;
|
||||||
|
|
||||||
import com.samskivert.swing.Controller;
|
import com.samskivert.swing.Controller;
|
||||||
|
import com.samskivert.swing.event.AncestorAdapter;
|
||||||
import com.samskivert.util.HashIntMap;
|
import com.samskivert.util.HashIntMap;
|
||||||
import com.samskivert.util.Interval;
|
import com.samskivert.util.Interval;
|
||||||
import com.samskivert.util.IntervalManager;
|
import com.samskivert.util.IntervalManager;
|
||||||
@@ -33,42 +39,35 @@ public class KeyboardManager
|
|||||||
* @param xlate the key translator used to map keyboard events to
|
* @param xlate the key translator used to map keyboard events to
|
||||||
* controller action commands.
|
* controller action commands.
|
||||||
*/
|
*/
|
||||||
public KeyboardManager (Component target, KeyTranslator xlate)
|
public KeyboardManager (JComponent target, KeyTranslator xlate)
|
||||||
{
|
{
|
||||||
// save off references
|
// save off references
|
||||||
_target = target;
|
_target = target;
|
||||||
_xlate = xlate;
|
_xlate = xlate;
|
||||||
|
|
||||||
// listen to key events
|
// listen to ancestor events so that we can cease our business if
|
||||||
target.addKeyListener(new KeyAdapter () {
|
// we lose the focus
|
||||||
public void keyPressed (KeyEvent e) {
|
target.addAncestorListener(new AncestorAdapter() {
|
||||||
KeyboardManager.this.keyPressed(e);
|
public void ancestorAdded (AncestorEvent e) {
|
||||||
}
|
KeyboardManager.this.gainedFocus();
|
||||||
public void keyReleased (KeyEvent e) {
|
// add the window focus listener if it's not yet present
|
||||||
KeyboardManager.this.keyReleased(e);
|
if (_wadapter == null) {
|
||||||
}
|
addWindowListener();
|
||||||
});
|
|
||||||
|
|
||||||
// listen to focus events so that we can cease repeating if we
|
|
||||||
// lose focus
|
|
||||||
target.addFocusListener(new FocusAdapter() {
|
|
||||||
public void focusLost (FocusEvent e) {
|
|
||||||
releaseAllKeys();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (DEBUG_EVENTS) {
|
|
||||||
// listen to and report on lower-level incoming keyboard
|
|
||||||
// events at the keyboard focus manager level
|
|
||||||
KeyboardFocusManager keymgr =
|
|
||||||
KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
|
||||||
keymgr.addKeyEventDispatcher(new KeyEventDispatcher() {
|
|
||||||
public boolean dispatchKeyEvent (KeyEvent e) {
|
|
||||||
Log.info("dispatchKeyEvent [e=" + e + "].");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
public void ancestorRemoved (AncestorEvent e) {
|
||||||
|
KeyboardManager.this.lostFocus();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// capture low-level keyboard events via the keyboard focus manager
|
||||||
|
KeyboardFocusManager keymgr =
|
||||||
|
KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||||
|
keymgr.addKeyEventDispatcher(new KeyEventDispatcher() {
|
||||||
|
public boolean dispatchKeyEvent (KeyEvent e) {
|
||||||
|
return KeyboardManager.this.dispatchKeyEvent(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,16 +113,76 @@ public class KeyboardManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the {@link KeyboardFocusManager} has a key event for us
|
||||||
|
* to scrutinize. Returns whether we've handled the key event.
|
||||||
|
*/
|
||||||
|
protected boolean dispatchKeyEvent (KeyEvent e)
|
||||||
|
{
|
||||||
|
// bail if we're not enabled or we haven't the focus
|
||||||
|
if (!_enabled || !_focus) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle key press and release events
|
||||||
|
switch (e.getID()) {
|
||||||
|
case KeyEvent.KEY_PRESSED:
|
||||||
|
KeyboardManager.this.keyPressed(e);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case KeyEvent.KEY_RELEASED:
|
||||||
|
KeyboardManager.this.keyReleased(e);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the keyboard manager gains focus and should begin
|
||||||
|
* handling keys again if it was previously enabled.
|
||||||
|
*/
|
||||||
|
protected void gainedFocus ()
|
||||||
|
{
|
||||||
|
_focus = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the keyboard manager loses focus and should cease
|
||||||
|
* handling keys.
|
||||||
|
*/
|
||||||
|
protected void lostFocus ()
|
||||||
|
{
|
||||||
|
releaseAllKeys();
|
||||||
|
_focus = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a window focus event listener to the target component's window
|
||||||
|
* so that the keyboard manager can enabled and disable handling of
|
||||||
|
* keyboard events appropriately.
|
||||||
|
*/
|
||||||
|
protected void addWindowListener ()
|
||||||
|
{
|
||||||
|
_wadapter = new WindowAdapter() {
|
||||||
|
public void windowGainedFocus (WindowEvent e) {
|
||||||
|
KeyboardManager.this.gainedFocus();
|
||||||
|
}
|
||||||
|
public void windowLostFocus (WindowEvent e) {
|
||||||
|
KeyboardManager.this.lostFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Window window = SwingUtilities.getWindowAncestor(_target);
|
||||||
|
window.addWindowFocusListener(_wadapter);
|
||||||
|
}
|
||||||
|
|
||||||
// documentation inherited
|
// documentation inherited
|
||||||
protected void keyPressed (KeyEvent e)
|
protected void keyPressed (KeyEvent e)
|
||||||
{
|
{
|
||||||
logKey("keyPressed", e);
|
logKey("keyPressed", e);
|
||||||
|
|
||||||
// bail if we're not accepting input
|
|
||||||
if (!_enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the action command associated with this key
|
// get the action command associated with this key
|
||||||
int keyCode = e.getKeyCode();
|
int keyCode = e.getKeyCode();
|
||||||
if (_xlate.hasCommand(keyCode)) {
|
if (_xlate.hasCommand(keyCode)) {
|
||||||
@@ -144,11 +203,6 @@ public class KeyboardManager
|
|||||||
{
|
{
|
||||||
logKey("keyReleased", e);
|
logKey("keyReleased", e);
|
||||||
|
|
||||||
// bail if we're not accepting input
|
|
||||||
if (!_enabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// get the info object for this key
|
// get the info object for this key
|
||||||
KeyInfo info = (KeyInfo)_keys.get(e.getKeyCode());
|
KeyInfo info = (KeyInfo)_keys.get(e.getKeyCode());
|
||||||
if (info != null) {
|
if (info != null) {
|
||||||
@@ -399,12 +453,18 @@ public class KeyboardManager
|
|||||||
/** A hashtable mapping key codes to {@link KeyInfo} objects. */
|
/** A hashtable mapping key codes to {@link KeyInfo} objects. */
|
||||||
protected HashIntMap _keys = new HashIntMap();
|
protected HashIntMap _keys = new HashIntMap();
|
||||||
|
|
||||||
|
/** Whether the keyboard manager currently has the keyboard focus. */
|
||||||
|
protected boolean _focus = true;
|
||||||
|
|
||||||
/** Whether the keyboard manager is accepting keyboard input. */
|
/** Whether the keyboard manager is accepting keyboard input. */
|
||||||
protected boolean _enabled = true;
|
protected boolean _enabled = true;
|
||||||
|
|
||||||
|
/** The window focus event listener. */
|
||||||
|
protected WindowAdapter _wadapter;
|
||||||
|
|
||||||
/** The component that receives keyboard events and that we associate
|
/** The component that receives keyboard events and that we associate
|
||||||
* with posted controller commands. */
|
* with posted controller commands. */
|
||||||
protected Component _target;
|
protected JComponent _target;
|
||||||
|
|
||||||
/** The translator that maps keyboard events to controller commands. */
|
/** The translator that maps keyboard events to controller commands. */
|
||||||
protected KeyTranslator _xlate;
|
protected KeyTranslator _xlate;
|
||||||
|
|||||||
Reference in New Issue
Block a user