I've been working on a Qt app that uses drag-and-drop (Xdnd) between
multiple windows.  When the pointer leaves one window and enters another
(or even re-enters the original window), Qt sometimes gets confused.

There is some code at the end of HandleClientMessage() that forwards
ClientMessage events on to the client window.  It's marked with a
comments that says "I'm not so sure this should be done or not, since
every other window manager I've looked at doesn't."  If I comment out
that code, drag-and-drop works perfectly.

This is with Qt 2.5.28 (though I was originally using 2.5.4, and it
behaved identically - so it's not a new problem).

I looked at the Qt source code a little bit.  If Qt is going to send an
Xdnd event (XdndLeave, XdndEnter, etc.), and the target is another Qt
widget in the same process, it simply calls its own internal event
handler function instead of calling XSendEvent.  When the mouse pointer
moves over an fvwm window frame, Qt uses XSendEvent to send XdndEnter
and XdndLeave ClientMessages (because it doesn't recognize the window ID
as corresponding to a Qt widget).  Fvwm forwards those back to the
application, but now with the window ID of the main window, which Qt
does recognize.  My guess is that some reordering happens between the
messages sent via XSendEvent and the messages sent directly to Qt's
internal event handler, and that's what is causing the problems.

I'm really not sure whether this is a Qt bug or an fvwm bug (and I'm not
entirely sure that my analysis is correct).  But, given the comment in
the fvwm code, I'm wondering if it would make sense to remove that code.
(I tried hacking the Qt source code, and failed to make it work.)

If anyone wants to look at this, here's how to reproduce it: start with
the "fridgemagnets" example code from Qt 4.5.2 or 4.5.3 (it's in
examples/draganddrop/fridgemagnets).  Run the program and try dragging a
tile out of the window and then back into it.  Note that sometimes the
drop works (the tile moves where it's dropped) and sometimes not (the
tile snaps back to its old position - same behavior as when it's dropped
outside the window).  If you add an implementation for
DragWidget::dragLeaveEvent, and put printfs in both dragEnterEvent and
dragLeaveEvent, you'll be able to see spurious dragLeaveEvents showing
up.

- Derek


Reply via email to