JDK-6342546 : REGRESSION: WinXP LaF: Disabled JButtons have black border
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0,6
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic,windows_xp,windows_vista
  • CPU: generic,x86
  • Submitted: 2005-10-27
  • Updated: 2010-05-10
  • Resolved: 2006-05-31
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.
Other JDK 6
5.0u8Fixed 6 b86Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0-ea"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-ea-b56)
Java HotSpot(TM) Client VM (build 1.6.0-ea-b56, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Disabled JButtons have a black border around their edges when using the Windows XP look and feel.

It seems that the problem only manifests itself when I use the "Olive Green"
theme. If I use "Default (blue)" or "Silver", the problem isn't there. I
have uploaded a screenshot of the test program running under the three
themes that come with Windows XP.[1] Of them, only the Olive Green one
displays the black border.

[1] http://www.cse.ohio-state.edu/~eckenror/Java/Disabled%20Buttons.png<http://www.cse.ohio-state.edu/%7Eeckenror/Java/Disabled%20Buttons.png>

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Observe any disabled JButton in the Windows XP look and feel.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The button looks like it does in native apps and did in Tiger.
ACTUAL -
The button has a black border when disabled.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;

public class Main {
    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        JButton button = new JButton("Disabled Text");
        button.setEnabled(false);
        
        frame.add(button);
        frame.pack();
        frame.setVisible(true);
    }
}

---------- END SOURCE ----------

Comments
EVALUATION Switching to default transparency of TRUE had the unforunate side effect of screwing up the +/- widget used by JTrees. It looks like the problem is with GetThemeBool(), which reports "Element not found" for both disabled buttons and the JTree widget. Fortunately, we can obtain the information we need from a different function, IsThemeBackgroundPartiallyTransparent(). This works properly for all the parts and states that we use (including buttons and tree widgets), so we're able to pass the appropriate transparency into copyDIBToBufferedImage().
04-05-2006

SUGGESTED FIX ------- ThemeReader.cpp ------- *** /tmp/sccs.003344 Wed May 3 16:10:48 2006 --- ThemeReader.cpp Wed May 3 14:46:38 2006 *************** *** 100,105 **** --- 100,107 ---- typedef HRESULT(__stdcall *PFNSETWINDOWTHEME)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList); + typedef HRESULT (__stdcall *PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT )(HTHEME hTheme, int iPartId, int iStateId); + static PFNOPENTHEMEDATA OpenThemeData = NULL; static PFNDRAWTHEMEBACKGROUND DrawThemeBackground = NULL; static PFNCLOSETHEMEDATA CloseThemeData = NULL; *************** *** 114,119 **** --- 116,122 ---- static PFNGETTHEMEPARTSIZE GetThemePartSize = NULL; static PFNGETTHEMEPOSITION GetThemePosition = NULL; static PFNSETWINDOWTHEME SetWindowTheme = NULL; + static PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT IsThemeBackgroundPartiallyTransparent = NULL; BOOL InitThemes() { *************** *** 149,154 **** --- 152,158 ---- "GetThemePartSize"); SetWindowTheme = (PFNSETWINDOWTHEME)GetProcAddress(hModThemes, "SetWindowTheme"); + IsThemeBackgroundPartiallyTransparent = (PFNISTHEMEBACKGROUNDPARTIALLYTRANSPARENT)GetProcAddress(hModThemes, "IsThemeBackgroundPartiallyTransparent"); if(OpenThemeData && DrawThemeBackground *************** *** 164,169 **** --- 168,174 ---- && GetThemePartSize && GetThemePosition && SetWindowTheme + && IsThemeBackgroundPartiallyTransparent ) { DTRACE_PRINTLN("Loaded function pointers.\n"); // We need to make sure we can load the Theme. This may not be *************** *** 422,428 **** // Copy the resulting pixels to our Java BufferedImage. pDstBits = (int *)env->GetPrimitiveArrayCritical(array, 0); BOOL transparent = FALSE; ! GetThemeBool(hTheme, part, state, TMT_TRANSPARENT, &transparent); copyDIBToBufferedImage(pDstBits, pSrcBits, transparent, w, h, stride); env->ReleasePrimitiveArrayCritical(array, pDstBits, 0); } --- 427,433 ---- // Copy the resulting pixels to our Java BufferedImage. pDstBits = (int *)env->GetPrimitiveArrayCritical(array, 0); BOOL transparent = FALSE; ! transparent = IsThemeBackgroundPartiallyTransparent(hTheme, part, state); copyDIBToBufferedImage(pDstBits, pSrcBits, transparent, w, h, stride); env->ReleasePrimitiveArrayCritical(array, pDstBits, 0); }
04-05-2006

EVALUATION The solution is to change our default for transparency from false to true. This is because Windows assumes a default of true but it is up to us to supply it if the property has not been specified in the visual style. We should check the return value of GetThemeBool() and use a default value if the function returns an error (implying that the property was missing or otherwise unavailable). - Josh
03-03-2006

EVALUATION Doing more research. It does indeed appear that the transparency is lost when in the corner of the button image with certain themes. Why, however, is puzzling. In the Royale theme, for example ( http://www.softpedia.com/progDownload/Royale-Theme-for-WinXP--official-Download-13027.html ) All of the button states have transparency but only the disabled one shows the border. They are, in fact, all just offsets into the exact same PNG image. Something different is happening in the disabled state for some reason. If I modify the PNG to have a solid red dot in the corner of each state the red will show up in the buttons, even the disabled one, overriding the black areas. This confirms that it is only transparent sections which have this problem. Printing the bitmap data when it comes back from the paint routine indicates that the transparent pixels are being shoved to 0xFF000000, which is black, not transparent. However, if there is even one pixel of *translucency* in the skin image (meaning partially transparent) then the problem goes away. Thus this shows that the root problem is in the src/windows/native/sun/windows/ThemeReader.cpp where it loads the images. Note that this translucency rule only applies to the section of the source PNG being used for the particular tile in question, not the entire source bitmap. Thus, for the standard Olive theme the enabled version has some translucency in it's area, but the disabled area does not so the black border is apparent, even though they are just different sections of the one source PNG.
02-03-2006

EVALUATION This is a regression caused by fix for 5106661. It looks like the corner transparency is lost when loading the image.
01-11-2005