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

Reply via email to