Module: wine Branch: master Commit: 3f99e71fde8231524597901e512e5c1909a82e1e URL: http://source.winehq.org/git/wine.git/?a=commit;h=3f99e71fde8231524597901e51...
Author: Damjan Jovanovic damjan.jov@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; }