This fixes a couple of issues that I had with Espial Espresso (a Swing-alike lightweight toolkit implementation). This does:

- validate() in paintAll()
- don't enable events in the various addXXXListener() methods. There are two methods for catching events, adding a listener OR calling enableEvents() in a subclass and overriding processXXXEvent(). It's not meant to call enableEvent() from the addXXXListener() methods.
- Fix some painting issues.

2006-09-18  Roman Kennke  <[EMAIL PROTECTED]>

        * java/awt/Component.java
        (show): Test for the peer beeing lightweight directly.
        (paintAll): Validate before painting. Don't paint when not
        showing. Call peer.paint() when the component is heavyweight.
        (repaint): Delegate to the parent when lightweight, rather
        than skipping to the nearest heavyweight.
        (createImage): Added null check to prevent NPE.
        (dispatchEvent): Moved old event dispatching and toolkit
        event dispatching to dispatchEventImpl.
        (addComponentListener): Don't enable event. Only add listener
        when not null. Switch to new event dispatching only.
        (addFocusListener): Likewise.
        (addHierarchyListener): Likewise.
        (addHierarchyBoundsListener): Likewise.
        (addKeyListener): Likewise.
        (addMouseListener): Likewise.
        (addMouseMotionListener): Likewise.
        (addMouseWheelListener): Likewise.
        (addInputMethodListener): Likewise.
        (coalesceEvents): For mouse events coalesce them only when
        their modifiers are equal. For paint events coalesce the events
        when one contains the other, without going through complicated
        heuristics.
        (dispatchEventImpl): Moved old event dispatching and toolkit
        event dispatching to dispatchEventImpl.
        (coalescePaintEvents): Removed.
        (HeavyweightInLightweightListener.componentHidden):
        Fixed condition.
        * java/awt/Container.java
        (addImpl): Don't enable events on lightweights.
        (remove): Reordered operations. Don't remove any listeners.
        Throw ArrayIndexOutOfBoundsException when index >= ncomponents.
        Only removeNotify() when peer is != null. Only invalidate if
        not already invalid. Only fire ContainerEvent if there is
        an interested listener or the event is enabled. Dispatch this
        event directly without the event queue.
        (removeAll): Likewise.
        (paintComponents): Only paint when showing. Also paint heavyweights.
        Don't paint the container itself.
        (removeNotify): Create local variables for improved thread safety.
        (addNotifyContainerChildren): Don't enable events for lightweights.

