diff options
author | J-P Nurmi <jpnurmi@digia.com> | 2014-06-05 22:26:44 +0200 |
---|---|---|
committer | J-P Nurmi <jpnurmi@digia.com> | 2014-06-05 22:26:44 +0200 |
commit | 0fcce50af009f97efa2a5c5f2c74415c92830962 (patch) | |
tree | f8abf0e4f445fed9480b426b2f856b50911f1210 /src/plugins/platforms/cocoa | |
parent | 74d46a669badc5bf32187686102ca4e644a3c0af (diff) | |
parent | c54f7720d09e7d00f3309736bbeaaa6a81967ec1 (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Conflicts:
mkspecs/features/qt.prf
src/plugins/platforms/xcb/qxcbwindow.h
src/tools/qdoc/qdocindexfiles.cpp
src/widgets/kernel/qwidget_qpa.cpp
Change-Id: I214f57b03bc2ff86cf3b7dfe2966168af93a5a67
Diffstat (limited to 'src/plugins/platforms/cocoa')
8 files changed, 77 insertions, 75 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index dd3b9f53db..078dc67cad 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; } |