6794764: Translucent windows are completely repainted on every paint event, on Windows
6719382: Printing of AWT components on windows is not working
6726866: Repainting artifacts when resizing or dragging JInternalFrames in non-opaque toplevel
6683775: Painting artifacts is seen when panel is made setOpaque(false) for a translucent window
Reviewed-by: anthony, tdv, alexp
--- a/jdk/src/share/classes/java/awt/GraphicsConfiguration.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/java/awt/GraphicsConfiguration.java Thu May 21 12:29:25 2009 +0400
@@ -436,7 +436,7 @@
}
/**
- * Returns whether this GraphicsConfiguration supports
+ * Returns whether this {@code GraphicsConfiguration} supports
* the {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
* PERPIXEL_TRANSLUCENT} kind of translucency.
*
--- a/jdk/src/share/classes/java/awt/GraphicsDevice.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/java/awt/GraphicsDevice.java Thu May 21 12:29:25 2009 +0400
@@ -246,7 +246,7 @@
* Simulated full-screen mode resizes
* the window to the size of the screen and positions it at (0,0).
* <p>
- * When entering full-screen mode, if the window to be used as the
+ * When entering full-screen mode, if the window to be used as a
* full-screen window is not visible, this method will make it visible.
* It will remain visible when returning to windowed mode.
* <p>
@@ -261,9 +261,9 @@
*
* @param w a window to use as the full-screen window; {@code null}
* if returning to windowed mode. Some platforms expect the
- * fullscreen window to be a top-level component (i.e., a Frame);
- * therefore it is preferable to use a Frame here rather than a
- * Window.
+ * fullscreen window to be a top-level component (i.e., a {@code Frame});
+ * therefore it is preferable to use a {@code Frame} here rather than a
+ * {@code Window}.
*
* @see #isFullScreenSupported
* @see #getFullScreenWindow
--- a/jdk/src/share/classes/java/awt/Window.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/java/awt/Window.java Thu May 21 12:29:25 2009 +0400
@@ -296,7 +296,7 @@
transient boolean isInShow = false;
/*
- * Opacity level of the window
+ * The opacity level of the window
*
* @serial
* @see #setOpacity(float)
@@ -306,7 +306,7 @@
private float opacity = 1.0f;
/*
- * The shape assigned to this window. This field is set to null if
+ * The shape assigned to this window. This field is set to {@code null} if
* no shape is set (rectangular window).
*
* @serial
@@ -3592,10 +3592,10 @@
@Override
public void setBackground(Color bgColor) {
Color oldBg = getBackground();
+ super.setBackground(bgColor);
if (oldBg != null && oldBg.equals(bgColor)) {
return;
}
- super.setBackground(bgColor);
int oldAlpha = oldBg != null ? oldBg.getAlpha() : 255;
int alpha = bgColor.getAlpha();
if ((oldAlpha == 255) && (alpha < 255)) { // non-opaque window
@@ -3623,16 +3623,37 @@
}
}
- private void updateWindow(BufferedImage backBuffer) {
+ private void updateWindow() {
synchronized (getTreeLock()) {
WindowPeer peer = (WindowPeer)getPeer();
if (peer != null) {
- peer.updateWindow(backBuffer);
+ peer.updateWindow();
}
}
}
- private static final Color TRANSPARENT_BACKGROUND_COLOR = new Color(0, 0, 0, 0);
+ /**
+ * {@inheritDoc}
+ *
+ * @since 1.7
+ */
+ @Override
+ public void paint(Graphics g) {
+ Color bgColor = getBackground();
+ if ((bgColor != null) && (bgColor.getAlpha() < 255)) {
+ Graphics gg = g.create();
+ try {
+ if (gg instanceof Graphics2D) {
+ gg.setColor(bgColor);
+ ((Graphics2D)gg).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
+ gg.fillRect(0, 0, getWidth(), getHeight());
+ }
+ } finally {
+ gg.dispose();
+ }
+ }
+ super.paint(g);
+ }
private static void setLayersOpaque(Component component, boolean isOpaque) {
// Shouldn't use instanceof to avoid loading Swing classes
@@ -3644,18 +3665,10 @@
Container c = root.getContentPane();
javax.swing.JComponent content =
(c instanceof javax.swing.JComponent) ? (javax.swing.JComponent)c : null;
- javax.swing.JComponent gp =
- (rpc.getGlassPane() instanceof javax.swing.JComponent) ?
- (javax.swing.JComponent)rpc.getGlassPane() : null;
- if (gp != null) {
- gp.setDoubleBuffered(isOpaque);
- }
lp.setOpaque(isOpaque);
root.setOpaque(isOpaque);
- root.setDoubleBuffered(isOpaque);
if (content != null) {
content.setOpaque(isOpaque);
- content.setDoubleBuffered(isOpaque);
// Iterate down one level to see whether we have a JApplet
// (which is also a RootPaneContainer) which requires processing
@@ -3748,8 +3761,8 @@
window.setBackground(new Color(bg.getRed(), bg.getGreen(), bg.getBlue(),
opaque ? 255 : 0));
}
- public void updateWindow(Window window, BufferedImage backBuffer) {
- window.updateWindow(backBuffer);
+ public void updateWindow(Window window) {
+ window.updateWindow();
}
public Dimension getSecurityWarningSize(Window window) {
--- a/jdk/src/share/classes/java/awt/peer/WindowPeer.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/java/awt/peer/WindowPeer.java Thu May 21 12:29:25 2009 +0400
@@ -110,12 +110,11 @@
void setOpaque(boolean isOpaque);
/**
- * Updates the native part of non-opaque window using
- * the given image with color+alpha values for each pixel.
+ * Updates the native part of non-opaque window.
*
* @see Window#setBackground(Color)
*/
- void updateWindow(BufferedImage backBuffer);
+ void updateWindow();
/**
* Instructs the peer to update the position of the security warning.
--- a/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/javax/swing/DefaultDesktopManager.java Thu May 21 12:29:25 2009 +0400
@@ -34,6 +34,9 @@
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
+import sun.awt.AWTAccessor;
+import sun.awt.SunToolkit;
+
/** This is an implementation of the <code>DesktopManager</code>.
* It currently implements the basic behaviors for managing
* <code>JInternalFrame</code>s in an arbitrary parent.
@@ -361,7 +364,7 @@
g.dispose();
}
} else if (dragMode == FASTER_DRAG_MODE) {
- dragFrameFaster(f, newX, newY);
+ dragFrameFaster(f, newX, newY);
} else {
setBoundsForFrame(f, newX, newY, f.getWidth(), f.getHeight());
}
@@ -634,13 +637,8 @@
boolean floaterCollision = isFloaterCollision(previousBounds, currentBounds);
- // System.out.println(previousBounds);
JComponent parent = (JComponent)f.getParent();
Rectangle visBounds = previousBounds.intersection(desktopBounds);
- // System.out.println(previousBounds);
-
-
- // System.out.println(visBounds);
RepaintManager currentManager = RepaintManager.currentManager(f);
@@ -682,7 +680,6 @@
} else {
dirtyRects = new Rectangle[1];
dirtyRects[0] = previousBounds;
- // System.out.println("no intersection");
};
// Fix the damage
@@ -701,14 +698,22 @@
parent.paintImmediately(dirtyRects[i]);
((JInternalFrame)f).isDragging = true;
-
- // System.out.println(dirtyRects[i]);
}
}
} finally {
currentManager.endPaint();
}
+
+ // update window if it's non-opaque
+ Window topLevel = SwingUtilities.getWindowAncestor(f);
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ if (!AWTAccessor.getWindowAccessor().isOpaque(topLevel) &&
+ (tk instanceof SunToolkit) &&
+ ((SunToolkit)tk).needUpdateWindow())
+ {
+ AWTAccessor.getWindowAccessor().updateWindow(topLevel);
+ }
}
private boolean isFloaterCollision(Rectangle moveFrom, Rectangle moveTo) {
--- a/jdk/src/share/classes/javax/swing/JComponent.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/javax/swing/JComponent.java Thu May 21 12:29:25 2009 +0400
@@ -1021,8 +1021,10 @@
int bw,bh;
boolean printing = getFlag(IS_PRINTING);
- if(!printing && repaintManager.isDoubleBufferingEnabled() &&
- !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered()) {
+ if (!printing && repaintManager.isDoubleBufferingEnabled() &&
+ !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered() &&
+ (getFlag(IS_REPAINTING) || repaintManager.isPainting()))
+ {
repaintManager.beginPaint();
try {
repaintManager.paint(this, this, co, clipX, clipY, clipW,
--- a/jdk/src/share/classes/javax/swing/RepaintManager.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/javax/swing/RepaintManager.java Thu May 21 12:29:25 2009 +0400
@@ -43,7 +43,6 @@
import com.sun.java.swing.SwingUtilities3;
-
/**
* This class manages repaint requests, allowing the number
* of repaints to be minimized, for example by collapsing multiple
@@ -717,14 +716,12 @@
}
}
- private Map<Component,Rectangle>
- updateWindows(Map<Component,Rectangle> dirtyComponents)
- {
+ private void updateWindows(Map<Component,Rectangle> dirtyComponents) {
Toolkit toolkit = Toolkit.getDefaultToolkit();
if (!(toolkit instanceof SunToolkit &&
((SunToolkit)toolkit).needUpdateWindow()))
{
- return dirtyComponents;
+ return;
}
Set<Window> windows = new HashSet<Window>();
@@ -734,25 +731,20 @@
Window window = dirty instanceof Window ?
(Window)dirty :
SwingUtilities.getWindowAncestor(dirty);
-
if (window != null &&
!AWTAccessor.getWindowAccessor().isOpaque(window))
{
- // if this component's toplevel is perpixel translucent, it will
- // be repainted below
- it.remove();
- // add to the set of windows to update (so that we don't update
- // the window many times for each component to be repainted that
- // belongs to this window)
windows.add(window);
}
}
for (Window window : windows) {
- AWTAccessor.getWindowAccessor().updateWindow(window, null);
+ AWTAccessor.getWindowAccessor().updateWindow(window);
}
+ }
- return dirtyComponents;
+ boolean isPainting() {
+ return painting;
}
/**
@@ -788,10 +780,6 @@
int localBoundsW;
Enumeration keys;
- // the components belonging to perpixel-translucent windows will be
- // removed from the list
- tmpDirtyComponents = updateWindows(tmpDirtyComponents);
-
roots = new ArrayList<Component>(count);
for (Component dirty : tmpDirtyComponents.keySet()) {
@@ -799,13 +787,11 @@
}
count = roots.size();
- // System.out.println("roots size is " + count);
painting = true;
try {
for(i=0 ; i < count ; i++) {
dirtyComponent = roots.get(i);
rect = tmpDirtyComponents.get(dirtyComponent);
- // System.out.println("Should refresh :" + rect);
localBoundsH = dirtyComponent.getHeight();
localBoundsW = dirtyComponent.getWidth();
@@ -848,6 +834,9 @@
} finally {
painting = false;
}
+
+ updateWindows(tmpDirtyComponents);
+
tmpDirtyComponents.clear();
}
@@ -1004,6 +993,16 @@
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 (!AWTAccessor.getWindowAccessor().isOpaque(w)) {
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
+ return null;
+ }
+ }
+
GraphicsConfiguration config = c.getGraphicsConfiguration();
if (config == null) {
config = GraphicsEnvironment.getLocalGraphicsEnvironment().
@@ -1031,6 +1030,15 @@
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 (!AWTAccessor.getWindowAccessor().isOpaque(w)) {
+ Toolkit tk = Toolkit.getDefaultToolkit();
+ if ((tk instanceof SunToolkit) && (((SunToolkit)tk).needUpdateWindow())) {
+ return null;
+ }
+ }
+
if (standardDoubleBuffer == null) {
standardDoubleBuffer = new DoubleBufferInfo();
}
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java Thu May 21 12:29:25 2009 +0400
@@ -132,7 +132,7 @@
/*
* Update the image of a non-opaque (translucent) window.
*/
- void updateWindow(Window window, BufferedImage backBuffer);
+ void updateWindow(Window window);
/** Get the size of the security warning.
*/
--- a/jdk/src/share/classes/sun/awt/EmbeddedFrame.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/share/classes/sun/awt/EmbeddedFrame.java Thu May 21 12:29:25 2009 +0400
@@ -592,8 +592,9 @@
public void setOpaque(boolean isOpaque) {
}
- public void updateWindow(BufferedImage bi) {
+ public void updateWindow() {
}
+
public void repositionSecurityWarning() {
}
}
--- a/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/solaris/classes/sun/awt/X11/XWindowPeer.java Thu May 21 12:29:25 2009 +0400
@@ -2058,7 +2058,7 @@
}
@Override
- public void updateWindow(BufferedImage backBuffer) {
+ public void updateWindow() {
// no-op
}
}
--- a/jdk/src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/TranslucentWindowPainter.java Thu May 21 12:29:25 2009 +0400
@@ -105,9 +105,10 @@
}
/**
- * Creates (if needed), clears and returns the buffer for this painter.
+ * Creates (if needed), clears (if requested) and returns the buffer
+ * for this painter.
*/
- protected abstract Image getBackBuffer();
+ protected abstract Image getBackBuffer(boolean clear);
/**
* Updates the the window associated with this painter with the contents
@@ -123,31 +124,16 @@
public abstract void flush();
/**
- * Updates the window associated with the painter given the passed image.
- * If the passed image is null the painter will use its own buffer for
- * rendering the contents of the window into it and updating the window.
+ * Updates the window associated with the painter.
*
- * If the passed buffer has dimensions different from the window, it is
- * copied into the internal buffer first and the latter is used to update
- * the window.
- *
- * @param bb the image to update the non opaque window with, or null.
- * If not null, the image must be of ARGB_PRE type.
+ * @param repaint indicates if the window should be completely repainted
+ * to the back buffer using {@link java.awt.Window#paintAll} before update.
*/
- public void updateWindow(Image bb) {
+ public void updateWindow(boolean repaint) {
boolean done = false;
- if (bb != null && (window.getWidth() != bb.getWidth(null) ||
- window.getHeight() != bb.getHeight(null)))
- {
- Image ourBB = getBackBuffer();
- Graphics2D g = (Graphics2D)ourBB.getGraphics();
- g.drawImage(bb, 0, 0, null);
- g.dispose();
- bb = ourBB;
- }
- do {
- if (bb == null) {
- bb = getBackBuffer();
+ Image bb = getBackBuffer(repaint);
+ while (!done) {
+ if (repaint) {
Graphics2D g = (Graphics2D)bb.getGraphics();
try {
window.paintAll(g);
@@ -156,17 +142,12 @@
}
}
- peer.paintAppletWarning((Graphics2D)bb.getGraphics(),
- bb.getWidth(null), bb.getHeight(null));
-
done = update(bb);
- // in case they passed us a lost VI, next time around we'll use our
- // own bb because we can not validate and restore the contents of
- // their VI
if (!done) {
- bb = null;
+ repaint = true;
+ bb = getBackBuffer(true);
}
- } while (!done);
+ }
}
private static final Image clearImage(Image bb) {
@@ -190,30 +171,24 @@
* method (VI, BI, regular Images).
*/
private static class BIWindowPainter extends TranslucentWindowPainter {
- private WeakReference<BufferedImage> biRef;
+ private BufferedImage backBuffer;
protected BIWindowPainter(WWindowPeer peer) {
super(peer);
}
- private BufferedImage getBIBackBuffer() {
+ @Override
+ protected Image getBackBuffer(boolean clear) {
int w = window.getWidth();
int h = window.getHeight();
- BufferedImage bb = biRef == null ? null : biRef.get();
- if (bb == null || bb.getWidth() != w || bb.getHeight() != h) {
- if (bb != null) {
- bb.flush();
- bb = null;
- }
- bb = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
- biRef = new WeakReference<BufferedImage>(bb);
+ if (backBuffer == null ||
+ backBuffer.getWidth() != w ||
+ backBuffer.getHeight() != h)
+ {
+ flush();
+ backBuffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
}
- return (BufferedImage)clearImage(bb);
- }
-
- @Override
- protected Image getBackBuffer() {
- return getBIBackBuffer();
+ return clear ? (BufferedImage)clearImage(backBuffer) : backBuffer;
}
@Override
@@ -246,10 +221,7 @@
}
// copy the passed image into our own buffer, then upload
- BufferedImage bi = getBIBackBuffer();
- Graphics2D g = (Graphics2D)bi.getGraphics();
- g.setComposite(AlphaComposite.Src);
- g.drawImage(bb, 0, 0, null);
+ BufferedImage bi = (BufferedImage)clearImage(backBuffer);
int data[] =
((DataBufferInt)bi.getRaster().getDataBuffer()).getData();
@@ -259,8 +231,9 @@
}
public void flush() {
- if (biRef != null) {
- biRef.clear();
+ if (backBuffer != null) {
+ backBuffer.flush();
+ backBuffer = null;
}
}
}
@@ -271,27 +244,22 @@
* Java heap-based buffer (which is then uploaded to the layered window)
*/
private static class VIWindowPainter extends BIWindowPainter {
- private WeakReference<VolatileImage> viRef;
+ private VolatileImage viBB;
protected VIWindowPainter(WWindowPeer peer) {
super(peer);
}
@Override
- protected Image getBackBuffer() {
+ protected Image getBackBuffer(boolean clear) {
int w = window.getWidth();
int h = window.getHeight();
GraphicsConfiguration gc = peer.getGraphicsConfiguration();
- VolatileImage viBB = viRef == null ? null : viRef.get();
-
if (viBB == null || viBB.getWidth() != w || viBB.getHeight() != h ||
viBB.validate(gc) == IMAGE_INCOMPATIBLE)
{
- if (viBB != null) {
- viBB.flush();
- viBB = null;
- }
+ flush();
if (gc instanceof AccelGraphicsConfig) {
AccelGraphicsConfig agc = ((AccelGraphicsConfig)gc);
@@ -303,21 +271,16 @@
viBB = gc.createCompatibleVolatileImage(w, h, TRANSLUCENT);
}
viBB.validate(gc);
- viRef = new WeakReference<VolatileImage>(viBB);
}
- return clearImage(viBB);
+ return clear ? clearImage(viBB) : viBB;
}
@Override
public void flush() {
- if (viRef != null) {
- VolatileImage viBB = viRef.get();
- if (viBB != null) {
- viBB.flush();
- viBB = null;
- }
- viRef.clear();
+ if (viBB != null) {
+ viBB.flush();
+ viBB = null;
}
}
}
--- a/jdk/src/windows/classes/sun/awt/windows/WCanvasPeer.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WCanvasPeer.java Thu May 21 12:29:25 2009 +0400
@@ -78,25 +78,6 @@
super.paint(g);
}
- public void print(Graphics g) {
- if (!(target instanceof Window) ||
- AWTAccessor.getWindowAccessor().isOpaque((Window)target))
- {
- Dimension d = ((Component)target).getSize();
- if (g instanceof Graphics2D ||
- g instanceof sun.awt.Graphics2Delegate) {
- // background color is setup correctly, so just use clearRect
- g.clearRect(0, 0, d.width, d.height);
- } else {
- // emulate clearRect
- g.setColor(((Component)target).getBackground());
- g.fillRect(0, 0, d.width, d.height);
- g.setColor(((Component)target).getForeground());
- }
- }
- super.print(g);
- }
-
public boolean shouldClearRectBeforePaint() {
return eraseBackground;
}
--- a/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WComponentPeer.java Thu May 21 12:29:25 2009 +0400
@@ -239,7 +239,8 @@
private static final double BANDING_DIVISOR = 4.0;
private native int[] createPrintedPixels(int srcX, int srcY,
- int srcW, int srcH);
+ int srcW, int srcH,
+ int alpha);
public void print(Graphics g) {
Component comp = (Component)target;
@@ -261,7 +262,9 @@
}
int h = endY - startY + 1;
- int[] pix = createPrintedPixels(0, startY, totalW, h);
+ Color bgColor = comp.getBackground();
+ int[] pix = createPrintedPixels(0, startY, totalW, h,
+ bgColor == null ? 255 : bgColor.getAlpha());
if (pix != null) {
BufferedImage bim = new BufferedImage(totalW, h,
BufferedImage.TYPE_INT_ARGB);
--- a/jdk/src/windows/classes/sun/awt/windows/WObjectPeer.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WObjectPeer.java Thu May 21 12:29:25 2009 +0400
@@ -42,6 +42,9 @@
// set from JNI if any errors in creating the peer occur
protected Error createError = null;
+ // used to synchronize the state of this peer
+ private final Object stateLock = new Object();
+
public static WObjectPeer getPeerForTarget(Object t) {
WObjectPeer peer = (WObjectPeer) WToolkit.targetToPeer(t);
return peer;
@@ -55,6 +58,10 @@
return target;
}
+ public final Object getStateLock() {
+ return stateLock;
+ }
+
/*
* Subclasses should override disposeImpl() instead of dispose(). Client
* code should always invoke dispose(), never disposeImpl().
--- a/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/windows/WWindowPeer.java Thu May 21 12:29:25 2009 +0400
@@ -54,7 +54,7 @@
private boolean isOpaque;
- private volatile TranslucentWindowPainter painter;
+ private TranslucentWindowPainter painter;
/*
* A key used for storing a list of active windows in AppContext. The value
@@ -106,11 +106,13 @@
GraphicsConfiguration gc = getGraphicsConfiguration();
((Win32GraphicsDevice)gc.getDevice()).removeDisplayChangedListener(this);
- TranslucentWindowPainter currentPainter = painter;
- if (currentPainter != null) {
- currentPainter.flush();
- // don't set the current one to null here; reduces the chances of
- // MT issues (like NPEs)
+ synchronized (getStateLock()) {
+ TranslucentWindowPainter currentPainter = painter;
+ if (currentPainter != null) {
+ currentPainter.flush();
+ // don't set the current one to null here; reduces the chances of
+ // MT issues (like NPEs)
+ }
}
super.disposeImpl();
@@ -178,9 +180,23 @@
updateIconImages();
- updateShape();
- updateOpacity();
- updateOpaque();
+ Shape shape = ((Window)target).getShape();
+ if (shape != null) {
+ applyShape(Region.getInstance(shape, null));
+ }
+
+ float opacity = ((Window)target).getOpacity();
+ if (opacity < 1.0f) {
+ setOpacity(opacity);
+ }
+
+ synchronized (getStateLock()) {
+ // default value of a boolean field is 'false', so set isOpaque to
+ // true here explicitly
+ this.isOpaque = true;
+ Color bgColor = ((Window)target).getBackground();
+ setOpaque((bgColor == null) || (bgColor.getAlpha() == 255));
+ }
}
native void createAwtWindow(WComponentPeer parent);
@@ -214,7 +230,11 @@
setAlwaysOnTop(alwaysOnTop);
}
- updateWindow(null);
+ synchronized (getStateLock()) {
+ if (!isOpaque) {
+ updateWindow(true);
+ }
+ }
}
// Synchronize the insets members (here & in helper) with actual window
@@ -334,29 +354,6 @@
}
}
- private void updateShape() {
- Shape shape = ((Window)target).getShape();
- if (shape != null) {
- applyShape(Region.getInstance(shape, null));
- }
- }
-
- private void updateOpacity() {
- float opacity = ((Window)target).getOpacity();
- if (opacity < 1.0f) {
- setOpacity(opacity);
- }
- }
-
- private void updateOpaque() {
- this.isOpaque = true;
- // boolean opaque = ((Window)target).isOpaque();
- boolean opaque = AWTAccessor.getWindowAccessor().isOpaque((Window)target);
- if (!opaque) {
- setOpaque(opaque);
- }
- }
-
native void setMinSize(int width, int height);
/*
@@ -579,6 +576,26 @@
}
}
+ @Override
+ public Graphics getGraphics() {
+ synchronized (getStateLock()) {
+ if (!isOpaque) {
+ return painter.getBackBuffer(false).getGraphics();
+ }
+ }
+ return super.getGraphics();
+ }
+
+ @Override
+ public void setBackground(Color c) {
+ super.setBackground(c);
+ synchronized (getStateLock()) {
+ if (!isOpaque && ((Window)target).isVisible()) {
+ updateWindow(true);
+ }
+ }
+ }
+
private native void setOpacity(int iOpacity);
public void setOpacity(float opacity) {
@@ -600,12 +617,23 @@
}
setOpacity(iOpacity);
- updateWindow(null);
+
+ synchronized (getStateLock()) {
+ if (!isOpaque && ((Window)target).isVisible()) {
+ updateWindow(true);
+ }
+ }
}
private native void setOpaqueImpl(boolean isOpaque);
public void setOpaque(boolean isOpaque) {
+ synchronized (getStateLock()) {
+ if (this.isOpaque == isOpaque) {
+ return;
+ }
+ }
+
Window target = (Window)getTarget();
if (!isOpaque) {
@@ -617,20 +645,17 @@
}
}
- boolean opaqueChanged = this.isOpaque != isOpaque;
boolean isVistaOS = Win32GraphicsEnvironment.isVistaOS();
- if (opaqueChanged && !isVistaOS){
+ if (!isVistaOS) {
// non-Vista OS: only replace the surface data if the opacity
// status changed (see WComponentPeer.isAccelCapable() for more)
replaceSurfaceDataRecursively(target);
}
- this.isOpaque = isOpaque;
-
- setOpaqueImpl(isOpaque);
-
- if (opaqueChanged) {
+ synchronized (getStateLock()) {
+ this.isOpaque = isOpaque;
+ setOpaqueImpl(isOpaque);
if (isOpaque) {
TranslucentWindowPainter currentPainter = painter;
if (currentPainter != null) {
@@ -642,7 +667,7 @@
}
}
- if (opaqueChanged && isVistaOS) {
+ if (isVistaOS) {
// On Vista: setting the window non-opaque makes the window look
// rectangular, though still catching the mouse clicks within
// its shape only. To restore the correct visual appearance
@@ -654,42 +679,33 @@
}
}
- updateWindow(null);
+ if (((Window)target).isVisible()) {
+ updateWindow(true);
+ }
}
public native void updateWindowImpl(int[] data, int width, int height);
- public void updateWindow(BufferedImage backBuffer) {
- if (isOpaque) {
- return;
- }
-
- Component target = (Component)this.target;
- if (target.getWidth() <= 0 || target.getHeight() <= 0) {
- return;
- }
-
- TranslucentWindowPainter currentPainter = painter;
- if (currentPainter != null) {
- currentPainter.updateWindow(backBuffer);
- } else if (log.isLoggable(Level.FINER)) {
- log.log(Level.FINER,
- "Translucent window painter is null in updateWindow");
- }
+ public void updateWindow() {
+ updateWindow(false);
}
- /**
- * Paints the Applet Warning into the passed Graphics2D. This method is
- * called by the TranslucentWindowPainter before updating the layered
- * window.
- *
- * @param g Graphics context to paint the warning to
- * @param w the width of the area
- * @param h the height of the area
- * @see TranslucentWindowPainter
- */
- public void paintAppletWarning(Graphics2D g, int w, int h) {
- // REMIND: the applet warning needs to be painted here
+ private void updateWindow(boolean repaint) {
+ Window w = (Window)target;
+ synchronized (getStateLock()) {
+ if (isOpaque || !w.isVisible() ||
+ (w.getWidth() <= 0) || (w.getHeight() <= 0))
+ {
+ return;
+ }
+ TranslucentWindowPainter currentPainter = painter;
+ if (currentPainter != null) {
+ currentPainter.updateWindow(repaint);
+ } else if (log.isLoggable(Level.FINER)) {
+ log.log(Level.FINER,
+ "Translucent window painter is null in updateWindow");
+ }
+ }
}
/*
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp Thu May 21 12:29:25 2009 +0400
@@ -30,6 +30,7 @@
#include "jlong.h"
#include "awt_AWTEvent.h"
+#include "awt_BitmapUtil.h"
#include "awt_Component.h"
#include "awt_Cursor.h"
#include "awt_Dimension.h"
@@ -127,6 +128,7 @@
jobject component;
int srcx, srcy;
int srcw, srch;
+ jint alpha;
};
// Struct for _SetRectangularShape() method
struct SetRectangularShapeStruct {
@@ -361,8 +363,8 @@
AwtComponent* AwtComponent::GetComponentImpl(HWND hWnd) {
AwtComponent *component =
(AwtComponent *)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
- DASSERT( !IsBadReadPtr(component, sizeof(AwtComponent)) );
- DASSERT( component->GetHWnd() == hWnd );
+ DASSERT(!component || !IsBadReadPtr(component, sizeof(AwtComponent)) );
+ DASSERT(!component || component->GetHWnd() == hWnd );
return component;
}
@@ -1918,11 +1920,14 @@
mr = mrConsume;
break;
}
- case WM_AWT_CREATE_PRINTED_PIXELS:
- retValue = (LRESULT)CreatePrintedPixels(*((SIZE *)wParam),
- *((SIZE *)lParam));
+ case WM_AWT_CREATE_PRINTED_PIXELS: {
+ CreatePrintedPixelsStruct* cpps = (CreatePrintedPixelsStruct*)wParam;
+ SIZE loc = { cpps->srcx, cpps->srcy };
+ SIZE size = { cpps->srcw, cpps->srch };
+ retValue = (LRESULT)CreatePrintedPixels(loc, size, cpps->alpha);
mr = mrConsume;
break;
+ }
case WM_UNDOCUMENTED_CLICKMENUBAR:
{
if (::IsWindow(AwtWindow::GetModalBlocker(GetHWnd()))) {
@@ -4526,18 +4531,20 @@
void AwtComponent::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
{
- if (bitmapBits) {
- DWORD* dest = (DWORD*)bitmapBits;
- //XXX: might be optimized to use one loop (cy*cx -> 0).
- for (int i = 0; i < size.cy; i++ ) {
- for (int j = 0; j < size.cx; j++ ) {
- ((BYTE*)(dest++))[3] = alpha;
- }
+ if (!bitmapBits) {
+ return;
+ }
+
+ DWORD* dest = (DWORD*)bitmapBits;
+ //XXX: might be optimized to use one loop (cy*cx -> 0)
+ for (int i = 0; i < size.cy; i++ ) {
+ for (int j = 0; j < size.cx; j++ ) {
+ ((BYTE*)(dest++))[3] = alpha;
}
}
}
-jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size) {
+jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha) {
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
if (!::IsWindowVisible(GetHWnd())) {
@@ -4549,12 +4556,12 @@
return NULL;
}
HDC hMemoryDC = ::CreateCompatibleDC(hdc);
- HBITMAP hBitmap = ::CreateCompatibleBitmap(hdc, size.cx, size.cy);
+ void *bitmapBits = NULL;
+ HBITMAP hBitmap = BitmapUtil::CreateARGBBitmap(size.cx, size.cy, &bitmapBits);
HBITMAP hOldBitmap = (HBITMAP)::SelectObject(hMemoryDC, hBitmap);
SendMessage(WM_AWT_RELEASEDC, (WPARAM)hdc);
- RECT eraseR = { 0, 0, size.cx, size.cy };
- VERIFY(::FillRect(hMemoryDC, &eraseR, GetBackgroundBrush()));
+ FillBackground(hMemoryDC, size);
VERIFY(::SetWindowOrgEx(hMemoryDC, loc.cx, loc.cy, NULL));
@@ -4562,6 +4569,14 @@
// above.
SendMessage(WM_PRINT, (WPARAM)hMemoryDC, PRF_CLIENT | PRF_NONCLIENT);
+ // First make sure the system completed any drawing to the bitmap.
+ ::GdiFlush();
+
+ // WM_PRINT does not fill the alpha-channel of the ARGB bitmap
+ // leaving it equal to zero. Hence we need to fill it manually. Otherwise
+ // the pixels will be considered transparent when interpreting the data.
+ FillAlpha(bitmapBits, size, alpha);
+
::SelectObject(hMemoryDC, hOldBitmap);
BITMAPINFO bmi;
@@ -5937,10 +5952,6 @@
CreatePrintedPixelsStruct *cpps = (CreatePrintedPixelsStruct *)param;
jobject self = cpps->component;
- jint srcx = cpps->srcx;
- jint srcy = cpps->srcy;
- jint srcw = cpps->srcw;
- jint srch = cpps->srch;
jintArray result = NULL;
AwtComponent *c = NULL;
@@ -5950,12 +5961,7 @@
c = (AwtComponent *)pData;
if (::IsWindow(c->GetHWnd()))
{
- SIZE loc = { srcx, srcy };
- SIZE size = { srcw, srch };
-
- result = (jintArray)
- c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)&loc,
- (LPARAM)&size);
+ result = (jintArray)c->SendMessage(WM_AWT_CREATE_PRINTED_PIXELS, (WPARAM)cpps, 0);
}
ret:
env->DeleteGlobalRef(self);
@@ -6749,7 +6755,7 @@
*/
JNIEXPORT jintArray JNICALL
Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
- jobject self, jint srcX, jint srcY, jint srcW, jint srcH)
+ jobject self, jint srcX, jint srcY, jint srcW, jint srcH, jint alpha)
{
TRY;
@@ -6761,6 +6767,7 @@
cpps->srcy = srcY;
cpps->srcw = srcW;
cpps->srch = srcH;
+ cpps->alpha = alpha;
jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
(void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
--- a/jdk/src/windows/native/sun/windows/awt_Component.h Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.h Thu May 21 12:29:25 2009 +0400
@@ -596,7 +596,7 @@
void UpdateColorModel();
- jintArray CreatePrintedPixels(SIZE &loc, SIZE &size);
+ jintArray CreatePrintedPixels(SIZE &loc, SIZE &size, int alpha);
/*
* HWND, AwtComponent and Java Peer interaction
@@ -738,7 +738,6 @@
virtual void SetDragCapture(UINT flags);
virtual void ReleaseDragCapture(UINT flags);
- //These functions are overridden in AwtWindow to handle non-opaque windows.
virtual void FillBackground(HDC hMemoryDC, SIZE &size);
virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha);
--- a/jdk/src/windows/native/sun/windows/awt_Window.cpp Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp Thu May 21 12:29:25 2009 +0400
@@ -464,7 +464,7 @@
size_t length = env->GetStringLength(javaWarningString) + 1;
warningString = new WCHAR[length];
env->GetStringRegion(javaWarningString, 0,
- static_cast<jsize>(length - 1), warningString);
+ static_cast<jsize>(length - 1), reinterpret_cast<jchar*>(warningString));
warningString[length-1] = L'\0';
env->DeleteLocalRef(javaWarningString);
@@ -2651,20 +2651,6 @@
::LeaveCriticalSection(&contentBitmapCS);
}
-void AwtWindow::FillBackground(HDC hMemoryDC, SIZE &size)
-{
- if (isOpaque()) {
- AwtCanvas::FillBackground(hMemoryDC, size);
- }
-}
-
-void AwtWindow::FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha)
-{
- if (isOpaque()) {
- AwtCanvas::FillAlpha(bitmapBits, size, alpha);
- }
-}
-
/*
* Fixed 6353381: it's improved fix for 4792958
* which was backed-out to avoid 5059656
--- a/jdk/src/windows/native/sun/windows/awt_Window.h Tue May 19 17:03:13 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Window.h Thu May 21 12:29:25 2009 +0400
@@ -343,11 +343,6 @@
BOOL m_iconInherited; /* TRUE if icon is inherited from the owner */
BOOL m_filterFocusAndActivation; /* Used in the WH_CBT hook */
- //These are used in AwtComponent::CreatePrintedPixels. They are overridden
- //here to handle non-opaque windows.
- virtual void FillBackground(HDC hMemoryDC, SIZE &size);
- virtual void FillAlpha(void *bitmapBits, SIZE &size, BYTE alpha);
-
inline BOOL IsUntrusted() {
return warningString != NULL;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JComponent/6683775/bug6683775.java Thu May 21 12:29:25 2009 +0400
@@ -0,0 +1,82 @@
+/* @test
+ @bug 6683775 6794764
+ @summary Painting artifacts is seen when panel is made setOpaque(false) for a translucent window
+ @author Alexander Potochkin
+ @run main bug6683775
+*/
+
+import com.sun.awt.AWTUtilities;
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+
+public class bug6683775 {
+ public static void main(String[] args) throws Exception {
+ GraphicsConfiguration gc = getGC();
+ if (!AWTUtilities.isTranslucencySupported(
+ AWTUtilities.Translucency.PERPIXEL_TRANSLUCENT)
+ || gc == null) {
+ return;
+ }
+ SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+ Robot robot = new Robot();
+ final JFrame testFrame = new JFrame(gc);
+
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ JFrame backgroundFrame = new JFrame("Background frame");
+ backgroundFrame.setUndecorated(true);
+ JPanel panel = new JPanel();
+ panel.setBackground(Color.RED);
+ backgroundFrame.add(panel);
+ backgroundFrame.setSize(200, 200);
+ backgroundFrame.setVisible(true);
+
+ testFrame.setUndecorated(true);
+ JPanel p = new JPanel();
+ p.setOpaque(false);
+ testFrame.add(p);
+ AWTUtilities.setWindowOpaque(testFrame, false);
+ testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ testFrame.setSize(400, 400);
+ testFrame.setLocation(0, 0);
+ testFrame.setVisible(true);
+ }
+ });
+
+ toolkit.realSync();
+
+ //robot.getPixelColor() didn't work right for some reason
+ BufferedImage capture = robot.createScreenCapture(new Rectangle(100, 100));
+
+ int redRGB = Color.RED.getRGB();
+ if (redRGB != capture.getRGB(10, 10)) {
+ throw new RuntimeException("Transparent frame is not transparent!");
+ }
+ }
+
+ private static GraphicsConfiguration getGC() {
+ GraphicsConfiguration transparencyCapableGC =
+ GraphicsEnvironment.getLocalGraphicsEnvironment()
+ .getDefaultScreenDevice().getDefaultConfiguration();
+ if (!AWTUtilities.isTranslucencyCapable(transparencyCapableGC)) {
+ transparencyCapableGC = null;
+
+ GraphicsEnvironment env =
+ GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice[] devices = env.getScreenDevices();
+
+ for (int i = 0; i < devices.length && transparencyCapableGC == null; i++) {
+ GraphicsConfiguration[] configs = devices[i].getConfigurations();
+ for (int j = 0; j < configs.length && transparencyCapableGC == null; j++) {
+ if (AWTUtilities.isTranslucencyCapable(configs[j])) {
+ transparencyCapableGC = configs[j];
+ }
+ }
+ }
+ }
+ return transparencyCapableGC;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JInternalFrame/6726866/bug6726866.html Thu May 21 12:29:25 2009 +0400
@@ -0,0 +1,7 @@
+<html>
+<body>
+<applet code="bug6726866.class" width=400 height=100></applet>
+Drag the internal frame inside the green undecorated window,
+if you can drag it the test passes, otherwise fails.
+</body>
+</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JInternalFrame/6726866/bug6726866.java Thu May 21 12:29:25 2009 +0400
@@ -0,0 +1,44 @@
+/* @test
+ @bug 6726866
+ @summary Repainting artifacts when resizing or dragging JInternalFrames in non-opaque toplevel
+ @author Alexander Potochkin
+ @run applet/manual=yesno bug6726866.html
+*/
+
+import javax.swing.*;
+import java.awt.*;
+import java.lang.reflect.Method;
+
+public class bug6726866 extends JApplet {
+
+ public void init() {
+ JFrame frame = new JFrame("bug6726866");
+ frame.setUndecorated(true);
+ setWindowNonOpaque(frame);
+
+ JDesktopPane desktop = new JDesktopPane();
+ desktop.setBackground(Color.GREEN);
+ JInternalFrame iFrame = new JInternalFrame("Test", true, true, true, true);
+ iFrame.add(new JLabel("internal Frame"));
+ iFrame.setBounds(10, 10, 300, 200);
+ iFrame.setVisible(true);
+ desktop.add(iFrame);
+ frame.add(desktop);
+
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setSize(400, 400);
+ frame.setVisible(true);
+ frame.toFront();
+ }
+
+ private void setWindowNonOpaque(Window w) {
+ try {
+ Class<?> c = Class.forName("com.sun.awt.AWTUtilities");
+ Method m = c.getMethod("setWindowOpaque", Window.class, boolean.class);
+ m.invoke(null, w, false);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}