Damjan Jovanovic : winex11: Use the correct drop effect for WM_DROPFILES.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Aug 7 10:57:42 CDT 2015
Module: wine
Branch: master
Commit: 3f99e71fde8231524597901e512e5c1909a82e1e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=3f99e71fde8231524597901e512e5c1909a82e1e
Author: Damjan Jovanovic <damjan.jov at gmail.com>
Date: Fri Aug 7 04:21:27 2015 +0200
winex11: Use the correct drop effect for WM_DROPFILES.
Tests show that on Windows, for a window to indicate it will accept a
file drop or to actually accept it, it must have WS_EX_ACCEPTFILES in
its style, contain DROPEFFECT_COPY (which will be chosen if offered
among several drop effects), and be offered the HDROP format.
---
dlls/winex11.drv/xdnd.c | 67 +++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 59 insertions(+), 8 deletions(-)
diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c
index 9944dab..72758a0 100644
--- a/dlls/winex11.drv/xdnd.c
+++ b/dlls/winex11.drv/xdnd.c
@@ -74,7 +74,8 @@ static HWND XDNDLastDropTargetWnd;
static void X11DRV_XDND_InsertXDNDData(int property, int format, HANDLE contents);
static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
Atom *types, unsigned long count);
-static void X11DRV_XDND_SendDropFiles(HWND hwnd);
+static BOOL X11DRV_XDND_HasHDROP(void);
+static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd);
static void X11DRV_XDND_FreeDragDropOp(void);
static CRITICAL_SECTION xdnd_cs;
@@ -338,8 +339,15 @@ void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event )
if (XDNDAccepted)
accept = 1;
- if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)
+ else if (dropTarget == NULL &&
+ (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) &&
+ (effect & DROPEFFECT_COPY) &&
+ X11DRV_XDND_HasHDROP())
+ {
accept = 1;
+ effect = DROPEFFECT_COPY;
+ XDNDDropEffect = effect;
+ }
TRACE("action req: %ld accept(%d) at x(%d),y(%d)\n",
event->data.l[4], accept, XDNDxy.x, XDNDxy.y);
@@ -407,8 +415,17 @@ void X11DRV_XDND_DropEvent( HWND hWnd, XClientMessageEvent *event )
{
/* Only send WM_DROPFILES if there is no drop target. Doing both
* causes winamp to duplicate the dropped files (#29081) */
- if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)
- X11DRV_XDND_SendDropFiles( hWnd );
+ if ((GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) &&
+ (effect & DROPEFFECT_COPY) &&
+ X11DRV_XDND_HasHDROP())
+ {
+ HRESULT hr = X11DRV_XDND_SendDropFiles( hWnd );
+ if (SUCCEEDED(hr))
+ {
+ accept = 1;
+ effect = DROPEFFECT_COPY;
+ }
+ }
}
X11DRV_XDND_FreeDragDropOp();
@@ -552,9 +569,9 @@ static void X11DRV_XDND_InsertXDNDData(int property, int format, HANDLE contents
/**************************************************************************
- * X11DRV_XDND_SendDropFiles
+ * X11DRV_XDND_HasHDROP
*/
-static void X11DRV_XDND_SendDropFiles(HWND hwnd)
+static BOOL X11DRV_XDND_HasHDROP(void)
{
LPXDNDDATA current = NULL;
BOOL found = FALSE;
@@ -571,10 +588,33 @@ static void X11DRV_XDND_SendDropFiles(HWND hwnd)
}
}
+ LeaveCriticalSection(&xdnd_cs);
+
+ return found;
+}
+
+/**************************************************************************
+ * X11DRV_XDND_SendDropFiles
+ */
+static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd)
+{
+ HRESULT hr;
+ LPXDNDDATA current = NULL;
+ BOOL found = FALSE;
+
+ EnterCriticalSection(&xdnd_cs);
+
+ LIST_FOR_EACH_ENTRY(current, &xdndData, XDNDDATA, entry)
+ {
+ if (current->cf_win == CF_HDROP)
+ {
+ found = TRUE;
+ break;
+ }
+ }
if (found)
{
HGLOBAL dropHandle = GlobalAlloc(GMEM_FIXED, GlobalSize(current->contents));
-
if (dropHandle)
{
DROPFILES *lpDrop = GlobalLock(dropHandle);
@@ -587,12 +627,23 @@ static void X11DRV_XDND_SendDropFiles(HWND hwnd)
lpDrop->fNC, lpDrop->pt.x, lpDrop->pt.y, ((char*)lpDrop) + lpDrop->pFiles,
debugstr_w((WCHAR*)(((char*)lpDrop) + lpDrop->pFiles)));
GlobalUnlock(dropHandle);
- if (!PostMessageW(hwnd, WM_DROPFILES, (WPARAM)dropHandle, 0))
+ if (PostMessageW(hwnd, WM_DROPFILES, (WPARAM)dropHandle, 0))
+ hr = S_OK;
+ else
+ {
+ hr = HRESULT_FROM_WIN32(GetLastError());
GlobalFree(dropHandle);
+ }
}
+ else
+ hr = HRESULT_FROM_WIN32(GetLastError());
}
+ else
+ hr = E_FAIL;
LeaveCriticalSection(&xdnd_cs);
+
+ return hr;
}
More information about the wine-cvs
mailing list