The method JComponent.processKeyEvent is Swing's entry point for
handling key events. Events like typing text in a text area even pass
through here to check first if the key event changes the focus (like
alt-tab), then if there is a low-level key listener that wants the
event, then if there is a registered key binding that deals with the
event, and then finally defaulting to inserting the text. So I decided
to tidy the code up and cut away the excess.
In the process, I noticed that there were actually correctness problems
in the code as well, specifically dealing with JInternalFrames, and so I
reported this bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=24781 .
This patch fixes that bug and improves performance for certain cases.
2005-11-10 Anthony Balkissoon <[EMAIL PROTECTED]>
* javax/swing/JComponent.java:
(processKeyEvent): Reworked this method to improve performance. Return
early if the event has already been handled. Don't stop climbing when
we hit a JInternalFrame, only stop at Applets or Windows (this fixes
PR 24781). Don't check WHEN_IN_FOCUSED_WINDOW bindings if there is no
top-level container present. If there is a top-level container, pass
it to KeyboardManager.processKeyStroke rather than the JComponent that
actually received the event, to save time in finding the top-level
container within KeyboardManager.
* javax/swing/KeyboardManager.java:
(findTopLevel): Changed parameter from JComponent to Component to allow
generality and to allow passing in of already-determined top-level
containers to save time.
(processKeyStroke): Likewise.
--Tony
Index: javax/swing/JComponent.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JComponent.java,v
retrieving revision 1.82
diff -u -r1.82 JComponent.java
--- javax/swing/JComponent.java 10 Nov 2005 12:36:44 -0000 1.82
+++ javax/swing/JComponent.java 10 Nov 2005 19:50:06 -0000
@@ -988,7 +988,8 @@
{
VetoableChangeListener[] listeners = getVetoableChangeListeners();
- PropertyChangeEvent evt = new PropertyChangeEvent(this, propertyName, oldValue, newValue);
+ PropertyChangeEvent evt =
+ new PropertyChangeEvent(this, propertyName, oldValue, newValue);
for (int i = 0; i < listeners.length; i++)
listeners[i].vetoableChange(evt);
@@ -2209,36 +2210,52 @@
boolean pressed = e.getID() == KeyEvent.KEY_PRESSED;
if (processKeyBinding(keyStroke, e, WHEN_FOCUSED, pressed))
- // This is step 1 from above comment.
- e.consume();
+ {
+ // This is step 1 from above comment.
+ e.consume();
+ return;
+ }
else if (processKeyBinding
(keyStroke, e, WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
- // This is step 2 from above comment.
- e.consume();
- else
{
- // This is step 3 from above comment.
- Container current = this;
- while ((current = current.getParent()) instanceof JComponent)
+ // This is step 2 from above comment.
+ e.consume();
+ return;
+ }
+
+ // This is step 3 from above comment.
+ Container current = getParent();
+ while (current != null)
+ {
+ // If current is a JComponent, see if it handles the event in its
+ // WHEN_ANCESTOR_OF_FOCUSED_COMPONENT maps.
+ if ((current instanceof JComponent) &&
+ ((JComponent)current).processKeyBinding
+ (keyStroke, e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, pressed))
{
- if (((JComponent)current).processKeyBinding
- (keyStroke, e,WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
- pressed))
- {
- e.consume();
- break;
- }
- if (current instanceof Window || current instanceof Applet
- || current instanceof JInternalFrame)
- break;
- }
- if (e.isConsumed())
- return;
-
- // This is step 4 from above comment.
- if (KeyboardManager.getManager().processKeyStroke(this, keyStroke, e))
- e.consume();
+ e.consume();
+ return;
+ }
+
+ // Stop when we've tried a top-level container and it didn't handle it
+ if (current instanceof Window || current instanceof Applet)
+ break;
+
+ // Move up the hierarchy
+ current = current.getParent();
}
+
+ // Current being null means the JComponent does not currently have a
+ // top-level ancestor, in which case we don't need to check
+ // WHEN_IN_FOCUSED_WINDOW bindings.
+ if (current == null || e.isConsumed())
+ return;
+
+ // This is step 4 from above comment. KeyboardManager maintains mappings
+ // related to WHEN_IN_FOCUSED_WINDOW bindings so that we don't have to
+ // traverse the containment hierarchy each time.
+ if (KeyboardManager.getManager().processKeyStroke(current, keyStroke, e))
+ e.consume();
}
protected boolean processKeyBinding(KeyStroke ks,
@@ -3349,6 +3366,7 @@
// delete all the old bindings for the component and then register
// the current bindings.
km.clearBindingsForComp(changed.getComponent());
- km.registerEntireMap((ComponentInputMap) getInputMap(WHEN_IN_FOCUSED_WINDOW));
+ km.registerEntireMap((ComponentInputMap)
+ getInputMap(WHEN_IN_FOCUSED_WINDOW));
}
}
Index: javax/swing/KeyboardManager.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/KeyboardManager.java,v
retrieving revision 1.1
diff -u -r1.1 KeyboardManager.java
--- javax/swing/KeyboardManager.java 9 Nov 2005 21:59:40 -0000 1.1
+++ javax/swing/KeyboardManager.java 10 Nov 2005 19:50:06 -0000
@@ -39,6 +39,7 @@
package javax.swing;
import java.applet.Applet;
+import java.awt.Component;
import java.awt.Container;
import java.awt.Window;
import java.awt.event.KeyEvent;
@@ -78,9 +79,10 @@
* @param c the JComponent whose top-level ancestor we want
* @return the top-level ancestor for the given JComponent.
*/
- static Container findTopLevel (JComponent c)
+ static Container findTopLevel (Component c)
{
- Container topLevel = (c instanceof Container) ? c : c.getParent();
+ Container topLevel = (c instanceof Container) ? (Container) c
+ : c.getParent();
while (topLevel != null &&
!(topLevel instanceof Window) &&
!(topLevel instanceof Applet) &&
@@ -197,7 +199,7 @@
keyToComponent.put(keys[i], comp);
}
- public boolean processKeyStroke (JComponent comp, KeyStroke key, KeyEvent e)
+ public boolean processKeyStroke (Component comp, KeyStroke key, KeyEvent e)
{
// Look for the top-level ancestor
Container topLevel = findTopLevel(comp);
_______________________________________________
Classpath-patches mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/classpath-patches