diff options
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 171 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication_p.h | 9 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication_qpa.cpp | 23 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 23 |
4 files changed, 82 insertions, 144 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index a8b1fa6d1c..c560dba1b7 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -440,8 +440,6 @@ FontHash *qt_app_fonts_hash() QWidgetList *QApplicationPrivate::popupWidgets = 0; // has keyboard input focus QDesktopWidget *qt_desktopWidget = 0; // root window widgets -QWidgetList * qt_modal_stack = 0; // stack of modal widgets -bool app_do_modal = false; /*! \internal @@ -755,7 +753,8 @@ QWidget *QApplication::activePopupWidget() QWidget *QApplication::activeModalWidget() { - return qt_modal_stack && !qt_modal_stack->isEmpty() ? qt_modal_stack->first() : 0; + QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(modalWindow()); + return widgetWindow ? widgetWindow->widget() : 0; } /*! @@ -2315,31 +2314,52 @@ Q_WIDGETS_EXPORT bool qt_tryModalHelper(QWidget *widget, QWidget **rettop) bool QApplicationPrivate::isBlockedByModal(QWidget *widget) { widget = widget->window(); - if (!modalState()) + return self->isWindowBlocked(widget->windowHandle()); +} + +bool QApplicationPrivate::isWindowBlocked(QWindow *window, QWindow **blockingWindow) const +{ + QWindow *unused = 0; + if (!blockingWindow) + blockingWindow = &unused; + + if (modalWindowList.isEmpty()) { + *blockingWindow = 0; return false; - if (QApplication::activePopupWidget() == widget) + } + QWidget *popupWidget = QApplication::activePopupWidget(); + QWindow *popupWindow = popupWidget ? popupWidget->windowHandle() : 0; + if (popupWindow == window) { + *blockingWindow = 0; return false; + } - for (int i = 0; i < qt_modal_stack->size(); ++i) { - QWidget *modalWidget = qt_modal_stack->at(i); + for (int i = 0; i < modalWindowList.count(); ++i) { + QWindow *modalWindow = modalWindowList.at(i); { - // check if the active modal widget is our widget or a parent of our widget - QWidget *w = widget; + // check if the modal window is our window or a (transient) parent of our window + QWindow *w = window; while (w) { - if (w == modalWidget) + if (w == modalWindow) { + *blockingWindow = 0; return false; - w = w->parentWidget(); + } + QWindow *p = w->parent(); + if (!p) + p = w->transientParent(); + w = p; } } - Qt::WindowModality windowModality = modalWidget->windowModality(); + Qt::WindowModality windowModality = modalWindow->windowModality(); + QWidgetWindow *modalWidgetWindow = qobject_cast<QWidgetWindow *>(modalWindow); if (windowModality == Qt::NonModal) { // determine the modality type if it hasn't been set on the - // modalWidget, this normally happens when waiting for a - // native dialog. use WindowModal if we are the child of a - // group leader; otherwise use ApplicationModal. - QWidget *m = modalWidget; + // modalWindow's widget, this normally happens when waiting for a + // native dialog. use WindowModal if we are the child of a group + // leader; otherwise use ApplicationModal. + QWidget *m = modalWidgetWindow ? modalWidgetWindow->widget() : 0; while (m && !m->testAttribute(Qt::WA_GroupLeader)) { m = m->parentWidget(); if (m) @@ -2352,98 +2372,59 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget) switch (windowModality) { case Qt::ApplicationModal: - { - QWidget *groupLeaderForWidget = widget; - while (groupLeaderForWidget && !groupLeaderForWidget->testAttribute(Qt::WA_GroupLeader)) - groupLeaderForWidget = groupLeaderForWidget->parentWidget(); - - if (groupLeaderForWidget) { - // if \a widget has WA_GroupLeader, it can only be blocked by ApplicationModal children - QWidget *m = modalWidget; - while (m && m != groupLeaderForWidget && !m->testAttribute(Qt::WA_GroupLeader)) - m = m->parentWidget(); - if (m == groupLeaderForWidget) - return true; - } else if (modalWidget != widget) { + { + QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(window); + QWidget *groupLeaderForWidget = widgetWindow ? widgetWindow->widget() : 0; + while (groupLeaderForWidget && !groupLeaderForWidget->testAttribute(Qt::WA_GroupLeader)) + groupLeaderForWidget = groupLeaderForWidget->parentWidget(); + + if (groupLeaderForWidget) { + // if \a widget has WA_GroupLeader, it can only be blocked by ApplicationModal children + QWidget *m = modalWidgetWindow ? modalWidgetWindow->widget() : 0; + while (m && m != groupLeaderForWidget && !m->testAttribute(Qt::WA_GroupLeader)) + m = m->parentWidget(); + if (m == groupLeaderForWidget) { + *blockingWindow = m->windowHandle(); return true; } - break; + } else if (modalWindow != window) { + *blockingWindow = modalWindow; + return true; } + break; + } case Qt::WindowModal: - { - QWidget *w = widget; + { + QWindow *w = window; + do { + QWindow *m = modalWindow; do { - QWidget *m = modalWidget; - do { - if (m == w) - return true; - m = m->parentWidget(); - if (m) - m = m->window(); - } while (m); - w = w->parentWidget(); - if (w) - w = w->window(); - } while (w); - break; - } + if (m == w) { + *blockingWindow = m; + return true; + } + QWindow *p = m->parent(); + if (!p) + p = m->transientParent(); + m = p; + } while (m); + QWindow *p = w->parent(); + if (!p) + p = w->transientParent(); + w = p; + } while (w); + break; + } default: - Q_ASSERT_X(false, "QApplication", "internal error, a modal widget cannot be modeless"); + Q_ASSERT_X(false, "QApplication", "internal error, a modal window cannot be modeless"); break; } } + *blockingWindow = 0; return false; } /*!\internal - */ -void QApplicationPrivate::enterModal(QWidget *widget) -{ - QSet<QWidget*> blocked; - QList<QWidget*> windows = QApplication::topLevelWidgets(); - for (int i = 0; i < windows.count(); ++i) { - QWidget *window = windows.at(i); - if (window->windowType() != Qt::Tool && isBlockedByModal(window)) - blocked.insert(window); - } - - enterModal_sys(widget); - - windows = QApplication::topLevelWidgets(); - QEvent e(QEvent::WindowBlocked); - for (int i = 0; i < windows.count(); ++i) { - QWidget *window = windows.at(i); - if (!blocked.contains(window) && window->windowType() != Qt::Tool && isBlockedByModal(window)) - QApplication::sendEvent(window, &e); - } -} - -/*!\internal - */ -void QApplicationPrivate::leaveModal(QWidget *widget) -{ - QSet<QWidget*> blocked; - QList<QWidget*> windows = QApplication::topLevelWidgets(); - for (int i = 0; i < windows.count(); ++i) { - QWidget *window = windows.at(i); - if (window->windowType() != Qt::Tool && isBlockedByModal(window)) - blocked.insert(window); - } - - leaveModal_sys(widget); - - windows = QApplication::topLevelWidgets(); - QEvent e(QEvent::WindowUnblocked); - for (int i = 0; i < windows.count(); ++i) { - QWidget *window = windows.at(i); - if(blocked.contains(window) && window->windowType() != Qt::Tool && !isBlockedByModal(window)) - QApplication::sendEvent(window, &e); - } -} - - - -/*!\internal Called from qapplication_\e{platform}.cpp, returns true if the widget should accept the event. diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 74af3bca6d..8f67a29d84 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -198,10 +198,7 @@ public: static void dispatchEnterLeave(QWidget *enter, QWidget *leave); //modality - static void enterModal(QWidget*); - static void leaveModal(QWidget*); - static void enterModal_sys(QWidget*); - static void leaveModal_sys(QWidget*); + Q_DECL_OVERRIDE bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = 0) const; static bool isBlockedByModal(QWidget *widget); static bool modalState(); static bool tryModalHelper(QWidget *widget, QWidget **rettop = 0); @@ -279,10 +276,6 @@ public: static bool widgetCount; // Coupled with -widgetcount switch static bool load_testability; // Coupled with -testability switch -#ifdef Q_WS_MAC - static bool native_modal_dialog_active; -#endif - static void setSystemPalette(const QPalette &pal); static void setPalette_helper(const QPalette &palette, const char* className, bool clearWidgetPaletteHash); static void initializeWidgetPaletteHash(); diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp index bcea2676bc..92b831101f 100644 --- a/src/widgets/kernel/qapplication_qpa.cpp +++ b/src/widgets/kernel/qapplication_qpa.cpp @@ -75,8 +75,6 @@ QT_BEGIN_NAMESPACE static QString appName; static QString appFont; static bool popupGrabOk; -extern bool app_do_modal; -extern QWidgetList *qt_modal_stack; extern QWidget *qt_button_down; extern QWidget *qt_popup_down; extern bool qt_replay_popup_mouse_event; @@ -126,28 +124,9 @@ bool qt_try_modal(QWidget *widget, QEvent::Type type) return !block_event; } -void QApplicationPrivate::enterModal_sys(QWidget *widget) -{ - if (!qt_modal_stack) - qt_modal_stack = new QWidgetList; - qt_modal_stack->insert(0, widget); - app_do_modal = true; -} - -void QApplicationPrivate::leaveModal_sys(QWidget *widget) -{ - if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { - if (qt_modal_stack->isEmpty()) { - delete qt_modal_stack; - qt_modal_stack = 0; - } - } - app_do_modal = qt_modal_stack != 0; -} - bool QApplicationPrivate::modalState() { - return app_do_modal; + return !self->modalWindowList.isEmpty(); } QWidget *qt_tlw_for_window(QWindow *wnd) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index cccde764ad..70839e705f 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -7080,12 +7080,6 @@ void QWidgetPrivate::show_helper() QShowEvent showEvent; QApplication::sendEvent(q, &showEvent); - if (!isEmbedded && q->isModal() && q->isWindow()) - // QApplicationPrivate::enterModal *before* show, otherwise the initial - // stacking might be wrong - QApplicationPrivate::enterModal(q); - - show_sys(); if (!isEmbedded && q->windowType() == Qt::Popup) @@ -7141,12 +7135,6 @@ void QWidgetPrivate::hide_helper() if (!isEmbedded && (q->windowType() == Qt::Popup)) qApp->d_func()->closePopup(q); - // Move test modal here. Otherwise, a modal dialog could get - // destroyed and we lose all access to its parent because we haven't - // left modality. (Eg. modal Progress Dialog) - if (!isEmbedded && q->isModal() && q->isWindow()) - QApplicationPrivate::leaveModal(q); - #if defined(Q_WS_WIN) if (q->isWindow() && !(q->windowType() == Qt::Popup) && q->parentWidget() && !q->parentWidget()->isHidden() && q->isActiveWindow()) @@ -10047,9 +10035,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; case Qt::WA_ShowModal: if (!on) { - if (isVisible()) - QApplicationPrivate::leaveModal(this); - // reset modality type to Modeless when clearing WA_ShowModal + // reset modality type to NonModal when clearing WA_ShowModal data->window_modality = Qt::NonModal; } else if (data->window_modality == Qt::NonModal) { // determine the modality type if it hasn't been set prior @@ -10067,10 +10053,9 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) data->window_modality = (w && w->testAttribute(Qt::WA_GroupLeader)) ? Qt::WindowModal : Qt::ApplicationModal; - // Some window managers does not allow us to enter modal after the - // window is showing. Therefore, to be consistent, we cannot call - // QApplicationPrivate::enterModal(this) here. The window must be - // hidden before changing modality. + // Some window managers do not allow us to enter modality after the + // window is visible.The window must be hidden before changing the + // windowModality property and then reshown. } if (testAttribute(Qt::WA_WState_Created)) { // don't call setModal_sys() before create_sys() |