aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/java/awt/LightweightDispatcher.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/java/awt/LightweightDispatcher.java')
-rw-r--r--libjava/classpath/java/awt/LightweightDispatcher.java165
1 files changed, 138 insertions, 27 deletions
diff --git a/libjava/classpath/java/awt/LightweightDispatcher.java b/libjava/classpath/java/awt/LightweightDispatcher.java
index 8606464..7e33bd4 100644
--- a/libjava/classpath/java/awt/LightweightDispatcher.java
+++ b/libjava/classpath/java/awt/LightweightDispatcher.java
@@ -38,8 +38,6 @@ exception statement from your version. */
package java.awt;
-import gnu.java.awt.AWTUtilities;
-
import java.awt.event.MouseEvent;
import java.util.WeakHashMap;
@@ -67,6 +65,13 @@ class LightweightDispatcher
* as well as the MOUSE_RELEASED event following the dragging.
*/
private Component dragTarget;
+
+ /**
+ * Stores the button number which started the drag operation. This is needed
+ * because we want to handle only one drag operation and only the button that
+ * started the dragging should be able to stop it (by a button release).
+ */
+ private int dragButton;
/**
* The last mouse event target. If the target changes, additional
@@ -121,15 +126,41 @@ class LightweightDispatcher
/**
* Handles all mouse events that are targetted at toplevel containers
* (Window instances) and dispatches them to the correct lightweight child.
- *
+ *
* @param ev the mouse event
* @return whether or not we found a lightweight that handled the event.
*/
private boolean handleMouseEvent(MouseEvent ev)
{
Window window = (Window) ev.getSource();
- Component target = window.findComponentAt(ev.getX(), ev.getY());
- target = findTarget(target);
+ // Find the target for the mouse event. We first seach the deepest
+ // component at the specified location. The we go up to its parent and
+ // try to find a neighbor of the deepest component that is suitable as
+ // mouse event target (it must be showing, at that location and have either
+ // a MouseListener or MouseMotionListener installed). If no such component
+ // is found, then we walk up the container hierarchy and find the next
+ // container that has a MouseListener or MouseMotionListener installed.
+ Component deepest = window.findComponentAt(ev.getX(), ev.getY());
+ if (deepest == null)
+ return false;
+ Container parent = deepest.getParent();
+ Point loc = ev.getPoint();
+ loc = convertPointToChild(window, loc, parent);
+ Component target = null;
+ if (parent != null)
+ {
+ target = findTarget(parent, loc);
+ while (target == null && parent != null)
+ {
+ if (parent.getMouseListeners().length > 0
+ || parent.getMouseMotionListeners().length > 0)
+ {
+ target = parent;
+ }
+ else
+ parent = parent.getParent();
+ }
+ }
if (target == null || target.isLightweight())
{
// Dispatch additional MOUSE_EXITED and MOUSE_ENTERED if event target
@@ -138,18 +169,26 @@ class LightweightDispatcher
{
if (lastTarget != null)
{
- Point p1 = AWTUtilities.convertPoint(window, ev.getX(),
- ev.getY(), lastTarget);
+ Point p1 = convertPointToChild(window, ev.getPoint(),
+ lastTarget);
MouseEvent mouseExited =
new MouseEvent(lastTarget, MouseEvent.MOUSE_EXITED,
ev.getWhen(), ev.getModifiers(), p1.x, p1.y,
ev.getClickCount(), ev.isPopupTrigger());
lastTarget.dispatchEvent(mouseExited);
}
- if (target != null)
+
+ // If a target exists dispatch the MOUSE_ENTERED event only if
+ // there is currently no component from which a drag operation
+ // started (dragTarget == null) or the target is that component
+ // (dragTarget == target)
+ // That way a user can click and hold on a button (putting it into
+ // the armed state), move the cursor above other buttons without
+ // affecting their rollover state and get back to the initial
+ // button.
+ if (target != null && (dragTarget == null || dragTarget == target))
{
- Point p = AWTUtilities.convertPoint(window, ev.getX(), ev.getY(),
- target);
+ Point p = convertPointToChild(window, ev.getPoint(), target);
MouseEvent mouseEntered =
new MouseEvent(target, MouseEvent.MOUSE_ENTERED, ev.getWhen(),
ev.getModifiers(), p.x, p.y, ev.getClickCount(),
@@ -161,12 +200,30 @@ class LightweightDispatcher
switch (ev.getID())
{
case MouseEvent.MOUSE_PRESSED:
- dragTarget = target;
+ // Handle the start of a drag operation or discard the event if
+ // one is already in progress. This prevents focus changes with the
+ // other mouse buttons when one is used for dragging.
+ if (dragTarget == null)
+ {
+ lastTarget = dragTarget = target;
+
+ // Save the button that started the drag operation.
+ dragButton = ev.getButton();
+ }
+ else
+ return false;
+
break;
case MouseEvent.MOUSE_RELEASED:
- if (dragTarget != null)
- target = dragTarget;
- dragTarget = null;
+ // Stop the drag operation only when the button that started
+ // it was released.
+ if (dragTarget != null && dragButton == ev.getButton())
+ {
+ target = dragTarget;
+ dragTarget = null;
+ }
+
+ lastTarget = target;
break;
case MouseEvent.MOUSE_CLICKED:
// When we receive a MOUSE_CLICKED, we set the target to the
@@ -174,27 +231,35 @@ class LightweightDispatcher
// This is necessary for the case when the MOUSE_RELEASED has
// caused the original target (like an internal component) go
// away.
+ // This line is the reason why it is not possible to move the
+ // 'lastTarget = target' assignment before the switch-statement.
target = lastTarget;
break;
case MouseEvent.MOUSE_DRAGGED:
+ // We consider only dragTarget for redispatching the event still
+ // we have to act in a way that the newly found target component
+ // was handled.
+ lastTarget = target;
target = dragTarget;
break;
default:
- // Do nothing in other cases.
+ // Only declare current target as the old value in all other
+ // cases.
+ lastTarget = target;
break;
}
- lastTarget = target;
-
if (target != null)
{
- Point targetCoordinates =
- AWTUtilities.convertPoint(window, ev.getX(), ev.getY(), target);
+ Point targetCoordinates = convertPointToChild(window,
+ ev.getPoint(),
+ target);
int dx = targetCoordinates.x - ev.getX();
int dy = targetCoordinates.y - ev.getY();
ev.translatePoint(dx, dy);
ev.setSource(target);
target.dispatchEvent(ev);
+
// We reset the event, so that the normal event dispatching is not
// influenced by this modified event.
ev.setSource(window);
@@ -209,20 +274,66 @@ class LightweightDispatcher
/**
* Finds the actual target for a mouseevent, starting at <code>c</code>.
- * This searches upwards the component hierarchy until it finds a component
- * that has a mouselistener attached.
+ * This searches through the children of the container and finds the first
+ * one which is showing, at the location from the mouse event and has
+ * a MouseListener or MouseMotionListener attached. If no such child component
+ * is found, null is returned.
*
- * @param c the component to start searching from
+ * @param c the container to search through
+ * @param loc the mouse event point
*
- * @return the actual receiver of the mouse event
+ * @return the actual receiver of the mouse event, or null, if no such
+ * component has been found
*/
- private Component findTarget(Component c)
+ private Component findTarget(Container c, Point loc)
{
- Component target = c;
- while (target != null && target.getMouseListeners().length == 0)
+ Component[] children = c.getComponents();
+ Component target = null;
+ if (c != null)
{
- target = target.getParent();
+ for (int i = 0; i < children.length; i++)
+ {
+ Component child = children[i];
+ if (child.isShowing())
+ {
+ if (child.contains(loc.x - child.getX(), loc.y - child.getY())
+ && (child.getMouseListeners().length > 0
+ || child.getMouseMotionListeners().length > 0))
+ {
+ target = child;
+ break;
+ }
+ }
+ }
}
return target;
}
+
+ /**
+ * Converts a point in the parent's coordinate system to a child coordinate
+ * system. The resulting point is stored in the same Point object and
+ * returned.
+ *
+ * @param parent the parent component
+ * @param p the point
+ * @param child the child component
+ *
+ * @return the translated point
+ */
+ private Point convertPointToChild(Component parent, Point p,
+ Component child)
+ {
+ int offX = 0;
+ int offY = 0;
+ Component comp = child;
+ while (comp != null && comp != parent)
+ {
+ offX += comp.getX();
+ offY += comp.getY();
+ comp = comp.getParent();
+ }
+ p.x -= offX;
+ p.y -= offY;
+ return p;
+ }
}