提交 daa16cb1 编写于 作者: S serb

7124244: [macosx] Shaped windows support

Reviewed-by: anthony, art
上级 a60d90be
......@@ -68,11 +68,12 @@ public class CGLLayer extends CFRetainedResource {
}
public boolean isOpaque() {
return peer.isOpaque();
return !peer.isTranslucent();
}
public int getTransparency() {
return (peer.isOpaque() ? Transparency.OPAQUE : Transparency.TRANSLUCENT);
return peer.isTranslucent() ? Transparency.TRANSLUCENT :
Transparency.OPAQUE;
}
public Object getDestination() {
......
......@@ -424,8 +424,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
@Override
public final Graphics getGraphics() {
Graphics g = getWindowPeerOrSelf().isOpaque() ? getOnscreenGraphics()
: getOffscreenGraphics();
final Graphics g = getOnscreenGraphics();
if (g != null) {
synchronized (getPeerTreeLock()){
applyConstrain(g);
......@@ -443,13 +442,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
final LWWindowPeer wp = getWindowPeerOrSelf();
return wp.getOnscreenGraphics(getForeground(), getBackground(),
getFont());
}
public final Graphics getOffscreenGraphics() {
final LWWindowPeer wp = getWindowPeerOrSelf();
return wp.getOffscreenGraphics(getForeground(), getBackground(),
getFont());
}
private void applyConstrain(final Graphics g) {
......@@ -463,7 +456,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
}
//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.constrainY = sg2d.transY;
......@@ -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
// mostly drawn to.
// TODO: check for "use platform metrics" settings
Graphics g = getWindowPeer().getOffscreenGraphics();
Graphics g = getWindowPeer().getGraphics();
try {
if (g != null) {
return g.getFontMetrics(f);
......@@ -1011,14 +1004,33 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
@Override
public final void applyShape(final Region shape) {
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());
}
protected final Region getRegion() {
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>
}
}
// Just a helper method, thus final
protected final void flushOffscreenGraphics() {
flushOffscreenGraphics(getSize());
}
protected static final void flushOnscreenGraphics(){
final OGLRenderQueue rq = OGLRenderQueue.getInstance();
rq.lock();
......@@ -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.
*
......
......@@ -58,9 +58,6 @@ final class LWRepaintArea extends RepaintArea {
private static void flushBuffers(final LWComponentPeer peer) {
if (peer != null) {
if (!peer.getWindowPeerOrSelf().isOpaque()) {
peer.flushOffscreenGraphics();
}
peer.flushOnscreenGraphics();
}
}
......
......@@ -522,12 +522,6 @@ public abstract class LWToolkit extends SunToolkit implements Runnable {
postEvent(targetToAppContext(event.getSource()), event);
}
// use peer's back buffer to implement non-opaque windows.
@Override
public boolean needUpdateWindow() {
return true;
}
@Override
public void grab(Window w) {
if (w.getPeer() != null) {
......
......@@ -37,6 +37,7 @@ import sun.awt.*;
import sun.java2d.*;
import sun.java2d.loops.Blit;
import sun.java2d.loops.CompositeType;
import sun.java2d.pipe.Region;
import sun.util.logging.PlatformLogger;
public class LWWindowPeer
......@@ -109,6 +110,8 @@ public class LWWindowPeer
private volatile boolean skipNextFocusChange;
private static final Color nonOpaqueBackground = new Color(0, 0, 0, 0);
/**
* Current modal blocker or null.
*
......@@ -169,6 +172,11 @@ public class LWWindowPeer
setAlwaysOnTop(getTarget().isAlwaysOnTop());
updateMinimumSize();
final Shape shape = getTarget().getShape();
if (shape != null) {
applyShape(Region.getInstance(shape, null));
}
final float opacity = getTarget().getOpacity();
if (opacity < 1.0f) {
setOpacity(opacity);
......@@ -178,7 +186,7 @@ public class LWWindowPeer
updateInsets(platformWindow.getInsets());
if (getSurfaceData() == null) {
replaceSurfaceData();
replaceSurfaceData(false);
}
}
......@@ -280,7 +288,7 @@ public class LWWindowPeer
// "buffer", that's why numBuffers - 1
assert numBuffers > 1;
replaceSurfaceData(numBuffers - 1, caps);
replaceSurfaceData(numBuffers - 1, caps, false);
} catch (InvalidPipeException z) {
throw new AWTException(z.toString());
}
......@@ -420,19 +428,30 @@ public class LWWindowPeer
public final void setOpaque(final boolean isOpaque) {
if (this.isOpaque != isOpaque) {
this.isOpaque = isOpaque;
getPlatformWindow().setOpaque(isOpaque);
replaceSurfaceData();
repaintPeer();
updateOpaque();
}
}
public final boolean isOpaque() {
return isOpaque;
private void updateOpaque() {
getPlatformWindow().setOpaque(!isTranslucent());
replaceSurfaceData(false);
repaintPeer();
}
@Override
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
......@@ -587,7 +606,18 @@ public class LWWindowPeer
getFont());
if (g != null) {
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 {
g.dispose();
}
......@@ -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.
*/
......@@ -933,11 +934,16 @@ public class LWWindowPeer
}
private void replaceSurfaceData() {
replaceSurfaceData(backBufferCount, backBufferCaps);
replaceSurfaceData(true);
}
private void replaceSurfaceData(boolean blit) {
replaceSurfaceData(backBufferCount, backBufferCaps, blit);
}
private void replaceSurfaceData(int newBackBufferCount,
BufferCapabilities newBackBufferCaps) {
BufferCapabilities newBackBufferCaps,
boolean blit) {
synchronized (surfaceDataLock) {
final SurfaceData oldData = getSurfaceData();
surfaceData = platformWindow.replaceSurfaceData();
......@@ -950,7 +956,10 @@ public class LWWindowPeer
if (getSurfaceData() != null && oldData != getSurfaceData()) {
clearBackground(size.width, size.height);
}
blitSurfaceData(oldData, getSurfaceData());
if (blit) {
blitSurfaceData(oldData, getSurfaceData());
}
if (oldData != null && oldData != getSurfaceData()) {
// TODO: drop oldData for D3D/WGL pipelines
......@@ -965,10 +974,15 @@ public class LWWindowPeer
Graphics g = backBuffer.getGraphics();
try {
Rectangle r = getBounds();
g.setColor(getBackground());
if (g instanceof Graphics2D) {
((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);
if (oldBB != null) {
// Draw the old back buffer to the new one
......@@ -993,7 +1007,7 @@ public class LWWindowPeer
CompositeType.Src,
dst.getSurfaceType());
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);
}
}
......
......@@ -117,7 +117,7 @@ public class CPlatformEmbeddedFrame implements PlatformWindow {
Rectangle r = peer.getBounds();
Image im = null;
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);
}
return im;
......
......@@ -64,7 +64,7 @@ public class CPlatformView extends CFRetainedResource {
}
public boolean isOpaque() {
return peer.isOpaque();
return !peer.isTranslucent();
}
/*
......
......@@ -737,6 +737,15 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
long clearColor = CWrapper.NSColor.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
......@@ -805,6 +814,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
nativeSetEnabled(getNSWindowPtr(), !blocked);
}
public final void invalidateShadow(){
nativeRevalidateNSWindowShadow(getNSWindowPtr());
}
// ----------------------------------------------------------------------
// UTILITY METHODS
// ----------------------------------------------------------------------
......
......@@ -749,6 +749,11 @@ public class LWCToolkit extends LWToolkit {
(modalityType == Dialog.ModalityType.TOOLKIT_MODAL);
}
@Override
public boolean isWindowShapingSupported() {
return true;
}
@Override
public boolean isWindowTranslucencySupported() {
return true;
......@@ -759,6 +764,10 @@ public class LWCToolkit extends LWToolkit {
return true;
}
public boolean isSwingBackbufferTranslucencySupported() {
return true;
}
@Override
public boolean enableInputMethodsForTextComponent() {
return true;
......
......@@ -941,14 +941,17 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeRevalidateNSW
(JNIEnv *env, jclass clazz, jlong windowPtr)
{
JNF_COCOA_ENTER(env);
AWT_ASSERT_NOT_APPKIT_THREAD;
NSWindow *nsWindow = OBJC(windowPtr);
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
AWT_ASSERT_APPKIT_THREAD;
if ([NSThread isMainThread]) {
[nsWindow invalidateShadow];
}];
} else {
[JNFRunLoop performOnMainThreadWaiting:NO withBlock:^(){
AWT_ASSERT_APPKIT_THREAD;
[nsWindow invalidateShadow];
}];
}
JNF_COCOA_EXIT(env);
}
......
......@@ -118,6 +118,11 @@ public class RepaintManager
// Whether or not a VolatileImage should be used for double-buffered painting
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.
*/
......@@ -204,6 +209,13 @@ public class RepaintManager
((SunGraphicsEnvironment)ge).addDisplayChangedListener(
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
if (image != null) {
image.flush();
}
image = config.createCompatibleVolatileImage(width, height);
image = config.createCompatibleVolatileImage(width, height,
volatileBufferType);
volatileMap.put(config, image);
}
return image;
......@@ -1483,9 +1496,26 @@ public class RepaintManager
for(y=clipY, maxy = clipY + clipH; y < maxy ; y += bh) {
osg.translate(-x, -y);
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);
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);
}
}
......
......@@ -1984,6 +1984,13 @@ public abstract class SunToolkit extends Toolkit
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
* component is
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册