diff --git a/src/plugins/platforms/cocoa/qcocoamessagedialog.h b/src/plugins/platforms/cocoa/qcocoamessagedialog.h index 564dd915c5a..b8c273469a3 100644 --- a/src/plugins/platforms/cocoa/qcocoamessagedialog.h +++ b/src/plugins/platforms/cocoa/qcocoamessagedialog.h @@ -28,6 +28,7 @@ private: Qt::WindowModality modality() const; NSAlert *m_alert = nullptr; QEventLoop *m_eventLoop = nullptr; + NSModalResponse runModal() const; void processResponse(NSModalResponse response); }; diff --git a/src/plugins/platforms/cocoa/qcocoamessagedialog.mm b/src/plugins/platforms/cocoa/qcocoamessagedialog.mm index e058450ebd5..56c3fceed25 100644 --- a/src/plugins/platforms/cocoa/qcocoamessagedialog.mm +++ b/src/plugins/platforms/cocoa/qcocoamessagedialog.mm @@ -222,7 +222,7 @@ bool QCocoaMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality w if (m_alert && NSApp.modalWindow != m_alert.window) { qCDebug(lcQpaDialogs) << "Running deferred modal" << m_alert; QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); - processResponse([m_alert runModal]); + processResponse(runModal()); } }); } @@ -230,6 +230,20 @@ bool QCocoaMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality w return true; } +// We shouldn't get NSModalResponseContinue as a response from NSAlert::runModal, +// and processResponse must not be called with that value (if we are there, it's +// too late to do anything about it. +// However, as QTBUG-114546 shows, there are scenarios where we might get that +// response anyway. We interpret it to keep the modal loop running, and we only +// return if we got something else to pass to processResponse. +NSModalResponse QCocoaMessageDialog::runModal() const +{ + NSModalResponse response = NSModalResponseContinue; + while (response == NSModalResponseContinue) + response = [m_alert runModal]; + return response; +} + void QCocoaMessageDialog::exec() { Q_ASSERT(m_alert); @@ -242,7 +256,7 @@ void QCocoaMessageDialog::exec() } else { qCDebug(lcQpaDialogs) << "Running modal" << m_alert; QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); - processResponse([m_alert runModal]); + processResponse(runModal()); } }