From a1ba8b726ec520487d2607de82b22487f4a1fd91 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Mon, 10 Oct 2022 14:25:45 +0200 Subject: [PATCH] Allow programmatic closing of windows that are modally blocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Qt 6, after changes such as 121fddcf5ae2ab238ef802e44b45ce62c56015f5, we go through the QPA layer to close widget windows properly. Closing and hiding of windows is now done in when we receive and handle the window system's CloseEvent. Such an event to a modally blocked window should be blocked, so that users can't close a modally blocked window. However, if the event is the result of a call to QWindow::close, then it should not be blocked. Luckily, we know that the event is the result of such a call, so let such events through. This restores compatibility with Qt 5, where it was possible to first open a new dialog, and then close the previous dialog. Add a test case. Fixes: QTBUG-107188 Change-Id: Id812c1fc36aa0e1a10dfb8d3a16a11d387289b05 Reviewed-by: Axel Spoerl Reviewed-by: Shawn Rutledge Reviewed-by: Tor Arne Vestbø Reviewed-by: Qt CI Bot (cherry picked from commit cdadd1bdb3f0137659f0f82b06628d0b20b858e3) Reviewed-by: Qt Cherry-pick Bot --- src/gui/kernel/qguiapplication.cpp | 5 +++-- tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index d12b93f9e61..da513408dbb 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2629,8 +2629,9 @@ void QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::Cl { if (e->window.isNull()) return; - if (e->window.data()->d_func()->blockedByModalWindow) { - // a modal window is blocking this window, don't allow close events through + if (e->window.data()->d_func()->blockedByModalWindow && !e->window.data()->d_func()->inClose) { + // a modal window is blocking this window, don't allow close events through, unless they + // originate from a call to QWindow::close. return; } diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index b995b3fb77c..bb0f9817c3a 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -70,6 +70,7 @@ private slots: void modalWithChildWindow(); void modalWindowModallity(); void modalWindowPosition(); + void modalCloseWhileBlocked(); #ifndef QT_NO_CURSOR void modalWindowEnterEventOnHide_QTBUG35109(); void spuriousMouseMove(); @@ -2250,6 +2251,22 @@ void tst_QWindow::modalWindowPosition() QCOMPARE(window.geometry(), origGeo); } +void tst_QWindow::modalCloseWhileBlocked() +{ + QWindow first; + first.setModality(Qt::ApplicationModal); + first.show(); + QVERIFY(QTest::qWaitForWindowExposed(&first)); + + QWindow second; + second.setModality(Qt::ApplicationModal); + second.show(); + QVERIFY(QTest::qWaitForWindowExposed(&first)); + + first.close(); + QTRY_VERIFY(!first.isVisible()); +} + #ifndef QT_NO_CURSOR void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109() {