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