[PATCH v2] winex11.drv: Search for the drop target in a correct manner.
John Found
johnfound at asm32.info
Tue Apr 23 06:28:58 CDT 2019
Ah, yes - attached is the test application I am using for the tests. It is interesting
whether such behavior is only in Windows 10 (where I tested) or on older versions as well.
If someone has an access to older windows and want to try - check what is displayed in the
indicator label on dropping files on the popup window.
Sorry for the strange sources of the test application. :)
On Tue, 23 Apr 2019 14:21:56 +0300
John Found <johnfound at asm32.info> wrote:
> After some more tests with a real Windows it turned,
> that using GetAncestor() instead of GetParent() is a mistake.
>
> In fact, the popup window, owned by a window with WS_EX_ACCEPTFILES also becomes a drop target and the
> WM_DROPFILES is sent to the **owner** window. This way the proper solution is to use exactly GetParent
> that returns the owner window (only for the popup windows) as well.
>
> So, patch v3 is to be released soon.
>
>
> On Sat, 20 Apr 2019 10:20:27 +0300
> "John Found" <johnfound at asm32.info> wrote:
>
> > Signed-off-by: John Found <johnfound at asm32.info>
> > ---
> > dlls/winex11.drv/xdnd.c | 50 ++++++++++++++++++++++++++++++++++-------
> > 1 file changed, 42 insertions(+), 8 deletions(-)
> >
> > diff --git a/dlls/winex11.drv/xdnd.c b/dlls/winex11.drv/xdnd.c
> > index 2ab28e43bf..ac2fc644dc 100644
> > --- a/dlls/winex11.drv/xdnd.c
> > +++ b/dlls/winex11.drv/xdnd.c
> > @@ -254,6 +254,34 @@ void X11DRV_XDND_EnterEvent( HWND hWnd, XClientMessageEvent *event )
> > XFree(xdndtypes);
> > }
> >
> > +/* Recursively searches for a window on given coordinates in a drag&drop specific manner.
> > + *
> > + * Don't use WindowFromPoint instead, because it omits the STATIC and transparent
> > + * windows, but they can be a valid drop targets if have WS_EX_ACCEPTFILES set.
> > + */
> > +static HWND window_from_point_dnd(HWND hwnd, POINT point)
> > +{
> > + HWND child;
> > + ScreenToClient(hwnd, &point);
> > + while ((child = ChildWindowFromPointEx(hwnd, point, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE)) && child != hwnd)
> > + {
> > + MapWindowPoints(hwnd, child, &point, 1);
> > + hwnd = child;
> > + }
> > +
> > + return hwnd;
> > +}
> > +
> > +/* Returns the first window down the hierarchy that has WS_EX_ACCEPTFILES set or
> > + * returns NULL, if such window does not exists.
> > + */
> > +static HWND window_accepting_files(HWND hwnd)
> > +{
> > + while (hwnd && !(GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES))
> > + hwnd = GetAncestor(hwnd, GA_PARENT);
> > + return hwnd;
> > +}
> > +
> > /**************************************************************************
> > * X11DRV_XDND_PositionEvent
> > *
> > @@ -270,7 +298,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 +362,15 @@ 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. */
> > +
> > + if (window_accepting_files(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,12 @@ 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())
> > +
> > + HWND hwnd_drop = window_accepting_files(window_from_point_dnd(hWnd, XDNDxy));
> > +
> > + if (hwnd_drop && X11DRV_XDND_HasHDROP())
> > {
> > - HRESULT hr = X11DRV_XDND_SendDropFiles( hWnd );
> > + HRESULT hr = X11DRV_XDND_SendDropFiles(hwnd_drop);
> > if (SUCCEEDED(hr))
> > {
> > accept = 1;
> > --
> > 2.21.0
> >
>
>
> --
> John Found <johnfound at asm32.info>
>
>
--
John Found <johnfound at asm32.info>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: TestWineDnD.tar.gz
Type: application/gzip
Size: 5715 bytes
Desc: not available
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20190423/9bf74e68/attachment-0001.gz>
More information about the wine-devel
mailing list