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
