6840086: JFileChooser lacks icons on top right when running on Windows 7
Reviewed-by: peterz, uta
--- a/jdk/src/share/classes/sun/awt/shell/ShellFolderManager.java Thu Sep 17 19:08:15 2009 +0400
+++ b/jdk/src/share/classes/sun/awt/shell/ShellFolderManager.java Fri Sep 18 15:11:28 2009 +0400
@@ -57,8 +57,9 @@
* 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 <code>Image</code> - icon nn from resource 124 in comctl32.dll (Windows only).
+ * "fileChooserIcon <icon>":
+ * Returns an <code>Image</code> - icon can be ListView, DetailsView, UpFolder, NewFolder or
+ * ViewMenu (Windows only).
*
* @return An Object matching the key string.
*/
--- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Thu Sep 17 19:08:15 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Fri Sep 18 15:11:28 2009 +0400
@@ -922,7 +922,7 @@
// 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 @@
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.
--- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Thu Sep 17 19:08:15 2009 +0400
+++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Fri Sep 18 15:11:28 2009 +0400
@@ -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.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 @@
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 @@
private static Win32ShellFolder2 network;
private static Win32ShellFolder2 personal;
- private static final boolean USE_SHELL32_ICONS = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
- public Boolean run() {
- return OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) >= 0;
- }
- });
-
static Win32ShellFolder2 getDesktop() {
if (desktop == null) {
try {
@@ -206,9 +225,9 @@
* 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 <code>Image</code> - icon nn from resource 216 in shell32.dll,
- * or if not found there from resource 124 in comctl32.dll (Windows only).
+ * "fileChooserIcon <icon>":
+ * Returns an <code>Image</code> - icon can be ListView, DetailsView, UpFolder, NewFolder or
+ * ViewMenu (Windows only).
* "optionPaneIcon iconName":
* Returns an <code>Image</code> - icon from the system icon list
*
@@ -303,26 +322,23 @@
}
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;
- }
+ 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;
}
- if (i >= 0) {
- return Win32ShellFolder2.getFileChooserIcon(i);
- }
+
+ return getStandardViewButton(iconIndex);
} else if (key.startsWith("optionPaneIcon ")) {
Win32ShellFolder2.SystemIcon iconType;
if (key == "optionPaneIcon Error") {
--- a/jdk/src/windows/native/sun/windows/ShellFolder2.cpp Thu Sep 17 19:08:15 2009 +0400
+++ b/jdk/src/windows/native/sun/windows/ShellFolder2.cpp Fri Sep 18 15:11:28 2009 +0400
@@ -256,7 +256,6 @@
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 @@
/*
* 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);
+ // Create a toolbar
+ HWND hWndToolbar = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
+ 0, 0, 0, 0, 0,
+ NULL, NULL, NULL, NULL);
+
+ if (hWndToolbar != NULL) {
+ SendMessage(hWndToolbar, TB_LOADIMAGES, (WPARAM)IDB_VIEW_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
- 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);
+ HIMAGELIST hImageList = (HIMAGELIST) SendMessage(hWndToolbar, TB_GETIMAGELIST, 0, 0);
+
+ if (hImageList != NULL) {
+ HICON hIcon = ImageList_GetIcon(hImageList, iconIndex, ILD_TRANSPARENT);
+
+ if (hIcon != NULL) {
+ result = Java_sun_awt_shell_Win32ShellFolder2_getIconBits(env, cls, ptr_to_jlong(hIcon), 16);
+
+ DestroyIcon(hIcon);
+ }
+
+ ImageList_Destroy(hImageList);
}
- }
- 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;
+
+ DestroyWindow(hWndToolbar);
}
- GetObject(hBitmap, sizeof(bm), (LPSTR)&bm);
-
- // Get the screen DC
- HDC dc = GetDC(NULL);
- if (dc == NULL) {
- return NULL;
- }
-
- // 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;
- }
-
- // Release DC
- ReleaseDC(NULL, dc);
-
- // 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;
- }
- }
-
- // 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;
}
/*
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JFileChooser/6840086/bug6840086.java Fri Sep 18 15:11:28 2009 +0400
@@ -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.");
+ }
+}