/Roman
Index: java/awt/Component.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Component.java,v
retrieving revision 1.146
diff -u -1 -5 -r1.146 Component.java
--- java/awt/Component.java	16 Aug 2006 20:26:03 -0000	1.146
+++ java/awt/Component.java	18 Sep 2006 13:22:16 -0000
@@ -959,50 +959,50 @@
     show(visible);
   }
 
   /**
    * Makes this component visible on the screen.
    *
    * @deprecated use [EMAIL PROTECTED] #setVisible(boolean)} instead
    */
   public void show()
   {
     // We must set visible before showing the peer.  Otherwise the
     // peer could post paint events before visible is true, in which
     // case lightweight components are not initially painted --
     // Container.paint first calls isShowing () before painting itself
     // and its children.
-    if(!isVisible())
+    if(! visible)
       {
         // Need to lock the tree here to avoid races and inconsistencies.
         synchronized (getTreeLock())
           {
             visible = true;
             // Avoid NullPointerExceptions by creating a local reference.
-            ComponentPeer currentPeer=peer;
+            ComponentPeer currentPeer = peer;
             if (currentPeer != null)
               {
                 currentPeer.show();
 
                 // Fire HierarchyEvent.
                 fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
                                    this, parent,
                                    HierarchyEvent.SHOWING_CHANGED);
 
                 // The JDK repaints the component before invalidating the parent.
                 // So do we.
-                if (isLightweight())
+                if (peer instanceof LightweightPeer)
                   repaint();
               }
 
             // Only post an event if this component actually has a listener
             // or has this event explicitly enabled.
             if (componentListener != null
                 || (eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0)
               {
                 ComponentEvent ce =
                   new ComponentEvent(this,ComponentEvent.COMPONENT_SHOWN);
                 getToolkit().getSystemEventQueue().postEvent(ce);
               }
           }
 
         // Invalidate the parent if we have one. The component itself must
@@ -1025,31 +1025,31 @@
   public void show(boolean visible)
   {
     if (visible)
       show();
     else
       hide();
   }
 
   /**
    * Hides this component so that it is no longer shown on the screen.
    *
    * @deprecated use [EMAIL PROTECTED] #setVisible(boolean)} instead
    */
   public void hide()
   {
-    if (isVisible())
+    if (visible)
       {
         // Need to lock the tree here to avoid races and inconsistencies.
         synchronized (getTreeLock())
           {
             visible = false;
 
             // Avoid NullPointerExceptions by creating a local reference.
             ComponentPeer currentPeer = peer;
             if (currentPeer != null)
               {
                 currentPeer.hide();
 
                 // Fire hierarchy event.
                 fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED,
                                    this, parent,
@@ -2217,33 +2217,38 @@
     // Note 2 (for peer implementors): The JDK doesn't seem call update() for
     // toplevel components, even when an UPDATE event is sent (as a result
     // of repaint).
     paint(g);
   }
 
   /**
    * Paints this entire component, including any sub-components.
    *
    * @param g the graphics context for this paint job
    * 
    * @see #paint(Graphics)
    */
   public void paintAll(Graphics g)
   {
-    if (! visible)
-      return;
-    paint(g);
+    if (isShowing())
+      {
+        validate();
+        if (peer instanceof LightweightPeer)
+          paint(g);
+        else
+          peer.paint(g);
+      }
   }
 
   /**
    * Repaint this entire component. The <code>update()</code> method
    * on this component will be called as soon as possible.
    *
    * @see #update(Graphics)
    * @see #repaint(long, int, int, int, int)
    */
   public void repaint()
   {   
     repaint(0, 0, 0, width, height);
   }
 
   /**
@@ -2290,60 +2295,56 @@
    * @param height the height of the region to repaint
    * @see #update(Graphics)
    */
   public void repaint(long tm, int x, int y, int width, int height)
   {
     // The repaint() call has previously been delegated to
     // [EMAIL PROTECTED] ComponentPeer.repaint()}. Testing on the JDK using some
     // dummy peers show that this methods is never called. I think it makes
     // sense to actually perform the tasks below here, since it's pretty
     // much peer independent anyway, and makes sure only heavyweights are
     // bothered by this.
     ComponentPeer p = peer;
 
     // Let the nearest heavyweight parent handle repainting for lightweight
     // components.
-    // This goes up the hierarchy until we hit
-    // a heavyweight component that handles this and translates the
-    // rectangle while doing so.
-
-    // We perform some boundary checking to restrict the paint
-    // region to this component.
-    int px = (x < 0 ? 0 : x);
-    int py = (y < 0 ? 0 : y);
-    int pw = width;
-    int ph = height;
-    Component par = this;
-    while (par != null && p instanceof LightweightPeer)
+    // We need to recursivly call repaint() on the parent here, since
+    // a (lightweight) parent component might have overridden repaint()
+    // to perform additional custom tasks.
+
+    if (p instanceof LightweightPeer)
       {
-        px += par.x; 
-        py += par.y; 
         // We perform some boundary checking to restrict the paint
         // region to this component.
-        pw = Math.min(pw, par.width);
-        ph = Math.min(ph, par.height);
-        par = par.parent;
-        p = par == null ? null : par.peer;
+        if (parent != null)
+          {
+            int px = this.x + Math.max(0, x); 
+            int py = this.y + Math.max(0, y);
+            int pw = Math.min(this.width, width);
+            int ph = Math.min(this.height, height);
+            parent.repaint(tm, px, py, pw, ph);
+          }
       }
-
-    // Now send an UPDATE event to the heavyweight component that we've found.
-    if (par != null && par.isVisible() && p != null && pw > 0 && ph > 0)
+    else
       {
-        assert ! (p instanceof LightweightPeer);
-        PaintEvent pe = new PaintEvent(par, PaintEvent.UPDATE,
-                                       new Rectangle(px, py, pw, ph));
-        getToolkit().getSystemEventQueue().postEvent(pe);
+        // Now send an UPDATE event to the heavyweight component that we've found.
+        if (isVisible() && p != null && width > 0 && height > 0)
+          {
+            PaintEvent pe = new PaintEvent(this, PaintEvent.UPDATE,
+                                           new Rectangle(x, y, width, height));
+            getToolkit().getSystemEventQueue().postEvent(pe);
+          }
       }
   }
 
   /**
    * Prints this component. This method is provided so that printing can be
    * done in a different manner from painting. However, the implementation
    * in this class simply calls the <code>paint()</code> method.
    *
    * @param g the graphics context of the print device
    * 
    * @see #paint(Graphics)
    */
   public void print(Graphics g)
   {
     paint(g);
@@ -2447,31 +2448,32 @@
    */
   public Image createImage (int width, int height)
   {
     Image returnValue = null;
     if (!GraphicsEnvironment.isHeadless ())
       {
         // Only heavyweight peers can handle this.
         ComponentPeer p = peer;
         Component comp = this;
         while (p instanceof LightweightPeer)
           {
             comp = comp.parent;
             p = comp == null ? null : comp.peer;
           }
 
-        returnValue = p.createImage(width, height);
+        if (p != null)
+          returnValue = p.createImage(width, height);
       }
     return returnValue;
   }
 
   /**
    * Creates an image with the specified width and height for use in
    * double buffering. Headless environments do not support images.
    *
    * @param width the width of the image
    * @param height the height of the image
    * @return the requested image, or null if it is not supported
    * @since 1.4
    */
   public VolatileImage createVolatileImage(int width, int height)
   {
@@ -2744,38 +2746,30 @@
   {
     postEvent (e);
   }
 
   /**
    * Forwards AWT events to processEvent() if:<ul>
    * <li>Events have been enabled for this type of event via
    * <code>enableEvents()</code></li>,
    * <li>There is at least one registered listener for this type of event</li>
    * </ul>
    *
    * @param e the event to dispatch
    */
   public final void dispatchEvent(AWTEvent e)
   {
-    Event oldEvent = translateEvent(e);
-    if (oldEvent != null)
-      postEvent (oldEvent);
-
-    // Give toolkit a chance to dispatch the event
-    // to globally registered listeners.
-    Toolkit.getDefaultToolkit().globalDispatchEvent(e);
-
     // Some subclasses in the AWT package need to override this behavior,
     // hence the use of dispatchEventImpl().
     dispatchEventImpl(e);
   }
 
   /**
    * By default, no old mouse events should be ignored.
    * This can be overridden by subclasses.
    * 
    * @return false, no mouse events are ignored.
    */
   static boolean ignoreOldMouseEvents()
   {
     return false;
   }
@@ -2802,33 +2796,36 @@
   }
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see ComponentEvent
    * @see #removeComponentListener(ComponentListener)
    * @see #getComponentListeners()
    * @since 1.1
    */
   public synchronized void addComponentListener(ComponentListener listener)
   {
-    componentListener = AWTEventMulticaster.add(componentListener, listener);
-    if (componentListener != null)
-      enableEvents(AWTEvent.COMPONENT_EVENT_MASK);
+    if (listener != null)
+      {
+        componentListener = AWTEventMulticaster.add(componentListener,
+                                                    listener);
+        newEventsOnly = true;
+      }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see ComponentEvent
    * @see #addComponentListener(ComponentListener)
    * @see #getComponentListeners()
    * @since 1.1
    */
   public synchronized void removeComponentListener(ComponentListener listener)
   {
     componentListener = AWTEventMulticaster.remove(componentListener, listener);
@@ -2850,33 +2847,35 @@
   }
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see FocusEvent
    * @see #removeFocusListener(FocusListener)
    * @see #getFocusListeners()
    * @since 1.1
    */
   public synchronized void addFocusListener(FocusListener listener)
   {
-    focusListener = AWTEventMulticaster.add(focusListener, listener);
-    if (focusListener != null)
-      enableEvents(AWTEvent.FOCUS_EVENT_MASK);
+    if (listener != null)
+      {
+        focusListener = AWTEventMulticaster.add(focusListener, listener);
+        newEventsOnly = true;
+      }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see FocusEvent
    * @see #addFocusListener(FocusListener)
    * @see #getFocusListeners()
    * @since 1.1
    */
   public synchronized void removeFocusListener(FocusListener listener)
   {
     focusListener = AWTEventMulticaster.remove(focusListener, listener);
@@ -2897,40 +2896,43 @@
   }
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see HierarchyEvent
    * @see #removeHierarchyListener(HierarchyListener)
    * @see #getHierarchyListeners()
    * @since 1.3
    */
   public synchronized void addHierarchyListener(HierarchyListener listener)
   {
-    hierarchyListener = AWTEventMulticaster.add(hierarchyListener, listener);
-    if (hierarchyListener != null)
-      enableEvents(AWTEvent.HIERARCHY_EVENT_MASK);
-
-    // Need to lock the tree, otherwise we might end up inconsistent.
-    synchronized (getTreeLock())
+    if (listener != null)
       {
-        numHierarchyListeners++;
-        if (parent != null)
-          parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK, 1);
+        hierarchyListener = AWTEventMulticaster.add(hierarchyListener,
+                                                    listener);
+        newEventsOnly = true;
+        // Need to lock the tree, otherwise we might end up inconsistent.
+        synchronized (getTreeLock())
+        {
+          numHierarchyListeners++;
+          if (parent != null)
+            parent.updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+                                                1);
+        }
       }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see HierarchyEvent
    * @see #addHierarchyListener(HierarchyListener)
    * @see #getHierarchyListeners()
    * @since 1.3
    */
   public synchronized void removeHierarchyListener(HierarchyListener listener)
   {
@@ -2963,43 +2965,44 @@
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see HierarchyEvent
    * @see #removeHierarchyBoundsListener(HierarchyBoundsListener)
    * @see #getHierarchyBoundsListeners()
    * @since 1.3
    */
   public synchronized void
     addHierarchyBoundsListener(HierarchyBoundsListener listener)
   {
-    hierarchyBoundsListener =
-      AWTEventMulticaster.add(hierarchyBoundsListener, listener);
-    if (hierarchyBoundsListener != null)
-      enableEvents(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
-
-    // Need to lock the tree, otherwise we might end up inconsistent.
-    synchronized (getTreeLock())
+    if (listener != null)
       {
-        numHierarchyBoundsListeners++;
-        if (parent != null)
-          parent.updateHierarchyListenerCount
-                                        (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
-                                         1);
+        hierarchyBoundsListener =
+          AWTEventMulticaster.add(hierarchyBoundsListener, listener);
+        newEventsOnly = true;
+
+        // Need to lock the tree, otherwise we might end up inconsistent.
+        synchronized (getTreeLock())
+        {
+          numHierarchyBoundsListeners++;
+          if (parent != null)
+            parent.updateHierarchyListenerCount
+                                     (AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK, 1);
+        }
       }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see HierarchyEvent
    * @see #addHierarchyBoundsListener(HierarchyBoundsListener)
    * @see #getHierarchyBoundsListeners()
    * @since 1.3
    */
   public synchronized void
     removeHierarchyBoundsListener(HierarchyBoundsListener listener)
@@ -3068,33 +3071,35 @@
   }
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see KeyEvent
    * @see #removeKeyListener(KeyListener)
    * @see #getKeyListeners()
    * @since 1.1
    */
   public synchronized void addKeyListener(KeyListener listener)
   {
-    keyListener = AWTEventMulticaster.add(keyListener, listener);
-    if (keyListener != null)
-      enableEvents(AWTEvent.KEY_EVENT_MASK);
+    if (listener != null)
+      {
+        keyListener = AWTEventMulticaster.add(keyListener, listener);
+        newEventsOnly = true;
+      }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see KeyEvent
    * @see #addKeyListener(KeyListener)
    * @see #getKeyListeners()
    * @since 1.1
    */
   public synchronized void removeKeyListener(KeyListener listener)
   {
     keyListener = AWTEventMulticaster.remove(keyListener, listener);
@@ -3115,33 +3120,35 @@
   }
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see MouseEvent
    * @see #removeMouseListener(MouseListener)
    * @see #getMouseListeners()
    * @since 1.1
    */
   public synchronized void addMouseListener(MouseListener listener)
   {
-    mouseListener = AWTEventMulticaster.add(mouseListener, listener);
-    if (mouseListener != null)
-      enableEvents(AWTEvent.MOUSE_EVENT_MASK);
+    if (listener != null)
+      {
+        mouseListener = AWTEventMulticaster.add(mouseListener, listener);
+        newEventsOnly = true;
+      }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see MouseEvent
    * @see #addMouseListener(MouseListener)
    * @see #getMouseListeners()
    * @since 1.1
    */
   public synchronized void removeMouseListener(MouseListener listener)
   {
     mouseListener = AWTEventMulticaster.remove(mouseListener, listener);
@@ -3162,33 +3169,36 @@
   }
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see MouseEvent
    * @see #removeMouseMotionListener(MouseMotionListener)
    * @see #getMouseMotionListeners()
    * @since 1.1
    */
   public synchronized void addMouseMotionListener(MouseMotionListener listener)
   {
-    mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener, listener);
-    if (mouseMotionListener != null)
-      enableEvents(AWTEvent.MOUSE_MOTION_EVENT_MASK);
+    if (listener != null)
+      {
+        mouseMotionListener = AWTEventMulticaster.add(mouseMotionListener,
+                                                      listener);
+        newEventsOnly = true;
+      }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see MouseEvent
    * @see #addMouseMotionListener(MouseMotionListener)
    * @see #getMouseMotionListeners()
    * @since 1.1
    */
   public synchronized void removeMouseMotionListener(MouseMotionListener listener)
   {
     mouseMotionListener = AWTEventMulticaster.remove(mouseMotionListener, listener);
@@ -3211,33 +3221,36 @@
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see MouseEvent
    * @see MouseWheelEvent
    * @see #removeMouseWheelListener(MouseWheelListener)
    * @see #getMouseWheelListeners()
    * @since 1.4
    */
   public synchronized void addMouseWheelListener(MouseWheelListener listener)
   {
-    mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener, listener);
-    if (mouseWheelListener != null)
-      enableEvents(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
+    if (listener != null)
+      {
+        mouseWheelListener = AWTEventMulticaster.add(mouseWheelListener,
+                                                     listener);
+        newEventsOnly = true;
+      }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see MouseEvent
    * @see MouseWheelEvent
    * @see #addMouseWheelListener(MouseWheelListener)
    * @see #getMouseWheelListeners()
    * @since 1.4
    */
   public synchronized void removeMouseWheelListener(MouseWheelListener listener)
   {
@@ -3261,33 +3274,36 @@
 
   /**
    * Adds the specified listener to this component. This is harmless if the
    * listener is null, but if the listener has already been registered, it
    * will now be registered twice.
    *
    * @param listener the new listener to add
    * @see InputMethodEvent
    * @see #removeInputMethodListener(InputMethodListener)
    * @see #getInputMethodListeners()
    * @see #getInputMethodRequests()
    * @since 1.2
    */
   public synchronized void addInputMethodListener(InputMethodListener listener)
   {
-    inputMethodListener = AWTEventMulticaster.add(inputMethodListener, listener);
-    if (inputMethodListener != null)
-      enableEvents(AWTEvent.INPUT_METHOD_EVENT_MASK);
+    if (listener != null)
+      {
+        inputMethodListener = AWTEventMulticaster.add(inputMethodListener,
+                                                      listener);
+        newEventsOnly = true;
+      }
   }
 
   /**
    * Removes the specified listener from the component. This is harmless if
    * the listener was not previously registered.
    *
    * @param listener the listener to remove
    * @see InputMethodEvent
    * @see #addInputMethodListener(InputMethodListener)
    * @see #getInputMethodRequests()
    * @since 1.2
    */
   public synchronized void removeInputMethodListener(InputMethodListener listener)
   {
     inputMethodListener = AWTEventMulticaster.remove(inputMethodListener, listener);
@@ -3500,43 +3516,60 @@
   }
 
   /**
    * This is called by the EventQueue if two events with the same event id
    * and owner component are queued. Returns a new combined event, or null if
    * no combining is done. The coelesced events are currently mouse moves
    * (intermediate ones are discarded) and paint events (a merged paint is
    * created in place of the two events).
    *
    * @param existingEvent the event on the queue
    * @param newEvent the new event that might be entered on the queue
    * @return null if both events are kept, or the replacement coelesced event
    */
   protected AWTEvent coalesceEvents(AWTEvent existingEvent, AWTEvent newEvent)
   {
+    AWTEvent coalesced = null;
     switch (existingEvent.id)
       {
       case MouseEvent.MOUSE_MOVED:
       case MouseEvent.MOUSE_DRAGGED:
         // Just drop the old (intermediate) event and return the new one.
-        return newEvent;
+        MouseEvent me1 = (MouseEvent) existingEvent;
+        MouseEvent me2 = (MouseEvent) newEvent;
+        if (me1.getModifiers() == me2.getModifiers())
+          coalesced = newEvent;
+        break;
       case PaintEvent.PAINT:
       case PaintEvent.UPDATE:
-        return coalescePaintEvents((PaintEvent) existingEvent,
-                                   (PaintEvent) newEvent);
+        // For heavyweights the EventQueue should ask the peer.
+        if (peer == null || peer instanceof LightweightPeer)
+          {
+            PaintEvent pe1 = (PaintEvent) existingEvent;
+            PaintEvent pe2 = (PaintEvent) newEvent;
+            Rectangle r1 = pe1.getUpdateRect();
+            Rectangle r2 = pe2.getUpdateRect();
+            if (r1.contains(r2))
+              coalesced = existingEvent;
+            else if (r2.contains(r1))
+              coalesced = newEvent;
+          }
+        break;
       default:
-        return null;
+        coalesced = null;
       }
+    return coalesced;
   }
 
   /**
    * Processes the specified event. In this class, this method simply
    * calls one of the more specific event handlers.
    *
    * @param e the event to process
    * @throws NullPointerException if e is null
    * @see #processComponentEvent(ComponentEvent)
    * @see #processFocusEvent(FocusEvent)
    * @see #processKeyEvent(KeyEvent)
    * @see #processMouseEvent(MouseEvent)
    * @see #processMouseMotionEvent(MouseEvent)
    * @see #processInputMethodEvent(InputMethodEvent)
    * @see #processHierarchyEvent(HierarchyEvent)
@@ -5587,35 +5620,45 @@
 
   void dispatchEventImpl(AWTEvent e)
   {
     // Retarget focus events before dispatching it to the KeyboardFocusManager
     // in order to handle lightweight components properly.
     boolean dispatched = false;
     if (! e.isFocusManagerEvent)
       {
         e = KeyboardFocusManager.retargetFocusEvent(e);
         dispatched = KeyboardFocusManager.getCurrentKeyboardFocusManager()
                                           .dispatchEvent(e);
       }
 
     if (! dispatched)
       {
-        if (eventTypeEnabled (e.id))
+        // Give toolkit a chance to dispatch the event
+        // to globally registered listeners.
+        Toolkit.getDefaultToolkit().globalDispatchEvent(e);
+
+        if (newEventsOnly)
           {
-            if (e.id != PaintEvent.PAINT && e.id != PaintEvent.UPDATE)
+            if (eventTypeEnabled(e.id))
               processEvent(e);
           }
+        else
+          {
+            Event oldEvent = translateEvent(e);
+            if (oldEvent != null)
+              postEvent (oldEvent);
+          }
         if (peer != null)
           peer.handleEvent(e);
       }
   }
 
   /**
    * Tells whether or not an event type is enabled.
    */
   boolean eventTypeEnabled (int type)
   {
     if (type > AWTEvent.RESERVED_ID_MAX)
       return true;
 
     switch (type)
       {
@@ -5684,69 +5727,30 @@
    */
   boolean isHierarchyVisible()
   {
     boolean visible = isVisible();
     Component comp = parent;
     while (comp != null && visible)
       {
         comp = comp.parent;
         if (comp != null)
           visible = visible && comp.isVisible();
       }
     return visible;
   }
 
   /**
-   * Coalesce paint events. Current heuristic is: Merge if the union of
-   * areas is less than twice that of the sum of the areas. The X server
-   * tend to create a lot of paint events that are adjacent but not
-   * overlapping.
-   *
-   * <pre>
-   * +------+
-   * |      +-----+  ...will be merged
-   * |      |     |
-   * |      |     |
-   * +------+     |
-   *        +-----+
-   *
-   * +---------------+--+
-   * |               |  |  ...will not be merged
-   * +---------------+  |
-   *                 |  |
-   *                 |  |
-   *                 |  |
-   *                 |  |
-   *                 |  |
-   *                 +--+
-   * </pre>
-   *
-   * @param queuedEvent the first paint event
-   * @param newEvent the second paint event
-   * @return the combined paint event, or null
-   */
-  private PaintEvent coalescePaintEvents(PaintEvent queuedEvent,
-                                         PaintEvent newEvent)
-  {
-    Rectangle r1 = queuedEvent.getUpdateRect();
-    Rectangle r2 = newEvent.getUpdateRect();
-    Rectangle union = r1.union(r2);
-    newEvent.setUpdateRect(union);
-    return newEvent;
-  }
-
-  /**
    * This method is used to implement transferFocus(). CHILD is the child
    * making the request. This is overridden by Container; when called for an
    * ordinary component there is no child and so we always return null.
    *
    * FIXME: is this still needed, in light of focus traversal policies?
    *
    * @param child the component making the request
    * @return the next component to focus on
    */
   Component findNextFocusComponent(Component child)
   {
     return null;
   }
 
   /**
@@ -5862,31 +5866,31 @@
      * @param event the <code>ComponentEvent</code> indicating the visibility
      */
     public void componentShown(ComponentEvent event)
     {
       if (isShowing())
         peer.show();
     }
 
     /**
      * This method is called when the component is hidden.
      * 
      * @param event the <code>ComponentEvent</code> indicating the visibility
      */
     public void componentHidden(ComponentEvent event)
     {
-      if (!isShowing())
+      if (isShowing())
         peer.hide();
     }
   }
   
   /**
    * This class provides accessibility support for subclasses of container.
    *
    * @author Eric Blake ([EMAIL PROTECTED])
    * @since 1.3
    * @status updated to 1.4
    */
   protected abstract class AccessibleAWTComponent extends AccessibleContext
     implements Serializable, AccessibleComponent
   {
     /**
Index: java/awt/Container.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/awt/Container.java,v
retrieving revision 1.104
diff -u -1 -5 -r1.104 Container.java
--- java/awt/Container.java	23 Aug 2006 14:23:27 -0000	1.104
+++ java/awt/Container.java	18 Sep 2006 13:22:16 -0000
@@ -318,37 +318,30 @@
             || comp instanceof Window
             || (comp instanceof Container
                 && ((Container) comp).isAncestorOf(this)))
           throw new IllegalArgumentException();
 
         // Reparent component, and make sure component is instantiated if
         // we are.
         if (comp.parent != null)
           comp.parent.remove(comp);
         comp.parent = this;
 
         if (peer != null)
           {
 	    // Notify the component that it has a new parent.
 	    comp.addNotify();
-
-            if (comp.isLightweight ())
-	      {
-		enableEvents (comp.eventMask);
-		if (!isLightweight ())
-		  enableEvents (AWTEvent.PAINT_EVENT_MASK);
-	      }
           }
 
         // Invalidate the layout of the added component and its ancestors.
         comp.invalidate();
 
         if (component == null)
           component = new Component[4]; // FIXME, better initial size?
    
         // This isn't the most efficient implementation.  We could do less
         // copying when growing the array.  It probably doesn't matter.
         if (ncomponents >= component.length)
           {
             int nl = component.length * 2;
             Component[] c = new Component[nl];
             System.arraycopy(component, 0, c, 0, ncomponents);
@@ -405,66 +398,67 @@
         // Notify hierarchy listeners.
         comp.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, comp,
                                 this, HierarchyEvent.PARENT_CHANGED);
       }
   }
 
   /**
    * Removes the component at the specified index from this container.
    *
    * @param index The index of the component to remove.
    */
   public void remove(int index)
   {
     synchronized (getTreeLock ())
       {
-        Component r = component[index];
+        if (index < 0 || index >= ncomponents)
+          throw new ArrayIndexOutOfBoundsException();
 
-        ComponentListener[] list = r.getComponentListeners();
-        for (int j = 0; j < list.length; j++)
-              r.removeComponentListener(list[j]);
-        
-        r.removeNotify();
+        Component r = component[index];
+        if (peer != null)
+          r.removeNotify();
 
-        System.arraycopy(component, index + 1, component, index,
-                         ncomponents - index - 1);
-        component[--ncomponents] = null;
+        if (layoutMgr != null)
+          layoutMgr.removeLayoutComponent(r);
 
         // Update the counter for Hierarchy(Bounds)Listeners.
         int childHierarchyListeners = r.numHierarchyListeners;
         if (childHierarchyListeners > 0)
           updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
                                        -childHierarchyListeners);
         int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
         if (childHierarchyBoundsListeners > 0)
           updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
                                        -childHierarchyListeners);
 
-        invalidate();
+        r.parent = null;
 
-        if (layoutMgr != null)
-          layoutMgr.removeLayoutComponent(r);
+        System.arraycopy(component, index + 1, component, index,
+                         ncomponents - index - 1);
+        component[--ncomponents] = null;
 
-        r.parent = null;
+        if (valid)
+          invalidate();
 
-        if (isShowing ())
+        if (containerListener != null
+            || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
           {
             // Post event to notify of removing the component.
             ContainerEvent ce = new ContainerEvent(this,
-                                               ContainerEvent.COMPONENT_REMOVED,
-                                               r);
-            getToolkit().getSystemEventQueue().postEvent(ce);
+                                              ContainerEvent.COMPONENT_REMOVED,
+                                              r);
+            dispatchEvent(ce);
           }
 
         // Notify hierarchy listeners.
         r.fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r,
                              this, HierarchyEvent.PARENT_CHANGED);
       }
   }
 
   /**
    * Removes the specified component from this container.
    *
    * @param comp The component to remove from this container.
    */
   public void remove(Component comp)
   {
@@ -484,77 +478,75 @@
   /**
    * Removes all components from this container.
    */
   public void removeAll()
   {
     synchronized (getTreeLock ())
       {
         // In order to allow the same bad tricks to be used as in RI
         // this code has to stay exactly that way: In a real-life app
         // a Container subclass implemented its own vector for
         // subcomponents, supplied additional addXYZ() methods
         // and overrode remove(int) and removeAll (the latter calling
         // super.removeAll() ).
         // By doing it this way, user code cannot prevent the correct
         // removal of components.
-        for ( int index = 0; index < ncomponents; index++)
+        while (ncomponents > 0)
           {
-            Component r = component[index];
+            ncomponents--;
+            Component r = component[ncomponents];
+            component[ncomponents] = null;
 
-            ComponentListener[] list = r.getComponentListeners();
-            for (int j = 0; j < list.length; j++)
-              r.removeComponentListener(list[j]);
-            
-            r.removeNotify();
-
-            // Update the counter for Hierarchy(Bounds)Listeners.
-            int childHierarchyListeners = r.numHierarchyListeners;
-            if (childHierarchyListeners > 0)
-              updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
-                                           -childHierarchyListeners);
-            int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
-            if (childHierarchyBoundsListeners > 0)
-              updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
-                                           -childHierarchyListeners);
+            if (peer != null)
+              r.removeNotify();
 
             if (layoutMgr != null)
               layoutMgr.removeLayoutComponent(r);
 
             r.parent = null;
 
             // Send ContainerEvent if necessary.
             if (containerListener != null
                 || (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0)
               {
                 // Post event to notify of removing the component.
                 ContainerEvent ce
                   = new ContainerEvent(this,
                                        ContainerEvent.COMPONENT_REMOVED,
                                        r);
                 dispatchEvent(ce);
               }
 
+            // Update the counter for Hierarchy(Bounds)Listeners.
+            int childHierarchyListeners = r.numHierarchyListeners;
+            if (childHierarchyListeners > 0)
+              updateHierarchyListenerCount(AWTEvent.HIERARCHY_EVENT_MASK,
+                                           -childHierarchyListeners);
+            int childHierarchyBoundsListeners = r.numHierarchyBoundsListeners;
+            if (childHierarchyBoundsListeners > 0)
+              updateHierarchyListenerCount(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
+                                           -childHierarchyListeners);
+
+
             // Send HierarchyEvent if necessary.
             fireHierarchyEvent(HierarchyEvent.HIERARCHY_CHANGED, r, this,
                                HierarchyEvent.PARENT_CHANGED);
 
           }
 
         if (valid)
           invalidate();
-        
-        ncomponents = 0;
       }
   }
 
   /**
    * Returns the current layout manager for this container.
    *
    * @return The layout manager for this container.
    */
   public LayoutManager getLayout()
   {
     return layoutMgr;
   }
 
   /**
    * Sets the layout manager for this container to the specified layout
@@ -783,32 +775,33 @@
    *
    * @return The maximum size of this container.
    */
   public Dimension getMaximumSize()
   {
     Dimension size = maxSize;
     // Try to return cached value if possible.
     if (size == null || !(maxSizeSet || valid))
       {
         // Need to lock here.
         synchronized (getTreeLock())
           {
             LayoutManager l = layoutMgr;
             if (l instanceof LayoutManager2)
               maxSize = ((LayoutManager2) l).maximumLayoutSize(this);
-            else
+            else {
               maxSize = super.maximumSizeImpl();
+            }
             size = maxSize;
           }
       }
     if (size != null)
       return new Dimension(size);
     else
       return size;
   }
 
   /**
    * Returns the preferred alignment along the X axis.  This is a value
    * between 0 and 1 where 0 represents alignment flush left and
    * 1 means alignment flush right, and 0.5 means centered.
    *
    * @return The preferred alignment along the X axis.
@@ -919,32 +912,32 @@
    * @param g The graphics context for this print job.
    */
   public void print(Graphics g)
   {
     super.print(g);
     visitChildren(g, GfxPrintVisitor.INSTANCE, true);
   }
 
   /**
    * Paints all of the components in this container.
    *
    * @param g The graphics context for this paint job.
    */
   public void paintComponents(Graphics g)
   {
-    paint(g);
-    visitChildren(g, GfxPaintAllVisitor.INSTANCE, true);
+    if (isShowing())
+      visitChildren(g, GfxPaintAllVisitor.INSTANCE, false);
   }
 
   /**
    * Prints all of the components in this container.
    *
    * @param g The graphics context for this print job.
    */
   public void printComponents(Graphics g)
   {
     super.paint(g);
     visitChildren(g, GfxPrintAllVisitor.INSTANCE, true);
   }
 
   /**
    * Adds the specified container listener to this object's list of
@@ -1246,32 +1239,38 @@
       {
         super.addNotify();
         addNotifyContainerChildren();
       }
   }
 
   /**
    * Called when this container is removed from its parent container to
    * inform it to destroy its peer.  This causes the peers of all child
    * component to be destroyed as well.
    */
   public void removeNotify()
   {
     synchronized (getTreeLock ())
       {
-        for (int i = 0; i < ncomponents; ++i)
-          component[i].removeNotify();
+        int ncomps = ncomponents;
+        Component[] comps = component;
+        for (int i = ncomps - 1; i >= 0; --i)
+          {
+            Component comp = comps[i];
+            if (comp != null)
+              comp.removeNotify();
+          }
         super.removeNotify();
       }
   }
 
   /**
    * Tests whether or not the specified component is contained within
    * this components subtree.
    *
    * @param comp The component to test.
    *
    * @return <code>true</code> if this container is an ancestor of the
    * specified component, <code>false</code> otherwise.
    */
   public boolean isAncestorOf(Component comp)
   {
@@ -2047,36 +2046,30 @@
                 Component child = getComponent(i);
                 child.fireHierarchyEvent(HierarchyEvent.ANCESTOR_MOVED,
                                          this, parent, 0);
               }
           }
       }
   }
 
   private void addNotifyContainerChildren()
   {
     synchronized (getTreeLock ())
       {
         for (int i = ncomponents;  --i >= 0; )
           {
             component[i].addNotify();
-            if (component[i].isLightweight ())
-	      {
-		enableEvents(component[i].eventMask);
-		if (peer != null && !isLightweight ())
-		  enableEvents (AWTEvent.PAINT_EVENT_MASK);
-	      }
           }
       }
   }
 
   /**
    * Deserialize this Container:
    * <ol>
    * <li>Read from the stream the default serializable fields.</li>
    * <li>Read a list of serializable ContainerListeners as optional
    * data.  If the list is null, no listeners will be registered.</li>
    * <li>Read this Container's FocusTraversalPolicy as optional data.
    * If this is null, then this Container will use a
    * DefaultFocusTraversalPolicy.</li>
    * </ol>
    *

Reply via email to