summaryrefslogtreecommitdiffstats
path: root/src/plugins/styles/mac/qmacstyle_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/styles/mac/qmacstyle_mac.mm')
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm492
1 files changed, 207 insertions, 285 deletions
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index dad81dc8a1..3f57f284e6 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
/*
Note: The qdoc comments for QMacStyle are contained in
@@ -196,44 +160,7 @@ const int pushButtonBevelRectOffsets[3] = {
QVector<QPointer<QObject> > QMacStylePrivate::scrollBars;
-// Title bar gradient colors for Lion were determined by inspecting PSDs exported
-// using CoreUI's CoreThemeDocument; there is no public API to retrieve them
-
-static QLinearGradient titlebarGradientActive()
-{
- static QLinearGradient darkGradient = [](){
- QLinearGradient gradient;
- // FIXME: colors are chosen somewhat arbitrarily and could be fine-tuned,
- // or ideally determined by calling a native API.
- gradient.setColorAt(0, QColor(47, 47, 47));
- return gradient;
- }();
- static QLinearGradient lightGradient = [](){
- QLinearGradient gradient;
- gradient.setColorAt(0, QColor(235, 235, 235));
- gradient.setColorAt(0.5, QColor(210, 210, 210));
- gradient.setColorAt(0.75, QColor(195, 195, 195));
- gradient.setColorAt(1, QColor(180, 180, 180));
- return gradient;
- }();
- return qt_mac_applicationIsInDarkMode() ? darkGradient : lightGradient;
-}
-
-static QLinearGradient titlebarGradientInactive()
-{
- static QLinearGradient darkGradient = [](){
- QLinearGradient gradient;
- gradient.setColorAt(1, QColor(42, 42, 42));
- return gradient;
- }();
- static QLinearGradient lightGradient = [](){
- QLinearGradient gradient;
- gradient.setColorAt(0, QColor(250, 250, 250));
- gradient.setColorAt(1, QColor(225, 225, 225));
- return gradient;
- }();
- return qt_mac_applicationIsInDarkMode() ? darkGradient : lightGradient;
-}
+bool isDarkMode() { return QGuiApplicationPrivate::platformTheme()->colorScheme() == Qt::ColorScheme::Dark; }
#if QT_CONFIG(tabwidget)
/*
@@ -254,7 +181,7 @@ static void clipTabBarFrame(const QStyleOption *option, const QMacStyle *style,
Q_ASSERT(style);
Q_ASSERT(ctx);
- if (qt_mac_applicationIsInDarkMode()) {
+ if (isDarkMode()) {
QTabWidget *tabWidget = qobject_cast<QTabWidget *>(option->styleObject);
Q_ASSERT(tabWidget);
@@ -286,7 +213,7 @@ static const QColor titlebarSeparatorLineInactive(131, 131, 131);
static const QColor darkModeSeparatorLine(88, 88, 88);
// Gradient colors used for the dock widget title bar and
-// non-unifed tool bar bacground.
+// non-unifed tool bar background.
static const QColor lightMainWindowGradientBegin(240, 240, 240);
static const QColor lightMainWindowGradientEnd(200, 200, 200);
static const QColor darkMainWindowGradientBegin(47, 47, 47);
@@ -302,7 +229,6 @@ static const qreal titleBarButtonSpacing = 8;
// active: window is active
// selected: tab is selected
// hovered: tab is hovered
-bool isDarkMode() { return qt_mac_applicationIsInDarkMode(); }
#if QT_CONFIG(tabbar)
static const QColor lightTabBarTabBackgroundActive(190, 190, 190);
@@ -352,7 +278,7 @@ static const int closeButtonSize = 14;
static const qreal closeButtonCornerRadius = 2.0;
#endif // QT_CONFIG(tabbar)
-#ifndef QT_NO_ACCESSIBILITY // This ifdef to avoid "unused function" warning.
+#if QT_CONFIG(accessibility) // This ifdef to avoid "unused function" warning.
QBrush brushForToolButton(bool isOnKeyWindow)
{
// When a toolbutton in a toolbar is in the 'ON' state, we draw a
@@ -363,7 +289,7 @@ QBrush brushForToolButton(bool isOnKeyWindow)
return isOnKeyWindow ? QColor(0, 0, 0, 28) : QColor(0, 0, 0, 21);
}
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
static const int headerSectionArrowHeight = 6;
@@ -388,16 +314,15 @@ static const QMarginsF pushButtonShadowMargins[3] = {
{ 1.5, 0.5, 1.5, 2.5 }
};
-// These are frame heights as reported by Xcode 9's Interface Builder.
-// Alignemnet rectangle's heights match for push and popup buttons
-// with respective values 21, 18 and 15.
+// These are frame heights as reported by Xcode 9's Interface Builder
+// and determined experimentally.
static const qreal comboBoxDefaultHeight[3] = {
26, 22, 19
};
static const qreal pushButtonDefaultHeight[3] = {
- 32, 28, 16
+ 32, 28, 24
};
static const qreal popupButtonDefaultHeight[3] = {
@@ -421,16 +346,14 @@ class AppearanceSync {
public:
AppearanceSync()
{
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave
- && !qt_mac_applicationIsInDarkMode()) {
+ && !isDarkMode()) {
auto requiredAppearanceName = NSApplication.sharedApplication.effectiveAppearance.name;
if (![NSAppearance.currentAppearance.name isEqualToString:requiredAppearanceName]) {
previous = NSAppearance.currentAppearance;
NSAppearance.currentAppearance = [NSAppearance appearanceNamed:requiredAppearanceName];
}
}
-#endif // QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
}
~AppearanceSync()
@@ -468,6 +391,7 @@ static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl)
return false;
slider.frame = sl->rect.toCGRect();
+
slider.minValue = sl->minimum;
slider.maxValue = sl->maximum;
slider.intValue = sl->sliderPosition;
@@ -844,6 +768,8 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QStyleOption
return ret;
}
+ const bool isBigSurOrAbove = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSBigSur;
+
if (ct == QStyle::CT_CustomBase && widg) {
#if QT_CONFIG(pushbutton)
if (qobject_cast<const QPushButton *>(widg))
@@ -1024,6 +950,8 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QStyleOption
w = qt_mac_aqua_get_metric(HSliderHeight);
if (sld->tickPosition != QSlider::NoTicks)
w += qt_mac_aqua_get_metric(HSliderTickHeight);
+ else if (isBigSurOrAbove)
+ w += 3;
} else {
w = qt_mac_aqua_get_metric(VSliderWidth);
if (sld->tickPosition != QSlider::NoTicks)
@@ -1087,7 +1015,7 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QStyleOption
#if QT_CONFIG(combobox)
case QStyle::CT_LineEdit:
if (!widg || !qobject_cast<QComboBox *>(widg->parentWidget())) {
- //should I take into account the font dimentions of the lineedit? -Sam
+ //should I take into account the font dimensions of the lineedit? -Sam
if (sz == QStyleHelper::SizeLarge)
ret = QSize(-1, 21);
else
@@ -1149,6 +1077,8 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
{
+ const bool isBigSurOrAbove = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSBigSur;
+
QPainterPath focusRingPath;
focusRingPath.setFillRule(Qt::OddEvenFill);
@@ -1198,7 +1128,6 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
}
case Button_PullDown:
case Button_PushButton: {
- const bool isBigSurOrAbove = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSBigSur;
QRectF focusRect;
auto *pb = static_cast<NSButton *>(cocoaControl(cw));
const QRectF frameRect = cw.adjustedControlFrame(targetRect.adjusted(hMargin, vMargin, -hMargin, -vMargin));
@@ -1206,8 +1135,9 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]);
if (cw.type == QMacStylePrivate::Button_PushButton) {
focusRect -= pushButtonShadowMargins[cw.size];
- }
- else if (cw.type == QMacStylePrivate::Button_PullDown) {
+ if (cw.size == QStyleHelper::SizeMini)
+ focusRect.adjust(0, 3, 0, -3);
+ } else if (cw.type == QMacStylePrivate::Button_PullDown) {
focusRect -= pullDownButtonShadowMargins[cw.size];
//fix focus ring drawn slightly off for pull downs
if (cw.size == QStyleHelper::SizeLarge)
@@ -1229,11 +1159,16 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
}
case Button_PopupButton:
case SegmentedControl_Single: {
+ QRectF focusRect = targetRect;
+ if (isBigSurOrAbove)
+ focusRect.translate(0, -1.5);
+ else if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSCatalina)
+ focusRect.adjust(0, 0, 0, -1);
const qreal innerRadius = cw.type == Button_PushButton ? 3 : 4;
const qreal outerRadius = innerRadius + focusRingWidth;
- hOffset = targetRect.left();
- vOffset = targetRect.top();
- const auto innerRect = targetRect.translated(-targetRect.topLeft());
+ hOffset = focusRect.left();
+ vOffset = focusRect.top();
+ const auto innerRect = focusRect.translated(-focusRect.topLeft());
const auto outerRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin);
focusRingPath.addRoundedRect(innerRect, innerRadius, innerRadius);
focusRingPath.addRoundedRect(outerRect, outerRadius, outerRadius);
@@ -1282,7 +1217,7 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int
}
auto focusRingColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor);
- if (!qt_mac_applicationIsInDarkMode()) {
+ if (!isDarkMode()) {
// This color already has alpha ~ 0.25, this value is too small - the ring is
// very pale and nothing like the native one. 0.39 makes it better (not ideal
// anyway). The color seems to be correct in dark more without any modification.
@@ -1592,9 +1527,9 @@ QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect)
frameRect = QRectF(rect.topLeft(),
QSizeF(rect.width(), frameSize.height()));
if (size == QStyleHelper::SizeSmall)
- frameRect = frameRect.translated(0, 1.5);
+ frameRect.translate(0, 0.5);
else if (size == QStyleHelper::SizeMini)
- frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4);
+ frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, -0.5);
frameRect = frameRect.adjusted(-pushButtonBevelRectOffsets[size], 0,
pushButtonBevelRectOffsets[size], 0);
} else {
@@ -1666,7 +1601,7 @@ bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonTyp
*bezelStyle = NSBezelStyleShadowlessSquare;
break;
case Button_PushButton:
- *buttonType = NSButtonTypePushOnPushOff;
+ *buttonType = NSButtonTypeMomentaryPushIn;
*bezelStyle = NSBezelStyleRounded;
break;
default:
@@ -1680,13 +1615,15 @@ QMacStylePrivate::CocoaControlType cocoaControlType(const QStyleOption *opt, con
{
if (const auto *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
const bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
- // When the contents won't fit in a large sized button,
- // and WA_MacNormalSize is not set, make the button square.
+ // Buttons that don't fit (or don't get filled by) the default bevel
+ // will be made of square type, unless WA_MacNormalSize is not set.
// Threshold used to be at 34, not 32.
- const auto maxNonSquareHeight = pushButtonDefaultHeight[QStyleHelper::SizeLarge];
+ // Needs to be in sync with similar logic in CE_FocusFrame handling
+ QStyleHelper::WidgetSizePolicy sizePolicy = QStyleHelper::widgetSizePolicy(w, opt);
+ if (sizePolicy == QStyleHelper::SizeDefault)
+ sizePolicy = QStyleHelper::SizeLarge;
const bool isSquare = (btn->features & QStyleOptionButton::Flat)
- || (btn->rect.height() > maxNonSquareHeight
- && !(w && w->testAttribute(Qt::WA_MacNormalSize)));
+ || (btn->rect.height() != pushButtonDefaultHeight[sizePolicy]);
return (isSquare? QMacStylePrivate::Button_SquareButton :
hasMenu ? QMacStylePrivate::Button_PullDown :
QMacStylePrivate::Button_PushButton);
@@ -1805,10 +1742,6 @@ QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outerBounds, const Coc
QMacStylePrivate::QMacStylePrivate()
: backingStoreNSView(nil)
{
- if (auto *ssf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::SmallFont))
- smallSystemFont = *ssf;
- if (auto *msf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::MiniFont))
- miniSystemFont = *msf;
}
QMacStylePrivate::~QMacStylePrivate()
@@ -1826,13 +1759,9 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
|| widget.size == QStyleHelper::SizeDefault)
return nil;
- if (widget.type == Box) {
- if (__builtin_available(macOS 10.14, *)) {
- if (qt_mac_applicationIsInDarkMode()) {
- // See render code in drawPrimitive(PE_FrameTabWidget)
- widget.type = Box_Dark;
- }
- }
+ if (widget.type == Box && isDarkMode()) {
+ // See render code in drawPrimitive(PE_FrameTabWidget)
+ widget.type = Box_Dark;
}
NSView *bv = cocoaControls.value(widget, nil);
@@ -2077,7 +2006,6 @@ QMacStyle::QMacStyle()
QCoreApplication::sendEvent(o, &event);
});
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
Q_D(QMacStyle);
// FIXME: Tie this logic into theme change, or even polish/unpolish
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
@@ -2088,7 +2016,6 @@ QMacStyle::QMacStyle()
d->cocoaControls.clear();
});
}
-#endif
}
QMacStyle::~QMacStyle()
@@ -2109,6 +2036,14 @@ void QMacStyle::unpolish(QApplication *)
void QMacStyle::polish(QWidget* w)
{
+ Q_D(QMacStyle);
+ if (!d->smallSystemFont && QGuiApplicationPrivate::platformTheme()) {
+ if (auto *ssf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::SmallFont))
+ d->smallSystemFont = *ssf;
+ else
+ d->smallSystemFont = QFont();
+ }
+
if (false
#if QT_CONFIG(menu)
|| qobject_cast<QMenu*>(w)
@@ -2221,25 +2156,6 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
case PM_FocusFrameHMargin:
ret = qt_mac_aqua_get_metric(FocusRectOutset);
break;
- case PM_DialogButtonsSeparator:
- ret = -5;
- break;
- case PM_DialogButtonsButtonHeight: {
- QSize sz;
- ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz);
- if (sz == QSize(-1, -1))
- ret = 32;
- else
- ret = sz.height();
- break; }
- case PM_DialogButtonsButtonWidth: {
- QSize sz;
- ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz);
- if (sz == QSize(-1, -1))
- ret = 70;
- else
- ret = sz.width();
- break; }
case PM_MenuBarHMargin:
ret = 8;
@@ -2566,10 +2482,13 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
case PM_ToolBarFrameWidth:
ret = 1;
break;
- case PM_ScrollView_ScrollBarOverlap:
- ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay ?
- pixelMetric(PM_ScrollBarExtent, opt, widget) : 0;
+ case PM_ScrollView_ScrollBarOverlap: {
+ const QStyle *realStyle = widget ? widget->style() : proxy();
+ ret = realStyle->styleHint(SH_ScrollBar_Transient, opt, widget)
+ ? realStyle->pixelMetric(PM_ScrollBarExtent, opt, widget)
+ : 0;
break;
+ }
default:
ret = QCommonStyle::pixelMetric(metric, opt, widget);
break;
@@ -2877,7 +2796,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
case SH_ScrollBar_Transient:
if ((qobject_cast<const QScrollBar *>(w) && w->parent() &&
qobject_cast<QAbstractScrollArea*>(w->parent()->parent()))
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
|| (opt && QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ScrollBar))
#endif
) {
@@ -3036,7 +2955,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
}
#if QT_CONFIG(tabwidget)
QRegion region(tbb->rect);
- region -= tbb->tabBarRect;
+ region -= tbb->tabBarRect.adjusted(3, 0, -3, 0);
p->save();
p->setClipRegion(region);
QStyleOptionTabWidgetFrame twf;
@@ -3094,7 +3013,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
auto adjustedRect = opt->rect;
bool needTranslation = false;
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave
- && !qt_mac_applicationIsInDarkMode()) {
+ && !isDarkMode()) {
// In Aqua theme we have to use the 'default' NSBox (as opposite
// to the 'custom' QDarkNSBox we use in dark theme). Since -drawRect:
// does nothing in default NSBox, we call -displayRectIgnoringOpaticty:.
@@ -3103,7 +3022,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
// vertically and even worse, if QTabWidget has autoFillBackground
// set, this background overpaints NSBox making it to disappear.
// We trick our NSBox to render in a larger rectangle, so that
- // the actuall result (which is again smaller than requested),
+ // the actual result (which is again smaller than requested),
// more or less is what we really want. We'll have to adjust CTM
// and translate accordingly.
adjustedRect.adjust(0, 0, 6, 6);
@@ -3142,14 +3061,14 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
theStroker.setCapStyle(Qt::FlatCap);
theStroker.setDashPattern(QVector<qreal>() << 1 << 2);
path = theStroker.createStroke(path);
- const auto dark = qt_mac_applicationIsInDarkMode() ? opt->palette.dark().color().darker()
+ const auto dark = isDarkMode() ? opt->palette.dark().color().darker()
: QColor(0, 0, 0, 119);
p->fillPath(path, dark);
}
break;
case PE_FrameWindow:
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
- if (w && w->inherits("QMdiSubWindow")) {
+ if (qobject_cast<const QMdiSubWindow*>(w)) {
p->save();
p->setPen(QPen(frame->palette.dark().color(), frame->lineWidth));
p->setBrush(frame->palette.window());
@@ -3297,7 +3216,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
NSButtonCell *triangleCell = static_cast<NSButtonCell *>(d->cocoaCell(cw));
[triangleCell setState:(opt->state & State_Open) ? NSControlStateValueOn : NSControlStateValueOff];
bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus);
- [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight];
+ [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleEmphasized : NSBackgroundStyleNormal];
d->setupNSGraphicsContext(cg, NO);
@@ -3336,7 +3255,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel;
tf.frame = opt->rect.toCGRect();
d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef, const CGRect &rect) {
- if (!qt_mac_applicationIsInDarkMode()) {
+ if (!isDarkMode()) {
// In 'Dark' mode controls are transparent, so we do not
// over-paint the (potentially custom) color in the background.
// In 'Light' mode we have to care about the correct
@@ -3369,7 +3288,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
case PE_PanelLineEdit:
{
const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt);
- if (qt_mac_applicationIsInDarkMode() || (panel && panel->lineWidth <= 0)) {
+ if (isDarkMode() || (panel && panel->lineWidth <= 0)) {
// QCommonStyle::drawPrimitive(PE_PanelLineEdit) fill the background with
// a proper color, defined in opt->palette and then, if lineWidth > 0, it
// calls QMacStyle::drawPrimitive(PE_FrameLineEdit). We use NSTextFieldCell
@@ -3434,17 +3353,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
} break;
#endif // QT_CONFIG(tabbar)
case PE_PanelStatusBar: {
- // Fill the status bar with the titlebar gradient.
- QLinearGradient linearGrad;
- if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) {
- linearGrad = titlebarGradientActive();
- } else {
- linearGrad = titlebarGradientInactive();
- }
-
- linearGrad.setStart(0, opt->rect.top());
- linearGrad.setFinalStop(0, opt->rect.bottom());
- p->fillRect(opt->rect, linearGrad);
+ p->fillRect(opt->rect, opt->palette.window());
// Draw the black separator line at the top of the status bar.
if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active))
@@ -3548,38 +3457,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
break;
- case CE_HeaderLabel:
- if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
- p->save();
- QRect textr = header->rect;
- if (!header->icon.isNull()) {
- QIcon::Mode mode = QIcon::Disabled;
- if (opt->state & State_Enabled)
- mode = QIcon::Normal;
- int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
- QPixmap pixmap = header->icon.pixmap(QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(), mode);
-
- QRect pixr = header->rect;
- pixr.setY(header->rect.center().y() - (pixmap.height() / pixmap.devicePixelRatio() - 1) / 2);
- proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap);
- textr.translate(pixmap.width() / pixmap.devicePixelRatio() + 2, 0);
- }
- QString text = header->text;
- if (const QStyleOptionHeaderV2 *headerV2 = qstyleoption_cast<const QStyleOptionHeaderV2 *>(header)) {
- if (headerV2->textElideMode != Qt::ElideNone)
- text = header->fontMetrics.elidedText(text, headerV2->textElideMode, textr.width());
- }
-
- proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette,
- header->state.testFlag(State_Enabled), text, QPalette::ButtonText);
- p->restore();
- }
- break;
case CE_ToolButtonLabel:
if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QStyleOptionToolButton myTb = *tb;
myTb.state &= ~State_AutoRaise;
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) {
QRect cr = tb->rect;
int shiftX = 0;
@@ -3619,12 +3501,13 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// Draw the text if it's needed.
if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) {
needText = true;
+ QSizeF size = pixmap.deviceIndependentSize();
if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
- pr.setHeight(pixmap.size().height() / pixmap.devicePixelRatio() + 6);
+ pr.setHeight(size.height() + 6);
cr.adjust(0, pr.bottom(), 0, -3);
alignment |= Qt::AlignCenter;
} else {
- pr.setWidth(pixmap.width() / pixmap.devicePixelRatio() + 8);
+ pr.setWidth(size.width() + 8);
cr.adjust(pr.right(), 0, 0, 0);
alignment |= Qt::AlignLeft | Qt::AlignVCenter;
}
@@ -3668,7 +3551,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QCommonStyle::drawControl(ce, &myTb, p, w);
}
} else
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
{
QCommonStyle::drawControl(ce, &myTb, p, w);
}
@@ -3711,14 +3594,27 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
auto *pb = static_cast<NSButton *>(d->cocoaControl(cw));
// Ensure same size and location as we used to have with HITheme.
- // This is more convoluted than we initialy thought. See for example
+ // This is more convoluted than we initially thought. See for example
// differences between plain and menu button frames.
const QRectF frameRect = cw.adjustedControlFrame(btn->rect);
pb.frame = frameRect.toCGRect();
pb.enabled = isEnabled;
+
+ // With the 'momentary push in' type this gives an impression of a
+ // button in a 'pressed' state (the 'momentary push in' does
+ // not show its state otherwise):
[pb highlight:isPressed];
- pb.state = isHighlighted && !isPressed ? NSControlStateValueOn : NSControlStateValueOff;
+
+
+ if (cw.type == QMacStylePrivate::Button_SquareButton) {
+ pb.state = isHighlighted && !isPressed ? NSControlStateValueOn : NSControlStateValueOff;
+ } else {
+ // For default/checked button this will give the required
+ // button accent color:
+ pb.keyEquivalent = isHighlighted ? @"\r" : @"";
+ }
+
d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef, const CGRect &r) {
[pb.cell drawBezelWithFrame:r inView:pb.superview];
});
@@ -3760,16 +3656,28 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const bool hasText = !btn.text.isEmpty();
const bool isActive = btn.state & State_Active;
const bool isPressed = btn.state & State_Sunken;
+ const bool isDefault = (btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton)
+ || d->autoDefaultButton == btn.styleObject;
+ // cocoaControlType evaluates the type based on the control's geometry, not on the
+ // label's geometry
+ const QRect oldRect = btn.rect;
+ if (w)
+ btn.rect = w->rect();
const auto ct = cocoaControlType(&btn, w);
+ btn.rect = oldRect;
if (!hasMenu && ct != QMacStylePrivate::Button_SquareButton) {
- if (isPressed
- || (isActive && isEnabled
- && ((btn.state & State_On)
- || ((btn.features & QStyleOptionButton::DefaultButton) && !d->autoDefaultButton)
- || d->autoDefaultButton == btn.styleObject)))
- btn.palette.setColor(QPalette::ButtonText, Qt::white);
+ if (isPressed || (isActive && isEnabled && ((btn.state & State_On) || isDefault)))
+ btn.palette.setColor(QPalette::ButtonText, Qt::white);
+ }
+
+ if (isEnabled && !isDarkMode() && QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur) {
+ if (!isDefault && !(btn.state & State_On)) {
+ // On macOS 12 it's a gray button, white text color (if set in the
+ // previous statement) would be almost invisible.
+ btn.palette.setColor(QPalette::ButtonText, Qt::black);
+ }
}
if ((!hasIcon && !hasMenu) || (hasIcon && !hasText)) {
@@ -3798,12 +3706,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (btn.state & State_On)
state = QIcon::On;
QPixmap pixmap = btn.icon.pixmap(btn.iconSize, p->device()->devicePixelRatio(), mode, state);
- int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
- int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
- contentW += pixmapWidth + QMacStylePrivate::PushButtonContentPadding;
+ QSizeF pixmapSize = pixmap.deviceIndependentSize();
+ contentW += pixmapSize.width() + QMacStylePrivate::PushButtonContentPadding;
int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2;
- int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapHeight) / 2;
- QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapWidth, pixmapHeight);
+ int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapSize.height()) / 2;
+ QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapSize.width(), pixmapSize.height());
QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect);
proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
int newOffset = iconDestRect.x() + iconDestRect.width()
@@ -3927,6 +3834,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
frameRect = frameRect.adjusted(-1, 0, 1, 0);
}
break;
+ case QStyleOptionTab::Moving: // Moving tab treated like End
case QStyleOptionTab::End:
// Pressed state hack: tweak adjustments in preparation for flip below
if (isSelected || tabDirection == QMacStylePrivate::West)
@@ -3945,10 +3853,22 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
pb.frame = frameRect.toCGRect();
+ if (!isPopupButton) {
+ // Note: these days we use 'momentary push in' for Button_PushButton,
+ // but tabs are also rendered using NSButton/ButtonPushButton, and
+ // here we need 'push on/off' to make it work (tab highlight colors).
+ pb.buttonType = NSButtonTypePushOnPushOff;
+ }
+
pb.enabled = isEnabled;
[pb highlight:isPressed];
+
// Set off state when inactive. See needsInactiveHack for when it's selected
- pb.state = (isActive && isSelected && !isPressed) ? NSControlStateValueOn : NSControlStateValueOff;
+ // On macOS 12, don't set the Off state for selected tabs as it draws a gray backgorund even when highlighted
+ if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur)
+ pb.state = (isActive && isSelected) ? NSControlStateValueOn : NSControlStateValueOff;
+ else
+ pb.state = (isActive && isSelected && !isPressed) ? NSControlStateValueOn : NSControlStateValueOff;
const auto drawBezelBlock = ^(CGContextRef ctx, const CGRect &r) {
CGContextClipToRect(ctx, opt->rect.toCGRect());
@@ -4063,32 +3983,12 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
p->restore();
}
-
- // TODO Needs size adjustment to fit the focus ring
- if (tabOpt->state & State_HasFocus) {
- QMacStylePrivate::CocoaControlType focusRingType;
- switch (tp) {
- case QStyleOptionTab::Beginning:
- focusRingType = verticalTabs ? QMacStylePrivate::SegmentedControl_Last
- : QMacStylePrivate::SegmentedControl_First;
- break;
- case QStyleOptionTab::Middle:
- focusRingType = QMacStylePrivate::SegmentedControl_Middle;
- break;
- case QStyleOptionTab::End:
- focusRingType = verticalTabs ? QMacStylePrivate::SegmentedControl_First
- : QMacStylePrivate::SegmentedControl_Last;
- break;
- case QStyleOptionTab::OnlyOneTab:
- focusRingType = QMacStylePrivate::SegmentedControl_Single;
- break;
- }
- }
}
break;
case CE_TabBarTabLabel:
if (const auto *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
QStyleOptionTab myTab = *tab;
+ const auto foregroundRole = w ? w->foregroundRole() : QPalette::WindowText;
const auto tabDirection = QMacStylePrivate::tabDirection(tab->shape);
const bool verticalTabs = tabDirection == QMacStylePrivate::East
|| tabDirection == QMacStylePrivate::West;
@@ -4102,11 +4002,11 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (!myTab.documentMode && (myTab.state & State_Selected) && (myTab.state & State_Active))
if (const auto *tabBar = qobject_cast<const QTabBar *>(w))
if (!tabBar->tabTextColor(tabBar->currentIndex()).isValid())
- myTab.palette.setColor(QPalette::WindowText, Qt::white);
+ myTab.palette.setColor(foregroundRole, Qt::white);
if (myTab.documentMode && isDarkMode()) {
bool active = (myTab.state & State_Selected) && (myTab.state & State_Active);
- myTab.palette.setColor(QPalette::WindowText, active ? Qt::white : Qt::gray);
+ myTab.palette.setColor(foregroundRole, active ? Qt::white : Qt::gray);
}
int heightOffset = 0;
@@ -4135,12 +4035,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
// fill title bar background
- QLinearGradient linearGrad;
- linearGrad.setStart(QPointF(0, 0));
- linearGrad.setFinalStop(QPointF(0, 2 * effectiveRect.height()));
- linearGrad.setColorAt(0, opt->palette.button().color());
- linearGrad.setColorAt(1, opt->palette.dark().color());
- p->fillRect(effectiveRect, linearGrad);
+ p->fillRect(effectiveRect, opt->palette.window());
// draw horizontal line at bottom
p->setPen(opt->palette.dark().color());
@@ -4155,7 +4050,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
titleRect.width());
const auto text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width());
- proxy()->drawItemText(p, titleRect, Qt::AlignCenter, dwOpt->palette,
+ proxy()->drawItemText(p, titleRect, Qt::AlignCenter | Qt::TextHideMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, text, QPalette::WindowText);
}
p->restore();
@@ -4167,17 +4062,21 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
const auto *ffw = ff ? ff->widget() : nullptr;
const auto ct = [=] {
if (ffw) {
- if (ffw->inherits("QCheckBox"))
+ if (qobject_cast<const QCheckBox*>(ffw))
return QMacStylePrivate::Button_CheckBox;
- if (ffw->inherits("QRadioButton"))
+ if (qobject_cast<const QRadioButton*>(ffw))
return QMacStylePrivate::Button_RadioButton;
- if (ffw->inherits("QLineEdit") || ffw->inherits("QTextEdit"))
+ if (qobject_cast<const QLineEdit*>(ffw) || qobject_cast<const QTextEdit*>(ffw))
return QMacStylePrivate::TextField;
if (const auto *pb = qobject_cast<const QPushButton *>(ffw)) {
- if (pb->isFlat() || (pb->rect().height()
- > pushButtonDefaultHeight[QStyleHelper::SizeLarge]
- && !(pb->testAttribute(Qt::WA_MacNormalSize))))
- return QMacStylePrivate::Button_SquareButton;
+ // keep in sync with cocoaControlType
+ auto sizePolicy = QStyleHelper::widgetSizePolicy(ffw, opt);
+ if (sizePolicy == QStyleHelper::SizeDefault)
+ sizePolicy = QStyleHelper::SizeLarge;
+ if (pb->isFlat()
+ || (pb->rect().height() != pushButtonDefaultHeight[sizePolicy])) {
+ return QMacStylePrivate::Button_SquareButton;
+ }
if (pb->menu() != nullptr)
return QMacStylePrivate::Button_PullDown;
return QMacStylePrivate::Button_PushButton;
@@ -4186,10 +4085,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
return QMacStylePrivate::Box; // Not really, just make it the default
} ();
- const auto cs = ffw ? (ffw->testAttribute(Qt::WA_MacMiniSize) ? QStyleHelper::SizeMini :
- ffw->testAttribute(Qt::WA_MacSmallSize) ? QStyleHelper::SizeSmall :
- QStyleHelper::SizeLarge) :
- QStyleHelper::SizeLarge;
+ auto cs = QStyleHelper::widgetSizePolicy(ffw, opt);
+ if (cs == QStyleHelper::SizeDefault)
+ cs = QStyleHelper::SizeLarge;
const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w);
const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w);
d->drawFocusRing(p, opt->rect, hMargin, vMargin, QMacStylePrivate::CocoaControl(ct, cs));
@@ -4297,13 +4195,12 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
#endif
QPixmap pixmap = mi->icon.pixmap(iconSize, p->device()->devicePixelRatio(), mode);
- int pixw = pixmap.width() / pixmap.devicePixelRatio();
- int pixh = pixmap.height() / pixmap.devicePixelRatio();
QRect cr(xpos, mi->rect.y(), checkcol, mi->rect.height());
- QRect pmr(0, 0, pixw, pixh);
+ QSize size = pixmap.deviceIndependentSize().toSize();
+ QRect pmr(QPoint(0, 0), size);
pmr.moveCenter(cr.center());
p->drawPixmap(pmr.topLeft(), pixmap);
- xpos += pixw + 6;
+ xpos += size.width() + 6;
}
QString s = mi->text;
@@ -4332,9 +4229,25 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (!rightMarginText.isEmpty()) {
p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font()));
int xp = mi->rect.right() - tabwidth - macRightBorder + 2;
- if (!isSubMenu)
+ if (isSubMenu) {
+ p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags | Qt::AlignRight, rightMarginText);
+ } else {
xp -= macItemHMargin + macItemFrame + 3; // Adjust for shortcut
- p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags | Qt::AlignRight, rightMarginText);
+ // try to render modifier part of shortcut string right aligned, key part left aligned
+ const QKeySequence seq = QKeySequence::fromString(rightMarginText, QKeySequence::NativeText);
+ if (seq.count() == 1) { // one-combo sequence, the right most character is the key
+ // we don't know which key of all menu items is the widest, so use the widest possible
+ const int maxKeyWidth = p->fontMetrics().maxWidth();
+ const QChar key = rightMarginText.at(rightMarginText.length() - 1);
+ const QString modifiers = rightMarginText.left(rightMarginText.size() - 1);
+ p->drawText(xp + tabwidth - maxKeyWidth, yPos, maxKeyWidth, mi->rect.height(), text_flags, key);
+ // don't clip the shortcuts; maxKeyWidth might be more than what we have been allotted by the menu
+ p->drawText(xp, yPos, tabwidth - maxKeyWidth, mi->rect.height(),
+ text_flags | Qt::AlignRight | Qt::TextDontClip, modifiers);
+ } else { // draw the whole thing left-aligned for complex or unparsable cases
+ p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags, rightMarginText);
+ }
+ }
}
if (!s.isEmpty()) {
@@ -4376,8 +4289,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// line-break the string if it doesn't fit the given rect. It's better to draw outside
// the rect and possibly overlap something than to have part of the text disappear.
[s.toNSString() drawAtPoint:CGPointMake(xpos, yPos)
- withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c,
- NSObliquenessAttributeName: [NSNumber numberWithDouble: myFont.italic() ? 0.3 : 0.0]}];
+ withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c,
+ NSObliquenessAttributeName: [NSNumber numberWithDouble: myFont.italic() ? 0.3 : 0.0],
+ NSUnderlineStyleAttributeName: [NSNumber numberWithInt: myFont.underline() ? NSUnderlineStyleSingle
+ : NSUnderlineStyleNone]}];
d->restoreNSGraphicsContext(cgCtx);
} else {
@@ -4559,7 +4474,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
#ifndef QT_NO_TOOLBAR
case CE_ToolBar: {
const QStyleOptionToolBar *toolBar = qstyleoption_cast<const QStyleOptionToolBar *>(opt);
- const bool isDarkMode = qt_mac_applicationIsInDarkMode();
+ const bool darkMode = isDarkMode();
// Unified title and toolbar drawing. In this mode the cocoa platform plugin will
// fill the top toolbar area part with a background gradient that "unifies" with
@@ -4584,7 +4499,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (isEndOfUnifiedArea) {
const int margin = qt_mac_aqua_get_metric(SeparatorSize);
const auto separatorRect = QRect(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin);
- p->fillRect(separatorRect, isDarkMode ? darkModeSeparatorLine : opt->palette.dark().color());
+ p->fillRect(separatorRect, darkMode ? darkModeSeparatorLine : opt->palette.dark().color());
}
break;
}
@@ -4599,24 +4514,24 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
else
linearGrad = QLinearGradient(opt->rect.left(), 0, opt->rect.right(), 0);
- QColor mainWindowGradientBegin = isDarkMode ? darkMainWindowGradientBegin : lightMainWindowGradientBegin;
- QColor mainWindowGradientEnd = isDarkMode ? darkMainWindowGradientEnd : lightMainWindowGradientEnd;
+ QColor mainWindowGradientBegin = darkMode ? darkMainWindowGradientBegin : lightMainWindowGradientBegin;
+ QColor mainWindowGradientEnd = darkMode ? darkMainWindowGradientEnd : lightMainWindowGradientEnd;
linearGrad.setColorAt(0, mainWindowGradientBegin);
linearGrad.setColorAt(1, mainWindowGradientEnd);
p->fillRect(opt->rect, linearGrad);
p->save();
- QRect toolbarRect = isDarkMode ? opt->rect.adjusted(0, 0, 0, 1) : opt->rect;
+ QRect toolbarRect = darkMode ? opt->rect.adjusted(0, 0, 0, 1) : opt->rect;
if (opt->state & State_Horizontal) {
- p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
+ p->setPen(darkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
p->drawLine(toolbarRect.topLeft(), toolbarRect.topRight());
- p->setPen(isDarkMode ? darkModeSeparatorLine :mainWindowGradientEnd.darker(114));
+ p->setPen(darkMode ? darkModeSeparatorLine :mainWindowGradientEnd.darker(114));
p->drawLine(toolbarRect.bottomLeft(), toolbarRect.bottomRight());
} else {
- p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
+ p->setPen(darkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
p->drawLine(toolbarRect.topLeft(), toolbarRect.bottomLeft());
- p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientEnd.darker(114));
+ p->setPen(darkMode ? darkModeSeparatorLine : mainWindowGradientEnd.darker(114));
p->drawLine(toolbarRect.topRight(), toolbarRect.bottomRight());
}
p->restore();
@@ -5181,7 +5096,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
const bool drawTrack = sb->subControls & SC_ScrollBarGroove;
- const bool drawKnob = sb->subControls & SC_ScrollBarSlider;
+ const bool drawKnob = sb->subControls & SC_ScrollBarSlider && sb->minimum != sb->maximum;
if (!drawTrack && !drawKnob)
break;
@@ -5195,7 +5110,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const auto cocoaSize = d->effectiveAquaSizeConstrain(opt, widget);
const CGFloat maxExpandScale = expandedKnobWidths[cocoaSize] / knobWidths[cocoaSize];
- const bool isTransient = proxy()->styleHint(SH_ScrollBar_Transient, opt, widget);
+ const QStyle *realStyle = widget ? widget->style() : proxy();
+ const bool isTransient = realStyle->styleHint(SH_ScrollBar_Transient, opt, widget);
if (!isTransient)
d->stopAnimation(opt->styleObject);
bool wasActive = false;
@@ -5384,6 +5300,15 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const CGRect knobRect = [slider.cell knobRectFlipped:slider.isFlipped];
pressPoint.x = CGRectGetMidX(knobRect);
pressPoint.y = CGRectGetMidY(knobRect);
+
+ // The only way to tell a NSSlider/NSSliderCell to render as pressed
+ // is to start tracking. But this API has some weird behaviors that
+ // we have to account for. First of all, the pressed state will not
+ // be visually reflected unless we start tracking twice. And secondly
+ // if we don't track twice, the state of one render-pass will affect
+ // the render pass of other sliders, even if we set up the shared
+ // NSSlider with a new slider value.
+ [slider.cell startTrackingAt:pressPoint inView:slider];
[slider.cell startTrackingAt:pressPoint inView:slider];
}
@@ -5413,7 +5338,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
#if 0
- // FIXME: Sadly, this part doesn't work. It seems to somehow polute the
+ // FIXME: Sadly, this part doesn't work. It seems to somehow pollute the
// NSSlider's internal state and, when we need to use the "else" part,
// the slider's frame is not in sync with its cell dimensions.
const bool drawAllParts = drawKnob && drawBar && (!hasTicks || drawTicks);
@@ -5488,8 +5413,12 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
});
- if (isPressed)
+ if (isPressed) {
+ // We stop twice to be on the safe side, even if one seems to be enough.
+ // See startTracking above for why we do this.
+ [slider.cell stopTracking:pressPoint at:pressPoint inView:slider mouseIsUp:NO];
[slider.cell stopTracking:pressPoint at:pressPoint inView:slider mouseIsUp:NO];
+ }
}
break;
#if QT_CONFIG(spinbox)
@@ -5551,7 +5480,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
auto *cc = static_cast<NSControl *>(d->cocoaControl(cw));
cc.enabled = isEnabled;
- QRectF frameRect = cw.adjustedControlFrame(combo->rect);;
+ QRectF frameRect = cw.adjustedControlFrame(combo->rect);
if (cw.type == QMacStylePrivate::Button_PopupButton) {
// Non-editable QComboBox
auto *pb = static_cast<NSPopUpButton *>(cc);
@@ -5624,16 +5553,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const auto frameAdjust = 1.0 / p->device()->devicePixelRatio();
const auto innerFrameRect = outerFrameRect.adjusted(frameAdjust, frameAdjust, -frameAdjust, 0);
QPainterPath innerFramePath = d->windowPanelPath(innerFrameRect);
- if (isActive) {
- QLinearGradient g;
- g.setStart(QPointF(0, 0));
- g.setFinalStop(QPointF(0, 2 * opt->rect.height()));
- g.setColorAt(0, opt->palette.button().color());
- g.setColorAt(1, opt->palette.dark().color());
- p->fillPath(innerFramePath, g);
- } else {
- p->fillPath(innerFramePath, opt->palette.button());
- }
+ p->fillPath(innerFramePath, opt->palette.button());
if (titlebar->subControls & (SC_TitleBarCloseButton
| SC_TitleBarMaxButton
@@ -5696,8 +5616,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const bool rtl = groupBox.direction == Qt::RightToLeft;
const int alignment = Qt::TextHideMnemonic | (rtl ? Qt::AlignRight : Qt::AlignLeft);
const QFont savedFont = p->font();
- if (!flat)
- p->setFont(d->smallSystemFont);
+ if (!flat && d->smallSystemFont)
+ p->setFont(*d->smallSystemFont);
proxy()->drawItemText(p, rect, alignment, groupBox.palette, groupBox.state & State_Enabled, groupBox.text, QPalette::WindowText);
if (!flat)
p->setFont(savedFont);
@@ -5707,7 +5627,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
case CC_ToolButton:
if (const QStyleOptionToolButton *tb
= qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) {
if (tb->subControls & SC_ToolButtonMenu) {
QStyleOption arrowOpt = *tb;
@@ -5733,7 +5653,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget);
} else
-#endif // QT_NO_ACCESSIBILITY
+#endif // QT_CONFIG(accessibility)
{
auto bflags = tb->state;
if (tb->subControls & SC_ToolButton)
@@ -5980,7 +5900,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
qreal controlsSpacing = lastButtonRect.right() + titleBarButtonSpacing;
if (!titlebar->icon.isNull()) {
const auto iconSize = proxy()->pixelMetric(PM_SmallIconSize);
- const auto actualIconSize = titlebar->icon.actualSize(QSize(iconSize, iconSize)).width();;
+ const auto actualIconSize = titlebar->icon.actualSize(QSize(iconSize, iconSize)).width();
controlsSpacing += actualIconSize + titleBarIconTitleSpacing;
}
@@ -6061,7 +5981,9 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
const int margin = flat || hasNoText ? 0 : 9;
ret = groupBox->rect.adjusted(margin, 0, -margin, 0);
- const QFontMetricsF fm = flat || fontIsSet ? QFontMetricsF(groupBox->fontMetrics) : QFontMetricsF(d->smallSystemFont);
+ const QFontMetricsF fm = flat || fontIsSet || !d->smallSystemFont
+ ? QFontMetricsF(groupBox->fontMetrics)
+ : QFontMetricsF(*d->smallSystemFont);
const QSizeF s = fm.size(Qt::AlignHCenter | Qt::AlignVCenter, qt_mac_removeMnemonics(groupBox->text), 0, nullptr);
const int tw = qCeil(s.width());
const int h = qCeil(fm.height());
@@ -6215,7 +6137,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
case CC_ToolButton:
ret = QCommonStyle::subControlRect(cc, opt, sc, widget);
if (sc == SC_ToolButtonMenu) {
-#ifndef QT_NO_ACCESSIBILITY
+#if QT_CONFIG(accessibility)
if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar))
ret.adjust(-toolButtonArrowMargin, 0, 0, 0);
#endif
@@ -6626,7 +6548,7 @@ QIcon QMacStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *o
return QCommonStyle::standardIcon(standardIcon, opt, widget);
case SP_ToolBarHorizontalExtensionButton:
case SP_ToolBarVerticalExtensionButton: {
- QPixmap pixmap(QLatin1String(":/qt-project.org/styles/macstyle/images/toolbar-ext.png"));
+ QPixmap pixmap(QLatin1String(":/qt-project.org/styles/macstyle/images/toolbar-ext-macstyle.png"));
if (standardIcon == SP_ToolBarVerticalExtensionButton) {
QPixmap pix2(pixmap.height(), pixmap.width());
pix2.setDevicePixelRatio(pixmap.devicePixelRatio());