diff options
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoawindow.mm')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 219 |
1 files changed, 91 insertions, 128 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 87a0991098..f87ddab455 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -90,16 +90,20 @@ static void qt_closePopups() @implementation QNSWindowHelper @synthesize window = _window; -@synthesize platformWindow = _platformWindow; @synthesize grabbingMouse = _grabbingMouse; @synthesize releaseOnMouseUp = _releaseOnMouseUp; +- (QCocoaWindow *)platformWindow +{ + return _platformWindow.data(); +} + - (id)initWithNSWindow:(QCocoaNSWindow *)window platformWindow:(QCocoaWindow *)platformWindow { self = [super init]; if (self) { _window = window; - _platformWindow.assign(platformWindow); + _platformWindow = platformWindow; _window.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:_platformWindow]; @@ -118,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(); @@ -159,18 +163,14 @@ 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]; } } - (void)detachFromPlatformWindow { - self.platformWindow.clear(); + _platformWindow.clear(); [self.window.delegate release]; self.window.delegate = nil; } @@ -191,7 +191,7 @@ static void qt_closePopups() - (void)dealloc { _window = nil; - self.platformWindow.clear(); + _platformWindow.clear(); [super dealloc]; } @@ -343,27 +343,14 @@ static void qt_closePopups() @end -void QCocoaWindowPointer::assign(QCocoaWindow *w) -{ - window = w; - watcher = &w->sentinel; -} - -void QCocoaWindowPointer::clear() -{ - window = Q_NULLPTR; - watcher.clear(); -} - const int QCocoaWindow::NoAlertRequest = -1; QCocoaWindow::QCocoaWindow(QWindow *tlw) : QPlatformWindow(tlw) - , m_contentView(nil) - , m_qtView(nil) + , m_view(nil) , m_nsWindow(0) - , m_contentViewIsEmbedded(false) - , m_contentViewIsToBeEmbedded(false) + , m_viewIsEmbedded(false) + , m_viewIsToBeEmbedded(false) , m_parentCocoaWindow(0) , m_isNSWindowChild(false) , m_effectivelyMaximized(false) @@ -399,11 +386,9 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) QMacAutoReleasePool pool; if (tlw->type() == Qt::ForeignWindow) { - NSView *foreignView = (NSView *)WId(tlw->property("_q_foreignWinId").value<WId>()); - setContentView(foreignView); + m_view = (NSView *)WId(tlw->property("_q_foreignWinId").value<WId>()); } else { - m_qtView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this]; - m_contentView = 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 @@ -412,14 +397,14 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) if (tlw->supportsOpenGL()) { BOOL enable = qt_mac_resolveOption(YES, tlw, "_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE"); - [m_contentView setWantsBestResolutionOpenGLSurface:enable]; + [m_view setWantsBestResolutionOpenGLSurface:enable]; } BOOL enable = qt_mac_resolveOption(NO, tlw, "_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER"); - [m_contentView setWantsLayer:enable]; + [m_view setWantsLayer:enable]; } setGeometry(tlw->geometry()); - recreateWindow(parent()); + recreateWindow(QPlatformWindow::parent()); tlw->setGeometry(geometry()); if (tlw->isTopLevel()) setWindowIcon(tlw->icon()); @@ -437,25 +422,23 @@ QCocoaWindow::~QCocoaWindow() if (m_isNSWindowChild) { if (m_parentCocoaWindow) m_parentCocoaWindow->removeChildWindow(this); - } else if ([m_contentView superview]) { - [m_contentView removeFromSuperview]; + } else if ([m_view superview]) { + [m_view removeFromSuperview]; } removeMonitor(); // 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. @@ -468,7 +451,7 @@ QCocoaWindow::~QCocoaWindow() child->m_parentCocoaWindow = 0; } - [m_contentView release]; + [m_view release]; [m_nsWindow release]; [m_windowCursor release]; } @@ -509,12 +492,12 @@ 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_contentViewIsEmbedded) { - NSPoint windowPoint = [m_contentView convertPoint:NSMakePoint(0, 0) toView:nil]; - NSRect screenRect = [[m_contentView window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; + if (m_viewIsEmbedded) { + 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; QPoint position = qt_mac_flipPoint(screenPoint).toPoint(); - QSize size = QRectF::fromCGRect(NSRectToCGRect([m_contentView bounds])).toRect().size(); + QSize size = QRectF::fromCGRect(NSRectToCGRect([m_view bounds])).toRect().size(); return QRect(position, size); } @@ -526,9 +509,9 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setCocoaGeometry" << window() << rect; QMacAutoReleasePool pool; - if (m_contentViewIsEmbedded) { - if (m_qtView) { - [m_qtView setFrame:NSMakeRect(0, 0, rect.width(), rect.height())]; + if (m_viewIsEmbedded) { + if (window()->type() != Qt::ForeignWindow) { + [m_view setFrame:NSMakeRect(0, 0, rect.width(), rect.height())]; } else { QPlatformWindow::setGeometry(rect); } @@ -548,10 +531,10 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) NSRect bounds = qt_mac_flipRect(rect); [m_nsWindow setFrame:[m_nsWindow frameRectForContentRect:bounds] display:YES animate:NO]; } else { - [m_contentView 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); // will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) @@ -576,7 +559,7 @@ void QCocoaWindow::clipWindow(const NSRect &clipRect) // Clipping top/left offsets the content. Move it back. NSPoint contentViewOffset = NSMakePoint(qMax(CGFloat(0), NSMinX(clippedWindowRect) - NSMinX(windowFrame)), qMax(CGFloat(0), NSMaxY(windowFrame) - NSMaxY(clippedWindowRect))); - [m_contentView setBoundsOrigin:contentViewOffset]; + [m_view setBoundsOrigin:contentViewOffset]; } if (NSIsEmptyRect(clippedWindowRect)) { @@ -662,7 +645,7 @@ void QCocoaWindow::setVisible(bool visible) if (visible) { // We need to recreate if the modality has changed as the style mask will need updating if (m_windowModality != window()->modality() || isNativeWindowTypeInconsistent()) - recreateWindow(parent()); + recreateWindow(QPlatformWindow::parent()); // Register popup windows. The Cocoa platform plugin will forward mouse events // to them and close them when needed. @@ -747,8 +730,8 @@ void QCocoaWindow::setVisible(bool visible) // In some cases, e.g. QDockWidget, the content view is hidden before moving to its own // Cocoa window, and then shown again. Therefore, we test for the view being hidden even // if it's attached to an NSWindow. - if ([m_contentView isHidden]) - [m_contentView setHidden:NO]; + if ([m_view isHidden]) + [m_view setHidden:NO]; } else { // qDebug() << "close" << this; #ifndef QT_NO_OPENGL @@ -781,7 +764,7 @@ void QCocoaWindow::setVisible(bool visible) [mainWindow makeKeyWindow]; } } else { - [m_contentView setHidden:YES]; + [m_view setHidden:YES]; } removeMonitor(); @@ -946,7 +929,7 @@ void QCocoaWindow::setWindowTitle(const QString &title) if (!m_nsWindow) return; - CFStringRef windowTitle = QCFString::toCFStringRef(title); + CFStringRef windowTitle = title.toCFString(); [m_nsWindow setTitle: const_cast<NSString *>(reinterpret_cast<const NSString *>(windowTitle))]; CFRelease(windowTitle); } @@ -958,7 +941,7 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath) return; QFileInfo fi(filePath); - [m_nsWindow setRepresentedFilename: fi.exists() ? QCFString::toNSString(filePath) : @""]; + [m_nsWindow setRepresentedFilename:fi.exists() ? filePath.toNSString() : @""]; } void QCocoaWindow::setWindowIcon(const QIcon &icon) @@ -969,7 +952,7 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) if (iconButton == nil) { if (icon.isNull()) return; - NSString *title = QCFString::toNSString(window()->title()); + NSString *title = window()->title().toNSString(); [m_nsWindow setRepresentedURL:[NSURL fileURLWithPath:title]]; iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton]; } @@ -1080,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; } @@ -1141,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) @@ -1171,7 +1154,7 @@ bool QCocoaWindow::setMouseGrabEnabled(bool grab) WId QCocoaWindow::winId() const { - return WId(m_contentView); + return WId(m_view); } void QCocoaWindow::setParent(const QPlatformWindow *parentWindow) @@ -1179,38 +1162,16 @@ void QCocoaWindow::setParent(const QPlatformWindow *parentWindow) qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setParent" << window() << (parentWindow ? parentWindow->window() : 0); // recreate the window for compatibility - bool unhideAfterRecreate = parentWindow && !m_contentViewIsToBeEmbedded && ![m_contentView isHidden]; + bool unhideAfterRecreate = parentWindow && !m_viewIsToBeEmbedded && ![m_view isHidden]; recreateWindow(parentWindow); if (unhideAfterRecreate) - [m_contentView setHidden:NO]; + [m_view setHidden:NO]; setCocoaGeometry(geometry()); } -NSView *QCocoaWindow::contentView() const +NSView *QCocoaWindow::view() const { - return m_contentView; -} - -void QCocoaWindow::setContentView(NSView *contentView) -{ - // Remove and release the previous content view - if (m_nsWindow) - [m_nsWindow setContentView:nil]; - else - [m_contentView removeFromSuperview]; - - [m_contentView release]; - - // Insert and retain the new content view - [contentView retain]; - m_contentView = contentView; - m_qtView = 0; // The new content view is not a QNSView. - recreateWindow(parent()); // Adds the content view to parent NSView -} - -QNSView *QCocoaWindow::qtView() const -{ - return m_qtView; + return m_view; } NSWindow *QCocoaWindow::nativeWindow() const @@ -1220,7 +1181,7 @@ NSWindow *QCocoaWindow::nativeWindow() const void QCocoaWindow::setEmbeddedInForeignView(bool embedded) { - m_contentViewIsToBeEmbedded = embedded; + m_viewIsToBeEmbedded = embedded; // Release any previosly created NSWindow. [m_nsWindow closeAndRelease]; m_nsWindow = 0; @@ -1237,7 +1198,7 @@ void QCocoaWindow::windowDidMove() if (m_isNSWindowChild) return; - [m_qtView updateGeometry]; + [qnsview_cast(m_view) updateGeometry]; } void QCocoaWindow::windowDidResize() @@ -1249,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]; } } @@ -1332,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) @@ -1351,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]; @@ -1360,13 +1321,13 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) if (oldParentCocoaWindow) { if (!m_isNSWindowChild || oldParentCocoaWindow != m_parentCocoaWindow) oldParentCocoaWindow->removeChildWindow(this); - m_forwardWindow.assign(oldParentCocoaWindow); + m_forwardWindow = oldParentCocoaWindow; } setNSWindow(m_nsWindow); } - if (m_contentViewIsToBeEmbedded) { + if (m_viewIsToBeEmbedded) { // An embedded window doesn't have its own NSWindow. } else if (!parentWindow) { // QPlatformWindow subclasses must sync up with QWindow on creation: @@ -1396,18 +1357,18 @@ void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) } } else { // Child windows have no NSWindow, link the NSViews instead. - if ([m_contentView superview]) - [m_contentView removeFromSuperview]; + if ([m_view superview]) + [m_view removeFromSuperview]; - [m_parentCocoaWindow->m_contentView addSubview : m_contentView]; + [m_parentCocoaWindow->m_view addSubview:m_view]; QRect rect = windowGeometry(); // Prevent setting a (0,0) window size; causes opengl context // "Invalid Drawable" warnings. if (rect.isNull()) rect.setSize(QSize(1, 1)); NSRect frame = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); - [m_contentView setFrame:frame]; - [m_contentView setHidden: YES]; + [m_view setFrame:frame]; + [m_view setHidden:!window()->isVisible()]; } m_nsWindow.ignoresMouseEvents = @@ -1438,9 +1399,9 @@ void QCocoaWindow::reinsertChildWindow(QCocoaWindow *child) void QCocoaWindow::requestActivateWindow() { - NSWindow *window = [m_contentView window]; - [ window makeFirstResponder : m_contentView ]; - [ window makeKeyWindow ]; + NSWindow *window = [m_view window]; + [window makeFirstResponder:m_view]; + [window makeKeyWindow]; } bool QCocoaWindow::shouldUseNSPanel() @@ -1525,14 +1486,14 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow() void QCocoaWindow::setNSWindow(QCocoaNSWindow *window) { - if (window.contentView != m_contentView) { - [m_contentView setPostsFrameChangedNotifications: NO]; - [m_contentView retain]; - if (m_contentView.superview) // m_contentView comes from another NSWindow - [m_contentView removeFromSuperview]; - [window setContentView:m_contentView]; - [m_contentView release]; - [m_contentView setPostsFrameChangedNotifications: YES]; + if (window.contentView != m_view) { + [m_view setPostsFrameChangedNotifications:NO]; + [m_view retain]; + if (m_view.superview) // m_view comes from another NSWindow + [m_view removeFromSuperview]; + [window setContentView:m_view]; + [m_view release]; + [m_view setPostsFrameChangedNotifications:YES]; } } @@ -1590,7 +1551,7 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState) return; // if content view width or height is 0 then the window animations will crash so // do nothing except set the new state - NSRect contentRect = [contentView() frame]; + NSRect contentRect = m_view.frame; if (contentRect.size.width <= 0 || contentRect.size.height <= 0) { qWarning("invalid window content view size, check your window geometry"); m_synchedWindowState = newState; @@ -1699,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]; @@ -1711,9 +1672,9 @@ void QCocoaWindow::registerTouch(bool enable) { m_registerTouchCount += enable ? 1 : -1; if (enable && m_registerTouchCount == 1) - [m_contentView setAcceptsTouchEvents:YES]; + [m_view setAcceptsTouchEvents:YES]; else if (m_registerTouchCount == 0) - [m_contentView setAcceptsTouchEvents:NO]; + [m_view setAcceptsTouchEvents:NO]; } void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickness) @@ -1813,7 +1774,7 @@ qreal QCocoaWindow::devicePixelRatio() const // methods such as [NSWindow backingScaleFacor] might not give the correct // result, for example if setWantsBestResolutionOpenGLSurface is not set or // or ignored by the OpenGL driver. - NSSize backingSize = [m_contentView convertSizeToBacking:NSMakeSize(1.0, 1.0)]; + NSSize backingSize = [m_view convertSizeToBacking:NSMakeSize(1.0, 1.0)]; return backingSize.height; } @@ -1823,8 +1784,8 @@ bool QCocoaWindow::isWindowExposable() { QSize size = geometry().size(); bool validGeometry = (size.width() > 0 && size.height() > 0); - bool validScreen = ([[m_contentView window] screen] != 0); - bool nonHiddenSuperView = ![[m_contentView superview] isHidden]; + bool validScreen = ([[m_view window] screen] != 0); + bool nonHiddenSuperView = ![[m_view superview] isHidden]; return (validGeometry && validScreen && nonHiddenSuperView); } @@ -1936,11 +1897,11 @@ QPoint QCocoaWindow::bottomLeftClippedByNSWindowOffsetStatic(QWindow *window) QPoint QCocoaWindow::bottomLeftClippedByNSWindowOffset() const { - if (!m_contentView) + if (!m_view) return QPoint(); - const NSPoint origin = [m_contentView isFlipped] ? NSMakePoint(0, [m_contentView frame].size.height) + const NSPoint origin = [m_view isFlipped] ? NSMakePoint(0, [m_view frame].size.height) : NSMakePoint(0, 0); - const NSRect visibleRect = [m_contentView visibleRect]; + const NSRect visibleRect = [m_view visibleRect]; return QPoint(visibleRect.origin.x, -visibleRect.origin.y + (origin.y - visibleRect.size.height)); } @@ -1960,3 +1921,5 @@ void QCocoaWindow::setFrameStrutEventsEnabled(bool enabled) { m_frameStrutEventsEnabled = enabled; } + +#include "moc_qcocoawindow.cpp" |