diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 1ce2642cf2d..5a1ad13b603 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1079,6 +1079,14 @@ bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute) \brief Whether the use of the QEventLoopLocker feature can cause the application to quit. + When this property is \c true the release of the last remaining + QEventLoopLocker operating on the application will attempt to + quit the application. + + Note that attempting a quit may not necessarily result in the + application quitting, for example if there still are open windows, + or the QEvent::Quit event is ignored. + The default is \c true. \sa QEventLoopLocker @@ -2081,7 +2089,13 @@ bool QCoreApplicationPrivate::canQuitAutomatically() if (!in_exec) return false; - if (quitLockEnabled && quitLockRef.loadRelaxed()) + // The automatic quit functionality is triggered by + // both QEventLoopLocker and maybeLastWindowClosed. + // In either case, we don't want to quit if there + // are active QEventLoopLockers, even if quitLockEnabled + // is not enabled, as the property signals whether to + // trigger the automatic quit, not whether to block it. + if (quitLockRef.loadRelaxed()) return false; return true; diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp index dcd5f6d5c07..47ab7663542 100644 --- a/src/corelib/kernel/qeventloop.cpp +++ b/src/corelib/kernel/qeventloop.cpp @@ -337,7 +337,11 @@ static_assert(alignof(QCoreApplication) >= 4); /*! Creates an event locker operating on the QCoreApplication. - The application will quit when there are no more QEventLoopLockers operating on it. + The application will attempt to quit when there are no more QEventLoopLockers + operating on it, as long as QCoreApplication::isQuitLockEnabled() is \c true. + + Note that attempting a quit may not necessarily result in the application quitting, + if there for example are open windows, or the QEvent::Quit event is ignored. \sa QCoreApplication::quit(), QCoreApplication::isQuitLockEnabled() */ diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 86f4e5fdea0..af28f083a3a 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -3675,9 +3675,13 @@ void QGuiApplicationPrivate::notifyWindowIconChanged() The default is \c true. - If this property is \c true, the applications quits when the last visible - \l{Primary and Secondary Windows}{primary window} (i.e. top level window - with no transient parent) is closed. + If this property is \c true, the application will attempt to + quit when the last visible \l{Primary and Secondary Windows}{primary window} + (i.e. top level window with no transient parent) is closed. + + Note that attempting a quit may not necessarily result in the + application quitting, for example if there still are active + QEventLoopLocker instances, or the QEvent::Quit event is ignored. \sa quit(), QWindow::close() */ @@ -3733,7 +3737,13 @@ bool QGuiApplicationPrivate::lastWindowClosed() const bool QGuiApplicationPrivate::canQuitAutomatically() { - if (quitOnLastWindowClosed && !lastWindowClosed()) + // The automatic quit functionality is triggered by + // both QEventLoopLocker and maybeLastWindowClosed. + // Although the former is a QCoreApplication feature + // we don't want to quit the application when there + // are open windows, regardless of whether the app + // also quits automatically on maybeLastWindowClosed. + if (!lastWindowClosed()) return false; return QCoreApplicationPrivate::canQuitAutomatically(); diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index 2fef1797892..38a6a311fc3 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -1008,8 +1008,8 @@ void tst_QGuiApplication::quitOnLastWindowClosedWithEventLoopLocker() }); { - // Disabling QEventLoopLocker support should not affect - // quitting when last window is closed. + // Disabling QEventLoopLocker automatic quit should not affect + // quitting when last window is closed if there are no lockers. app.setQuitLockEnabled(false); QuitSpy quitSpy; @@ -1023,8 +1023,40 @@ void tst_QGuiApplication::quitOnLastWindowClosedWithEventLoopLocker() } { - // Disabling quitOnLastWindowClosed support should not affect - // quitting when last QEventLoopLocker goes out of scope. + // Disabling QEventLoopLocker automatic quit should still block + // quitting when last window is closed if there is a locker alive. + app.setQuitLockEnabled(false); + + QScopedPointer locker(new QEventLoopLocker); + + QuitSpy quitSpy; + QWindow window; + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTimer::singleShot(0, &window, &QWindow::close); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 0); + } + + { + // Disabling quitOnLastWindowClosed automatic quit should not affect + // quitting when last QEventLoopLocker goes out of scope if + // there are no windows. + app.setQuitLockEnabled(true); + app.setQuitOnLastWindowClosed(false); + + QuitSpy quitSpy; + QScopedPointer locker(new QEventLoopLocker); + QTimer::singleShot(0, [&]{ locker.reset(nullptr); }); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 1); + } + + { + // Disabling quitOnLastWindowClosed automatic quit should still block + // quitting via QEventLoopLocker if there's a window alive. app.setQuitLockEnabled(true); app.setQuitOnLastWindowClosed(false); @@ -1036,7 +1068,7 @@ void tst_QGuiApplication::quitOnLastWindowClosedWithEventLoopLocker() QTimer::singleShot(0, [&]{ locker.reset(nullptr); }); QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); app.exec(); - QCOMPARE(quitSpy.quits, 1); + QCOMPARE(quitSpy.quits, 0); } {