aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/awt/Container.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/awt/Container.java')
-rw-r--r--libjava/java/awt/Container.java144
1 files changed, 98 insertions, 46 deletions
diff --git a/libjava/java/awt/Container.java b/libjava/java/awt/Container.java
index ff1dde1..d666559 100644
--- a/libjava/java/awt/Container.java
+++ b/libjava/java/awt/Container.java
@@ -502,6 +502,20 @@ public class Container extends Component
}
/**
+ * Recursively invalidates the container tree.
+ */
+ private void invalidateTree()
+ {
+ for (int i = 0; i < ncomponents; i++)
+ {
+ Component comp = component[i];
+ comp.invalidate();
+ if (comp instanceof Container)
+ ((Container) comp).invalidateTree();
+ }
+ }
+
+ /**
* Recursively validates the container tree, recomputing any invalid
* layouts.
*/
@@ -546,7 +560,10 @@ public class Container extends Component
public void setFont(Font f)
{
super.setFont(f);
- // FIXME, should invalidate all children with font == null
+ // FIXME: Although it might make more sense to invalidate only
+ // those children whose font == null, Sun invalidates all children.
+ // So we'll do the same.
+ invalidateTree();
}
/**
@@ -1234,6 +1251,7 @@ public class Container extends Component
Rectangle oldClip = gfx.getClipBounds();
if (oldClip == null)
oldClip = bounds;
+
Rectangle clip = oldClip.intersection(bounds);
if (clip.isEmpty()) return;
@@ -1337,10 +1355,10 @@ public class Container extends Component
// 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)
+ if (! this.isLightweight())
{
- dispatcher = new LightweightDispatcher (this);
+ if (dispatcher == null)
+ dispatcher = new LightweightDispatcher (this);
dispatcher.enableEvents (component[i].eventMask);
}
@@ -1536,6 +1554,9 @@ class LightweightDispatcher implements Serializable
private long eventMask;
private transient Component mouseEventTarget;
+ private transient Component pressedComponent;
+ private transient Component lastComponentEntered;
+ private transient int pressCount;
LightweightDispatcher(Container c)
{
@@ -1551,46 +1572,37 @@ class LightweightDispatcher implements Serializable
{
int x = me.getX ();
int y = me.getY ();
- Component candidate = mouseEventTarget;
-
- while(candidate != null)
- {
- if (candidate.isShowing())
- {
- // Convert our point to the candidate's parent's space.
- Point cp = SwingUtilities.convertPoint(nativeContainer, x, y, candidate);
-
- // If the event lands inside candidate, we have a hit.
- if (candidate.contains(cp.x, cp.y))
- {
- // If candidate has children, we refine the hit.
- if (candidate instanceof Container &&
- ((Container)candidate).getComponentCount() > 0)
- candidate = SwingUtilities.getDeepestComponentAt(candidate, cp.x, cp.y);
- break;
- }
- }
- // If candidate isn't showing or doesn't contain point, we back out a level.
- candidate = candidate.getParent();
- }
-
- if (candidate == null)
+
+ // Find the candidate which should receive this event.
+ Component parent = nativeContainer;
+ Component candidate = null;
+ Point p = me.getPoint();
+ while (candidate == null && parent != null)
{
- // We either lost, or never had, a candidate; acquire from our native.
- candidate =
- SwingUtilities.getDeepestComponentAt(nativeContainer, x, y);
+ candidate =
+ SwingUtilities.getDeepestComponentAt(parent, p.x, p.y);
+ if (candidate == null)
+ {
+ p = SwingUtilities.convertPoint(parent, p.x, p.y, parent.parent);
+ parent = parent.parent;
+ }
}
+ // If the only candidate we found was the native container itself,
+ // don't dispatch any event at all. We only care about the lightweight
+ // children here.
+ if (candidate == nativeContainer)
+ candidate = null;
// If our candidate is new, inform the old target we're leaving.
- if (mouseEventTarget != null
- && mouseEventTarget.isShowing()
- && mouseEventTarget != candidate)
+ if (lastComponentEntered != null
+ && lastComponentEntered.isShowing()
+ && lastComponentEntered != candidate)
{
Point tp =
SwingUtilities.convertPoint(nativeContainer,
- x, y, mouseEventTarget);
- MouseEvent exited = new MouseEvent (mouseEventTarget,
+ x, y, lastComponentEntered);
+ MouseEvent exited = new MouseEvent (lastComponentEntered,
MouseEvent.MOUSE_EXITED,
me.getWhen (),
me.getModifiers (),
@@ -1598,22 +1610,23 @@ class LightweightDispatcher implements Serializable
me.getClickCount (),
me.isPopupTrigger (),
me.getButton ());
- mouseEventTarget.dispatchEvent (exited);
- mouseEventTarget = null;
+ lastComponentEntered.dispatchEvent (exited);
+ lastComponentEntered = null;
}
// If we have a candidate, maybe enter it.
if (candidate != null)
{
+ mouseEventTarget = candidate;
if (candidate.isLightweight()
&& candidate.isShowing()
&& candidate != nativeContainer
- && candidate != mouseEventTarget)
+ && candidate != lastComponentEntered)
{
- mouseEventTarget = candidate;
+ lastComponentEntered = mouseEventTarget;
Point cp = SwingUtilities.convertPoint(nativeContainer,
- x, y, candidate);
- MouseEvent entered = new MouseEvent (mouseEventTarget,
+ x, y, lastComponentEntered);
+ MouseEvent entered = new MouseEvent (lastComponentEntered,
MouseEvent.MOUSE_ENTERED,
me.getWhen (),
me.getModifiers (),
@@ -1621,9 +1634,29 @@ class LightweightDispatcher implements Serializable
me.getClickCount (),
me.isPopupTrigger (),
me.getButton ());
- mouseEventTarget.dispatchEvent (entered);
+ lastComponentEntered.dispatchEvent (entered);
}
}
+
+ if (me.getID() == MouseEvent.MOUSE_RELEASED
+ || me.getID() == MouseEvent.MOUSE_PRESSED && pressCount > 0
+ || me.getID() == MouseEvent.MOUSE_DRAGGED)
+ // If any of the following events occur while a button is held down,
+ // they should be dispatched to the same component to which the
+ // original MOUSE_PRESSED event was dispatched:
+ // - MOUSE_RELEASED
+ // - MOUSE_PRESSED: another button pressed while the first is held down
+ // - MOUSE_DRAGGED
+ mouseEventTarget = pressedComponent;
+ else if (me.getID() == MouseEvent.MOUSE_CLICKED)
+ {
+ // Don't dispatch CLICKED events whose target is not the same as the
+ // target for the original PRESSED event.
+ if (candidate != pressedComponent)
+ mouseEventTarget = null;
+ else if (pressCount == 0)
+ pressedComponent = null;
+ }
}
boolean handleEvent(AWTEvent e)
@@ -1634,17 +1667,36 @@ class LightweightDispatcher implements Serializable
if (e instanceof MouseEvent)
{
MouseEvent me = (MouseEvent) e;
- acquireComponentForMouseEvent(me);
- // Avoid dispatching an ENTERED event twice.
+ acquireComponentForMouseEvent(me);
+
+ // Avoid dispatching ENTERED and EXITED events twice.
if (mouseEventTarget != null
&& mouseEventTarget.isShowing()
- && e.getID() != MouseEvent.MOUSE_ENTERED)
+ && e.getID() != MouseEvent.MOUSE_ENTERED
+ && e.getID() != MouseEvent.MOUSE_EXITED)
{
MouseEvent newEvt =
SwingUtilities.convertMouseEvent(nativeContainer, me,
mouseEventTarget);
mouseEventTarget.dispatchEvent(newEvt);
+
+ switch (e.getID())
+ {
+ case MouseEvent.MOUSE_PRESSED:
+ if (pressCount++ == 0)
+ pressedComponent = mouseEventTarget;
+ break;
+
+ case MouseEvent.MOUSE_RELEASED:
+ // Clear our memory of the original PRESSED event, only if
+ // we're not expecting a CLICKED event after this. If
+ // there is a CLICKED event after this, it will do clean up.
+ if (--pressCount == 0
+ && mouseEventTarget != pressedComponent)
+ pressedComponent = null;
+ break;
+ }
}
}
else if (e instanceof KeyEvent && focus != null)