From b46189c3c3a92c9093bd05bf976b2e7a368511a3 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 26 Apr 2012 13:32:14 +0200 Subject: Support all modality types in QPlatformDialogHelper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Modality is not a boolean property in Qt. There are 2 types: window modality and application modality. Native dialogs can support both of these types as well (e.g. on Cocoa, a window modal file dialog should be displayed as a Sheet). Remove the QPlatformDialogHelper::ShowFlags enum and instead pass a Qt::WindowModality parameter to QPlatformDialogHelper::show_sys(). The Windows implementation has been updated to check for Qt::ApplicationModal instead of the ShowModal flag (since only Qt::ApplicationModal dialogs are blocking). The Cocoa implementation has been updated to only use non-modal and application modal native color and font dialogs (which restores Qt 4 behavior). These are shared Cocoa panels that cannot be shown as sheets, however. If the programmer asks for window modal color/font dialogs, we use the Qt versions, not the native ones. The file dialog can be shown either as a Sheet (but we need to pass an NSWindow parent for it to work properly) or as an application modal dialog. This change has been tested on Mac OS X with tests/manual/windowmodality. Change-Id: I9064987433895c55f68aac979ef8e8207fb24bbe Reviewed-by: Friedemann Kleint Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qplatformdialoghelper_qpa.h | 9 ++------- .../platforms/cocoa/qcocoacolordialoghelper.h | 4 ++-- .../platforms/cocoa/qcocoacolordialoghelper.mm | 14 ++++++++++---- src/plugins/platforms/cocoa/qcocoafiledialoghelper.h | 4 ++-- .../platforms/cocoa/qcocoafiledialoghelper.mm | 20 ++++++++++---------- src/plugins/platforms/cocoa/qcocoafontdialoghelper.h | 4 ++-- .../platforms/cocoa/qcocoafontdialoghelper.mm | 14 ++++++++++---- .../platforms/windows/qwindowsdialoghelpers.cpp | 6 +++--- .../platforms/windows/qwindowsdialoghelpers.h | 4 ++-- src/widgets/dialogs/qdialog.cpp | 6 ++---- 10 files changed, 45 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/gui/kernel/qplatformdialoghelper_qpa.h b/src/gui/kernel/qplatformdialoghelper_qpa.h index 80a9f0efaf..5cd3ab055b 100644 --- a/src/gui/kernel/qplatformdialoghelper_qpa.h +++ b/src/gui/kernel/qplatformdialoghelper_qpa.h @@ -84,11 +84,6 @@ public: SnapToDefaultButton }; enum DialogCode { Rejected, Accepted }; - enum ShowFlag { - ShowModal = 0x00000001 - }; - - Q_DECLARE_FLAGS(ShowFlags, ShowFlag) QPlatformDialogHelper(); virtual ~QPlatformDialogHelper(); @@ -99,8 +94,8 @@ public: virtual void _q_platformRunNativeAppModalPanel() = 0; virtual void deleteNativeDialog_sys() = 0; - virtual bool show_sys(ShowFlags showFlags, - Qt::WindowFlags windowFlags, + virtual bool show_sys(Qt::WindowFlags windowFlags, + Qt::WindowModality windowModality, QWindow *parent) = 0; virtual void hide_sys() = 0; diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h index 505fd4f111..4b901f3ef3 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h @@ -56,7 +56,7 @@ public: void platformNativeDialogModalHelp(); void _q_platformRunNativeAppModalPanel(); void deleteNativeDialog_sys(); - bool show_sys(QFlags, Qt::WindowFlags, QWindow*); + bool show_sys(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent); void hide_sys(); DialogCode dialogResultCode_sys(); @@ -64,7 +64,7 @@ public: QColor currentColor_sys() const; public: - bool showCocoaColorPanel(QWindow *parent); + bool showCocoaColorPanel(Qt::WindowModality windowModality, QWindow *parent); bool hideCocoaColorPanel(); void createNSColorPanelDelegate(); diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index 405cacee01..9f4446b32e 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -381,9 +381,13 @@ void QCocoaColorDialogHelper::deleteNativeDialog_sys() mDelegate = 0; } -bool QCocoaColorDialogHelper::show_sys(QFlags, Qt::WindowFlags, QWindow *parent) +bool QCocoaColorDialogHelper::show_sys(Qt::WindowFlags, Qt::WindowModality windowModality, QWindow *parent) { - return showCocoaColorPanel(parent); + if (windowModality == Qt::WindowModal) { + // Cocoa's shared color panel cannot be shown as a sheet + return false; + } + return showCocoaColorPanel(windowModality, parent); } void QCocoaColorDialogHelper::hide_sys() @@ -447,13 +451,15 @@ void QCocoaColorDialogHelper::createNSColorPanelDelegate() mDelegate = delegate; } -bool QCocoaColorDialogHelper::showCocoaColorPanel(QWindow *parent) +bool QCocoaColorDialogHelper::showCocoaColorPanel(Qt::WindowModality windowModality, QWindow *parent) { Q_UNUSED(parent); createNSColorPanelDelegate(); QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) *delegate = static_cast(mDelegate); [delegate->mColorPanel setShowsAlpha:options()->testOption(QColorDialogOptions::ShowAlphaChannel)]; - [delegate showModelessPanel]; + if (windowModality == Qt::NonModal) + [delegate showModelessPanel]; + // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel() return true; } diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h index 7d4da019c2..9768d3e6f9 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h @@ -62,7 +62,7 @@ public: bool defaultNameFilterDisables() const; void deleteNativeDialog_sys(); - bool show_sys(ShowFlags flags, Qt::WindowFlags windowFlags, QWindow *parent); + bool show_sys(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent); void hide_sys(); QPlatformFileDialogHelper::DialogCode dialogResultCode_sys(); void setDirectory_sys(const QString &directory); @@ -74,7 +74,7 @@ public: QString selectedNameFilter_sys() const; public: - bool showCocoaFilePanel(QWindow *parent); + bool showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent); bool hideCocoaFilePanel(); void createNSOpenSavePanelDelegate(); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index c333e3ac1f..9bc7df02fb 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -244,18 +244,18 @@ typedef QSharedPointer SharedPointerFileDialogOptions; return (mReturnCode == NSOKButton) ? QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Accepted) : QT_PREPEND_NAMESPACE(QPlatformDialogHelper::Rejected); } -- (void)showWindowModalSheet:(QWindow *)docWidget +- (void)showWindowModalSheet:(QWindow *)parent { - Q_UNUSED(docWidget); QFileInfo info(*mCurrentSelection); NSString *filename = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.fileName()); NSString *filepath = QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath()); bool selectable = (mOptions->acceptMode() == QFileDialogOptions::AcceptSave) || [self panel:nil shouldShowFilename:filepath]; + NSWindow *nsparent = static_cast(qGuiApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parent)); [mSavePanel beginSheetForDirectory:mCurrentDir file:selectable ? filename : nil - modalForWindow:nil + modalForWindow:nsparent modalDelegate:self didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) contextInfo:nil]; @@ -613,7 +613,7 @@ void QCocoaFileDialogHelper::hide_sys() hideCocoaFilePanel(); } -bool QCocoaFileDialogHelper::show_sys(ShowFlags /* flags */, Qt::WindowFlags windowFlags, QWindow *parent) +bool QCocoaFileDialogHelper::show_sys(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) { // Q_Q(QFileDialog); if (windowFlags & Qt::WindowStaysOnTopHint) { @@ -624,7 +624,7 @@ bool QCocoaFileDialogHelper::show_sys(ShowFlags /* flags */, Qt::WindowFlags win return false; } - return showCocoaFilePanel(parent); + return showCocoaFilePanel(windowModality, parent); } void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate() @@ -645,15 +645,15 @@ void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate() mDelegate = delegate; } -bool QCocoaFileDialogHelper::showCocoaFilePanel(QWindow *parent) +bool QCocoaFileDialogHelper::showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent) { -// Q_Q(QFileDialog); createNSOpenSavePanelDelegate(); QT_MANGLE_NAMESPACE(QNSOpenSavePanelDelegate) *delegate = static_cast(mDelegate); - if (0 /*qt_mac_is_macsheet(qtFileDialog)*/) // ### sheet support. - [delegate showWindowModalSheet:parent]; - else + if (windowModality == Qt::NonModal) [delegate showModelessPanel]; + else if (windowModality == Qt::WindowModal && parent) + [delegate showWindowModalSheet:parent]; + // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel() return true; } diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h index 8a914bf632..f9dd4357a5 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h @@ -60,7 +60,7 @@ public: void _q_platformRunNativeAppModalPanel(); void deleteNativeDialog_sys(); - bool show_sys(ShowFlags showFlags, Qt::WindowFlags windowFlags, QWindow *parent); + bool show_sys(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent); void hide_sys(); QPlatformDialogHelper::DialogCode dialogResultCode_sys(); @@ -70,7 +70,7 @@ public: protected: void createNSFontPanelDelegate(); - bool showCocoaFontPanel(QWindow *parent); + bool showCocoaFontPanel(Qt::WindowModality windowModality, QWindow *parent); bool hideCocoaFontPanel(); private: diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index 1e89270775..515bc2a6ee 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -400,9 +400,13 @@ void QCocoaFontDialogHelper::deleteNativeDialog_sys() mDelegate = 0; } -bool QCocoaFontDialogHelper::show_sys(QFlags, Qt::WindowFlags, QWindow *parent) +bool QCocoaFontDialogHelper::show_sys(Qt::WindowFlags, Qt::WindowModality windowModality, QWindow *parent) { - return showCocoaFontPanel(parent); + if (windowModality == Qt::WindowModal) { + // Cocoa's shared font panel cannot be shown as a sheet + return false; + } + return showCocoaFontPanel(windowModality, parent); } void QCocoaFontDialogHelper::hide_sys() @@ -466,12 +470,14 @@ void QCocoaFontDialogHelper::createNSFontPanelDelegate() mDelegate = delegate; } -bool QCocoaFontDialogHelper::showCocoaFontPanel(QWindow *parent) +bool QCocoaFontDialogHelper::showCocoaFontPanel(Qt::WindowModality windowModality, QWindow *parent) { Q_UNUSED(parent); createNSFontPanelDelegate(); QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast(mDelegate); - [delegate showModelessPanel]; + if (windowModality == Qt::NonModal) + [delegate showModelessPanel]; + // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel() return true; } diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index a6bde74103..12ea880ab0 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -486,11 +486,11 @@ void QWindowsDialogThread::run() } template -bool QWindowsDialogHelperBase::show_sys(QPlatformDialogHelper::ShowFlags flags, - Qt::WindowFlags, +bool QWindowsDialogHelperBase::show_sys(Qt::WindowFlags, + Qt::WindowModality windowModality, QWindow *parent) { - const bool modal = flags & QPlatformDialogHelper::ShowModal; + const bool modal = (windowModality == Qt::ApplicationModal); if (parent) { m_ownerWindow = QWindowsWindow::handleOf(parent); } else { diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h index 3ae22e69eb..909ce5984e 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h @@ -69,8 +69,8 @@ public: virtual void platformNativeDialogModalHelp(); virtual void _q_platformRunNativeAppModalPanel(); virtual void deleteNativeDialog_sys(); - virtual bool show_sys(QPlatformDialogHelper::ShowFlags flags, - Qt::WindowFlags windowFlags, + virtual bool show_sys(Qt::WindowFlags windowFlags, + Qt::WindowModality windowModality, QWindow *parent); virtual void hide_sys(); virtual QVariant styleHint(QPlatformDialogHelper::StyleHint) const; diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp index df76d0af0e..718d64bd27 100644 --- a/src/widgets/dialogs/qdialog.cpp +++ b/src/widgets/dialogs/qdialog.cpp @@ -108,11 +108,9 @@ bool QDialogPrivate::setNativeDialogVisible(bool visible) { if (QPlatformDialogHelper *helper = platformHelper()) { if (visible) { + Q_Q(QDialog); helperPrepareShow(helper); - QPlatformDialogHelper::ShowFlags flags(0); - if (q_func()->isModal()) - flags |= QPlatformDialogHelper::ShowModal; - nativeDialogInUse = helper->show_sys(flags, q_func()->windowFlags(), parentWindow()); + nativeDialogInUse = helper->show_sys(q->windowFlags(), q->windowModality(), parentWindow()); } else { helper->hide_sys(); } -- cgit v1.2.3