summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@qt.io>2016-11-01 15:28:17 -0700
committerJani Heikkinen <jani.heikkinen@qt.io>2016-11-08 10:45:45 +0000
commite79b40ee8f78a9669ed0b7b6def2a69ef7ab02fa (patch)
tree9dd88af03555174565470edefa6222742cf44a08 /src
parent3f347262da369b0a4adae89750f9fe0247fcd486 (diff)
macOS: Clear event dispatcher interrupt state
A pending interrupt of a QEventLoop may interfere with native runModal calls, resulting in Cocoa's main event loop to be stopped unexpectedly. After commit 9ab60b9c processEvents() no longer resets the event dispatcher interrupt flag. Add QCocoaEventDispatcher::clearCurrentThreadCocoa EventDispatcherInterruptFlag(). Use it to clear the interrupt state before calling runModal and variants. Work around the inability to use platform API in the print support code. Change-Id: I3e03e7ec21ff6c49442c7a6e803a7200aac0b58d Task-number: QTBUG-56746 Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm13
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm6
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_mac.mm5
-rw-r--r--src/printsupport/dialogs/qprintdialog_mac.mm5
9 files changed, 48 insertions, 0 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
index 0319d4ca6d..7d12804d47 100644
--- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm
@@ -45,6 +45,7 @@
#include "qcocoacolordialoghelper.h"
#include "qcocoahelpers.h"
+#include "qcocoaeventdispatcher.h"
#import <AppKit/AppKit.h>
@@ -322,6 +323,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate);
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
// close down during the cleanup.
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
+
+ // Make sure we don't interrupt the runModalForWindow call.
+ QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
+
[NSApp runModalForWindow:mColorPanel];
mDialogIsExecuting = false;
return (mResultCode == NSOKButton);
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 84880d51c5..70887c41c9 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -131,6 +131,8 @@ public:
void interrupt();
void flush();
+ static void clearCurrentThreadCocoaEventDispatcherInterruptFlag();
+
friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher);
};
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 5c27cf8059..d9c835d797 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -966,6 +966,19 @@ void QCocoaEventDispatcher::interrupt()
void QCocoaEventDispatcher::flush()
{ }
+// QTBUG-56746: The behavior of processEvents() has been changed to not clear
+// the interrupt flag. Use this function to clear it.
+ void QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag()
+{
+ QCocoaEventDispatcher *cocoaEventDispatcher =
+ qobject_cast<QCocoaEventDispatcher *>(QThread::currentThread()->eventDispatcher());
+ if (!cocoaEventDispatcher)
+ return;
+ QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate =
+ static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
+ cocoaEventDispatcherPrivate->interrupt = false;
+}
+
QCocoaEventDispatcher::~QCocoaEventDispatcher()
{
Q_D(QCocoaEventDispatcher);
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 4eb35f5495..c7191e4841 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -53,6 +53,7 @@
#include "qt_mac_p.h"
#include "qcocoahelpers.h"
#include "qcocoamenubar.h"
+#include "qcocoaeventdispatcher.h"
#include <qregexp.h>
#include <qbuffer.h>
#include <qdebug.h>
@@ -243,6 +244,10 @@ static QString strippedText(QString s)
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
// close down during the cleanup.
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
+
+ // Make sure we don't interrupt the runModal call below.
+ QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
+
QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder();
mReturnCode = [mSavePanel runModal];
QCocoaMenuBar::resetKnownMenuItemsToQt();
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
index dc7dfb788f..d0b76861d8 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
@@ -49,6 +49,7 @@
#include "qcocoafontdialoghelper.h"
#include "qcocoahelpers.h"
+#include "qcocoaeventdispatcher.h"
#import <AppKit/AppKit.h>
@@ -319,6 +320,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate);
// cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
// close down during the cleanup.
qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
+
+ // Make sure we don't interrupt the runModalForWindow call.
+ QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
+
[NSApp runModalForWindow:mFontPanel];
mDialogIsExecuting = false;
return (mResultCode == NSOKButton);
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
index 7065a364bf..b06fff1375 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h
@@ -100,6 +100,8 @@ private:
*/
Q_INVOKABLE QPixmap defaultBackgroundPixmapForQWizard();
+ Q_INVOKABLE void clearCurrentThreadCocoaEventDispatcherInterruptFlag();
+
// QMacPastebardMime support. The mac pasteboard void pointers are
// QMacPastebardMime instances from the cocoa plugin or qtmacextras
// These two classes are kept in sync and can be casted between.
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index 8562246817..a327750ffd 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -44,6 +44,7 @@
#include "qcocoahelpers.h"
#include "qcocoaapplication.h"
#include "qcocoaintegration.h"
+#include "qcocoaeventdispatcher.h"
#include <qbytearray.h>
#include <qwindow.h>
@@ -194,6 +195,11 @@ QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard()
return QPixmap();
}
+void QCocoaNativeInterface::clearCurrentThreadCocoaEventDispatcherInterruptFlag()
+{
+ QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag();
+}
+
void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window)
{
Q_UNUSED(window);
diff --git a/src/printsupport/dialogs/qpagesetupdialog_mac.mm b/src/printsupport/dialogs/qpagesetupdialog_mac.mm
index e3e7523a16..c29b911e35 100644
--- a/src/printsupport/dialogs/qpagesetupdialog_mac.mm
+++ b/src/printsupport/dialogs/qpagesetupdialog_mac.mm
@@ -133,6 +133,11 @@ void QMacPageSetupDialogPrivate::openCocoaPageLayout(Qt::WindowModality modality
QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPageLayoutDelegate) alloc] initWithNSPrintInfo:printInfo];
if (modality == Qt::ApplicationModal) {
+
+ // Make sure we don't interrupt the runModalWithPrintInfo call.
+ (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
+ "clearCurrentThreadCocoaEventDispatcherInterruptFlag");
+
int rval = [pageLayout runModalWithPrintInfo:printInfo];
[delegate pageLayoutDidEnd:pageLayout returnCode:rval contextInfo:q];
} else {
diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm
index c16bb93013..c630ab634a 100644
--- a/src/printsupport/dialogs/qprintdialog_mac.mm
+++ b/src/printsupport/dialogs/qprintdialog_mac.mm
@@ -245,6 +245,11 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
if (modality == Qt::ApplicationModal || !q->parentWidget()) {
if (modality == Qt::NonModal)
qWarning("QPrintDialog is required to be modal on OS X");
+
+ // Make sure we don't interrupt the runModalWithPrintInfo call.
+ (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
+ "clearCurrentThreadCocoaEventDispatcherInterruptFlag");
+
int rval = [printPanel runModalWithPrintInfo:printInfo];
[delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:q];
} else {