[PATCH] winex11.drv: Allow the children windows to accept WM_DROPFILES if they have WS_EX_ACCEPTFILES.

John Found johnfound at asm32.info
Sun Jul 8 02:05:43 CDT 2018


Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=41606
Signed-off-by: John Found <johnfound at asm32.info>
---
 dlls/winex11.drv/xdnd.c | 58 +++++++++++++++++++++++++++++++++++------
 1 file changed, 50 insertions(+), 8 deletions(-)

diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c
index 2ab28e43bf..2ba98491e1 100644
--- a/dlls/winex11.drv/xdnd.c
+++ b/dlls/winex11.drv/xdnd.c
@@ -254,6 +254,31 @@ void X11DRV_XDND_EnterEvent( HWND hWnd, XClientMessageEvent *event )
         XFree(xdndtypes);
 }
 
+/* the recursive worker for window_from_point_dnd */
+HWND do_window_from_point_dnd(HWND hwnd, POINT* point)
+{
+    HWND w;
+    w = ChildWindowFromPointEx(hwnd, *point, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE);
+    if (w && (w != hwnd))
+    {
+        ClientToScreen(hwnd, point);
+        ScreenToClient(w, point);
+        w = do_window_from_point_dnd(w, point);
+    }
+    return w;
+}
+
+
+/* Recursively search for the window on given coordinates in a drag&drop specific manner. */
+HWND window_from_point_dnd(HWND hwnd, POINT point)
+{
+    POINT p;
+    p.x = point.x;
+    p.y = point.y;
+    ScreenToClient(hwnd, &p);
+    return do_window_from_point_dnd(hwnd, &p);
+}
+
 /**************************************************************************
  * X11DRV_XDND_PositionEvent
  *
@@ -270,7 +295,7 @@ void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event )
     HRESULT hr;
 
     XDNDxy = root_to_virtual_screen( event->data.l[2] >> 16, event->data.l[2] & 0xFFFF );
-    targetWindow = WindowFromPoint(XDNDxy);
+    targetWindow = window_from_point_dnd(hWnd, XDNDxy);
 
     pointl.x = XDNDxy.x;
     pointl.y = XDNDxy.y;
@@ -334,11 +359,18 @@ void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event )
 
     if (XDNDAccepted)
         accept = 1;
-    else if ((GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) &&
-            X11DRV_XDND_HasHDROP())
+    else
     {
-        accept = 1;
-        effect = DROPEFFECT_COPY;
+        /* fallback search for window able to accept these files. */
+
+        while (targetWindow && !(GetWindowLongW(targetWindow, GWL_EXSTYLE) & WS_EX_ACCEPTFILES))
+            targetWindow = GetParent(targetWindow);
+
+        if (targetWindow && X11DRV_XDND_HasHDROP())
+        {
+            accept = 1;
+            effect = DROPEFFECT_COPY;
+        }
     }
 
     TRACE("actionRequested(%ld) accept(%d) chosen(0x%x) at x(%d),y(%d)\n",
@@ -423,10 +455,20 @@ void X11DRV_XDND_DropEvent( HWND hWnd, XClientMessageEvent *event )
     {
         /* Only send WM_DROPFILES if Drop didn't succeed or DROPEFFECT_NONE was set.
          * Doing both causes winamp to duplicate the dropped files (#29081) */
-        if ((GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) &&
-                X11DRV_XDND_HasHDROP())
+        POINT pt;
+        HWND hwnd_drop;
+
+        pt.x = XDNDxy.x;
+        pt.y = XDNDxy.y;
+
+        hwnd_drop = window_from_point_dnd(hWnd, pt);
+
+        while (hwnd_drop && !(GetWindowLongW(hwnd_drop, GWL_EXSTYLE) & WS_EX_ACCEPTFILES))
+            hwnd_drop = GetParent(hwnd_drop);
+
+        if (hwnd_drop)
         {
-            HRESULT hr = X11DRV_XDND_SendDropFiles( hWnd );
+            HRESULT hr = X11DRV_XDND_SendDropFiles(hwnd_drop);
             if (SUCCEEDED(hr))
             {
                 accept = 1;
-- 
2.18.0



More information about the wine-devel mailing list