Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=41606 Signed-off-by: John Found johnfound@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;
John Found johnfound@asm32.info writes:
+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);
MapWindowPoints() would be more efficient.
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);
+}
There's no need to make it recursive.
@@ -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)
You are losing the X11DRV_XDND_HasHDROP() check. If that's deliberate, it should be a separate patch.
On Fri, 20 Jul 2018 16:43:02 +0200 Alexandre Julliard julliard@winehq.org wrote:
John Found johnfound@asm32.info writes:
+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);
MapWindowPoints() would be more efficient.
Will use it. Thanks.
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);
+}
There's no need to make it recursive.
How about if the target is a window deep inside the parent-child tree? Actually the recursive search is the very essence of this patch. ChildWindowFromPointEx searches only immediate children of the window. Or I am missing something?
@@ -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)
You are losing the X11DRV_XDND_HasHDROP() check. If that's deliberate, it should be a separate patch.
It is my fault. Will fix it.
-- Alexandre Julliard julliard@winehq.org