/*
 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package javax.swing;


import java.awt.*;
import java.awt.event.*;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.image.VolatileImage;
import java.security.AccessController;
import java.util.*;
import java.applet.*;

import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.DisplayChangedListener;
import sun.awt.SunToolkit;
import sun.java2d.SunGraphicsEnvironment;
import sun.security.action.GetPropertyAction;

import com.sun.java.swing.SwingUtilities3;

/**
 * This class manages repaint requests, allowing the number
 * of repaints to be minimized, for example by collapsing multiple
 * requests into a single repaint for members of a component tree.
 * <p>
 * As of 1.6 <code>RepaintManager</code> handles repaint requests
 * for Swing's top level components (<code>JApplet</code>,
 * <code>JWindow</code>, <code>JFrame</code> and <code>JDialog</code>).
 * Any calls to <code>repaint</code> on one of these will call into the
 * appropriate <code>addDirtyRegion</code> method.
 *
 * @author Arnaud Weber
 */
public class RepaintManager
{
    /**
     * Whether or not the RepaintManager should handle paint requests
     * for top levels.
     */
    static final boolean HANDLE_TOP_LEVEL_PAINT;

    private static final short BUFFER_STRATEGY_NOT_SPECIFIED = 0;
    private static final short BUFFER_STRATEGY_SPECIFIED_ON = 1;
    private static final short BUFFER_STRATEGY_SPECIFIED_OFF = 2;

    private static final short BUFFER_STRATEGY_TYPE;

    /**
     * Maps from GraphicsConfiguration to VolatileImage.
     */
    private Map<GraphicsConfiguration,VolatileImage> volatileMap = new
                        HashMap<GraphicsConfiguration,VolatileImage>(1);

    //
    // As of 1.6 Swing handles scheduling of paint events from native code.
    // That is, SwingPaintEventDispatcher is invoked on the toolkit thread,
    // which in turn invokes nativeAddDirtyRegion.  Because this is invoked
    // from the native thread we can not invoke any public methods and so
    // we introduce these added maps.  So, any time nativeAddDirtyRegion is
    // invoked the region is added to hwDirtyComponents and a work request
    // is scheduled.  When the work request is processed all entries in
    // this map are pushed to the real map (dirtyComponents) and then
    // painted with the rest of the components.
    //
    private Map<Container,Rectangle> hwDirtyComponents;

    private Map<Component,Rectangle> dirtyComponents;
    private Map<Component,Rectangle> tmpDirtyComponents;
    private java.util.List<Component> invalidComponents;

    // List of Runnables that need to be processed before painting from AWT.
    private java.util.List<Runnable> runnableList;

    boolean   doubleBufferingEnabled = true;

    private Dimension doubleBufferMaxSize;

    // Support for both the standard and volatile offscreen buffers exists to
    // provide backwards compatibility for the [rare] programs which may be
    // calling getOffScreenBuffer() and not expecting to get a VolatileImage.
    // Swing internally is migrating to use *only* the volatile image buffer.

    // Support for standard offscreen buffer
    //
    DoubleBufferInfo standardDoubleBuffer;

    /**
     * Object responsible for hanlding core paint functionality.
     */
    private PaintManager paintManager;

    private static final Object repaintManagerKey = RepaintManager.class;

    // Whether or not a VolatileImage should be used for double-buffered painting
    static boolean volatileImageBufferEnabled = true;
    /**
     * Value of the system property awt.nativeDoubleBuffering.
     */
    private static boolean nativeDoubleBuffering;

    // The maximum number of times Swing will attempt to use the VolatileImage
    // buffer during a paint operation.
    private static final int VOLATILE_LOOP_MAX = 2;

    /**
     * Number of <code>beginPaint</code> that have been invoked.
     */
    private int paintDepth = 0;

    /**
     * Type of buffer strategy to use.  Will be one of the BUFFER_STRATEGY_
     * constants.
     */
    private short bufferStrategyType;

    //
    // BufferStrategyPaintManager has the unique characteristic that it
    // must deal with the buffer being lost while painting to it.  For
    // example, if we paint a component and show it and the buffer has
    // become lost we must repaint the whole window.  To deal with that
    // the PaintManager calls into repaintRoot, and if we're still in
    // the process of painting the repaintRoot field is set to the JRootPane
    // and after the current JComponent.paintImmediately call finishes
    // paintImmediately will be invoked on the repaintRoot.  In this
    // way we don't try to show garbage to the screen.
    //
    /**
     * True if we're in the process of painting the dirty regions.  This is
     * set to true in <code>paintDirtyRegions</code>.
     */
    private boolean painting;
    /**
     * If the PaintManager calls into repaintRoot during painting this field
     * will be set to the root.
     */
    private JComponent repaintRoot;

    /**
     * The Thread that has initiated painting.  If null it
     * indicates painting is not currently in progress.
     */
    private Thread paintThread;

    /**
     * Runnable used to process all repaint/revalidate requests.
     */
    private final ProcessingRunnable processingRunnable;


