@@ -0,0 +1,159 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
@@ -100,6 +100,7 @@
|
|||||||
<!-- <Patch level="1">fedora/qtbase-firebird.patch</Patch> -->
|
<!-- <Patch level="1">fedora/qtbase-firebird.patch</Patch> -->
|
||||||
<Patch level="1">fedora/qtbase-mysql.patch</Patch>
|
<Patch level="1">fedora/qtbase-mysql.patch</Patch>
|
||||||
<Patch level="1">fedora/qtbase-libglvnd.patch</Patch>
|
<Patch level="1">fedora/qtbase-libglvnd.patch</Patch>
|
||||||
|
<Patch level="1">qtbase-6.7.1-qeventlooplocker.patch</Patch>
|
||||||
</Patches>
|
</Patches>
|
||||||
</Source>
|
</Source>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user