提交 02ec5bc7 编写于 作者: A art

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
上级 f839595c
......@@ -436,7 +436,7 @@ public abstract class GraphicsConfiguration {
}
/**
* Returns whether this GraphicsConfiguration supports
* Returns whether this {@code GraphicsConfiguration} supports
* the {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT
* PERPIXEL_TRANSLUCENT} kind of translucency.
*
......
......@@ -246,7 +246,7 @@ public abstract class GraphicsDevice {
* 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 @@ public abstract class GraphicsDevice {
*
* @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
......
......@@ -296,7 +296,7 @@ public class Window extends Container implements Accessible {
transient boolean isInShow = false;
/*
* Opacity level of the window
* The opacity level of the window
*
* @serial
* @see #setOpacity(float)
......@@ -306,7 +306,7 @@ public class Window extends Container implements Accessible {
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 @@ public class Window extends Container implements Accessible {
@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 @@ public class Window extends Container implements Accessible {
}
}
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 @@ public class Window extends Container implements Accessible {
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 @@ public class Window extends Container implements Accessible {
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) {
......
......@@ -110,12 +110,11 @@ public interface WindowPeer extends ContainerPeer {
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.
......
......@@ -34,6 +34,9 @@ import java.awt.event.ComponentListener;
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 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab
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 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab
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 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab
} else {
dirtyRects = new Rectangle[1];
dirtyRects[0] = previousBounds;
// System.out.println("no intersection");
};
// Fix the damage
......@@ -701,14 +698,22 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab
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) {
......
......@@ -1021,8 +1021,10 @@ public abstract class JComponent extends Container implements Serializable,
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,
......
......@@ -43,7 +43,6 @@ 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
......@@ -717,14 +716,12 @@ public class RepaintManager
}
}
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 @@ public class RepaintManager
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 @@ public class RepaintManager
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 @@ public class RepaintManager
}
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 @@ public class RepaintManager
} finally {
painting = false;
}
updateWindows(tmpDirtyComponents);
tmpDirtyComponents.clear();
}
......@@ -1004,6 +993,16 @@ public class RepaintManager
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 @@ public class RepaintManager
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();
}
......
......@@ -132,7 +132,7 @@ public final class AWTAccessor {
/*
* 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.
*/
......
......@@ -592,8 +592,9 @@ public abstract class EmbeddedFrame extends Frame
public void setOpaque(boolean isOpaque) {
}
public void updateWindow(BufferedImage bi) {
public void updateWindow() {
}
public void repositionSecurityWarning() {
}
}
......
......@@ -2058,7 +2058,7 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
}
@Override
public void updateWindow(BufferedImage backBuffer) {
public void updateWindow() {
// no-op
}
}
......@@ -105,9 +105,10 @@ public abstract class TranslucentWindowPainter {
}
/**
* 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 class TranslucentWindowPainter {
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 @@ public abstract class TranslucentWindowPainter {
}
}
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 @@ public abstract class TranslucentWindowPainter {
* 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 @@ public abstract class TranslucentWindowPainter {
}
// 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 abstract class TranslucentWindowPainter {
}
public void flush() {
if (biRef != null) {
biRef.clear();
if (backBuffer != null) {
backBuffer.flush();
backBuffer = null;
}
}
}
......@@ -271,27 +244,22 @@ public abstract class TranslucentWindowPainter {
* 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 @@ public abstract class TranslucentWindowPainter {
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;
}
}
}
......
......@@ -78,25 +78,6 @@ class WCanvasPeer extends WComponentPeer implements CanvasPeer {
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;
}
......
......@@ -239,7 +239,8 @@ public abstract class WComponentPeer extends WObjectPeer
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 @@ public abstract class WComponentPeer extends WObjectPeer
}
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);
......
......@@ -42,6 +42,9 @@ abstract class WObjectPeer {
// 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 @@ abstract class WObjectPeer {
return target;
}
public final Object getStateLock() {
return stateLock;
}
/*
* Subclasses should override disposeImpl() instead of dispose(). Client
* code should always invoke dispose(), never disposeImpl().
......
......@@ -54,7 +54,7 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
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 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
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 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
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 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
setAlwaysOnTop(alwaysOnTop);
}
updateWindow(null);
synchronized (getStateLock()) {
if (!isOpaque) {
updateWindow(true);
}
}
}
// Synchronize the insets members (here & in helper) with actual window
......@@ -334,29 +354,6 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
}
}
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 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
}
}
@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 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
}
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 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
}
}
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 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
}
}
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 @@ public class WWindowPeer extends WPanelPeer implements WindowPeer,
}
}
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");
}
}
}
/*
......
......@@ -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 @@ struct CreatePrintedPixelsStruct {
jobject component;
int srcx, srcy;
int srcw, srch;
jint alpha;
};
// Struct for _SetRectangularShape() method
struct SetRectangularShapeStruct {
......@@ -361,8 +363,8 @@ AwtComponent* AwtComponent::GetComponent(HWND hWnd) {
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 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
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::FillBackground(HDC hMemoryDC, SIZE &size)
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 @@ jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size) {
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 @@ jintArray AwtComponent::CreatePrintedPixels(SIZE &loc, SIZE &size) {
// 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 @@ jintArray AwtComponent::_CreatePrintedPixels(void *param)
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 @@ jintArray AwtComponent::_CreatePrintedPixels(void *param)
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 @@ Java_sun_awt_windows_WComponentPeer_getTargetGC(JNIEnv* env, jobject theThis)
*/
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 @@ Java_sun_awt_windows_WComponentPeer_createPrintedPixels(JNIEnv* env,
cpps->srcy = srcY;
cpps->srcw = srcW;
cpps->srch = srcH;
cpps->alpha = alpha;
jintArray globalRef = (jintArray)AwtToolkit::GetInstance().SyncCall(
(void*(*)(void*))AwtComponent::_CreatePrintedPixels, cpps);
......
......@@ -596,7 +596,7 @@ public:
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 @@ protected:
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);
......
......@@ -464,7 +464,7 @@ void AwtWindow::CreateHWnd(JNIEnv *env, LPCWSTR title,
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 @@ void AwtWindow::UpdateWindow(JNIEnv* env, jintArray data, int width, int height,
::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
......
......@@ -343,11 +343,6 @@ protected:
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;
}
......
/* @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;
}
}
<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>
/* @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();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册