path: root/src
diff options
authorRichard Moe Gustavsen <>2014-04-04 12:01:03 +0200
committerThe Qt Project <>2014-04-07 11:07:31 +0200
commitb8d0fac5a92984c432271530e2d3560ec0f1d442 (patch)
tree4cd14debc3e02196cf0163fb39762dac15d6ea91 /src
parente30ae1268f8e224369ff7841b90184c8694a86e7 (diff)
QGuiApplication: fix crash caused by posting fake mouse event
Since Qt expects a mouse press/release event to not change mouse position in the same event, QGuiApplicationPrivate::processMouseEvent will detect if a QWindowSystemInterfacePrivate::MouseEvent tries to do this and convert it to two events; one move and one press/release. The problem is that the extra mouse event gets posted. So if delivering the first event causes a flush in the event queue (which can easily happen if e.g calling processEvents), the second event will be processed before the first returns. On iOS we see a crash with DnD as result of this, since drag data gets deleted on mouse release, and returning back to a mouse move after that will cause dangling pointers. This patch will instead of posting the event, call the event handler recursively with the faked event as argument. That way a flush will not cause the "pending" event to be delivered. Change-Id: Id9d88053b4859083fedd666584815016d67ac51b Reviewed-by: Tor Arne Vestbø <> Reviewed-by: Laszlo Agocs <> Reviewed-by: Friedemann Kleint <>
Diffstat (limited to 'src')
1 files changed, 10 insertions, 6 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index f96bdc39a6..bdedc9d75f 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1609,14 +1609,17 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e)
QEvent::Type type;
- // move first
Qt::MouseButtons stateChange = e->buttons ^ buttons;
- const bool frameStrut = e->type == QWindowSystemInterfacePrivate::FrameStrutMouse;
if (e->globalPos != QGuiApplicationPrivate::lastCursorPosition && (stateChange != Qt::NoButton)) {
- QWindowSystemInterfacePrivate::MouseEvent * newMouseEvent =
- new QWindowSystemInterfacePrivate::MouseEvent(e->, e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers);
- QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(newMouseEvent); // just in case the move triggers a new event loop
- stateChange = Qt::NoButton;
+ // A mouse event should not change both position and buttons at the same time. Instead we
+ // should first send a move event followed by a button changed event. Since this is not the case
+ // with the current event, we fake a move-only event that we recurse and process first. This
+ // will update the global mouse position and cause the second event to be a button only event.
+ QWindowSystemInterfacePrivate::MouseEvent moveEvent(e->,
+ e->timestamp, e->type, e->localPos, e->globalPos, buttons, e->modifiers);
+ processMouseEvent(&moveEvent);
+ Q_ASSERT(e->globalPos == QGuiApplicationPrivate::lastCursorPosition);
+ // continue with processing mouse button change event
QWindow *window = e->;
@@ -1635,6 +1638,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
Qt::MouseButton button = Qt::NoButton;
bool doubleClick = false;
+ const bool frameStrut = e->type == QWindowSystemInterfacePrivate::FrameStrutMouse;
if (QGuiApplicationPrivate::lastCursorPosition != globalPoint) {
type = frameStrut ? QEvent::NonClientAreaMouseMove : QEvent::MouseMove;