classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[patch] implement LightweightDispatcher


From: graydon hoare
Subject: [patch] implement LightweightDispatcher
Date: Mon, 01 Dec 2003 17:46:09 -0500
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.5) Gecko/20031115 Thunderbird/0.3

hi,

this patch implements a rough, preliminary version of java.awt.Container.LightweightDispatcher, which is a helper class which appears to exist (undocumented) in sun's library, and which is needed to route events around inside lightweight peers.

it also changes the container repaint cycle to reuse a single Graphics object, rather than cloning it for each child.

ok to commit?

-graydon
Index: java/awt/Container.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Container.java,v
retrieving revision 1.23
diff -u -b -w -r1.23 Container.java
--- java/awt/Container.java     1 Dec 2003 22:35:28 -0000       1.23
+++ java/awt/Container.java     1 Dec 2003 22:39:27 -0000
@@ -41,6 +41,7 @@
 import java.awt.event.ContainerEvent;
 import java.awt.event.ContainerListener;
 import java.awt.event.MouseEvent;
+import java.awt.event.KeyEvent;
 import java.awt.peer.ContainerPeer;
 import java.awt.peer.LightweightPeer;
 import java.beans.PropertyChangeListener;
@@ -1225,30 +1226,39 @@
                           Component comp)
   {
     Rectangle bounds = comp.getBounds();
-    Rectangle clip = gfx.getClipBounds();
-    if (clip == null)
-      clip = bounds;
-    else
-      clip = clip.intersection(bounds);
+    Rectangle oldClip = gfx.getClipBounds();
+    if (oldClip == null)
+       oldClip = bounds;
+    Rectangle clip = oldClip.intersection(bounds);
 
     if (clip.isEmpty()) return;
 
-    Graphics gfx2 = gfx.create();
+    boolean clipped = false;
+    boolean translated = false;
     try
       {
-       gfx2.setClip(clip.x, clip.y, clip.width, clip.height);
-       gfx2.translate(bounds.x, bounds.y);
-
-       visitor.visit(comp, gfx2);
+       gfx.setClip(clip.x, clip.y, clip.width, clip.height);
+       clipped = true;
+       gfx.translate(bounds.x, bounds.y);
+       translated = true;
+       visitor.visit(comp, gfx);
       }
     finally
       {
-       gfx2.dispose ();
+         if (translated)
+             gfx.translate (-bounds.x, -bounds.y);
+         if (clipped)
+             gfx.setClip (oldClip.x, oldClip.y, oldClip.width, oldClip.height);
       }
   }
 
   void dispatchEventImpl(AWTEvent e)
   {
+      // give lightweight dispatcher a chance to handle it
+      if (dispatcher != null 
+         && dispatcher.handleEvent (e))
+         return;
+      
     if ((e.id <= ContainerEvent.CONTAINER_LAST
              && e.id >= ContainerEvent.CONTAINER_FIRST)
         && (containerListener != null
@@ -1319,6 +1329,17 @@
             component[i].addNotify();
             if (component[i].isLightweight ())
              {
+
+                 // if we're not lightweight, and we just got a lightweight
+                 // child, we need a lightweight dispatcher to feed it events.
+                 if (! this.isLightweight() 
+                     && dispatcher == null)
+                     {
+                         dispatcher = new LightweightDispatcher (this);
+                         dispatcher.enableEvents (component[i].eventMask);
+                     }
+                 
+
                enableEvents(component[i].eventMask);
                if (peer != null && !isLightweight ())
                  enableEvents (AWTEvent.PAINT_EVENT_MASK);
@@ -1495,22 +1516,25 @@
 } // class Container
 
 /**
- * Undocumented helper class.
- * STUBBED
+ * there is a helper class implied from stack traces called
+ * LightweightDispatcher, but since it is not part of the public API,
+ * rather than mimic it exactly we write something which does "roughtly
+ * the same thing".
  */
-class LightweightDispatcher implements Serializable, AWTEventListener
+
+class LightweightDispatcher implements Serializable
 {
   private static final long serialVersionUID = 5184291520170872969L;
   private Container nativeContainer;
   private Component focus;
-  private transient Component mouseEventTarget;
-  private transient Component targetLastEntered;
-  private transient boolean isMouseInNativeContainer;
   private Cursor nativeCursor;
   private long eventMask;
   
+    private transient Component mouseEventTarget;
+  
   LightweightDispatcher(Container c)
   {
+       nativeContainer = c;
   }
 
   void dispose()
@@ -1519,40 +1543,106 @@
 
   void enableEvents(long l)
   {
+       eventMask |= l;
   }
 
-  boolean dispatchEvent(AWTEvent e)
+    void mouseExit (MouseEvent me, int x, int y)
   {
-    return true;
   }
 
-  boolean isMouseGrab(MouseEvent e)
+    void acquireComponentForMouseEvent (MouseEvent me)
   {
-    return true;
-  }
+       int x = me.getX ();
+       int y = me.getY ();
+
+       Component candidate = mouseEventTarget;
+
+       boolean candidate_is_container_with_children = 
+           ((candidate != null)
+            && (candidate instanceof Container)
+            && (((Container)candidate).getComponentCount () > 0));
 
-  boolean processMouseEvent(MouseEvent e)
+       boolean candidate_does_not_contain_point =
+           ((candidate != null)
+            && (! candidate.contains (x - candidate.getX (),
+                                      y - candidate.getY ())));
+
+       if (candidate == null
+           || candidate_is_container_with_children
+           || candidate_does_not_contain_point)
   {
-    return true;
+               // try to reacquire
+               candidate = nativeContainer.findComponentAt (x, y);
   }
 
-  void trackMouseEnterExit(Component c, MouseEvent e)
+       if (mouseEventTarget != null
+           && mouseEventTarget != candidate)
   {
+               int nx = x - mouseEventTarget.getX ();
+               int ny = y - mouseEventTarget.getY ();
+               MouseEvent exited = new MouseEvent (mouseEventTarget, 
+                                                   MouseEvent.MOUSE_EXITED,
+                                                   me.getWhen (), 
+                                                   me.getModifiers (), 
+                                                   nx, ny,
+                                                   me.getClickCount (),
+                                                   me.isPopupTrigger (),
+                                                   me.getButton ());
+               mouseEventTarget.dispatchEvent (exited); 
+               mouseEventTarget = null;
   }
 
-  void startListeningForOtherDrags()
+       if (candidate != null)
+           {
+               // possibly set new state
+               if (candidate.isLightweight() 
+                   && candidate != nativeContainer
+                   && candidate != mouseEventTarget)
   {
+                       
+                       mouseEventTarget = candidate;
+                       
+                       int nx = x - mouseEventTarget.getX ();
+                       int ny = y - mouseEventTarget.getY ();
+                       
+                       // if acquired, enter it
+                       MouseEvent entered = new MouseEvent (mouseEventTarget, 
+                                                            
MouseEvent.MOUSE_ENTERED,
+                                                            me.getWhen (), 
+                                                            me.getModifiers 
(), 
+                                                            nx, ny,
+                                                            me.getClickCount 
(),
+                                                            me.isPopupTrigger 
(),
+                                                            me.getButton ());
+                       mouseEventTarget.dispatchEvent (entered);
+                   }
+           }
   }
 
-  void stopListeningForOtherDrags()
+    boolean handleEvent (AWTEvent e)
   {
-  }
+       if ((eventMask & e.getID ()) == 0)
+           return false;
 
-  public void eventDispatched(AWTEvent e)
+       if (e instanceof MouseEvent)
   {
-  }
+               MouseEvent me = (MouseEvent) e;
+               acquireComponentForMouseEvent (me);
 
-  void retargetMouseEvent(Component c, int i, MouseEvent e)
+               if (mouseEventTarget != null)
+                   {
+                       Component oldSource = (Component) me.getSource ();
+                       me.setSource (mouseEventTarget);
+                       mouseEventTarget.dispatchEvent (me);
+                       me.setSource (oldSource);
+                   }
+           }
+       else if (e instanceof KeyEvent && focus != null)
   {
+               focus.processKeyEvent ((KeyEvent) e);
+           }
+      
+       return e.isConsumed();
   }
+
 } // class LightweightDispatcher

reply via email to

[Prev in Thread] Current Thread [Next in Thread]