From 95e12767394f08ff637626db19dcbba5d7a64e39 Mon Sep 17 00:00:00 2001 From: rupashka Date: Fri, 18 Sep 2009 15:11:28 +0400 Subject: [PATCH] 6840086: JFileChooser lacks icons on top right when running on Windows 7 Reviewed-by: peterz, uta --- .../sun/awt/shell/ShellFolderManager.java | 5 +- .../sun/awt/shell/Win32ShellFolder2.java | 30 +----- .../awt/shell/Win32ShellFolderManager2.java | 74 ++++++++------ .../native/sun/windows/ShellFolder2.cpp | 96 +++++-------------- .../JFileChooser/6840086/bug6840086.java | 66 +++++++++++++ 5 files changed, 138 insertions(+), 133 deletions(-) create mode 100644 test/javax/swing/JFileChooser/6840086/bug6840086.java diff --git a/src/share/classes/sun/awt/shell/ShellFolderManager.java b/src/share/classes/sun/awt/shell/ShellFolderManager.java index fe00063ff..ce42bd3a3 100644 --- a/src/share/classes/sun/awt/shell/ShellFolderManager.java +++ b/src/share/classes/sun/awt/shell/ShellFolderManager.java @@ -57,8 +57,9 @@ class ShellFolderManager { * folders, such as Desktop, Documents, History, Network, Home, etc. * This is used in the shortcut panel of the filechooser on Windows 2000 * and Windows Me. - * "fileChooserIcon nn": - * Returns an Image - icon nn from resource 124 in comctl32.dll (Windows only). + * "fileChooserIcon ": + * Returns an Image - icon can be ListView, DetailsView, UpFolder, NewFolder or + * ViewMenu (Windows only). * * @return An Object matching the key string. */ diff --git a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java index c1efb0de5..36636aef6 100644 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -922,7 +922,7 @@ final class Win32ShellFolder2 extends ShellFolder { // Dispose the HICON private static native void disposeIcon(long hIcon); - public static native int[] getFileChooserBitmapBits(); + static native int[] getStandardViewButton0(int iconIndex); // Should be called from the COM thread private long getIShellIcon() { @@ -933,34 +933,6 @@ final class Win32ShellFolder2 extends ShellFolder { return pIShellIcon; } - - static int[] fileChooserBitmapBits = null; - static Image[] fileChooserIcons = new Image[47]; - - static Image getFileChooserIcon(int i) { - if (fileChooserIcons[i] != null) { - return fileChooserIcons[i]; - } else { - if (fileChooserBitmapBits == null) { - fileChooserBitmapBits = getFileChooserBitmapBits(); - } - if (fileChooserBitmapBits != null) { - int nImages = fileChooserBitmapBits.length / (16*16); - int[] bitmapBits = new int[16 * 16]; - for (int y = 0; y < 16; y++) { - for (int x = 0; x < 16; x++) { - bitmapBits[y * 16 + x] = fileChooserBitmapBits[y * (nImages * 16) + (i * 16) + x]; - } - } - BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); - img.setRGB(0, 0, 16, 16, bitmapBits, 0, 16); - fileChooserIcons[i] = img; - } - } - return fileChooserIcons[i]; - } - - private static Image makeIcon(long hIcon, boolean getLargeIcon) { if (hIcon != 0L && hIcon != -1L) { // Get the bits. This has the side effect of setting the imageHash value for this object. diff --git a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index 8b692fa68..97cc532d3 100644 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -25,7 +25,8 @@ package sun.awt.shell; -import java.awt.Toolkit; +import java.awt.*; +import java.awt.image.BufferedImage; import java.io.File; import java.io.FileNotFoundException; @@ -33,6 +34,7 @@ import java.io.IOException; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; +import java.util.List; import java.util.concurrent.*; import sun.security.action.LoadLibraryAction; @@ -98,6 +100,29 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { return parent; } + private static final int VIEW_LIST = 2; + private static final int VIEW_DETAILS = 3; + private static final int VIEW_PARENTFOLDER = 8; + private static final int VIEW_NEWFOLDER = 11; + + private static final Image[] STANDARD_VIEW_BUTTONS = new Image[12]; + + private static Image getStandardViewButton(int iconIndex) { + Image result = STANDARD_VIEW_BUTTONS[iconIndex]; + + if (result != null) { + return result; + } + + BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); + + img.setRGB(0, 0, 16, 16, Win32ShellFolder2.getStandardViewButton0(iconIndex), 0, 16); + + STANDARD_VIEW_BUTTONS[iconIndex] = img; + + return img; + } + // Special folders private static Win32ShellFolder2 desktop; private static Win32ShellFolder2 drives; @@ -105,12 +130,6 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { private static Win32ShellFolder2 network; private static Win32ShellFolder2 personal; - private static final boolean USE_SHELL32_ICONS = AccessController.doPrivileged(new PrivilegedAction() { - public Boolean run() { - return OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) >= 0; - } - }); - static Win32ShellFolder2 getDesktop() { if (desktop == null) { try { @@ -206,9 +225,9 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { * folders, such as Desktop, Documents, History, Network, Home, etc. * This is used in the shortcut panel of the filechooser on Windows 2000 * and Windows Me. - * "fileChooserIcon nn": - * Returns an Image - icon nn from resource 216 in shell32.dll, - * or if not found there from resource 124 in comctl32.dll (Windows only). + * "fileChooserIcon ": + * Returns an Image - icon can be ListView, DetailsView, UpFolder, NewFolder or + * ViewMenu (Windows only). * "optionPaneIcon iconName": * Returns an Image - icon from the system icon list * @@ -303,26 +322,23 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { } return folders.toArray(new File[folders.size()]); } else if (key.startsWith("fileChooserIcon ")) { - int i = -1; - String name = key.substring(key.indexOf(" ")+1); - try { - i = Integer.parseInt(name); - } catch (NumberFormatException ex) { - if (name.equals("ListView")) { - i = (USE_SHELL32_ICONS) ? 21 : 2; - } else if (name.equals("DetailsView")) { - i = (USE_SHELL32_ICONS) ? 23 : 3; - } else if (name.equals("UpFolder")) { - i = (USE_SHELL32_ICONS) ? 28 : 8; - } else if (name.equals("NewFolder")) { - i = (USE_SHELL32_ICONS) ? 31 : 11; - } else if (name.equals("ViewMenu")) { - i = (USE_SHELL32_ICONS) ? 21 : 2; - } - } - if (i >= 0) { - return Win32ShellFolder2.getFileChooserIcon(i); + String name = key.substring(key.indexOf(" ") + 1); + + int iconIndex; + + if (name.equals("ListView") || name.equals("ViewMenu")) { + iconIndex = VIEW_LIST; + } else if (name.equals("DetailsView")) { + iconIndex = VIEW_DETAILS; + } else if (name.equals("UpFolder")) { + iconIndex = VIEW_PARENTFOLDER; + } else if (name.equals("NewFolder")) { + iconIndex = VIEW_NEWFOLDER; + } else { + return null; } + + return getStandardViewButton(iconIndex); } else if (key.startsWith("optionPaneIcon ")) { Win32ShellFolder2.SystemIcon iconType; if (key == "optionPaneIcon Error") { diff --git a/src/windows/native/sun/windows/ShellFolder2.cpp b/src/windows/native/sun/windows/ShellFolder2.cpp index 64eea69bc..353e47cff 100644 --- a/src/windows/native/sun/windows/ShellFolder2.cpp +++ b/src/windows/native/sun/windows/ShellFolder2.cpp @@ -256,7 +256,6 @@ JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_uninitializeC static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) { // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp HRESULT hres; - HICON hIcon = NULL; IShellIcon* pIShellIcon; if (pIShellFolder != NULL) { hres = pIShellFolder->QueryInterface(IID_IShellIcon, (void**)&pIShellIcon); @@ -965,89 +964,40 @@ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits /* * Class: sun_awt_shell_Win32ShellFolder2 - * Method: getFileChooserBitmapBits - * Signature: ()[I + * Method: getStandardViewButton0 + * Signature: (I)[I */ -JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileChooserBitmapBits - (JNIEnv* env, jclass cls) +JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getStandardViewButton0 + (JNIEnv* env, jclass cls, jint iconIndex) { - HBITMAP hBitmap = NULL; - BITMAP bm; - HINSTANCE libComCtl32; - HINSTANCE libShell32; + jintArray result = NULL; - libShell32 = LoadLibrary(TEXT("shell32.dll")); - if (libShell32 != NULL) { - hBitmap = (HBITMAP)LoadImage(libShell32, - IS_WINVISTA ? TEXT("IDB_TB_SH_DEF_16") : MAKEINTRESOURCE(216), - IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); - - if (hBitmap == NULL) { - // version of shell32.dll doesn't match OS version. - // So we either are in a Vista Compatibility Mode - // or shell32.dll was copied from OS of another version - hBitmap = (HBITMAP)LoadImage(libShell32, - IS_WINVISTA ? MAKEINTRESOURCE(216) : TEXT("IDB_TB_SH_DEF_16"), - IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); - } - } - if (hBitmap == NULL) { - libComCtl32 = LoadLibrary(TEXT("comctl32.dll")); - if (libComCtl32 != NULL) { - hBitmap = (HBITMAP)LoadImage(libComCtl32, MAKEINTRESOURCE(124), - IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); - } - } - if (hBitmap == NULL) { - return NULL; - } + // Create a toolbar + HWND hWndToolbar = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, + 0, 0, 0, 0, 0, + NULL, NULL, NULL, NULL); - GetObject(hBitmap, sizeof(bm), (LPSTR)&bm); + if (hWndToolbar != NULL) { + SendMessage(hWndToolbar, TB_LOADIMAGES, (WPARAM)IDB_VIEW_SMALL_COLOR, (LPARAM)HINST_COMMCTRL); - // Get the screen DC - HDC dc = GetDC(NULL); - if (dc == NULL) { - return NULL; - } + HIMAGELIST hImageList = (HIMAGELIST) SendMessage(hWndToolbar, TB_GETIMAGELIST, 0, 0); - // Set up BITMAPINFO - BITMAPINFO bmi; - memset(&bmi, 0, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = bm.bmWidth; - bmi.bmiHeader.biHeight = -bm.bmHeight; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - // Extract the color bitmap - int numPixels = bm.bmWidth * bm.bmHeight; - //long colorBits[192 * 16]; - long *colorBits = (long*)safe_Malloc(numPixels * sizeof(long)); - if (GetDIBits(dc, hBitmap, 0, bm.bmHeight, colorBits, &bmi, DIB_RGB_COLORS) == 0) { - return NULL; - } + if (hImageList != NULL) { + HICON hIcon = ImageList_GetIcon(hImageList, iconIndex, ILD_TRANSPARENT); - // Release DC - ReleaseDC(NULL, dc); + if (hIcon != NULL) { + result = Java_sun_awt_shell_Win32ShellFolder2_getIconBits(env, cls, ptr_to_jlong(hIcon), 16); - // The color of the first pixel defines the transparency, according - // to the documentation for LR_LOADTRANSPARENT at - // http://msdn.microsoft.com/library/psdk/winui/resource_9fhi.htm - long transparent = colorBits[0]; - for (int i=0; i < numPixels; i++) { - if (colorBits[i] != transparent) { - colorBits[i] |= 0xff000000; + DestroyIcon(hIcon); + } + + ImageList_Destroy(hImageList); } + + DestroyWindow(hWndToolbar); } - // Create java array - jintArray bits = env->NewIntArray(numPixels); - // Copy values to java array - env->SetIntArrayRegion(bits, 0, numPixels, colorBits); - // Fix 4745575 GDI Resource Leak - ::DeleteObject(hBitmap); - ::FreeLibrary(libComCtl32); - return bits; + return result; } /* diff --git a/test/javax/swing/JFileChooser/6840086/bug6840086.java b/test/javax/swing/JFileChooser/6840086/bug6840086.java new file mode 100644 index 000000000..bdd012f4c --- /dev/null +++ b/test/javax/swing/JFileChooser/6840086/bug6840086.java @@ -0,0 +1,66 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + @bug 6840086 + @summary JFileChooser lacks icons on top right when running on Windows 7 + @author Pavel Porvatov + @run main bug6840086 +*/ + +import sun.awt.OSInfo; +import sun.awt.shell.ShellFolder; + +import java.awt.*; + +public class bug6840086 { + private static final String[] KEYS = { + "fileChooserIcon ListView", + "fileChooserIcon ViewMenu", + "fileChooserIcon DetailsView", + "fileChooserIcon UpFolder", + "fileChooserIcon NewFolder", + }; + + public static void main(String[] args) { + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) { + System.out.println("The test was skipped because it is sensible only for Windows."); + + return; + } + + for (String key : KEYS) { + Image image = (Image) ShellFolder.get(key); + + if (image == null) { + throw new RuntimeException("The image '" + key + "' not found."); + } + + if (image != ShellFolder.get(key)) { + throw new RuntimeException("The image '" + key + "' is not cached."); + } + } + + System.out.println("The test passed."); + } +} -- GitLab