JDK-6710012 : Per pixel translucency not working on X
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: linux
  • CPU: x86
  • Submitted: 2008-06-03
  • Updated: 2011-01-19
  • Resolved: 2008-09-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
6u10 b31Fixed
Related Reports
Relates :  
java version "1.6.0_10-beta"
Java(TM) SE Runtime Environment (build 1.6.0_10-beta-b23)
Java HotSpot(TM) Server VM (build 11.0-b11, mixed mode)

Linux penguin-splendor 2.6.24-17-generic #1 SMP Thu May 1 14:31:33 UTC 2008 i686 GNU/Linux

When "Enable the per-pixel translucency effect" is selected in the demo available at,


The translucent frame completely disappears.  However, if this option is not selected, the translucent window is visible and normal translucency works fine.  Due to this, the "Paint Gradient" option does not work well too.

The demo runs perfectly well on Windows platforms.  I'm sorry that I'm unable to provide my own code to demonstrate the bug as I do not want to install a Beta JDK for various reasons.

But I decided that it should be due to a bug in JRE because the same demo runs well on Windows.  It is really disheartening to see a brand new exciting feature having a platform specific bug.

Launch the demo at http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/#Demo

With compiz enabled on Ubuntu 8.04, select "Enable the per-pixel translucency effect" and "Paint gradient" check boxes.  Then click on "Display the frame" button.

A translucent window with a gradient of 100% opacity at one corner and 0% opacity on the other.
The translucent window was not visible.  However, a taskbar entry is visible with "Java" as title.

This bug can be reproduced always.

EVALUATION The suggested fix introduces the sun.awt.SunToolkit.needUpdateWindow() method. If this method returns false, the RepaintManager.updateWindows() method simply returns the initial dirtyComponents map. If needUpdateWindow() returns true, then the updateWindow() works as usual.

SUGGESTED FIX --- old/src/share/classes/javax/swing/RepaintManager.java 2008-07-16 16:18:02.000000000 +0400 +++ new/src/share/classes/javax/swing/RepaintManager.java 2008-07-16 16:18:02.000000000 +0400 @@ -717,8 +717,12 @@ private Map<Component,Rectangle> updateWindows(Map<Component,Rectangle> dirtyComponents) { + Toolkit toolkit = Toolkit.getDefaultToolkit(); + if (!AWTUtilities.isTranslucencySupported( - AWTUtilities.Translucency.PERPIXEL_TRANSLUCENT)) + AWTUtilities.Translucency.PERPIXEL_TRANSLUCENT) || + !(toolkit instanceof SunToolkit && + ((SunToolkit)toolkit).needUpdateWindow())) { return dirtyComponents; } @@ -1327,10 +1331,11 @@ if (paintManager == null) { PaintManager paintManager = null; if (doubleBufferingEnabled && !nativeDoubleBuffering) { + Toolkit toolkit = Toolkit.getDefaultToolkit(); switch (bufferStrategyType) { case BUFFER_STRATEGY_NOT_SPECIFIED: - if (((SunToolkit)Toolkit.getDefaultToolkit()). - useBufferPerWindow()) { + if (toolkit instanceof SunToolkit && + ((SunToolkit)toolkit).useBufferPerWindow()) { paintManager = new BufferStrategyPaintManager(); } break; --- old/src/share/classes/sun/awt/SunToolkit.java 2008-07-16 16:18:03.000000000 +0400 +++ new/src/share/classes/sun/awt/SunToolkit.java 2008-07-16 16:18:03.000000000 +0400 @@ -1997,6 +1997,17 @@ return c != null && AWTUtilities.getWindowOpacity((Window)c) < 1.0f; } + /** + * Returns whether the native system requires using the peer.updateWindow() + * method to update the contents of a non-opaque window, or if usual + * painting procedures are sufficient. The default return value covers + * the X11 systems. On MS Windows this method is overriden in WToolkit + * to return true. + */ + public boolean needUpdateWindow() { + return false; + } + /////////////////////////////////////////////////////////////////////////// // // The following methods help set and identify whether a particular --- old/src/windows/classes/sun/awt/windows/WToolkit.java 2008-07-16 16:18:03.000000000 +0400 +++ new/src/windows/classes/sun/awt/windows/WToolkit.java 2008-07-16 16:18:03.000000000 +0400 @@ -1012,4 +1012,11 @@ //XXX: worth checking if 8-bit? Anyway, it doesn't hurt. return true; } + + // On MS Windows one must use the peer.updateWindow() to implement + // non-opaque windows. + @Override + public boolean needUpdateWindow() { + return true; + } }

EVALUATION Note that simply undoing the fix for 6687141 would not work as it would break the windows side, not to mention the double-repainting which severely degrades perforance since the second time the rendering is done to a GDI surface. Please consider changing the way translucent windows repainted to be consistent, or perhaps change updateWindow to return a status of whether it actually did something, and do "normal" swing repainting in case it didn't.

EVALUATION This issue is reproducible with Swing frames only. If the application uses AWT frames, everything works fine. I've manually extracted the method that applies translucency-related changes to the frame when making it non-opaque. In this case the effect could not be reproduced: the frame bacame translucent and visible. Hence, the most probable reason for this issue tp appear is some code that checks whether the window is opaque or not. The only such location is the javax.swing.RepaintManager.updateWindows() method. Last time it got changed as a part of the fix for CR 6687141. With this fix this method started to remove the components belonging to a non-opaque frame from the dirtyComponents map. Indeed, on MS Windows platform this should not hurt because all the components get repainted whith the updateWindow() method. However, on X11 platform this does not work correctly, because updateWindow() does nothing on these platforms: we expect that what Swing paints gets directly to the X11 window, and hence appears on the screen. Excluding the components from the dirtyComponents map excludes them from repainting, and therefore nothing gets painted on the screen. So, this seems to be a regression of 6687141.