diff options
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 59 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 5 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 70 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication_p.h | 3 |
4 files changed, 42 insertions, 95 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 7887db8534..0814339150 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -852,6 +852,17 @@ void QGuiApplicationPrivate::hideModalWindow(QWindow *window) } } +Qt::WindowModality QGuiApplicationPrivate::defaultModality() const +{ + return Qt::NonModal; +} + +bool QGuiApplicationPrivate::windowNeverBlocked(QWindow *window) const +{ + Q_UNUSED(window); + return false; +} + /* Returns \c true if \a window is blocked by a modal window. If \a blockingWindow is non-zero, *blockingWindow will be set to the blocking @@ -859,49 +870,40 @@ void QGuiApplicationPrivate::hideModalWindow(QWindow *window) */ bool QGuiApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWindow) const { + Q_ASSERT_X(window, Q_FUNC_INFO, "The window must not be null"); + QWindow *unused = nullptr; if (!blockingWindow) blockingWindow = &unused; + *blockingWindow = nullptr; - if (modalWindowList.isEmpty()) { - *blockingWindow = nullptr; + if (modalWindowList.isEmpty() || windowNeverBlocked(window)) return false; - } for (int i = 0; i < modalWindowList.count(); ++i) { QWindow *modalWindow = modalWindowList.at(i); // A window is not blocked by another modal window if the two are // the same, or if the window is a child of the modal window. - if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) { - *blockingWindow = nullptr; + if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) return false; - } - Qt::WindowModality windowModality = modalWindow->modality(); - switch (windowModality) { + switch (modalWindow->modality() == Qt::NonModal ? defaultModality() + : modalWindow->modality()) { case Qt::ApplicationModal: - { - if (modalWindow != window) { - *blockingWindow = modalWindow; - return true; - } - break; - } - case Qt::WindowModal: - { - QWindow *w = window; + *blockingWindow = modalWindow; + return true; + case Qt::WindowModal: { + // Find the nearest ancestor of window which is also an ancestor of modal window to + // determine if the modal window blocks the window. + auto *current = window; do { - QWindow *m = modalWindow; - do { - if (m == w) { - *blockingWindow = m; - return true; - } - m = m->parent(QWindow::IncludeTransients); - } while (m); - w = w->parent(QWindow::IncludeTransients); - } while (w); + if (current->isAncestorOf(modalWindow, QWindow::IncludeTransients)) { + *blockingWindow = current; + return true; + } + current = current->parent(QWindow::IncludeTransients); + } while (current); break; } default: @@ -909,7 +911,6 @@ bool QGuiApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blocking break; } } - *blockingWindow = nullptr; return false; } diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 3b30c14dbe..8309e2bfa7 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -188,7 +188,10 @@ public: static void showModalWindow(QWindow *window); static void hideModalWindow(QWindow *window); static void updateBlockedStatus(QWindow *window); - virtual bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const; + + virtual Qt::WindowModality defaultModality() const; + virtual bool windowNeverBlocked(QWindow *window) const; + bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const; virtual bool popupActive() { return false; } virtual bool closeAllPopups() { return false; } diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index a075182969..ea2e53867f 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2170,74 +2170,16 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget) return window && self->isWindowBlocked(window); } -bool QApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWindow) const +Qt::WindowModality QApplicationPrivate::defaultModality() const { - QWindow *unused = nullptr; - if (Q_UNLIKELY(!window)) { - qWarning().nospace() << "window == 0 passed."; - return false; - } - if (!blockingWindow) - blockingWindow = &unused; + return Qt::ApplicationModal; +} - if (modalWindowList.isEmpty()) { - *blockingWindow = nullptr; - return false; - } +bool QApplicationPrivate::windowNeverBlocked(QWindow *window) const +{ QWidget *popupWidget = QApplication::activePopupWidget(); QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : nullptr; - if (popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup())) { - *blockingWindow = nullptr; - return false; - } - - for (int i = 0; i < modalWindowList.count(); ++i) { - QWindow *modalWindow = modalWindowList.at(i); - - // A window is not blocked by another modal window if the two are - // the same, or if the window is a child of the modal window. - if (window == modalWindow || modalWindow->isAncestorOf(window, QWindow::IncludeTransients)) { - *blockingWindow = nullptr; - return false; - } - - Qt::WindowModality windowModality = modalWindow->modality(); - if (windowModality == Qt::NonModal) { - // If modality type hasn't been set on the modalWindow's widget, as - // when waiting for a native dialog, use ApplicationModal. - windowModality = Qt::ApplicationModal; - } - - switch (windowModality) { - case Qt::ApplicationModal: - if (modalWindow != window) { - *blockingWindow = modalWindow; - return true; - } - break; - case Qt::WindowModal: - { - QWindow *w = window; - do { - QWindow *m = modalWindow; - do { - if (m == w) { - *blockingWindow = m; - return true; - } - m = m->parent(QWindow::IncludeTransients); - } while (m); - w = w->parent(QWindow::IncludeTransients); - } while (w); - break; - } - default: - Q_ASSERT_X(false, "QApplication", "internal error, a modal window cannot be modeless"); - break; - } - } - *blockingWindow = nullptr; - return false; + return popupWindow == window || (!popupWindow && QWindowPrivate::get(window)->isPopup()); } /*!\internal diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 6d80201d62..4be35320d9 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -84,7 +84,8 @@ public: #endif //modality - bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const override; + Qt::WindowModality defaultModality() const override; + bool windowNeverBlocked(QWindow *window) const override; static bool isBlockedByModal(QWidget *widget); static bool modalState(); static bool tryModalHelper(QWidget *widget, QWidget **rettop = nullptr); |