diff options
Diffstat (limited to 'libjava/java/awt/Container.java')
-rw-r--r-- | libjava/java/awt/Container.java | 144 |
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) |