[PATCH 2/3] include/ole32/user32/winemac.drv/winex11.drv: do not allow dropping drags through obscuring native windows
ken at codeweavers.com
Wed Mar 4 13:30:46 CST 2015
On Mar 3, 2015, at 12:22 PM, Damjan Jovanovic <damjan.jov at gmail.com> wrote:
> On Mon, Mar 2, 2015 at 10:09 PM, Ken Thomases <ken at codeweavers.com> wrote:
>> I appreciate your work on this, but I think this isn't the right approach. I think if you solve the other problem (dragging from Wine to other apps) by having the driver take over drags and translating them into a native drag operation, then this problem gets solved automatically. The native drag operation will target the proper window under the cursor, eliminating the problem of dropping through non-Wine windows. If the drag goes over a Wine window, then the native drag will get translated back into Win32 by the existing code in the drivers for receiving drops.
> Thank you. So in other words you want only native drag and drop to
> exist, and Wine's drag and drop to be implemented on top of native in
> all cases.
Yes, although there needs to still be an implementation in ole32 (the current one) for drivers which don't take over.
> It's doable, we can use native drag and drop for window
> selection, and nothing forces us to use native APIs for the data
> transfer when both the source and destination are Wine windows, so
> potentially lossy data conversions to and from native data formats can
> still be avoided.
Possibly, although if Win32 types are represented in the drag data in "raw" form in addition to a translation to a format that will be meaningful to native apps, it should come across faithfully. (I guess the hard part will be if the raw Win32 type is an opaque handle and one drags between wineprefixes. The handle could come across but be meaningless in the destination. I don't recall if I accounted for that in the Mac driver's clipboard code or not, either.)
> Does Alexandre agree with this approach though?
Good question. I'll sacrifice a chicken, you recite the incantation, and maybe we'll receive revelation. ;)
Most likely the answer is "I won't know until I see a proposed implementation". :-/
>> I understand your point from the next patch email that this may result in code duplication between the drivers, but I think that's largely inevitable because of the requirements of driving a native drag operation.
>> Also, I don't believe your design where the driver implements IDropTarget and ole32 calls its methods can be made to work on the Mac. As is often the case, Cocoa has a much more closed API for drag and drop than X11. We can't really arbitrarily do pieces of the drag operation in isolation and effectively start and stop the drag (as the cursor moves from Wine window to native window and back to a Wine window). We can only start the drag and then Cocoa takes it from there. It calls relevant methods on the drag source object along the way, of course, but we don't have a lot of control over the drag operation other than that.
> Yes I see Cocoa's
> dragImage:at:offset:event:pasteboard:source:slideBack: is analogous to
> Windows's closed and drag source blocking DoDragDrop() API, rather
> than XDnD's flexible event-driven protocol.
Yes, it's analogous, although Cocoa's method is not blocking. It returns immediately. But we can build an internal event loop in the Mac driver. (The Cocoa stuff will happen on a different thread from the driver's implementation of DoDragDrop(), anyway.)
> But the worst problem with
> it isn't that it's closed, but rather its different and incompatible
> semantics: AFAICT, unlike in Windows where the drag source is an
> active participant in the drag with its QueryContinueDrag() method
> allowing cancelling the drop or dropping at the chosen time, the drag
> source callback methods in Cocoa are just passive observers with no
> possibility of cancelling the drop or choosing when to drop. It does
> not seem possible to implement DoDragDrop() correctly on top of that:
> the source will be forced to drop even if it doesn't want to, and
> can't willingly drop when it does want to.
Correct, we may not be able to implement all of the Windows semantics for the drag source. But that's true regardless of which approach we use to implement dragging from Wine to native on OS X. There's simply no way to get a drag to interact with a native drag destination without starting the native drag with this fairly closed API. At least, no way I know that's fully supported.
We can perhaps simulate some of the semantics with kludges. For example, the drag data could be promised rather than supplied in advance. If the Win32 drag source cancels early, we can't cancel the native drag but we can refuse to satisfy the request for the promised data.
We can't really force dropping programmatically.
There's another possible semantic we can't support. I assume that if the user presses Escape or releases the mouse button and the drop source does _not_ return DRAGDROP_S_CANCEL/DRAGDROP_S_DROP from QueryContinueDrag(), then the drag is supposed to continue. However, OS X will always end the drag, one way or another, when those things happen.
Still, a partial implementation is better than none, I think. We can also hope that few Windows apps force cancellation or dropping programmatically, anyway. As a user, if a drag spontaneously cancels itself for any reason other than my hitting Escape, that will be surprising and alarming. Likewise for a drag spontaneously dropping for any reason other than my releasing the mouse button or continuing after my releasing the button or pressing Escape. Since it would be a usability problem, hopefully it's not done in many cases.
If the limitations of the native drag implementation cause real problems, we could put in a registry setting to disable it and fall back to the ole32 implementation.
More information about the wine-devel