diff options
author | Morten Johan Sørvig <morten.sorvig@qt.io> | 2018-04-24 12:46:44 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-04-24 18:38:00 +0000 |
commit | 127659c45020a83b80eeed7106c1f377a36c5c77 (patch) | |
tree | 101acd9d0d36da0a2d64f2b8eb172f3af90ef16c /src/quick/items/qquickwindow.cpp | |
parent | 913dc3f4f2be7c2c23237bcb9bffb3192cb10d60 (diff) |
QQuickWindow: Don’t crash on events during destruction
Deleting d->contentItem may call into the platform
plugin, for example if the contentItem is a Window. This
can again make the platform (plugin) generate events
for the QQuickWindow that is being destroyed. The QQuickWindow
may try to use the now invalid d->contentItem during
event processing, and crash.
This is especially prone to happening if/when the platform
plugin does less queuing of events, for example on macOS
after commit ed483346.
Fix this by clearing the d->contentItem pointer before
deleting it. Also make sure all d->contentItem accesses
have nullptr checks.
Task-number: QTBUG-67802
Change-Id: Ieff97711fbe15818948d4b6ade069b096a55c683
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/quick/items/qquickwindow.cpp')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 48eba6a7a0..b0b747a5eb 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -256,14 +256,16 @@ void QQuickWindow::hideEvent(QHideEvent *) void QQuickWindow::focusOutEvent(QFocusEvent *ev) { Q_D(QQuickWindow); - d->contentItem->setFocus(false, ev->reason()); + if (d->contentItem) + d->contentItem->setFocus(false, ev->reason()); } /*! \reimp */ void QQuickWindow::focusInEvent(QFocusEvent *ev) { Q_D(QQuickWindow); - d->contentItem->setFocus(true, ev->reason()); + if (d->contentItem) + d->contentItem->setFocus(true, ev->reason()); d->updateFocusItemTransform(); } @@ -1315,7 +1317,9 @@ QQuickWindow::~QQuickWindow() #if QT_CONFIG(draganddrop) delete d->dragGrabber; d->dragGrabber = nullptr; #endif - delete d->contentItem; d->contentItem = nullptr; + QQuickRootItem *root = d->contentItem; + d->contentItem = nullptr; + delete root; qDeleteAll(d->pointerEventInstances); d->pointerEventInstances.clear(); @@ -1571,6 +1575,8 @@ bool QQuickWindow::event(QEvent *e) return d->deliverTouchCancelEvent(static_cast<QTouchEvent*>(e)); break; case QEvent::Enter: { + if (!d->contentItem) + return false; QEnterEvent *enter = static_cast<QEnterEvent*>(e); bool accepted = enter->isAccepted(); bool delivered = d->deliverHoverEvent(d->contentItem, enter->windowPos(), d->lastMousePosition, @@ -1592,7 +1598,8 @@ bool QQuickWindow::event(QEvent *e) break; #endif case QEvent::WindowDeactivate: - contentItem()->windowDeactivateEvent(); + if (d->contentItem) + d->contentItem->windowDeactivateEvent(); break; case QEvent::Close: { // TOOD Qt 6 (binary incompatible) @@ -1617,7 +1624,8 @@ bool QQuickWindow::event(QEvent *e) } #if QT_CONFIG(gestures) case QEvent::NativeGesture: - d->deliverNativeGestureEvent(d->contentItem, static_cast<QNativeGestureEvent*>(e)); + if (d->contentItem) + d->deliverNativeGestureEvent(d->contentItem, static_cast<QNativeGestureEvent*>(e)); break; #endif case QEvent::ShortcutOverride: @@ -1937,7 +1945,8 @@ void QQuickWindow::wheelEvent(QWheelEvent *event) return; event->ignore(); - d->deliverWheelEvent(d->contentItem, event); + if (d->contentItem) + d->deliverWheelEvent(d->contentItem, event); d->lastWheelEventAccepted = event->isAccepted(); } #endif // wheelevent |