From eafca2229b007f53685fabe9a6217f0eb4c8b67f Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Fri, 25 Dec 2015 14:24:44 +0300 Subject: [PATCH] Allow to prevent blocking of native dialogs by a proxy Qt dialog When native dialogs become visible, their invisible proxy Qt dialog blocks input to Qt windows. It is intended for native dialogs which can't block Qt windows themselves, e.g. on Android. But this behavior is incompatible with native dialogs which are implemented as in-process Qt windows, because the proxy dialog blocks them as well. This change introduces QPlatformDialogHelper::DialogIsQtWindow style which allows to detect such cases and prevent blocking. Change-Id: I8f1f741e05d09f2c27192890bcec35fdd2e8f074 Task-number: QTBUG-58116 Reviewed-by: Alberto Mardegan Reviewed-by: David Faure --- src/gui/kernel/qplatformdialoghelper.cpp | 12 ++++++++++++ src/gui/kernel/qplatformdialoghelper.h | 1 + src/widgets/dialogs/qdialog.cpp | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index b787629f6a..6a0adca9ca 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -61,6 +61,18 @@ QT_BEGIN_NAMESPACE */ +/*! + \enum QPlatformDialogHelper::StyleHint + + This enum type specifies platform-specific style hints. + + \value DialogIsQtWindow Indicates that a platform-specific dialog is implemented + as in-process Qt window. It allows to prevent blocking the + dialog by an invisible proxy Qt dialog. + + \sa styleHint() +*/ + static const int buttonRoleLayouts[2][6][14] = { // Qt::Horizontal diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h index 2c050535d8..0832e19dc3 100644 --- a/src/gui/kernel/qplatformdialoghelper.h +++ b/src/gui/kernel/qplatformdialoghelper.h @@ -80,6 +80,7 @@ class Q_GUI_EXPORT QPlatformDialogHelper : public QObject Q_OBJECT public: enum StyleHint { + DialogIsQtWindow }; enum DialogCode { Rejected, Accepted }; diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index 06f0393b4c..cadd7ef031 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -731,6 +731,20 @@ void QDialog::setVisible(bool visible) if (!testAttribute(Qt::WA_DontShowOnScreen) && d->canBeNativeDialog() && d->setNativeDialogVisible(visible)) return; + // We should not block windows by the invisible modal dialog + // if a platform-specific dialog is implemented as an in-process + // Qt window, because in this case it will also be blocked. + const bool dontBlockWindows = testAttribute(Qt::WA_DontShowOnScreen) + && d->styleHint(QPlatformDialogHelper::DialogIsQtWindow).toBool(); + Qt::WindowModality oldModality; + bool wasModalitySet; + + if (dontBlockWindows) { + oldModality = windowModality(); + wasModalitySet = testAttribute(Qt::WA_SetWindowModality); + setWindowModality(Qt::NonModal); + } + if (visible) { if (testAttribute(Qt::WA_WState_ExplicitShowHide) && !testAttribute(Qt::WA_WState_Hidden)) return; @@ -797,6 +811,11 @@ void QDialog::setVisible(bool visible) d->eventLoop->exit(); } + if (dontBlockWindows) { + setWindowModality(oldModality); + setAttribute(Qt::WA_SetWindowModality, wasModalitySet); + } + #if QT_CONFIG(pushbutton) const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); if (d->mainDef && isActiveWindow()