diff options
author | Oleg Yadrov <oleg.yadrov@qt.io> | 2017-10-02 10:27:10 -0400 |
---|---|---|
committer | Gabriel de Dietrich <gabriel.dedietrich@qt.io> | 2017-10-05 17:04:07 +0000 |
commit | 5ff9d6a470dbcf424f2f43206ab6ab6eb91edcc1 (patch) | |
tree | eb2424ff6dfb579aaa962f218e094b932fe41cec | |
parent | 08e083e682d92290e36e4fb09abaf0318575dd41 (diff) |
QMacStyle: smooth QMenu corners for real
It's been for years that QMenu's rounded corners in qmacstyle_mac were
done via QWidget::setMask(QRegion). Unfortunately, QRegion mask does not
work well with retina displays and also does not support translucency.
That's why in this change we explicitly make QMenu's background
transparent and then draw a rectangle with rounded corners in
QMacStyle::drawPrimitive(PE_PanelMenu). This not only gives much better
result than the mask-based approach, but also de-HIThemes QMenu.
As a consequence, QComboBoxPrivateContainer doesn't get any mask from
QMacStyle anymore. Therefore, when the mask is empty, we need to paint
PE_PanelMenu before invoking QFrame's paint event handler.
Made-with: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
Change-Id: Ia9236176113f23b86e45507fa6ddf77236084ce3
Reviewed-by: Oleg Yadrov <oleg.yadrov@qt.io>
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoasystemsettings.mm | 1 | ||||
-rw-r--r-- | src/plugins/styles/mac/qmacstyle_mac.mm | 92 | ||||
-rw-r--r-- | src/widgets/widgets/qcombobox.cpp | 14 | ||||
-rw-r--r-- | src/widgets/widgets/qcombobox_p.h | 1 |
4 files changed, 56 insertions, 52 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index 91fb6e973d..7c6f879b18 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -144,7 +144,6 @@ QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes() } if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette || mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) { - pal.setBrush(QPalette::Background, qt_mac_toQColor([NSColor windowBackgroundColor])); pal.setBrush(QPalette::Highlight, qt_mac_toQColor([NSColor selectedMenuItemColor])); qc = qt_mac_toQColor([NSColor labelColor]); pal.setBrush(QPalette::ButtonText, qc); diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index d9e622c28a..b24ecee102 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -663,14 +663,6 @@ HIMutableShapeRef qt_mac_toHIMutableShape(const QRegion ®ion) return shape; } -QRegion qt_mac_fromHIShapeRef(HIShapeRef shape) -{ - QRegion returnRegion; - //returnRegion.detach(); - HIShapeEnumerate(shape, kHIShapeParseFromTopLeft, qt_mac_shape2QRegionHelper, &returnRegion); - return returnRegion; -} - bool qt_macWindowIsTextured(const QWidget *window) { if (QWindow *w = window->windowHandle()) @@ -2291,24 +2283,7 @@ void QMacStyle::polish(QWidget* w) || qobject_cast<QComboBoxPrivateContainer *>(w) #endif ) { - w->setWindowOpacity(0.985); - if (!w->testAttribute(Qt::WA_SetPalette)) { - QPixmap px(64, 64); - px.fill(Qt::white); - HIThemeMenuDrawInfo mtinfo; - mtinfo.version = qt_mac_hitheme_version; - mtinfo.menuType = kThemeMenuTypePopUp; - // HIRect rect = CGRectMake(0, 0, px.width(), px.height()); - // ### - //HIThemeDrawMenuBackground(&rect, &mtinfo, QMacCGContext(&px)), - // kHIThemeOrientationNormal); - QPalette pal = w->palette(); - QBrush background(px); - pal.setBrush(QPalette::All, QPalette::Window, background); - pal.setBrush(QPalette::All, QPalette::Button, background); - w->setPalette(pal); - w->setAttribute(Qt::WA_SetPalette, false); - } + w->setAttribute(Qt::WA_TranslucentBackground, true); } #endif @@ -3023,7 +2998,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w ret = Qt::AlignRight; break; case SH_ComboBox_PopupFrameStyle: - ret = QFrame::NoFrame | QFrame::Plain; + ret = QFrame::NoFrame; break; case SH_MessageBox_TextInteractionFlags: ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard; @@ -3057,27 +3032,6 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w case SH_Menu_FadeOutOnHide: ret = true; break; - case SH_Menu_Mask: - if (opt) { - if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) { - ret = true; - CGRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4, - opt->rect.width(), opt->rect.height() - 8); - HIThemeMenuDrawInfo mdi; - mdi.version = 0; -#if QT_CONFIG(menu) - if (w && qobject_cast<QMenu *>(w->parentWidget())) - mdi.menuType = kThemeMenuTypeHierarchical; - else -#endif - mdi.menuType = kThemeMenuTypePopUp; - QCFType<HIShapeRef> shape; - HIThemeGetMenuBackgroundShape(&menuRect, &mdi, &shape); - - mask->region = qt_mac_fromHIShapeRef(shape); - } - } - break; case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: ret = true; break; @@ -3587,6 +3541,40 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai break; } + case PE_PanelMenu: { + p->save(); + p->fillRect(opt->rect, Qt::transparent); + p->setPen(Qt::transparent); + p->setBrush(opt->palette.window()); + p->setRenderHint(QPainter::Antialiasing, true); + QPainterPath path; + static const qreal CornerPointOffset = 5.5; + static const qreal CornerControlOffset = 2.1; + QRectF r = opt->rect; + // Top-left corner + path.moveTo(r.left(), r.top() + CornerPointOffset); + path.cubicTo(r.left(), r.top() + CornerControlOffset, + r.left() + CornerControlOffset, r.top(), + r.left() + CornerPointOffset, r.top()); + // Top-right corner + path.lineTo(r.right() - CornerPointOffset, r.top()); + path.cubicTo(r.right() - CornerControlOffset, r.top(), + r.right(), r.top() + CornerControlOffset, + r.right(), r.top() + CornerPointOffset); + // Bottom-right corner + path.lineTo(r.right(), r.bottom() - CornerPointOffset); + path.cubicTo(r.right(), r.bottom() - CornerControlOffset, + r.right() - CornerControlOffset, r.bottom(), + r.right() - CornerPointOffset, r.bottom()); + // Bottom-right corner + path.lineTo(r.left() + CornerPointOffset, r.bottom()); + path.cubicTo(r.left() + CornerControlOffset, r.bottom(), + r.left(), r.bottom() - CornerControlOffset, + r.left(), r.bottom() - CornerPointOffset); + path.lineTo(r.left(), r.top() + CornerPointOffset); + p->drawPath(path); + p->restore(); + } break; default: QCommonStyle::drawPrimitive(pe, opt, p, w); @@ -4269,16 +4257,18 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w); d->drawFocusRing(p, opt->rect, hMargin, vMargin); break; } + case CE_MenuEmptyArea: + // Skip: PE_PanelMenu fills in everything + break; case CE_MenuItem: case CE_MenuHMargin: case CE_MenuVMargin: - case CE_MenuEmptyArea: case CE_MenuTearoff: case CE_MenuScroller: if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) { const bool active = mi->state & State_Selected; - const QBrush bg = active ? mi->palette.highlight() : mi->palette.background(); - p->fillRect(mi->rect, bg); + if (active) + p->fillRect(mi->rect, mi->palette.highlight()); const QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, w); diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 1338a496e6..9afb4b3ae6 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -428,6 +428,20 @@ void QComboBoxPrivateContainer::resizeEvent(QResizeEvent *e) QFrame::resizeEvent(e); } +void QComboBoxPrivateContainer::paintEvent(QPaintEvent *e) +{ + QStyleOptionComboBox cbOpt = comboStyleOption(); + if (combo->style()->styleHint(QStyle::SH_ComboBox_Popup, &cbOpt, combo) + && mask().isEmpty()) { + QStyleOption opt; + opt.initFrom(this); + QPainter p(this); + style()->drawPrimitive(QStyle::PE_PanelMenu, &opt, &p, this); + } + + QFrame::paintEvent(e); +} + void QComboBoxPrivateContainer::leaveEvent(QEvent *) { // On Mac using the Mac style we want to clear the selection diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h index 835bbf866e..3f75a357e4 100644 --- a/src/widgets/widgets/qcombobox_p.h +++ b/src/widgets/widgets/qcombobox_p.h @@ -248,6 +248,7 @@ protected: void timerEvent(QTimerEvent *timerEvent) override; void leaveEvent(QEvent *e) override; void resizeEvent(QResizeEvent *e) override; + void paintEvent(QPaintEvent *e) override; QStyleOptionComboBox comboStyleOption() const; Q_SIGNALS: |