diff options
author | Paul Pazderski | 2019-08-11 16:24:20 +0000 |
---|---|---|
committer | Paul Pazderski | 2019-08-15 17:43:25 +0000 |
commit | 72476dd4c1385c8df23092b19d585fecc8f575f4 (patch) | |
tree | 4fd88c77535decd64640bcc318a28927fa5c16e7 | |
parent | 1d0010bad752650b9e59e8f4bdc76ba758e9a108 (diff) | |
download | eclipse.platform.swt-72476dd4c1385c8df23092b19d585fecc8f575f4.tar.gz eclipse.platform.swt-72476dd4c1385c8df23092b19d585fecc8f575f4.tar.xz eclipse.platform.swt-72476dd4c1385c8df23092b19d585fecc8f575f4.zip |
Bug 549661 - [Win32][DND] FileTransfer can not drop on Portable Device
First problem: dropping on Portable Device does not like the fake PIDLs
which were used before.
Second problem: dropping on Portable Device query for the data after the
drag and drop operation is finished.
Change-Id: Ic5f17e12c070759fb957d5010cd8cec5165fc8ff
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/DragSource.java | 25 | ||||
-rw-r--r-- | bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/com_custom.cpp | 13 |
2 files changed, 34 insertions, 4 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/DragSource.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/DragSource.java index c4c4e09894..3615995c1a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/DragSource.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/DragSource.java @@ -391,6 +391,31 @@ private void drag(Event dragEvent) { } } + /* + * Bug 549643: a proper drag&drop operation is finished when the DoDragDrop loop/function returns. + * Unfortunately the Windows Explorer is ignoring this fact while showing a Portable Device + * (e.g. Smartphone attached through MTP). I.e. dropping a file on Windows Explorer in this + * situation will query the iDataObject at least once for its data _after_ DoDragDrop finished. + * Revoking this getData request will fail the drop. + * + * This behavior can succeeds because most applications store the actual data to transfer in + * the IDataObject and since its lifetime is managed through ref counting it can return the data + * even after the drag&drop finished. In SWT the data to transfer is not stored in the IDataObject + * but instead obtained on demand through a DND.DragSetData event. Additional some clients release + * the data to drag in the DragEnd event and therefore do not like to get such events after DragEnd. + * + * That's why the next few lines exist. In case the DropTarget has not yet released the IDataObject + * (which is the case for the faulty Windows Explorer described above) we delay the DragEnd event in + * case an additional DragSetData is triggered. Since the DropTarget can be any (faulty or malicious) + * application maybe never releasing the object wait is combined with a tight timeout. + */ + final long start = System.currentTimeMillis(); + while (refCount > 0 && System.currentTimeMillis() - start < 1000) { + if (!display.readAndDispatch()) { + try { Thread.sleep(10); } + catch (InterruptedException e) { break; } + } + } disposeCOMInterfaces(); event = new DNDEvent(); 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 index e4509e4c94..791d8df1be 100644 --- 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 @@ -71,13 +71,18 @@ private: }; /* - * 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. + * An extended version of SHParseDisplayName which use bind context to support + * creation of simple PIDLs in case the normal PIDL creation failed. + * (most likley due to non existing file/directory) */ extern "C" HRESULT PathToPIDL(PCWSTR pszName, PIDLIST_ABSOLUTE *ppidl) { if (!ppidl) return E_FAIL; *ppidl = nullptr; + + SFGAOF sfgao = 0; + HRESULT hr = SHParseDisplayName(pszName, nullptr, ppidl, sfgao, &sfgao); + if (hr == S_OK) return hr; IFileSystemBindData *pfsbd = new CFileSysBindData(); if (!pfsbd) return E_OUTOFMEMORY; @@ -87,7 +92,7 @@ extern "C" HRESULT PathToPIDL(PCWSTR pszName, PIDLIST_ABSOLUTE *ppidl) IBindCtx* pbc; - HRESULT hr = CreateBindCtx(0, &pbc); + hr = CreateBindCtx(0, &pbc); if (hr == S_OK) { BIND_OPTS bo = { sizeof(bo), 0, STGM_CREATE, 0 }; @@ -97,7 +102,7 @@ extern "C" HRESULT PathToPIDL(PCWSTR pszName, PIDLIST_ABSOLUTE *ppidl) hr = pbc->RegisterObjectParam(STR_FILE_SYS_BIND_DATA, pfsbd); if (hr == S_OK) { - SFGAOF sfgao = 0; + sfgao = 0; hr = SHParseDisplayName(pszName, pbc, ppidl, sfgao, &sfgao); } } |