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()) {
QCocoaWindow *win = static_cast<QCocoaWindow*>(window->handle());
return win->qtView();
return qnsview_cast(win->view());
}
QAccessibleInterface *parent = iface->parent();

View File

@ -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<QCocoaWindow *>(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 &region, const QPo
return;
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

View File

@ -55,6 +55,8 @@
#include <QtGui/qpalette.h>
#include <QtGui/qscreen.h>
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();

View File

@ -40,7 +40,7 @@
#include <qpa/qplatformtheme.h>
#include "qcocoahelpers.h"
#include "qnsview.h"
#include <QtCore>
#include <QtGui>
@ -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<QNSView *>(view);
}
//
// Misc

View File

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

View File

@ -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<QCocoaWindow> m_forwardWindow;

View File

@ -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<WId>());
} 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 &region)
if (m_nsWindow)
[m_nsWindow setBackgroundColor:[NSColor clearColor]];
[m_qtView setMaskRegion:&region];
[m_nsWindow setOpaque: isOpaque()];
[qnsview_cast(m_view) setMaskRegion:&region];
[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];

View File

@ -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;
}
}

View File

@ -38,6 +38,7 @@
****************************************************************************/
#include "qnswindowdelegate.h"
#include "qcocoahelpers.h"
#include <QDebug>
#include <qpa/qwindowsysteminterface.h>
@ -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;
}