summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@nokia.com>2011-02-18 08:20:06 (GMT)
committerRichard Moe Gustavsen <richard.gustavsen@nokia.com>2011-02-18 08:20:06 (GMT)
commit8f74a64f3f2f5a6273c5e7de1591585a97dff82d (patch)
tree1163a8ecb656274389aeecd46777ccdbd52aad5d /src/gui
parent5727255ce985862ac9970f3fb2db96735700b92f (diff)
downloadQt-8f74a64f3f2f5a6273c5e7de1591585a97dff82d.zip
Qt-8f74a64f3f2f5a6273c5e7de1591585a97dff82d.tar.gz
Qt-8f74a64f3f2f5a6273c5e7de1591585a97dff82d.tar.bz2
Cocoa: implement eventdispatcher flag excludeUserInputEvents
When executing modal windows, the event dispatcher would not respect the QEventLoop::ExcludeUserInputEvents. This patch implements this support. The way it now works is that we fetch events manually from NSApplication and do the dispatching ourselves in those cases. From earlier research, this patch has shown to be a bit unreliable in some cases, and might have some sideeffects. Hence the reason we avoid it if we can. But it still feels better that we try to follow the flag in those few application that wants to do this.
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm60
1 files changed, 42 insertions, 18 deletions
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index b4f3805..677a736 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -561,6 +561,7 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
wakeUp();
emit awake();
+ bool excludeUserEvents = flags & QEventLoop::ExcludeUserInputEvents;
bool retVal = false;
forever {
if (d->interrupt)
@@ -571,7 +572,7 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
NSEvent* event = 0;
// First, send all previously excluded input events, if any:
- if (!(flags & QEventLoop::ExcludeUserInputEvents)) {
+ if (!excludeUserEvents) {
while (!d->queuedUserInputEvents.isEmpty()) {
event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
if (!filterEvent(event)) {
@@ -590,9 +591,8 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
// Finally, if we are to exclude user input events, we cannot call [NSApp run]
// as we then loose control over which events gets dispatched:
const bool canExec_3rdParty = d->nsAppRunCalledByQt || ![NSApp isRunning];
- const bool canExec_Qt =
- (flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec)
- && !(flags & QEventLoop::ExcludeUserInputEvents);
+ const bool canExec_Qt = !excludeUserEvents &&
+ (flags & QEventLoop::DialogExec || flags & QEventLoop::EventLoopExec) ;
if (canExec_Qt && canExec_3rdParty) {
// We can use exec-mode, meaning that we can stay in a tight loop until
@@ -620,22 +620,46 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
// Instead we will process all current pending events and return.
d->ensureNSAppInitialized();
if (NSModalSession session = d->currentModalSession()) {
- if (flags & QEventLoop::WaitForMoreEvents)
- qt_mac_waitForMoreModalSessionEvents();
- NSInteger status = [NSApp runModalSession:session];
- if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
- // INVARIANT: Someone called [NSApp stopModal:] from outside the event
- // dispatcher (e.g to stop a native dialog). But that call wrongly stopped
- // 'session' as well. As a result, we need to restart all internal sessions:
- d->temporarilyStopAllModalSessions();
- }
- retVal = true;
- } else do {
- event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ // INVARIANT: a modal window is executing.
+ if (!excludeUserEvents) {
+ // Since we can dispatch all kinds of events, we choose
+ // to use cocoa's native way of running modal sessions:
+ if (flags & QEventLoop::WaitForMoreEvents)
+ qt_mac_waitForMoreModalSessionEvents();
+ NSInteger status = [NSApp runModalSession:session];
+ if (status != NSRunContinuesResponse && session == d->currentModalSessionCached) {
+ // INVARIANT: Someone called [NSApp stopModal:] from outside the event
+ // dispatcher (e.g to stop a native dialog). But that call wrongly stopped
+ // 'session' as well. As a result, we need to restart all internal sessions:
+ d->temporarilyStopAllModalSessions();
+ }
+ retVal = true;
+ } else do {
+ // Dispatch all non-user events (but que non-user events up for later). In
+ // this case, we need more control over which events gets dispatched, and
+ // cannot use [NSApp runModalSession:session]:
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:nil
- inMode:NSDefaultRunLoopMode
+ inMode:NSModalPanelRunLoopMode
dequeue: YES];
+ if (event) {
+ if (IsMouseOrKeyEvent(event)) {
+ [event retain];
+ d->queuedUserInputEvents.append(event);
+ continue;
+ }
+ if (!filterEvent(event) && qt_mac_send_event(flags, event, 0))
+ retVal = true;
+ }
+ } while (!d->interrupt && event != nil);
+ } else do {
+ // INVARIANT: No modal window is executing.
+ event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ untilDate:nil
+ inMode:NSDefaultRunLoopMode
+ dequeue: YES];
+
if (event) {
if (flags & QEventLoop::ExcludeUserInputEvents) {
if (IsMouseOrKeyEvent(event)) {
@@ -649,7 +673,7 @@ bool QEventDispatcherMac::processEvents(QEventLoop::ProcessEventsFlags flags)
}
} while (!d->interrupt && event != nil);
- // Be sure to flush the Qt posted events when not using mode
+ // Be sure to flush the Qt posted events when not using exec mode
// (exec mode will always do this call from the event loop source):
if (!d->interrupt)
QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);