From: Damjan Jovanovic Subject: [PATCH 5/7] winex11.drv: use the correct drop effect for WM_DROPFILES (try 3) Message-Id: Date: Sat, 18 Jul 2015 10:43:05 +0200 Tests show that 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, and be offered the HDROP format. Try 2 and 3: no changes. Damjan Jovanovic --- dlls/winex11.drv/xdnd.c | 91 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 31 deletions(-) diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c index a177957..cdb79ad 100644 --- a/dlls/winex11.drv/xdnd.c +++ b/dlls/winex11.drv/xdnd.c @@ -67,7 +67,8 @@ static HWND XDNDLastTargetWnd; /* might be an ancestor of XDNDLastTargetWnd */ static HWND XDNDLastDropTargetWnd; -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); @@ -346,8 +347,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); @@ -419,8 +427,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(); @@ -467,12 +484,12 @@ void X11DRV_XDND_LeaveEvent( HWND hWnd, XClientMessageEvent *event ) /************************************************************************** - * X11DRV_XDND_SendDropFiles + * X11DRV_XDND_HasHDROP */ -static void X11DRV_XDND_SendDropFiles(HWND hwnd) +static BOOL X11DRV_XDND_HasHDROP(void) { - DWORD i; BOOL found = FALSE; + DWORD i; /* Find CF_HDROP type if any */ for (i = 0; i < XDNDTypeListSize; i++) @@ -485,35 +502,47 @@ static void X11DRV_XDND_SendDropFiles(HWND hwnd) } } - if (found) - { - HRESULT hr; - FORMATETC formatEtc; - STGMEDIUM stgMedium; + return found; +} - formatEtc.cfFormat = CF_HDROP; - formatEtc.dwAspect = DVASPECT_CONTENT; - formatEtc.ptd = NULL; - formatEtc.tymed = TYMED_HGLOBAL; - hr = IDataObject_GetData(&XDNDDataObject, &formatEtc, &stgMedium); - if (SUCCEEDED(hr)) +/************************************************************************** + * X11DRV_XDND_SendDropFiles + */ +static HRESULT X11DRV_XDND_SendDropFiles(HWND hwnd) +{ + HRESULT hr; + FORMATETC formatEtc; + STGMEDIUM stgMedium; + + formatEtc.cfFormat = CF_HDROP; + formatEtc.dwAspect = DVASPECT_CONTENT; + formatEtc.ptd = NULL; + formatEtc.tymed = TYMED_HGLOBAL; + + hr = IDataObject_GetData(&XDNDDataObject, &formatEtc, &stgMedium); + if (SUCCEEDED(hr)) + { + DROPFILES *lpDrop = GlobalLock(stgMedium.u.hGlobal); + lpDrop->pt.x = XDNDxy.x; + lpDrop->pt.y = XDNDxy.y; + lpDrop->fNC = !ScreenToClient(hwnd, &lpDrop->pt); + TRACE("Sending WM_DROPFILES: hWnd=0x%p, fNC=%d, x=%d, y=%d, files=%p(%s)\n", hwnd, + lpDrop->fNC, lpDrop->pt.x, lpDrop->pt.y, ((char*)lpDrop) + lpDrop->pFiles, + debugstr_w((WCHAR*)(((char*)lpDrop) + lpDrop->pFiles))); + GlobalUnlock(stgMedium.u.hGlobal); + + if (PostMessageW(hwnd, WM_DROPFILES, (WPARAM)stgMedium.u.hGlobal, 0)) + hr = S_OK; + else { - DROPFILES *lpDrop = GlobalLock(stgMedium.u.hGlobal); - lpDrop->pt.x = XDNDxy.x; - lpDrop->pt.y = XDNDxy.y; - lpDrop->fNC = !ScreenToClient(hwnd, &lpDrop->pt); - TRACE("Sending WM_DROPFILES: hWnd=0x%p, fNC=%d, x=%d, y=%d, files=%p(%s)\n", hwnd, - lpDrop->fNC, lpDrop->pt.x, lpDrop->pt.y, ((char*)lpDrop) + lpDrop->pFiles, - debugstr_w((WCHAR*)(((char*)lpDrop) + lpDrop->pFiles))); - GlobalUnlock(stgMedium.u.hGlobal); - - if (!PostMessageW(hwnd, WM_DROPFILES, (WPARAM)stgMedium.u.hGlobal, 0)) - GlobalFree(stgMedium.u.hGlobal); + hr = HRESULT_FROM_WIN32(GetLastError()); + GlobalFree(stgMedium.u.hGlobal); } - else - ERR("fetching CF_HDROP data for WM_DROPFILES failed, hr=0x%08x\n", hr); } + else + ERR("fetching CF_HDROP data for WM_DROPFILES failed, hr=0x%08x\n", hr); + return hr; }