summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorJ-P Nurmi <jpnurmi@digia.com>2014-06-07 00:40:44 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-06-07 00:40:44 +0200
commitd9a7ad80f78e7346d6f4dbae2cabe31305d6458f (patch)
tree26a410780b94c553051b8898d5abaf37a909691b /src/plugins/platforms/cocoa
parentd707acfc9e357ffc86feb5d9219372c30c5ff157 (diff)
parent0fcce50af009f97efa2a5c5f2c74415c92830962 (diff)
Merge "Merge remote-tracking branch 'origin/stable' into dev" into refs/staging/dev
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm91
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm17
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuloader.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm31
8 files changed, 77 insertions, 75 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index 6d2c2a401e..b309df6242 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -380,7 +380,7 @@
- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute {
QAccessibleInterface *iface = QAccessible::accessibleInterface(axid);
if (!iface)
- return nil;
+ return NO;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
return iface->state().focusable ? YES : NO;
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index d322079cb2..a2f9f8c984 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -124,7 +124,7 @@ static void cleanupCocoaApplicationDelegate()
[dockMenu release];
[qtMenuLoader release];
if (reflectionDelegate) {
- [NSApp setDelegate:reflectionDelegate];
+ [[NSApplication sharedApplication] setDelegate:reflectionDelegate];
[reflectionDelegate release];
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index de6c6585e9..dc0b8fcc18 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -134,8 +134,6 @@ public:
void interrupt();
void flush();
- bool event(QEvent *);
-
friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher);
};
@@ -180,6 +178,8 @@ public:
void maybeCancelWaitForMoreEvents();
void ensureNSAppInitialized();
+ void removeQueuedUserInputEvents(int nsWinNumber);
+
QCFSocketNotifier cfSocketNotifier;
QList<void *> queuedUserInputEvents; // NSEvent *
CFRunLoopSourceRef postedEventsSource;
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index e0ce9f9648..e7f8992c6d 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -415,6 +415,11 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
// 'session' as well. As a result, we need to restart all internal sessions:
d->temporarilyStopAllModalSessions();
}
+
+ // Clean up the modal session list, call endModalSession.
+ if (d->cleanupModalSessionsNeeded)
+ d->cleanupModalSessions();
+
} else {
d->nsAppRunCalledByQt = true;
QBoolBlocker execGuard(d->currentExecIsNSAppRun, true);
@@ -441,6 +446,11 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
// 'session' as well. As a result, we need to restart all internal sessions:
d->temporarilyStopAllModalSessions();
}
+
+ // Clean up the modal session list, call endModalSession.
+ if (d->cleanupModalSessionsNeeded)
+ d->cleanupModalSessions();
+
retVal = true;
} else do {
// Dispatch all non-user events (but que non-user events up for later). In
@@ -622,7 +632,8 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
if (!info.session) {
QCocoaAutoReleasePool pool;
- NSWindow *nswindow = static_cast<QCocoaWindow *>(info.window->handle())->nativeWindow();
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(info.window->handle());
+ NSWindow *nswindow = cocoaWindow->nativeWindow();
if (!nswindow)
continue;
@@ -630,7 +641,10 @@ NSModalSession QCocoaEventDispatcherPrivate::currentModalSession()
QBoolBlocker block1(blockSendPostedEvents, true);
info.nswindow = nswindow;
[(NSWindow*) info.nswindow retain];
+ QRect rect = cocoaWindow->geometry();
info.session = [NSApp beginModalSessionForWindow:nswindow];
+ if (rect != cocoaWindow->geometry())
+ cocoaWindow->setGeometry(rect);
}
currentModalSessionCached = info.session;
cleanupModalSessionsNeeded = false;
@@ -717,10 +731,9 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
{
// We need to start spinning the modal session. Usually this is done with
// QDialog::exec() for Qt Widgets based applications, but for others that
- // just call show(), we need to interrupt(). We call this here, before
- // setting currentModalSessionCached to zero, so that interrupt() calls
- // [NSApp abortModal] if another modal session is currently running
+ // just call show(), we need to interrupt().
Q_Q(QCocoaEventDispatcher);
+ q->interrupt();
// Add a new, empty (null), NSModalSession to the stack.
// It will become active the next time QEventDispatcher::processEvents is called.
@@ -733,24 +746,6 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
cocoaModalSessionStack.push(info);
updateChildrenWorksWhenModal();
currentModalSessionCached = 0;
- if (currentExecIsNSAppRun) {
- QEvent *e = new QEvent(QEvent::User);
- qApp->postEvent(q, e, Qt::HighEventPriority);
- } else {
- q->interrupt();
- }
-}
-
-bool QCocoaEventDispatcher::event(QEvent *e)
-{
- Q_D(QCocoaEventDispatcher);
-
- if (e->type() == QEvent::User) {
- d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents);
- return true;
- }
-
- return QObject::event(e);
}
void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
@@ -772,10 +767,7 @@ void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
info.window = 0;
if (i + endedSessions == stackSize-1) {
// The top sessions ended. Interrupt the event dispatcher to
- // start spinning the correct session immediately. Like in
- // beginModalSession(), we call interrupt() before clearing
- // currentModalSessionCached to make sure we stop any currently
- // running modal session with [NSApp abortModal]
+ // start spinning the correct session immediately.
q->interrupt();
currentModalSessionCached = 0;
cleanupModalSessionsNeeded = true;
@@ -878,10 +870,7 @@ void QCocoaEventDispatcherPrivate::processPostedEvents()
return;
}
- if (cleanupModalSessionsNeeded)
- cleanupModalSessions();
-
- if (interrupt) {
+ if (processEventsCalled > 0 && interrupt) {
if (currentExecIsNSAppRun) {
// The event dispatcher has been interrupted. But since
// [NSApplication run] is running the event loop, we
@@ -903,6 +892,21 @@ void QCocoaEventDispatcherPrivate::processPostedEvents()
}
}
+void QCocoaEventDispatcherPrivate::removeQueuedUserInputEvents(int nsWinNumber)
+{
+ if (nsWinNumber) {
+ int eventIndex = queuedUserInputEvents.size();
+
+ while (--eventIndex >= 0) {
+ NSEvent * nsevent = static_cast<NSEvent *>(queuedUserInputEvents.at(eventIndex));
+ if ([nsevent windowNumber] == nsWinNumber) {
+ queuedUserInputEvents.removeAt(eventIndex);
+ [nsevent release];
+ }
+ }
+ }
+}
+
void QCocoaEventDispatcherPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
CFRunLoopActivity activity,
void *info)
@@ -948,23 +952,16 @@ void QCocoaEventDispatcher::interrupt()
{
Q_D(QCocoaEventDispatcher);
d->interrupt = true;
- if (d->currentModalSessionCached) {
- // If a modal session is active, abort it so that we can clean it up
- // later. We can't use [NSApp stopModal] here, because we do not know
- // where the interrupt() came from.
- [NSApp abortModal];
- } else {
- wakeUp();
-
- // We do nothing more here than setting d->interrupt = true, and
- // poke the event loop if it is sleeping. Actually stopping
- // NSApp, or the current modal session, is done inside the send
- // posted events callback. We do this to ensure that all current pending
- // cocoa events gets delivered before we stop. Otherwise, if we now stop
- // the last event loop recursion, cocoa will just drop pending posted
- // events on the floor before we get a chance to reestablish a new session.
- d->cancelWaitForMoreEvents();
- }
+ wakeUp();
+
+ // We do nothing more here than setting d->interrupt = true, and
+ // poke the event loop if it is sleeping. Actually stopping
+ // NSApp, or the current modal session, is done inside the send
+ // posted events callback. We do this to ensure that all current pending
+ // cocoa events gets delivered before we stop. Otherwise, if we now stop
+ // the last event loop recursion, cocoa will just drop pending posted
+ // events on the floor before we get a chance to reestablish a new session.
+ d->cancelWaitForMoreEvents();
}
void QCocoaEventDispatcher::flush()
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 9c4f86d893..07b73c1a7a 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -139,8 +139,6 @@ public:
void setToolbar(QWindow *window, NSToolbar *toolbar);
NSToolbar *toolbar(QWindow *window) const;
void clearToolbars();
- void setWindow(NSWindow* nsWindow, QCocoaWindow *window);
- QCocoaWindow *window(NSWindow *window);
private:
static QCocoaIntegration *mInstance;
@@ -159,7 +157,6 @@ private:
QScopedPointer<QCocoaKeyMapper> mKeyboardMapper;
QHash<QWindow *, NSToolbar *> mToolbars;
- QHash<NSWindow *, QCocoaWindow*> mWindows;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index e7a973e45b..8723b20615 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -159,9 +159,12 @@ qreal QCocoaScreen::devicePixelRatio() const
QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
{
// Get a z-ordered list of windows. Iterate through it until
- // we find a window which contains the point.
+ // we find a (Qt) window which contains the point.
for (NSWindow *nsWindow in [NSApp orderedWindows]) {
- QCocoaWindow *cocoaWindow = QCocoaIntegration::instance()->window(nsWindow);
+ if (![nsWindow isKindOfClass:[QNSWindow class]])
+ continue;
+ QNSWindow *qnsWindow = static_cast<QNSWindow *>(nsWindow);
+ QCocoaWindow *cocoaWindow = qnsWindow.helper.platformWindow;
if (!cocoaWindow)
continue;
QWindow *window = cocoaWindow->window();
@@ -517,16 +520,6 @@ NSToolbar *QCocoaIntegration::toolbar(QWindow *window) const
return mToolbars.value(window);
}
-void QCocoaIntegration::setWindow(NSWindow* nsWindow, QCocoaWindow *window)
-{
- mWindows.insert(nsWindow, window);
-}
-
-QCocoaWindow *QCocoaIntegration::window(NSWindow *window)
-{
- return mWindows.value(window);
-}
-
void QCocoaIntegration::clearToolbars()
{
QHash<QWindow *, NSToolbar *>::const_iterator it = mToolbars.constBegin();
diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
index 60bc3b5a55..9340e945fb 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm
@@ -174,7 +174,7 @@ QT_END_NAMESPACE
- (void)removeActionsFromAppMenu
{
for (NSMenuItem *item in [appMenu itemArray])
- [item setTag:nil];
+ [item setTag:0];
}
- (void)dealloc
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 651fedb26e..c8ca494b33 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -182,13 +182,22 @@ static bool isMouseEvent(NSEvent *ev)
- (void)detachFromPlatformWindow
{
+ _platformWindow = 0;
[self.window.delegate release];
self.window.delegate = nil;
}
- (void)clearWindow
{
- _window = nil;
+ if (_window) {
+ QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
+ if (cocoaEventDispatcher) {
+ QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
+ cocoaEventDispatcherPrivate->removeQueuedUserInputEvents([_window windowNumber]);
+ }
+
+ _window = nil;
+ }
}
- (void)dealloc
@@ -261,8 +270,6 @@ static bool isMouseEvent(NSEvent *ev)
{
[self close];
- QCocoaIntegration::instance()->setWindow(self, 0);
-
if (self.helper.grabbingMouse) {
self.helper.releaseOnMouseUp = YES;
} else {
@@ -329,7 +336,6 @@ static bool isMouseEvent(NSEvent *ev)
{
[self.helper detachFromPlatformWindow];
[self close];
- QCocoaIntegration::instance()->setWindow(self, 0);
[self release];
}
@@ -1001,9 +1007,14 @@ bool QCocoaWindow::isExposed() const
bool QCocoaWindow::isOpaque() const
{
+ // OpenGL surfaces can be ordered either above(default) or below the NSWindow.
+ // When ordering below the window must be tranclucent.
+ static GLint openglSourfaceOrder = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER");
+
bool translucent = (window()->format().alphaBufferSize() > 0
|| window()->opacity() < 1
- || (m_qtView && [m_qtView hasMask]));
+ || (m_qtView && [m_qtView hasMask]))
+ || (surface()->supportsOpenGL() && openglSourfaceOrder == -1);
return !translucent;
}
@@ -1404,7 +1415,13 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow()
NSInteger level = windowLevel(flags);
[createdWindow setLevel:level];
- if (window()->format().alphaBufferSize() > 0) {
+ // OpenGL surfaces can be ordered either above(default) or below the NSWindow.
+ // When ordering below the window must be tranclucent and have a clear background color.
+ static GLint openglSourfaceOrder = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER");
+
+ bool isTranslucent = window()->format().alphaBufferSize() > 0
+ || (surface()->supportsOpenGL() && openglSourfaceOrder == -1);
+ if (isTranslucent) {
[createdWindow setBackgroundColor:[NSColor clearColor]];
[createdWindow setOpaque:NO];
}
@@ -1413,8 +1430,6 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow()
applyContentBorderThickness(createdWindow);
- QCocoaIntegration::instance()->setWindow(createdWindow, this);
-
return createdWindow;
}