    static {
        volatileImageBufferEnabled = "true".equals(AccessController.
                doPrivileged(new GetPropertyAction(
                "swing.volatileImageBufferEnabled", "true")));
        boolean headless = GraphicsEnvironment.isHeadless();
        if (volatileImageBufferEnabled && headless) {
            volatileImageBufferEnabled = false;
        }
        nativeDoubleBuffering = "true".equals(AccessController.doPrivileged(
                    new GetPropertyAction("awt.nativeDoubleBuffering")));
        String bs = AccessController.doPrivileged(
                          new GetPropertyAction("swing.bufferPerWindow"));
        if (headless) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
        }
        else if (bs == null) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_NOT_SPECIFIED;
        }
        else if ("true".equals(bs)) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_ON;
        }
        else {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
        }
        HANDLE_TOP_LEVEL_PAINT = "true".equals(AccessController.doPrivileged(
               new GetPropertyAction("swing.handleTopLevelPaint", "true")));
        GraphicsEnvironment ge = GraphicsEnvironment.
                getLocalGraphicsEnvironment();
        if (ge instanceof SunGraphicsEnvironment) {
            ((SunGraphicsEnvironment)ge).addDisplayChangedListener(
                    new DisplayChangedHandler());
        }
    }

    /**
     * Return the RepaintManager for the calling thread given a Component.
     *
     * @param c a Component -- unused in the default implementation, but could
     *          be used by an overridden version to return a different RepaintManager
     *          depending on the Component
     * @return the RepaintManager object
     */
    public static RepaintManager currentManager(Component c) {
        // Note: DisplayChangedRunnable passes in null as the component, so if
        // component is ever used to determine the current
        // RepaintManager, DisplayChangedRunnable will need to be modified
        // accordingly.
        return currentManager(AppContext.getAppContext());
    }

    /**
     * Returns the RepaintManager for the specified AppContext.  If
     * a RepaintManager has not been created for the specified
     * AppContext this will return null.
     */
    static RepaintManager currentManager(AppContext appContext) {
        RepaintManager rm = (RepaintManager)appContext.get(repaintManagerKey);
        if (rm == null) {
            rm = new RepaintManager(BUFFER_STRATEGY_TYPE);
            appContext.put(repaintManagerKey, rm);
        }
        return rm;
    }

    /**
     * Return the RepaintManager for the calling thread given a JComponent.
     * <p>
    * Note: This method exists for backward binary compatibility with earlier
     * versions of the Swing library. It simply returns the result returned by
     * {@link #currentManager(Component)}.
     *
     * @param c a JComponent -- unused
     * @return the RepaintManager object
     */
    public static RepaintManager currentManager(JComponent c) {
        return currentManager((Component)c);
    }


    /**
     * Set the RepaintManager that should be used for the calling
     * thread. <b>aRepaintManager</b> will become the current RepaintManager
     * for the calling thread's thread group.
     * @param aRepaintManager  the RepaintManager object to use
     */
    public static void setCurrentManager(RepaintManager aRepaintManager) {
        if (aRepaintManager != null) {
            SwingUtilities.appContextPut(repaintManagerKey, aRepaintManager);
        } else {
            SwingUtilities.appContextRemove(repaintManagerKey);
        }
    }

    /**
     * Create a new RepaintManager instance. You rarely call this constructor.
     * directly. To get the default RepaintManager, use
     * RepaintManager.currentManager(JComponent) (normally "this").
     */
    public RepaintManager() {
        // Because we can't know what a subclass is doing with the
        // volatile image we immediately punt in subclasses.  If this
        // poses a problem we'll need a more sophisticated detection algorithm,
        // or API.
        this(BUFFER_STRATEGY_SPECIFIED_OFF);
    }

    private RepaintManager(short bufferStrategyType) {
        // If native doublebuffering is being used, do NOT use
        // Swing doublebuffering.
        doubleBufferingEnabled = !nativeDoubleBuffering;
        synchronized(this) {
            dirtyComponents = new IdentityHashMap<Component,Rectangle>();
            tmpDirtyComponents = new IdentityHashMap<Component,Rectangle>();
            this.bufferStrategyType = bufferStrategyType;
            hwDirtyComponents = new IdentityHashMap<Container,Rectangle>();
        }
        processingRunnable = new ProcessingRunnable();
    }

    private void displayChanged() {
        clearImages();
    }

    /**
     * Mark the component as in need of layout and queue a runnable
     * for the event dispatching thread that will validate the components
     * first isValidateRoot() ancestor.
     *
     * @see JComponent#isValidateRoot
     * @see #removeInvalidComponent
     */
    public synchronized void addInvalidComponent(JComponent invalidComponent)
    {
        RepaintManager delegate = getDelegate(invalidComponent);
        if (delegate != null) {
            delegate.addInvalidComponent(invalidComponent);
            return;
        }
        Component validateRoot =
            SwingUtilities.getValidateRoot(invalidComponent, true);

        if (validateRoot == null) {
            return;
        }

        /* Lazily create the invalidateComponents vector and add the
         * validateRoot if it's not there already.  If this validateRoot
         * is already in the vector, we're done.
         */
        if (invalidComponents == null) {
            invalidComponents = new ArrayList<Component>();
        }
        else {
            int n = invalidComponents.size();
            for(int i = 0; i < n; i++) {
                if(validateRoot == invalidComponents.get(i)) {
                    return;
                }
            }
        }
        invalidComponents.add(validateRoot);

        // Queue a Runnable to invoke paintDirtyRegions and
        // validateInvalidComponents.
        scheduleProcessingRunnable();
    }


    /**
     * Remove a component from the list of invalid components.
     *
     * @see #addInvalidComponent
     */
    public synchronized void removeInvalidComponent(JComponent component) {
        RepaintManager delegate = getDelegate(component);
        if (delegate != null) {
            delegate.removeInvalidComponent(component);
            return;
        }
        if(invalidComponents != null) {
            int index = invalidComponents.indexOf(component);
            if(index != -1) {
                invalidComponents.remove(index);
            }
        }
    }


    /**
     * Add a component in the list of components that should be refreshed.
     * If <i>c</i> already has a dirty region, the rectangle <i>(x,y,w,h)</i>
     * will be unioned with the region that should be redrawn.
     *
     * @see JComponent#repaint
     */
    private void addDirtyRegion0(Container c, int x, int y, int w, int h) {
        /* Special cases we don't have to bother with.
         */
        if ((w <= 0) || (h <= 0) || (c == null)) {
            return;
        }

        if ((c.getWidth() <= 0) || (c.getHeight() <= 0)) {
            return;
        }

        if (extendDirtyRegion(c, x, y, w, h)) {
            // Component was already marked as dirty, region has been
            // extended, no need to continue.
            return;
        }

        /* Make sure that c and all it ancestors (up to an Applet or
         * Window) are visible.  This loop has the same effect as
         * checking c.isShowing() (and note that it's still possible
         * that c is completely obscured by an opaque ancestor in
         * the specified rectangle).
         */
        Component root = null;

        // Note: We can't synchronize around this, Frame.getExtendedState
        // is synchronized so that if we were to synchronize around this
        // it could lead to the possibility of getting locks out
        // of order and deadlocking.
        for (Container p = c; p != null; p = p.getParent()) {
            if (!p.isVisible() || (p.getPeer() == null)) {
                return;
            }
            if ((p instanceof Window) || (p instanceof Applet)) {
                // Iconified frames are still visible!
                if (p instanceof Frame &&
                        (((Frame)p).getExtendedState() & Frame.ICONIFIED) ==
                                    Frame.ICONIFIED) {
                    return;
                }
                root = p;
                break;
            }
        }

        if (root == null) return;

        synchronized(this) {
            if (extendDirtyRegion(c, x, y, w, h)) {
                // In between last check and this check another thread
                // queued up runnable, can bail here.
                return;
            }
            dirtyComponents.put(c, new Rectangle(x, y, w, h));
        }

        // Queue a Runnable to invoke paintDirtyRegions and
        // validateInvalidComponents.
        scheduleProcessingRunnable();
    }

    /**
     * Add a component in the list of components that should be refreshed.
     * If <i>c</i> already has a dirty region, the rectangle <i>(x,y,w,h)</i>
     * will be unioned with the region that should be redrawn.
     *
     * @param c Component to repaint, null results in nothing happening.
     * @param x X coordinate of the region to repaint
     * @param y Y coordinate of the region to repaint
     * @param w Width of the region to repaint
     * @param h Height of the region to repaint
     * @see JComponent#repaint
     */
    public void addDirtyRegion(JComponent c, int x, int y, int w, int h)
    {
        RepaintManager delegate = getDelegate(c);
        if (delegate != null) {
            delegate.addDirtyRegion(c, x, y, w, h);
            return;
        }
        addDirtyRegion0(c, x, y, w, h);
    }

    /**
     * Adds <code>window</code> to the list of <code>Component</code>s that
     * need to be repainted.
     *
     * @param window Window to repaint, null results in nothing happening.
     * @param x X coordinate of the region to repaint
     * @param y Y coordinate of the region to repaint
     * @param w Width of the region to repaint
     * @param h Height of the region to repaint
     * @see JFrame#repaint
     * @see JWindow#repaint
     * @see JDialog#repaint
     * @since 1.6
     */
    public void addDirtyRegion(Window window, int x, int y, int w, int h) {
        addDirtyRegion0(window, x, y, w, h);
    }

    /**
     * Adds <code>applet</code> to the list of <code>Component</code>s that
     * need to be repainted.
     *
     * @param applet Applet to repaint, null results in nothing happening.
     * @param x X coordinate of the region to repaint
     * @param y Y coordinate of the region to repaint
     * @param w Width of the region to repaint
     * @param h Height of the region to repaint
     * @see JApplet#repaint
     * @since 1.6
     */
    public void addDirtyRegion(Applet applet, int x, int y, int w, int h) {
        addDirtyRegion0(applet, x, y, w, h);
    }

    void scheduleHeavyWeightPaints() {
        Map<Container,Rectangle> hws;

        synchronized(this) {
            if (hwDirtyComponents.size() == 0) {
                return;
            }
            hws = hwDirtyComponents;
            hwDirtyComponents =  new IdentityHashMap<Container,Rectangle>();
        }
        for (Container hw : hws.keySet()) {
            Rectangle dirty = hws.get(hw);
            if (hw instanceof Window) {
                addDirtyRegion((Window)hw, dirty.x, dirty.y,
                               dirty.width, dirty.height);
            }
            else if (hw instanceof Applet) {
                addDirtyRegion((Applet)hw, dirty.x, dirty.y,
                               dirty.width, dirty.height);
            }
            else { // SwingHeavyWeight
                addDirtyRegion0(hw, dirty.x, dirty.y,
                                dirty.width, dirty.height);
            }
        }
    }

    //
    // This is called from the toolkit thread when a native expose is
    // received.
    //
    void nativeAddDirtyRegion(AppContext appContext, Container c,
                              int x, int y, int w, int h) {
        if (w > 0 && h > 0) {
            synchronized(this) {
                Rectangle dirty = hwDirtyComponents.get(c);
                if (dirty == null) {
                    hwDirtyComponents.put(c, new Rectangle(x, y, w, h));
                }
                else {
                    hwDirtyComponents.put(c, SwingUtilities.computeUnion(
                                              x, y, w, h, dirty));
                }
            }
            scheduleProcessingRunnable(appContext);
        }
    }

    //
    // This is called from the toolkit thread when awt needs to run a
    // Runnable before we paint.
    //
    void nativeQueueSurfaceDataRunnable(AppContext appContext, Component c,
                                        Runnable r) {
        synchronized(this) {
            if (runnableList == null) {
                runnableList = new LinkedList<Runnable>();
            }
            runnableList.add(r);
        }
        scheduleProcessingRunnable(appContext);
    }

    /**
     * Extends the dirty region for the specified component to include
     * the new region.
     *
     * @return false if <code>c</code> is not yet marked dirty.
     */
    private synchronized boolean extendDirtyRegion(
        Component c, int x, int y, int w, int h) {
        Rectangle r = dirtyComponents.get(c);
        if (r != null) {
            // A non-null r implies c is already marked as dirty,
            // and that the parent is valid. Therefore we can
            // just union the rect and bail.
            SwingUtilities.computeUnion(x, y, w, h, r);
            return true;
        }
        return false;
    }

    /** Return the current dirty region for a component.
     *  Return an empty rectangle if the component is not
     *  dirty.
     */
    public Rectangle getDirtyRegion(JComponent aComponent) {
        RepaintManager delegate = getDelegate(aComponent);
        if (delegate != null) {
            return delegate.getDirtyRegion(aComponent);
        }
        Rectangle r;
        synchronized(this) {
            r = dirtyComponents.get(aComponent);
        }
        if(r == null)
            return new Rectangle(0,0,0,0);
        else
            return new Rectangle(r);
    }

    /**
     * Mark a component completely dirty. <b>aComponent</b> will be
     * completely painted during the next paintDirtyRegions() call.
     */
    public void markCompletelyDirty(JComponent aComponent) {
        RepaintManager delegate = getDelegate(aComponent);
        if (delegate != null) {
            delegate.markCompletelyDirty(aComponent);
            return;
        }
        addDirtyRegion(aComponent,0,0,Integer.MAX_VALUE,Integer.MAX_VALUE);
    }

    /**
     * Mark a component completely clean. <b>aComponent</b> will not
     * get painted during the next paintDirtyRegions() call.
     */
    public void markCompletelyClean(JComponent aComponent) {
        RepaintManager delegate = getDelegate(aComponent);
        if (delegate != null) {
            delegate.markCompletelyClean(aComponent);
            return;
        }
        synchronized(this) {
                dirtyComponents.remove(aComponent);
        }
    }

    /**
     * Convenience method that returns true if <b>aComponent</b> will be completely
     * painted during the next paintDirtyRegions(). If computing dirty regions is
     * expensive for your component, use this method and avoid computing dirty region
     * if it return true.
     */
    public boolean isCompletelyDirty(JComponent aComponent) {
        RepaintManager delegate = getDelegate(aComponent);
        if (delegate != null) {
            return delegate.isCompletelyDirty(aComponent);
        }
        Rectangle r;

        r = getDirtyRegion(aComponent);
        if(r.width == Integer.MAX_VALUE &&
           r.height == Integer.MAX_VALUE)
            return true;
        else
            return false;
    }


    /**
     * Validate all of the components that have been marked invalid.
     * @see #addInvalidComponent
     */
    public void validateInvalidComponents() {
        java.util.List<Component> ic;
        synchronized(this) {
            if(invalidComponents == null) {
                return;
            }
            ic = invalidComponents;
            invalidComponents = null;
        }
        int n = ic.size();
        for(int i = 0; i < n; i++) {
            ic.get(i).validate();
        }
    }


    /**
     * This is invoked to process paint requests.  It's needed
     * for backward compatability in so far as RepaintManager would previously
     * not see paint requests for top levels, so, we have to make sure
     * a subclass correctly paints any dirty top levels.
     */
    private void prePaintDirtyRegions() {
        Map<Component,Rectangle> dirtyComponents;
        java.util.List<Runnable> runnableList;
        synchronized(this) {
            dirtyComponents = this.dirtyComponents;
            runnableList = this.runnableList;
            this.runnableList = null;
        }
        if (runnableList != null) {
            for (Runnable runnable : runnableList) {
                runnable.run();
            }
        }
        paintDirtyRegions();
        if (dirtyComponents.size() > 0) {
            // This'll only happen if a subclass isn't correctly dealing
            // with toplevels.
            paintDirtyRegions(dirtyComponents);
        }
    }

    private void updateWindows(Map<Component,Rectangle> dirtyComponents) {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        if (!(toolkit instanceof SunToolkit &&
              ((SunToolkit)toolkit).needUpdateWindow()))
        {
            return;
        }

        Set<Window> windows = new HashSet<Window>();
        Set<Component> dirtyComps = dirtyComponents.keySet();
        for (Iterator<Component> it = dirtyComps.iterator(); it.hasNext();) {
            Component dirty = it.next();
            Window window = dirty instanceof Window ?
                (Window)dirty :
                SwingUtilities.getWindowAncestor(dirty);
            if (window != null &&
                !window.isOpaque())
            {
                windows.add(window);
            }
        }

        for (Window window : windows) {
            AWTAccessor.getWindowAccessor().updateWindow(window);
        }
    }

    boolean isPainting() {
        return painting;
    }

    /**
     * Paint all of the components that have been marked dirty.
     *
     * @see #addDirtyRegion
     */
    public void paintDirtyRegions() {
        synchronized(this) {  // swap for thread safety
            Map<Component,Rectangle> tmp = tmpDirtyComponents;
            tmpDirtyComponents = dirtyComponents;
            dirtyComponents = tmp;
            dirtyComponents.clear();
        }
        paintDirtyRegions(tmpDirtyComponents);
    }

    private void paintDirtyRegions(Map<Component,Rectangle>
                                   tmpDirtyComponents){
        int i, count;
        java.util.List<Component> roots;
        Component dirtyComponent;

        count = tmpDirtyComponents.size();
        if (count == 0) {
            return;
        }

        Rectangle rect;
        int localBoundsX = 0;
        int localBoundsY = 0;
        int localBoundsH;
        int localBoundsW;
        Enumeration keys;

        roots = new ArrayList<Component>(count);

        for (Component dirty : tmpDirtyComponents.keySet()) {
            collectDirtyComponents(tmpDirtyComponents, dirty, roots);
        }

        count = roots.size();
        painting = true;
        try {
            for(i=0 ; i < count ; i++) {
                dirtyComponent = roots.get(i);
                rect = tmpDirtyComponents.get(dirtyComponent);
                localBoundsH = dirtyComponent.getHeight();
                localBoundsW = dirtyComponent.getWidth();

                SwingUtilities.computeIntersection(localBoundsX,
                                                   localBoundsY,
                                                   localBoundsW,
                                                   localBoundsH,
                                                   rect);
                if (dirtyComponent instanceof JComponent) {
                    ((JComponent)dirtyComponent).paintImmediately(
                        rect.x,rect.y,rect.width, rect.height);
                }
                else if (dirtyComponent.isShowing()) {
                    Graphics g = JComponent.safelyGetGraphics(
                            dirtyComponent, dirtyComponent);
                    // If the Graphics goes away, it means someone disposed of
                    // the window, don't do anything.
                    if (g != null) {
                        g.setClip(rect.x, rect.y, rect.width, rect.height);
                        try {
                            dirtyComponent.paint(g);
                        } finally {
                            g.dispose();
                        }
                    }
                }
                // If the repaintRoot has been set, service it now and
                // remove any components that are children of repaintRoot.
                if (repaintRoot != null) {
                    adjustRoots(repaintRoot, roots, i + 1);
                    count = roots.size();
                    paintManager.isRepaintingRoot = true;
                    repaintRoot.paintImmediately(0, 0, repaintRoot.getWidth(),
                                                 repaintRoot.getHeight());
                    paintManager.isRepaintingRoot = false;
                    // Only service repaintRoot once.
                    repaintRoot = null;
                }
            }
        } finally {
            painting = false;
        }

        updateWindows(tmpDirtyComponents);

        tmpDirtyComponents.clear();
    }


    /**
     * Removes any components from roots that are children of
     * root.
     */
    private void adjustRoots(JComponent root,
                             java.util.List<Component> roots, int index) {
        for (int i = roots.size() - 1; i >= index; i--) {
            Component c = roots.get(i);
            for(;;) {
                if (c == root || c == null || !(c instanceof JComponent)) {
                    break;
                }
                c = c.getParent();
            }
            if (c == root) {
                roots.remove(i);
            }
        }
    }

    Rectangle tmp = new Rectangle();

    void collectDirtyComponents(Map<Component,Rectangle> dirtyComponents,
                                Component dirtyComponent,
                                java.util.List<Component> roots) {
        int dx, dy, rootDx, rootDy;
        Component component, rootDirtyComponent,parent;
        Rectangle cBounds;

        // Find the highest parent which is dirty.  When we get out of this
        // rootDx and rootDy will contain the translation from the
        // rootDirtyComponent's coordinate system to the coordinates of the
        // original dirty component.  The tmp Rect is also used to compute the
        // visible portion of the dirtyRect.

        component = rootDirtyComponent = dirtyComponent;

        int x = dirtyComponent.getX();
        int y = dirtyComponent.getY();
        int w = dirtyComponent.getWidth();
        int h = dirtyComponent.getHeight();

        dx = rootDx = 0;
        dy = rootDy = 0;
        tmp.setBounds(dirtyComponents.get(dirtyComponent));

        // System.out.println("Collect dirty component for bound " + tmp +
        //                                   "component bounds is " + cBounds);;
        SwingUtilities.computeIntersection(0,0,w,h,tmp);

        if (tmp.isEmpty()) {
            // System.out.println("Empty 1");
            return;
        }

        for(;;) {
            if(!(component instanceof JComponent))
                break;

            parent = component.getParent();
            if(parent == null)
                break;

            component = parent;

            dx += x;
            dy += y;
            tmp.setLocation(tmp.x + x, tmp.y + y);

            x = component.getX();
            y = component.getY();
            w = component.getWidth();
            h = component.getHeight();
            tmp = SwingUtilities.computeIntersection(0,0,w,h,tmp);

            if (tmp.isEmpty()) {
                // System.out.println("Empty 2");
                return;
            }

            if (dirtyComponents.get(component) != null) {
                rootDirtyComponent = component;
                rootDx = dx;
                rootDy = dy;
            }
        }

        if (dirtyComponent != rootDirtyComponent) {
            Rectangle r;
            tmp.setLocation(tmp.x + rootDx - dx,
                            tmp.y + rootDy - dy);
            r = dirtyComponents.get(rootDirtyComponent);
            SwingUtilities.computeUnion(tmp.x,tmp.y,tmp.width,tmp.height,r);
        }

        // If we haven't seen this root before, then we need to add it to the
        // list of root dirty Views.

        if (!roots.contains(rootDirtyComponent))
            roots.add(rootDirtyComponent);
    }


    /**
     * Returns a string that displays and identifies this
     * object's properties.
     *
     * @return a String representation of this object
     */
    public synchronized String toString() {
        StringBuffer sb = new StringBuffer();
        if(dirtyComponents != null)
            sb.append("" + dirtyComponents);
        return sb.toString();
    }


   /**
     * Return the offscreen buffer that should be used as a double buffer with
     * the component <code>c</code>.
     * By default there is a double buffer per RepaintManager.
     * The buffer might be smaller than <code>(proposedWidth,proposedHeight)</code>
     * This happens when the maximum double buffer size as been set for the receiving
     * repaint manager.
     */
    public Image getOffscreenBuffer(Component c,int proposedWidth,int proposedHeight) {
        RepaintManager delegate = getDelegate(c);
        if (delegate != null) {
            return delegate.getOffscreenBuffer(c, proposedWidth, proposedHeight);
        }
        return _getOffscreenBuffer(c, proposedWidth, proposedHeight);
    }

  /**
   * Return a volatile offscreen buffer that should be used as a
   * double buffer with the specified component <code>c</code>.
   * The image returned will be an instance of VolatileImage, or null
   * if a VolatileImage object could not be instantiated.
   * This buffer might be smaller than <code>(proposedWidth,proposedHeight)</code>.
   * This happens when the maximum double buffer size has been set for this
   * repaint manager.
   *
   * @see java.awt.image.VolatileImage
   * @since 1.4
   */
    public Image getVolatileOffscreenBuffer(Component c,
                                            int proposedWidth,int proposedHeight) {
        RepaintManager delegate = getDelegate(c);
        if (delegate != null) {
            return delegate.getVolatileOffscreenBuffer(c, proposedWidth,
                                                        proposedHeight);
        }

        // If the window is non-opaque, it's double-buffered at peer's level
        Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c);
        if (!w.isOpaque()) {
            Toolkit tk = Toolkit.getDefaultToolkit();
            if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
                return null;
            }
        }

        GraphicsConfiguration config = c.getGraphicsConfiguration();
        if (config == null) {
            config = GraphicsEnvironment.getLocalGraphicsEnvironment().
                            getDefaultScreenDevice().getDefaultConfiguration();
        }
        Dimension maxSize = getDoubleBufferMaximumSize();
        int width = proposedWidth < 1 ? 1 :
            (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
        int height = proposedHeight < 1 ? 1 :
            (proposedHeight > maxSize.height? maxSize.height : proposedHeight);
        VolatileImage image = volatileMap.get(config);
        if (image == null || image.getWidth() < width ||
                             image.getHeight() < height) {
            if (image != null) {
                image.flush();
            }
            image = config.createCompatibleVolatileImage(width, height);
            volatileMap.put(config, image);
        }
        return image;
    }

    private Image _getOffscreenBuffer(Component c, int proposedWidth, int proposedHeight) {
        Dimension maxSize = getDoubleBufferMaximumSize();
        DoubleBufferInfo doubleBuffer;
        int width, height;

        // If the window is non-opaque, it's double-buffered at peer's level
        Window w = (c instanceof Window) ? (Window)c : SwingUtilities.getWindowAncestor(c);
        if (!w.isOpaque()) {
            Toolkit tk = Toolkit.getDefaultToolkit();
            if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
                return null;
            }
        }

        if (standardDoubleBuffer == null) {
            standardDoubleBuffer = new DoubleBufferInfo();
        }
        doubleBuffer = standardDoubleBuffer;

        width = proposedWidth < 1? 1 :
                  (proposedWidth > maxSize.width? maxSize.width : proposedWidth);
        height = proposedHeight < 1? 1 :
                  (proposedHeight > maxSize.height? maxSize.height : proposedHeight);

        if (doubleBuffer.needsReset || (doubleBuffer.image != null &&
                                        (doubleBuffer.size.width < width ||
                                         doubleBuffer.size.height < height))) {
            doubleBuffer.needsReset = false;
            if (doubleBuffer.image != null) {
                doubleBuffer.image.flush();
                doubleBuffer.image = null;
            }
            width = Math.max(doubleBuffer.size.width, width);
            height = Math.max(doubleBuffer.size.height, height);
        }

        Image result = doubleBuffer.image;

        if (doubleBuffer.image == null) {
            result = c.createImage(width , height);
            doubleBuffer.size = new Dimension(width, height);
            if (c instanceof JComponent) {
                ((JComponent)c).setCreatedDoubleBuffer(true);
                doubleBuffer.image = result;
            }
            // JComponent will inform us when it is no longer valid
            // (via removeNotify) we have no such hook to other components,
            // therefore we don't keep a ref to the Component
            // (indirectly through the Image) by stashing the image.
        }
        return result;
    }


    /** Set the maximum double buffer size. **/
    public void setDoubleBufferMaximumSize(Dimension d) {
        doubleBufferMaxSize = d;
        if (doubleBufferMaxSize == null) {
            clearImages();
        } else {
            clearImages(d.width, d.height);
        }
    }

    private void clearImages() {
        clearImages(0, 0);
    }

    private void clearImages(int width, int height) {
        if (standardDoubleBuffer != null && standardDoubleBuffer.image != null) {
            if (standardDoubleBuffer.image.getWidth(null) > width ||
                standardDoubleBuffer.image.getHeight(null) > height) {
                standardDoubleBuffer.image.flush();
                standardDoubleBuffer.image = null;
            }
        }
        // Clear out the VolatileImages
        Iterator gcs = volatileMap.keySet().iterator();
        while (gcs.hasNext()) {
            GraphicsConfiguration gc = (GraphicsConfiguration)gcs.next();
            VolatileImage image = volatileMap.get(gc);
            if (image.getWidth() > width || image.getHeight() > height) {
                image.flush();
                gcs.remove();
            }
        }
    }

    /**
     * Returns the maximum double buffer size.
     *
     * @return a Dimension object representing the maximum size
     */
    public Dimension getDoubleBufferMaximumSize() {
        if (doubleBufferMaxSize == null) {
            try {
                Rectangle virtualBounds = new Rectangle();
                GraphicsEnvironment ge = GraphicsEnvironment.
                                                 getLocalGraphicsEnvironment();
                for (GraphicsDevice gd : ge.getScreenDevices()) {
                    GraphicsConfiguration gc = gd.getDefaultConfiguration();
                    virtualBounds = virtualBounds.union(gc.getBounds());
                }
                doubleBufferMaxSize = new Dimension(virtualBounds.width,
                                                    virtualBounds.height);
            } catch (HeadlessException e) {
                doubleBufferMaxSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
            }
        }
        return doubleBufferMaxSize;
    }

    /**
     * Enables or disables double buffering in this RepaintManager.
     * CAUTION: The default value for this property is set for optimal
     * paint performance on the given platform and it is not recommended
     * that programs modify this property directly.
     *
     * @param aFlag  true to activate double buffering
     * @see #isDoubleBufferingEnabled
     */
    public void setDoubleBufferingEnabled(boolean aFlag) {
        doubleBufferingEnabled = aFlag;
        PaintManager paintManager = getPaintManager();
        if (!aFlag && paintManager.getClass() != PaintManager.class) {
            setPaintManager(new PaintManager());
        }
    }

    /**
     * Returns true if this RepaintManager is double buffered.
     * The default value for this property may vary from platform
     * to platform.  On platforms where native double buffering
     * is supported in the AWT, the default value will be <code>false</code>
     * to avoid unnecessary buffering in Swing.
     * On platforms where native double buffering is not supported,
     * the default value will be <code>true</code>.
     *
     * @return true if this object is double buffered
     */
    public boolean isDoubleBufferingEnabled() {
        return doubleBufferingEnabled;
    }

    /**
     * This resets the double buffer. Actually, it marks the double buffer
     * as invalid, the double buffer will then be recreated on the next
     * invocation of getOffscreenBuffer.
     */
    void resetDoubleBuffer() {
        if (standardDoubleBuffer != null) {
            standardDoubleBuffer.needsReset = true;
        }
    }

    /**
     * This resets the volatile double buffer.
     */
    void resetVolatileDoubleBuffer(GraphicsConfiguration gc) {
        Image image = volatileMap.remove(gc);
        if (image != null) {
            image.flush();
        }
    }

    /**
     * Returns true if we should use the <code>Image</code> returned
     * from <code>getVolatileOffscreenBuffer</code> to do double buffering.
     */
    boolean useVolatileDoubleBuffer() {
        return volatileImageBufferEnabled;
    }

    /**
     * Returns true if the current thread is the thread painting.  This
     * will return false if no threads are painting.
     */
    private synchronized boolean isPaintingThread() {
        return (Thread.currentThread() == paintThread);
    }
    //
    // Paint methods.  You very, VERY rarely need to invoke these.
    // They are invoked directly from JComponent's painting code and
    // when painting happens outside the normal flow: DefaultDesktopManager
    // and JViewport.  If you end up needing these methods in other places be
    // careful that you don't get stuck in a paint loop.
    //

    /**
     * Paints a region of a component
     *
     * @param paintingComponent Component to paint
     * @param bufferComponent Component to obtain buffer for
     * @param g Graphics to paint to
     * @param x X-coordinate
     * @param y Y-coordinate
     * @param w Width
     * @param h Height
     */
    void paint(JComponent paintingComponent,
               JComponent bufferComponent, Graphics g,
               int x, int y, int w, int h) {
        PaintManager paintManager = getPaintManager();
        if (!isPaintingThread()) {
            // We're painting to two threads at once.  PaintManager deals
            // with this a bit better than BufferStrategyPaintManager, use
            // it to avoid possible exceptions/corruption.
            if (paintManager.getClass() != PaintManager.class) {
                paintManager = new PaintManager();
                paintManager.repaintManager = this;
            }
        }
        if (!paintManager.paint(paintingComponent, bufferComponent, g,
                                x, y, w, h)) {
            g.setClip(x, y, w, h);
            paintingComponent.paintToOffscreen(g, x, y, w, h, x + w, y + h);
        }
    }

    /**
     * Does a copy area on the specified region.
     *
     * @param clip Whether or not the copyArea needs to be clipped to the
     *             Component's bounds.
     */
    void copyArea(JComponent c, Graphics g, int x, int y, int w, int h,
                  int deltaX, int deltaY, boolean clip) {
        getPaintManager().copyArea(c, g, x, y, w, h, deltaX, deltaY, clip);
    }

    /**
     * Invoked prior to any paint/copyArea method calls.  This will
     * be followed by an invocation of <code>endPaint</code>.
     * <b>WARNING</b>: Callers of this method need to wrap the call
     * in a <code>try/finally</code>, otherwise if an exception is thrown
     * during the course of painting the RepaintManager may
     * be left in a state in which the screen is not updated, eg:
     * <pre>
     * repaintManager.beginPaint();
     * try {
     *   repaintManager.paint(...);
     * } finally {
     *   repaintManager.endPaint();
     * }
     * </pre>
     */
    void beginPaint() {
        boolean multiThreadedPaint = false;
        int paintDepth;
        Thread currentThread = Thread.currentThread();
        synchronized(this) {
            paintDepth = this.paintDepth;
            if (paintThread == null || currentThread == paintThread) {
                paintThread = currentThread;
                this.paintDepth++;
            } else {
                multiThreadedPaint = true;
            }
        }
        if (!multiThreadedPaint && paintDepth == 0) {
            getPaintManager().beginPaint();
        }
    }

    /**
     * Invoked after <code>beginPaint</code> has been invoked.
     */
    void endPaint() {
        if (isPaintingThread()) {
            PaintManager paintManager = null;
            synchronized(this) {
                if (--paintDepth == 0) {
                    paintManager = getPaintManager();
                }
            }
            if (paintManager != null) {
                paintManager.endPaint();
                synchronized(this) {
                    paintThread = null;
                }
            }
        }
    }

    /**
     * If possible this will show a previously rendered portion of
     * a Component.  If successful, this will return true, otherwise false.
     * <p>
     * WARNING: This method is invoked from the native toolkit thread, be
     * very careful as to what methods this invokes!
     */
    boolean show(Container c, int x, int y, int w, int h) {
        return getPaintManager().show(c, x, y, w, h);
    }

    /**
     * Invoked when the doubleBuffered or useTrueDoubleBuffering
     * properties of a JRootPane change.  This may come in on any thread.
     */
    void doubleBufferingChanged(JRootPane rootPane) {
        getPaintManager().doubleBufferingChanged(rootPane);
    }

    /**
     * Sets the <code>PaintManager</code> that is used to handle all
     * double buffered painting.
     *
     * @param paintManager The PaintManager to use.  Passing in null indicates
     *        the fallback PaintManager should be used.
     */
    void setPaintManager(PaintManager paintManager) {
        if (paintManager == null) {
            paintManager = new PaintManager();
        }
        PaintManager oldPaintManager;
        synchronized(this) {
            oldPaintManager = this.paintManager;
            this.paintManager = paintManager;
            paintManager.repaintManager = this;
        }
        if (oldPaintManager != null) {
            oldPaintManager.dispose();
        }
    }

    private synchronized PaintManager getPaintManager() {
        if (paintManager == null) {
            PaintManager paintManager = null;
            if (doubleBufferingEnabled && !nativeDoubleBuffering) {
                switch (bufferStrategyType) {
                case BUFFER_STRATEGY_NOT_SPECIFIED:
                    Toolkit tk = Toolkit.getDefaultToolkit();
                    if (tk instanceof SunToolkit) {
                        SunToolkit stk = (SunToolkit) tk;
                        if (stk.useBufferPerWindow()) {
                            paintManager = new BufferStrategyPaintManager();
                        }
                    }
                    break;
                case BUFFER_STRATEGY_SPECIFIED_ON:
                    paintManager = new BufferStrategyPaintManager();
                    break;
                default:
                    break;
                }
            }
            // null case handled in setPaintManager
            setPaintManager(paintManager);
        }
        return paintManager;
    }

    private void scheduleProcessingRunnable() {
        scheduleProcessingRunnable(AppContext.getAppContext());
    }

    private void scheduleProcessingRunnable(AppContext context) {
        if (processingRunnable.markPending()) {
            Toolkit tk = Toolkit.getDefaultToolkit();
            if (tk instanceof SunToolkit) {
                SunToolkit.getSystemEventQueueImplPP(context).
                  postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
                                                processingRunnable));
            } else {
                Toolkit.getDefaultToolkit().getSystemEventQueue().
                      postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
                                                    processingRunnable));
            }
        }
    }


    /**
     * PaintManager is used to handle all double buffered painting for
     * Swing.  Subclasses should call back into the JComponent method
     * <code>paintToOffscreen</code> to handle the actual painting.
     */
    static class PaintManager {
        /**
         * RepaintManager the PaintManager has been installed on.
         */
        protected RepaintManager repaintManager;
        boolean isRepaintingRoot;

        /**
         * Paints a region of a component
         *
         * @param paintingComponent Component to paint
         * @param bufferComponent Component to obtain buffer for
         * @param g Graphics to paint to
         * @param x X-coordinate
         * @param y Y-coordinate
         * @param w Width
         * @param h Height
         * @return true if painting was successful.
         */
        public boolean paint(JComponent paintingComponent,
                             JComponent bufferComponent, Graphics g,
                             int x, int y, int w, int h) {
            // First attempt to use VolatileImage buffer for performance.
            // If this fails (which should rarely occur), fallback to a
            // standard Image buffer.
            boolean paintCompleted = false;
            Image offscreen;
            if (repaintManager.useVolatileDoubleBuffer() &&
                (offscreen = getValidImage(repaintManager.
                getVolatileOffscreenBuffer(bufferComponent, w, h))) != null) {
                VolatileImage vImage = (java.awt.image.VolatileImage)offscreen;
                GraphicsConfiguration gc = bufferComponent.
                                            getGraphicsConfiguration();
                for (int i = 0; !paintCompleted &&
                         i < RepaintManager.VOLATILE_LOOP_MAX; i++) {
                    if (vImage.validate(gc) ==
                                   VolatileImage.IMAGE_INCOMPATIBLE) {
                        repaintManager.resetVolatileDoubleBuffer(gc);
                        offscreen = repaintManager.getVolatileOffscreenBuffer(
                            bufferComponent,w, h);
                        vImage = (java.awt.image.VolatileImage)offscreen;
                    }
                    paintDoubleBuffered(paintingComponent, vImage, g, x, y,
                                        w, h);
                    paintCompleted = !vImage.contentsLost();
                }
            }
            // VolatileImage painting loop failed, fallback to regular
            // offscreen buffer
            if (!paintCompleted && (offscreen = getValidImage(
                      repaintManager.getOffscreenBuffer(
                      bufferComponent, w, h))) != null) {
                paintDoubleBuffered(paintingComponent, offscreen, g, x, y, w,
                                    h);
                paintCompleted = true;
            }
            return paintCompleted;
        }

        /**
         * Does a copy area on the specified region.
         */
        public void copyArea(JComponent c, Graphics g, int x, int y, int w,
                             int h, int deltaX, int deltaY, boolean clip) {
            g.copyArea(x, y, w, h, deltaX, deltaY);
        }

        /**
         * Invoked prior to any calls to paint or copyArea.
         */
        public void beginPaint() {
        }

        /**
         * Invoked to indicate painting has been completed.
         */
        public void endPaint() {
        }

        /**
         * Shows a region of a previously rendered component.  This
         * will return true if successful, false otherwise.  The default
         * implementation returns false.
         */
        public boolean show(Container c, int x, int y, int w, int h) {
            return false;
        }

        /**
         * Invoked when the doubleBuffered or useTrueDoubleBuffering
         * properties of a JRootPane change.  This may come in on any thread.
         */
        public void doubleBufferingChanged(JRootPane rootPane) {
        }

        /**
         * Paints a portion of a component to an offscreen buffer.
         */
        protected void paintDoubleBuffered(JComponent c, Image image,
                            Graphics g, int clipX, int clipY,
                            int clipW, int clipH) {
            Graphics osg = image.getGraphics();
            int bw = Math.min(clipW, image.getWidth(null));
            int bh = Math.min(clipH, image.getHeight(null));
            int x,y,maxx,maxy;

            try {
                for(x = clipX, maxx = clipX+clipW; x < maxx ;  x += bw ) {
                    for(y=clipY, maxy = clipY + clipH; y < maxy ; y += bh) {
                        osg.translate(-x, -y);
                        osg.setClip(x,y,bw,bh);
                        c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy);
                        g.setClip(x, y, bw, bh);
                        g.drawImage(image, x, y, c);
                        osg.translate(x, y);
                    }
                }
            } finally {
                osg.dispose();
            }
        }

        /**
         * If <code>image</code> is non-null with a positive size it
         * is returned, otherwise null is returned.
         */
        private Image getValidImage(Image image) {
            if (image != null && image.getWidth(null) > 0 &&
                                 image.getHeight(null) > 0) {
                return image;
            }
            return null;
        }

        /**
         * Schedules a repaint for the specified component.  This differs
         * from <code>root.repaint</code> in that if the RepaintManager is
         * currently processing paint requests it'll process this request
         * with the current set of requests.
         */
        protected void repaintRoot(JComponent root) {
            assert (repaintManager.repaintRoot == null);
            if (repaintManager.painting) {
                repaintManager.repaintRoot = root;
            }
            else {
                root.repaint();
            }
        }

        /**
         * Returns true if the component being painted is the root component
         * that was previously passed to <code>repaintRoot</code>.
         */
        protected boolean isRepaintingRoot() {
            return isRepaintingRoot;
        }

        /**
         * Cleans up any state.  After invoked the PaintManager will no
         * longer be used anymore.
         */
        protected void dispose() {
        }
    }


    private class DoubleBufferInfo {
        public Image image;
        public Dimension size;
        public boolean needsReset = false;
    }


    /**
     * Listener installed to detect display changes. When display changes,
     * schedules a callback to notify all RepaintManagers of the display
     * changes. Only one DisplayChangedHandler is ever installed. The
     * singleton instance will schedule notification for all AppContexts.
     */
    private static final class DisplayChangedHandler implements
                                             DisplayChangedListener {
        public void displayChanged() {
            scheduleDisplayChanges();
        }

        public void paletteChanged() {
        }

        private void scheduleDisplayChanges() {
            // To avoid threading problems, we notify each RepaintManager
            // on the thread it was created on.
            for (Object c : AppContext.getAppContexts()) {
                AppContext context = (AppContext) c;
                synchronized(context) {
                    if (!context.isDisposed()) {
                        EventQueue eventQueue = (EventQueue)context.get(
                            AppContext.EVENT_QUEUE_KEY);
                        if (eventQueue != null) {
                            eventQueue.postEvent(new InvocationEvent(
                                Toolkit.getDefaultToolkit(),
                                new DisplayChangedRunnable()));
                        }
                    }
                }
            }
        }
    }


    private static final class DisplayChangedRunnable implements Runnable {
        public void run() {
            RepaintManager.currentManager((JComponent)null).displayChanged();
        }
    }


    /**
     * Runnable used to process all repaint/revalidate requests.
     */
    private final class ProcessingRunnable implements Runnable {
        // If true, we're wainting on the EventQueue.
        private boolean pending;

        /**
         * Marks this processing runnable as pending. If this was not
         * already marked as pending, true is returned.
         */
        public synchronized boolean markPending() {
            if (!pending) {
                pending = true;
                return true;
            }
            return false;
        }

        public void run() {
            synchronized (this) {
                pending = false;
            }
            // First pass, flush any heavy paint events into real paint
            // events.  If there are pending heavy weight requests this will
            // result in q'ing this request up one more time.  As
            // long as no other requests come in between now and the time
            // the second one is processed nothing will happen.  This is not
            // ideal, but the logic needed to suppress the second request is
            // more headache than it's worth.
            scheduleHeavyWeightPaints();
            // Do the actual validation and painting.
            validateInvalidComponents();
            prePaintDirtyRegions();
        }
    }
    private RepaintManager getDelegate(Component c) {
        RepaintManager delegate = SwingUtilities3.getDelegateRepaintManager(c);
        if (this == delegate) {
            delegate = null;
        }
        return delegate;
    }
}
