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 <erik.verbruggen@qt.io>
This commit is contained in:
Tor Arne Vestbø 2016-10-05 21:56:58 +02:00
parent 1df4b2a360
commit f835b5aa9c
9 changed files with 65 additions and 49 deletions

View File

@ -237,7 +237,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
if (QWindow *window = iface->window()) { if (QWindow *window = iface->window()) {
QCocoaWindow *win = static_cast<QCocoaWindow*>(window->handle()); QCocoaWindow *win = static_cast<QCocoaWindow*>(window->handle());
return win->qtView(); return qnsview_cast(win->view());
} }
QAccessibleInterface *parent = iface->parent(); QAccessibleInterface *parent = iface->parent();

View File

@ -40,6 +40,7 @@
#include "qcocoabackingstore.h" #include "qcocoabackingstore.h"
#include "qcocoawindow.h" #include "qcocoawindow.h"
#include "qcocoahelpers.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -51,7 +52,7 @@ QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
QCocoaBackingStore::~QCocoaBackingStore() QCocoaBackingStore::~QCocoaBackingStore()
{ {
if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle())) if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle()))
[cocoaWindow->m_qtView clearBackingStore:this]; [qnsview_cast(cocoaWindow->view()) clearBackingStore:this];
} }
QImage::Format QCocoaBackingStore::format() const QImage::Format QCocoaBackingStore::format() const
@ -68,7 +69,7 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
return; return;
if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle())) if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle()))
[cocoaWindow->m_qtView flushBackingStore:this region:region offset:offset]; [qnsview_cast(cocoaWindow->view()) flushBackingStore:this region:region offset:offset];
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -55,6 +55,8 @@
#include <QtGui/qpalette.h> #include <QtGui/qpalette.h>
#include <QtGui/qscreen.h> #include <QtGui/qscreen.h>
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSView));
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaCocoaWindow) Q_DECLARE_LOGGING_CATEGORY(lcQpaCocoaWindow)
@ -74,6 +76,8 @@ NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions); Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions); Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions);
QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view);
// Misc // Misc
void qt_mac_transformProccessToForegroundApplication(); void qt_mac_transformProccessToForegroundApplication();
QString qt_mac_applicationName(); QString qt_mac_applicationName();

View File

@ -40,7 +40,7 @@
#include <qpa/qplatformtheme.h> #include <qpa/qplatformtheme.h>
#include "qcocoahelpers.h" #include "qcocoahelpers.h"
#include "qnsview.h"
#include <QtCore> #include <QtCore>
#include <QtGui> #include <QtGui>
@ -143,7 +143,30 @@ Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
return actions; 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<QNSView *>(view);
}
// //
// Misc // Misc

View File

@ -41,6 +41,7 @@
#include "qcocoainputcontext.h" #include "qcocoainputcontext.h"
#include "qcocoanativeinterface.h" #include "qcocoanativeinterface.h"
#include "qcocoawindow.h" #include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include <Carbon/Carbon.h> #include <Carbon/Carbon.h>
@ -102,7 +103,8 @@ void QCocoaInputContext::reset()
if (!mWindow) if (!mWindow)
return; return;
QNSView *view = static_cast<QCocoaWindow *>(mWindow->handle())->qtView(); QCocoaWindow *window = static_cast<QCocoaWindow *>(mWindow->handle());
QNSView *view = qnsview_cast(window->view());
if (!view) if (!view)
return; return;

View File

@ -183,7 +183,6 @@ public:
void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE; void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
NSView *view() const; NSView *view() const;
QNSView *qtView() const;
NSWindow *nativeWindow() const; NSWindow *nativeWindow() const;
void setEmbeddedInForeignView(bool subwindow); void setEmbeddedInForeignView(bool subwindow);
@ -260,7 +259,6 @@ public: // for QNSView
void removeMonitor(); void removeMonitor();
NSView *m_view; NSView *m_view;
QNSView *m_qtView;
QCocoaNSWindow *m_nsWindow; QCocoaNSWindow *m_nsWindow;
QPointer<QCocoaWindow> m_forwardWindow; QPointer<QCocoaWindow> m_forwardWindow;

