/* * Copyright (c) 1997, 2011, 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,Lines 1–500 of 1631. Load more
/* * Copyright (c) 1997, 2011, 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,