summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Ehrlicher <[email protected]>2025-06-21 22:51:27 +0200
committerChristian Ehrlicher <[email protected]>2025-06-27 16:50:31 +0200
commitb335784c25600cf7df20e67f45d0ab315e0a02b3 (patch)
tree6281150069a424c6f833086528f09fd6b6e4f544
parent513f5a9b8a6855c3c8b6ff8a45fd219c6240bc21 (diff)
Windows11Style: fix/cleanup QLineEdit/SpinBox/ComboBox painting
Fix style issues: - paint lineedit indicator more like windows 11 - don't draw frame when not requested - use same height for all three widget types when no frame is painted Also cleanup the code: - move frame painting into own function (drawLineEditFrame()) for all three widgets - sync the painting of the other paintings as it can not be merged into one function due to PE_FrameLineEdit - use helper functions drawRoundedRect() and winUI3Color() to avoid code repetitions Pick-to: 6.10 Fixes: QTBUG-137403 Change-Id: I50e6fc16f13e0c043965d1bbe9406e61dff4dac7 Reviewed-by: Volker Hilsheimer <[email protected]>
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp172
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style_p.h25
2 files changed, 88 insertions, 109 deletions
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
index ab6a636959f..c65a6222b9f 100644
--- a/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -38,27 +38,13 @@ QT_BEGIN_NAMESPACE
static constexpr int topLevelRoundingRadius = 8; //Radius for toplevel items like popups for round corners
static constexpr int secondLevelRoundingRadius = 4; //Radius for second level items like hovered menu item round corners
-
-enum WINUI3Color {
- subtleHighlightColor, //Subtle highlight based on alpha used for hovered elements
- subtlePressedColor, //Subtle highlight based on alpha used for pressed elements
- frameColorLight, //Color of frame around flyouts and controls except for Checkbox and Radiobutton
- frameColorStrong, //Color of frame around Checkbox and Radiobuttons
- controlStrongFill, //Color of controls with strong filling such as the right side of a slider
- controlStrokeSecondary,
- controlStrokePrimary,
- controlFillTertiary, //Color of filled sunken controls
- controlFillSecondary, //Color of filled hovered controls
- menuPanelFill, //Color of menu panel
- textOnAccentPrimary, //Color of text on controls filled in accent color
- textOnAccentSecondary, //Color of text of sunken controls in accent color
- controlTextSecondary, //Color of text of sunken controls
- controlStrokeOnAccentSecondary, //Color of frame around Buttons in accent color
- controlFillSolid, //Color for solid fill
- surfaceStroke, //Color of MDI window frames
- controlAccentDisabled,
- textAccentDisabled
-};
+template <typename R, typename P, typename B>
+static inline void drawRoundedRect(QPainter *p, R &&rect, P &&pen, B &&brush)
+{
+ p->setPen(pen);
+ p->setBrush(brush);
+ p->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+}
static const QColor WINUI3ColorsLight [] {
QColor(0x00,0x00,0x00,0x09), //subtleHighlightColor
@@ -253,42 +239,24 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt
QCachedPainter cp(painter, QLatin1StringView("win11_spinbox") % HexString<uint8_t>(colorSchemeIndex),
sb, sb->rect.size());
if (cp.needsPainting()) {
- if (sb->frame && (sub & SC_SpinBoxFrame)) {
- const qreal sublineOffset = secondLevelRoundingRadius + 2.0;
- cp->save();
- cp->setClipRect(option->rect.adjusted(-2, -2, 2, 2));
- cp->setPen(editSublineColor(option, colorSchemeIndex));
- cp->drawLine(option->rect.bottomLeft() + QPointF(sublineOffset, 0.5),
- option->rect.bottomRight() + QPointF(-sublineOffset, 0.5));
- cp->restore();
- }
- const QRectF frameRect = QRectF(option->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
- cp->setBrush(option->palette.brush(QPalette::Base));
- cp->setPen(highContrastTheme == true ? sb->palette.buttonText().color()
- : WINUI3Colors[colorSchemeIndex][frameColorLight]);
- cp->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius);
- const QPoint mousePos = widget ? widget->mapFromGlobal(QCursor::pos()) : QPoint();
- if (sub & SC_SpinBoxEditField) {
- const QRect rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxEditField,
- widget).adjusted(0, 0, 0, 1);
- if (!(state & State_HasFocus) && rect.contains(mousePos)) {
- cp->setPen(Qt::NoPen);
- cp->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
- cp->drawRoundedRect(option->rect.adjusted(2, 2, -2, -2), secondLevelRoundingRadius,
- secondLevelRoundingRadius);
- }
- }
+ const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1));
+ drawRoundedRect(cp.painter(), frameRect, Qt::NoPen, option->palette.brush(QPalette::Base));
+
+ if (sb->frame && (sub & SC_SpinBoxFrame))
+ drawLineEditFrame(cp.painter(), option);
+
+ const bool isMouseOver = state & State_MouseOver;
+ const bool hasFocus = state & State_HasFocus;
+ if (isMouseOver && !hasFocus && !highContrastTheme)
+ drawRoundedRect(cp.painter(), frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor));
+
const auto drawUpDown = [&](QStyle::SubControl sc) {
const bool isUp = sc == SC_SpinBoxUp;
- QRect rect = proxy()->subControlRect(CC_SpinBox, option, isUp ? SC_SpinBoxUp : SC_SpinBoxDown, widget);
- if (isUp)
- rect.adjust(0, 0, 0, 1);
- if (rect.contains(mousePos)) {
- cp->setPen(Qt::NoPen);
- cp->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
- cp->drawRoundedRect(rect.adjusted(1, 1, -1, -1), secondLevelRoundingRadius,
- secondLevelRoundingRadius);
- }
+ const QRect rect = proxy()->subControlRect(CC_SpinBox, option, sc, widget);
+ if (sb->activeSubControls & sc)
+ drawRoundedRect(cp.painter(), rect.adjusted(1, 1, -1, -2), Qt::NoPen,
+ winUI3Color(subtleHighlightColor));
+
cp->setFont(assetFont);
cp->setPen(sb->palette.buttonText().color());
cp->setBrush(Qt::NoBrush);
@@ -441,36 +409,23 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt
#if QT_CONFIG(combobox)
case CC_ComboBox:
if (const QStyleOptionComboBox *combobox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- QRectF rect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1));
- painter->setBrush(combobox->palette.brush(QPalette::Base));
- painter->setPen(Qt::NoPen);
- painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1));
+ drawRoundedRect(painter, frameRect, Qt::NoPen, option->palette.brush(QPalette::Base));
- const bool comboboxHovered = state & State_MouseOver;
- // In case the QComboBox is hovered overdraw the background with a alpha mask to
- // highlight the QComboBox.
- if (comboboxHovered && !highContrastTheme) {
- painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
- painter->setPen(Qt::NoPen);
- painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
- }
+ if (combobox->frame)
+ drawLineEditFrame(painter, option);
+
+ const bool isMouseOver = state & State_MouseOver;
+ const bool hasFocus = state & State_HasFocus;
+ if (isMouseOver && !hasFocus && !highContrastTheme)
+ drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor));
- rect.adjust(0.5,0.5,-0.5,-0.5);
- painter->setBrush(Qt::NoBrush);
- painter->setPen(highContrastTheme ? (comboboxHovered ? combobox->palette.accent().color() : combobox->palette.buttonText().color()) : WINUI3Colors[colorSchemeIndex][frameColorLight]);
- painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
if (sub & SC_ComboBoxArrow) {
QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget).adjusted(4, 0, -4, 1);
painter->setFont(assetFont);
painter->setPen(combobox->palette.text().color());
painter->drawText(rect, QStringLiteral(u"\uE70D"), Qt::AlignVCenter | Qt::AlignHCenter);
}
-
- if (combobox->editable) {
- const qreal sublineOffset = secondLevelRoundingRadius;
- painter->setPen(editSublineColor(option, colorSchemeIndex));
- painter->drawLine(rect.bottomLeft() + QPointF(sublineOffset, 1.0), rect.bottomRight() + QPointF(-sublineOffset, 1.0));
- }
}
break;
#endif // QT_CONFIG(combobox)
@@ -951,36 +906,21 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption
break;
}
case PE_PanelLineEdit:
- if (widget && widget->objectName() == QStringLiteral(u"qt_spinbox_lineedit"))
- break;
if (const auto *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
- QRectF frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1));
- painter->setBrush(option->palette.brush(QPalette::Base));
- painter->setPen(Qt::NoPen);
- painter->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius);
- // In case the QLineEdit is hovered overdraw the background with a alpha mask to
- // highlight the QLineEdit.
- if (state & State_MouseOver && !(state & State_HasFocus)) {
- painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
- painter->setPen(Qt::NoPen);
- painter->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius);
- }
+ const auto frameRect = option->rect.marginsRemoved(QMargins(1, 1, 1, 1));
+ drawRoundedRect(painter, frameRect, Qt::NoPen, option->palette.brush(QPalette::Base));
+
if (panel->lineWidth > 0)
proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
+
+ const bool isMouseOver = state & State_MouseOver;
+ const bool hasFocus = state & State_HasFocus;
+ if (isMouseOver && !hasFocus && !highContrastTheme)
+ drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor));
}
break;
- case PE_FrameLineEdit: {
- const qreal sublineOffset = secondLevelRoundingRadius + 1.5;
- if (widget && widget->parent() && qobject_cast<QComboBox*>(widget->parent()))
- break;
- QRectF rect = option->rect;
- rect.adjust(1.5, 1.5, -1.5, -1.5);
- painter->setBrush(Qt::NoBrush);
- painter->setPen(highContrastTheme == true ? option->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
- painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
- painter->setPen(editSublineColor(option, colorSchemeIndex));
- painter->drawLine(option->rect.bottomLeft() + QPointF(sublineOffset, 0.5), option->rect.bottomRight() + QPointF(-sublineOffset, 0.5));
- }
+ case PE_FrameLineEdit:
+ drawLineEditFrame(painter, option);
break;
case PE_Frame: {
if (const auto *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
@@ -2442,12 +2382,30 @@ QColor QWindows11Style::buttonLabelColor(const QStyleOption *option, int colorSc
: option->palette.buttonText().color();
}
-QColor QWindows11Style::editSublineColor(const QStyleOption *option, int colorSchemeIndex)
+void QWindows11Style::drawLineEditFrame(QPainter *p, const QStyleOption *o) const
+{
+ const auto rect = QRectF(o->rect).marginsRemoved(QMarginsF(1.5, 1.5, 1.5, 1.5));
+ const bool isHovered = o->state & State_MouseOver;
+ const auto frameCol = highContrastTheme
+ ? o->palette.color(isHovered ? QPalette::Accent
+ : QPalette::ButtonText)
+ : winUI3Color(frameColorLight);
+ drawRoundedRect(p, rect, frameCol, Qt::NoBrush);
+
+ QPainterStateGuard psg(p);
+ p->setClipRect(rect.marginsRemoved(QMarginsF(0, rect.height() - 0.5, 0, -1)));
+ const bool hasFocus = o->state & State_HasFocus;
+ const auto underlineCol = hasFocus
+ ? o->palette.color(QPalette::Accent)
+ : colorSchemeIndex == 0 ? QColor(0x80, 0x80, 0x80)
+ : QColor(0xa0, 0xa0, 0xa0);
+ const auto penUnderline = QPen(underlineCol, hasFocus ? 2 : 1);
+ drawRoundedRect(p, rect, penUnderline, Qt::NoBrush);
+}
+
+QColor QWindows11Style::winUI3Color(enum WINUI3Color col) const
{
- const State state = option->state;
- return state & State_HasFocus ? option->palette.accent().color()
- : (colorSchemeIndex == 0 ? QColor(0x80, 0x80, 0x80)
- : QColor(0xa0, 0xa0, 0xa0));
+ return WINUI3Colors[colorSchemeIndex][col];
}
#undef SET_IF_UNRESOLVED
diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h
index 1be56fe3aa5..66343a02203 100644
--- a/src/plugins/styles/modernwindows/qwindows11style_p.h
+++ b/src/plugins/styles/modernwindows/qwindows11style_p.h
@@ -21,7 +21,27 @@
QT_BEGIN_NAMESPACE
class QWindows11StylePrivate;
-class QWindows11Style;
+
+enum WINUI3Color {
+ subtleHighlightColor, //Subtle highlight based on alpha used for hovered elements
+ subtlePressedColor, //Subtle highlight based on alpha used for pressed elements
+ frameColorLight, //Color of frame around flyouts and controls except for Checkbox and Radiobutton
+ frameColorStrong, //Color of frame around Checkbox and Radiobuttons
+ controlStrongFill, //Color of controls with strong filling such as the right side of a slider
+ controlStrokeSecondary,
+ controlStrokePrimary,
+ controlFillTertiary, //Color of filled sunken controls
+ controlFillSecondary, //Color of filled hovered controls
+ menuPanelFill, //Color of menu panel
+ textOnAccentPrimary, //Color of text on controls filled in accent color
+ textOnAccentSecondary, //Color of text of sunken controls in accent color
+ controlTextSecondary, //Color of text of sunken controls
+ controlStrokeOnAccentSecondary, //Color of frame around Buttons in accent color
+ controlFillSolid, //Color for solid fill
+ surfaceStroke, //Color of MDI window frames
+ controlAccentDisabled,
+ textAccentDisabled
+};
class QWindows11Style : public QWindowsVistaStyle
{
@@ -55,7 +75,8 @@ protected:
private:
static inline QBrush buttonFillBrush(const QStyleOption *option);
static inline QColor buttonLabelColor(const QStyleOption *option, int colorSchemeIndex);
- static inline QColor editSublineColor(const QStyleOption *option, int colorSchemeIndex);
+ void drawLineEditFrame(QPainter *p, const QStyleOption *o) const;
+ inline QColor winUI3Color(enum WINUI3Color col) const;
private:
Q_DISABLE_COPY_MOVE(QWindows11Style)