diff options
author | Mitch Curtis <mitch.curtis@qt.io> | 2021-01-11 17:03:21 +0100 |
---|---|---|
committer | Mitch Curtis <mitch.curtis@qt.io> | 2021-01-13 13:27:57 +0100 |
commit | 51d416cdfd909aacd5047632a7cc1661a158731a (patch) | |
tree | 9880e8ee8b2ce0cbe65645f6dddc3e4f2f067357 /src | |
parent | 4b66c0bd7de6063982459fe45f69278fd0519b1b (diff) |
Fix popups with exit transitions blocking mouse events when destroyed
If a popup had an exit transition set and was destroyed upon e.g.
being rejected, it would not destroy its modal dimmer, and so events
would not go through to popups that were beneath it even after it
was destroyed.
QQuickPopup's destructor does indirectly attempt to call
finalizeExitTransition() through a setParentItem(nullptr) call,
but prepareExitTransition() returns false if it sees that the
exit transition is already running, and so transitionExit()
never calls finished().
This patch fixes the problem by explicitly calling
finalizeExitTransition() in QQuickPopup's destructor if the exit
transition is running.
Fixes: QTBUG-89673
Pick-to: 5.15 6.0
Change-Id: I468fae52f6a83ac314877c67d062028634bb7e17
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/quicktemplates2/qquickpopup.cpp | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp index 455b0425..f54b610c 100644 --- a/src/quicktemplates2/qquickpopup.cpp +++ b/src/quicktemplates2/qquickpopup.cpp @@ -51,6 +51,8 @@ QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcDimmer, "qt.quick.controls.popup.dimmer") + /*! \qmltype Popup \inherits QtObject @@ -499,8 +501,10 @@ void QQuickPopupPrivate::finalizeExitTransition() { Q_Q(QQuickPopup); getPositioner()->setParentItem(nullptr); - popupItem->setParentItem(nullptr); - popupItem->setVisible(false); + if (popupItem) { + popupItem->setParentItem(nullptr); + popupItem->setVisible(false); + } destroyOverlay(); if (hadActiveFocusBeforeExitTransition && window) { @@ -531,8 +535,10 @@ void QQuickPopupPrivate::finalizeExitTransition() hadActiveFocusBeforeExitTransition = false; emit q->visibleChanged(); emit q->closed(); - popupItem->setScale(prevScale); - popupItem->setOpacity(prevOpacity); + if (popupItem) { + popupItem->setScale(prevScale); + popupItem->setOpacity(prevOpacity); + } } void QQuickPopupPrivate::opened() @@ -733,6 +739,8 @@ static QQuickItem *createDimmer(QQmlComponent *component, QQuickPopup *popup, QQ if (component) component->completeCreate(); } + qCDebug(lcDimmer) << "finished creating dimmer from component" << component + << "for popup" << popup << "with parent" << parent << "- item is:" << item; return item; } @@ -759,6 +767,7 @@ void QQuickPopupPrivate::createOverlay() void QQuickPopupPrivate::destroyOverlay() { if (dimmer) { + qCDebug(lcDimmer) << "destroying dimmer" << dimmer; dimmer->setParentItem(nullptr); dimmer->deleteLater(); dimmer = nullptr; @@ -857,6 +866,12 @@ QQuickPopup::~QQuickPopup() d->popupItem = nullptr; delete d->positioner; d->positioner = nullptr; + + // If the popup is destroyed before the exit transition finishes, + // the necessary cleanup (removing modal dimmers that block mouse events, + // emitting closed signal, etc.) won't happen. That's why we do it manually here. + if (d->transitionState == QQuickPopupPrivate::ExitTransition && d->transitionManager.isRunning()) + d->finalizeExitTransition(); } /*! |