Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Pazderski2019-06-24 14:45:51 +0000
committerPaul Pazderski2019-06-30 07:19:05 +0000
commitc1dbf469eda9d72bf46f698d1fc4b676aecb5559 (patch)
tree136bfe6d69bceae4c61c192e5bf23dfb05ebecea
parent0f3e134c4c34e816c8b0fd1862574fcce3a9b9f1 (diff)
downloadeclipse.platform.swt-c1dbf469eda9d72bf46f698d1fc4b676aecb5559.tar.gz
eclipse.platform.swt-c1dbf469eda9d72bf46f698d1fc4b676aecb5559.tar.xz
eclipse.platform.swt-c1dbf469eda9d72bf46f698d1fc4b676aecb5559.zip
Bug 547634 - [win32] Add CFSTR_SHELLIDLIST transfer type to FileTransfer
to support drop on taskbar CFSTR_SHELLIDLIST transfer type is only added as drag source not as drop target. Like the existing CF_HDROP transfer type implementation the new transfer type allow dragging non existing file paths. Change-Id: I02c4f64081ec2b55073e1878f99b8e52eeabdd01 Signed-off-by: Paul Pazderski <paul-eclipse@ppazderski.de>
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/FileTransfer.java127
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/ImageTransfer.java4
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com.c19
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.c19
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.cpp108
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.h11
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.c1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.h1
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c51
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.c4
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h4
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.c34
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.h14
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/ole/win32/COM.java6
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/CIDA.java25
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java17
-rw-r--r--tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/AllWin32Tests.java5
-rw-r--r--tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/SwtWin32TestUtil.java44
-rw-r--r--tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/Test_org_eclipse_swt_dnd_DND.java276
19 files changed, 720 insertions, 50 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/FileTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/FileTransfer.java
index 7f6ecfcf6f..2b94832fcf 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/FileTransfer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/FileTransfer.java
@@ -27,8 +27,8 @@ import org.eclipse.swt.internal.win32.*;
* below:</p>
*
* <pre><code>
- * File file1 = new File("C:\temp\file1");
- * File file2 = new File("C:\temp\file2");
+ * File file1 = new File("C:\\temp\\file1");
+ * File file2 = new File("C:\\temp\\file2");
* String[] fileData = new String[2];
* fileData[0] = file1.getAbsolutePath();
* fileData[1] = file2.getAbsolutePath();
@@ -39,8 +39,10 @@ import org.eclipse.swt.internal.win32.*;
public class FileTransfer extends ByteArrayTransfer {
private static FileTransfer _instance = new FileTransfer();
- private static final String CF_HDROP = "CF_HDROP "; //$NON-NLS-1$
+ private static final String CF_HDROP = "CF_HDROP"; //$NON-NLS-1$
private static final int CF_HDROPID = COM.CF_HDROP;
+ private static final String CFSTR_SHELLIDLIST = "Shell IDList Array"; //$NON-NLS-1$
+ private static final int CFSTR_SHELLIDLISTID = registerType(CFSTR_SHELLIDLIST);
private FileTransfer() {}
@@ -71,30 +73,37 @@ public void javaToNative(Object object, TransferData transferData) {
DND.error(DND.ERROR_INVALID_DATA);
}
String[] fileNames = (String[]) object;
- StringBuffer allFiles = new StringBuffer();
- for (int i = 0; i < fileNames.length; i++) {
- allFiles.append(fileNames[i]);
- allFiles.append('\0'); // each name is null terminated
+ long newPtr = 0;
+ if (transferData.type == CF_HDROPID) {
+ StringBuffer allFiles = new StringBuffer();
+ for (int i = 0; i < fileNames.length; i++) {
+ allFiles.append(fileNames[i]);
+ allFiles.append('\0'); // each name is null terminated
+ }
+ allFiles.append('\0'); // there is an extra null terminator at the very end
+ char [] buffer = new char [allFiles.length()];
+ allFiles.getChars(0, allFiles.length(), buffer, 0);
+ DROPFILES dropfiles = new DROPFILES();
+ dropfiles.pFiles = DROPFILES.sizeof;
+ dropfiles.pt_x = dropfiles.pt_y = 0;
+ dropfiles.fNC = 0;
+ dropfiles.fWide = 1;
+ // Allocate the memory because the caller (DropTarget) has not handed it in
+ // The caller of this method must release the data when it is done with it.
+ int byteCount = buffer.length * TCHAR.sizeof;
+ newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, DROPFILES.sizeof + byteCount);
+ if (newPtr != 0) {
+ OS.MoveMemory(newPtr, dropfiles, DROPFILES.sizeof);
+ OS.MoveMemory(newPtr + DROPFILES.sizeof, buffer, byteCount);
+ }
+ } else if (transferData.type == CFSTR_SHELLIDLISTID) {
+ newPtr = generateCidaFromFilepaths(fileNames);
}
- allFiles.append('\0'); // there is an extra null terminator at the very end
- char [] buffer = new char [allFiles.length()];
- allFiles.getChars(0, allFiles.length(), buffer, 0);
- DROPFILES dropfiles = new DROPFILES();
- dropfiles.pFiles = DROPFILES.sizeof;
- dropfiles.pt_x = dropfiles.pt_y = 0;
- dropfiles.fNC = 0;
- dropfiles.fWide = 1;
- // Allocate the memory because the caller (DropTarget) has not handed it in
- // The caller of this method must release the data when it is done with it.
- int byteCount = buffer.length * TCHAR.sizeof;
- long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, DROPFILES.sizeof + byteCount);
- OS.MoveMemory(newPtr, dropfiles, DROPFILES.sizeof);
- OS.MoveMemory(newPtr + DROPFILES.sizeof, buffer, byteCount);
transferData.stgmedium = new STGMEDIUM();
transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
transferData.stgmedium.unionField = newPtr;
transferData.stgmedium.pUnkForRelease = 0;
- transferData.result = COM.S_OK;
+ transferData.result = newPtr != 0 ? COM.S_OK : COM.E_FAIL;
}
/**
@@ -141,14 +150,84 @@ public Object nativeToJava(TransferData transferData) {
return fileNames;
}
+/**
+ * Generate {@link CIDA} structure and trailing data to transfer filenames
+ * as {@link #CFSTR_SHELLIDLIST}.
+ * <p>
+ * For more information on the {@link CIDA} structure see also {@link #resolveCidaToFilepaths(long)}.
+ * </p>
+ *
+ * @param fileNames filenames to pack in {@link CIDA}.
+ * @return pointer to global memory chunk filled with generated data or <code>0</code> on failure
+ */
+private long generateCidaFromFilepaths(String[] fileNames) {
+ final int n = fileNames.length;
+ long [] pidls = new long [n];
+ try {
+ CIDA cida = new CIDA();
+ cida.cidl = n;
+ int cidaSize = CIDA.sizeof + 4 * n;
+ cida.aoffset = cidaSize; // offsets are from cida begin so the first is equal to cida size
+
+ int[] pidlOffsets = new int[n];
+ int[] pidlSizes = new int[n];
+ int pidlSizeSum = 2; // initialize with 2 for the empty (but double null terminated) parent pidl
+ for (int i = 0; i < n; i++) {
+ TCHAR szfileName = new TCHAR(0, fileNames[i], true);
+ long [] ppv = new long [1];
+ int hr = COM.PathToPIDL(szfileName.chars, ppv);
+ if (hr != OS.S_OK) {
+ return 0;
+ }
+ pidls[i] = ppv[0];
+ pidlSizes[i] = OS.ILGetSize(pidls[i]);
+ pidlSizeSum += pidlSizes[i];
+
+ if (i == 0) {
+ pidlOffsets[0] = cidaSize + 2;
+ }
+ else {
+ pidlOffsets[i] = pidlOffsets[i - 1] + pidlSizes[i - 1];
+ }
+ }
+
+ long newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, cidaSize + pidlSizeSum);
+ if (newPtr != 0) {
+ OS.MoveMemory(newPtr, cida, CIDA.sizeof);
+ OS.MoveMemory(newPtr + CIDA.sizeof, pidlOffsets, 4 * cida.cidl);
+ for (int i = 0; i < n; i++) {
+ OS.MoveMemory(newPtr + pidlOffsets[i], pidls[i], pidlSizes[i]);
+ }
+ }
+ return newPtr;
+ } finally {
+ for (int i = 0; i < n; i++) {
+ if (pidls[i] != 0) {
+ OS.CoTaskMemFree(pidls[i]);
+ }
+ }
+ }
+}
+
+@Override
+public boolean isSupportedType(TransferData transferData) {
+ // filter Shell ID List Array transfer only for dropping
+ if (transferData != null && transferData.pIDataObject != 0 && transferData.type == CFSTR_SHELLIDLISTID) {
+ return false;
+ }
+ return super.isSupportedType(transferData);
+}
+
@Override
protected int[] getTypeIds(){
- return new int[] {CF_HDROPID};
+ // Note: FileTransfer adds Shell ID List as transfer type but later
+ // limit this type for dragging only.
+ return new int[] {CF_HDROPID, CFSTR_SHELLIDLISTID};
}
@Override
protected String[] getTypeNames(){
- return new String[] {CF_HDROP};
+ return new String[] {CF_HDROP, CFSTR_SHELLIDLIST};
}
boolean checkFile(Object object) {
if (object == null || !(object instanceof String[]) || ((String[])object).length == 0) return false;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/ImageTransfer.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/ImageTransfer.java
index f5e21ec2a6..0c678f16c3 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/ImageTransfer.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/ImageTransfer.java
@@ -27,8 +27,8 @@ import org.eclipse.swt.internal.win32.*;
* <p>An example of a java <code>ImageData</code> is shown below:</p>
*
* <pre><code>
- * Image image = new Image(display, "C:\temp\img1.gif");
- * ImageData imgData = image.getImageData();
+ * Image image = new Image(display, "C:\\temp\\img1.gif");
+ * ImageData imgData = image.getImageData();
* </code></pre>
*
* @see Transfer
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com.c
index 11d2eff2fc..d663eca6e7 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com.c
@@ -894,6 +894,25 @@ fail:
}
#endif
+#ifndef NO_PathToPIDL
+JNIEXPORT jint JNICALL COM_NATIVE(PathToPIDL)
+ (JNIEnv *env, jclass that, jcharArray arg0, jlongArray arg1)
+{
+ jchar *lparg0=NULL;
+ jlong *lparg1=NULL;
+ jint rc = 0;
+ COM_NATIVE_ENTER(env, that, PathToPIDL_FUNC);
+ if (arg0) if ((lparg0 = (*env)->GetCharArrayElements(env, arg0, NULL)) == NULL) goto fail;
+ if (arg1) if ((lparg1 = (*env)->GetLongArrayElements(env, arg1, NULL)) == NULL) goto fail;
+ rc = (jint)PathToPIDL((PCWSTR)lparg0, (PIDLIST_ABSOLUTE)lparg1);
+fail:
+ if (arg1 && lparg1) (*env)->ReleaseLongArrayElements(env, arg1, lparg1, 0);
+ if (arg0 && lparg0) (*env)->ReleaseCharArrayElements(env, arg0, lparg0, 0);
+ COM_NATIVE_EXIT(env, that, PathToPIDL_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO_ProgIDFromCLSID
JNIEXPORT jint JNICALL COM_NATIVE(ProgIDFromCLSID)
(JNIEnv *env, jclass that, jobject arg0, jlongArray arg1)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.c
deleted file mode 100644
index 590330a0fb..0000000000
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.c
+++ /dev/null
@@ -1,19 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
- *
- * This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License 2.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-
-#include "swt.h"
-#include "com_structs.h"
-#include "com_stats.h"
-
-#define COM_NATIVE(func) Java_org_eclipse_swt_internal_ole_win32_COM_##func
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.cpp b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.cpp
new file mode 100644
index 0000000000..e4509e4c94
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.cpp
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Paul Pazderski - Bug 547634: PathToPIDL
+ *******************************************************************************/
+
+#include "swt.h"
+#include "com_structs.h"
+#include "com_stats.h"
+#include <Shlobj.h>
+
+#define COM_NATIVE(func) Java_org_eclipse_swt_internal_ole_win32_COM_##func
+
+class CFileSysBindData : public IFileSystemBindData
+{
+public:
+ CFileSysBindData() : refCount(1)
+ {
+ ZeroMemory(&findData, sizeof(findData));
+ }
+
+ IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv)
+ {
+ *ppv = nullptr;
+ HRESULT hr = E_NOINTERFACE;
+ if (riid == IID_IUnknown || riid == IID_IFileSystemBindData) {
+ *ppv = static_cast<IFileSystemBindData*>(this);
+ AddRef();
+ hr = S_OK;
+ }
+ return hr;
+ }
+
+ IFACEMETHODIMP_(ULONG) AddRef()
+ {
+ return InterlockedIncrement(&refCount);
+ }
+
+ IFACEMETHODIMP_(ULONG) Release()
+ {
+ long rc = InterlockedDecrement(&refCount);
+ if (!rc)
+ delete this;
+ return rc;
+ }
+
+ IFACEMETHODIMP SetFindData(const WIN32_FIND_DATAW *pfd)
+ {
+ findData = *pfd;
+ return S_OK;
+ }
+
+ IFACEMETHODIMP GetFindData(WIN32_FIND_DATAW *pfd)
+ {
+ *pfd = findData;
+ return S_OK;
+ }
+
+private:
+ long refCount;
+ WIN32_FIND_DATAW findData;
+};
+
+/*
+ * An extended version of SHParseDisplayName which ignores the attribute query part
+ * and use bind context to support creation of simple PIDLs for non existing paths.
+ */
+extern "C" HRESULT PathToPIDL(PCWSTR pszName, PIDLIST_ABSOLUTE *ppidl)
+{
+ if (!ppidl) return E_FAIL;
+ *ppidl = nullptr;
+
+ IFileSystemBindData *pfsbd = new CFileSysBindData();
+ if (!pfsbd) return E_OUTOFMEMORY;
+
+ WIN32_FIND_DATAW data = {};
+ pfsbd->SetFindData(&data);
+
+ IBindCtx* pbc;
+
+ HRESULT hr = CreateBindCtx(0, &pbc);
+ if (hr == S_OK)
+ {
+ BIND_OPTS bo = { sizeof(bo), 0, STGM_CREATE, 0 };
+ hr = pbc->SetBindOptions(&bo);
+ if (hr == S_OK)
+ {
+ hr = pbc->RegisterObjectParam(STR_FILE_SYS_BIND_DATA, pfsbd);
+ if (hr == S_OK)
+ {
+ SFGAOF sfgao = 0;
+ hr = SHParseDisplayName(pszName, pbc, ppidl, sfgao, &sfgao);
+ }
+ }
+ pbc->Release();
+ }
+ pfsbd->Release();
+ return hr;
+}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.h b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.h
index d7bbd072b4..eff05db8cc 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -21,3 +21,12 @@
#define AccessibleObjectFromWindow_LIB "oleacc.dll"
#define CreateStdAccessibleObject_LIB "oleacc.dll"
#define LresultFromObject_LIB "oleacc.dll"
+
+/* Custom functions */
+#ifdef __cplusplus
+extern "C" {
+#endif
+HRESULT PathToPIDL(_In_ PCWSTR pszName, _Outptr_ PIDLIST_ABSOLUTE *ppidl);
+#ifdef __cplusplus
+}
+#endif
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.c
index 407a2b5da8..492c6b530e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.c
@@ -78,6 +78,7 @@ char * COM_nativeFunctionNames[] = {
"OleSetContainedObject",
"OleSetMenuDescriptor",
"OleTranslateColor",
+ "PathToPIDL",
"ProgIDFromCLSID",
"RegisterDragDrop",
"ReleaseStgMedium",
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.h
index 8f6070dd67..b25d4f9f20 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_stats.h
@@ -88,6 +88,7 @@ typedef enum {
OleSetContainedObject_FUNC,
OleSetMenuDescriptor_FUNC,
OleTranslateColor_FUNC,
+ PathToPIDL_FUNC,
ProgIDFromCLSID_FUNC,
RegisterDragDrop_FUNC,
ReleaseStgMedium_FUNC,
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 416a2eee99..7ff02ec395 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
@@ -450,6 +450,18 @@ JNIEXPORT jint JNICALL OS_NATIVE(CHOOSEFONT_1sizeof)
}
#endif
+#ifndef NO_CIDA_1sizeof
+JNIEXPORT jint JNICALL OS_NATIVE(CIDA_1sizeof)
+ (JNIEnv *env, jclass that)
+{
+ jint rc = 0;
+ OS_NATIVE_ENTER(env, that, CIDA_1sizeof_FUNC);
+ rc = (jint)CIDA_sizeof();
+ OS_NATIVE_EXIT(env, that, CIDA_1sizeof_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO_COMBOBOXINFO_1sizeof
JNIEXPORT jint JNICALL OS_NATIVE(COMBOBOXINFO_1sizeof)
(JNIEnv *env, jclass that)
@@ -4106,6 +4118,18 @@ fail:
}
#endif
+#ifndef NO_ILGetSize
+JNIEXPORT jint JNICALL OS_NATIVE(ILGetSize)
+ (JNIEnv *env, jclass that, jlong arg0)
+{
+ jint rc = 0;
+ OS_NATIVE_ENTER(env, that, ILGetSize_FUNC);
+ rc = (jint)ILGetSize((PCIDLIST_ABSOLUTE)arg0);
+ OS_NATIVE_EXIT(env, that, ILGetSize_FUNC);
+ return rc;
+}
+#endif
+
#ifndef NO_INITCOMMONCONTROLSEX_1sizeof
JNIEXPORT jint JNICALL OS_NATIVE(INITCOMMONCONTROLSEX_1sizeof)
(JNIEnv *env, jclass that)
@@ -5392,6 +5416,19 @@ JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JJI)
}
#endif
+#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I)
+ (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
+{
+ CIDA _arg1, *lparg1=NULL;
+ OS_NATIVE_ENTER(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I_FUNC);
+ if (arg1) if ((lparg1 = getCIDAFields(env, arg1, &_arg1)) == NULL) goto fail;
+ MoveMemory((PVOID)arg0, (CONST VOID *)lparg1, arg2);
+fail:
+ OS_NATIVE_EXIT(env, that, MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I_FUNC);
+}
+#endif
+
#ifndef NO_MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I
JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I)
(JNIEnv *env, jclass that, jlong arg0, jobject arg1, jint arg2)
@@ -5862,6 +5899,20 @@ fail:
}
#endif
+#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI
+JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI)
+ (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
+{
+ CIDA _arg0, *lparg0=NULL;
+ OS_NATIVE_ENTER(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI_FUNC);
+ if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail;
+ MoveMemory((PVOID)lparg0, (CONST VOID *)arg1, arg2);
+fail:
+ if (arg0 && lparg0) setCIDAFields(env, arg0, lparg0);
+ OS_NATIVE_EXIT(env, that, MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI_FUNC);
+}
+#endif
+
#ifndef NO_MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI
JNIEXPORT void JNICALL OS_NATIVE(MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI)
(JNIEnv *env, jclass that, jobject arg0, jlong arg1, jint arg2)
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 19895a44cc..fb697d329a 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
@@ -53,6 +53,7 @@ char * OS_nativeFunctionNames[] = {
"CERT_1PUBLIC_1KEY_1INFO_1sizeof",
"CHOOSECOLOR_1sizeof",
"CHOOSEFONT_1sizeof",
+ "CIDA_1sizeof",
"COMBOBOXINFO_1sizeof",
"COMPOSITIONFORM_1sizeof",
"CREATESTRUCT_1sizeof",
@@ -313,6 +314,7 @@ char * OS_nativeFunctionNames[] = {
"HideCaret",
"ICONINFO_1sizeof",
"IIDFromString",
+ "ILGetSize",
"INITCOMMONCONTROLSEX_1sizeof",
"INPUT_1sizeof",
"ImageList_1Add",
@@ -410,6 +412,7 @@ char * OS_nativeFunctionNames[] = {
"ModifyWorldTransform",
"MonitorFromWindow",
"MoveMemory__JJI",
+ "MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I",
"MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I",
"MoveMemory__JLorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2I",
"MoveMemory__JLorg_eclipse_swt_internal_win32_DROPFILES_2I",
@@ -445,6 +448,7 @@ char * OS_nativeFunctionNames[] = {
"MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2_3BI",
"MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1CONTEXT_2JI",
"MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1INFO_2JI",
+ "MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI",
"MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI",
"MoveMemory__Lorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2JI",
"MoveMemory__Lorg_eclipse_swt_internal_win32_DRAWITEMSTRUCT_2JI",
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 ab3155cf1a..0508568c46 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
@@ -63,6 +63,7 @@ typedef enum {
CERT_1PUBLIC_1KEY_1INFO_1sizeof_FUNC,
CHOOSECOLOR_1sizeof_FUNC,
CHOOSEFONT_1sizeof_FUNC,
+ CIDA_1sizeof_FUNC,
COMBOBOXINFO_1sizeof_FUNC,
COMPOSITIONFORM_1sizeof_FUNC,
CREATESTRUCT_1sizeof_FUNC,
@@ -323,6 +324,7 @@ typedef enum {
HideCaret_FUNC,
ICONINFO_1sizeof_FUNC,
IIDFromString_FUNC,
+ ILGetSize_FUNC,
INITCOMMONCONTROLSEX_1sizeof_FUNC,
INPUT_1sizeof_FUNC,
ImageList_1Add_FUNC,
@@ -420,6 +422,7 @@ typedef enum {
ModifyWorldTransform_FUNC,
MonitorFromWindow_FUNC,
MoveMemory__JJI_FUNC,
+ MoveMemory__JLorg_eclipse_swt_internal_win32_CIDA_2I_FUNC,
MoveMemory__JLorg_eclipse_swt_internal_win32_DEVMODE_2I_FUNC,
MoveMemory__JLorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2I_FUNC,
MoveMemory__JLorg_eclipse_swt_internal_win32_DROPFILES_2I_FUNC,
@@ -455,6 +458,7 @@ typedef enum {
MoveMemory__Lorg_eclipse_swt_internal_win32_BITMAPINFOHEADER_2_3BI_FUNC,
MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1CONTEXT_2JI_FUNC,
MoveMemory__Lorg_eclipse_swt_internal_win32_CERT_1INFO_2JI_FUNC,
+ MoveMemory__Lorg_eclipse_swt_internal_win32_CIDA_2JI_FUNC,
MoveMemory__Lorg_eclipse_swt_internal_win32_DEVMODE_2JI_FUNC,
MoveMemory__Lorg_eclipse_swt_internal_win32_DOCHOSTUIINFO_2JI_FUNC,
MoveMemory__Lorg_eclipse_swt_internal_win32_DRAWITEMSTRUCT_2JI_FUNC,
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.c
index 0e58a96622..4a8266ed5e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.c
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.c
@@ -819,6 +819,40 @@ void setCHOOSEFONTFields(JNIEnv *env, jobject lpObject, CHOOSEFONT *lpStruct)
}
#endif
+#ifndef NO_CIDA
+typedef struct CIDA_FID_CACHE {
+ int cached;
+ jclass clazz;
+ jfieldID cidl, aoffset;
+} CIDA_FID_CACHE;
+
+CIDA_FID_CACHE CIDAFc;
+
+void cacheCIDAFields(JNIEnv *env, jobject lpObject)
+{
+ if (CIDAFc.cached) return;
+ CIDAFc.clazz = (*env)->GetObjectClass(env, lpObject);
+ CIDAFc.cidl = (*env)->GetFieldID(env, CIDAFc.clazz, "cidl", "I");
+ CIDAFc.aoffset = (*env)->GetFieldID(env, CIDAFc.clazz, "aoffset", "I");
+ CIDAFc.cached = 1;
+}
+
+CIDA *getCIDAFields(JNIEnv *env, jobject lpObject, CIDA *lpStruct)
+{
+ if (!CIDAFc.cached) cacheCIDAFields(env, lpObject);
+ lpStruct->cidl = (*env)->GetIntField(env, lpObject, CIDAFc.cidl);
+ lpStruct->aoffset[0] = (*env)->GetIntField(env, lpObject, CIDAFc.aoffset);
+ return lpStruct;
+}
+
+void setCIDAFields(JNIEnv *env, jobject lpObject, CIDA *lpStruct)
+{
+ if (!CIDAFc.cached) cacheCIDAFields(env, lpObject);
+ (*env)->SetIntField(env, lpObject, CIDAFc.cidl, (jint)lpStruct->cidl);
+ (*env)->SetIntField(env, lpObject, CIDAFc.aoffset, (jint)lpStruct->aoffset[0]);
+}
+#endif
+
#ifndef NO_COMBOBOXINFO
typedef struct COMBOBOXINFO_FID_CACHE {
int cached;
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.h b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.h
index c704b10f8c..6182b6c01b 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.h
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_structs.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -197,6 +197,18 @@ void setCHOOSEFONTFields(JNIEnv *env, jobject lpObject, CHOOSEFONT *lpStruct);
#define CHOOSEFONT_sizeof() 0
#endif
+#ifndef NO_CIDA
+void cacheCIDAFields(JNIEnv *env, jobject lpObject);
+CIDA *getCIDAFields(JNIEnv *env, jobject lpObject, CIDA *lpStruct);
+void setCIDAFields(JNIEnv *env, jobject lpObject, CIDA *lpStruct);
+#define CIDA_sizeof() sizeof(CIDA)
+#else
+#define cacheCIDAFields(a,b)
+#define getCIDAFields(a,b,c) NULL
+#define setCIDAFields(a,b,c)
+#define CIDA_sizeof() 0
+#endif
+
#ifndef NO_COMBOBOXINFO
void cacheCOMBOBOXINFOFields(JNIEnv *env, jobject lpObject);
COMBOBOXINFO *getCOMBOBOXINFOFields(JNIEnv *env, jobject lpObject, COMBOBOXINFO *lpStruct);
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/ole/win32/COM.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/ole/win32/COM.java
index db75d0c91d..11da510822 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/ole/win32/COM.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/ole/win32/COM.java
@@ -633,6 +633,12 @@ public static final native int OleSetMenuDescriptor(long holemenu, long hwndFram
* @param pcolorref cast=(COLORREF *)
*/
public static final native int OleTranslateColor(int clr, long hpal, int[] pcolorref);
+/**
+ * Custom native function.
+ * @param pszName cast=(PCWSTR)
+ * @param ppidl cast=(PIDLIST_ABSOLUTE)
+ */
+public static final native int PathToPIDL (char [] pszName, long [] ppidl);
/** @param lplpszProgID cast=(LPOLESTR *) */
public static final native int ProgIDFromCLSID(GUID clsid, long[] lplpszProgID);
/**
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/CIDA.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/CIDA.java
new file mode 100644
index 0000000000..ad0085386f
--- /dev/null
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/CIDA.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Paul Pazderski and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Paul Pazderski - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.internal.win32;
+
+/**
+ * @see <a href="https://docs.microsoft.com/en-us/windows/desktop/api/shlobj_core/ns-shlobj_core-_ida">WinAPI documentation: CIDA</a>
+ */
+public class CIDA {
+ public int cidl;
+ /** @field accessor=aoffset[0] */
+ public int aoffset;
+ // minimum size since the actual size depends on the number of offsets
+ public static final int sizeof = OS.CIDA_sizeof ();
+}
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 739dc438f4..2ba2550243 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -2021,6 +2021,7 @@ public static final native int HDHITTESTINFO_sizeof ();
public static final native int HELPINFO_sizeof ();
public static final native int HIGHCONTRAST_sizeof ();
public static final native int ICONINFO_sizeof ();
+public static final native int CIDA_sizeof ();
public static final native int INITCOMMONCONTROLSEX_sizeof ();
public static final native int INPUT_sizeof ();
public static final native int KEYBDINPUT_sizeof ();
@@ -3108,6 +3109,10 @@ public static final native boolean HideCaret (long hWnd);
*/
public static final native int IIDFromString (char[] lpsz, byte[] lpiid);
/**
+ * @param pidl cast=(PCIDLIST_ABSOLUTE)
+ */
+public static final native int ILGetSize(long pidl);
+/**
* @param himl cast=(HIMAGELIST)
* @param hbmImage cast=(HBITMAP)
* @param hbmMask cast=(HBITMAP)
@@ -3790,6 +3795,16 @@ public static final native void MoveMemory (long Destination, MOUSEINPUT Source,
*/
public static final native void MoveMemory (long Destination, GESTURECONFIG Source, int Length);
/**
+ * @param Destination cast=(PVOID)
+ * @param Source cast=(CONST VOID *),flags=no_out
+ */
+public static final native void MoveMemory (long Destination, CIDA Source, int Length);
+/**
+ * @param Destination cast=(PVOID),flags=no_in
+ * @param Source cast=(CONST VOID *)
+ */
+public static final native void MoveMemory (CIDA Destination, long Source, int Length);
+/**
* @param hdc cast=(HDC)
* @param lPoint cast=(LPPOINT)
*/
diff --git a/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/AllWin32Tests.java b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/AllWin32Tests.java
index 411fe41953..4bdcf97204 100644
--- a/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/AllWin32Tests.java
+++ b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/AllWin32Tests.java
@@ -14,19 +14,20 @@
*/
package org.eclipse.swt.tests.win32;
+import org.junit.runner.JUnitCore;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
- // Test.class be added here.
+ Test_org_eclipse_swt_dnd_DND.class,
})
public class AllWin32Tests {
public static void main(String[] args) {
-// JUnitCore.main(AllWin32Tests.class.getName()); // Enable once a test is added.
+ JUnitCore.main(AllWin32Tests.class.getName());
}
}
diff --git a/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/SwtWin32TestUtil.java b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/SwtWin32TestUtil.java
new file mode 100644
index 0000000000..d374b9f64d
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/SwtWin32TestUtil.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Paul Pazderski and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Paul Pazderski - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.win32;
+
+import java.util.function.BooleanSupplier;
+
+import org.eclipse.swt.widgets.Display;
+
+public class SwtWin32TestUtil {
+
+/**
+ * Dispatch events until <em>condition</em> is <code>true</code> or timeout reached.
+ *
+ * @param display display to dispatch events for (not <code>null</code>)
+ * @param timeoutMs max time in milliseconds to process events
+ * @param condition optional condition. If the condition returns <code>true</code> event processing is stopped.
+ */
+public static void processEvents(Display display, int timeoutMs, BooleanSupplier condition) throws InterruptedException {
+ if (condition == null) {
+ condition = () -> false;
+ }
+ long targetTimestamp = System.currentTimeMillis() + timeoutMs;
+ while (!condition.getAsBoolean()) {
+ if (!display.readAndDispatch()) {
+ if (System.currentTimeMillis() < targetTimestamp) {
+ Thread.sleep(50);
+ } else {
+ return;
+ }
+ }
+ }
+}
+}
diff --git a/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/Test_org_eclipse_swt_dnd_DND.java b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/Test_org_eclipse_swt_dnd_DND.java
new file mode 100644
index 0000000000..6d6d56678b
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/tests/win32/Test_org_eclipse_swt_dnd_DND.java
@@ -0,0 +1,276 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Paul Pazderski and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Paul Pazderski - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.win32;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.ByteArrayTransfer;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.HTMLTransfer;
+import org.eclipse.swt.dnd.ImageTransfer;
+import org.eclipse.swt.dnd.RTFTransfer;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.dnd.URLTransfer;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Shell;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Some simple tests for drag and drop.
+ * <p>
+ * To test drag and drop the appropriate user input must be simulated. This
+ * requires that the test window is visible/active/focused and if it fails may
+ * move something or trigger other actions when the input is simulated but the
+ * test window not at the expected position. This should be no problem for fully
+ * automated tests but may disturb when run locally in background as part of a
+ * larger test suite.
+ * </p>
+ */
+public class Test_org_eclipse_swt_dnd_DND {
+
+private Shell shell;
+
+@Before
+public void setUp() {
+ shell = new Shell();
+ shell.setLayout(new RowLayout());
+ shell.setSize(300, 300);
+ shell.open();
+ try {
+ SwtWin32TestUtil.processEvents(shell.getDisplay(), 1000, shell::isVisible);
+ } catch (InterruptedException e) {
+ fail("Initialization interrupted");
+ }
+ assertTrue("Shell not visible.", shell.isVisible());
+}
+
+@After
+public void tearDown() {
+ Display display = shell.getDisplay();
+ display.dispose();
+ assertTrue(display.isDisposed());
+}
+
+/**
+ * DnD some random bytes using a custom transfer type and the abstract {@link ByteArrayTransfer}.
+ */
+@Test
+public void testByteArrayTransfer() throws InterruptedException {
+ final byte[] drag = new byte[1024];
+ final byte[] drop;
+
+ new Random(4).nextBytes(drag);
+ drop = testTransferRoundtrip(new ByteArrayTransfer() {
+ private final String TEST_TYPE = "SWT JUnit Transfer Test";
+ private final int TEST_ID = registerType(TEST_TYPE);
+
+ @Override
+ protected String[] getTypeNames() {
+ return new String[] { TEST_TYPE };
+ }
+
+ @Override
+ protected int[] getTypeIds() {
+ return new int[] { TEST_ID };
+ }
+ }, drag);
+ assertArrayEquals("Drop received other data as we dragged.", drag, drop);
+}
+
+/**
+ * DnD some filenames using the {@link FileTransfer}.
+ */
+@Test
+public void testFileTransfer() throws InterruptedException {
+ final String[] drag = new String[] { "C:\\temp\\file1", "C:\\temp\\file2" };
+ final String[] drop;
+
+ drop = testTransferRoundtrip(FileTransfer.getInstance(), drag);
+ assertArrayEquals("Drop received other data as we dragged.", drag, drop);
+}
+
+/**
+ * DnD some HTML using the {@link HTMLTransfer}.
+ */
+@Test
+public void testHtmlTransfer() throws InterruptedException {
+ final String drag = "<p>This is a paragraph of text.</p>";
+ final String drop;
+
+ drop = testTransferRoundtrip(HTMLTransfer.getInstance(), drag);
+ assertEquals("Drop received other data as we dragged.", drag, drop);
+}
+
+/**
+ * DnD an image using the {@link ImageTransfer}.
+ */
+@Test
+public void testImageTransfer() throws InterruptedException {
+ final Image image = new Image(shell.getDisplay(), 16, 16);
+ try {
+ Color color = shell.getDisplay().getSystemColor(SWT.COLOR_DARK_BLUE);
+ GC gc = new GC(image);
+ gc.setBackground(color);
+ gc.fillRectangle(image.getBounds());
+ gc.dispose();
+
+ final ImageData drag = image.getImageData();
+ final ImageData drop;
+
+ drop = testTransferRoundtrip(ImageTransfer.getInstance(), drag);
+ // ImageData has no custom equals method and the default one isn't sufficient
+ boolean equals = (drag == drop);
+ if (!equals && drag != null && drop != null) {
+ equals = (drag.width == drop.width && drag.height == drop.height);
+ if (equals) {
+ outer: for (int y = 0; y < drag.height; y++) {
+ for (int x = 0; x < drag.width; x++) {
+ if (drag.getPixel(x, y) != drop.getPixel(x, y)) {
+ equals = false;
+ break outer;
+ }
+ }
+ }
+ }
+ }
+ assertTrue("Drop received other data as we dragged.", equals);
+ } finally {
+ image.dispose();
+ }
+}
+
+/**
+ * DnD some formatted text using the {@link RTFTransfer}.
+ */
+@Test
+public void testRtfTransfer() throws InterruptedException {
+ final String drag = "{\\rtf1{\\colortbl;\\red255\\green0\\blue0;}\\uc1\\b\\i Hello World}";
+ final String drop;
+
+ drop = testTransferRoundtrip(RTFTransfer.getInstance(), drag);
+ assertEquals("Drop received other data as we dragged.", drag, drop);
+}
+
+/**
+ * DnD some simple text using the {@link TextTransfer}.
+ */
+@Test
+public void testTextTransfer() throws InterruptedException {
+ final String drag = "Hello World";
+ final String drop;
+
+ drop = testTransferRoundtrip(TextTransfer.getInstance(), drag);
+ assertEquals("Drop received other data as we dragged.", drag, drop);
+}
+
+/**
+ * DnD an URL using the {@link URLTransfer}.
+ */
+@Test
+public void testUrlTransfer() throws InterruptedException {
+ final String drag = "https://www.eclipse.org";
+ final String drop;
+
+ drop = testTransferRoundtrip(URLTransfer.getInstance(), drag);
+ assertEquals("Drop received other data as we dragged.", drag, drop);
+}
+
+/**
+ * Test transfer implementation by dragging and dropping some data onto ourself.
+ *
+ * @param <T> the data's type
+ * @param transfer the transfer type to test
+ * @param data the data to drag and drop
+ * @return the data received from the drop
+ */
+private <T> T testTransferRoundtrip(Transfer transfer, T data) throws InterruptedException {
+ int maxTries = 3;
+ AtomicBoolean dropped = new AtomicBoolean(false);
+ AtomicReference<T> droppedData = new AtomicReference<>(null);
+
+ DragSource source = new DragSource(shell, DND.DROP_LINK | DND.DROP_COPY | DND.DROP_MOVE);
+ source.setTransfer(transfer);
+ source.addListener(DND.DragSetData, event -> event.data = data);
+
+ DropTarget target = new DropTarget(shell, DND.DROP_DEFAULT | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_MOVE);
+ target.setTransfer(transfer);
+ target.addListener(DND.Drop, event -> {
+ try {
+ @SuppressWarnings("unchecked")
+ T o = (T) event.data;
+ droppedData.set(o);
+ } catch (ClassCastException ex) {
+ }
+ dropped.set(true);
+ });
+
+ do {
+ postDragAndDropEvents();
+ SwtWin32TestUtil.processEvents(shell.getDisplay(), 2000, dropped::get);
+ } while(!dropped.get() && --maxTries > 0);
+
+ assertTrue("No drop received.", dropped.get());
+ assertNotNull("No data was dropped.", droppedData.get());
+
+ return droppedData.get();
+}
+
+/**
+ * Posts the events required to do a drag and drop. (i.e. click and hold mouse button and move mouse)
+ * <p>
+ * The caller is responsible to ensure the generated events are processed by the event loop.
+ * </p>
+ */
+private void postDragAndDropEvents() {
+ shell.forceActive();
+ assertTrue("Test shell requires input focus.", shell.forceFocus());
+ Event event = new Event();
+ Point pt = shell.toDisplay(50, 50);
+ event.x = pt.x;
+ event.y = pt.y;
+ event.type = SWT.MouseMove;
+ shell.getDisplay().post(event);
+ event.button = 1;
+ event.count = 1;
+ event.type = SWT.MouseDown;
+ shell.getDisplay().post(event);
+ event.x += 30;
+ event.type = SWT.MouseMove;
+ shell.getDisplay().post(event);
+ event.type = SWT.MouseUp;
+ shell.getDisplay().post(event);
+}
+}

Back to the top