Index: java/awt/Container.java =================================================================== RCS file: /cvsroot/classpath/classpath/java/awt/Container.java,v retrieving revision 1.61 diff -u -r1.61 Container.java --- java/awt/Container.java 16 Aug 2005 12:31:24 -0000 1.61 +++ java/awt/Container.java 6 Sep 2005 20:11:30 -0000 @@ -38,6 +38,8 @@ package java.awt; +import gnu.java.awt.AWTUtilities; + import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; import java.awt.event.KeyEvent; @@ -60,8 +62,7 @@ import java.util.Set; import javax.accessibility.Accessible; - -import gnu.java.awt.AWTUtilities; +import javax.swing.RootPaneContainer; /** * A generic window toolkit object that acts as a container for other objects. @@ -1016,6 +1017,16 @@ return getComponentAt (p.x, p.y); } + /** + * Locates the visible child component that contains the specified position. + * If the containing child component is a Container, continues searching + * for the deepest nested child component. + * @param x the x position that should be contained + * @param y the y position that should be contained + * @return null if this container does not contain the position, this container + * itself if no child contains the position, otherwise the deepest containing + * visible child component. + */ public Component findComponentAt(int x, int y) { synchronized (getTreeLock ()) @@ -1048,6 +1059,56 @@ } } + /** + * Locates the visible child component that contains the specified position. + * If the containing child component is a Container, continues searching + * for the deepest nested child component. + * + * Similar to findComponentAt, but this method is called when + * this container (nativeContainer) is a RootPaneContainer with a GlassPane + * that is visible but has no attached MouseListeners. In this case the + * GlassPane should not intercept MouseEvents. + * @param x the x position that should be contained + * @param y the y position that should be contained + * @return null if this container does not contain the position, this container + * itself if no child contains the position, otherwise the deepest containing + * visible child component. + */ + Component findNonGlassPaneComponentAt(Component glassPane, int x, int y) + { + synchronized (getTreeLock ()) + { + if (! contains(x, y)) + return null; + + for (int i = 0; i < ncomponents; ++i) + { + // Ignore invisible children... + // Assume the GlassPane meets the requirements to be ignored + // This method should ONLY be called if the GlassPane is visible + // but has no attached MouseListeners, otherwise findComponentAt + // should be called instead + if (!component[i].isVisible() || component[i].equals(glassPane)) + continue; + + int x2 = x - component[i].x; + int y2 = y - component[i].y; + // We don't do the contains() check right away because + // findComponentAt would redundantly do it first thing. + if (component[i] instanceof Container) + { + Container k = (Container) component[i]; + Component r = k.findNonGlassPaneComponentAt(glassPane, x2, y2); + if (r != null) + return r; + } + else if (component[i].contains(x2, y2)) + return component[i]; + } + return this; + } + } + public Component findComponentAt(Point p) { return findComponentAt(p.x, p.y); @@ -1955,20 +2016,69 @@ eventMask |= l; } + /** + * Returns the deepest visible descendent Component of parent that + * contains the x,y location. If parent is a RootPaneContainer, this method + * will not return its GlassPane unless the GlassPane is visible and + * has one or more MouseListeners attached. If parent does not contain + * the specified location, null is returned. If parent is not a container + * or none of its visible descendents contain the specified location then + * parent is returned + * @param parent the root component from where we being our search + * @param glassPane the GlassPane if parent is a RootPaneContainer, + * or null if it is not. + * @param x the x coordinate + * @param y the y coordinate + */ + Component getDeepestComponentForMouseEventAt + (Component parent, Component glassPane, int x, int y) + { + if (parent == null || (!parent.contains(x, y))) + return null; + + if (!(parent instanceof Container)) + return parent; + + Container c = (Container) parent; + // A GlassPane should only intercept mouse events if it is visible and has + // one or more mouseListeners attached. + // findNonGlassPaneComponentAt is used when there is a glassPane that is + // visible but it has no mouseListeners attached. + // In any other situation we prefer findComponentAt because it is faster + if (glassPane == null || !glassPane.isVisible() || + (glassPane.getMouseListeners() != null + && glassPane.getMouseListeners().length > 0)) + return c.findComponentAt(x, y); + + // Since findNonGlassPaneComponentAt is a recursive method we've put + // the checks for glassPane being visible and having no mouseListeners + // HERE (getDeepestComponentForMouseEventAt) rather than in + // findNonGlassPaneComponentAt itself because that could hurt performance. + // This means that findNonGlassPaneComponentAt assumes the proper + // conditions on glassPane and should ONLY be called when the glassPane + // is visible but has no mouseListeners attached. + return c.findNonGlassPaneComponentAt(glassPane, x, y); + } + Component acquireComponentForMouseEvent(MouseEvent me) { int x = me.getX (); int y = me.getY (); - + Component mouseEventTarget = null; // Find the candidate which should receive this event. Component parent = nativeContainer; Component candidate = null; + Component glassPane = null; Point p = me.getPoint(); + + if (nativeContainer instanceof RootPaneContainer) + glassPane = ((RootPaneContainer)nativeContainer).getGlassPane(); + while (candidate == null && parent != null) { candidate = - AWTUtilities.getDeepestComponentAt(parent, p.x, p.y); + getDeepestComponentForMouseEventAt(parent, glassPane, p.x, p.y); if (candidate == null || (candidate.eventMask & me.getID()) == 0) { candidate = null; @@ -1976,7 +2086,7 @@ 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.