United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-6710012 : Per pixel translucency not working on X

Details
Type:
Bug
Submit Date:
2008-06-03
Status:
Resolved
Updated Date:
2011-01-19
Project Name:
JDK
Resolved Date:
2008-09-02
Component:
client-libs
OS:
linux
Sub-Component:
java.awt
CPU:
x86
Priority:
P2
Resolution:
Fixed
Affected Versions:
6
Fixed Versions:
6u10 (b31)

Related Reports
Relates:

Sub Tasks

Description
FULL PRODUCT VERSION :
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)

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


A DESCRIPTION OF THE PROBLEM :
When "Enable the per-pixel translucency effect" is selected in the demo available at,

http://java.sun.com/developer/technicalArticles/GUI/translucent_shaped_windows/#Demo

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.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
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.

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

REPRODUCIBILITY :
This bug can be reproduced always.

                                    

Comments
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.
                                     
2008-07-14
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.
                                     
2008-07-11
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.
                                     
2008-07-11
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;
+    }
 }
                                     
2008-07-14



Hardware and Software, Engineered to Work Together