123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- https://bugs.kde.org/show_bug.cgi?id=484405
- https://bugreports.qt.io/browse/QTBUG-124386
- https://codereview.qt-project.org/c/qt/qtbase/+/556573
- https://github.com/qt/qtbase/commit/a8ef8ea55014546e0e835cd0eacf694919702a11
- From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= <tor.arne.vestbo@qt.io>
- Date: Wed, 24 Apr 2024 22:33:42 +0200
- Subject: [PATCH] Don't quit automatically via QEventLoopLocker if there are
- open windows
- As part of df359bcb703db5a8adbf14e88ba4ae0d54f0cfcd the semantics and
- interaction between QEventLoopLocker and QGuiApplication was changed,
- based on the assumption that these two mechanisms were independent
- and should not affect each other.
- This had a surprising regression where the use of QEventLoopLocker in
- combination with the QCoreApplication::isQuitLockEnabled() automatic
- quit would end up quitting the app, even if it had open windows, for
- example when the last job of some internal job queue finished.
- It could be argued that if the app has open windows that should not
- be closed, they should ignore the Close event, and that an application
- with running QEventLoopLocker jobs should maintain an active window
- showing the progress of those jobs, but still, this is regression
- that we want to fix.
- We now bail out if !lastWindowClosed() in QGuiApplication's
- canQuitAutomatically, which is triggered from QEventLoopLocker's
- isQuitLockEnabled() behavior. And we do so regardless of whether
- quitOnLastWindowClosed is set or not, as the latter property
- determines the behavior when closing a window, not the behavior
- when a QEventLoopLocker goes out of scope.
- Similarly, we now block quitting of the application when triggered
- by quitOnLastWindowClosed() if a QEventLoop is active, regardless of
- the isQuitLockEnabled(), as the latter property is determining
- whether we should trigger a quit, not whether we should block them.
- [ChangeLog][Important behavior changes] Fixed a regression where
- the last QEventLoopLocker going out of scope would quit the app,
- even if there were open windows, if quitOnLastWindowClosed was
- false.
- [ChangeLog][Important behavior changes] Fixed a regression where
- closing the last window would quit the app, even if there were
- active QEventLoopLockers, if isQuitLockEnabled was false.
- --- a/src/corelib/kernel/qcoreapplication.cpp
- +++ b/src/corelib/kernel/qcoreapplication.cpp
- @@ -1081,2 +1081,10 @@
-
- + 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.
- @@ -2083,3 +2091,9 @@
-
- - 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;
- --- a/src/corelib/kernel/qeventloop.cpp
- +++ b/src/corelib/kernel/qeventloop.cpp
- @@ -339,3 +339,7 @@
-
- - 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.
-
- --- a/src/gui/kernel/qguiapplication.cpp
- +++ b/src/gui/kernel/qguiapplication.cpp
- @@ -3677,5 +3677,9 @@
-
- - 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.
-
- @@ -3735,3 +3739,9 @@
- {
- - 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;
- --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
- +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
- @@ -1010,4 +1010,4 @@
- {
- - // 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);
- @@ -1025,4 +1025,36 @@
- {
- - // 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<QEventLoopLocker> 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<QEventLoopLocker> 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);
- @@ -1038,3 +1070,3 @@
- app.exec();
- - QCOMPARE(quitSpy.quits, 1);
- + QCOMPARE(quitSpy.quits, 0);
- }
|