1
--- src/gui/kernel/qeventdispatcher_mac.mm 2014-08-02 14:07:52.000000000 -0400
2
+++ src/gui/kernel/qeventdispatcher_mac.mm 2014-08-05 16:35:27.000000000 -0400
5
// In case we end up recursing while we now process events, make sure
6
// that we send remaining posted Qt events before this call returns:
10
bool excludeUserEvents = flags & QEventLoop::ExcludeUserInputEvents;
12
// [NSApp run], which is the normal code path for cocoa applications.
13
if (NSModalSession session = d->currentModalSession()) {
14
QBoolBlocker execGuard(d->currentExecIsNSAppRun, false);
15
- while ([NSApp runModalSession:session] == NSRunContinuesResponse && !d->interrupt)
16
- qt_mac_waitForMoreModalSessionEvents();
18
+ // OSX 10.9 appears to tighten up its internal code such that
19
+ // sessions shouldn't be used once they've been freed, which
20
+ // could happen in the else condition of the if(canExec)
21
+ // statement. Add extra logic to make sure we don't use the
22
+ // session once the current modal session is freed. We stop if
23
+ // the session is no longer current or if runModalSession()
24
+ // indicates the modal session is no longer continuing.
25
+ bool stayInLoop = true;
26
+ while (!d->interrupt && stayInLoop) {
27
+ // Mavericks deprecated the status we wish to check.
28
+ NSInteger checkStatus = 0;
29
+ if(QSysInfo::MacintoshVersion < QSysInfo::MV_10_9) {
30
+ checkStatus = NSRunContinuesResponse;
33
+ checkStatus = NSModalResponseContinue;
35
+ if([NSApp runModalSession:session] == checkStatus) {
36
+ qt_mac_waitForMoreModalSessionEvents();
42
+ if(session != d->currentModalSession()) {
47
if (!d->interrupt && session == d->currentModalSessionCached) {
48
// Someone called [NSApp stopModal:] from outside the event
50
d->temporarilyStopAllModalSessions();
53
- // Clean up the modal session list, call endModalSession.
54
- if (d->cleanupModalSessionsNeeded) {
55
+ if (d->cleanupModalSessionsNeeded) {
56
d->cleanupModalSessions();
60
// to use cocoa's native way of running modal sessions:
61
if (flags & QEventLoop::WaitForMoreEvents)
62
qt_mac_waitForMoreModalSessionEvents();
64
+ // Mavericks deprecated the status we wish to check.
65
+ NSInteger checkStatus = 0;
66
+ if(QSysInfo::MacintoshVersion < QSysInfo::MV_10_9) {
67
+ checkStatus = NSRunContinuesResponse;
70
+ checkStatus = NSModalResponseContinue;
72
NSInteger status = [NSApp runModalSession:session];
73
- if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
74
+ if (status != checkStatus && session == d->currentModalSessionCached) {
75
// INVARIANT: Someone called [NSApp stopModal:] from outside the event
76
// dispatcher (e.g to stop a native dialog). But that call wrongly stopped
77
// 'session' as well. As a result, we need to restart all internal sessions:
78
d->temporarilyStopAllModalSessions();
81
- // Clean up the modal session list, call endModalSession.
82
if (d->cleanupModalSessionsNeeded) {
83
d->cleanupModalSessions();
87
[NSApp endModalSession:info.session];
89
+ [(NSWindow*) info.nswindow release];
92
currentModalSessionCached = 0;
94
currentModalSessionCached = info.session;
97
- cocoaModalSessionStack.remove(i);
98
currentModalSessionCached = 0;
100
+ Q_ASSERT(info.nswindow != 0);
101
[NSApp endModalSession:info.session];
102
[(NSWindow *)info.nswindow release];
105
+ // remove the info now that we are finished with it
106
+ cocoaModalSessionStack.remove(i);
109
updateChildrenWorksWhenModal();
112
void QEventDispatcherMacPrivate::beginModalSession(QWidget *widget)
114
+ QEventDispatcherMac::instance()->interrupt();
116
// Add a new, empty (null), NSModalSession to the stack.
117
// It will become active the next time QEventDispatcher::processEvents is called.
118
// A QCocoaModalSessionInfo is considered pending to become active if the widget pointer
119
@@ -970,16 +1009,20 @@
120
// when we stop the _current_ modal session (which is the session on top of
121
// the stack, and might not belong to 'widget').
122
int stackSize = cocoaModalSessionStack.size();
123
+ int endedSessions = 0;
124
for (int i=stackSize-1; i>=0; --i) {
125
QCocoaModalSessionInfo &info = cocoaModalSessionStack[i];
126
+ if (!info.widget) {
129
if (info.widget == widget) {
131
- if (i == stackSize-1) {
132
+ if (i + endedSessions == stackSize-1) {
133
// The top sessions ended. Interrupt the event dispatcher
134
// to start spinning the correct session immidiatly:
135
+ QEventDispatcherMac::instance()->interrupt();
136
currentModalSessionCached = 0;
137
cleanupModalSessionsNeeded = true;
138
- QEventDispatcherMac::instance()->interrupt();
142
@@ -1056,8 +1099,9 @@
145
#ifdef QT_MAC_USE_COCOA
146
- if (d->cleanupModalSessionsNeeded && d->currentExecIsNSAppRun)
147
+ if (d->cleanupModalSessionsNeeded && d->currentExecIsNSAppRun) {
148
d->cleanupModalSessions();
153
@@ -1067,8 +1111,9 @@
154
// [NSApplication run] is running the event loop, we
155
// delayed stopping it until now (to let cocoa process
156
// pending cocoa events first).
157
- if (d->currentModalSessionCached)
158
+ if (d->currentModalSessionCached) {
159
d->temporarilyStopAllModalSessions();
162
d->cancelWaitForMoreEvents();