[Top][All Lists]
[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
- [patch] implement LightweightDispatcher,
graydon hoare <=