diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2021-10-12 15:25:26 +0200 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2021-10-16 14:33:28 +0200 |
commit | 1dfc74970c8ab0bfc210b7038aad401189eae542 (patch) | |
tree | a85b88588e11a181ae97ee2e3aedef4bd452f8c7 /src/gui/kernel/qguiapplication.cpp | |
parent | 30404b49d8cc9ad8c4d9f128952844c20da0ad0d (diff) |
Deduplicate lastWindowClosed handling
Whenever a window was closed, we had logic to check if it was the last
window, and if so emitted lastWindowClosed and then tried to quit the
application. But the automatic quit process also checked if there were
any remaining windows, as this process could be triggered as a result
of a QEventLoopLocker going out of scope. The two paths now share the
same logic for determining if there are any remaining windows.
The docs have been updated to reflect the original intent of the logic,
dealing only with primary windows (top levels without a transient parent).
This was how both the original code paths implemented their logic.
For historical reasons the Qt::WA_QuitOnClose attribute is closely
tied to the lastWindowClosed signal, and isn't merely limited to
controlling whether we try an automatic quit when the last window
closes. For now this behavior has been kept, but the docs have been
updated to clarify how the attribute is handled in practice.
Change-Id: If3d06b065236aad2e59e9091cac3146bc4cf79f6
Reviewed-by: Doris Verria <doris.verria@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/gui/kernel/qguiapplication.cpp')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 50 |
1 files changed, 24 insertions, 26 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 86ec5ad7b5..2ca1ff0a44 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1930,7 +1930,7 @@ bool QGuiApplication::notify(QObject *object, QEvent *event) bool accepted = QCoreApplication::notify(object, event); if (event->type() == QEvent::Close && object->isWindowType() && accepted) - d->maybeQuitOnLastWindowClosed(static_cast<QWindow*>(object)); + d->maybeLastWindowClosed(static_cast<QWindow*>(object)); return accepted; } @@ -3530,7 +3530,8 @@ void QGuiApplicationPrivate::notifyWindowIconChanged() The default is \c true. If this property is \c true, the applications quits when the last visible - primary window (i.e. window with no parent) is closed. + \l{Primary and Secondary Windows}{primary window} (i.e. top level window + with no transient parent) is closed. \sa quit(), QWindow::close() */ @@ -3545,19 +3546,17 @@ bool QGuiApplication::quitOnLastWindowClosed() return QCoreApplication::isQuitLockEnabled(); } -void QGuiApplicationPrivate::maybeQuitOnLastWindowClosed(QWindow *closedWindow) +void QGuiApplicationPrivate::maybeLastWindowClosed(QWindow *closedWindow) { Q_ASSERT(closedWindow); - if (!qt_window_private(closedWindow)->shouldTriggerQuitOnClose()) + // Only windows that themselves participates in last-window-closed + // should be allowed to trigger lastWindowClosed. + if (!qt_window_private(closedWindow)->participatesInLastWindowClosed()) return; - // Check if there are any remaining windows that should prevent us from quitting - for (auto *topLevelWindow : QGuiApplication::topLevelWindows()) { - auto *windowPrivate = qt_window_private(topLevelWindow); - if (windowPrivate->shouldCancelQuitOnClose()) - return; - } + if (!lastWindowClosed()) + return; if (in_exec) emit q_func()->lastWindowClosed(); @@ -3570,32 +3569,31 @@ void QGuiApplicationPrivate::maybeQuitOnLastWindowClosed(QWindow *closedWindow) \fn void QGuiApplication::lastWindowClosed() This signal is emitted from exec() when the last visible - primary window (i.e. window with no parent) is closed. + \l{Primary and Secondary Windows}{primary window} (i.e. + top level window with no transient parent) is closed. By default, QGuiApplication quits after this signal is emitted. This feature can be turned off by setting \l quitOnLastWindowClosed to \c false. - \sa QWindow::close(), QWindow::isTopLevel() + \sa QWindow::close(), QWindow::isTopLevel(), QWindow::transientParent() */ -bool QGuiApplicationPrivate::shouldQuit() +bool QGuiApplicationPrivate::lastWindowClosed() const { - const QWindowList processedWindows; - return shouldQuitInternal(processedWindows); + for (auto *window : QGuiApplication::topLevelWindows()) { + if (!qt_window_private(window)->participatesInLastWindowClosed()) + continue; + + if (window->isVisible()) + return false; + } + + return true; } -bool QGuiApplicationPrivate::shouldQuitInternal(const QWindowList &processedWindows) +bool QGuiApplicationPrivate::shouldQuit() { - /* if there is no visible top-level window left, we allow the quit */ - QWindowList list = QGuiApplication::topLevelWindows(); - for (int i = 0; i < list.size(); ++i) { - QWindow *w = list.at(i); - if (processedWindows.contains(w)) - continue; - if (w->isVisible() && !w->transientParent()) - return false; - } - return true; + return lastWindowClosed(); } void QGuiApplicationPrivate::quit() |