qtbase-6.7.1-qeventlooplocker.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. https://bugs.kde.org/show_bug.cgi?id=484405
  2. https://bugreports.qt.io/browse/QTBUG-124386
  3. https://codereview.qt-project.org/c/qt/qtbase/+/556573
  4. https://github.com/qt/qtbase/commit/a8ef8ea55014546e0e835cd0eacf694919702a11
  5. From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= <tor.arne.vestbo@qt.io>
  6. Date: Wed, 24 Apr 2024 22:33:42 +0200
  7. Subject: [PATCH] Don't quit automatically via QEventLoopLocker if there are
  8. open windows
  9. As part of df359bcb703db5a8adbf14e88ba4ae0d54f0cfcd the semantics and
  10. interaction between QEventLoopLocker and QGuiApplication was changed,
  11. based on the assumption that these two mechanisms were independent
  12. and should not affect each other.
  13. This had a surprising regression where the use of QEventLoopLocker in
  14. combination with the QCoreApplication::isQuitLockEnabled() automatic
  15. quit would end up quitting the app, even if it had open windows, for
  16. example when the last job of some internal job queue finished.
  17. It could be argued that if the app has open windows that should not
  18. be closed, they should ignore the Close event, and that an application
  19. with running QEventLoopLocker jobs should maintain an active window
  20. showing the progress of those jobs, but still, this is regression
  21. that we want to fix.
  22. We now bail out if !lastWindowClosed() in QGuiApplication's
  23. canQuitAutomatically, which is triggered from QEventLoopLocker's
  24. isQuitLockEnabled() behavior. And we do so regardless of whether
  25. quitOnLastWindowClosed is set or not, as the latter property
  26. determines the behavior when closing a window, not the behavior
  27. when a QEventLoopLocker goes out of scope.
  28. Similarly, we now block quitting of the application when triggered
  29. by quitOnLastWindowClosed() if a QEventLoop is active, regardless of
  30. the isQuitLockEnabled(), as the latter property is determining
  31. whether we should trigger a quit, not whether we should block them.
  32. [ChangeLog][Important behavior changes] Fixed a regression where
  33. the last QEventLoopLocker going out of scope would quit the app,
  34. even if there were open windows, if quitOnLastWindowClosed was
  35. false.
  36. [ChangeLog][Important behavior changes] Fixed a regression where
  37. closing the last window would quit the app, even if there were
  38. active QEventLoopLockers, if isQuitLockEnabled was false.
  39. --- a/src/corelib/kernel/qcoreapplication.cpp
  40. +++ b/src/corelib/kernel/qcoreapplication.cpp
  41. @@ -1081,2 +1081,10 @@
  42. + When this property is \c true the release of the last remaining
  43. + QEventLoopLocker operating on the application will attempt to
  44. + quit the application.
  45. +
  46. + Note that attempting a quit may not necessarily result in the
  47. + application quitting, for example if there still are open windows,
  48. + or the QEvent::Quit event is ignored.
  49. +
  50. The default is \c true.
  51. @@ -2083,3 +2091,9 @@
  52. - if (quitLockEnabled && quitLockRef.loadRelaxed())
  53. + // The automatic quit functionality is triggered by
  54. + // both QEventLoopLocker and maybeLastWindowClosed.
  55. + // In either case, we don't want to quit if there
  56. + // are active QEventLoopLockers, even if quitLockEnabled
  57. + // is not enabled, as the property signals whether to
  58. + // trigger the automatic quit, not whether to block it.
  59. + if (quitLockRef.loadRelaxed())
  60. return false;
  61. --- a/src/corelib/kernel/qeventloop.cpp
  62. +++ b/src/corelib/kernel/qeventloop.cpp
  63. @@ -339,3 +339,7 @@
  64. - The application will quit when there are no more QEventLoopLockers operating on it.
  65. + The application will attempt to quit when there are no more QEventLoopLockers
  66. + operating on it, as long as QCoreApplication::isQuitLockEnabled() is \c true.
  67. +
  68. + Note that attempting a quit may not necessarily result in the application quitting,
  69. + if there for example are open windows, or the QEvent::Quit event is ignored.
  70. --- a/src/gui/kernel/qguiapplication.cpp
  71. +++ b/src/gui/kernel/qguiapplication.cpp
  72. @@ -3677,5 +3677,9 @@
  73. - If this property is \c true, the applications quits when the last visible
  74. - \l{Primary and Secondary Windows}{primary window} (i.e. top level window
  75. - with no transient parent) is closed.
  76. + If this property is \c true, the application will attempt to
  77. + quit when the last visible \l{Primary and Secondary Windows}{primary window}
  78. + (i.e. top level window with no transient parent) is closed.
  79. +
  80. + Note that attempting a quit may not necessarily result in the
  81. + application quitting, for example if there still are active
  82. + QEventLoopLocker instances, or the QEvent::Quit event is ignored.
  83. @@ -3735,3 +3739,9 @@
  84. {
  85. - if (quitOnLastWindowClosed && !lastWindowClosed())
  86. + // The automatic quit functionality is triggered by
  87. + // both QEventLoopLocker and maybeLastWindowClosed.
  88. + // Although the former is a QCoreApplication feature
  89. + // we don't want to quit the application when there
  90. + // are open windows, regardless of whether the app
  91. + // also quits automatically on maybeLastWindowClosed.
  92. + if (!lastWindowClosed())
  93. return false;
  94. --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
  95. +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp
  96. @@ -1010,4 +1010,4 @@
  97. {
  98. - // Disabling QEventLoopLocker support should not affect
  99. - // quitting when last window is closed.
  100. + // Disabling QEventLoopLocker automatic quit should not affect
  101. + // quitting when last window is closed if there are no lockers.
  102. app.setQuitLockEnabled(false);
  103. @@ -1025,4 +1025,36 @@
  104. {
  105. - // Disabling quitOnLastWindowClosed support should not affect
  106. - // quitting when last QEventLoopLocker goes out of scope.
  107. + // Disabling QEventLoopLocker automatic quit should still block
  108. + // quitting when last window is closed if there is a locker alive.
  109. + app.setQuitLockEnabled(false);
  110. +
  111. + QScopedPointer<QEventLoopLocker> locker(new QEventLoopLocker);
  112. +
  113. + QuitSpy quitSpy;
  114. + QWindow window;
  115. + window.show();
  116. + QVERIFY(QTest::qWaitForWindowExposed(&window));
  117. + QTimer::singleShot(0, &window, &QWindow::close);
  118. + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); });
  119. + app.exec();
  120. + QCOMPARE(quitSpy.quits, 0);
  121. + }
  122. +
  123. + {
  124. + // Disabling quitOnLastWindowClosed automatic quit should not affect
  125. + // quitting when last QEventLoopLocker goes out of scope if
  126. + // there are no windows.
  127. + app.setQuitLockEnabled(true);
  128. + app.setQuitOnLastWindowClosed(false);
  129. +
  130. + QuitSpy quitSpy;
  131. + QScopedPointer<QEventLoopLocker> locker(new QEventLoopLocker);
  132. + QTimer::singleShot(0, [&]{ locker.reset(nullptr); });
  133. + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); });
  134. + app.exec();
  135. + QCOMPARE(quitSpy.quits, 1);
  136. + }
  137. +
  138. + {
  139. + // Disabling quitOnLastWindowClosed automatic quit should still block
  140. + // quitting via QEventLoopLocker if there's a window alive.
  141. app.setQuitLockEnabled(true);
  142. @@ -1038,3 +1070,3 @@
  143. app.exec();
  144. - QCOMPARE(quitSpy.quits, 1);
  145. + QCOMPARE(quitSpy.quits, 0);
  146. }