View File

@ -122,7 +122,7 @@ static void qt_closePopups()
QCocoaWindow *pw = self.platformWindow; QCocoaWindow *pw = self.platformWindow;
if (pw && pw->m_forwardWindow) { if (pw && pw->m_forwardWindow) {
if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) { if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) {
QNSView *forwardView = pw->m_qtView; QNSView *forwardView = qnsview_cast(pw->view());
if (theEvent.type == NSLeftMouseUp) { if (theEvent.type == NSLeftMouseUp) {
[forwardView mouseUp:theEvent]; [forwardView mouseUp:theEvent];
pw->m_forwardWindow.clear(); pw->m_forwardWindow.clear();
@ -163,12 +163,8 @@ static void qt_closePopups()
NSPoint loc = [theEvent locationInWindow]; NSPoint loc = [theEvent locationInWindow];
NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]];
NSRect contentFrame = [[self.window contentView] frame]; NSRect contentFrame = [[self.window contentView] frame];
if (NSMouseInRect(loc, windowFrame, NO) && if (NSMouseInRect(loc, windowFrame, NO) && !NSMouseInRect(loc, contentFrame, NO))
!NSMouseInRect(loc, contentFrame, NO)) [qnsview_cast(pw->view()) handleFrameStrutMouseEvent:theEvent];
{
QNSView *contentView = pw->m_qtView;
[contentView handleFrameStrutMouseEvent: theEvent];
}
} }
} }
@ -352,7 +348,6 @@ const int QCocoaWindow::NoAlertRequest = -1;
QCocoaWindow::QCocoaWindow(QWindow *tlw) QCocoaWindow::QCocoaWindow(QWindow *tlw)
: QPlatformWindow(tlw) : QPlatformWindow(tlw)
, m_view(nil) , m_view(nil)
, m_qtView(nil)
, m_nsWindow(0) , m_nsWindow(0)
, m_viewIsEmbedded(false) , m_viewIsEmbedded(false)
, m_viewIsToBeEmbedded(false) , m_viewIsToBeEmbedded(false)
@ -393,8 +388,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
if (tlw->type() == Qt::ForeignWindow) { if (tlw->type() == Qt::ForeignWindow) {
m_view = (NSView *)WId(tlw->property("_q_foreignWinId").value<WId>()); m_view = (NSView *)WId(tlw->property("_q_foreignWinId").value<WId>());
} else { } else {
m_qtView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this]; m_view = [[QNSView alloc] initWithQWindow:tlw platformWindow:this];
m_view = m_qtView;
// Enable high-dpi OpenGL for retina displays. Enabling has the side // Enable high-dpi OpenGL for retina displays. Enabling has the side
// effect that Cocoa will start calling glViewport(0, 0, width, height), // effect that Cocoa will start calling glViewport(0, 0, width, height),
// overriding any glViewport calls in application code. This is usually not a // 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 // Make sure to disconnect observer in all case if view is valid
// to avoid notifications received when deleting when using Qt::AA_NativeWindows attribute // to avoid notifications received when deleting when using Qt::AA_NativeWindows attribute
if (m_qtView) { if (window()->type() != Qt::ForeignWindow)
[[NSNotificationCenter defaultCenter] removeObserver:m_qtView]; [[NSNotificationCenter defaultCenter] removeObserver:m_view];
}
// The QNSView object may outlive the corresponding QCocoaWindow object, // The QNSView object may outlive the corresponding QCocoaWindow object,
// for example during app shutdown when the QNSView is embedded in a // for example during app shutdown when the QNSView is embedded in a
// foregin NSView hiearchy. Clear the pointers to the QWindow/QCocoaWindow // foregin NSView hiearchy. Clear the pointers to the QWindow/QCocoaWindow
// here to make sure QNSView does not dereference stale pointers. // here to make sure QNSView does not dereference stale pointers.
if (m_qtView) { if (window()->type() != Qt::ForeignWindow)
[m_qtView clearQWindowPointers]; [qnsview_cast(m_view) clearQWindowPointers];
}
// While it is unlikely that this window will be in the popup stack // While it is unlikely that this window will be in the popup stack
// during deletetion we clear any pointers here to make sure. // during deletetion we clear any pointers here to make sure.
@ -518,8 +510,8 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
QMacAutoReleasePool pool; QMacAutoReleasePool pool;
if (m_viewIsEmbedded) { if (m_viewIsEmbedded) {
if (m_qtView) { if (window()->type() != Qt::ForeignWindow) {
[m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())]; [m_view setFrame:NSMakeRect(0, 0, rect.width(), rect.height())];
} else { } else {
QPlatformWindow::setGeometry(rect); 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())]; [m_view setFrame:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
} }
if (!m_qtView) if (window()->type() == Qt::ForeignWindow)
QPlatformWindow::setGeometry(rect); QPlatformWindow::setGeometry(rect);
// will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) // 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. // When ordering below the window must be tranclucent.
static GLint openglSourfaceOrder = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER"); 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 || window()->opacity() < 1
|| (m_qtView && [m_qtView hasMask])) || [qnsview_cast(m_view) hasMask]
|| (surface()->supportsOpenGL() && openglSourfaceOrder == -1); || (surface()->supportsOpenGL() && openglSourfaceOrder == -1);
return !translucent; return !translucent;
} }
@ -1132,8 +1124,8 @@ void QCocoaWindow::setMask(const QRegion &region)
if (m_nsWindow) if (m_nsWindow)
[m_nsWindow setBackgroundColor:[NSColor clearColor]]; [m_nsWindow setBackgroundColor:[NSColor clearColor]];
[m_qtView setMaskRegion:&region]; [qnsview_cast(m_view) setMaskRegion:&region];
[m_nsWindow setOpaque: isOpaque()]; [m_nsWindow setOpaque:isOpaque()];
} }
bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
@ -1182,11 +1174,6 @@ NSView *QCocoaWindow::view() const
return m_view; return m_view;
} }
QNSView *QCocoaWindow::qtView() const
{
return m_qtView;
}
NSWindow *QCocoaWindow::nativeWindow() const NSWindow *QCocoaWindow::nativeWindow() const
{ {
return m_nsWindow; return m_nsWindow;
@ -1211,7 +1198,7 @@ void QCocoaWindow::windowDidMove()
if (m_isNSWindowChild) if (m_isNSWindowChild)
return; return;
[m_qtView updateGeometry]; [qnsview_cast(m_view) updateGeometry];
} }
void QCocoaWindow::windowDidResize() void QCocoaWindow::windowDidResize()
@ -1223,14 +1210,14 @@ void QCocoaWindow::windowDidResize()
return; return;
clipChildWindows(); clipChildWindows();
[m_qtView updateGeometry]; [qnsview_cast(m_view) updateGeometry];
} }
void QCocoaWindow::windowDidEndLiveResize() void QCocoaWindow::windowDidEndLiveResize()
{ {
if (m_synchedWindowState == Qt::WindowMaximized && ![m_nsWindow isZoomed]) { if (m_synchedWindowState == Qt::WindowMaximized && ![m_nsWindow isZoomed]) {
m_effectivelyMaximized = false; 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]]; bool usesNSPanel = [m_nsWindow isKindOfClass:[QNSPanel class]];
// No child QNSWindow should notify its QNSView // No child QNSWindow should notify its QNSView
if (m_nsWindow && m_qtView && m_parentCocoaWindow && !oldParentCocoaWindow) if (m_nsWindow && (window()->type() != Qt::ForeignWindow) && m_parentCocoaWindow && !oldParentCocoaWindow)
[[NSNotificationCenter defaultCenter] removeObserver:m_qtView [[NSNotificationCenter defaultCenter] removeObserver:m_view
name:nil object:m_nsWindow]; name:nil object:m_nsWindow];
// Remove current window (if any) // Remove current window (if any)
@ -1325,8 +1312,8 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
// Only non-child QNSWindows should notify their QNSViews // Only non-child QNSWindows should notify their QNSViews
// (but don't register more than once). // (but don't register more than once).
if (m_qtView && (noPreviousWindow || (wasNSWindowChild && !m_isNSWindowChild))) if ((window()->type() != Qt::ForeignWindow) && (noPreviousWindow || (wasNSWindowChild && !m_isNSWindowChild)))
[[NSNotificationCenter defaultCenter] addObserver:m_qtView [[NSNotificationCenter defaultCenter] addObserver:m_view
selector:@selector(windowNotification:) selector:@selector(windowNotification:)
name:nil // Get all notifications name:nil // Get all notifications
object:m_nsWindow]; object:m_nsWindow];
@ -1673,8 +1660,8 @@ void QCocoaWindow::setWindowCursor(NSCursor *cursor)
// Othervise, set the cursor if this window is under the mouse. In // Othervise, set the cursor if this window is under the mouse. In
// this case QNSView::cursorUpdate will set the cursor as the pointer // this case QNSView::cursorUpdate will set the cursor as the pointer
// moves. // moves.
if (m_nsWindow && m_qtView) { if (m_nsWindow && window()->type() != Qt::ForeignWindow) {
[m_nsWindow invalidateCursorRectsForView : m_qtView]; [m_nsWindow invalidateCursorRectsForView:m_view];
} else { } else {
if (m_windowUnderMouse) if (m_windowUnderMouse)
[cursor set]; [cursor set];

View File

@ -749,7 +749,7 @@ static bool _q_dontOverrideCtrlLMB = false;
QNSView *targetView = self; QNSView *targetView = self;
if (m_platformWindow && m_platformWindow->m_forwardWindow) { if (m_platformWindow && m_platformWindow->m_forwardWindow) {
if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp) if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)
targetView = m_platformWindow->m_forwardWindow->m_qtView; targetView = qnsview_cast(m_platformWindow->m_forwardWindow->view());
else else
m_platformWindow->m_forwardWindow.clear(); m_platformWindow->m_forwardWindow.clear();
} }
@ -759,7 +759,7 @@ static bool _q_dontOverrideCtrlLMB = false;
// Tooltips must be transparent for mouse events // Tooltips must be transparent for mouse events
// The bug reference is QTBUG-46379 // The bug reference is QTBUG-46379
if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) { if (!popup->m_windowFlags.testFlag(Qt::ToolTip)) {
if (QNSView *popupView = popup->qtView()) if (QNSView *popupView = qnsview_cast(popup->view()))
targetView = popupView; targetView = popupView;
} }
} }

View File

@ -38,6 +38,7 @@
****************************************************************************/ ****************************************************************************/
#include "qnswindowdelegate.h" #include "qnswindowdelegate.h"
#include "qcocoahelpers.h"
#include <QDebug> #include <QDebug>
#include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface.h>
@ -60,7 +61,7 @@
if (m_cocoaWindow->m_windowUnderMouse) { if (m_cocoaWindow->m_windowUnderMouse) {
QPointF windowPoint; QPointF windowPoint;
QPointF screenPoint; 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); QWindowSystemInterface::handleEnterEvent(m_cocoaWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
} }
} }
@ -110,8 +111,8 @@
- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame - (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame
{ {
Q_UNUSED(newFrame); Q_UNUSED(newFrame);
if (m_cocoaWindow && m_cocoaWindow->m_qtView) if (m_cocoaWindow && m_cocoaWindow->window()->type() != Qt::ForeignWindow)
[m_cocoaWindow->m_qtView notifyWindowWillZoom:![window isZoomed]]; [qnsview_cast(m_cocoaWindow->view()) notifyWindowWillZoom:![window isZoomed]];
return YES; return YES;
} }