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.
This commit is contained in:
Damjan Jovanovic 2015-08-07 04:21:27 +02:00 committed by Alexandre Julliard
parent b78a9f1aa1
commit 3f99e71fde
1 changed files with 59 additions and 8 deletions

View File

@ -74,7 +74,8 @@ static HWND XDNDLastDropTargetWnd;
static void X11DRV_XDND_InsertXDNDData(int property, int format, HANDLE contents); static void X11DRV_XDND_InsertXDNDData(int property, int format, HANDLE contents);
static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm, static void X11DRV_XDND_ResolveProperty(Display *display, Window xwin, Time tm,
Atom *types, unsigned long count); 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 void X11DRV_XDND_FreeDragDropOp(void);
static CRITICAL_SECTION xdnd_cs; static CRITICAL_SECTION xdnd_cs;
@ -338,8 +339,15 @@ void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event )
if (XDNDAccepted) if (XDNDAccepted)
accept = 1; 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; accept = 1;
effect = DROPEFFECT_COPY;
XDNDDropEffect = effect;
}
TRACE("action req: %ld accept(%d) at x(%d),y(%d)\n", TRACE("action req: %ld accept(%d) at x(%d),y(%d)\n",
event->data.l[4], accept, XDNDxy.x, XDNDxy.y); 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 /* Only send WM_DROPFILES if there is no drop target. Doing both
* causes winamp to duplicate the dropped files (#29081) */ * causes winamp to duplicate the dropped files (#29081) */
if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) if ((GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) &&
X11DRV_XDND_SendDropFiles( hWnd ); (effect & DROPEFFECT_COPY) &&
X11DRV_XDND_HasHDROP())
{
HRESULT hr = X11DRV_XDND_SendDropFiles( hWnd );
if (SUCCEEDED(hr))
{
accept = 1;
effect = DROPEFFECT_COPY;
}
}
} }
X11DRV_XDND_FreeDragDropOp(); 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; LPXDNDDATA current = NULL;
BOOL found = FALSE; 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) if (found)
{ {
HGLOBAL dropHandle = GlobalAlloc(GMEM_FIXED, GlobalSize(current->contents)); HGLOBAL dropHandle = GlobalAlloc(GMEM_FIXED, GlobalSize(current->contents));
if (dropHandle) if (dropHandle)
{ {
DROPFILES *lpDrop = GlobalLock(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, lpDrop->fNC, lpDrop->pt.x, lpDrop->pt.y, ((char*)lpDrop) + lpDrop->pFiles,
debugstr_w((WCHAR*)(((char*)lpDrop) + lpDrop->pFiles))); debugstr_w((WCHAR*)(((char*)lpDrop) + lpDrop->pFiles)));
GlobalUnlock(dropHandle); 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); GlobalFree(dropHandle);
}
} }
else
hr = HRESULT_FROM_WIN32(GetLastError());
} }
else
hr = E_FAIL;
LeaveCriticalSection(&xdnd_cs); LeaveCriticalSection(&xdnd_cs);
return hr;
} }