提交 daa16cb1 编写于 作者: S serb

7124244: [macosx] Shaped windows support

Reviewed-by: anthony, art
上级 a60d90be
...@@ -68,11 +68,12 @@ public class CGLLayer extends CFRetainedResource { ...@@ -68,11 +68,12 @@ public class CGLLayer extends CFRetainedResource {
} }
public boolean isOpaque() { public boolean isOpaque() {
return peer.isOpaque(); return !peer.isTranslucent();
} }
public int getTransparency() { public int getTransparency() {
return (peer.isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT); return peer.isTranslucent() ? Transparency.TRANSLUCENT :
Transparency.OPAQUE;
} }
public Object getDestination() { public Object getDestination() {
......
...@@ -424,8 +424,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ...@@ -424,8 +424,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
@Override @Override
public final Graphics getGraphics() { public final Graphics getGraphics() {
Graphics g = getWindowPeerOrSelf().isOpaque() ? getOnscreenGraphics() final Graphics g = getOnscreenGraphics();
: getOffscreenGraphics();
if (g != null) { if (g != null) {
synchronized (getPeerTreeLock()){ synchronized (getPeerTreeLock()){
applyConstrain(g); applyConstrain(g);
...@@ -443,13 +442,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ...@@ -443,13 +442,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
final LWWindowPeer wp = getWindowPeerOrSelf(); final LWWindowPeer wp = getWindowPeerOrSelf();
return wp.getOnscreenGraphics(getForeground(), getBackground(), return wp.getOnscreenGraphics(getForeground(), getBackground(),
getFont()); getFont());
}
public final Graphics getOffscreenGraphics() {
final LWWindowPeer wp = getWindowPeerOrSelf();
return wp.getOffscreenGraphics(getForeground(), getBackground(),
getFont());
} }
private void applyConstrain(final Graphics g) { private void applyConstrain(final Graphics g) {
...@@ -463,7 +456,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ...@@ -463,7 +456,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
} }
//TODO Move this method to SG2D? //TODO Move this method to SG2D?
private void SG2DConstraint(final SunGraphics2D sg2d, Region r) { void SG2DConstraint(final SunGraphics2D sg2d, Region r) {
sg2d.constrainX = sg2d.transX; sg2d.constrainX = sg2d.transX;
sg2d.constrainY = sg2d.transY; sg2d.constrainY = sg2d.transY;
...@@ -710,7 +703,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ...@@ -710,7 +703,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
// Obtain the metrics from the offscreen window where this peer is // Obtain the metrics from the offscreen window where this peer is
// mostly drawn to. // mostly drawn to.
// TODO: check for "use platform metrics" settings // TODO: check for "use platform metrics" settings
Graphics g = getWindowPeer().getOffscreenGraphics(); Graphics g = getWindowPeer().getGraphics();
try { try {
if (g != null) { if (g != null) {
return g.getFontMetrics(f); return g.getFontMetrics(f);
...@@ -1011,14 +1004,33 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ...@@ -1011,14 +1004,33 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
@Override @Override
public final void applyShape(final Region shape) { public final void applyShape(final Region shape) {
synchronized (getStateLock()) { synchronized (getStateLock()) {
region = shape; if (region == shape || (region != null && region.equals(shape))) {
return;
}
}
applyShapeImpl(shape);
}
void applyShapeImpl(final Region shape) {
synchronized (getStateLock()) {
if (shape != null) {
region = Region.WHOLE_REGION.getIntersection(shape);
} else {
region = null;
}
} }
repaintParent(getBounds()); repaintParent(getBounds());
} }
protected final Region getRegion() { protected final Region getRegion() {
synchronized (getStateLock()) { synchronized (getStateLock()) {
return region == null ? Region.getInstance(getSize()) : region; return isShaped() ? region : Region.getInstance(getSize());
}
}
public boolean isShaped() {
synchronized (getStateLock()) {
return region != null;
} }
} }
...@@ -1386,11 +1398,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ...@@ -1386,11 +1398,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
} }
} }
// Just a helper method, thus final
protected final void flushOffscreenGraphics() {
flushOffscreenGraphics(getSize());
}
protected static final void flushOnscreenGraphics(){ protected static final void flushOnscreenGraphics(){
final OGLRenderQueue rq = OGLRenderQueue.getInstance(); final OGLRenderQueue rq = OGLRenderQueue.getInstance();
rq.lock(); rq.lock();
...@@ -1401,36 +1408,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent> ...@@ -1401,36 +1408,6 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
} }
} }
/*
* Flushes the given rectangle from the back buffer to the screen.
*/
protected void flushOffscreenGraphics(Rectangle r) {
flushOffscreenGraphics(r.x, r.y, r.width, r.height);
}
private void flushOffscreenGraphics(int x, int y, int width, int height) {
Image bb = getWindowPeerOrSelf().getBackBuffer();
if (bb != null) {
// g is a screen Graphics from the delegate
final Graphics g = getOnscreenGraphics();
if (g != null && g instanceof Graphics2D) {
try {
Graphics2D g2d = (Graphics2D)g;
Point p = localToWindow(new Point(0, 0));
Composite composite = g2d.getComposite();
g2d.setComposite(AlphaComposite.Src);
g.drawImage(bb, x, y, x + width, y + height, p.x + x,
p.y + y, p.x + x + width, p.y + y + height,
null);
g2d.setComposite(composite);
} finally {
g.dispose();
}
}
}
}
/** /**
* Used by ContainerPeer to skip all the paint events during layout. * Used by ContainerPeer to skip all the paint events during layout.
* *
......
...@@ -58,9 +58,6 @@ final class LWRepaintArea extends RepaintArea { ...@@ -58,9 +58,6 @@ final class LWRepaintArea extends RepaintArea {
private static void flushBuffers(final LWComponentPeer peer) { private static void flushBuffers(final LWComponentPeer peer) {
if (peer != null) { if (peer != null) {
if (!peer.getWindowPeerOrSelf().isOpaque()) {
peer.flushOffscreenGraphics();
}
peer.flushOnscreenGraphics(); peer.flushOnscreenGraphics();
} }
} }
......
...@@ -522,12 +522,6 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { ...@@ -522,12 +522,6 @@ public abstract class LWToolkit extends SunToolkit implements Runnable {
postEvent(targetToAppContext(event.getSource()), event); postEvent(targetToAppContext(event.getSource()), event);
} }
// use peer's back buffer to implement non-opaque windows.
@Override
public boolean needUpdateWindow() {
return true;
}
@Override @Override
public void grab(Window w) { public void grab(Window w) {
if (w.getPeer() != null) { if (w.getPeer() != null) {
......
...@@ -37,6 +37,7 @@ import sun.awt.*; ...@@ -37,6 +37,7 @@ import sun.awt.*;
import sun.java2d.*; import sun.java2d.*;
import sun.java2d.loops.Blit; import sun.java2d.loops.Blit;
import sun.java2d.loops.CompositeType; import sun.java2d.loops.CompositeType;
import sun.java2d.pipe.Region;
import sun.util.logging.PlatformLogger; import sun.util.logging.PlatformLogger;
public class LWWindowPeer public class LWWindowPeer
...@@ -109,6 +110,8 @@ public class LWWindowPeer ...@@ -109,6 +110,8 @@ public class LWWindowPeer
private volatile boolean skipNextFocusChange; private volatile boolean skipNextFocusChange;
private static final Color nonOpaqueBackground = new Color(0, 0, 0, 0);
/** /**
* Current modal blocker or null. * Current modal blocker or null.
* *
...@@ -169,6 +172,11 @@ public class LWWindowPeer ...@@ -169,6 +172,11 @@ public class LWWindowPeer
setAlwaysOnTop(getTarget().isAlwaysOnTop()); setAlwaysOnTop(getTarget().isAlwaysOnTop());
updateMinimumSize(); updateMinimumSize();
final Shape shape = getTarget().getShape();
if (shape != null) {
applyShape(Region.getInstance(shape, null));
}
final float opacity = getTarget().getOpacity(); final float opacity = getTarget().getOpacity();
if (opacity < 1.0f) { if (opacity < 1.0f) {
setOpacity(opacity); setOpacity(opacity);
...@@ -178,7 +186,7 @@ public class LWWindowPeer ...@@ -178,7 +186,7 @@ public class LWWindowPeer
updateInsets(platformWindow.getInsets()); updateInsets(platformWindow.getInsets());
if (getSurfaceData() == null) { if (getSurfaceData() == null) {
replaceSurfaceData(); replaceSurfaceData(false);
} }
} }
...@@ -280,7 +288,7 @@ public class LWWindowPeer ...@@ -280,7 +288,7 @@ public class LWWindowPeer
// "buffer", that's why numBuffers - 1 // "buffer", that's why numBuffers - 1
assert numBuffers > 1; assert numBuffers > 1;
replaceSurfaceData(numBuffers - 1, caps); replaceSurfaceData(numBuffers - 1, caps, false);
} catch (InvalidPipeException z) { } catch (InvalidPipeException z) {
throw new AWTException(z.toString()); throw new AWTException(z.toString());
} }
...@@ -420,19 +428,30 @@ public class LWWindowPeer ...@@ -420,19 +428,30 @@ public class LWWindowPeer
public final void setOpaque(final boolean isOpaque) { public final void setOpaque(final boolean isOpaque) {
if (this.isOpaque != isOpaque) { if (this.isOpaque != isOpaque) {
this.isOpaque = isOpaque; this.isOpaque = isOpaque;
getPlatformWindow().setOpaque(isOpaque); updateOpaque();
replaceSurfaceData();
repaintPeer();
} }
} }
public final boolean isOpaque() { private void updateOpaque() {
return isOpaque; getPlatformWindow().setOpaque(!isTranslucent());
replaceSurfaceData(false);
repaintPeer();
} }
@Override @Override
public void updateWindow() { public void updateWindow() {
flushOffscreenGraphics(); }
public final boolean isTranslucent() {
synchronized (getStateLock()) {
return !isOpaque || isShaped();
}
}
@Override
final void applyShapeImpl(final Region shape) {
super.applyShapeImpl(shape);
updateOpaque();
} }
@Override @Override
...@@ -587,7 +606,18 @@ public class LWWindowPeer ...@@ -587,7 +606,18 @@ public class LWWindowPeer
getFont()); getFont());
if (g != null) { if (g != null) {
try { try {
g.clearRect(0, 0, w, h); if (g instanceof Graphics2D) {
((Graphics2D) g).setComposite(AlphaComposite.Src);
}
if (isTranslucent()) {
g.setColor(nonOpaqueBackground);
g.fillRect(0, 0, w, h);
}
if (g instanceof SunGraphics2D) {
SG2DConstraint((SunGraphics2D) g, getRegion());
}
g.setColor(getBackground());
g.fillRect(0, 0, w, h);
} finally { } finally {
g.dispose(); g.dispose();
} }
...@@ -894,35 +924,6 @@ public class LWWindowPeer ...@@ -894,35 +924,6 @@ public class LWWindowPeer
}); });
} }
/**
* This method returns a back buffer Graphics to render all the
* peers to. After the peer is painted, the back buffer contents
* should be flushed to the screen. All the target painting
* (Component.paint() method) should be done directly to the screen.
*/
protected final Graphics getOffscreenGraphics(Color fg, Color bg, Font f) {
final Image bb = getBackBuffer();
if (bb == null) {
return null;
}
if (fg == null) {
fg = SystemColor.windowText;
}
if (bg == null) {
bg = SystemColor.window;
}
if (f == null) {
f = DEFAULT_FONT;
}
final Graphics2D g = (Graphics2D) bb.getGraphics();
if (g != null) {
g.setColor(fg);
g.setBackground(bg);
g.setFont(f);
}
return g;
}
/* /*
* May be called by delegate to provide SD to Java2D code. * May be called by delegate to provide SD to Java2D code.
*/ */
...@@ -933,11 +934,16 @@ public class LWWindowPeer ...@@ -933,11 +934,16 @@ public class LWWindowPeer
} }
private void replaceSurfaceData() { private void replaceSurfaceData() {
replaceSurfaceData(backBufferCount, backBufferCaps); replaceSurfaceData(true);
}
private void replaceSurfaceData(boolean blit) {
replaceSurfaceData(backBufferCount, backBufferCaps, blit);
} }
private void replaceSurfaceData(int newBackBufferCount, private void replaceSurfaceData(int newBackBufferCount,
BufferCapabilities newBackBufferCaps) { BufferCapabilities newBackBufferCaps,
boolean blit) {
synchronized (surfaceDataLock) { synchronized (surfaceDataLock) {
final SurfaceData oldData = getSurfaceData(); final SurfaceData oldData = getSurfaceData();
surfaceData = platformWindow.replaceSurfaceData(); surfaceData = platformWindow.replaceSurfaceData();
...@@ -950,7 +956,10 @@ public class LWWindowPeer ...@@ -950,7 +956,10 @@ public class LWWindowPeer
if (getSurfaceData() != null && oldData != getSurfaceData()) { if (getSurfaceData() != null && oldData != getSurfaceData()) {
clearBackground(size.width, size.height); clearBackground(size.width, size.height);
} }
blitSurfaceData(oldData, getSurfaceData());
if (blit) {
blitSurfaceData(oldData, getSurfaceData());
}
if (oldData != null && oldData != getSurfaceData()) { if (oldData != null && oldData != getSurfaceData()) {
// TODO: drop oldData for D3D/WGL pipelines // TODO: drop oldData for D3D/WGL pipelines
...@@ -965,10 +974,15 @@ public class LWWindowPeer ...@@ -965,10 +974,15 @@ public class LWWindowPeer
Graphics g = backBuffer.getGraphics(); Graphics g = backBuffer.getGraphics();
try { try {
Rectangle r = getBounds(); Rectangle r = getBounds();
g.setColor(getBackground());
if (g instanceof Graphics2D) { if (g instanceof Graphics2D) {
((Graphics2D) g).setComposite(AlphaComposite.Src); ((Graphics2D) g).setComposite(AlphaComposite.Src);
} }
g.setColor(nonOpaqueBackground);
g.fillRect(0, 0, r.width, r.height);
if (g instanceof SunGraphics2D) {
SG2DConstraint((SunGraphics2D) g, getRegion());
}
g.setColor(getBackground());
g.fillRect(0, 0, r.width, r.height); g.fillRect(0, 0, r.width, r.height);
if (oldBB != null) { if (oldBB != null) {
// Draw the old back buffer to the new one // Draw the old back buffer to the new one
...@@ -993,7 +1007,7 @@ public class LWWindowPeer ...@@ -993,7 +1007,7 @@ public class LWWindowPeer
CompositeType.Src, CompositeType.Src,
dst.getSurfaceType()); dst.getSurfaceType());
if (blit != null) { if (blit != null) {
blit.Blit(src, dst, ((Graphics2D) getGraphics()).getComposite(), blit.Blit(src, dst, AlphaComposite.Src,
getRegion(), 0, 0, 0, 0, size.width, size.height); getRegion(), 0, 0, 0, 0, size.width, size.height);
} }
} }
......
...@@ -117,7 +117,7 @@ public class CPlatformEmbeddedFrame implements PlatformWindow { ...@@ -117,7 +117,7 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
Rectangle r = peer.getBounds(); Rectangle r = peer.getBounds();
Image im = null; Image im = null;
if (!r.isEmpty()) { if (!r.isEmpty()) {
int transparency = (peer.isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT); int transparency = peer.isTranslucent() ? Transparency.TRANSLUCENT : Transparency.OPAQUE;
im = peer.getGraphicsConfiguration().createCompatibleImage(r.width, r.height, transparency); im = peer.getGraphicsConfiguration().createCompatibleImage(r.width, r.height, transparency);
} }
return im; return im;
......
...@@ -64,7 +64,7 @@ public class CPlatformView extends CFRetainedResource { ...@@ -64,7 +64,7 @@ public class CPlatformView extends CFRetainedResource {
} }
public boolean isOpaque() { public boolean isOpaque() {
return peer.isOpaque(); return !peer.isTranslucent();
} }
/* /*
......
...@@ -737,6 +737,15 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo ...@@ -737,6 +737,15 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
long clearColor = CWrapper.NSColor.clearColor(); long clearColor = CWrapper.NSColor.clearColor();
CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), clearColor); CWrapper.NSWindow.setBackgroundColor(getNSWindowPtr(), clearColor);
} }
//This is a temporary workaround. Looks like after 7124236 will be fixed
//the correct place for invalidateShadow() is CGLayer.drawInCGLContext.
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
invalidateShadow();
}
});
} }
@Override @Override
...@@ -805,6 +814,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo ...@@ -805,6 +814,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
nativeSetEnabled(getNSWindowPtr(), !blocked); nativeSetEnabled(getNSWindowPtr(), !blocked);
} }
public final void invalidateShadow(){
nativeRevalidateNSWindowShadow(getNSWindowPtr());
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// UTILITY METHODS // UTILITY METHODS
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
......
...@@ -749,6 +749,11 @@ public class LWCToolkit extends LWToolkit { ...@@ -749,6 +749,11 @@ public class LWCToolkit extends LWToolkit {
(modalityType == Dialog.ModalityType.TOOLKIT_MODAL); (modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
} }
@Override
public boolean isWindowShapingSupported() {
return true;
}
@Override @Override
public boolean isWindowTranslucencySupported() { public boolean isWindowTranslucencySupported() {
return true; return true;
...@@ -759,6 +764,10 @@ public class LWCToolkit extends LWToolkit { ...@@ -759,6 +764,10 @@ public class LWCToolkit extends LWToolkit {
return true; return true;
} }
public boolean isSwingBackbufferTranslucencySupported() {
return true;
}
@Override @Override
public boolean enableInputMethodsForTextComponent() { public boolean enableInputMethodsForTextComponent() {
return true; return true;
......
...@@ -941,14 +941,17 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSW ...@@ -941,14 +941,17 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSW
(JNIEnv *env, jclass clazz, jlong windowPtr) (JNIEnv *env, jclass clazz, jlong windowPtr)
{ {
JNF_COCOA_ENTER(env); JNF_COCOA_ENTER(env);
AWT_ASSERT_NOT_APPKIT_THREAD;
NSWindow *nsWindow = OBJC(windowPtr); NSWindow *nsWindow = OBJC(windowPtr);
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){ if ([NSThread isMainThread]) {
AWT_ASSERT_APPKIT_THREAD;
[nsWindow invalidateShadow]; [nsWindow invalidateShadow];
}]; } else {
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
AWT_ASSERT_APPKIT_THREAD;
[nsWindow invalidateShadow];
}];
}
JNF_COCOA_EXIT(env); JNF_COCOA_EXIT(env);
} }
......
...@@ -118,6 +118,11 @@ public class RepaintManager ...@@ -118,6 +118,11 @@ public class RepaintManager
// Whether or not a VolatileImage should be used for double-buffered painting // Whether or not a VolatileImage should be used for double-buffered painting
static boolean volatileImageBufferEnabled = true; static boolean volatileImageBufferEnabled = true;
/**
* Type of VolatileImage which should be used for double-buffered
* painting.
*/
private static final int volatileBufferType;
/** /**
* Value of the system property awt.nativeDoubleBuffering. * Value of the system property awt.nativeDoubleBuffering.
*/ */
...@@ -204,6 +209,13 @@ public class RepaintManager ...@@ -204,6 +209,13 @@ public class RepaintManager
((SunGraphicsEnvironment)ge).addDisplayChangedListener( ((SunGraphicsEnvironment)ge).addDisplayChangedListener(
new DisplayChangedHandler()); new DisplayChangedHandler());
} }
Toolkit tk = Toolkit.getDefaultToolkit();
if ((tk instanceof SunToolkit)
&& ((SunToolkit) tk).isSwingBackbufferTranslucencySupported()) {
volatileBufferType = Transparency.TRANSLUCENT;
} else {
volatileBufferType = Transparency.OPAQUE;
}
} }
/** /**
...@@ -989,7 +1001,8 @@ public class RepaintManager ...@@ -989,7 +1001,8 @@ public class RepaintManager
if (image != null) { if (image != null) {
image.flush(); image.flush();
} }
image = config.createCompatibleVolatileImage(width, height); image = config.createCompatibleVolatileImage(width, height,
volatileBufferType);
volatileMap.put(config, image); volatileMap.put(config, image);
} }
return image; return image;
...@@ -1483,9 +1496,26 @@ public class RepaintManager ...@@ -1483,9 +1496,26 @@ public class RepaintManager
for(y=clipY, maxy = clipY + clipH; y < maxy ; y += bh) { for(y=clipY, maxy = clipY + clipH; y < maxy ; y += bh) {
osg.translate(-x, -y); osg.translate(-x, -y);
osg.setClip(x,y,bw,bh); osg.setClip(x,y,bw,bh);
if (volatileBufferType != Transparency.OPAQUE
&& osg instanceof Graphics2D) {
final Graphics2D g2d = (Graphics2D) osg;
final Color oldBg = g2d.getBackground();
g2d.setBackground(c.getBackground());
g2d.clearRect(x, y, bw, bh);
g2d.setBackground(oldBg);
}
c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy); c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy);
g.setClip(x, y, bw, bh); g.setClip(x, y, bw, bh);
g.drawImage(image, x, y, c); if (volatileBufferType != Transparency.OPAQUE
&& g instanceof Graphics2D) {
final Graphics2D g2d = (Graphics2D) g;
final Composite oldComposite = g2d.getComposite();
g2d.setComposite(AlphaComposite.Src);
g2d.drawImage(image, x, y, c);
g2d.setComposite(oldComposite);
} else {
g.drawImage(image, x, y, c);
}
osg.translate(x, y); osg.translate(x, y);
} }
} }
......
...@@ -1984,6 +1984,13 @@ public abstract class SunToolkit extends Toolkit ...@@ -1984,6 +1984,13 @@ public abstract class SunToolkit extends Toolkit
return false; return false;
} }
/**
* Returns true if swing backbuffer should be translucent.
*/
public boolean isSwingBackbufferTranslucencySupported() {
return false;
}
/** /**
* Returns whether or not a containing top level window for the passed * Returns whether or not a containing top level window for the passed
* component is * component is
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册