Mac: Implement unified toolbar look for QTabBar
Extend the unified title and toolbar gradient to tabs in document mode that are adjacent unified tool bars. Change the updateMacBorderMetrics() function to register the tab bar geometry and visibility status with the Cocoa platform plugin. The Cocoa platform plugin will then merge this area with other registered areas if possible. Add QCocoaNativeInterface::testContentBorderPosition(). This function tests whether the given point is within the unified title and toolbar area. Use testContentBorderPosition() in QMacStyle to enable code paths that skips drawing the QToolBar bottom separator line and paints the active tab background with transparent pixels to make the background gradient visible. Change-Id: I2b70f9bb0c2c59af053a691a7df538f958783dab Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
This commit is contained in:
parent
0f2acaf1cb
commit
3876a05adf
@ -147,6 +147,10 @@ private:
|
|||||||
// Enables or disiables a content border area.
|
// Enables or disiables a content border area.
|
||||||
static void setContentBorderAreaEnabled(QWindow *window, quintptr identifier, bool enable);
|
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
|
// Sets a NSToolbar instance for the given QWindow. The
|
||||||
// toolbar will be attached to the native NSWindow when
|
// toolbar will be attached to the native NSWindow when
|
||||||
// that is created;
|
// that is created;
|
||||||
|
@ -133,6 +133,8 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter
|
|||||||
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setContentBorderEnabled);
|
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setContentBorderEnabled);
|
||||||
if (resource.toLower() == "setnstoolbar")
|
if (resource.toLower() == "setnstoolbar")
|
||||||
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setNSToolbar);
|
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setNSToolbar);
|
||||||
|
if (resource.toLower() == "testcontentborderposition")
|
||||||
|
return NativeResourceForIntegrationFunction(QCocoaNativeInterface::testContentBorderPosition);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -332,4 +334,15 @@ void QCocoaNativeInterface::setNSToolbar(QWindow *window, void *nsToolbar)
|
|||||||
cocoaWindow->updateNSToolbar();
|
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
|
QT_END_NAMESPACE
|
||||||
|
@ -213,6 +213,7 @@ public:
|
|||||||
void registerContentBorderArea(quintptr identifier, int upper, int lower);
|
void registerContentBorderArea(quintptr identifier, int upper, int lower);
|
||||||
void setContentBorderAreaEnabled(quintptr identifier, bool enable);
|
void setContentBorderAreaEnabled(quintptr identifier, bool enable);
|
||||||
void setContentBorderEnabled(bool enable);
|
void setContentBorderEnabled(bool enable);
|
||||||
|
bool testContentBorderAreaPosition(int position) const;
|
||||||
void applyContentBorderThickness(NSWindow *window);
|
void applyContentBorderThickness(NSWindow *window);
|
||||||
void updateNSToolbar();
|
void updateNSToolbar();
|
||||||
|
|
||||||
|
@ -1665,6 +1665,12 @@ void QCocoaWindow::updateNSToolbar()
|
|||||||
[m_nsWindow setShowsToolbarButton:YES];
|
[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
|
qreal QCocoaWindow::devicePixelRatio() const
|
||||||
{
|
{
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
|
||||||
|
@ -179,6 +179,19 @@ static bool isVerticalTabs(const QTabBar::Shape shape) {
|
|||||||
|| shape == QTabBar::TriangularWest);
|
|| 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)
|
void drawTabCloseButton(QPainter *p, bool hover, bool active, bool selected)
|
||||||
{
|
{
|
||||||
// draw background circle
|
// draw background circle
|
||||||
@ -239,7 +252,7 @@ QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect)
|
|||||||
return tabRect;
|
return tabRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt)
|
void drawTabShape(QPainter *p, const QStyleOptionTabV3 *tabOpt, bool isUnified)
|
||||||
{
|
{
|
||||||
QRect r = tabOpt->rect;
|
QRect r = tabOpt->rect;
|
||||||
p->translate(tabOpt->rect.x(), tabOpt->rect.y());
|
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);
|
QRect rect(1, 0, width - 2, height);
|
||||||
|
|
||||||
// fill body
|
// 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;
|
int d = (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ? 16 : 0;
|
||||||
p->fillRect(rect, QColor(151 + d, 151 + d, 151 + d));
|
p->fillRect(rect, QColor(151 + d, 151 + d, 151 + d));
|
||||||
} else {
|
} else {
|
||||||
@ -3733,8 +3751,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
|
|||||||
if (const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
|
if (const QStyleOptionTabV3 *tabOptV3 = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
|
||||||
if (tabOptV3->documentMode) {
|
if (tabOptV3->documentMode) {
|
||||||
p->save();
|
p->save();
|
||||||
// QRect tabRect = tabOptV3->rect;
|
bool isUnified = false;
|
||||||
drawTabShape(p, tabOptV3);
|
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();
|
p->restore();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4442,15 +4466,22 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
|
|||||||
p->fillRect(opt->rect, Qt::transparent);
|
p->fillRect(opt->rect, Qt::transparent);
|
||||||
p->restore();
|
p->restore();
|
||||||
|
|
||||||
// drow horizontal sepearator line at toolBar bottom.
|
// Drow a horizontal sepearator line at the toolBar bottom if the "unified" area ends here.
|
||||||
SInt32 margin;
|
// There might be additional toolbars or other widgets such as tab bars in document
|
||||||
GetThemeMetric(kThemeMetricSeparatorSize, &margin);
|
// mode below. Determine this by making a unified toolbar area test for the row below
|
||||||
CGRect separatorRect = CGRectMake(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin);
|
// this toolbar.
|
||||||
HIThemeSeparatorDrawInfo separatorDrawInfo;
|
QPoint windowToolbarEnd = w->mapTo(w->window(), opt->rect.bottomLeft());
|
||||||
separatorDrawInfo.version = 0;
|
bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1);
|
||||||
separatorDrawInfo.state = qt_macWindowMainWindow(mainWindow) ? kThemeStateActive : kThemeStateInactive;
|
if (isEndOfUnifiedArea) {
|
||||||
QMacCGContext cg(p);
|
SInt32 margin;
|
||||||
HIThemeDrawSeparator(&separatorRect, &separatorDrawInfo, cg, kHIThemeOrientationNormal);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,9 @@
|
|||||||
#ifndef QT_NO_ACCESSIBILITY
|
#ifndef QT_NO_ACCESSIBILITY
|
||||||
#include "qaccessible.h"
|
#include "qaccessible.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef Q_OS_OSX
|
||||||
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "qdebug.h"
|
#include "qdebug.h"
|
||||||
#include "private/qtabbar_p.h"
|
#include "private/qtabbar_p.h"
|
||||||
@ -80,35 +83,44 @@ inline static bool verticalTabs(QTabBar::Shape shape)
|
|||||||
|
|
||||||
void QTabBarPrivate::updateMacBorderMetrics()
|
void QTabBarPrivate::updateMacBorderMetrics()
|
||||||
{
|
{
|
||||||
#if defined(Q_WS_MAC)
|
#if defined(Q_OS_OSX)
|
||||||
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
|
Q_Q(QTabBar);
|
||||||
Q_Q(QTabBar);
|
// Extend the unified title and toolbar area to cover the tab bar iff
|
||||||
::HIContentBorderMetrics metrics;
|
// 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.
|
||||||
|
|
||||||
// TODO: get metrics to preserve the bottom value
|
// Calculate geometry
|
||||||
// TODO: test tab bar position
|
int upper, lower;
|
||||||
|
if (documentMode) {
|
||||||
OSWindowRef window = qt_mac_window_for(q);
|
QPoint windowPos = q->mapTo(q->window(), QPoint(0,0));
|
||||||
|
upper = windowPos.y();
|
||||||
// push base line separator down to the client are so we can paint over it (Carbon)
|
int tabStripHeight = q->tabSizeHint(0).height();
|
||||||
metrics.top = (documentMode && q->isVisible()) ? 1 : 0;
|
int pixelTweak = -3;
|
||||||
metrics.bottom = 0;
|
lower = upper + tabStripHeight + pixelTweak;
|
||||||
metrics.left = 0;
|
} else {
|
||||||
metrics.right = 0;
|
upper = 0;
|
||||||
qt_mac_updateContentBorderMetricts(window, metrics);
|
lower = 0;
|
||||||
// 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1502,6 +1514,9 @@ bool QTabBar::event(QEvent *event)
|
|||||||
|| (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
|
|| (!d->rightB->isHidden() && d->rightB->geometry().contains(pos));
|
||||||
if (!isEventInCornerButtons)
|
if (!isEventInCornerButtons)
|
||||||
emit tabBarDoubleClicked(tabAt(pos));
|
emit tabBarDoubleClicked(tabAt(pos));
|
||||||
|
} else if (event->type() == QEvent::Move) {
|
||||||
|
d->updateMacBorderMetrics();
|
||||||
|
return QWidget::event(event);
|
||||||
}
|
}
|
||||||
return QWidget::event(event);
|
return QWidget::event(event);
|
||||||
}
|
}
|
||||||
|
@ -182,6 +182,7 @@ public:
|
|||||||
void layoutWidgets(int start = 0);
|
void layoutWidgets(int start = 0);
|
||||||
void layoutTab(int index);
|
void layoutTab(int index);
|
||||||
void updateMacBorderMetrics();
|
void updateMacBorderMetrics();
|
||||||
|
bool isTabInMacUnifiedToolbarArea() const;
|
||||||
void setupMovableTab();
|
void setupMovableTab();
|
||||||
|
|
||||||
void makeVisible(int index);
|
void makeVisible(int index);
|
||||||
|
Loading…
Reference in New Issue
Block a user