3192 const QWidget *w)
const
3194 Q_D(
const QMacStyle);
3195 QMacCGContext cg(p);
3197 qCWarning(lcMacStyle) <<
"drawPrimitive:" << pe <<
"invalid (nullptr) graphics context";
3199 QWindow *window = w && w->window() ? w->window()->windowHandle() :
nullptr;
3200 d->resolveCurrentNSView(window);
3202 case PE_IndicatorArrowUp:
3203 case PE_IndicatorArrowDown:
3204 case PE_IndicatorArrowRight:
3205 case PE_IndicatorArrowLeft: {
3207 p->setRenderHint(QPainter::Antialiasing);
3208 const int xOffset = 1;
3209 qreal halfSize = 0.5 * qMin(opt->rect.width(), opt->rect.height());
3210 const qreal penWidth = qMax(halfSize / 3.0, 1.25);
3211#if QT_CONFIG(toolbutton)
3212 if (
const QToolButton *tb = qobject_cast<
const QToolButton *>(w)) {
3214 if (tb->arrowType() != Qt::NoArrow
3215 || tb->popupMode() == QToolButton::MenuButtonPopup)
3216 halfSize -= penWidth;
3220 QTransform transform;
3221 transform.translate(opt->rect.center().x() + xOffset, opt->rect.center().y() + 2);
3225 case PE_IndicatorArrowDown:
3227 case PE_IndicatorArrowUp:
3228 transform.rotate(180);
3230 case PE_IndicatorArrowLeft:
3231 transform.rotate(90);
3233 case PE_IndicatorArrowRight:
3234 transform.rotate(-90);
3237 p->setTransform(transform);
3239 path.moveTo(-halfSize, -halfSize * 0.5);
3240 path.lineTo(0.0, halfSize * 0.5);
3241 path.lineTo(halfSize, -halfSize * 0.5);
3243 const QPen arrowPen(opt->palette.text(), penWidth,
3244 Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
3245 p->strokePath(path, arrowPen);
3248#if QT_CONFIG(tabbar)
3249 case PE_FrameTabBarBase:
3250 if (
const QStyleOptionTabBarBase *tbb
3251 = qstyleoption_cast<
const QStyleOptionTabBarBase *>(opt)) {
3252 if (tbb->documentMode) {
3254 drawTabBase(p, tbb, w);
3258#if QT_CONFIG(tabwidget)
3259 QRegion region(tbb->rect);
3260 region -= tbb->tabBarRect.adjusted(3, 0, -3, 0);
3262 p->setClipRegion(region);
3263 QStyleOptionTabWidgetFrame twf;
3264 twf.QStyleOption::operator=(*tbb);
3265 twf.shape = tbb->shape;
3266 switch (QMacStylePrivate::tabDirection(twf.shape)) {
3267 case QMacStylePrivate::North:
3268 twf.rect = twf.rect.adjusted(0, 0, 0, 10);
3270 case QMacStylePrivate::South:
3271 twf.rect = twf.rect.adjusted(0, -10, 0, 0);
3273 case QMacStylePrivate::West:
3274 twf.rect = twf.rect.adjusted(0, 0, 10, 0);
3276 case QMacStylePrivate::East:
3277 twf.rect = twf.rect.adjusted(0, -10, 0, 0);
3280 proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w);
3286 case PE_PanelTipLabel:
3287 p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase));
3289 case PE_FrameGroupBox:
3290 if (
const auto *groupBox = qstyleoption_cast<
const QStyleOptionFrame *>(opt))
3291 if (groupBox->features & QStyleOptionFrame::Flat) {
3292 QCommonStyle::drawPrimitive(pe, groupBox, p, w);
3295#if QT_CONFIG(tabwidget)
3297 case PE_FrameTabWidget:
3300 const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeLarge);
3301 auto *box =
static_cast<NSBox *>(d->cocoaControl(cw));
3315 auto adjustedRect = opt->rect;
3316 bool needTranslation =
false;
3318 if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave
3319 && !qt_apple_runningWithLiquidGlass() && !isDarkMode()) {
3332 adjustedRect.adjust(0, 0, 6, 6);
3333 needTranslation =
true;
3335 d->drawNSViewInRect(box, adjustedRect, p, ^(CGContextRef ctx,
const CGRect &rect) {
3336#if QT_CONFIG(tabwidget)
3337 if (qobject_cast<QTabWidget *>(opt->styleObject))
3338 clipTabBarFrame(opt,
this, ctx);
3340 CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height);
3341 CGContextScaleCTM(ctx, 1, -1);
3342 if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSMojave
3343 || [box isMemberOfClass:QDarkNSBox.
class]) {
3344 [box drawRect:rect];
3346 if (needTranslation)
3347 CGContextTranslateCTM(ctx, -3.0, 5.0);
3348 [box displayRectIgnoringOpacity:box.bounds inContext:NSGraphicsContext.currentContext];
3353 case PE_IndicatorToolBarSeparator: {
3355 if (opt->state & State_Horizontal) {
3356 int xpoint = opt->rect.center().x();
3357 path.moveTo(xpoint + 0.5, opt->rect.top() + 1);
3358 path.lineTo(xpoint + 0.5, opt->rect.bottom());
3360 int ypoint = opt->rect.center().y();
3361 path.moveTo(opt->rect.left() + 2 , ypoint + 0.5);
3362 path.lineTo(opt->rect.right() + 1, ypoint + 0.5);
3364 QPainterPathStroker theStroker;
3365 theStroker.setCapStyle(Qt::FlatCap);
3366 theStroker.setDashPattern(QVector<qreal>() << 1 << 2);
3367 path = theStroker.createStroke(path);
3368 const auto dark =
isDarkMode() ? opt->palette.dark().color().darker()
3369 : QColor(0, 0, 0, 119);
3370 p->fillPath(path, dark);
3373 case PE_FrameWindow:
3374 if (
const QStyleOptionFrame *frame = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
3375 if (qobject_cast<
const QMdiSubWindow*>(w)) {
3377 p->setPen(QPen(frame->palette.dark().color(), frame->lineWidth));
3378 p->setBrush(frame->palette.window());
3379 p->drawRect(frame->rect);
3384 case PE_IndicatorDockWidgetResizeHandle: {
3387 if (opt->state & State_Horizontal) {
3388 p->setPen(QColor(160, 160, 160));
3389 p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
3391 p->setPen(QColor(145, 145, 145));
3392 p->drawLine(opt->rect.topRight(), opt->rect.bottomRight());
3396 case PE_IndicatorToolBarHandle: {
3399 int x = opt->rect.x() + 6;
3400 int y = opt->rect.y() + 7;
3401 static const int RectHeight = 2;
3402 if (opt->state & State_Horizontal) {
3403 while (y < opt->rect.height() - RectHeight - 5) {
3405 path.addEllipse(x, y, RectHeight, RectHeight);
3409 while (x < opt->rect.width() - RectHeight - 5) {
3411 path.addEllipse(x, y, RectHeight, RectHeight);
3415 p->setPen(Qt::NoPen);
3416 QColor dark = opt->palette.dark().color().darker();
3417 dark.setAlphaF(0.50);
3418 p->fillPath(path, dark);
3423 case PE_IndicatorHeaderArrow:
3424 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(opt)) {
3426 if (header->sortIndicator != QStyleOptionHeader::None)
3427 proxy()->drawPrimitive(
3428 (header->sortIndicator == QStyleOptionHeader::SortDown) ?
3429 PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w);
3432 case PE_IndicatorMenuCheckMark: {
3436 if (opt->state & State_On)
3437 pc = opt->palette.highlightedText().color();
3439 pc = opt->palette.text().color();
3441 QCFType<CGColorRef> checkmarkColor = CGColorCreateGenericRGB(
static_cast<CGFloat>(pc.redF()),
3442 static_cast<CGFloat>(pc.greenF()),
3443 static_cast<CGFloat>(pc.blueF()),
3444 static_cast<CGFloat>(pc.alphaF()));
3450 const CTFontUIFontType fontType = (opt->state & State_Mini) ? kCTFontUIFontMiniSystem :
3451 (opt->state & State_Small) ? kCTFontUIFontSmallSystem :
3452 kCTFontUIFontMenuItemMark;
3456 const CGFloat fontSize = fontType == kCTFontUIFontMenuItemMark ? opt->fontMetrics.height() : 0.0;
3457 QCFType<CTFontRef> checkmarkFont = CTFontCreateUIFontForLanguage(fontType, fontSize, NULL);
3459 CGContextSaveGState(cg);
3460 CGContextSetShouldSmoothFonts(cg, NO);
3463 const CGFloat vOffset = (opt->state & State_Mini) ? 0.0 :
3464 (opt->state & State_Small) ? 1.0 :
3467 CGContextTranslateCTM(cg, 0, opt->rect.bottom());
3468 CGContextScaleCTM(cg, 1, -1);
3470 CGContextTranslateCTM(cg, opt->rect.x(), vOffset);
3474 static const CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName };
3475 static const int numValues =
sizeof(keys) /
sizeof(keys[0]);
3476 const CFTypeRef values[] = { (CFTypeRef)checkmarkFont, (CFTypeRef)checkmarkColor };
3477 static_assert((
sizeof(values) /
sizeof(values[0])) == numValues);
3478 QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(kCFAllocatorDefault, (
const void **)keys, (
const void **)values,
3479 numValues, NULL, NULL);
3481 QCFType<CFAttributedStringRef> checkmarkString = CFAttributedStringCreate(kCFAllocatorDefault, (CFStringRef)@
"\u2713", attributes);
3482 QCFType<CTLineRef> line = CTLineCreateWithAttributedString(checkmarkString);
3484 CTLineDraw((CTLineRef)line, cg);
3487 CGContextRestoreGState(cg);
3489 case PE_IndicatorItemViewItemCheck:
3490 case PE_IndicatorRadioButton:
3491 case PE_IndicatorCheckBox: {
3492 const bool isEnabled = opt->state & State_Enabled;
3493 const bool isPressed = opt->state & State_Sunken;
3494 const bool isRadioButton = (pe == PE_IndicatorRadioButton);
3495 const auto ct = isRadioButton ? QMacStylePrivate::Button_RadioButton : QMacStylePrivate::Button_CheckBox;
3496 const auto cs = d->effectiveAquaSizeConstrain(opt, w);
3497 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
3498 auto *tb =
static_cast<NSButton *>(d->cocoaControl(cw));
3499 tb.enabled = isEnabled;
3500 tb.state = (opt->state & State_NoChange) ? NSControlStateValueMixed :
3501 (opt->state & State_On) ? NSControlStateValueOn : NSControlStateValueOff;
3502 [tb highlight:isPressed];
3503 const auto vOffset = [=] {
3505 if (cs == QStyleHelper::SizeMini)
3506 return ct == QMacStylePrivate::Button_CheckBox ? -0.5 : 0.5;
3508 return cs == QStyleHelper::SizeSmall ? 0.5 : 0.0;
3510 d->drawNSViewInRect(tb, opt->rect, p, ^(CGContextRef ctx,
const CGRect &rect) {
3511 CGContextTranslateCTM(ctx, 0, vOffset);
3512 [tb.cell drawInteriorWithFrame:rect inView:tb];
3515 case PE_FrameFocusRect:
3518 case PE_IndicatorBranch: {
3519 if (!(opt->state & State_Children))
3523 const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Button_Disclosure, QStyleHelper::SizeLarge);
3524 NSButtonCell *triangleCell =
static_cast<NSButtonCell *>(d->cocoaCell(cw));
3525 [triangleCell setState:(opt->state & State_Open) ? NSControlStateValueOn : NSControlStateValueOff];
3526 bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus);
3527 [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleEmphasized : NSBackgroundStyleNormal];
3528 [triangleCell setUserInterfaceLayoutDirection:qt_macLayoutDirectionFromQt(opt->direction)];
3530 d->setupNSGraphicsContext(cg, NO);
3533 CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height());
3534 CGContextTranslateCTM(cg, rect.origin.x, rect.origin.y + rect.size.height);
3535 CGContextScaleCTM(cg, 1, -1);
3536 CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y);
3538 [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
3540 d->restoreNSGraphicsContext(cg);
3544 QPen oldPen = p->pen();
3545 p->setPen(opt->palette.base().color().darker(140));
3546 p->drawRect(opt->rect.adjusted(0, 0, -1, -1));
3547 p->setPen(opt->palette.base().color().darker(180));
3548 p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
3552 case PE_FrameLineEdit:
3553 if (
const QStyleOptionFrame *frame = qstyleoption_cast<
const QStyleOptionFrame *>(opt)) {
3554 if (frame->state & State_Sunken) {
3555 const bool isEnabled = opt->state & State_Enabled;
3556 const bool isReadOnly = opt->state & State_ReadOnly;
3557 const bool isRounded = frame->features & QStyleOptionFrame::Rounded;
3558 const auto cs = d->effectiveAquaSizeConstrain(opt, w, CT_LineEdit);
3559 const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::TextField, cs);
3560 auto *tf =
static_cast<NSTextField *>(d->cocoaControl(cw));
3561 tf.enabled = isEnabled;
3562 tf.editable = !isReadOnly;
3564 static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel;
3565 tf.frame = opt->rect.toCGRect();
3566 d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef,
const CGRect &rect) {
3567 if (!isDarkMode()) {
3572 CGContextRef cgContext = NSGraphicsContext.currentContext.CGContext;
3576 if (cgContext ?
bool(CGBitmapContextGetColorSpace(cgContext)) :
false) {
3577 tf.drawsBackground = YES;
3578 const QColor bgColor = frame->palette.brush(QPalette::Base).color();
3579 tf.backgroundColor = [NSColor colorWithSRGBRed:bgColor.redF()
3580 green:bgColor.greenF()
3581 blue:bgColor.blueF()
3582 alpha:bgColor.alphaF()];
3583 if (bgColor.alpha() != 255) {
3590 CGRect fixedRect = rect;
3591 if (qt_apple_runningWithLiquidGlass()) {
3596 fixedRect = CGRectInset(rect, 1., 1.);
3598 [tf.cell drawWithFrame:fixedRect inView:tf];
3601 QCommonStyle::drawPrimitive(pe, opt, p, w);
3605 case PE_PanelLineEdit:
3607 const QStyleOptionFrame *panel = qstyleoption_cast<
const QStyleOptionFrame *>(opt);
3608 if (
isDarkMode() || (panel && panel->lineWidth <= 0)) {
3614 QCommonStyle::drawPrimitive(pe, opt, p, w);
3619 drawPrimitive(PE_FrameLineEdit, opt, p, w);
3625#if QT_CONFIG(lineedit)
3626 if ((opt->state & State_HasFocus) && !qobject_cast<
const QLineEdit*>(w)) {
3627 int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin);
3628 int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin);
3629 QStyleOptionFrame focusFrame = *panel;
3630 focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin);
3631 drawControl(CE_FocusFrame, &focusFrame, p, w);
3637 case PE_PanelScrollAreaCorner: {
3638 const QBrush brush(opt->palette.brush(QPalette::Base));
3639 p->fillRect(opt->rect, brush);
3640 p->setPen(QPen(QColor(217, 217, 217)));
3641 p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
3642 p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft());
3644 case PE_FrameStatusBarItem:
3646#if QT_CONFIG(tabbar)
3647 case PE_IndicatorTabClose: {
3649 QTabBar *tabBar = qobject_cast<QTabBar*>(w->parentWidget());
3650 const QWidget *closeBtn = w;
3654 tabBar = qobject_cast<QTabBar *>(
const_cast<QWidget*>(w));
3655 closeBtn =
decltype(closeBtn)(property(
"_q_styleSheetRealCloseButton").value<
void *>());
3658 const bool documentMode = tabBar->documentMode();
3659 const QTabBarPrivate *tabBarPrivate =
static_cast<QTabBarPrivate *>(QObjectPrivate::get(tabBar));
3660 const int hoveredTabIndex = tabBarPrivate->hoveredTabIndex();
3661 if (!documentMode ||
3662 (hoveredTabIndex != -1 && ((closeBtn == tabBar->tabButton(hoveredTabIndex, QTabBar::LeftSide)) ||
3663 (closeBtn == tabBar->tabButton(hoveredTabIndex, QTabBar::RightSide))))) {
3664 const bool hover = (opt->state & State_MouseOver);
3665 const bool selected = (opt->state & State_Selected);
3666 const bool pressed = (opt->state & State_Sunken);
3667 drawTabCloseButton(p, hover, selected, pressed, documentMode);
3672 case PE_PanelStatusBar: {
3673 p->fillRect(opt->rect, opt->palette.window());
3676 if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active))
3677 p->setPen(titlebarSeparatorLineActive);
3679 p->setPen(titlebarSeparatorLineInactive);
3680 p->drawLine(opt->rect.left(), opt->rect.top(), opt->rect.right(), opt->rect.top());
3684 case PE_PanelMenu: {
3686 p->fillRect(opt->rect, Qt::transparent);
3687 p->setPen(Qt::transparent);
3688 p->setBrush(opt->palette.window());
3689 p->setRenderHint(QPainter::Antialiasing,
true);
3690 const QPainterPath path = d->windowPanelPath(opt->rect);
3696 QCommonStyle::drawPrimitive(pe, opt, p, w);
3737 const QWidget *w)
const
3739 Q_D(
const QMacStyle);
3740 const QMacAutoReleasePool pool;
3741 QMacCGContext cg(p);
3743 qCWarning(lcMacStyle) <<
"drawControl:" << ce <<
"invalid (nullptr) graphics context";
3745 QWindow *window = w && w->window() ? w->window()->windowHandle() :
nullptr;
3746 d->resolveCurrentNSView(window);
3748 case CE_HeaderSection:
3749 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(opt)) {
3750 State flags = header->state;
3751 QRect ir = header->rect;
3755 bool noVerticalHeader =
true;
3756#if QT_CONFIG(tableview)
3758 if (
const QTableView *table = qobject_cast<
const QTableView *>(w->parentWidget()))
3759 noVerticalHeader = !table->verticalHeader()->isVisible();
3762 const bool drawLeftBorder = header->orientation == Qt::Vertical
3763 || header->position == QStyleOptionHeader::OnlyOneSection
3764 || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader);
3767 const bool pressed = (flags & State_Sunken) && !(flags & State_On);
3768 p->fillRect(ir, pressed ? header->palette.dark() : header->palette.button());
3769 p->setPen(QPen(header->palette.dark(), 1.0));
3770 if (header->orientation == Qt::Horizontal)
3779 case CE_ToolButtonLabel:
3780 if (
const QStyleOptionToolButton *tb = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
3781 QStyleOptionToolButton myTb = *tb;
3782 myTb.state &= ~State_AutoRaise;
3783#if QT_CONFIG(accessibility)
3784 if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) {
3785 QRect cr = tb->rect;
3788 bool needText =
false;
3790 bool down = tb->state & (State_Sunken | State_On);
3792 shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w);
3793 shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w);
3799 if (!(tb->features & QStyleOptionToolButton::Arrow)) {
3800 Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle;
3801 if (tb->icon.isNull() && !tb->text.isEmpty())
3802 tbstyle = Qt::ToolButtonTextOnly;
3805 case Qt::ToolButtonTextOnly: {
3807 alignment = Qt::AlignCenter;
3809 case Qt::ToolButtonIconOnly:
3810 case Qt::ToolButtonTextBesideIcon:
3811 case Qt::ToolButtonTextUnderIcon: {
3813 QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal
3815 QIcon::State iconState = (tb->state & State_On) ? QIcon::On
3817 QPixmap pixmap = tb->icon.pixmap(tb->rect.size().boundedTo(tb->iconSize), p->device()->devicePixelRatio(),
3818 iconMode, iconState);
3821 if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) {
3823 QSizeF size = pixmap.deviceIndependentSize();
3824 if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
3825 pr.setHeight(size.height() + 6);
3826 cr.adjust(0, pr.bottom(), 0, -3);
3827 alignment |= Qt::AlignCenter;
3829 pr.setWidth(size.width() + 8);
3830 cr.adjust(pr.right(), 0, 0, 0);
3831 alignment |= Qt::AlignLeft | Qt::AlignVCenter;
3834 if (opt->state & State_Sunken) {
3835 pr.translate(shiftX, shiftY);
3836 pixmap = darkenPixmap(pixmap);
3838 proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap);
3846 QPalette pal = tb->palette;
3847 QPalette::ColorRole role = QPalette::NoRole;
3848 if (!proxy()->styleHint(SH_UnderlineShortcut, tb, w))
3849 alignment |= Qt::TextHideMnemonic;
3851 cr.translate(shiftX, shiftY);
3852 if (tbstyle == Qt::ToolButtonTextOnly
3853 || (tbstyle != Qt::ToolButtonTextOnly && !down)) {
3854 QPen pen = p->pen();
3855 QColor light = down || isDarkMode() ? Qt::black : Qt::white;
3856 light.setAlphaF(0.375f);
3858 p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text);
3860 if (down && tbstyle == Qt::ToolButtonTextOnly) {
3861 pal = QApplication::palette(
"QMenu");
3862 pal.setCurrentColorGroup(tb->palette.currentColorGroup());
3863 role = QPalette::HighlightedText;
3866 proxy()->drawItemText(p, cr, alignment, pal,
3867 tb->state & State_Enabled, tb->text, role);
3870 QCommonStyle::drawControl(ce, &myTb, p, w);
3875 QCommonStyle::drawControl(ce, &myTb, p, w);
3879 case CE_ToolBoxTabShape:
3880 QCommonStyle::drawControl(ce, opt, p, w);
3882 case CE_PushButtonBevel:
3883 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3884 if (!(btn->state & (State_Raised | State_Sunken | State_On)))
3887 if (btn->features & QStyleOptionButton::CommandLinkButton) {
3888 QCommonStyle::drawControl(ce, opt, p, w);
3892 const bool hasFocus = btn->state & State_HasFocus;
3893 const bool isActive = btn->state & State_Active;
3897 if ((btn->features & QStyleOptionButton::AutoDefaultButton)
3898 && isActive && hasFocus)
3899 d->autoDefaultButton = btn->styleObject;
3900 else if (d->autoDefaultButton == btn->styleObject)
3901 d->autoDefaultButton =
nullptr;
3903 const bool isEnabled = btn->state & State_Enabled;
3904 const bool isPressed = btn->state & State_Sunken;
3905 const bool isHighlighted = isActive &&
3906 ((btn->state & State_On)
3907 || (btn->features & QStyleOptionButton::DefaultButton)
3908 || (btn->features & QStyleOptionButton::AutoDefaultButton
3909 && d->autoDefaultButton == btn->styleObject));
3910 const bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
3911 const auto ct = cocoaControlType(btn, w);
3912 const auto cs = d->effectiveAquaSizeConstrain(btn, w);
3913 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
3914 auto *pb =
static_cast<NSButton *>(d->cocoaControl(cw));
3918 const QRectF frameRect = cw.adjustedControlFrame(btn->rect);
3919 pb.frame = frameRect.toCGRect();
3921 pb.enabled = isEnabled;
3926 [pb highlight:isPressed];
3929 if (cw.type == QMacStylePrivate::Button_SquareButton) {
3930 pb.state = isHighlighted && !isPressed ? NSControlStateValueOn : NSControlStateValueOff;
3934 pb.keyEquivalent = isHighlighted ? @
"\r" : @
"";
3937 d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef,
const CGRect &r) {
3938 [pb.cell drawBezelWithFrame:r inView:pb.superview];
3942 if (hasMenu && cw.type == QMacStylePrivate::Button_SquareButton) {
3945 const int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
3946 const auto ir = frameRect.toRect();
3947 int arrowYOffset = 0;
3952 arrowYOffset -= ir.top();
3953 if (cw.second == QStyleHelper::SizeSmall)
3957 const auto ar = visualRect(btn->direction, ir, QRect(ir.right() - mbi - 6, ir.height() / 2 - arrowYOffset, mbi, mbi));
3959 QStyleOption arrowOpt = *opt;
3961 proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, w);
3965 case CE_PushButtonLabel:
3966 if (
const QStyleOptionButton *b = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
3967 QStyleOptionButton btn(*b);
3972 const bool isEnabled = btn.state & State_Enabled;
3973 const bool hasMenu = btn.features & QStyleOptionButton::HasMenu;
3974 const bool hasIcon = !btn.icon.isNull();
3975 const bool hasText = !btn.text.isEmpty();
3976 const bool isActive = btn.state & State_Active;
3977 const bool isPressed = btn.state & State_Sunken;
3978 const bool isDefault = (btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton)
3979 || d->autoDefaultButton == btn.styleObject;
3983 const QRect oldRect = btn.rect;
3985 btn.rect = w->rect();
3986 const auto ct = cocoaControlType(&btn, w);
3989 if (!hasMenu && ct != QMacStylePrivate::Button_SquareButton) {
3990 if (isPressed || (isActive && isEnabled && ((btn.state & State_On) || isDefault)))
3991 btn.palette.setColor(QPalette::ButtonText, Qt::white);
3994 if (isEnabled && !isDarkMode() && QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur) {
3995 if (!isDefault && !(btn.state & State_On)) {
3998 btn.palette.setColor(QPalette::ButtonText, Qt::black);
4002 if ((!hasIcon && !hasMenu) || (hasIcon && !hasText)) {
4003 QCommonStyle::drawControl(ce, &btn, p, w);
4005 QRect freeContentRect = btn.rect;
4006 QRect textRect = itemTextRect(
4007 btn.fontMetrics, freeContentRect, Qt::AlignCenter, isEnabled, btn.text);
4009 if (ct == QMacStylePrivate::Button_SquareButton)
4010 textRect.moveTo(w ? 8 : 11, textRect.top());
4012 textRect.moveTo(w ? (15 - pushButtonBevelRectOffsets[d->effectiveAquaSizeConstrain(b, w)])
4013 : 11, textRect.top());
4017 int contentW = textRect.width();
4019 contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4;
4020 QIcon::Mode mode = isEnabled ? QIcon::Normal : QIcon::Disabled;
4021 if (mode == QIcon::Normal && btn.state & State_HasFocus)
4022 mode = QIcon::Active;
4024 QIcon::State state = QIcon::Off;
4025 if (btn.state & State_On)
4027 QPixmap pixmap = btn.icon.pixmap(btn.iconSize, p->device()->devicePixelRatio(), mode, state);
4028 QSizeF pixmapSize = pixmap.deviceIndependentSize();
4029 contentW += pixmapSize.width() + QMacStylePrivate::PushButtonContentPadding;
4030 int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2;
4031 int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapSize.height()) / 2;
4032 QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapSize.width(), pixmapSize.height());
4033 QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect);
4034 proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
4035 int newOffset = iconDestRect.x() + iconDestRect.width()
4036 + QMacStylePrivate::PushButtonContentPadding - textRect.x();
4037 textRect.adjust(newOffset, 0, newOffset, 0);
4041 textRect = visualRect(btn.direction, freeContentRect, textRect);
4042 proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette,
4043 isEnabled, btn.text, QPalette::ButtonText);
4048#if QT_CONFIG(combobox)
4049 case CE_ComboBoxLabel:
4050 if (
const auto *cb = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
4051 auto comboCopy = *cb;
4052 comboCopy.direction = Qt::LeftToRight;
4054 QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w);
4058#if QT_CONFIG(tabbar)
4059 case CE_TabBarTabShape:
4060 if (
const auto *tabOpt = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
4061 if (tabOpt->documentMode) {
4063 bool isUnified =
false;
4065 QRect tabRect = tabOpt->rect;
4066 QPoint windowTabStart = w->mapTo(w->window(), tabRect.topLeft());
4067 isUnified = isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowTabStart.y());
4070 const int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, opt, w);
4071 drawTabShape(p, tabOpt, isUnified, tabOverlap);
4100 const bool isActive = tabOpt->state & State_Active;
4101 const bool isEnabled = tabOpt->state & State_Enabled;
4102 const bool isPressed = tabOpt->state & State_Sunken;
4103 const bool isSelected = tabOpt->state & State_Selected;
4104 const auto tabDirection = QMacStylePrivate::tabDirection(tabOpt->shape);
4105 const bool verticalTabs = tabDirection == QMacStylePrivate::East
4106 || tabDirection == QMacStylePrivate::West;
4108 QStyleOptionTab::TabPosition tp = tabOpt->position;
4109 QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition;
4110 if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) {
4111 if (tp == QStyleOptionTab::Beginning)
4112 tp = QStyleOptionTab::End;
4113 else if (tp == QStyleOptionTab::End)
4114 tp = QStyleOptionTab::Beginning;
4116 if (sp == QStyleOptionTab::NextIsSelected)
4117 sp = QStyleOptionTab::PreviousIsSelected;
4118 else if (sp == QStyleOptionTab::PreviousIsSelected)
4119 sp = QStyleOptionTab::NextIsSelected;
4128 const auto cs = d->effectiveAquaSizeConstrain(opt, w);
4130 const bool needsInactiveHack = !isActive && isSelected;
4131 const bool isBigSurOrAbove = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSBigSur;
4132 const auto ct = !needsInactiveHack && (isSelected || tp == QStyleOptionTab::OnlyOneTab) ?
4133 QMacStylePrivate::Button_PushButton :
4134 QMacStylePrivate::Button_PopupButton;
4135 const bool isPopupButton = ct == QMacStylePrivate::Button_PopupButton;
4136 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
4137 auto *pb =
static_cast<NSButton *>(d->cocoaControl(cw));
4138 auto vOffset = isPopupButton ? 1 : 2;
4139 if (isBigSurOrAbove) {
4145 if (tabDirection == QMacStylePrivate::East)
4147 const auto outerAdjust = isPopupButton ? 1 : 4;
4148 const auto innerAdjust = isPopupButton ? 20 : 10;
4149 QRectF frameRect = tabOpt->rect;
4151 frameRect = QRectF(frameRect.y(), frameRect.x(), frameRect.height(), frameRect.width());
4153 frameRect = frameRect.translated(0, vOffset);
4155 case QStyleOptionTab::Beginning:
4157 if (!isSelected && tabDirection == QMacStylePrivate::West)
4158 frameRect = frameRect.adjusted(-innerAdjust, 0, outerAdjust, 0);
4160 frameRect = frameRect.adjusted(-outerAdjust, 0, innerAdjust, 0);
4162 if (isSelected && isBigSurOrAbove) {
4165 frameRect = frameRect.adjusted(0, 0, 1, 0);
4168 case QStyleOptionTab::Middle:
4169 frameRect = frameRect.adjusted(-innerAdjust, 0, innerAdjust, 0);
4171 if (isSelected && isBigSurOrAbove) {
4174 frameRect = frameRect.adjusted(-1, 0, 1, 0);
4177 case QStyleOptionTab::Moving:
4178 case QStyleOptionTab::End:
4180 if (isSelected || tabDirection == QMacStylePrivate::West)
4181 frameRect = frameRect.adjusted(-innerAdjust, 0, outerAdjust, 0);
4183 frameRect = frameRect.adjusted(-outerAdjust, 0, innerAdjust, 0);
4185 if (isSelected && isBigSurOrAbove) {
4187 frameRect = frameRect.adjusted(-1, 0, 0, 0);
4190 case QStyleOptionTab::OnlyOneTab:
4191 frameRect = frameRect.adjusted(-outerAdjust, 0, outerAdjust, 0);
4194 pb.frame = frameRect.toCGRect();
4196 if (!isPopupButton) {
4200 pb.buttonType = NSButtonTypePushOnPushOff;
4203 pb.enabled = isEnabled;
4204 [pb highlight:isPressed];
4208 if (QOperatingSystemVersion::current() > QOperatingSystemVersion::MacOSBigSur)
4209 pb.state = (isActive && isSelected) ? NSControlStateValueOn : NSControlStateValueOff;
4211 pb.state = (isActive && isSelected && !isPressed) ? NSControlStateValueOn : NSControlStateValueOff;
4213 const auto drawBezelBlock = ^(CGContextRef ctx,
const CGRect &r) {
4214 CGContextClipToRect(ctx, opt->rect.toCGRect());
4215 if (!isSelected || needsInactiveHack) {
4217 if (!verticalTabs && tp == QStyleOptionTab::End) {
4218 CGContextTranslateCTM(ctx, opt->rect.right(), 0);
4219 CGContextScaleCTM(ctx, -1, 1);
4220 CGContextTranslateCTM(ctx, -frameRect.left(), 0);
4221 }
else if (tabDirection == QMacStylePrivate::West && tp == QStyleOptionTab::Beginning) {
4222 CGContextTranslateCTM(ctx, 0, opt->rect.top());
4223 CGContextScaleCTM(ctx, 1, -1);
4224 CGContextTranslateCTM(ctx, 0, -frameRect.right());
4225 }
else if (tabDirection == QMacStylePrivate::East && tp == QStyleOptionTab::End) {
4226 CGContextTranslateCTM(ctx, 0, opt->rect.bottom());
4227 CGContextScaleCTM(ctx, 1, -1);
4228 CGContextTranslateCTM(ctx, 0, -frameRect.left());
4234 if (tabDirection == QMacStylePrivate::West) {
4235 CGContextTranslateCTM(ctx, 0, frameRect.right());
4236 CGContextRotateCTM(ctx, -M_PI_2);
4237 CGContextTranslateCTM(ctx, -frameRect.left(), 0);
4238 }
else if (tabDirection == QMacStylePrivate::East) {
4239 CGContextTranslateCTM(ctx, opt->rect.right(), 0);
4240 CGContextRotateCTM(ctx, M_PI_2);
4245 NSPopUpArrowPosition oldPosition = NSPopUpArrowAtCenter;
4246 NSPopUpButtonCell *pbCell = nil;
4248 if (isPopupButton && (tp == QStyleOptionTab::OnlyOneTab || isBigSurOrAbove)) {
4252 pbCell =
static_cast<NSPopUpButtonCell *>(pb.cell);
4253 oldPosition = pbCell.arrowPosition;
4254 pbCell.arrowPosition = NSPopUpNoArrow;
4255 if (pb.state == NSControlStateValueOff) {
4257 rAdjusted.origin.x -= 3;
4258 rAdjusted.size.width += 6;
4259 if (isBigSurOrAbove) {
4260 if (tp == QStyleOptionTab::End)
4261 rAdjusted.origin.x -= 2;
4265 if (qt_apple_runningWithLiquidGlass()) {
4274 const CGFloat deltaW = 20.0;
4275 rAdjusted = CGContextGetClipBoundingBox(ctx);
4276 if (tp == QStyleOptionTab::Beginning) {
4281 rAdjusted.size.width += deltaW;
4283 if (tabDirection == QMacStylePrivate::West && isSelected && isActive) {
4287 rAdjusted.origin.x -= deltaW;
4289 }
else if (tp == QStyleOptionTab::Middle) {
4291 rAdjusted.origin.x -= deltaW;
4292 rAdjusted.size.width += deltaW * 2;
4293 }
else if (tp == QStyleOptionTab::End) {
4294 if (isSelected && isActive && tabDirection != QMacStylePrivate::West)
4295 rAdjusted.origin.x -= deltaW;
4296 rAdjusted.size.width += deltaW;
4300 [pb.cell drawBezelWithFrame:rAdjusted inView:pb.superview];
4303 pbCell.arrowPosition = oldPosition;
4306 if (needsInactiveHack) {
4308 const qreal pixelRatio = p->device()->devicePixelRatio();
4309 QImage tabPixmap(opt->rect.size() * pixelRatio, QImage::Format_ARGB32_Premultiplied);
4310 tabPixmap.setDevicePixelRatio(pixelRatio);
4311 tabPixmap.fill(Qt::transparent);
4312 QPainter tabPainter(&tabPixmap);
4313 d->drawNSViewInRect(pb, frameRect, &tabPainter, ^(CGContextRef ctx,
const CGRect &r) {
4314 CGContextTranslateCTM(ctx, -opt->rect.left(), -opt->rect.top());
4315 drawBezelBlock(ctx, r);
4320 const qreal inactiveGray = 0.898;
4321 const int inactiveGray8 = qRound(inactiveGray * 255.0);
4322 const QRgb inactiveGrayRGB = qRgb(inactiveGray8, inactiveGray8, inactiveGray8);
4323 for (
int l = 0; l < tabPixmap.height(); ++l) {
4324 auto *line =
reinterpret_cast<QRgb*>(tabPixmap.scanLine(l));
4325 for (
int i = 0; i < tabPixmap.width(); ++i) {
4326 if (qAlpha(line[i]) == 255) {
4327 line[i] = inactiveGrayRGB;
4328 }
else if (qAlpha(line[i]) > 128) {
4329 const int g = qRound(inactiveGray * qRed(line[i]));
4330 line[i] = qRgba(g, g, g, qAlpha(line[i]));
4336 p->drawImage(opt->rect, tabPixmap);
4338 d->drawNSViewInRect(pb, frameRect, p, drawBezelBlock);
4341 if (!isSelected && sp != QStyleOptionTab::NextIsSelected
4342 && tp != QStyleOptionTab::End
4343 && tp != QStyleOptionTab::OnlyOneTab) {
4344 static const QPen separatorPen(Qt::black, 1.0);
4346 p->setOpacity(isEnabled ? 0.105 : 0.06);
4347 p->setPen(separatorPen);
4348 if (tabDirection == QMacStylePrivate::West) {
4349 p->drawLine(QLineF(opt->rect.left() + 1.5, opt->rect.bottom(),
4350 opt->rect.right() - 0.5, opt->rect.bottom()));
4351 }
else if (tabDirection == QMacStylePrivate::East) {
4352 p->drawLine(QLineF(opt->rect.left(), opt->rect.bottom(),
4353 opt->rect.right() - 0.5, opt->rect.bottom()));
4355 p->drawLine(QLineF(opt->rect.right(), opt->rect.top() + 1.0,
4356 opt->rect.right(), opt->rect.bottom() - 0.5));
4362 case CE_TabBarTabLabel:
4363 if (
const auto *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
4364 QStyleOptionTab myTab = *tab;
4365 const auto foregroundRole = w ? w->foregroundRole() : QPalette::WindowText;
4366 const auto tabDirection = QMacStylePrivate::tabDirection(tab->shape);
4367 const bool verticalTabs = tabDirection == QMacStylePrivate::East
4368 || tabDirection == QMacStylePrivate::West;
4374 const bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value(
"QComboMenuItem");
4376 if (!myTab.documentMode && (myTab.state & State_Selected) && (myTab.state & State_Active))
4377 if (
const auto *tabBar = qobject_cast<
const QTabBar *>(w))
4378 if (!tabBar->tabTextColor(tabBar->currentIndex()).isValid())
4379 myTab.palette.setColor(foregroundRole, Qt::white);
4381 if (myTab.documentMode && isDarkMode()) {
4382 bool active = (myTab.state & State_Selected) && (myTab.state & State_Active);
4383 myTab.palette.setColor(foregroundRole, active ? Qt::white : Qt::gray);
4386 int heightOffset = 0;
4389 }
else if (nonDefaultFont) {
4390 if (p->fontMetrics().height() == myTab.rect.height())
4393 myTab.rect.setHeight(myTab.rect.height() + heightOffset);
4395 QCommonStyle::drawControl(ce, &myTab, p, w);
4399#if QT_CONFIG(dockwidget)
4400 case CE_DockWidgetTitle:
4401 if (
const auto *dwOpt = qstyleoption_cast<
const QStyleOptionDockWidget *>(opt)) {
4402 const bool isVertical = dwOpt->verticalTitleBar;
4403 const auto effectiveRect = isVertical ? opt->rect.transposed() : opt->rect;
4406 p->translate(effectiveRect.left(), effectiveRect.top() + effectiveRect.width());
4408 p->translate(-effectiveRect.left(), -effectiveRect.top());
4412 p->fillRect(effectiveRect, opt->palette.window());
4415 p->setPen(opt->palette.dark().color());
4416 p->drawLine(effectiveRect.bottomLeft(), effectiveRect.bottomRight());
4418 if (!dwOpt->title.isEmpty()) {
4419 auto titleRect = proxy()->subElementRect(SE_DockWidgetTitleBarText, opt, w);
4421 titleRect = QRect(effectiveRect.left() + opt->rect.bottom() - titleRect.bottom(),
4422 effectiveRect.top() + titleRect.left() - opt->rect.left(),
4426 const auto text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width());
4427 proxy()->drawItemText(p, titleRect, Qt::AlignCenter | Qt::TextHideMnemonic, dwOpt->palette,
4428 dwOpt->state & State_Enabled, text, QPalette::WindowText);
4434 case CE_FocusFrame: {
4435 const auto *ff = qobject_cast<
const QFocusFrame *>(w);
4436 const auto *ffw = ff ? ff->widget() :
nullptr;
4437 const auto ct = [=] {
4439 if (qobject_cast<
const QCheckBox*>(ffw))
4440 return QMacStylePrivate::Button_CheckBox;
4441 if (qobject_cast<
const QRadioButton*>(ffw))
4442 return QMacStylePrivate::Button_RadioButton;
4443 if (qobject_cast<
const QLineEdit*>(ffw) || qobject_cast<
const QTextEdit*>(ffw))
4444 return QMacStylePrivate::TextField;
4445 if (
const auto *pb = qobject_cast<
const QPushButton *>(ffw)) {
4447 auto sizePolicy = QStyleHelper::widgetSizePolicy(ffw, opt);
4448 if (sizePolicy == QStyleHelper::SizeDefault)
4449 sizePolicy = QStyleHelper::SizeLarge;
4451 || (pb->rect().height() != pushButtonDefaultHeight[sizePolicy])) {
4452 return QMacStylePrivate::Button_SquareButton;
4454 if (pb->menu() !=
nullptr)
4455 return QMacStylePrivate::Button_PullDown;
4456 return QMacStylePrivate::Button_PushButton;
4460 return QMacStylePrivate::Box;
4462 auto cs = QStyleHelper::widgetSizePolicy(ffw, opt);
4463 if (cs == QStyleHelper::SizeDefault)
4464 cs = QStyleHelper::SizeLarge;
4465 const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w);
4466 const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w);
4467 d->drawFocusRing(p, opt->rect, hMargin, vMargin, QMacStylePrivate::CocoaControl(ct, cs));
4469 case CE_MenuEmptyArea:
4471 if (qobject_cast<
const QAbstractItemView *>(w))
4472 proxy()->drawPrimitive(PE_PanelMenu, opt, p, w);
4476 case CE_MenuHMargin:
4477 case CE_MenuVMargin:
4478 case CE_MenuTearoff:
4479 case CE_MenuScroller:
4480 if (
const QStyleOptionMenuItem *mi = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
4481 const bool active = mi->state & State_Selected;
4483 p->fillRect(mi->rect, mi->palette.highlight());
4485 const QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, w);
4487 if (ce == CE_MenuTearoff) {
4488 p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine));
4489 p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1,
4490 mi->rect.x() + mi->rect.width() - 4,
4491 mi->rect.y() + mi->rect.height() / 2 - 1);
4492 p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine));
4493 p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2,
4494 mi->rect.x() + mi->rect.width() - 4,
4495 mi->rect.y() + mi->rect.height() / 2);
4496 }
else if (ce == CE_MenuScroller) {
4497 const QSize scrollerSize = QSize(10, 8);
4498 const int scrollerVOffset = 5;
4499 const int left = mi->rect.x() + (mi->rect.width() - scrollerSize.width()) / 2;
4500 const int right = left + scrollerSize.width();
4503 if (opt->state & State_DownArrow) {
4504 bottom = mi->rect.y() + scrollerVOffset;
4505 top = bottom + scrollerSize.height();
4507 bottom = mi->rect.bottom() - scrollerVOffset;
4508 top = bottom - scrollerSize.height();
4511 p->setRenderHint(QPainter::Antialiasing);
4513 path.moveTo(left, bottom);
4514 path.lineTo(right, bottom);
4515 path.lineTo((left + right) / 2, top);
4516 p->fillPath(path, opt->palette.buttonText());
4518 }
else if (ce != CE_MenuItem) {
4522 if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
4523 CGColorRef separatorColor = [NSColor quaternaryLabelColor].CGColor;
4524 const QRect separatorRect = QRect(mi->rect.left(), mi->rect.center().y(), mi->rect.width(), 2);
4525 p->fillRect(separatorRect, qt_mac_toQColor(separatorColor));
4529 const int maxpmw = mi->maxIconWidth;
4530 const bool enabled = mi->state & State_Enabled;
4532 int xpos = mi->rect.x() + 18;
4533 int checkcol = maxpmw;
4535 p->setPen(mi->palette.text().color());
4537 p->setPen(mi->palette.highlightedText().color());
4539 p->setPen(mi->palette.buttonText().color());
4542 QStyleOption checkmarkOpt;
4543 checkmarkOpt.initFrom(w);
4548 checkmarkOpt.rect = QRect(xp, mi->rect.y() - checkmarkOpt.fontMetrics.descent(), mw, mh);
4550 checkmarkOpt.state.setFlag(State_On, active);
4551 checkmarkOpt.state.setFlag(State_Enabled, enabled);
4552 if (widgetSize == QStyleHelper::SizeMini)
4553 checkmarkOpt.state |= State_Mini;
4554 else if (widgetSize == QStyleHelper::SizeSmall)
4555 checkmarkOpt.state |= State_Small;
4558 checkmarkOpt.palette.setColor(QPalette::HighlightedText, p->pen().color());
4559 checkmarkOpt.palette.setColor(QPalette::Text, p->pen().color());
4561 proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &checkmarkOpt, p, w);
4563 if (!mi->icon.isNull()) {
4564 QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal
4567 int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize);
4568 QSize iconSize(smallIconSize, smallIconSize);
4569#if QT_CONFIG(combobox)
4570 if (
const QComboBox *comboBox = qobject_cast<
const QComboBox *>(w)) {
4571 iconSize = comboBox->iconSize();
4574 QPixmap pixmap = mi->icon.pixmap(iconSize, p->device()->devicePixelRatio(), mode);
4575 QRect cr(xpos, mi->rect.y(), checkcol, mi->rect.height());
4576 QSize size = pixmap.deviceIndependentSize().toSize();
4577 QRect pmr(QPoint(0, 0), size);
4578 pmr.moveCenter(cr.center());
4579 p->drawPixmap(pmr.topLeft(), pixmap);
4580 xpos += size.width() + 6;
4583 QString s = mi->text;
4584 const auto text_flags = Qt::AlignVCenter | Qt::TextHideMnemonic
4585 | Qt::TextSingleLine | Qt::AlignAbsolute;
4586 int yPos = mi->rect.y();
4587 if (widgetSize == QStyleHelper::SizeMini)
4590 const bool isSubMenu = mi->menuItemType == QStyleOptionMenuItem::SubMenu;
4591 const int tabwidth = isSubMenu ? 9 : mi->reservedShortcutWidth;
4593 QString rightMarginText;
4595 rightMarginText = QStringLiteral(
"\u25b6\ufe0e");
4598 const int tabIndex = s.indexOf(QLatin1Char(
'\t'));
4599 if (tabIndex >= 0) {
4601 rightMarginText = s.mid(tabIndex + 1);
4602 s = s.left(tabIndex);
4606 if (!rightMarginText.isEmpty()) {
4607 p->setFont(qt_app_fonts_hash()->value(
"QMenuItem", p->font()));
4610 p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags | Qt::AlignRight, rightMarginText);
4614 const QKeySequence seq = QKeySequence::fromString(rightMarginText, QKeySequence::NativeText);
4615 if (seq.count() == 1) {
4617 const int maxKeyWidth = p->fontMetrics().maxWidth();
4618 const QChar key = rightMarginText.at(rightMarginText.length() - 1);
4619 const QString modifiers = rightMarginText.left(rightMarginText.size() - 1);
4620 p->drawText(xp + tabwidth - maxKeyWidth, yPos, maxKeyWidth, mi->rect.height(), text_flags, key);
4622 p->drawText(xp, yPos, tabwidth - maxKeyWidth, mi->rect.height(),
4623 text_flags | Qt::AlignRight | Qt::TextDontClip, modifiers);
4625 p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags, rightMarginText);
4632 QFont myFont = mi->font;
4638 myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF());
4643 const auto *fontEngine = QFontPrivate::get(myFont)->engineForScript(QChar::Script_Common);
4644 Q_ASSERT(fontEngine);
4645 if (fontEngine->type() == QFontEngine::Multi) {
4646 fontEngine =
static_cast<
const QFontEngineMulti *>(fontEngine)->engine(0);
4647 Q_ASSERT(fontEngine);
4649 if (fontEngine->type() == QFontEngine::Mac) {
4650 NSFont *f = (NSFont *)(CTFontRef)fontEngine->handle();
4653 const auto pc = p->pen().color();
4654 NSColor *c = [NSColor colorWithSRGBRed:pc.redF()
4659 s = qt_mac_removeMnemonics(s);
4661 QMacCGContext cgCtx(p);
4662 d->setupNSGraphicsContext(cgCtx, YES);
4668 [s.toNSString() drawAtPoint:CGPointMake(xpos, yPos)
4669 withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c,
4670 NSObliquenessAttributeName: [NSNumber numberWithDouble: myFont.italic() ? 0.3 : 0.0],
4671 NSUnderlineStyleAttributeName: [NSNumber numberWithInt: myFont.underline() ? NSUnderlineStyleSingle
4672 : NSUnderlineStyleNone],
4673 NSStrikethroughStyleAttributeName: [NSNumber numberWithInt: myFont.strikeOut() ? NSUnderlineStyleSingle
4674 : NSUnderlineStyleNone]}];
4676 d->restoreNSGraphicsContext(cgCtx);
4679 p->drawText(xpos, yPos, mi->rect.width() - xm - tabwidth + 1,
4680 mi->rect.height(), text_flags, s);
4686 case CE_MenuBarItem:
4687 case CE_MenuBarEmptyArea:
4688 if (
const QStyleOptionMenuItem *mi = qstyleoption_cast<
const QStyleOptionMenuItem *>(opt)) {
4689 const bool selected = (opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken);
4690 const QBrush bg = selected ? mi->palette.highlight() : mi->palette.window();
4691 p->fillRect(mi->rect, bg);
4693 if (ce != CE_MenuBarItem)
4696 if (!mi->icon.isNull()) {
4697 int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
4698 drawItemPixmap(p, mi->rect,
4699 Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip
4700 | Qt::TextSingleLine,
4701 mi->icon.pixmap(QSize(iconExtent, iconExtent), p->device()->devicePixelRatio(),
4702 (mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled));
4704 drawItemText(p, mi->rect,
4705 Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip
4706 | Qt::TextSingleLine,
4707 mi->palette, mi->state & State_Enabled,
4708 mi->text, selected ? QPalette::HighlightedText : QPalette::ButtonText);
4712 case CE_ProgressBarLabel:
4713 case CE_ProgressBarGroove:
4716 case CE_ProgressBarContents:
4717 if (
const QStyleOptionProgressBar *pb = qstyleoption_cast<
const QStyleOptionProgressBar *>(opt)) {
4718 const bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0);
4719 const bool vertical = !(pb->state & QStyle::State_Horizontal);
4720 const bool inverted = pb->invertedAppearance;
4721 bool reverse = (!vertical && (pb->direction == Qt::RightToLeft));
4724 QRect rect = pb->rect;
4726 const auto aquaSize = d->effectiveAquaSizeConstrain(opt, w);
4727 const QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject));
4728 if (isIndeterminate) {
4736 if (!animation && opt->styleObject) {
4737 auto *animation =
new QProgressStyleAnimation(d->animateSpeed(QMacStylePrivate::AquaProgressBar), opt->styleObject);
4739 animation->setFrameRate(QStyleAnimation::FifteenFps);
4740 d->startAnimation(animation);
4743 if (qt_apple_runningWithLiquidGlass()) {
4744 d->drawProgressBar(p, pb);
4747 rect = rect.transposed();
4748 d->setupNSGraphicsContext(cg, NO);
4749 d->setupVerticalInvertedXform(cg, reverse, vertical, rect.toCGRect());
4751 =
static_cast<QIndeterminateProgressIndicator *>(
4752 d->cocoaControl({ QMacStylePrivate::ProgressIndicator_Indeterminate, aquaSize }))) {
4753 [ipi startAnimation];
4754 [ipi drawWithFrame:rect.toCGRect() inView:d->backingStoreNSView];
4756 d->restoreNSGraphicsContext(cg);
4760 d->stopAnimation(opt->styleObject);
4762 =
static_cast<QIndeterminateProgressIndicator *>(
4763 d->cocoaControl({ QMacStylePrivate::ProgressIndicator_Indeterminate, aquaSize })))
4764 [ipi stopAnimation];
4766 if (qt_apple_runningWithLiquidGlass()) {
4767 d->drawProgressBar(p, pb);
4770 rect = rect.transposed();
4771 const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::ProgressIndicator_Determinate, aquaSize);
4772 auto *pi =
static_cast<NSProgressIndicator *>(d->cocoaControl(cw));
4773 d->drawNSViewInRect(pi, rect, p, ^(CGContextRef ctx,
const CGRect &cgrect) {
4774 d->setupVerticalInvertedXform(ctx, reverse, vertical, cgrect);
4775 pi.minValue = pb->minimum;
4776 pi.maxValue = pb->maximum;
4777 pi.doubleValue = pb->progress;
4778 [pi drawRect:cgrect]; });
4785#ifndef QT_NO_MDIAREA
4786 if (!w || !qobject_cast<QMdiSubWindow *>(w->parentWidget()))
4790 if (w->testAttribute(Qt::WA_MacOpaqueSizeGrip))
4791 p->fillRect(opt->rect, opt->palette.window());
4793 QPen lineColor = QColor(82, 82, 82, 192);
4794 lineColor.setWidth(1);
4796 p->setRenderHint(QPainter::Antialiasing);
4797 p->setPen(lineColor);
4798 const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection();
4799 const int NumLines = 3;
4800 for (
int l = 0; l < NumLines; ++l) {
4801 const int offset = (l * 4 + 3);
4803 if (layoutDirection == Qt::LeftToRight) {
4804 start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1);
4805 end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset);
4807 start = QPoint(offset, opt->rect.height() - 1);
4808 end = QPoint(1, opt->rect.height() - offset);
4810 p->drawLine(start, end);
4816 if (opt->rect.width() > 1 && opt->rect.height() > 1) {
4817 const bool isVertical = !(opt->state & QStyle::State_Horizontal);
4819 const auto ct = isVertical ? QMacStylePrivate::SplitView_Horizontal : QMacStylePrivate::SplitView_Vertical;
4820 const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge);
4821 auto *sv =
static_cast<NSSplitView *>(d->cocoaControl(cw));
4822 sv.frame = opt->rect.toCGRect();
4823 d->drawNSViewInRect(sv, opt->rect, p, ^(CGContextRef,
const CGRect &rect) {
4824 [sv drawDividerInRect:rect];
4827 QPen oldPen = p->pen();
4828 p->setPen(opt->palette.dark().color());
4829 if (opt->state & QStyle::State_Horizontal)
4830 p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft());
4832 p->drawLine(opt->rect.topLeft(), opt->rect.topRight());
4837 if (
const QStyleOptionRubberBand *rubber = qstyleoption_cast<
const QStyleOptionRubberBand *>(opt)) {
4838 QColor fillColor(opt->palette.color(QPalette::Disabled, QPalette::Highlight));
4839 if (!rubber->opaque) {
4842 strokeColor.setHsvF(0, 0, 0.86, 1.0);
4843 fillColor.setHsvF(0, 0, 0.53, 0.25);
4844 if (opt->rect.width() * opt->rect.height() <= 3) {
4845 p->fillRect(opt->rect, strokeColor);
4847 QPen oldPen = p->pen();
4848 QBrush oldBrush = p->brush();
4849 QPen pen(strokeColor);
4851 p->setBrush(fillColor);
4852 QRect adjusted = opt->rect.adjusted(1, 1, -1, -1);
4853 if (adjusted.isValid())
4854 p->drawRect(adjusted);
4856 p->setBrush(oldBrush);
4859 p->fillRect(opt->rect, fillColor);
4863#ifndef QT_NO_TOOLBAR
4865 const QStyleOptionToolBar *toolBar = qstyleoption_cast<
const QStyleOptionToolBar *>(opt);
4873#if QT_CONFIG(mainwindow)
4874 if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) {
4875 if (toolBar && toolBar->toolBarArea == Qt::TopToolBarArea && mainWindow->unifiedTitleAndToolBarOnMac()) {
4878 p->setCompositionMode(QPainter::CompositionMode_Source);
4879 p->fillRect(opt->rect, Qt::transparent);
4886 const QPoint windowToolbarEnd = w->mapTo(w->window(), opt->rect.bottomLeft());
4887 const bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1);
4888 if (isEndOfUnifiedArea) {
4889 const int margin = qt_mac_aqua_get_metric(SeparatorSize);
4890 const auto separatorRect = QRect(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin);
4891 p->fillRect(separatorRect, darkMode ? darkModeSeparatorLine : opt->palette.dark().color());
4900 QLinearGradient linearGrad;
4901 if (opt->state & State_Horizontal)
4902 linearGrad = QLinearGradient(0, opt->rect.top(), 0, opt->rect.bottom());
4904 linearGrad = QLinearGradient(opt->rect.left(), 0, opt->rect.right(), 0);
4906 QColor mainWindowGradientBegin = darkMode ? darkMainWindowGradientBegin : lightMainWindowGradientBegin;
4907 QColor mainWindowGradientEnd = darkMode ? darkMainWindowGradientEnd : lightMainWindowGradientEnd;
4909 linearGrad.setColorAt(0, mainWindowGradientBegin);
4910 linearGrad.setColorAt(1, mainWindowGradientEnd);
4911 p->fillRect(opt->rect, linearGrad);
4914 QRect toolbarRect = darkMode ? opt->rect.adjusted(0, 0, 0, 1) : opt->rect;
4915 if (opt->state & State_Horizontal) {
4916 p->setPen(darkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
4917 p->drawLine(toolbarRect.topLeft(), toolbarRect.topRight());
4918 p->setPen(darkMode ? darkModeSeparatorLine :mainWindowGradientEnd.darker(114));
4919 p->drawLine(toolbarRect.bottomLeft(), toolbarRect.bottomRight());
4921 p->setPen(darkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114));
4922 p->drawLine(toolbarRect.topLeft(), toolbarRect.bottomLeft());
4923 p->setPen(darkMode ? darkModeSeparatorLine : mainWindowGradientEnd.darker(114));
4924 p->drawLine(toolbarRect.topRight(), toolbarRect.bottomRight());
4932 QCommonStyle::drawControl(ce, opt, p, w);
4947 const QWidget *widget)
const
4949 Q_D(
const QMacStyle);
4951 const int controlSize = getControlSize(opt, widget);
4954#if QT_CONFIG(itemviews)
4955 case SE_ItemViewItemText:
4956 if (
const QStyleOptionViewItem *vopt = qstyleoption_cast<
const QStyleOptionViewItem *>(opt)) {
4957 int fw = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, widget);
4959 rect = QCommonStyle::subElementRect(sr, opt, widget);
4960 if (vopt->features & QStyleOptionViewItem::HasDecoration)
4961 rect.adjust(-fw, 0, 0, 0);
4965 case SE_ToolBoxTabContents:
4966 rect = QCommonStyle::subElementRect(sr, opt, widget);
4968 case SE_PushButtonBevel:
4969 case SE_PushButtonContents:
4970 if (
const QStyleOptionButton *btn = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
4979 const auto ct = cocoaControlType(btn, widget);
4980 const auto cs = d->effectiveAquaSizeConstrain(btn, widget);
4981 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
4982 auto frameRect = cw.adjustedControlFrame(btn->rect);
4983 if (sr == SE_PushButtonContents) {
4984 frameRect -= cw.titleMargins();
4985 }
else if (cw.type != QMacStylePrivate::Button_SquareButton) {
4986 auto *pb =
static_cast<NSButton *>(d->cocoaControl(cw));
4987 frameRect = QRectF::fromCGRect([pb alignmentRectForFrame:frameRect.toCGRect()]);
4988 if (cw.type == QMacStylePrivate::Button_PushButton)
4989 frameRect -= pushButtonShadowMargins[cw.size];
4990 else if (cw.type == QMacStylePrivate::Button_PullDown)
4991 frameRect -= pullDownButtonShadowMargins[cw.size];
4993 rect = frameRect.toRect();
4996 case SE_HeaderLabel: {
4997 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
4998 rect.setRect(opt->rect.x() + margin, opt->rect.y(),
4999 opt->rect.width() - margin * 2, opt->rect.height() - 2);
5000 if (
const QStyleOptionHeader *header = qstyleoption_cast<
const QStyleOptionHeader *>(opt)) {
5002 if (header->sortIndicator != QStyleOptionHeader::None) {
5003 if (opt->state & State_Horizontal)
5009 rect = visualRect(opt->direction, opt->rect, rect);
5012 case SE_HeaderArrow: {
5013 int h = opt->rect.height();
5014 int w = opt->rect.width();
5015 int x = opt->rect.x();
5016 int y = opt->rect.y();
5017 int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
5019 if (opt->state & State_Horizontal) {
5026 rect = visualRect(opt->direction, opt->rect, rect);
5029 case SE_ProgressBarGroove:
5033 case SE_ProgressBarLabel:
5035 case SE_ProgressBarContents:
5038 case SE_TreeViewDisclosureItem: {
5044#if QT_CONFIG(tabwidget)
5045 case SE_TabWidgetLeftCorner:
5046 if (
const QStyleOptionTabWidgetFrame *twf
5047 = qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
5048 switch (twf->shape) {
5049 case QTabBar::RoundedNorth:
5050 case QTabBar::TriangularNorth:
5051 rect = QRect(QPoint(0, 0), twf->leftCornerWidgetSize);
5053 case QTabBar::RoundedSouth:
5054 case QTabBar::TriangularSouth:
5055 rect = QRect(QPoint(0, twf->rect.height() - twf->leftCornerWidgetSize.height()),
5056 twf->leftCornerWidgetSize);
5061 rect = visualRect(twf->direction, twf->rect, rect);
5064 case SE_TabWidgetRightCorner:
5065 if (
const QStyleOptionTabWidgetFrame *twf
5066 = qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
5067 switch (twf->shape) {
5068 case QTabBar::RoundedNorth:
5069 case QTabBar::TriangularNorth:
5070 rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 0),
5071 twf->rightCornerWidgetSize);
5073 case QTabBar::RoundedSouth:
5074 case QTabBar::TriangularSouth:
5075 rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(),
5076 twf->rect.height() - twf->rightCornerWidgetSize.height()),
5077 twf->rightCornerWidgetSize);
5082 rect = visualRect(twf->direction, twf->rect, rect);
5085 case SE_TabWidgetTabContents:
5086 rect = QCommonStyle::subElementRect(sr, opt, widget);
5087 if (
const auto *twf = qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
5088 if (twf->lineWidth != 0) {
5089 switch (QMacStylePrivate::tabDirection(twf->shape)) {
5090 case QMacStylePrivate::North:
5091 rect.adjust(+1, +14, -1, -1);
5093 case QMacStylePrivate::South:
5094 rect.adjust(+1, +1, -1, -14);
5096 case QMacStylePrivate::West:
5097 rect.adjust(+14, +1, -1, -1);
5099 case QMacStylePrivate::East:
5100 rect.adjust(+1, +1, -14, -1);
5105 case SE_TabBarTabText:
5106 if (
const QStyleOptionTab *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
5107 QRect dummyIconRect;
5108 d->tabLayout(tab, widget, &rect, &dummyIconRect);
5111 case SE_TabBarTabLeftButton:
5112 case SE_TabBarTabRightButton:
5113 if (
const QStyleOptionTab *tab = qstyleoption_cast<
const QStyleOptionTab *>(opt)) {
5114 bool selected = tab->state & State_Selected;
5115 int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
5116 int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
5119 bool verticalTabs = tab->shape == QTabBar::RoundedEast
5120 || tab->shape == QTabBar::RoundedWest
5121 || tab->shape == QTabBar::TriangularEast
5122 || tab->shape == QTabBar::TriangularWest;
5124 QRect tr = tab->rect;
5125 if (tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::TriangularSouth)
5126 verticalShift = -verticalShift;
5128 qSwap(horizontalShift, verticalShift);
5129 horizontalShift *= -1;
5130 verticalShift *= -1;
5132 if (tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularWest)
5133 horizontalShift = -horizontalShift;
5135 tr.adjust(0, 0, horizontalShift, verticalShift);
5138 tr.setBottom(tr.bottom() - verticalShift);
5139 tr.setRight(tr.right() - horizontalShift);
5142 QSize size = (sr == SE_TabBarTabLeftButton) ? tab->leftButtonSize : tab->rightButtonSize;
5143 int w = size.width();
5144 int h = size.height();
5145 int midHeight =
static_cast<
int>(qCeil(
float(tr.height() - h) / 2));
5146 int midWidth = ((tr.width() - w) / 2);
5148 bool atTheTop =
true;
5149 switch (tab->shape) {
5150 case QTabBar::RoundedWest:
5151 case QTabBar::TriangularWest:
5152 atTheTop = (sr == SE_TabBarTabLeftButton);
5154 case QTabBar::RoundedEast:
5155 case QTabBar::TriangularEast:
5156 atTheTop = (sr == SE_TabBarTabRightButton);
5159 if (sr == SE_TabBarTabLeftButton)
5160 rect = QRect(tab->rect.x() + hpadding, midHeight, w, h);
5162 rect = QRect(tab->rect.right() - w - hpadding, midHeight, w, h);
5163 rect = visualRect(tab->direction, tab->rect, rect);
5167 rect = QRect(midWidth, tr.y() + tab->rect.height() - hpadding - h, w, h);
5169 rect = QRect(midWidth, tr.y() + hpadding, w, h);
5174 case SE_LineEditContents:
5175 rect = QCommonStyle::subElementRect(sr, opt, widget);
5176#if QT_CONFIG(combobox)
5177 if (widget && qobject_cast<
const QComboBox*>(widget->parentWidget()))
5178 rect.adjust(-1, -2, 0, 0);
5181 rect.adjust(-1, -1, 0, +1);
5183 case SE_CheckBoxLayoutItem:
5185 if (controlSize == QStyleHelper::SizeLarge) {
5186 setLayoutItemMargins(+2, +3, -9, -4, &rect, opt->direction);
5187 }
else if (controlSize == QStyleHelper::SizeSmall) {
5188 setLayoutItemMargins(+1, +5, 0 , -6, &rect, opt->direction);
5190 setLayoutItemMargins(0, +7, 0 , -6, &rect, opt->direction);
5193 case SE_ComboBoxLayoutItem:
5194#ifndef QT_NO_TOOLBAR
5195 if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) {
5204 if (controlSize == QStyleHelper::SizeLarge) {
5205 rect.adjust(+3, +2, -3, -4);
5206 }
else if (controlSize == QStyleHelper::SizeSmall) {
5207 setLayoutItemMargins(+2, +1, -3, -4, &rect, opt->direction);
5209 setLayoutItemMargins(+1, 0, -2, 0, &rect, opt->direction);
5213 case SE_LabelLayoutItem:
5215 setLayoutItemMargins(+1, 0 , 0, 0 , &rect, opt->direction);
5217 case SE_ProgressBarLayoutItem: {
5219 int bottom =
SIZE(3, 8, 8);
5220 if (opt->state & State_Horizontal) {
5221 rect.adjust(0, +1, 0, -bottom);
5223 setLayoutItemMargins(+1, 0, -bottom, 0, &rect, opt->direction);
5227 case SE_PushButtonLayoutItem:
5228 if (
const QStyleOptionButton *buttonOpt
5229 = qstyleoption_cast<
const QStyleOptionButton *>(opt)) {
5230 if ((buttonOpt->features & QStyleOptionButton::Flat))
5232 if ((buttonOpt->features & QStyleOptionButton::CommandLinkButton)) {
5234 if (controlSize == QStyleHelper::SizeLarge)
5235 rect.adjust(+6, +4, -6, -8);
5236 else if (controlSize == QStyleHelper::SizeSmall)
5237 rect.adjust(+5, +4, -5, -6);
5239 rect.adjust(+1, 0, -1, -2);
5244 if (controlSize == QStyleHelper::SizeLarge) {
5245 rect.adjust(0, +4, 0, -8);
5246 }
else if (controlSize == QStyleHelper::SizeSmall) {
5247 rect.adjust(0, +4, 0, -6);
5249 rect.adjust(0, 0, 0, -2);
5252 case SE_RadioButtonLayoutItem:
5254 if (controlSize == QStyleHelper::SizeLarge) {
5255 setLayoutItemMargins(+2, +2 ,
5256 0, -4 , &rect, opt->direction);
5257 }
else if (controlSize == QStyleHelper::SizeSmall) {
5258 rect.adjust(0, +6, 0 , -5);
5260 rect.adjust(0, +6, 0 , -7);
5263 case SE_SliderLayoutItem:
5264 if (
const QStyleOptionSlider *sliderOpt
5265 = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
5267 if (sliderOpt->tickPosition == QSlider::NoTicks) {
5268 int above =
SIZE(3, 0, 2);
5269 int below =
SIZE(4, 3, 0);
5270 if (sliderOpt->orientation == Qt::Horizontal) {
5271 rect.adjust(0, +above, 0, -below);
5273 rect.adjust(+above, 0, -below, 0);
5275 }
else if (sliderOpt->tickPosition == QSlider::TicksAbove) {
5276 int below =
SIZE(3, 2, 0);
5277 if (sliderOpt->orientation == Qt::Horizontal) {
5278 rect.setHeight(rect.height() - below);
5280 rect.setWidth(rect.width() - below);
5282 }
else if (sliderOpt->tickPosition == QSlider::TicksBelow) {
5283 int above =
SIZE(3, 2, 0);
5284 if (sliderOpt->orientation == Qt::Horizontal) {
5285 rect.setTop(rect.top() + above);
5287 rect.setLeft(rect.left() + above);
5292 case SE_FrameLayoutItem:
5294 if (
const QFrame *frame = qobject_cast<
const QFrame *>(widget)) {
5296 switch (frame->frameStyle() & QFrame::Shape_Mask) {
5298 rect.adjust(0, +1, 0, -1);
5301 rect.adjust(+1, 0, -1, 0);
5308 case SE_GroupBoxLayoutItem:
5310 if (
const QStyleOptionGroupBox *groupBoxOpt =
5311 qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
5313
5314
5315
5316
5317 if (groupBoxOpt->subControls & (QStyle::SC_GroupBoxCheckBox
5318 | QStyle::SC_GroupBoxLabel)) {
5320 if (groupBoxOpt->subControls & QStyle::SC_GroupBoxCheckBox) {
5321 delta =
SIZE(8, 4, 4);
5323 delta =
SIZE(15, 12, 12);
5325 rect.setTop(rect.top() + delta);
5328 rect.setBottom(rect.bottom() - 1);
5330#if QT_CONFIG(tabwidget)
5331 case SE_TabWidgetLayoutItem:
5332 if (
const QStyleOptionTabWidgetFrame *tabWidgetOpt =
5333 qstyleoption_cast<
const QStyleOptionTabWidgetFrame *>(opt)) {
5335
5336
5337
5338
5339 rect = tabWidgetOpt->rect;
5340 if (tabWidgetOpt->shape == QTabBar::RoundedNorth)
5341 rect.setTop(rect.top() + SIZE(6 , 3 , 2 ));
5345#if QT_CONFIG(dockwidget)
5346 case SE_DockWidgetCloseButton:
5347 case SE_DockWidgetFloatButton:
5348 case SE_DockWidgetTitleBarText:
5349 case SE_DockWidgetIcon: {
5350 int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
5351 int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget);
5352 QRect srect = opt->rect;
5354 const QStyleOptionDockWidget *dwOpt
5355 = qstyleoption_cast<
const QStyleOptionDockWidget*>(opt);
5356 bool canClose = dwOpt == 0 ?
true : dwOpt->closable;
5357 bool canFloat = dwOpt == 0 ?
false : dwOpt->floatable;
5359 const bool verticalTitleBar = dwOpt->verticalTitleBar;
5363 if (verticalTitleBar)
5364 srect = srect.transposed();
5367 int right = srect.right();
5368 int left = srect.left();
5372 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton,
5373 opt, widget).actualSize(QSize(iconSize, iconSize));
5374 sz += QSize(buttonMargin, buttonMargin);
5375 if (verticalTitleBar)
5376 sz = sz.transposed();
5377 closeRect = QRect(left,
5378 srect.center().y() - sz.height()/2,
5379 sz.width(), sz.height());
5380 left = closeRect.right() + 1;
5382 if (sr == SE_DockWidgetCloseButton) {
5389 QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarNormalButton,
5390 opt, widget).actualSize(QSize(iconSize, iconSize));
5391 sz += QSize(buttonMargin, buttonMargin);
5392 if (verticalTitleBar)
5393 sz = sz.transposed();
5394 floatRect = QRect(left,
5395 srect.center().y() - sz.height()/2,
5396 sz.width(), sz.height());
5397 left = floatRect.right() + 1;
5399 if (sr == SE_DockWidgetFloatButton) {
5405 if (
const QDockWidget *dw = qobject_cast<
const QDockWidget*>(widget)) {
5407 if (dw->isFloating())
5408 icon = dw->windowIcon();
5410 && icon.cacheKey() != QApplication::windowIcon().cacheKey()) {
5411 QSize sz = icon.actualSize(QSize(rect.height(), rect.height()));
5412 if (verticalTitleBar)
5413 sz = sz.transposed();
5414 iconRect = QRect(right - sz.width(), srect.center().y() - sz.height()/2,
5415 sz.width(), sz.height());
5416 right = iconRect.left() - 1;
5419 if (sr == SE_DockWidgetIcon) {
5424 QRect textRect = QRect(left, srect.top(),
5425 right - left, srect.height());
5426 if (sr == SE_DockWidgetTitleBarText) {
5432 if (verticalTitleBar) {
5433 rect = QRect(srect.left() + rect.top() - srect.top(),
5434 srect.top() + srect.right() - rect.right(),
5435 rect.height(), rect.width());
5437 rect = visualRect(opt->direction, srect, rect);
5443 rect = QCommonStyle::subElementRect(sr, opt, widget);
5476 const QWidget *widget)
const
5478 Q_D(
const QMacStyle);
5479 QMacCGContext cg(p);
5481 qCWarning(lcMacStyle) <<
"drawComplexControl:" << cc <<
"invalid (nullptr) graphics context";
5482 QWindow *window = widget && widget->window() ? widget->window()->windowHandle() :
nullptr;
5483 d->resolveCurrentNSView(window);
5486 if (
const QStyleOptionSlider *sb = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
5489 const bool drawTrack = sb->subControls & SC_ScrollBarGroove;
5490 const bool drawKnob = sb->subControls & SC_ScrollBarSlider && sb->minimum != sb->maximum;
5491 if (!drawTrack && !drawKnob)
5494 const bool isHorizontal = sb->orientation == Qt::Horizontal;
5496 if (opt && opt->styleObject && !QMacStylePrivate::scrollBars.contains(opt->styleObject))
5497 QMacStylePrivate::scrollBars.append(QPointer<QObject>(opt->styleObject));
5499 static const CGFloat knobWidths[] = { 7.0, 5.0, 5.0 };
5500 static const CGFloat expandedKnobWidths[] = { 11.0, 9.0, 9.0 };
5501 const auto cocoaSize = d->effectiveAquaSizeConstrain(opt, widget);
5502 const CGFloat maxExpandScale = expandedKnobWidths[cocoaSize] / knobWidths[cocoaSize];
5504 const QStyle *realStyle = widget ? widget->style() : proxy();
5505 const bool isTransient = realStyle->styleHint(SH_ScrollBar_Transient, opt, widget);
5507 d->stopAnimation(opt->styleObject);
5508 bool wasActive =
false;
5509 CGFloat opacity = 0.0;
5510 CGFloat expandScale = 1.0;
5511 CGFloat expandOffset = 0.0;
5512 bool shouldExpand =
false;
5514 if (QObject *styleObject = opt->styleObject) {
5515 const int oldPos = styleObject->property(
"_q_stylepos").toInt();
5516 const int oldMin = styleObject->property(
"_q_stylemin").toInt();
5517 const int oldMax = styleObject->property(
"_q_stylemax").toInt();
5518 const QRect oldRect = styleObject->property(
"_q_stylerect").toRect();
5519 const QStyle::State oldState =
static_cast<QStyle::State>(styleObject->property(
"_q_stylestate").value<QStyle::State::Int>());
5520 const uint oldActiveControls = styleObject->property(
"_q_stylecontrols").toUInt();
5524 const bool transient = isTransient && !opt->activeSubControls && !(sb->state & State_On);
5527 oldPos != sb->sliderPosition ||
5528 oldMin != sb->minimum ||
5529 oldMax != sb->maximum ||
5530 oldRect != sb->rect ||
5531 oldState != sb->state ||
5532 oldActiveControls != sb->activeSubControls) {
5538 styleObject->setProperty(
"_q_stylepos", sb->sliderPosition);
5539 styleObject->setProperty(
"_q_stylemin", sb->minimum);
5540 styleObject->setProperty(
"_q_stylemax", sb->maximum);
5541 styleObject->setProperty(
"_q_stylerect", sb->rect);
5542 styleObject->setProperty(
"_q_stylestate",
static_cast<QStyle::State::Int>(sb->state));
5543 styleObject->setProperty(
"_q_stylecontrols",
static_cast<uint>(sb->activeSubControls));
5545 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject));
5548 anim =
new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject);
5549 d->startAnimation(anim);
5550 }
else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) {
5553 anim->setCurrentTime(0);
5555 }
else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
5556 d->stopAnimation(styleObject);
5560 QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject));
5561 if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
5564 if (oldActiveControls)
5565 anim->setActive(
true);
5567 wasActive = anim->wasActive();
5568 opacity = anim->currentValue();
5571 shouldExpand = isTransient && (opt->activeSubControls || wasActive);
5573 if (!anim && !oldActiveControls) {
5575 anim =
new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject);
5576 d->startAnimation(anim);
5578 if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) {
5579 expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue();
5580 expandOffset = 5.5 * (1.0 - anim->currentValue());
5583 expandScale = maxExpandScale;
5589 d->setupNSGraphicsContext(cg, NO );
5591 const auto controlType = isHorizontal ? QMacStylePrivate::Scroller_Horizontal : QMacStylePrivate::Scroller_Vertical;
5592 const auto cw = QMacStylePrivate::CocoaControl(controlType, cocoaSize);
5593 NSScroller *scroller =
static_cast<NSScroller *>(d->cocoaControl(cw));
5595 const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget);
5596 const bool hasDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128;
5600 scroller.knobStyle = hasDarkBg? NSScrollerKnobStyleLight : NSScrollerKnobStyleDark;
5602 scroller.knobStyle = NSScrollerKnobStyleDefault;
5605 scroller.scrollerStyle = isTransient ? NSScrollerStyleOverlay : NSScrollerStyleLegacy;
5607 if (!setupScroller(scroller, sb))
5611 CGContextBeginTransparencyLayerWithRect(cg, scroller.frame,
nullptr);
5612 CGContextSetAlpha(cg, opacity);
5617 if (!isTransient || opt->activeSubControls || wasActive) {
5618 CGRect trackRect = scroller.bounds;
5620 trackRect.origin.y += expandOffset;
5622 trackRect.origin.x += expandOffset;
5623 [scroller drawKnobSlotInRect:trackRect highlight:NO];
5633 const CGFloat scrollerWidth = [NSScroller scrollerWidthForControlSize:scroller.controlSize scrollerStyle:scroller.scrollerStyle];
5634 const CGFloat knobWidth = knobWidths[cocoaSize] * expandScale;
5636 const CGRect scrollerKnobRect = CGRectInset([scroller rectForPart:NSScrollerKnob], 1, 1);
5637 const CGFloat knobLength = isHorizontal ? scrollerKnobRect.size.width : scrollerKnobRect.size.height;
5638 const CGFloat knobPos = isHorizontal ? scrollerKnobRect.origin.x : scrollerKnobRect.origin.y;
5639 const CGFloat knobOffset = qRound((scrollerWidth + expandOffset - knobWidth) / 2.0);
5640 const CGFloat knobRadius = knobWidth / 2.0;
5643 knobRect = CGRectMake(knobPos, knobOffset, knobLength, knobWidth);
5645 knobRect = CGRectMake(knobOffset, knobPos, knobWidth, knobLength);
5646 QCFType<CGPathRef> knobPath = CGPathCreateWithRoundedRect(knobRect, knobRadius, knobRadius,
nullptr);
5647 CGContextAddPath(cg, knobPath);
5648 CGContextSetAlpha(cg, 0.5);
5649 CGColorRef knobColor = hasDarkBg ? NSColor.whiteColor.CGColor : NSColor.blackColor.CGColor;
5650 CGContextSetFillColorWithColor(cg, knobColor);
5651 CGContextFillPath(cg);
5653 [scroller drawKnob];
5655 if (!isTransient && opt->activeSubControls) {
5660 CGContextSetBlendMode(cg, kCGBlendModePlusDarker);
5661 [scroller drawKnob];
5667 CGContextEndTransparencyLayer(cg);
5669 d->restoreNSGraphicsContext(cg);
5673 if (
const QStyleOptionSlider *sl = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
5674 const bool isHorizontal = sl->orientation == Qt::Horizontal;
5675 const auto ct = isHorizontal ? QMacStylePrivate::Slider_Horizontal : QMacStylePrivate::Slider_Vertical;
5676 const auto cs = d->effectiveAquaSizeConstrain(opt, widget);
5677 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
5678 auto *slider =
static_cast<NSSlider *>(d->cocoaControl(cw));
5679 if (!setupSlider(slider, sl))
5682 const bool hasTicks = sl->tickPosition != QSlider::NoTicks;
5683 const bool hasDoubleTicks = sl->tickPosition == QSlider::TicksBothSides;
5684 const bool drawKnob = sl->subControls & SC_SliderHandle;
5685 const bool drawBar = sl->subControls & SC_SliderGroove;
5686 const bool drawTicks = sl->subControls & SC_SliderTickmarks;
5687 const bool isPressed = qt_apple_runningWithLiquidGlass() ?
false : sl->state & State_Sunken;
5691 const CGRect knobRect = [slider.cell knobRectFlipped:slider.isFlipped];
5692 pressPoint.x = CGRectGetMidX(knobRect);
5693 pressPoint.y = CGRectGetMidY(knobRect);
5708 [slider.cell startTrackingAt:pressPoint inView:slider];
5709 [slider.cell startTrackingAt:pressPoint inView:slider];
5712 d->drawNSViewInRect(slider, opt->rect, p, ^(CGContextRef ctx,
const CGRect &rect) {
5715 const bool verticalFlip = !isHorizontal && !sl->upsideDown;
5718 if (sl->upsideDown) {
5719 CGContextTranslateCTM(ctx, rect.size.width, rect.origin.y);
5720 CGContextScaleCTM(ctx, -1, 1);
5722 CGContextTranslateCTM(ctx, 0, rect.origin.y);
5724 }
else if (verticalFlip) {
5725 CGContextTranslateCTM(ctx, rect.origin.x, rect.size.height);
5726 CGContextScaleCTM(ctx, 1, -1);
5729 if (hasDoubleTicks) {
5732 CGContextTranslateCTM(ctx, 0, 4);
5734 CGContextTranslateCTM(ctx, 1, 0);
5741 const bool drawAllParts = drawKnob && drawBar && (!hasTicks || drawTicks);
5742 if (drawAllParts && !hasDoubleTicks && (!verticalFlip || drawTicks)) {
5746 if (verticalFlip && drawTicks) {
5749 slider.intValue = slider.maxValue - slider.intValue + slider.minValue;
5751 [slider drawRect:CGRectZero];
5755 NSSliderCell *cell = slider.cell;
5757 const int numberOfTickMarks = slider.numberOfTickMarks;
5760 slider.numberOfTickMarks = 0;
5762 const CGRect barRect = [cell barRectFlipped:slider.isFlipped];
5764 if (!isHorizontal && !sl->upsideDown && (hasDoubleTicks || !hasTicks)) {
5772 [cell drawBarInside:barRect flipped:
true];
5774 [cell drawBarInside:barRect flipped:!verticalFlip];
5778 slider.numberOfTickMarks = numberOfTickMarks;
5781 if (hasTicks && drawTicks) {
5782 if (!drawBar && hasDoubleTicks)
5783 slider.numberOfTickMarks = numberOfTickMarks;
5785 if (qt_apple_runningWithLiquidGlass())
5786 drawTickMarks(ctx, slider, sl);
5788 [cell drawTickMarks];
5790 if (hasDoubleTicks) {
5792 CGAffineTransform tickMarksFlip;
5793 const CGRect tickMarkRect = [cell rectOfTickMarkAtIndex:0];
5795 tickMarksFlip = CGAffineTransformMakeTranslation(0, rect.size.height - tickMarkRect.size.height - 3);
5796 tickMarksFlip = CGAffineTransformScale(tickMarksFlip, 1, -1);
5798 tickMarksFlip = CGAffineTransformMakeTranslation(rect.size.width - tickMarkRect.size.width / 2, 0);
5799 tickMarksFlip = CGAffineTransformScale(tickMarksFlip, -1, 1);
5801 CGContextConcatCTM(ctx, tickMarksFlip);
5802 [cell drawTickMarks];
5803 CGContextConcatCTM(ctx, CGAffineTransformInvert(tickMarksFlip));
5810 slider.numberOfTickMarks = 0;
5811 if (qt_apple_runningWithLiquidGlass())
5812 drawSliderKnob(ctx, slider);
5822 [slider.cell stopTracking:pressPoint at:pressPoint inView:slider mouseIsUp:NO];
5823 [slider.cell stopTracking:pressPoint at:pressPoint inView:slider mouseIsUp:NO];
5827#if QT_CONFIG(spinbox)
5829 if (
const QStyleOptionSpinBox *sb = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
5830 if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) {
5831 const auto lineEditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget);
5832 QStyleOptionFrame frame;
5833 static_cast<QStyleOption &>(frame) = *opt;
5834 frame.rect = lineEditRect;
5835 frame.state |= State_Sunken;
5836 frame.lineWidth = 1;
5837 frame.midLineWidth = 0;
5838 frame.features = QStyleOptionFrame::None;
5839 frame.frameShape = QFrame::Box;
5840 drawPrimitive(PE_FrameLineEdit, &frame, p, widget);
5842 if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) {
5843 const QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget)
5844 | proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
5847 d->setupNSGraphicsContext(cg, NO);
5849 const auto aquaSize = d->effectiveAquaSizeConstrain(opt, widget);
5850 const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Stepper, aquaSize);
5851 NSStepperCell *cell =
static_cast<NSStepperCell *>(d->cocoaCell(cw));
5852 cell.enabled = (sb->state & State_Enabled);
5854 const CGRect newRect = [cell drawingRectForBounds:updown.toCGRect()];
5856 const bool upPressed = sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken);
5857 const bool downPressed = sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken);
5858 const CGFloat x = CGRectGetMidX(newRect);
5859 const CGFloat y = upPressed ? -3 : 3;
5860 const CGPoint pressPoint = CGPointMake(x, y);
5863 if (upPressed || downPressed)
5864 [cell startTrackingAt:pressPoint inView:d->backingStoreNSView];
5866 [cell drawWithFrame:newRect inView:d->backingStoreNSView];
5868 if (upPressed || downPressed)
5869 [cell stopTracking:pressPoint at:pressPoint inView:d->backingStoreNSView mouseIsUp:NO];
5871 d->restoreNSGraphicsContext(cg);
5876#if QT_CONFIG(combobox)
5878 if (
const auto *combo = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
5879 const bool isEnabled = combo->state & State_Enabled;
5880 const bool isPressed = combo->state & State_Sunken;
5882 const auto ct = cocoaControlType(combo, widget);
5883 const auto cs = d->effectiveAquaSizeConstrain(combo, widget);
5884 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
5885 auto *cc =
static_cast<NSControl *>(d->cocoaControl(cw));
5886 cc.enabled = isEnabled;
5887 QRectF frameRect = cw.adjustedControlFrame(combo->rect);
5888 if (cw.type == QMacStylePrivate::Button_PopupButton) {
5890 auto *pb =
static_cast<NSPopUpButton *>(cc);
5892 if (cw.size == QStyleHelper::SizeSmall) {
5893 frameRect = frameRect.translated(0, 1);
5894 }
else if (cw.size == QStyleHelper::SizeMini) {
5896 frameRect = frameRect.translated(2, -0.5);
5898 pb.frame = frameRect.toCGRect();
5899 [pb highlight:isPressed];
5900 d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef,
const CGRect &r) {
5901 [pb.cell drawBezelWithFrame:r inView:pb.superview];
5903 }
else if (cw.type == QMacStylePrivate::ComboBox) {
5905 auto *cb =
static_cast<NSComboBox *>(cc);
5906 const auto frameRect = cw.adjustedControlFrame(combo->rect);
5907 cb.frame = frameRect.toCGRect();
5910 if (NSButtonCell *cell =
static_cast<NSButtonCell *>([cc.cell qt_valueForPrivateKey:@
"_buttonCell"])) {
5911 cell.highlighted = isPressed;
5916 d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef,
const CGRect &r) {
5918 [cb.cell drawWithFrame:r inView:cb];
5922 if (combo->state & State_HasFocus) {
5924 const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, combo, widget);
5925 const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, combo, widget);
5927 if (cw.type == QMacStylePrivate::Button_PopupButton) {
5928 if (qt_apple_runningWithLiquidGlass())
5929 focusRect = QRectF::fromCGRect(qt_alignmentRectForFrame(cc.frame, cw.size, cw.type));
5931 focusRect = QRectF::fromCGRect([cc alignmentRectForFrame:cc.frame]);
5932 focusRect -= pullDownButtonShadowMargins[cw.size];
5933 if (cw.size == QStyleHelper::SizeSmall)
5934 focusRect = focusRect.translated(0, 1);
5935 else if (cw.size == QStyleHelper::SizeMini)
5936 focusRect = focusRect.translated(2, -1);
5937 }
else if (cw.type == QMacStylePrivate::ComboBox) {
5938 focusRect = frameRect - comboBoxFocusRingMargins[cw.size];
5940 d->drawFocusRing(p, focusRect, hMargin, vMargin, cw);
5946 if (
const auto *titlebar = qstyleoption_cast<
const QStyleOptionTitleBar *>(opt)) {
5947 const bool isActive = (titlebar->state & State_Active)
5948 && (titlebar->titleBarState & State_Active);
5950 p->fillRect(opt->rect, Qt::transparent);
5951 p->setRenderHint(QPainter::Antialiasing);
5952 p->setClipRect(opt->rect, Qt::IntersectClip);
5956 const auto outerFrameRect = QRectF(opt->rect.adjusted(0, 0, 0, opt->rect.height()));
5957 QPainterPath outerFramePath = d->windowPanelPath(outerFrameRect);
5958 p->fillPath(outerFramePath, opt->palette.dark());
5960 const auto frameAdjust = 1.0 / p->device()->devicePixelRatio();
5961 const auto innerFrameRect = outerFrameRect.adjusted(frameAdjust, frameAdjust, -frameAdjust, 0);
5962 QPainterPath innerFramePath = d->windowPanelPath(innerFrameRect);
5963 p->fillPath(innerFramePath, opt->palette.button());
5965 if (titlebar->subControls & (SC_TitleBarCloseButton
5966 | SC_TitleBarMaxButton
5967 | SC_TitleBarMinButton
5968 | SC_TitleBarNormalButton)) {
5969 const bool isHovered = (titlebar->state & State_MouseOver);
5970 static const SubControl buttons[] = {
5971 SC_TitleBarCloseButton, SC_TitleBarMinButton, SC_TitleBarMaxButton
5973 for (
const auto sc : buttons) {
5974 const auto ct = d->windowButtonCocoaControl(sc);
5975 const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge);
5976 auto *wb =
static_cast<NSButton *>(d->cocoaControl(cw));
5977 wb.enabled = (sc & titlebar->subControls) && isActive;
5978 [wb highlight:(titlebar->state & State_Sunken) && (sc & titlebar->activeSubControls)];
5979 Q_UNUSED(isHovered);
5981 const auto buttonRect = proxy()->subControlRect(CC_TitleBar, titlebar, sc, widget);
5982 d->drawNSViewInRect(wb, buttonRect, p, ^(CGContextRef,
const CGRect &rect) {
5983 auto *wbCell =
static_cast<NSButtonCell *>(wb.cell);
5984 [wbCell drawWithFrame:rect inView:wb];
5989 if (titlebar->subControls & SC_TitleBarLabel) {
5990 const auto tr = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarLabel, widget);
5991 if (!titlebar->icon.isNull()) {
5992 const auto iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
5993 const auto iconSize = QSize(iconExtent, iconExtent);
5994 const auto iconPos = tr.x() - titlebar->icon.actualSize(iconSize).width() - qRound(titleBarIconTitleSpacing);
5996 if (iconPos < tr.right() - titleBarIconTitleSpacing)
5997 p->drawPixmap(iconPos, tr.y(), titlebar->icon.pixmap(iconSize, QIcon::Normal));
6000 if (!titlebar->text.isEmpty())
6001 drawItemText(p, tr, Qt::AlignCenter, opt->palette, isActive, titlebar->text, QPalette::Text);
6006 if (
const QStyleOptionGroupBox *gb
6007 = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
6009 QStyleOptionGroupBox groupBox(*gb);
6010 const bool flat = groupBox.features & QStyleOptionFrame::Flat;
6012 groupBox.state |= QStyle::State_Mini;
6014 groupBox.subControls = groupBox.subControls & ~SC_GroupBoxFrame;
6016 const bool didSetFont = widget && widget->testAttribute(Qt::WA_SetFont);
6017 const bool didModifySubControls = !didSetFont && QApplication::desktopSettingsAware();
6018 if (didModifySubControls)
6019 groupBox.subControls = groupBox.subControls & ~SC_GroupBoxLabel;
6020 QCommonStyle::drawComplexControl(cc, &groupBox, p, widget);
6021 if (didModifySubControls) {
6022 const QRect rect = proxy()->subControlRect(CC_GroupBox, &groupBox, SC_GroupBoxLabel, widget);
6023 const bool rtl = groupBox.direction == Qt::RightToLeft;
6024 const int alignment = Qt::TextHideMnemonic | (rtl ? Qt::AlignRight : Qt::AlignLeft);
6025 const QFont savedFont = p->font();
6026 if (!flat && d->smallSystemFont)
6027 p->setFont(*d->smallSystemFont);
6028 proxy()->drawItemText(p, rect, alignment, groupBox.palette, groupBox.state & State_Enabled, groupBox.text, QPalette::WindowText);
6030 p->setFont(savedFont);
6035 if (
const QStyleOptionToolButton *tb
6036 = qstyleoption_cast<
const QStyleOptionToolButton *>(opt)) {
6037#if QT_CONFIG(accessibility)
6038 if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) {
6039 if (tb->subControls & SC_ToolButtonMenu) {
6040 QStyleOption arrowOpt = *tb;
6041 arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
6042 arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2);
6043 arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2);
6044 proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
6045 }
else if ((tb->features & QStyleOptionToolButton::HasMenu)
6046 && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) {
6047 d->drawToolbarButtonArrow(tb, p);
6049 if (tb->state & State_On) {
6050 NSView *view = window ? (NSView *)window->winId() : nil;
6053 isKey = [view.window isKeyWindow];
6055 QBrush brush(brushForToolButton(isKey));
6057 path.addRoundedRect(QRectF(tb->rect.x(), tb->rect.y(), tb->rect.width(), tb->rect.height() + 4), 4, 4);
6058 p->setRenderHint(QPainter::Antialiasing);
6059 p->fillPath(path, brush);
6061 proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget);
6065 auto bflags = tb->state;
6066 if (tb->subControls & SC_ToolButton)
6067 bflags |= State_Sunken;
6068 auto mflags = tb->state;
6069 if (tb->subControls & SC_ToolButtonMenu)
6070 mflags |= State_Sunken;
6072 if (tb->subControls & SC_ToolButton) {
6073 if (bflags & (State_Sunken | State_On | State_Raised)) {
6074 const bool isEnabled = tb->state & State_Enabled;
6075 const bool isPressed = tb->state & State_Sunken;
6076 const bool isHighlighted = (tb->state & State_Active) && (tb->state & State_On);
6077 const auto ct = QMacStylePrivate::Button_PushButton;
6078 const auto cs = d->effectiveAquaSizeConstrain(opt, widget);
6079 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
6080 auto *pb =
static_cast<NSButton *>(d->cocoaControl(cw));
6081 pb.bezelStyle = NSBezelStyleShadowlessSquare;
6082 pb.frame = opt->rect.toCGRect();
6083 pb.buttonType = NSButtonTypePushOnPushOff;
6084 pb.enabled = isEnabled;
6085 [pb highlight:isPressed];
6086 pb.state = isHighlighted && !isPressed ? NSControlStateValueOn : NSControlStateValueOff;
6087 const auto buttonRect = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
6088 d->drawNSViewInRect(pb, buttonRect, p, ^(CGContextRef,
const CGRect &rect) {
6089 [pb.cell drawBezelWithFrame:rect inView:pb];
6094 if (tb->subControls & SC_ToolButtonMenu) {
6095 const auto menuRect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
6096 QStyleOption arrowOpt = *tb;
6101 proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
6102 }
else if (tb->features & QStyleOptionToolButton::HasMenu) {
6103 d->drawToolbarButtonArrow(tb, p);
6105 QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget);
6106 int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
6107 QStyleOptionToolButton label = *tb;
6108 label.rect = buttonRect.adjusted(fw, fw, -fw, -fw);
6109 proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
6115 if (
const QStyleOptionSlider *dial = qstyleoption_cast<
const QStyleOptionSlider *>(opt))
6116 QStyleHelper::drawDial(dial, p);
6120 QCommonStyle::drawComplexControl(cc, opt, p, widget);
6212 const QWidget *widget)
const
6214 Q_D(
const QMacStyle);
6218 if (
const QStyleOptionSlider *sb = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
6219 const bool isHorizontal = sb->orientation == Qt::Horizontal;
6220 const bool isReverseHorizontal = isHorizontal && (sb->direction == Qt::RightToLeft);
6222 NSScrollerPart part = NSScrollerNoPart;
6223 if (sc == SC_ScrollBarSlider) {
6224 part = NSScrollerKnob;
6225 }
else if (sc == SC_ScrollBarGroove) {
6226 part = NSScrollerKnobSlot;
6227 }
else if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) {
6228 if ((!isReverseHorizontal && sc == SC_ScrollBarSubPage)
6229 || (isReverseHorizontal && sc == SC_ScrollBarAddPage))
6230 part = NSScrollerDecrementPage;
6232 part = NSScrollerIncrementPage;
6236 if (part != NSScrollerNoPart) {
6237 const auto ct = isHorizontal ? QMacStylePrivate::Scroller_Horizontal : QMacStylePrivate::Scroller_Vertical;
6238 const auto cs = d->effectiveAquaSizeConstrain(opt, widget);
6239 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
6240 auto *scroller =
static_cast<NSScroller *>(d->cocoaControl(cw));
6241 if (setupScroller(scroller, sb))
6242 ret = QRectF::fromCGRect([scroller rectForPart:part]).toRect();
6247 if (
const QStyleOptionSlider *sl = qstyleoption_cast<
const QStyleOptionSlider *>(opt)) {
6248 const bool hasTicks = sl->tickPosition != QSlider::NoTicks;
6249 const bool isHorizontal = sl->orientation == Qt::Horizontal;
6250 const auto ct = isHorizontal ? QMacStylePrivate::Slider_Horizontal : QMacStylePrivate::Slider_Vertical;
6251 const auto cs = d->effectiveAquaSizeConstrain(opt, widget);
6252 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
6253 auto *slider =
static_cast<NSSlider *>(d->cocoaControl(cw));
6254 if (!setupSlider(slider, sl))
6257 NSSliderCell *cell = slider.cell;
6258 if (sc == SC_SliderHandle) {
6259 ret = QRectF::fromCGRect([cell knobRectFlipped:slider.isFlipped]).toRect();
6261 ret.setTop(sl->rect.top());
6262 ret.setBottom(sl->rect.bottom());
6264 ret.setLeft(sl->rect.left());
6265 ret.setRight(sl->rect.right());
6267 }
else if (sc == SC_SliderGroove) {
6268 ret = QRectF::fromCGRect([cell barRectFlipped:slider.isFlipped]).toRect();
6269 }
else if (hasTicks && sc == SC_SliderTickmarks) {
6270 const auto tickMarkRect = QRectF::fromCGRect([cell rectOfTickMarkAtIndex:0]);
6272 ret = QRect(sl->rect.left(), tickMarkRect.top(), sl->rect.width(), tickMarkRect.height());
6274 ret = QRect(tickMarkRect.left(), sl->rect.top(), tickMarkRect.width(), sl->rect.height());
6279 if (sl->upsideDown) {
6280 ret = QRect(sl->rect.right() - ret.right(), sl->rect.top(), ret.width(), sl->rect.height());
6282 ret.setTop(sl->rect.top());
6283 ret.setBottom(sl->rect.bottom());
6286 if (!sl->upsideDown) {
6287 ret = QRect(sl->rect.left(), sl->rect.bottom() - ret.bottom(), sl->rect.width(), ret.height());
6289 ret.setLeft(sl->rect.left());
6290 ret.setRight(sl->rect.right());
6296 if (
const auto *titlebar = qstyleoption_cast<
const QStyleOptionTitleBar *>(opt)) {
6302 if (sc == SC_TitleBarLabel) {
6303 qreal labelWidth = titlebar->fontMetrics.horizontalAdvance(titlebar->text) + 1;
6304 qreal labelHeight = titlebar->fontMetrics.height();
6306 const auto lastButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarMaxButton, widget);
6307 qreal controlsSpacing = lastButtonRect.right() + titleBarButtonSpacing;
6308 if (!titlebar->icon.isNull()) {
6309 const auto iconSize = proxy()->pixelMetric(PM_SmallIconSize);
6310 const auto actualIconSize = titlebar->icon.actualSize(QSize(iconSize, iconSize)).width();
6311 controlsSpacing += actualIconSize + titleBarIconTitleSpacing;
6314 const qreal labelPos = qMax(controlsSpacing, (opt->rect.width() - labelWidth) / 2.0);
6315 labelWidth = qMin(labelWidth, opt->rect.width() - (labelPos + titleBarTitleRightMargin));
6316 ret = QRect(labelPos, (opt->rect.height() - labelHeight) / 2,
6317 labelWidth, labelHeight);
6319 const auto currentButton = d->windowButtonCocoaControl(sc);
6320 if (currentButton == QMacStylePrivate::NoControl)
6323 QPointF buttonPos = titlebar->rect.topLeft() + QPointF(titleBarButtonSpacing, 0);
6325 for (
int ct = QMacStylePrivate::Button_WindowClose; ct <= currentButton; ct++) {
6326 const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::CocoaControlType(ct),
6327 QStyleHelper::SizeLarge);
6328 auto *wb =
static_cast<NSButton *>(d->cocoaControl(cw));
6329 if (ct == currentButton)
6330 buttonSize = QSizeF::fromCGSize(wb.frame.size);
6332 buttonPos.rx() += wb.frame.size.width + titleBarButtonSpacing;
6335 const auto vOffset = (opt->rect.height() - buttonSize.height()) / 2.0;
6336 ret = QRectF(buttonPos, buttonSize).translated(0, vOffset).toRect();
6341 if (
const QStyleOptionComboBox *combo = qstyleoption_cast<
const QStyleOptionComboBox *>(opt)) {
6342 const auto ct = cocoaControlType(combo, widget);
6343 const auto cs = d->effectiveAquaSizeConstrain(combo, widget);
6344 const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
6345 const auto editRect = QMacStylePrivate::comboboxEditBounds(cw.adjustedControlFrame(combo->rect), cw);
6348 case SC_ComboBoxEditField:{
6349 ret = editRect.toAlignedRect();
6351 case SC_ComboBoxArrow:{
6352 ret = editRect.toAlignedRect();
6353 ret.setX(ret.x() + ret.width());
6354 ret.setWidth(combo->rect.right() - ret.right());
6356 case SC_ComboBoxListBoxPopup:{
6357 if (combo->editable) {
6358 const CGRect inner = QMacStylePrivate::comboboxInnerBounds(combo->rect.toCGRect(), cw);
6359 const int comboTop = combo->rect.top();
6360 ret = QRect(qRound(inner.origin.x),
6362 qRound(inner.origin.x - combo->rect.left() + inner.size.width),
6363 editRect.bottom() - comboTop + 2);
6365 ret = QRect(combo->rect.x() + 4 - 11,
6366 combo->rect.y() + 1,
6367 editRect.width() + 10 + 11,
6377 if (
const QStyleOptionGroupBox *groupBox = qstyleoption_cast<
const QStyleOptionGroupBox *>(opt)) {
6378 bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
6379 const bool flat = groupBox->features & QStyleOptionFrame::Flat;
6380 bool hasNoText = !checkable && groupBox->text.isEmpty();
6382 case SC_GroupBoxLabel:
6383 case SC_GroupBoxCheckBox: {
6385 const bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
6386 const bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont))
6387 || !QApplication::desktopSettingsAware();
6388 const int margin = flat || hasNoText ? 0 : 9;
6389 ret = groupBox->rect.adjusted(margin, 0, -margin, 0);
6391 const QFontMetricsF fm = flat || fontIsSet || !d->smallSystemFont
6392 ? QFontMetricsF(groupBox->fontMetrics)
6393 : QFontMetricsF(*d->smallSystemFont);
6394 const QSizeF s = fm.size(Qt::AlignHCenter | Qt::AlignVCenter, qt_mac_removeMnemonics(groupBox->text), 0,
nullptr);
6395 const int tw = qCeil(s.width());
6396 const int h = qCeil(fm.height());
6399 QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment,
6401 if (flat && checkable)
6402 labelRect.moveLeft(labelRect.left() + 4);
6403 int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
6404 bool rtl = groupBox->direction == Qt::RightToLeft;
6405 if (sc == SC_GroupBoxLabel) {
6407 int newSum = indicatorWidth + 1;
6408 int newLeft = labelRect.left() + (rtl ? -newSum : newSum);
6409 labelRect.moveLeft(newLeft);
6411 labelRect.moveTop(labelRect.top() + 3);
6413 labelRect.moveTop(labelRect.top() + 4);
6415 int newLeft = labelRect.left() - (rtl ? 3 : -3);
6416 labelRect.moveLeft(newLeft);
6417 labelRect.moveTop(labelRect.top() + 3);
6419 int newLeft = labelRect.left() - (rtl ? 3 : 2);
6420 labelRect.moveLeft(newLeft);
6421 labelRect.moveTop(labelRect.top() + 4);
6426 if (sc == SC_GroupBoxCheckBox) {
6427 int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left() - 1;
6428 int top = flat ? ret.top() + 1 : ret.top() + 5;
6429 ret.setRect(left, top,
6430 indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget));
6434 case SC_GroupBoxContents:
6435 case SC_GroupBoxFrame: {
6436 QFontMetrics fm = groupBox->fontMetrics;
6439 if (widget && !widget->testAttribute(Qt::WA_SetFont)
6440 && QApplication::desktopSettingsAware())
6441 fm = QFontMetrics(qt_app_fonts_hash()->value(
"QSmallFont", QFont()));
6446 yOffset = -qCeil(QFontMetricsF(fm).height());
6447 ret = opt->rect.adjusted(0, qCeil(QFontMetricsF(fm).height()) + yOffset, 0, 0);
6448 if (sc == SC_GroupBoxContents) {
6450 ret.adjust(3, -5, -3, -4);
6452 ret.adjust(3, 3, -3, -4);
6457 ret = QCommonStyle::subControlRect(cc, groupBox, sc, widget);
6462#if QT_CONFIG(spinbox)
6464 if (
const QStyleOptionSpinBox *spin = qstyleoption_cast<
const QStyleOptionSpinBox *>(opt)) {
6465 QStyleHelper::WidgetSizePolicy aquaSize = d->effectiveAquaSizeConstrain(spin, widget);
6466 const auto fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget);
6470 case QStyleHelper::SizeLarge:
6474 case QStyleHelper::SizeSmall:
6478 case QStyleHelper::SizeMini:
6488 case SC_SpinBoxDown: {
6489 if (spin->buttonSymbols == QAbstractSpinBox::NoButtons)
6493 const int x = spin->rect.width() - spinner_w;
6494 ret.setRect(x + spin->rect.x(), y + spin->rect.y(), spinner_w, spin->rect.height() - y * 2);
6497 case QStyleHelper::SizeLarge:
6500 case QStyleHelper::SizeSmall:
6501 hackTranslateX = -2;
6503 case QStyleHelper::SizeMini:
6504 hackTranslateX = -1;
6510 const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Stepper, aquaSize);
6511 NSStepperCell *cell =
static_cast<NSStepperCell *>(d->cocoaCell(cw));
6512 const CGRect outRect = [cell drawingRectForBounds:ret.toCGRect()];
6513 ret = QRectF::fromCGRect(outRect).toRect();
6517 ret.setHeight(ret.height() / 2);
6519 case SC_SpinBoxDown:
6520 ret.setY(ret.y() + ret.height() / 2);
6526 ret.translate(hackTranslateX, 0);
6527 ret = visualRect(spin->direction, spin->rect, ret);
6530 case SC_SpinBoxEditField:
6531 ret = spin->rect.adjusted(fw, fw, -fw, -fw);
6532 if (spin->buttonSymbols != QAbstractSpinBox::NoButtons) {
6533 ret.setWidth(spin->rect.width() - spinBoxSep - spinner_w);
6534 ret = visualRect(spin->direction, spin->rect, ret);
6538 ret = QCommonStyle::subControlRect(cc, spin, sc, widget);
6545 ret = QCommonStyle::subControlRect(cc, opt, sc, widget);
6546 if (sc == SC_ToolButtonMenu) {
6547#if QT_CONFIG(accessibility)
6548 if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar))
6549 ret.adjust(-toolButtonArrowMargin, 0, 0, 0);
6551 ret.adjust(-1, 0, 0, 0);
6555 ret = QCommonStyle::subControlRect(cc, opt, sc, widget);