diff options
author | Martin Karpisek | 2017-09-08 11:17:20 +0000 |
---|---|---|
committer | Niraj Modi | 2017-10-06 10:56:16 +0000 |
commit | 37e6b935a9b182ccc361b7f96a951e9a1c600671 (patch) | |
tree | 0a05a23ae5483962d38f3c65873f7c420f5919e2 | |
parent | 7359cb3bf2545f1dd97950f54bcc25b8badd16e7 (diff) | |
download | eclipse.platform.swt-37e6b935a9b182ccc361b7f96a951e9a1c600671.tar.gz eclipse.platform.swt-37e6b935a9b182ccc361b7f96a951e9a1c600671.tar.xz eclipse.platform.swt-37e6b935a9b182ccc361b7f96a951e9a1c600671.zip |
Bug 443250 - [win32] Support modern native directory dialog
- directory dialog on windows vista and newer will be from now using
more modern 'Common Item Dialog'
-if this vista-style dialog is not available (old windows version) then
basic win32 directory dialog will be used
Change-Id: Ib0f4f02e5909908442c23e0b618b82faf3b7cac8
Signed-off-by: Martin Karpisek <martin.karpisek@gmail.com>
8 files changed, 198 insertions, 5 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c index fab88806c3..3586326c98 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13119,6 +13119,36 @@ fail: } #endif +#ifndef NO_SHCreateItemFromParsingName +JNIEXPORT jint JNICALL OS_NATIVE(SHCreateItemFromParsingName) + (JNIEnv *env, jclass that, jcharArray arg0, jintLong arg1, jbyteArray arg2, jintLongArray arg3) +{ + jchar *lparg0=NULL; + jbyte *lparg2=NULL; + jintLong *lparg3=NULL; + jint rc = 0; + OS_NATIVE_ENTER(env, that, SHCreateItemFromParsingName_FUNC); + if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail; + if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail; + if (arg3) if ((lparg3 = (*env)->GetIntLongArrayElements(env, arg3, NULL)) == NULL) goto fail; +/* + rc = (jint)SHCreateItemFromParsingName(lparg0, arg1, lparg2, lparg3); +*/ + { + OS_LOAD_FUNCTION(fp, SHCreateItemFromParsingName) + if (fp) { + rc = (jint)((jint (CALLING_CONVENTION*)(jchar *, jintLong, jbyte *, jintLong *))fp)(lparg0, arg1, lparg2, lparg3); + } + } +fail: + if (arg3 && lparg3) (*env)->ReleaseIntLongArrayElements(env, arg3, lparg3, 0); + if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, 0); + if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0); + OS_NATIVE_EXIT(env, that, SHCreateItemFromParsingName_FUNC); + return rc; +} +#endif + #ifndef NO_SHCreateItemFromRelativeName JNIEXPORT jint JNICALL OS_NATIVE(SHCreateItemFromRelativeName) (JNIEnv *env, jclass that, jintLong arg0, jcharArray arg1, jintLong arg2, jbyteArray arg3, jintLongArray arg4) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_custom.h index 7c254b6b1c..529bb52995 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_custom.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_custom.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2012 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -93,6 +93,7 @@ #define SetWindowTheme_LIB "uxtheme.dll" #define SHCreateItemFromRelativeName_LIB "shell32.dll" #define SHCreateItemInKnownFolder_LIB "shell32.dll" +#define SHCreateItemFromParsingName_LIB "shell32.dll" #define TransparentBlt_LIB "msimg32.dll" #define UnregisterTouchWindow_LIB "user32.dll" #define UpdateLayeredWindow_LIB "user32.dll" diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c index 64fd8ea1fc..139cc47da5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -1337,6 +1337,7 @@ char * OS_nativeFunctionNames[] = { "SHACTIVATEINFO_1sizeof", "SHBrowseForFolderA", "SHBrowseForFolderW", + "SHCreateItemFromParsingName", "SHCreateItemFromRelativeName", "SHCreateItemInKnownFolder", "SHCreateMenuBar", diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h index 514f9124c8..ed962d9a73 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2017 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -1347,6 +1347,7 @@ typedef enum { SHACTIVATEINFO_1sizeof_FUNC, SHBrowseForFolderA_FUNC, SHBrowseForFolderW_FUNC, + SHCreateItemFromParsingName_FUNC, SHCreateItemFromRelativeName_FUNC, SHCreateItemInKnownFolder_FUNC, SHCreateMenuBar_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/com/win32/FileDialogVtbl.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/com/win32/FileDialogVtbl.java new file mode 100644 index 0000000000..ce28a225d8 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/com/win32/FileDialogVtbl.java @@ -0,0 +1,44 @@ +/*******************************************************************************
+ * Copyright (c) 2017 Martin Karpisek and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Martin Karpisek <martin.karpisek@gmail.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.com.win32;
+
+/**
+ * Function number constants for IFileDialog COM interface
+ */
+public class FileDialogVtbl{
+ public static final int QUERY_INTERFACE = 0;
+ public static final int ADD_REF = 1;
+ public static final int RELEASE = 2;
+ public static final int SHOW = 3;
+ public static final int SET_FILE_TYPES = 4;
+ public static final int SET_FILE_TYPE_INDEX = 5;
+ public static final int GET_FILE_TYPE_INDEX = 6;
+ public static final int ADVISE = 7;
+ public static final int UNADVISE = 8;
+ public static final int SET_OPTIONS = 9;
+ public static final int GET_OPTIONS = 10;
+ public static final int SET_DEFAULT_FOLDER = 11;
+ public static final int SET_FOLDER = 12;
+ public static final int GET_FOLDER = 13;
+ public static final int GET_CURRENT_SELECTION = 14;
+ public static final int SET_FILE_NAME = 15;
+ public static final int GET_FILE_NAME = 16;
+ public static final int SET_TITLE = 17;
+ public static final int SET_OK_BUTTON_LABEL = 18;
+ public static final int SET_FILE_NAME_LABEL = 19;
+ public static final int GET_RESULT = 20;
+ public static final int ADD_PLACE = 21;
+ public static final int SET_DEFAULT_EXTENSION = 22;
+ public static final int CLOSE = 23;
+ public static final int SET_CLIENT_GUID = 24;
+ public static final int CLEAR_CLIENT_DATA = 25;
+ public static final int SET_FILTER = 26;
+}
\ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/com/win32/ShellItemVtbl.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/com/win32/ShellItemVtbl.java new file mode 100644 index 0000000000..14a0d0afe7 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/com/win32/ShellItemVtbl.java @@ -0,0 +1,25 @@ +/*******************************************************************************
+ * Copyright (c) 2017 Martin Karpisek and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Martin Karpisek <martin.karpisek@gmail.com> - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.com.win32;
+
+/**
+ * Function number constants for IShellItem COM interface
+ */
+public class ShellItemVtbl{
+ public static final int QUERY_INTERFACE = 0;
+ public static final int ADD_REF = 1;
+ public static final int RELEASE = 2;
+ public static final int BIND_TO_HANDLER = 3;
+ public static final int GET_PARENT = 4;
+ public static final int GET_DISPLAY_NAME = 5;
+ public static final int GET_ATTRIBUTES = 6;
+ public static final int COMPARE = 7;
+}
\ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java index 4d5b9bddcd..0ce818eb8e 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Martin Karpisek <martin.karpisek@gmail.com> - Bug 443250 *******************************************************************************/ package org.eclipse.swt.internal.win32; @@ -25,6 +26,7 @@ public class OS extends C { public static final boolean IsWin95; public static final boolean IsWinNT; public static final boolean IsWinCE; + public static final boolean IsWinVista; public static final boolean IsPPC; public static final boolean IsHPC; public static final boolean IsSP; @@ -90,6 +92,7 @@ public class OS extends C { WIN32_MINOR = info.dwMinorVersion; WIN32_VERSION = VERSION (WIN32_MAJOR, WIN32_MINOR); IsUnicode = !IsWin32s && !IsWin95; + IsWinVista = OS.WIN32_VERSION >= OS.VERSION (6, 0); /* Load the manifest to force the XP Theme */ if (System.getProperty (NO_MANIFEST) == null) { @@ -703,6 +706,9 @@ public class OS extends C { public static final int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; public static final int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000; public static final int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200; + public static final int FOS_NOCHANGEDIR = 0x8; + public static final int FOS_PICKFOLDERS = 0x20; + public static final int FOS_FORCEFILESYSTEM = 0x40; public static final int FR_PRIVATE = 0x10; public static final int FSHIFT = 0x4; public static final int FVIRTKEY = 0x1; @@ -6863,6 +6869,8 @@ public static final native boolean SHGetPathFromIDListA (long /*int*/ pidl, byte public static final native int SHCreateItemInKnownFolder (byte [] kfid, int dwKFFlags, char [] pszItem, byte [] riid, long /*int*/ [] ppv); /** @method flags=dynamic */ public static final native int SHCreateItemFromRelativeName (long /*int*/ psiParent, char [] pszName, long /*int*/ pbc, byte [] riid, long /*int*/ [] ppv); +/** @method flags=dynamic */ +public static final native int SHCreateItemFromParsingName (char [] pszName, long /*int*/ pbc, byte [] riid, long /*int*/ [] ppv); /** * @param bVk cast=(BYTE) * @param hwnd cast=(HWND) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/DirectoryDialog.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/DirectoryDialog.java index 6c7b65fc82..aa29191360 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/DirectoryDialog.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/DirectoryDialog.java @@ -7,12 +7,14 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Martin Karpisek <martin.karpisek@gmail.com> - Bug 443250 *******************************************************************************/ package org.eclipse.swt.widgets; import org.eclipse.swt.*; import org.eclipse.swt.internal.*; +import org.eclipse.swt.internal.com.win32.*; import org.eclipse.swt.internal.win32.*; /** @@ -34,6 +36,19 @@ import org.eclipse.swt.internal.win32.*; * @noextend This class is not intended to be subclassed by clients. */ public class DirectoryDialog extends Dialog { + static final byte[] CLSID_FileOpenDialog = new byte[16]; + static final byte[] IID_IFileOpenDialog = new byte[16]; + static final byte[] IID_IShellItem = new byte[16]; + static { + if (OS.IsWinVista) { + //Common Item/File Dialog + OS.IIDFromString("{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}\0".toCharArray(), CLSID_FileOpenDialog); //$NON-NLS-1$ + OS.IIDFromString("{d57c7288-d4ad-4768-be02-9d969532d960}\0".toCharArray(), IID_IFileOpenDialog); //$NON-NLS-1$ + OS.IIDFromString("{43826d1e-e718-42ee-bc55-a1e261c37bfe}\0".toCharArray(), IID_IShellItem); //$NON-NLS-1$ + } + } + + String message = "", filterPath = ""; //$NON-NLS-1$//$NON-NLS-2$ String directoryPath; @@ -145,7 +160,14 @@ public String getMessage () { * <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the dialog</li> * </ul> */ -public String open () { +public String open() { + if (OS.IsWinVista) { + return openCommonItemDialog(); + } + return openCommonFileDialog(); +} + +private String openCommonFileDialog () { if (OS.IsWinCE) error (SWT.ERROR_NOT_IMPLEMENTED); long /*int*/ hHeap = OS.GetProcessHeap (); @@ -274,6 +296,67 @@ public String open () { return directoryPath; } +private String openCommonItemDialog() { + this.directoryPath = null; + + long /*int*/ [] ppv = new long /*int*/ [1]; + if (OS.CoCreateInstance(CLSID_FileOpenDialog, 0, OS.CLSCTX_INPROC_SERVER, IID_IFileOpenDialog, ppv) == OS.S_OK) { + long /*int*/ fileDialog = ppv[0]; + + int[] options = new int[1]; + if ((OS.VtblCall(FileDialogVtbl.GET_OPTIONS, fileDialog, options)) == OS.S_OK) { + options[0] |= OS.FOS_PICKFOLDERS | OS.FOS_FORCEFILESYSTEM | OS.FOS_NOCHANGEDIR; + + OS.VtblCall(FileDialogVtbl.SET_OPTIONS, fileDialog, options[0]); + } + + if (title == null) title = ""; + if (title.length() > 0) { + char[] buffer = new char[title.length() + 1]; + title.getChars(0, title.length(), buffer, 0); + OS.VtblCall(FileDialogVtbl.SET_TITLE, fileDialog, buffer); + } + + if (filterPath != null && filterPath.length() > 0) { + String path = filterPath.replace('/', '\\'); + char[] buffer = new char[path.length() + 1]; + path.getChars(0, path.length(), buffer, 0); + if (OS.SHCreateItemFromParsingName(buffer, 0, IID_IShellItem, ppv) == OS.S_OK) { + long /*int*/ psi = ppv[0]; + /* + * SetDefaultDirectory does not work if the dialog has + * persisted recently used folder. The fix is to clear the + * persisted data. + */ + OS.VtblCall(FileDialogVtbl.CLEAR_CLIENT_DATA, fileDialog); + OS.VtblCall(FileDialogVtbl.SET_DEFAULT_FOLDER, fileDialog, psi); + OS.VtblCall(FileDialogVtbl.RELEASE, psi); + } + } + + long /*int*/ hwndOwner = parent.handle; + if (OS.VtblCall(FileDialogVtbl.SHOW, fileDialog, hwndOwner) == OS.S_OK) { + if (OS.VtblCall(FileDialogVtbl.GET_RESULT, fileDialog, ppv) == OS.S_OK) { + long /*int*/ psi = ppv[0]; + if (OS.VtblCall(ShellItemVtbl.GET_DISPLAY_NAME, psi, OS.SIGDN_FILESYSPATH, ppv) == OS.S_OK) { + long /*int*/ wstr = ppv[0]; + int length = OS.wcslen(wstr); + char[] buffer = new char[length]; + OS.MoveMemory(buffer, wstr, length * 2); + OS.CoTaskMemFree(wstr); + + directoryPath = new String(buffer); + } + OS.VtblCall(FileDialogVtbl.RELEASE, psi); + } + } + + OS.VtblCall(FileDialogVtbl.RELEASE, fileDialog); + } + + return directoryPath; +} + /** * Sets the path that the dialog will use to filter * the directories it shows to the argument, which may |