--- old/src/macosx/classes/sun/java2d/opengl/CGLLayer.java 2012-06-25 03:33:40.979966585 -0700 +++ new/src/macosx/classes/sun/java2d/opengl/CGLLayer.java 2012-06-25 03:33:40.839966581 -0700 @@ -68,11 +68,12 @@ } 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() { --- old/src/macosx/classes/sun/lwawt/LWComponentPeer.java 2012-06-25 03:33:41.539966600 -0700 +++ new/src/macosx/classes/sun/lwawt/LWComponentPeer.java 2012-06-25 03:33:41.367966595 -0700 @@ -424,8 +424,7 @@ @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 @@ 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 @@ } //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 @@ // 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,6 +1004,15 @@ @Override public final void applyShape(final Region shape) { synchronized (getStateLock()) { + if (region == shape || (region != null && region.equals(shape))) { + return; + } + } + applyShapeImpl(shape); + } + + void applyShapeImpl(final Region shape) { + synchronized (getStateLock()) { region = shape; } repaintParent(getBounds()); @@ -1018,7 +1020,13 @@ 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 +1394,6 @@ } } - // 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 +1404,6 @@ } } - /* - * 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. * --- old/src/macosx/classes/sun/lwawt/LWRepaintArea.java 2012-06-25 03:33:42.171966615 -0700 +++ new/src/macosx/classes/sun/lwawt/LWRepaintArea.java 2012-06-25 03:33:42.039966612 -0700 @@ -58,9 +58,6 @@ private static void flushBuffers(final LWComponentPeer peer) { if (peer != null) { - if (!peer.getWindowPeerOrSelf().isOpaque()) { - peer.flushOffscreenGraphics(); - } peer.flushOnscreenGraphics(); } } --- old/src/macosx/classes/sun/lwawt/LWToolkit.java 2012-06-25 03:33:42.723966630 -0700 +++ new/src/macosx/classes/sun/lwawt/LWToolkit.java 2012-06-25 03:33:42.539966625 -0700 @@ -522,12 +522,6 @@ 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) { --- old/src/macosx/classes/sun/lwawt/LWWindowPeer.java 2012-06-25 03:33:43.299966644 -0700 +++ new/src/macosx/classes/sun/lwawt/LWWindowPeer.java 2012-06-25 03:33:43.151966641 -0700 @@ -37,6 +37,7 @@ 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 @@ private volatile boolean skipNextFocusChange; + private static final Color nonOpaqueBackground = new Color(0, 0, 0, 0); + /** * Current modal blocker or null. * @@ -169,6 +172,11 @@ 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 @@ updateInsets(platformWindow.getInsets()); if (getSurfaceData() == null) { - replaceSurfaceData(); + replaceSurfaceData(false); } } @@ -280,7 +288,7 @@ // "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,9 +428,7 @@ public final void setOpaque(final boolean isOpaque) { if (this.isOpaque != isOpaque) { this.isOpaque = isOpaque; - getPlatformWindow().setOpaque(isOpaque); - replaceSurfaceData(); - repaintPeer(); + updateOpaque(); } } @@ -430,9 +436,24 @@ return isOpaque; } + private void updateOpaque() { + getPlatformWindow().setOpaque(!isTranslucent()); + replaceSurfaceData(false); + repaintPeer(); + } + @Override public void updateWindow() { - flushOffscreenGraphics(); + } + + public final boolean isTranslucent() { + return !isOpaque() || isShaped(); + } + + @Override + final void applyShapeImpl(final Region shape) { + super.applyShapeImpl(shape); + updateOpaque(); } @Override @@ -599,7 +620,18 @@ 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(); } @@ -906,35 +938,6 @@ }); } - /** - * 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. */ @@ -945,11 +948,16 @@ } 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(); @@ -962,7 +970,10 @@ 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 @@ -972,23 +983,31 @@ // TODO: volatile image // backBuffer = (VolatileImage)delegate.createBackBuffer(); - backBuffer = (BufferedImage) platformWindow.createBackBuffer(); - if (backBuffer != null) { - Graphics g = backBuffer.getGraphics(); - try { - Rectangle r = getBounds(); - g.setColor(getBackground()); - if (g instanceof Graphics2D) { - ((Graphics2D) g).setComposite(AlphaComposite.Src); - } - g.fillRect(0, 0, r.width, r.height); - if (oldBB != null) { - // Draw the old back buffer to the new one - g.drawImage(oldBB, 0, 0, null); - oldBB.flush(); + + if (oldBB != null) { + backBuffer = (BufferedImage) platformWindow.createBackBuffer(); + if (backBuffer != null) { + Graphics g = backBuffer.getGraphics(); + try { + Rectangle r = getBounds(); + 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 + g.drawImage(oldBB, 0, 0, null); + oldBB.flush(); + } + } finally { + g.dispose(); } - } finally { - g.dispose(); } } } @@ -1005,7 +1024,7 @@ 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); } } --- old/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2012-06-25 03:33:44.011966663 -0700 +++ new/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java 2012-06-25 03:33:43.835966658 -0700 @@ -735,6 +735,15 @@ 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 @@ -803,6 +812,10 @@ nativeSetEnabled(getNSWindowPtr(), !blocked); } + public final void invalidateShadow(){ + nativeRevalidateNSWindowShadow(getNSWindowPtr()); + } + // ---------------------------------------------------------------------- // UTILITY METHODS // ---------------------------------------------------------------------- --- old/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java 2012-06-25 03:33:44.639966679 -0700 +++ new/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java 2012-06-25 03:33:44.495966675 -0700 @@ -751,6 +751,11 @@ } @Override + public boolean isWindowShapingSupported() { + return true; + } + + @Override public boolean isWindowTranslucencySupported() { return true; } @@ -760,6 +765,10 @@ return true; } + public boolean isSwingBackbufferTranslucencySupported() { + return true; + } + @Override public boolean enableInputMethodsForTextComponent() { return true; --- old/src/macosx/native/sun/awt/AWTWindow.m 2012-06-25 03:33:45.247966695 -0700 +++ new/src/macosx/native/sun/awt/AWTWindow.m 2012-06-25 03:33:45.067966690 -0700 @@ -940,14 +940,17 @@ (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); } --- old/src/share/classes/javax/swing/RepaintManager.java 2012-06-25 03:33:45.851966710 -0700 +++ new/src/share/classes/javax/swing/RepaintManager.java 2012-06-25 03:33:45.707966706 -0700 @@ -119,6 +119,11 @@ // 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 doubleBufferType; + /** * Value of the system property awt.nativeDoubleBuffering. */ private static boolean nativeDoubleBuffering; @@ -204,6 +209,13 @@ ((SunGraphicsEnvironment)ge).addDisplayChangedListener( new DisplayChangedHandler()); } + Toolkit tk = Toolkit.getDefaultToolkit(); + if ((tk instanceof SunToolkit) + && ((SunToolkit) tk).isSwingBackbufferTranslucencySupported()) { + doubleBufferType = Transparency.TRANSLUCENT; + } else { + doubleBufferType = Transparency.OPAQUE; + } } /** @@ -989,7 +1001,8 @@ if (image != null) { image.flush(); } - image = config.createCompatibleVolatileImage(width, height); + image = config.createCompatibleVolatileImage(width, height, + doubleBufferType); volatileMap.put(config, image); } return image; @@ -1483,9 +1496,24 @@ for(y=clipY, maxy = clipY + clipH; y < maxy ; y += bh) { osg.translate(-x, -y); osg.setClip(x,y,bw,bh); + if (doubleBufferType != Transparency.OPAQUE + && osg instanceof Graphics2D) { + Graphics2D g2d = (Graphics2D) osg.create(); + g2d.setBackground(c.getBackground()); + g2d.clearRect(x, y, bw, bh); + g2d.dispose(); + } c.paintToOffscreen(osg, x, y, bw, bh, maxx, maxy); g.setClip(x, y, bw, bh); - g.drawImage(image, x, y, c); + if (doubleBufferType != Transparency.OPAQUE + && osg instanceof Graphics2D) { + Graphics2D g2d = (Graphics2D) g.create(); + g2d.setComposite(AlphaComposite.Src); + g2d.drawImage(image, x, y, c); + g2d.dispose(); + } else { + g.drawImage(image, x, y, c); + } osg.translate(x, y); } } --- old/src/share/classes/sun/awt/SunToolkit.java 2012-06-25 03:33:46.491966726 -0700 +++ new/src/share/classes/sun/awt/SunToolkit.java 2012-06-25 03:33:46.327966722 -0700 @@ -1985,6 +1985,13 @@ } /** + * 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 * {@link GraphicsDevice.WindowTranslucency#PERPIXEL_TRANSLUCENT PERPIXEL_TRANSLUCENT}.