From 0caaf9966a8e4ea1e83de866020e61fd5ffaec1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 16 Dec 2013 22:38:13 +0100 Subject: Cocoa: Add setContentBorderThickness(). Add setContentBorderThickness() to the Cocoa platform plugin. This functions requests that the platform plugin draws a gradient in the unified title and toolbar area and/or the status bar area. The background gradient is drawn before and under the Qt backing store content. It is expected that parts of the backing store will be filled with transparent pixels to allow the gradient to be visible. To facilitate this the backing store image is created with an alpha channel. Task-number: QTBUG-34411 Change-Id: Iadc5e64ee9b9b42e92fb84a615817fdffd7a8802 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 3 +- .../platforms/cocoa/qcocoanativeinterface.h | 3 ++ .../platforms/cocoa/qcocoanativeinterface.mm | 12 +++++++ src/plugins/platforms/cocoa/qcocoawindow.h | 6 ++++ src/plugins/platforms/cocoa/qcocoawindow.mm | 41 ++++++++++++++++++++++ src/plugins/platforms/cocoa/qnsview.mm | 6 +++- 6 files changed, 69 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 665b3d4c13..30c15d823a 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -73,7 +73,8 @@ QPaintDevice *QCocoaBackingStore::paintDevice() } #endif - QImage::Format format = window()->format().hasAlpha() + QCocoaWindow *cocoaWindow = static_cast(window()->handle()); + QImage::Format format = (window()->format().hasAlpha() || cocoaWindow->m_drawContentBorderGradient) ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32; m_qImage = QImage(m_requestedSize * scaleFactor, format); m_qImage.setDevicePixelRatio(scaleFactor); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index d30b281eb8..5c59c73847 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -132,6 +132,9 @@ private: // touch events, which then will be delivered until the widget // deregisters. static void registerTouchWindow(QWindow *window, bool enable); + + // Request a unified title and toolbar look for the window. + static void setContentBorderThickness(QWindow *window, int topThickness, int bottomThickness); }; #endif // QCOCOANATIVEINTERFACE_H diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 6facab1785..eb520b97c9 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -123,6 +123,8 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter return NativeResourceForIntegrationFunction(QCocoaNativeInterface::registerTouchWindow); if (resource.toLower() == "setembeddedinforeignview") return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setEmbeddedInForeignView); + if (resource.toLower() == "setcontentborderthickness") + return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setContentBorderThickness); return 0; } @@ -273,4 +275,14 @@ void QCocoaNativeInterface::registerTouchWindow(QWindow *window, bool enable) cocoaWindow->registerTouch(enable); } +void QCocoaNativeInterface::setContentBorderThickness(QWindow *window, int topThickness, int bottomThickness) +{ + if (!window) + return; + + QCocoaWindow *cocoaWindow = static_cast(window->handle()); + if (cocoaWindow) + cocoaWindow->setContentBorderThickness(topThickness, bottomThickness); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index c7ec315f04..66c3241b3d 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -157,6 +157,8 @@ public: void setWindowCursor(NSCursor *cursor); void registerTouch(bool enable); + void setContentBorderThickness(int topThickness, int bottomThickness); + void applyContentBorderThickness(NSWindow *window); qreal devicePixelRatio() const; bool isWindowExposable(); @@ -214,6 +216,10 @@ public: // for QNSView static const int NoAlertRequest; NSInteger m_alertRequest; id monitor; + + bool m_drawContentBorderGradient; + int m_topContentBorderThickness; + int m_bottomContentBorderThickness; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index ad11a525ad..8e977236fa 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -220,6 +220,9 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_overrideBecomeKey(false) , m_alertRequest(NoAlertRequest) , monitor(nil) + , m_drawContentBorderGradient(false) + , m_topContentBorderThickness(0) + , m_bottomContentBorderThickness(0) { #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug() << "QCocoaWindow::QCocoaWindow" << this; @@ -502,6 +505,9 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) } } + if (m_drawContentBorderGradient) + styleMask |= NSTexturedBackgroundWindowMask; + #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug("windowStyleMask of '%s': flags %X -> styleMask %lX", qPrintable(window()->title()), (int)flags, styleMask); #endif @@ -927,6 +933,9 @@ NSWindow * QCocoaWindow::createNSWindow() } m_windowModality = window()->modality(); + + applyContentBorderThickness(createdWindow); + return createdWindow; } @@ -1069,6 +1078,38 @@ void QCocoaWindow::registerTouch(bool enable) [m_contentView setAcceptsTouchEvents:NO]; } +void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickness) +{ + m_topContentBorderThickness = topThickness; + m_bottomContentBorderThickness = bottomThickness; + bool enable = (topThickness > 0 || bottomThickness > 0); + m_drawContentBorderGradient = enable; + + applyContentBorderThickness(m_nsWindow); +} + +void QCocoaWindow::applyContentBorderThickness(NSWindow *window) +{ + if (!window) + return; + + if (m_drawContentBorderGradient) + [window setStyleMask:[window styleMask] | NSTexturedBackgroundWindowMask]; + else + [window setStyleMask:[window styleMask] & ~NSTexturedBackgroundWindowMask]; + + if (m_topContentBorderThickness > 0) { + [window setContentBorderThickness:m_topContentBorderThickness forEdge:NSMaxYEdge]; + [window setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge]; + } + + if (m_bottomContentBorderThickness > 0) { + [window setContentBorderThickness:m_topContentBorderThickness forEdge:NSMinYEdge]; + [window setAutorecalculatesContentBorderThickness:NO forEdge:NSMinYEdge]; + } +} + + qreal QCocoaWindow::devicePixelRatio() const { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index e183f93c6c..f7b129aea1 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -408,6 +408,9 @@ static QTouchDevice *touchDevice = 0; m_shouldSetGLContextinDrawRect = false; } + if (m_platformWindow->m_drawContentBorderGradient) + NSDrawWindowBackground(dirtyRect); + if (!m_backingStore) return; @@ -451,7 +454,8 @@ static QTouchDevice *touchDevice = 0; // Optimization: Copy frame buffer content instead of blending for // top-level windows where Qt fills the entire window content area. - if (m_platformWindow->m_nsWindow) + // (But don't overpaint the title-bar gradient) + if (m_platformWindow->m_nsWindow && !m_platformWindow->m_drawContentBorderGradient) CGContextSetBlendMode(cgContext, kCGBlendModeCopy); CGContextDrawImage(cgContext, dirtyWindowRect, cleanImg); -- cgit v1.2.3