Possible Qt bug? Weird Mac-specific drag-and-drop behavior
-
I have a dialog that accepts dropped files/folders. When it gets a drop, it pops up a modal dialog that the user can type a message into. Works fine on windows. On OS X (10.7.3) this is what happens when I drag a file or folder from Finder to my app:
- The popup opens and has focus but gets no keyboard events. In fact, keyboard events seem to be suppressed for the entire system (including terminal windows).
- After about 10 seconds, the file-dragging icon reappears from the point it was dropped and scurries back to finder, indicating a rejected drop operation. At this point the keyboard starts functioning normally.
- Overall, the behavior gives the appearance of hanging on the dropEvent until the system times out and cancels the transaction.
Now, I know what you're thinking: no, I am not exec()ing my popup from my dropEvent() function. Here is a simplified code snippet:
@void MyMainDialog::dragEnterEvent (QDragEnterEvent* ev)
{
ev->acceptProposedAction();
}void MyMainDialog::dropEvent (QDropEvent* ev)
{
ev->acceptProposedAction();
QTimer::singleShot(0, this, SLOT(slot_popup()));
}void MyMainDialog::slot_popup()
{
/*
* This dialog will not be opened in the same iteration
* of the application event loop that handled the QDropEvent.
/
QDialog dlg = new MyPopupDialog(this);
dlg->exec();
}@Now, here's where it gets interesting. If I show() the popup instead of exec() it, then there's no problem. If I make the QTimer 100ms instead of 0 then there's no problem. That suggests to me that there's something buggy about how the EventDispatcher interacts with system drop events on Mac (ie maybe having additional signals on the event queue prevents the dispatcher from returning control back to the OS from the dropEvent callback). Reinforcing this hunch is the following (partial) stack trace I get when I break in slot_popup():
#0 MyMainDialog::slot_popup (this=0x118a76b0)
#1 0x0072b9c0 in MyMainDialog::qt_static_metacall (_o=0x118a76b0, _c=QMetaObject::InvokeMetaMethod, _id=2, _a=0x118f61a0)
#2 0x04c05b64 in QMetaCallEvent::placeMetaCall (this=0x118ec940, object=0x118a76b0) at kernel/qobject.cpp:525
#3 0x04c08813 in QObject::event (this=0x118a76b0, e=0x118ec940) at kernel/qobject.cpp:1192
#4 0x03bbe6ac in QWidget::event (this=0x118a76b0, event=0x118ec940) at kernel/qwidget.cpp:8820
#5 0x03b58c16 in QApplicationPrivate::notify_helper (this=0x8c84760, receiver=0x118a76b0, e=0x118ec940) at kernel/qapplication.cpp:4550
#6 0x03b5bf9e in QApplication::notify (this=0xbffffb00, receiver=0x118a76b0, e=0x118ec940) at kernel/qapplication.cpp:4515
#7 0x04bf1b82 in QCoreApplication::notifyInternal (this=0xbffffb00, receiver=0x118a76b0, event=0x118ec940) at kernel/qcoreapplication.cpp:876
#8 0x04212484 in QCoreApplication::sendEvent (receiver=0x118a76b0, event=0x118ec940) at qcoreapplication.h:231
#9 0x04bf2014 in QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=0, data=0xa152f30) at kernel/qcoreapplication.cpp:1497
#10 0x03af6d48 in processPostedEvents (d=0x8c848a0, blockSendPostedEvents=false) at kernel/qeventdispatcher_mac.mm:1069
#11 0x03af6d6f in QEventDispatcherMacPrivate::postedEventsSourcePerformCallback (info=0x8c848a0) at kernel/qeventdispatcher_mac.mm:1087
#12 0x96c673df in CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION ()
#13 0x96c66d96 in __CFRunLoopDoSources0 ()
#14 0x96c90c68 in __CFRunLoopRun ()
#15 0x96c9047c in CFRunLoopRunSpecific ()
#16 0x96c90328 in CFRunLoopRunInMode ()
#17 0x92bb24e3 in -[NSRunLoop(NSRunLoop) runMode:beforeDate:] ()
#18 0x92c3ee76 in -[NSRunLoop(NSRunLoop) runUntilDate:] ()
#19 0x94dd4ffd in NSCoreDragReceiveMessageProc ()
#20 0x9865fa3a in CallReceiveMessageCollectionWithMessage ()
#21 0x9865fb54 in DoMultipartDropMessage ()
#22 0x9865fd9a in DoDropMessage ()Note specifically the frames with "DropMessage" in them - the dropEvent flow should definitely NOT still be in the stack by the time I get to this function. Moveover, they aren't there if I set the QTimer to larger values (and the problem doesn't manifest then).
I've tried all manner of tweaks to how I handle the dragEnter/Move/Drop events but the problem persists (and again, it works just fine on Windows). Is there something obvious I'm missing here? It's getting hard not to see this as a subtle platform-specific Qt bug. Anyone have any thoughts? [EDIT: btw, I'm using Qt 4.8.0]
-
You should "report a bug":http://bugreports.qt-project.org/.
-
Hi, did you find a solution to this issue? I can see this behaviour too in Qt 5.1.1 on OS X. It only seems to happen when popping up a dialog, even if it is started asynchronously via a single shot timer.
-
Seems that yes :)
https://bugreports.qt.io/browse/QTBUG-29701