diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoawindow.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 241 |
1 files changed, 122 insertions, 119 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 54254455e4..0ef06ccea7 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -117,24 +117,19 @@ static void qRegisterNotificationCallbacks() return; } - if (lcCocoaNotifications().isDebugEnabled()) { - if (cocoaWindows.isEmpty()) { - qCDebug(lcCocoaNotifications) << "Could not find forwarding target for" << - qPrintable(notificationName) << "from" << notification.object; - } else { - QVector<QCocoaWindow *> debugWindows; - for (QCocoaWindow *cocoaWindow : cocoaWindows) - debugWindows += cocoaWindow; - qCDebug(lcCocoaNotifications) << "Forwarding" << qPrintable(notificationName) << - "to" << debugWindows; - } + if (lcCocoaNotifications().isDebugEnabled() && !cocoaWindows.isEmpty()) { + QVector<QCocoaWindow *> debugWindows; + for (QCocoaWindow *cocoaWindow : cocoaWindows) + debugWindows += cocoaWindow; + qCDebug(lcCocoaNotifications) << "Forwarding" << qPrintable(notificationName) << + "to" << debugWindows; } // FIXME: Could be a foreign window, look up by iterating top level QWindows for (QCocoaWindow *cocoaWindow : cocoaWindows) { if (!method.invoke(cocoaWindow, Qt::DirectConnection)) { - qCWarning(lcQpaCocoaWindow) << "Failed to invoke NSNotification callback for" + qCWarning(lcQpaWindow) << "Failed to invoke NSNotification callback for" << notification.name << "on" << cocoaWindow; } } @@ -148,9 +143,7 @@ const int QCocoaWindow::NoAlertRequest = -1; QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) : QPlatformWindow(win) , m_view(nil) - , m_nsWindow(0) - , m_viewIsEmbedded(false) - , m_viewIsToBeEmbedded(false) + , m_nsWindow(nil) , m_lastReportedWindowState(Qt::WindowNoState) , m_windowModality(Qt::NonModal) , m_windowUnderMouse(false) @@ -159,9 +152,9 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) , m_inSetGeometry(false) , m_inSetStyleMask(false) #ifndef QT_NO_OPENGL - , m_glContext(0) + , m_glContext(nullptr) #endif - , m_menubar(0) + , m_menubar(nullptr) , m_needsInvalidateShadow(false) , m_hasModalSession(false) , m_frameStrutEventsEnabled(false) @@ -173,7 +166,7 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) , m_topContentBorderThickness(0) , m_bottomContentBorderThickness(0) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::QCocoaWindow" << window(); + qCDebug(lcQpaWindow) << "QCocoaWindow::QCocoaWindow" << window(); if (nativeHandle) { m_view = reinterpret_cast<NSView *>(nativeHandle); @@ -183,7 +176,7 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) void QCocoaWindow::initialize() { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::initialize" << window(); + qCDebug(lcQpaWindow) << "QCocoaWindow::initialize" << window(); QMacAutoReleasePool pool; @@ -200,9 +193,6 @@ void QCocoaWindow::initialize() [m_view setWantsBestResolutionOpenGLSurface:enable]; // See also QCocoaGLContext::makeCurrent for software renderer workarounds. } - BOOL enable = qt_mac_resolveOption(NO, window(), "_q_mac_wantsLayer", - "QT_MAC_WANTS_LAYER"); - [m_view setWantsLayer:enable]; } setGeometry(initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight)); @@ -217,7 +207,7 @@ void QCocoaWindow::initialize() QCocoaWindow::~QCocoaWindow() { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::~QCocoaWindow" << window(); + qCDebug(lcQpaWindow) << "QCocoaWindow::~QCocoaWindow" << window(); QMacAutoReleasePool pool; [m_nsWindow makeFirstResponder:nil]; @@ -255,7 +245,7 @@ QSurfaceFormat QCocoaWindow::format() const void QCocoaWindow::setGeometry(const QRect &rectIn) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setGeometry" << window() << rectIn; + qCDebug(lcQpaWindow) << "QCocoaWindow::setGeometry" << window() << rectIn; QBoolBlocker inSetGeometry(m_inSetGeometry, true); @@ -283,7 +273,7 @@ QRect QCocoaWindow::geometry() const // QWindows that are embedded in a NSView hiearchy may be considered // top-level from Qt's point of view but are not from Cocoa's point // of view. Embedded QWindows get global (screen) geometry. - if (m_viewIsEmbedded) { + if (isEmbedded()) { NSPoint windowPoint = [m_view convertPoint:NSMakePoint(0, 0) toView:nil]; NSRect screenRect = [[m_view window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; NSPoint screenPoint = screenRect.origin; @@ -297,12 +287,12 @@ QRect QCocoaWindow::geometry() const void QCocoaWindow::setCocoaGeometry(const QRect &rect) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setCocoaGeometry" << window() << rect; + qCDebug(lcQpaWindow) << "QCocoaWindow::setCocoaGeometry" << window() << rect; QMacAutoReleasePool pool; QPlatformWindow::setGeometry(rect); - if (m_viewIsEmbedded) { + if (isEmbedded()) { if (!isForeignWindow()) { [m_view setFrame:NSMakeRect(0, 0, rect.width(), rect.height())]; } @@ -321,12 +311,12 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) void QCocoaWindow::setVisible(bool visible) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setVisible" << window() << visible; + qCDebug(lcQpaWindow) << "QCocoaWindow::setVisible" << window() << visible; m_inSetVisible = true; QMacAutoReleasePool pool; - QCocoaWindow *parentCocoaWindow = 0; + QCocoaWindow *parentCocoaWindow = nullptr; if (window()->transientParent()) parentCocoaWindow = static_cast<QCocoaWindow *>(window()->transientParent()->handle()); @@ -378,13 +368,13 @@ void QCocoaWindow::setVisible(bool visible) } else if (window()->modality() != Qt::NonModal) { // show the window as application modal QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher()); - Q_ASSERT(cocoaEventDispatcher != 0); + Q_ASSERT(cocoaEventDispatcher); QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher)); cocoaEventDispatcherPrivate->beginModalSession(window()); m_hasModalSession = true; } else if ([m_view.window canBecomeKeyWindow]) { QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher()); - QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0; + QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = nullptr; if (cocoaEventDispatcher) cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher)); @@ -423,7 +413,7 @@ void QCocoaWindow::setVisible(bool visible) m_glContext->windowWasHidden(); #endif QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher()); - QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0; + QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = nullptr; if (cocoaEventDispatcher) cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher)); if (isContentView()) { @@ -491,7 +481,8 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags) // Any "special" window should be in at least the same level as its parent. if (type != Qt::Window) { const QWindow * const transientParent = window()->transientParent(); - const QCocoaWindow * const transientParentWindow = transientParent ? static_cast<QCocoaWindow *>(transientParent->handle()) : 0; + const QCocoaWindow * const transientParentWindow = transientParent ? + static_cast<QCocoaWindow *>(transientParent->handle()) : nullptr; if (transientParentWindow) windowLevel = qMax([transientParentWindow->nativeWindow() level], windowLevel); } @@ -555,46 +546,49 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags) void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) { - if (isContentView()) { - // While setting style mask we can have handleGeometryChange calls on a content - // view with null geometry, reporting an invalid coordinates as a result. - m_inSetStyleMask = true; - m_view.window.styleMask = windowStyleMask(flags); - m_inSetStyleMask = false; - m_view.window.level = this->windowLevel(flags); - - m_view.window.hasShadow = !(flags & Qt::NoDropShadowWindowHint); - - if (!(flags & Qt::FramelessWindowHint)) - setWindowTitle(window()->title()); - - Qt::WindowType type = window()->type(); - if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) { - NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior; - if (flags & Qt::WindowFullscreenButtonHint) { - behavior |= NSWindowCollectionBehaviorFullScreenPrimary; - behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary; - } else { - behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary; - behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; - } - m_view.window.collectionBehavior = behavior; + if (!isContentView()) + return; + + // While setting style mask we can have handleGeometryChange calls on a content + // view with null geometry, reporting an invalid coordinates as a result. + m_inSetStyleMask = true; + m_view.window.styleMask = windowStyleMask(flags); + m_inSetStyleMask = false; + + Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); + if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) { + NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior; + if (flags & Qt::WindowFullscreenButtonHint) { + behavior |= NSWindowCollectionBehaviorFullScreenPrimary; + behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary; + } else { + behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary; + behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary; } - setWindowZoomButton(flags); - - // Make window ignore mouse events if WindowTransparentForInput is set. - // Note that ignoresMouseEvents has a special initial state where events - // are ignored (passed through) based on window transparency, and that - // setting the property to false does not return us to that state. Instead, - // this makes the window capture all mouse events. Take care to only - // set the property if needed. FIXME: recreate window if needed or find - // some other way to implement WindowTransparentForInput. - bool ignoreMouse = flags & Qt::WindowTransparentForInput; - if (m_view.window.ignoresMouseEvents != ignoreMouse) - m_view.window.ignoresMouseEvents = ignoreMouse; + m_view.window.collectionBehavior = behavior; } - m_windowFlags = flags; + // Set styleMask and collectionBehavior before applying window level, as + // the window level change will trigger verification of the two properties. + m_view.window.level = this->windowLevel(flags); + + m_view.window.hasShadow = !(flags & Qt::NoDropShadowWindowHint); + + if (!(flags & Qt::FramelessWindowHint)) + setWindowTitle(window()->title()); + + setWindowZoomButton(flags); + + // Make window ignore mouse events if WindowTransparentForInput is set. + // Note that ignoresMouseEvents has a special initial state where events + // are ignored (passed through) based on window transparency, and that + // setting the property to false does not return us to that state. Instead, + // this makes the window capture all mouse events. Take care to only + // set the property if needed. FIXME: recreate window if needed or find + // some other way to implement WindowTransparentForInput. + bool ignoreMouse = flags & Qt::WindowTransparentForInput; + if (m_view.window.ignoresMouseEvents != ignoreMouse) + m_view.window.ignoresMouseEvents = ignoreMouse; } void QCocoaWindow::setWindowState(Qt::WindowStates state) @@ -673,7 +667,7 @@ bool QCocoaWindow::isAlertState() const void QCocoaWindow::raise() { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::raise" << window(); + qCDebug(lcQpaWindow) << "QCocoaWindow::raise" << window(); // ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm) if (!isContentView()) @@ -698,7 +692,7 @@ void QCocoaWindow::raise() void QCocoaWindow::lower() { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::lower" << window(); + qCDebug(lcQpaWindow) << "QCocoaWindow::lower" << window(); if (!isContentView()) return; @@ -711,6 +705,22 @@ bool QCocoaWindow::isExposed() const return !m_exposedRect.isEmpty(); } +bool QCocoaWindow::isEmbedded() const +{ + // Child QWindows are not embedded + if (window()->parent()) + return false; + + // Top-level QWindows with non-Qt NSWindows are embedded + if (m_view.window) + return !([m_view.window isKindOfClass:[QNSWindow class]] || + [m_view.window isKindOfClass:[QNSPanel class]]); + + // The window has no QWindow parent but also no NSWindow, + // conservatively reuturn false. + return false; +} + bool QCocoaWindow::isOpaque() const { // OpenGL surfaces can be ordered either above(default) or below the NSWindow. @@ -730,7 +740,7 @@ void QCocoaWindow::propagateSizeHints() if (!isContentView()) return; - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::propagateSizeHints" << window() + qCDebug(lcQpaWindow) << "QCocoaWindow::propagateSizeHints" << window() << "min:" << windowMinimumSize() << "max:" << windowMaximumSize() << "increment:" << windowSizeIncrement() << "base:" << windowBaseSize(); @@ -747,7 +757,7 @@ void QCocoaWindow::propagateSizeHints() window.contentMaxSize = NSSizeFromCGSize(windowMaximumSize().toCGSize()); // The window may end up with a fixed size; in this case the zoom button should be disabled. - setWindowZoomButton(m_windowFlags); + setWindowZoomButton(this->window()->flags()); // sizeIncrement is observed to take values of (-1, -1) and (0, 0) for windows that should be // resizable and that have no specific size increment set. Cocoa expects (1.0, 1.0) in this case. @@ -764,7 +774,7 @@ void QCocoaWindow::propagateSizeHints() void QCocoaWindow::setOpacity(qreal level) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setOpacity" << level; + qCDebug(lcQpaWindow) << "QCocoaWindow::setOpacity" << level; if (!isContentView()) return; @@ -773,7 +783,7 @@ void QCocoaWindow::setOpacity(qreal level) void QCocoaWindow::setMask(const QRegion ®ion) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMask" << window() << region; + qCDebug(lcQpaWindow) << "QCocoaWindow::setMask" << window() << region; if (m_view.layer) { if (!region.isEmpty()) { @@ -807,7 +817,7 @@ void QCocoaWindow::setMask(const QRegion ®ion) bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setKeyboardGrabEnabled" << window() << grab; + qCDebug(lcQpaWindow) << "QCocoaWindow::setKeyboardGrabEnabled" << window() << grab; if (!isContentView()) return false; @@ -819,7 +829,7 @@ bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) bool QCocoaWindow::setMouseGrabEnabled(bool grab) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMouseGrabEnabled" << window() << grab; + qCDebug(lcQpaWindow) << "QCocoaWindow::setMouseGrabEnabled" << window() << grab; if (!isContentView()) return false; @@ -836,10 +846,10 @@ WId QCocoaWindow::winId() const void QCocoaWindow::setParent(const QPlatformWindow *parentWindow) { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setParent" << window() << (parentWindow ? parentWindow->window() : 0); + qCDebug(lcQpaWindow) << "QCocoaWindow::setParent" << window() << (parentWindow ? parentWindow->window() : 0); // recreate the window for compatibility - bool unhideAfterRecreate = parentWindow && !m_viewIsToBeEmbedded && ![m_view isHidden]; + bool unhideAfterRecreate = parentWindow && !isEmbedded() && ![m_view isHidden]; recreateWindowIfNeeded(); if (unhideAfterRecreate) [m_view setHidden:NO]; @@ -856,9 +866,8 @@ NSWindow *QCocoaWindow::nativeWindow() const return m_view.window; } -void QCocoaWindow::setEmbeddedInForeignView(bool embedded) +void QCocoaWindow::setEmbeddedInForeignView() { - m_viewIsToBeEmbedded = embedded; // Release any previosly created NSWindow. [m_nsWindow closeAndRelease]; m_nsWindow = 0; @@ -941,8 +950,8 @@ void QCocoaWindow::windowDidBecomeKey() QWindowSystemInterface::handleEnterEvent(m_enterLeaveTargetWindow, windowPoint, screenPoint); } - if (!windowIsPopupType() && !qnsview_cast(m_view).isMenuView) - QWindowSystemInterface::handleWindowActivated(window()); + if (!windowIsPopupType()) + QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(window()); } void QCocoaWindow::windowDidResignKey() @@ -959,8 +968,8 @@ void QCocoaWindow::windowDidResignKey() NSWindow *keyWindow = [NSApp keyWindow]; if (!keyWindow || keyWindow == m_view.window) { // No new key window, go ahead and set the active window to zero - if (!windowIsPopupType() && !qnsview_cast(m_view).isMenuView) - QWindowSystemInterface::handleWindowActivated(0); + if (!windowIsPopupType()) + QWindowSystemInterface::handleWindowActivated<QWindowSystemInterface::SynchronousDelivery>(0); } } @@ -1000,7 +1009,7 @@ void QCocoaWindow::windowDidEnterFullScreen() "FullScreen category processes window notifications first"); // Reset to original styleMask - setWindowFlags(m_windowFlags); + setWindowFlags(window()->flags()); handleWindowStateChanged(); } @@ -1024,7 +1033,7 @@ void QCocoaWindow::windowDidExitFullScreen() "FullScreen category processes window notifications first"); // Reset to original styleMask - setWindowFlags(m_windowFlags); + setWindowFlags(window()->flags()); Qt::WindowState requestedState = window()->windowState(); @@ -1076,7 +1085,7 @@ void QCocoaWindow::windowWillClose() bool QCocoaWindow::windowShouldClose() { - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::windowShouldClose" << window(); + qCDebug(lcQpaWindow) << "QCocoaWindow::windowShouldClose" << window(); // This callback should technically only determine if the window // should (be allowed to) close, but since our QPA API to determine // that also involves actually closing the window we do both at the @@ -1097,22 +1106,14 @@ void QCocoaWindow::handleGeometryChange() if (!m_initialized) return; - // Don't send the geometry change if the QWindow is designated to be - // embedded in a foreign view hierarchy but has not actually been - // embedded yet - it's too early. - if (m_viewIsToBeEmbedded && !m_viewIsEmbedded) - return; - // It can happen that the current NSWindow is nil (if we are changing styleMask // from/to borderless, and the content view is being re-parented), which results // in invalid coordinates. if (m_inSetStyleMask && !m_view.window) return; - const bool isEmbedded = m_viewIsToBeEmbedded || m_viewIsEmbedded; - QRect newGeometry; - if (isContentView() && !isEmbedded) { + if (isContentView() && !isEmbedded()) { // Content views are positioned at (0, 0) in the window, so we resolve via the window CGRect contentRect = [m_view.window contentRectForFrameRect:m_view.window.frame]; @@ -1123,7 +1124,7 @@ void QCocoaWindow::handleGeometryChange() newGeometry = QRectF::fromCGRect(m_view.frame).toRect(); } - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleGeometryChange" << window() + qCDebug(lcQpaWindow) << "QCocoaWindow::handleGeometryChange" << window() << "current" << geometry() << "new" << newGeometry; QWindowSystemInterface::handleGeometryChange(window(), newGeometry); @@ -1155,7 +1156,7 @@ void QCocoaWindow::handleExposeEvent(const QRegion ®ion) m_exposedRect = QRect(); } - qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed(); + qCDebug(lcQpaDrawing) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed(); QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), region); } @@ -1165,7 +1166,7 @@ void QCocoaWindow::handleWindowStateChanged(HandleFlags flags) if (!(flags & HandleUnconditionally) && currentState == m_lastReportedWindowState) return; - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleWindowStateChanged" << + qCDebug(lcQpaWindow) << "QCocoaWindow::handleWindowStateChanged" << m_lastReportedWindowState << "-->" << currentState; QWindowSystemInterface::handleWindowStateChanged<QWindowSystemInterface::SynchronousDelivery>( @@ -1223,6 +1224,7 @@ void QCocoaWindow::recreateWindowIfNeeded() QPlatformWindow *parentWindow = QPlatformWindow::parent(); + const bool isEmbeddedView = isEmbedded(); RecreationReasons recreateReason = RecreationNotNeeded; QCocoaWindow *oldParentCocoaWindow = nullptr; @@ -1239,7 +1241,7 @@ void QCocoaWindow::recreateWindowIfNeeded() if (m_windowModality != window()->modality()) recreateReason |= WindowModalityChanged; - const bool shouldBeContentView = !parentWindow && !(m_viewIsToBeEmbedded || m_viewIsEmbedded); + const bool shouldBeContentView = !parentWindow && !isEmbeddedView; if (isContentView() != shouldBeContentView) recreateReason |= ContentViewChanged; @@ -1251,7 +1253,7 @@ void QCocoaWindow::recreateWindowIfNeeded() if (isPanel != shouldBePanel) recreateReason |= PanelChanged; - qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window() << recreateReason; + qCDebug(lcQpaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window() << recreateReason; if (recreateReason == RecreationNotNeeded) return; @@ -1261,33 +1263,28 @@ void QCocoaWindow::recreateWindowIfNeeded() // Remove current window (if any) if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) { if (m_nsWindow) { - qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow; + qCDebug(lcQpaWindow) << "Getting rid of existing window" << m_nsWindow; if (m_nsWindow.observationInfo) { - qCCritical(lcQpaCocoaWindow) << m_nsWindow << "has active key-value observers (KVO)!" + qCCritical(lcQpaWindow) << m_nsWindow << "has active key-value observers (KVO)!" << "These will stop working now that the window is recreated, and will result in exceptions" << "when the observers are removed. Break in QCocoaWindow::recreateWindowIfNeeded to debug."; } [m_nsWindow closeAndRelease]; - if (isContentView()) { + if (isContentView() && !isEmbeddedView) { // We explicitly disassociate m_view from the window's contentView, // as AppKit does not automatically do this in response to removing // the view from the NSThemeFrame subview list, so we might end up // with a NSWindow contentView pointing to a deallocated NSView. m_view.window.contentView = nil; } - m_nsWindow = 0; + m_nsWindow = nil; } } - if (shouldBeContentView) { - bool noPreviousWindow = m_nsWindow == 0; - QCocoaNSWindow *newWindow = nullptr; - if (noPreviousWindow) - newWindow = createNSWindow(shouldBePanel); - + if (shouldBeContentView && !m_nsWindow) { // Move view to new NSWindow if needed - if (newWindow) { - qCDebug(lcQpaCocoaWindow) << "Ensuring that" << m_view << "is content view for" << newWindow; + if (auto *newWindow = createNSWindow(shouldBePanel)) { + qCDebug(lcQpaWindow) << "Ensuring that" << m_view << "is content view for" << newWindow; [m_view setPostsFrameChangedNotifications:NO]; [newWindow setContentView:m_view]; [m_view setPostsFrameChangedNotifications:YES]; @@ -1297,7 +1294,7 @@ void QCocoaWindow::recreateWindowIfNeeded() } } - if (m_viewIsToBeEmbedded) { + if (isEmbeddedView) { // An embedded window doesn't have its own NSWindow. } else if (!parentWindow) { // QPlatformWindow subclasses must sync up with QWindow on creation: @@ -1327,16 +1324,22 @@ void QCocoaWindow::recreateWindowIfNeeded() // top-level QWindows may have an attached NSToolBar, call // update function which will attach to the NSWindow. - if (!parentWindow) + if (!parentWindow && !isEmbeddedView) updateNSToolbar(); } void QCocoaWindow::requestUpdate() { - qCDebug(lcQpaCocoaDrawing) << "QCocoaWindow::requestUpdate" << window(); + qCDebug(lcQpaDrawing) << "QCocoaWindow::requestUpdate" << window(); [qnsview_cast(m_view) requestUpdate]; } +void QCocoaWindow::deliverUpdateRequest() +{ + qCDebug(lcQpaDrawing) << "Delivering update request to" << window(); + QPlatformWindow::deliverUpdateRequest(); +} + void QCocoaWindow::requestActivateWindow() { NSWindow *window = [m_view window]; @@ -1359,7 +1362,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel) } if (!targetScreen) { - qCWarning(lcQpaCocoaWindow) << "Window position outside any known screen, using primary screen"; + qCWarning(lcQpaWindow) << "Window position outside any known screen, using primary screen"; targetScreen = QGuiApplication::primaryScreen(); } |