diff options
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoanativeinterface.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoanativeinterface.mm | 13 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 6 | ||||
-rw-r--r-- | src/widgets/styles/qmacstyle_mac.mm | 57 | ||||
-rw-r--r-- | src/widgets/widgets/qtabbar.cpp | 71 | ||||
-rw-r--r-- | src/widgets/widgets/qtabbar_p.h | 1 |
7 files changed, 112 insertions, 41 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 0318c52628..54e45a1d99 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -147,6 +147,10 @@ private: // Enables or disiables a content border area. static void setContentBorderAreaEnabled(QWindow *window, quintptr identifier, bool enable); + // Returns true if the given coordinate is inside the current + // content border. + static bool testContentBorderPosition(QWindow *window, int position); + // Sets a NSToolbar instance for the given QWindow. The // toolbar will be attached to the native NSWindow when // that is created; diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index b18c586212..e09c31231d 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -133,6 +133,8 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setContentBorderEnabled); if (resource.toLower() == "setnstoolbar") return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setNSToolbar); + if (resource.toLower() == "testcontentborderposition") + return NativeResourceForIntegrationFunction(QCocoaNativeInterface::testContentBorderPosition); return 0; } @@ -332,4 +334,15 @@ void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar) cocoaWindow->updateNSToolbar(); } +bool QCocoaNativeInterface::testContentBorderPosition(QWindow *window, int position) +{ + if (!window) + return false; + + QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle()); + if (cocoaWindow) + return cocoaWindow->testContentBorderAreaPosition(position); + return false; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index d8eb0ed0bd..7a01835d5b 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -213,6 +213,7 @@ public: void registerContentBorderArea(quintptr identifier, int upper, int lower); void setContentBorderAreaEnabled(quintptr identifier, bool enable); void setContentBorderEnabled(bool enable); + bool testContentBorderAreaPosition(int position) const; void applyContentBorderThickness(NSWindow *window); void updateNSToolbar(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 515e2bf132..5a4ac9b2cc 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1665,6 +1665,12 @@ void QCocoaWindow::updateNSToolbar() [m_nsWindow setShowsToolbarButton:YES]; } +bool QCocoaWindow::testContentBorderAreaPosition(int position) const +{ + return m_nsWindow && m_drawContentBorderGradient && + 0 <= position && position < [m_nsWindow contentBorderThicknessForEdge: NSMaxYEdge]; +} + qreal QCocoaWindow::devicePixelRatio() const { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 2d8489f47f..d35dd16f85 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -179,6 +179,19 @@ static bool isVerticalTabs(const QTabBar::Shape shape) { || shape == QTabBar::TriangularWest); } +static bool isInMacUnifiedToolbarArea(QWindow *window, int windowY) +{ + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + QPlatformNativeInterface::NativeResourceForIntegrationFunction function = + nativeInterface->nativeResourceFunctionForIntegration("testContentBorderPosition"); + if (!function) + return false; // Not Cocoa platform plugin. + + typedef bool (*TestContentBorderPositionFunction)(QWindow *, int); + return (reinterpret_cast<TestContentBorderPositionFunction>(function))(window, windowY); +} + + void drawTabCloseButton(QPainter *p, bool hover, bool active, bool selected) { // draw background circle @@ -239,7 +252,7 @@ QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect) return tabRect; } -void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt) +void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt, bool isUnified) { QRect r = tabOpt->rect; p->translate(tabOpt->rect.x(), tabOpt->rect.y()); @@ -256,7 +269,12 @@ void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt) QRect rect(1, 0, width - 2, height); // fill body - if (active) { + if (tabOpt->documentMode && isUnified) { + p->save(); + p->setCompositionMode(QPainter::CompositionMode_Source); + p->fillRect(rect, QColor(Qt::transparent)); + p->restore(); + } else if (active) { int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 16 : 0; p->fillRect(rect, QColor(151 + d, 151 + d, 151 + d)); } else { @@ -3733,8 +3751,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { if (tabOptV3->documentMode) { p->save(); - // QRect tabRect = tabOptV3->rect; - drawTabShape(p, tabOptV3); + bool isUnified = false; + if (w) { + QRect tabRect = tabOptV3->rect; + QPoint windowTabStart = w->mapTo(w->window(), tabRect.topLeft()); + isUnified = isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowTabStart.y()); + } + + drawTabShape(p, tabOptV3, isUnified); p->restore(); return; } @@ -4442,15 +4466,22 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter p->fillRect(opt->rect, Qt::transparent); p->restore(); - // drow horizontal sepearator line at toolBar bottom. - SInt32 margin; - GetThemeMetric(kThemeMetricSeparatorSize, &margin); - CGRect separatorRect = CGRectMake(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin); - HIThemeSeparatorDrawInfo separatorDrawInfo; - separatorDrawInfo.version = 0; - separatorDrawInfo.state = qt_macWindowMainWindow(mainWindow) ? kThemeStateActive : kThemeStateInactive; - QMacCGContext cg(p); - HIThemeDrawSeparator(&separatorRect, &separatorDrawInfo, cg, kHIThemeOrientationNormal); + // Drow a horizontal sepearator line at the toolBar bottom if the "unified" area ends here. + // There might be additional toolbars or other widgets such as tab bars in document + // mode below. Determine this by making a unified toolbar area test for the row below + // this toolbar. + QPoint windowToolbarEnd = w->mapTo(w->window(), opt->rect.bottomLeft()); + bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1); + if (isEndOfUnifiedArea) { + SInt32 margin; + GetThemeMetric(kThemeMetricSeparatorSize, &margin); + CGRect separatorRect = CGRectMake(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin); + HIThemeSeparatorDrawInfo separatorDrawInfo; + separatorDrawInfo.version = 0; + separatorDrawInfo.state = qt_macWindowMainWindow(mainWindow) ? kThemeStateActive : kThemeStateInactive; + QMacCGContext cg(p); + HIThemeDrawSeparator(&separatorRect, &separatorDrawInfo, cg, kHIThemeOrientationNormal); + } break; } } diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index b47d65f561..789ec2f6fd 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -56,6 +56,9 @@ #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" #endif +#ifdef Q_OS_OSX +#include <qpa/qplatformnativeinterface.h> +#endif #include "qdebug.h" #include "private/qtabbar_p.h" @@ -80,35 +83,44 @@ inline static bool verticalTabs(QTabBar::Shape shape) void QTabBarPrivate::updateMacBorderMetrics() { -#if defined(Q_WS_MAC) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - Q_Q(QTabBar); - ::HIContentBorderMetrics metrics; - - // TODO: get metrics to preserve the bottom value - // TODO: test tab bar position - - OSWindowRef window = qt_mac_window_for(q); - - // push base line separator down to the client are so we can paint over it (Carbon) - metrics.top = (documentMode && q->isVisible()) ? 1 : 0; - metrics.bottom = 0; - metrics.left = 0; - metrics.right = 0; - qt_mac_updateContentBorderMetricts(window, metrics); - // In Cocoa we need to keep track of the drawRect method. - // If documentMode is enabled we need to change it, unless - // a toolbar is present. - // Notice that all the information is kept in the window, - // that's why we get the private widget for it instead of - // the private widget for this widget. - QWidgetPrivate *privateWidget = qt_widget_private(q->window()); - if(privateWidget) - privateWidget->changeMethods = documentMode; - // Since in Cocoa there is no simple way to remove the baseline, so we just ask the - // top level to do the magic for us. - privateWidget->syncUnifiedMode(); +#if defined(Q_OS_OSX) + Q_Q(QTabBar); + // Extend the unified title and toolbar area to cover the tab bar iff + // 1) the tab bar is in document mode + // 2) the tab bar is directly below an "unified" area. + // The extending itself is done in the Cocoa platform plugin and Mac style, + // this function registers geometry and visibility state for the tab bar. + + // Calculate geometry + int upper, lower; + if (documentMode) { + QPoint windowPos = q->mapTo(q->window(), QPoint(0,0)); + upper = windowPos.y(); + int tabStripHeight = q->tabSizeHint(0).height(); + int pixelTweak = -3; + lower = upper + tabStripHeight + pixelTweak; + } else { + upper = 0; + lower = 0; } + + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + quintptr identifier = reinterpret_cast<quintptr>(q); + + // Set geometry + QPlatformNativeInterface::NativeResourceForIntegrationFunction function = + nativeInterface->nativeResourceFunctionForIntegration("registerContentBorderArea"); + if (!function) + return; // Not Cocoa platform plugin. + typedef void (*RegisterContentBorderAreaFunction)(QWindow *window, quintptr identifier, int upper, int lower); + (reinterpret_cast<RegisterContentBorderAreaFunction>(function))(q->window()->windowHandle(), identifier, upper, lower); + + // Set visibility state + function = nativeInterface->nativeResourceFunctionForIntegration("setContentBorderAreaEnabled"); + if (!function) + return; + typedef void (*SetContentBorderAreaEnabledFunction)(QWindow *window, quintptr identifier, bool enable); + (reinterpret_cast<SetContentBorderAreaEnabledFunction>(function))(q->window()->windowHandle(), identifier, q->isVisible()); #endif } @@ -1502,6 +1514,9 @@ bool QTabBar::event(QEvent *event) || (!d->rightB->isHidden() && d->rightB->geometry().contains(pos)); if (!isEventInCornerButtons) emit tabBarDoubleClicked(tabAt(pos)); + } else if (event->type() == QEvent::Move) { + d->updateMacBorderMetrics(); + return QWidget::event(event); } return QWidget::event(event); } diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h index b7b6998ca3..3228308bc6 100644 --- a/src/widgets/widgets/qtabbar_p.h +++ b/src/widgets/widgets/qtabbar_p.h @@ -182,6 +182,7 @@ public: void layoutWidgets(int start = 0); void layoutTab(int index); void updateMacBorderMetrics(); + bool isTabInMacUnifiedToolbarArea() const; void setupMovableTab(); void makeVisible(int index); |