From f835b5aa9cba2665423e6e96a45d97c3c80296a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 5 Oct 2016 21:56:58 +0200 Subject: macOS: Get rid of m_qtView member in QCocoaWindow that aliased m_view The member was mirroring m_view in all cases except for foreign windows. Instead of a member we now check window()->type() != Qt::ForeignWindow, which is more explicit, especially for people not normally working on the macOS platform. To call methods that are only implemented for our QNSView subclass, a new qnsview_cast() function has been introduced. Change-Id: I0a2cfe1a5e4502250c17e1c3ebdce19e9ee5e572 Reviewed-by: Erik Verbruggen --- .../platforms/cocoa/qcocoaaccessibilityelement.mm | 2 +- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 5 +- src/plugins/platforms/cocoa/qcocoahelpers.h | 4 ++ src/plugins/platforms/cocoa/qcocoahelpers.mm | 25 ++++++++- src/plugins/platforms/cocoa/qcocoainputcontext.mm | 4 +- src/plugins/platforms/cocoa/qcocoawindow.h | 2 - src/plugins/platforms/cocoa/qcocoawindow.mm | 61 +++++++++------------- src/plugins/platforms/cocoa/qnsview.mm | 4 +- src/plugins/platforms/cocoa/qnswindowdelegate.mm | 7 +-- 9 files changed, 65 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 5bad5973c4..9c410506b0 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -237,7 +237,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of if (QWindow *window = iface->window()) { QCocoaWindow *win = static_cast(window->handle()); - return win->qtView(); + return qnsview_cast(win->view()); } QAccessibleInterface *parent = iface->parent(); diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index af5418315c..a74995319b 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -40,6 +40,7 @@ #include "qcocoabackingstore.h" #include "qcocoawindow.h" +#include "qcocoahelpers.h" QT_BEGIN_NAMESPACE @@ -51,7 +52,7 @@ QCocoaBackingStore::QCocoaBackingStore(QWindow *window) QCocoaBackingStore::~QCocoaBackingStore() { if (QCocoaWindow *cocoaWindow = static_cast(window()->handle())) - [cocoaWindow->m_qtView clearBackingStore:this]; + [qnsview_cast(cocoaWindow->view()) clearBackingStore:this]; } QImage::Format QCocoaBackingStore::format() const @@ -68,7 +69,7 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo return; if (QCocoaWindow *cocoaWindow = static_cast(window->handle())) - [cocoaWindow->m_qtView flushBackingStore:this region:region offset:offset]; + [qnsview_cast(cocoaWindow->view()) flushBackingStore:this region:region offset:offset]; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 536a2d2d58..1b038a6b5e 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -55,6 +55,8 @@ #include #include +Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSView)); + QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQpaCocoaWindow) @@ -74,6 +76,8 @@ NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions); Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions); Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions); +QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view); + // Misc void qt_mac_transformProccessToForegroundApplication(); QString qt_mac_applicationName(); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 1dee11678e..c57567bdd6 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -40,7 +40,7 @@ #include #include "qcocoahelpers.h" - +#include "qnsview.h" #include #include @@ -143,7 +143,30 @@ Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions) return actions; } +/*! + Returns the view cast to a QNSview if possible. + + If the view is not a QNSView, nil is returned, which is safe to + send messages to, effectivly making [qnsview_cast(view) message] + a no-op. + For extra verbosity and clearer code, please consider checking + that window()->type() != Qt::ForeignWindow before using this cast. + + Do not use this method soley to check for foreign windows, as + that will make the code harder to read for people not working + primarily on macOS, who do not know the difference between the + NSView and QNSView cases. +*/ +QNSView *qnsview_cast(NSView *view) +{ + if (![view isKindOfClass:[QNSView class]]) { + qCWarning(lcQpaCocoaWindow) << "NSView is not QNSView, consider checking for Qt::ForeignWindow"; + return nil; + } + + return static_cast(view); +} // // Misc diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index ae060d5e2d..9e3d747cd7 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -41,6 +41,7 @@ #include "qcocoainputcontext.h" #include "qcocoanativeinterface.h" #include "qcocoawindow.h" +#include "qcocoahelpers.h" #include @@ -102,7 +103,8 @@ void QCocoaInputContext::reset() if (!mWindow) return; - QNSView *view = static_cast(mWindow->handle())->qtView(); + QCocoaWindow *window = static_cast(mWindow->handle()); + QNSView *view = qnsview_cast(window->view()); if (!view) return; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 11bd6b5cb9..bd7b23bc1b 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -183,7 +183,6 @@ public: void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE; NSView *view() const; - QNSView *qtView() const; NSWindow *nativeWindow() const; void setEmbeddedInForeignView(bool subwindow); @@ -260,7 +259,6 @@ public: // for QNSView void removeMonitor(); NSView *m_view; - QNSView *m_qtView; QCocoaNSWindow *m_nsWindow; QPointer m_forwardWindow; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index b5503be1a7..c75090f0c2 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -122,7 +122,7 @@ static void qt_closePopups() QCocoaWindow *pw = self.platformWindow; if (pw && pw->m_forwardWindow) { if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) { - QNSView *forwardView = pw->m_qtView; + QNSView *forwardView = qnsview_cast(pw->view()); if (theEvent.type == NSLeftMouseUp) { [forwardView mouseUp:theEvent]; pw->m_forwardWindow.clear(); @@ -163,12 +163,8 @@ static void qt_closePopups() NSPoint loc = [theEvent locationInWindow]; NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; NSRect contentFrame = [[self.window contentView] frame]; - if (NSMouseInRect(loc, windowFrame, NO) && - !NSMouseInRect(loc, contentFrame, NO)) - { - QNSView *contentView = pw->m_qtView; - [contentView handleFrameStrutMouseEvent: theEvent]; - } + if (NSMouseInRect(loc, windowFrame, NO) && !NSMouseInRect(loc, contentFrame, NO)) + [qnsview_cast(pw->view()) handleFrameStrutMouseEvent:theEvent]; } } @@ -352,7 +348,6 @@ const int QCocoaWindow::NoAlertRequest = -1; QCocoaWindow::QCocoaWindow(QWindow *tlw) : QPlatformWindow(tlw) , m_view(nil) - , m_qtView(nil) , m_nsWindow(0) , m_viewIsEmbedded(false) , m_viewIsToBeEmbedded(false) @@ -393,8 +388,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) if (tlw->type() == Qt::ForeignWindow) { m_view = (NSView *)WId(tlw->property("_q_foreignWinId").value()); } else { - m_qtView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this]; - m_view = m_qtView; + m_view = [[QNSView alloc] initWithQWindow:tlw platformWindow:this]; // Enable high-dpi OpenGL for retina displays. Enabling has the side // effect that Cocoa will start calling glViewport(0, 0, width, height), // overriding any glViewport calls in application code. This is usually not a @@ -436,17 +430,15 @@ QCocoaWindow::~QCocoaWindow() // Make sure to disconnect observer in all case if view is valid // to avoid notifications received when deleting when using Qt::AA_NativeWindows attribute - if (m_qtView) { - [[NSNotificationCenter defaultCenter] removeObserver:m_qtView]; - } + if (window()->type() != Qt::ForeignWindow) + [[NSNotificationCenter defaultCenter] removeObserver:m_view]; // The QNSView object may outlive the corresponding QCocoaWindow object, // for example during app shutdown when the QNSView is embedded in a // foregin NSView hiearchy. Clear the pointers to the QWindow/QCocoaWindow // here to make sure QNSView does not dereference stale pointers. - if (m_qtView) { - [m_qtView clearQWindowPointers]; - } + if (window()->type() != Qt::ForeignWindow) + [qnsview_cast(m_view) clearQWindowPointers]; // While it is unlikely that this window will be in the popup stack // during deletetion we clear any pointers here to make sure. @@ -518,8 +510,8 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) QMacAutoReleasePool pool; if (m_viewIsEmbedded) { - if (m_qtView) { - [m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())]; + if (window()->type() != Qt::ForeignWindow) { + [m_view setFrame:NSMakeRect(0, 0, rect.width(), rect.height())]; } else { QPlatformWindow::setGeometry(rect); } @@ -542,7 +534,7 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) [m_view setFrame:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; } - if (!m_qtView) + if (window()->type() == Qt::ForeignWindow) QPlatformWindow::setGeometry(rect); // will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) @@ -1071,9 +1063,9 @@ bool QCocoaWindow::isOpaque() const // 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 + bool translucent = window()->format().alphaBufferSize() > 0 || window()->opacity() < 1 - || (m_qtView && [m_qtView hasMask])) + || [qnsview_cast(m_view) hasMask] || (surface()->supportsOpenGL() && openglSourfaceOrder == -1); return !translucent; } @@ -1132,8 +1124,8 @@ void QCocoaWindow::setMask(const QRegion ®ion) if (m_nsWindow) [m_nsWindow setBackgroundColor:[NSColor clearColor]]; - [m_qtView setMaskRegion:®ion]; - [m_nsWindow setOpaque: isOpaque()]; + [qnsview_cast(m_view) setMaskRegion:®ion]; + [m_nsWindow setOpaque:isOpaque()]; } bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) @@ -1182,11 +1174,6 @@ NSView *QCocoaWindow::view() const return m_view; } -QNSView *QCocoaWindow::qtView() const -{ - return m_qtView; -} - NSWindow *QCocoaWindow::nativeWindow() const { return m_nsWindow; @@ -1211,7 +1198,7 @@ void QCocoaWindow::windowDidMove() if (m_isNSWindowChild) return; - [m_qtView updateGeometry]; + [qnsview_cast(m_view) updateGeometry]; } void QCocoaWindow::windowDidResize() @@ -1223,14 +1210,14 @@ void QCocoaWindow::windowDidResize() return; clipChildWindows(); - [m_qtView updateGeometry]; + [qnsview_cast(m_view) updateGeometry]; } void QCocoaWindow::windowDidEndLiveResize() { if (m_synchedWindowState == Qt::WindowMaximized && ![m_nsWindow isZoomed]) { m_effectivelyMaximized = false; - [m_qtView notifyWindowStateChanged:Qt::WindowNoState]; + [qnsview_cast(m_view) notifyWindowStateChanged:Qt::WindowNoState]; } } @@ -1306,8 +1293,8 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) bool usesNSPanel = [m_nsWindow isKindOfClass:[QNSPanel class]]; // No child QNSWindow should notify its QNSView - if (m_nsWindow && m_qtView && m_parentCocoaWindow && !oldParentCocoaWindow) - [[NSNotificationCenter defaultCenter] removeObserver:m_qtView + if (m_nsWindow && (window()->type() != Qt::ForeignWindow) && m_parentCocoaWindow && !oldParentCocoaWindow) + [[NSNotificationCenter defaultCenter] removeObserver:m_view name:nil object:m_nsWindow]; // Remove current window (if any) @@ -1325,8 +1312,8 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) // Only non-child QNSWindows should notify their QNSViews // (but don't register more than once). - if (m_qtView && (noPreviousWindow || (wasNSWindowChild && !m_isNSWindowChild))) - [[NSNotificationCenter defaultCenter] addObserver:m_qtView + if ((window()->type() != Qt::ForeignWindow) && (noPreviousWindow || (wasNSWindowChild && !m_isNSWindowChild))) + [[NSNotificationCenter defaultCenter] addObserver:m_view selector:@selector(windowNotification:) name:nil // Get all notifications object:m_nsWindow]; @@ -1673,8 +1660,8 @@ void QCocoaWindow::setWindowCursor(NSCursor *cursor) // Othervise, set the cursor if this window is under the mouse. In // this case QNSView::cursorUpdate will set the cursor as the pointer // moves. - if (m_nsWindow && m_qtView) { - [m_nsWindow invalidateCursorRectsForView : m_qtView]; + if (m_nsWindow && window()->type() != Qt::ForeignWindow) { + [m_nsWindow invalidateCursorRectsForView:m_view]; } else { if (m_windowUnderMouse) [cursor set]; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 7ac3cafc3c..be2342d51e 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -749,7 +749,7 @@ static bool _q_dontOverrideCtrlLMB = false; QNSView *targetView = self; if (m_platformWindow && m_platformWindow->m_forwardWindow) { if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp) - targetView = m_platformWindow->m_forwardWindow->m_qtView; + targetView = qnsview_cast(m_platformWindow->m_forwardWindow->view()); else m_platformWindow->m_forwardWindow.clear(); } @@ -759,7 +759,7 @@ static bool _q_dontOverrideCtrlLMB = false; // Tooltips must be transparent for mouse events // The bug reference is QTBUG-46379 if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) { - if (QNSView *popupView = popup->qtView()) + if (QNSView *popupView = qnsview_cast(popup->view())) targetView = popupView; } } diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm index b96a9491e8..cbae4fc50f 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qnswindowdelegate.h" +#include "qcocoahelpers.h" #include #include @@ -60,7 +61,7 @@ if (m_cocoaWindow->m_windowUnderMouse) { QPointF windowPoint; QPointF screenPoint; - [m_cocoaWindow->m_qtView convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; + [qnsview_cast(m_cocoaWindow->view()) convertFromScreen:[NSEvent mouseLocation] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; QWindowSystemInterface::handleEnterEvent(m_cocoaWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint); } } @@ -110,8 +111,8 @@ - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame { Q_UNUSED(newFrame); - if (m_cocoaWindow && m_cocoaWindow->m_qtView) - [m_cocoaWindow->m_qtView notifyWindowWillZoom:![window isZoomed]]; + if (m_cocoaWindow && m_cocoaWindow->window()->type() != Qt::ForeignWindow) + [qnsview_cast(m_cocoaWindow->view()) notifyWindowWillZoom:![window isZoomed]]; return YES; } -- cgit v1.2.3