summaryrefslogtreecommitdiffstats
path: root/src/plugins/styles
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/styles')
-rw-r--r--src/plugins/styles/CMakeLists.txt4
-rw-r--r--src/plugins/styles/android/CMakeLists.txt5
-rw-r--r--src/plugins/styles/android/qandroidstyle.cpp2
-rw-r--r--src/plugins/styles/mac/CMakeLists.txt7
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm142
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h1
-rw-r--r--src/plugins/styles/modernwindows/CMakeLists.txt (renamed from src/plugins/styles/windowsvista/CMakeLists.txt)11
-rw-r--r--src/plugins/styles/modernwindows/main.cpp36
-rw-r--r--src/plugins/styles/modernwindows/modernwindowsstyles.json3
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp2174
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style_p.h70
-rw-r--r--src/plugins/styles/modernwindows/qwindowsthemedata.cpp (renamed from src/plugins/styles/windowsvista/qwindowsthemedata.cpp)0
-rw-r--r--src/plugins/styles/modernwindows/qwindowsthemedata_p.h (renamed from src/plugins/styles/windowsvista/qwindowsthemedata_p.h)0
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistaanimation.cpp (renamed from src/plugins/styles/windowsvista/qwindowsvistaanimation.cpp)0
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistaanimation_p.h (renamed from src/plugins/styles/windowsvista/qwindowsvistaanimation_p.h)0
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle.cpp (renamed from src/plugins/styles/windowsvista/qwindowsvistastyle.cpp)209
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle_p.h (renamed from src/plugins/styles/windowsvista/qwindowsvistastyle_p.h)4
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h (renamed from src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h)3
-rw-r--r--src/plugins/styles/windowsvista/main.cpp28
-rw-r--r--src/plugins/styles/windowsvista/windowsvistastyle.json3
20 files changed, 2430 insertions, 272 deletions
diff --git a/src/plugins/styles/CMakeLists.txt b/src/plugins/styles/CMakeLists.txt
index db7790ae4e..b809042c14 100644
--- a/src/plugins/styles/CMakeLists.txt
+++ b/src/plugins/styles/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from styles.pro.
-
if(QT_FEATURE_style_android)
add_subdirectory(android)
endif()
@@ -10,5 +8,5 @@ if(QT_FEATURE_style_mac)
add_subdirectory(mac)
endif()
if(QT_FEATURE_style_windowsvista)
- add_subdirectory(windowsvista)
+ add_subdirectory(modernwindows)
endif()
diff --git a/src/plugins/styles/android/CMakeLists.txt b/src/plugins/styles/android/CMakeLists.txt
index fc4e6190b8..b8bda6fd5f 100644
--- a/src/plugins/styles/android/CMakeLists.txt
+++ b/src/plugins/styles/android/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from android.pro.
-
#####################################################################
## QAndroidStylePlugin Plugin:
#####################################################################
@@ -18,6 +16,3 @@ qt_internal_add_plugin(QAndroidStylePlugin
Qt::Gui
Qt::WidgetsPrivate
)
-
-#### Keys ignored in scope 1:.:.:android.pro:<TRUE>:
-# DISTFILES = "androidstyle.json"
diff --git a/src/plugins/styles/android/qandroidstyle.cpp b/src/plugins/styles/android/qandroidstyle.cpp
index ef625c6eb5..64940ed4d8 100644
--- a/src/plugins/styles/android/qandroidstyle.cpp
+++ b/src/plugins/styles/android/qandroidstyle.cpp
@@ -1209,7 +1209,7 @@ const QAndroidStyle::AndroidDrawable * QAndroidStyle::AndroidStateDrawable::best
int QAndroidStyle::AndroidStateDrawable::extractState(const QVariantMap &value)
{
- QStyle::State state = QStyle::State_Enabled | QStyle::State_Active;;
+ QStyle::State state = QStyle::State_Enabled | QStyle::State_Active;
for (auto it = value.cbegin(), end = value.cend(); it != end; ++it) {
const QString &key = it.key();
bool val = it.value().toString() == QLatin1String("true");
diff --git a/src/plugins/styles/mac/CMakeLists.txt b/src/plugins/styles/mac/CMakeLists.txt
index 2f3184855c..9dc8d01cc7 100644
--- a/src/plugins/styles/mac/CMakeLists.txt
+++ b/src/plugins/styles/mac/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from mac.pro.
-
#####################################################################
## QMacStylePlugin Plugin:
#####################################################################
@@ -21,12 +19,7 @@ qt_internal_add_plugin(QMacStylePlugin
Qt::WidgetsPrivate
)
-#### Keys ignored in scope 1:.:.:mac.pro:<TRUE>:
-# DISTFILES = "macstyle.json"
-
-# special case begin
set_target_properties(QMacStylePlugin
PROPERTIES
DISABLE_PRECOMPILE_HEADERS ON
)
-# special case end
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index e6d23ae6a4..3f57f284e6 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -160,46 +160,7 @@ const int pushButtonBevelRectOffsets[3] = {
QVector<QPointer<QObject> > QMacStylePrivate::scrollBars;
-bool isDarkMode() { return QGuiApplicationPrivate::platformTheme()->appearance() == Qt::Appearance::Dark; }
-
-// Title bar gradient colors for Lion were determined by inspecting PSDs exported
-// using CoreUI's CoreThemeDocument; there is no public API to retrieve them
-
-static QLinearGradient titlebarGradientActive()
-{
- static QLinearGradient darkGradient = [](){
- QLinearGradient gradient;
- // FIXME: colors are chosen somewhat arbitrarily and could be fine-tuned,
- // or ideally determined by calling a native API.
- gradient.setColorAt(0, QColor(47, 47, 47));
- return gradient;
- }();
- static QLinearGradient lightGradient = [](){
- QLinearGradient gradient;
- gradient.setColorAt(0, QColor(235, 235, 235));
- gradient.setColorAt(0.5, QColor(210, 210, 210));
- gradient.setColorAt(0.75, QColor(195, 195, 195));
- gradient.setColorAt(1, QColor(180, 180, 180));
- return gradient;
- }();
- return isDarkMode() ? darkGradient : lightGradient;
-}
-
-static QLinearGradient titlebarGradientInactive()
-{
- static QLinearGradient darkGradient = [](){
- QLinearGradient gradient;
- gradient.setColorAt(1, QColor(42, 42, 42));
- return gradient;
- }();
- static QLinearGradient lightGradient = [](){
- QLinearGradient gradient;
- gradient.setColorAt(0, QColor(250, 250, 250));
- gradient.setColorAt(1, QColor(225, 225, 225));
- return gradient;
- }();
- return isDarkMode() ? darkGradient : lightGradient;
-}
+bool isDarkMode() { return QGuiApplicationPrivate::platformTheme()->colorScheme() == Qt::ColorScheme::Dark; }
#if QT_CONFIG(tabwidget)
/*
@@ -429,12 +390,7 @@ static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl)
if (sl->minimum >= sl->maximum)
return false;
- // NSSlider seems to cache values based on tracking and the last layout of the
- // NSView, resulting in incorrect knob rects that break the interaction with
- // multiple sliders. So completely reinitialize the slider.
- const auto controlSize = slider.controlSize;
- [slider initWithFrame:sl->rect.toCGRect()];
- slider.controlSize = controlSize;
+ slider.frame = sl->rect.toCGRect();
slider.minValue = sl->minimum;
slider.maxValue = sl->maximum;
@@ -465,14 +421,6 @@ static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl)
// the cell for its metrics and to draw itself.
[slider layoutSubtreeIfNeeded];
- if (sl->state & QStyle::State_Sunken) {
- const CGRect knobRect = [slider.cell knobRectFlipped:slider.isFlipped];
- CGPoint pressPoint;
- pressPoint.x = CGRectGetMidX(knobRect);
- pressPoint.y = CGRectGetMidY(knobRect);
- [slider.cell startTrackingAt:pressPoint inView:slider];
- }
-
return true;
}
@@ -2208,25 +2156,6 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
case PM_FocusFrameHMargin:
ret = qt_mac_aqua_get_metric(FocusRectOutset);
break;
- case PM_DialogButtonsSeparator:
- ret = -5;
- break;
- case PM_DialogButtonsButtonHeight: {
- QSize sz;
- ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz);
- if (sz == QSize(-1, -1))
- ret = 32;
- else
- ret = sz.height();
- break; }
- case PM_DialogButtonsButtonWidth: {
- QSize sz;
- ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz);
- if (sz == QSize(-1, -1))
- ret = 70;
- else
- ret = sz.width();
- break; }
case PM_MenuBarHMargin:
ret = 8;
@@ -2553,10 +2482,13 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
case PM_ToolBarFrameWidth:
ret = 1;
break;
- case PM_ScrollView_ScrollBarOverlap:
- ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay ?
- pixelMetric(PM_ScrollBarExtent, opt, widget) : 0;
+ case PM_ScrollView_ScrollBarOverlap: {
+ const QStyle *realStyle = widget ? widget->style() : proxy();
+ ret = realStyle->styleHint(SH_ScrollBar_Transient, opt, widget)
+ ? realStyle->pixelMetric(PM_ScrollBarExtent, opt, widget)
+ : 0;
break;
+ }
default:
ret = QCommonStyle::pixelMetric(metric, opt, widget);
break;
@@ -2892,9 +2824,6 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
case SH_TabBar_AllowWheelScrolling:
ret = false;
break;
- case SH_SupportsDarkAppearance:
- ret = true;
- break;
default:
ret = QCommonStyle::styleHint(sh, opt, w, hret);
break;
@@ -3424,17 +3353,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
} break;
#endif // QT_CONFIG(tabbar)
case PE_PanelStatusBar: {
- // Fill the status bar with the titlebar gradient.
- QLinearGradient linearGrad;
- if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) {
- linearGrad = titlebarGradientActive();
- } else {
- linearGrad = titlebarGradientInactive();
- }
-
- linearGrad.setStart(0, opt->rect.top());
- linearGrad.setFinalStop(0, opt->rect.bottom());
- p->fillRect(opt->rect, linearGrad);
+ p->fillRect(opt->rect, opt->palette.window());
// Draw the black separator line at the top of the status bar.
if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active))
@@ -3915,6 +3834,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
frameRect = frameRect.adjusted(-1, 0, 1, 0);
}
break;
+ case QStyleOptionTab::Moving: // Moving tab treated like End
case QStyleOptionTab::End:
// Pressed state hack: tweak adjustments in preparation for flip below
if (isSelected || tabDirection == QMacStylePrivate::West)
@@ -4115,12 +4035,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
// fill title bar background
- QLinearGradient linearGrad;
- linearGrad.setStart(QPointF(0, 0));
- linearGrad.setFinalStop(QPointF(0, 2 * effectiveRect.height()));
- linearGrad.setColorAt(0, opt->palette.button().color());
- linearGrad.setColorAt(1, opt->palette.dark().color());
- p->fillRect(effectiveRect, linearGrad);
+ p->fillRect(effectiveRect, opt->palette.window());
// draw horizontal line at bottom
p->setPen(opt->palette.dark().color());
@@ -4135,7 +4050,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
titleRect.width());
const auto text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width());
- proxy()->drawItemText(p, titleRect, Qt::AlignCenter, dwOpt->palette,
+ proxy()->drawItemText(p, titleRect, Qt::AlignCenter | Qt::TextHideMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, text, QPalette::WindowText);
}
p->restore();
@@ -5195,7 +5110,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const auto cocoaSize = d->effectiveAquaSizeConstrain(opt, widget);
const CGFloat maxExpandScale = expandedKnobWidths[cocoaSize] / knobWidths[cocoaSize];
- const bool isTransient = proxy()->styleHint(SH_ScrollBar_Transient, opt, widget);
+ const QStyle *realStyle = widget ? widget->style() : proxy();
+ const bool isTransient = realStyle->styleHint(SH_ScrollBar_Transient, opt, widget);
if (!isTransient)
d->stopAnimation(opt->styleObject);
bool wasActive = false;
@@ -5384,6 +5300,15 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const CGRect knobRect = [slider.cell knobRectFlipped:slider.isFlipped];
pressPoint.x = CGRectGetMidX(knobRect);
pressPoint.y = CGRectGetMidY(knobRect);
+
+ // The only way to tell a NSSlider/NSSliderCell to render as pressed
+ // is to start tracking. But this API has some weird behaviors that
+ // we have to account for. First of all, the pressed state will not
+ // be visually reflected unless we start tracking twice. And secondly
+ // if we don't track twice, the state of one render-pass will affect
+ // the render pass of other sliders, even if we set up the shared
+ // NSSlider with a new slider value.
+ [slider.cell startTrackingAt:pressPoint inView:slider];
[slider.cell startTrackingAt:pressPoint inView:slider];
}
@@ -5488,8 +5413,12 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
});
- if (isPressed)
+ if (isPressed) {
+ // We stop twice to be on the safe side, even if one seems to be enough.
+ // See startTracking above for why we do this.
+ [slider.cell stopTracking:pressPoint at:pressPoint inView:slider mouseIsUp:NO];
[slider.cell stopTracking:pressPoint at:pressPoint inView:slider mouseIsUp:NO];
+ }
}
break;
#if QT_CONFIG(spinbox)
@@ -5551,7 +5480,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const auto cw = QMacStylePrivate::CocoaControl(ct, cs);
auto *cc = static_cast<NSControl *>(d->cocoaControl(cw));
cc.enabled = isEnabled;
- QRectF frameRect = cw.adjustedControlFrame(combo->rect);;
+ QRectF frameRect = cw.adjustedControlFrame(combo->rect);
if (cw.type == QMacStylePrivate::Button_PopupButton) {
// Non-editable QComboBox
auto *pb = static_cast<NSPopUpButton *>(cc);
@@ -5624,16 +5553,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
const auto frameAdjust = 1.0 / p->device()->devicePixelRatio();
const auto innerFrameRect = outerFrameRect.adjusted(frameAdjust, frameAdjust, -frameAdjust, 0);
QPainterPath innerFramePath = d->windowPanelPath(innerFrameRect);
- if (isActive) {
- QLinearGradient g;
- g.setStart(QPointF(0, 0));
- g.setFinalStop(QPointF(0, 2 * opt->rect.height()));
- g.setColorAt(0, opt->palette.button().color());
- g.setColorAt(1, opt->palette.dark().color());
- p->fillPath(innerFramePath, g);
- } else {
- p->fillPath(innerFramePath, opt->palette.button());
- }
+ p->fillPath(innerFramePath, opt->palette.button());
if (titlebar->subControls & (SC_TitleBarCloseButton
| SC_TitleBarMaxButton
@@ -5980,7 +5900,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
qreal controlsSpacing = lastButtonRect.right() + titleBarButtonSpacing;
if (!titlebar->icon.isNull()) {
const auto iconSize = proxy()->pixelMetric(PM_SmallIconSize);
- const auto actualIconSize = titlebar->icon.actualSize(QSize(iconSize, iconSize)).width();;
+ const auto actualIconSize = titlebar->icon.actualSize(QSize(iconSize, iconSize)).width();
controlsSpacing += actualIconSize + titleBarIconTitleSpacing;
}
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index e3f1e39d19..0dcfce2f0c 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -12,7 +12,6 @@
#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
#include <QtCore/qmath.h>
-#include <QtCore/qpair.h>
#include <QtCore/qpointer.h>
#include <QtCore/qtextstream.h>
diff --git a/src/plugins/styles/windowsvista/CMakeLists.txt b/src/plugins/styles/modernwindows/CMakeLists.txt
index ab87ad4186..985bce3a2d 100644
--- a/src/plugins/styles/windowsvista/CMakeLists.txt
+++ b/src/plugins/styles/modernwindows/CMakeLists.txt
@@ -1,18 +1,17 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from windowsvista.pro.
-
#####################################################################
## QWindowsVistaStylePlugin Plugin:
#####################################################################
-qt_internal_add_plugin(QWindowsVistaStylePlugin
- OUTPUT_NAME qwindowsvistastyle
+qt_internal_add_plugin(QModernWindowsStylePlugin
+ OUTPUT_NAME qmodernwindowsstyle
PLUGIN_TYPE styles
SOURCES
main.cpp
qwindowsvistastyle.cpp qwindowsvistastyle_p.h
+ qwindows11style.cpp qwindows11style_p.h
qwindowsvistastyle_p_p.h
qwindowsvistaanimation.cpp qwindowsvistaanimation_p.h
qwindowsthemedata.cpp qwindowsthemedata_p.h
@@ -23,8 +22,6 @@ qt_internal_add_plugin(QWindowsVistaStylePlugin
uxtheme
Qt::Core
Qt::Gui
+ Qt::GuiPrivate
Qt::WidgetsPrivate
)
-
-#### Keys ignored in scope 1:.:.:windowsvista.pro:<TRUE>:
-# DISTFILES = "windowsvistastyle.json"
diff --git a/src/plugins/styles/modernwindows/main.cpp b/src/plugins/styles/modernwindows/main.cpp
new file mode 100644
index 0000000000..a4d8e60385
--- /dev/null
+++ b/src/plugins/styles/modernwindows/main.cpp
@@ -0,0 +1,36 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <QtWidgets/qstyleplugin.h>
+#include <QtCore/qoperatingsystemversion.h>
+#include "qwindowsvistastyle_p.h"
+#include "qwindows11style_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QModernWindowsStylePlugin : public QStylePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "modernwindowsstyles.json")
+public:
+ QStyle *create(const QString &key) override;
+};
+
+QStyle *QModernWindowsStylePlugin::create(const QString &key)
+{
+ bool isWin11OrAbove = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11;
+ if (isWin11OrAbove && key.compare(QLatin1String("windows11"), Qt::CaseInsensitive) == 0) {
+ return new QWindows11Style();
+ } else if (!isWin11OrAbove && key.compare(QLatin1String("windows11"), Qt::CaseInsensitive) == 0) {
+ qWarning("QWindows11Style: Style is only supported on Windows11 and above");
+ return new QWindowsVistaStyle();
+ } else if (key.compare(QLatin1String("windowsvista"), Qt::CaseInsensitive) == 0) {
+ return new QWindowsVistaStyle();
+ }
+ return nullptr;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/plugins/styles/modernwindows/modernwindowsstyles.json b/src/plugins/styles/modernwindows/modernwindowsstyles.json
new file mode 100644
index 0000000000..e9cef558e8
--- /dev/null
+++ b/src/plugins/styles/modernwindows/modernwindowsstyles.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "windowsvista", "windows11" ]
+}
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
new file mode 100644
index 0000000000..63663c74aa
--- /dev/null
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -0,0 +1,2174 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qwindows11style_p.h"
+#include <qstylehints.h>
+#include <private/qstyleanimation_p.h>
+#include <private/qstylehelper_p.h>
+#include <private/qapplication_p.h>
+#include <qstyleoption.h>
+#include <qpainter.h>
+#include <QGraphicsDropShadowEffect>
+#include <QLatin1StringView>
+#include <QtWidgets/qcombobox.h>
+#include <QtWidgets/qcommandlinkbutton.h>
+#include <QtWidgets/qgraphicsview.h>
+#include <QtWidgets/qlistview.h>
+#include <QtWidgets/qmenu.h>
+#if QT_CONFIG(mdiarea)
+#include <QtWidgets/qmdiarea.h>
+#endif
+#include <QtWidgets/qtextedit.h>
+#include <QtWidgets/qtreeview.h>
+
+#include "qdrawutil.h"
+#include <chrono>
+
+QT_BEGIN_NAMESPACE
+
+const static int topLevelRoundingRadius = 8; //Radius for toplevel items like popups for round corners
+const static int secondLevelRoundingRadius = 4; //Radius for second level items like hovered menu item round corners
+constexpr QLatin1StringView originalWidthProperty("_q_windows11_style_original_width");
+
+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
+};
+
+const static QColor WINUI3ColorsLight [] {
+ QColor(0x00,0x00,0x00,0x09), //subtleHighlightColor
+ QColor(0x00,0x00,0x00,0x06), //subtlePressedColor
+ QColor(0x00,0x00,0x00,0x0F), //frameColorLight
+ QColor(0x00,0x00,0x00,0x9c), //frameColorStrong
+ QColor(0x00,0x00,0x00,0x72), //controlStrongFill
+ QColor(0x00,0x00,0x00,0x29), //controlStrokeSecondary
+ QColor(0x00,0x00,0x00,0x14), //controlStrokePrimary
+ QColor(0xF9,0xF9,0xF9,0x00), //controlFillTertiary
+ QColor(0xF9,0xF9,0xF9,0x80), //controlFillSecondary
+ QColor(0xFF,0xFF,0xFF,0xFF), //menuPanelFill
+ QColor(0xFF,0xFF,0xFF,0xFF), //textOnAccentPrimary
+ QColor(0xFF,0xFF,0xFF,0x7F), //textOnAccentSecondary
+ QColor(0x00,0x00,0x00,0x7F), //controlTextSecondary
+ QColor(0x00,0x00,0x00,0x66), //controlStrokeOnAccentSecondary
+ QColor(0xFF,0xFF,0xFF,0xFF), //controlFillSolid
+ QColor(0x75,0x75,0x75,0x66), //surfaceStroke
+};
+
+const static QColor WINUI3ColorsDark[] {
+ QColor(0xFF,0xFF,0xFF,0x0F), //subtleHighlightColor
+ QColor(0xFF,0xFF,0xFF,0x0A), //subtlePressedColor
+ QColor(0xFF,0xFF,0xFF,0x12), //frameColorLight
+ QColor(0xFF,0xFF,0xFF,0x8B), //frameColorStrong
+ QColor(0xFF,0xFF,0xFF,0x8B), //controlStrongFill
+ QColor(0xFF,0xFF,0xFF,0x18), //controlStrokeSecondary
+ QColor(0xFF,0xFF,0xFF,0x12), //controlStrokePrimary
+ QColor(0xF9,0xF9,0xF9,0x00), //controlFillTertiary
+ QColor(0xF9,0xF9,0xF9,0x80), //controlFillSecondary
+ QColor(0x0F,0x0F,0x0F,0xFF), //menuPanelFill
+ QColor(0x00,0x00,0x00,0xFF), //textOnAccentPrimary
+ QColor(0x00,0x00,0x00,0x80), //textOnAccentSecondary
+ QColor(0xFF,0xFF,0xFF,0x87), //controlTextSecondary
+ QColor(0xFF,0xFF,0xFF,0x14), //controlStrokeOnAccentSecondary
+ QColor(0x45,0x45,0x45,0xFF), //controlFillSolid
+ QColor(0x75,0x75,0x75,0x66), //surfaceStroke
+};
+
+const static QColor* WINUI3Colors[] {
+ WINUI3ColorsLight,
+ WINUI3ColorsDark
+};
+
+const QColor shellCloseButtonColor(0xC4,0x2B,0x1C,0xFF); //Color of close Button in Titlebar
+
+#if QT_CONFIG(toolbutton)
+static void drawArrow(const QStyle *style, const QStyleOptionToolButton *toolbutton,
+ const QRect &rect, QPainter *painter, const QWidget *widget = nullptr)
+{
+ QStyle::PrimitiveElement pe;
+ switch (toolbutton->arrowType) {
+ case Qt::LeftArrow:
+ pe = QStyle::PE_IndicatorArrowLeft;
+ break;
+ case Qt::RightArrow:
+ pe = QStyle::PE_IndicatorArrowRight;
+ break;
+ case Qt::UpArrow:
+ pe = QStyle::PE_IndicatorArrowUp;
+ break;
+ case Qt::DownArrow:
+ pe = QStyle::PE_IndicatorArrowDown;
+ break;
+ default:
+ return;
+ }
+ QStyleOption arrowOpt = *toolbutton;
+ arrowOpt.rect = rect;
+ style->drawPrimitive(pe, &arrowOpt, painter, widget);
+}
+#endif // QT_CONFIG(toolbutton)
+/*!
+ \class QWindows11Style
+ \brief The QWindows11Style class provides a look and feel suitable for applications on Microsoft Windows 11.
+ \since 6.6
+ \ingroup appearance
+ \inmodule QtWidgets
+ \internal
+
+ \warning This style is only available on the Windows 11 platform and above.
+
+ \sa QWindows11Style QWindowsVistaStyle, QMacStyle, QFusionStyle
+*/
+
+/*!
+ Constructs a QWindows11Style object.
+*/
+QWindows11Style::QWindows11Style() : QWindowsVistaStyle(*new QWindows11StylePrivate)
+{
+ highContrastTheme = QGuiApplicationPrivate::styleHints->colorScheme() == Qt::ColorScheme::Unknown;
+ colorSchemeIndex = QGuiApplicationPrivate::styleHints->colorScheme() == Qt::ColorScheme::Light ? 0 : 1;
+}
+
+/*!
+ \internal
+ Constructs a QWindows11Style object.
+*/
+QWindows11Style::QWindows11Style(QWindows11StylePrivate &dd) : QWindowsVistaStyle(dd)
+{
+ highContrastTheme = QGuiApplicationPrivate::styleHints->colorScheme() == Qt::ColorScheme::Unknown;
+ colorSchemeIndex = QGuiApplicationPrivate::styleHints->colorScheme() == Qt::ColorScheme::Light ? 0 : 1;
+}
+
+/*!
+ Destructor.
+*/
+QWindows11Style::~QWindows11Style() = default;
+
+/*!
+ \internal
+ see drawPrimitive for comments on the animation support
+
+ */
+void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
+ QPainter *painter, const QWidget *widget) const
+{
+ QWindows11StylePrivate *d = const_cast<QWindows11StylePrivate*>(d_func());
+
+ State state = option->state;
+ SubControls sub = option->subControls;
+ State flags = option->state;
+ if (widget && widget->testAttribute(Qt::WA_UnderMouse) && widget->isActiveWindow())
+ flags |= State_MouseOver;
+
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+ if (d->transitionsEnabled()) {
+ if (control == CC_Slider) {
+ if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ QObject *styleObject = option->styleObject; // Can be widget or qquickitem
+
+ QRectF thumbRect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ auto center = thumbRect.center();
+ const qreal outerRadius = qMin(8.0, (slider->orientation == Qt::Horizontal ? thumbRect.height() / 2.0 : thumbRect.width() / 2.0) - 1);
+
+ thumbRect.setWidth(outerRadius);
+ thumbRect.setHeight(outerRadius);
+ thumbRect.moveCenter(center);
+ QPointF cursorPos = widget ? widget->mapFromGlobal(QCursor::pos()) : QPointF();
+ bool isInsideHandle = thumbRect.contains(cursorPos);
+
+ bool oldIsInsideHandle = styleObject->property("_q_insidehandle").toBool();
+ int oldState = styleObject->property("_q_stylestate").toInt();
+ int oldActiveControls = styleObject->property("_q_stylecontrols").toInt();
+
+ QRectF oldRect = styleObject->property("_q_stylerect").toRect();
+ styleObject->setProperty("_q_insidehandle", isInsideHandle);
+ styleObject->setProperty("_q_stylestate", int(option->state));
+ styleObject->setProperty("_q_stylecontrols", int(option->activeSubControls));
+ styleObject->setProperty("_q_stylerect", option->rect);
+ if (option->styleObject->property("_q_end_radius").isNull())
+ option->styleObject->setProperty("_q_end_radius", outerRadius * 0.43);
+
+ bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
+ || ((oldIsInsideHandle) != (isInsideHandle))
+ || oldActiveControls != int(option->activeSubControls))
+ && state & State_Enabled);
+
+ if (oldRect != option->rect) {
+ doTransition = false;
+ d->stopAnimation(styleObject);
+ styleObject->setProperty("_q_inner_radius", outerRadius * 0.43);
+ }
+
+ if (doTransition) {
+ QNumberStyleAnimation *t = new QNumberStyleAnimation(styleObject);
+ t->setStartValue(styleObject->property("_q_inner_radius").toFloat());
+ if (state & State_Sunken)
+ t->setEndValue(outerRadius * 0.29);
+ else if (isInsideHandle)
+ t->setEndValue(outerRadius * 0.71);
+ else
+ t->setEndValue(outerRadius * 0.43);
+
+ styleObject->setProperty("_q_end_radius", t->endValue());
+
+ t->setStartTime(d->animationTime());
+ t->setDuration(150);
+ d->startAnimation(t);
+ }
+ }
+ }
+ }
+
+ switch (control) {
+#if QT_CONFIG(spinbox)
+ case CC_SpinBox:
+ if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ if (sb->frame && (sub & SC_SpinBoxFrame)) {
+ painter->save();
+ QRegion clipRegion = option->rect;
+ clipRegion -= option->rect.adjusted(2, 2, -2, -2);
+ painter->setClipRegion(clipRegion);
+ QColor lineColor = state & State_HasFocus ? option->palette.accent().color() : QColor(0,0,0);
+ painter->setPen(QPen(lineColor));
+ painter->drawLine(option->rect.bottomLeft() + QPointF(7,-0.5), option->rect.bottomRight() + QPointF(-7,-0.5));
+ painter->restore();
+ }
+ QRectF frameRect = option->rect;
+ frameRect.adjust(0.5,0.5,-0.5,-0.5);
+ QBrush fillColor = option->palette.brush(QPalette::Base);
+ painter->setBrush(fillColor);
+ painter->setPen(QPen(highContrastTheme == true ? sb->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]));
+ painter->drawRoundedRect(frameRect.adjusted(2,2,-2,-2), secondLevelRoundingRadius, secondLevelRoundingRadius);
+ QPoint mousePos = widget ? widget->mapFromGlobal(QCursor::pos()) : QPoint();
+ QColor hoverColor = WINUI3Colors[colorSchemeIndex][subtleHighlightColor];
+ if (sub & SC_SpinBoxEditField) {
+ QRect rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, widget).adjusted(0, 0, 0, 1);
+ if (rect.contains(mousePos) && !(state & State_HasFocus)) {
+ QBrush fillColor = QBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ painter->setBrush(fillColor);
+ painter->setPen(Qt::NoPen);
+ painter->drawRoundedRect(option->rect.adjusted(2,2,-2,-2), secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+ }
+ if (sub & SC_SpinBoxUp) {
+ QRect rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
+ float scale = rect.width() >= 16 ? 1.0 : rect.width()/16.0;
+ if (rect.contains(mousePos)) {
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(QBrush(hoverColor));
+ painter->drawRoundedRect(rect.adjusted(1,1,-1,-1),secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+ painter->save();
+ painter->translate(rect.center());
+ painter->scale(scale,scale);
+ painter->translate(-rect.center());
+ painter->setFont(assetFont);
+ painter->setPen(sb->palette.buttonText().color());
+ painter->setBrush(Qt::NoBrush);
+ painter->drawText(rect,"\uE018", Qt::AlignVCenter | Qt::AlignHCenter);
+ painter->restore();
+ }
+ if (sub & SC_SpinBoxDown) {
+ QRect rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ float scale = rect.width() >= 16 ? 1.0 : rect.width()/16.0;
+ if (rect.contains(mousePos)) {
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(QBrush(hoverColor));
+ painter->drawRoundedRect(rect.adjusted(1,1,-1,-1), secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+ painter->save();
+ painter->translate(rect.center());
+ painter->scale(scale,scale);
+ painter->translate(-rect.center());
+ painter->setFont(assetFont);
+ painter->setPen(sb->palette.buttonText().color());
+ painter->setBrush(Qt::NoBrush);
+ painter->drawText(rect,"\uE019", Qt::AlignVCenter | Qt::AlignHCenter);
+ painter->restore();
+ }
+ }
+ break;
+#endif // QT_CONFIG(spinbox)
+#if QT_CONFIG(slider)
+ case CC_Slider:
+ if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ QRectF slrect = slider->rect;
+ QRegion tickreg = slrect.toRect();
+
+ if (sub & SC_SliderGroove) {
+ QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ QRectF handleRect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ QPointF handlePos = handleRect.center();
+ QRectF leftRect;
+ QRectF rightRect;
+
+ if (slider->orientation == Qt::Horizontal) {
+ rect = QRect(slrect.left(), rect.center().y() - 2, slrect.width() - 5, 4);
+ leftRect = QRect(rect.left(), rect.top(), (handlePos.x() - rect.left()), rect.height());
+ rightRect = QRect(handlePos.x(), rect.top(), (rect.width() - handlePos.x()), rect.height());
+ } else {
+ rect = QRect(rect.center().x() - 2, slrect.top(), 4, slrect.height() - 5);
+ rightRect = QRect(rect.left(), rect.top(), rect.width(), (handlePos.y() - rect.top()));
+ leftRect = QRect(rect.left(), handlePos.y(), rect.width(), (rect.height() - handlePos.y()));
+ }
+
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(option->palette.accent());
+ painter->drawRoundedRect(leftRect,1,1);
+ painter->setBrush(QBrush(WINUI3Colors[colorSchemeIndex][controlStrongFill]));
+ painter->drawRoundedRect(rightRect,1,1);
+
+ painter->setPen(QPen(highContrastTheme == true ? slider->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawRoundedRect(leftRect,1.5,1.5);
+ painter->drawRoundedRect(rightRect,1.5,1.5);
+
+ tickreg -= rect.toRect();
+ }
+ if (sub & SC_SliderTickmarks) {
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int ticks = slider->tickPosition;
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int interval = slider->tickInterval;
+ if (interval <= 0) {
+ interval = slider->singleStep;
+ if (QStyle::sliderPositionFromValue(slider->minimum, slider->maximum, interval,
+ available)
+ - QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
+ 0, available) < 3)
+ interval = slider->pageStep;
+ }
+ if (!interval)
+ interval = 1;
+ int fudge = len / 2;
+ int pos;
+ int bothOffset = (ticks & QSlider::TicksAbove && ticks & QSlider::TicksBelow) ? 1 : 0;
+ painter->setPen(slider->palette.text().color());
+ QVarLengthArray<QLine, 32> lines;
+ int v = slider->minimum;
+ while (v <= slider->maximum + 1) {
+ if (v == slider->maximum + 1 && interval == 1)
+ break;
+ const int v_ = qMin(v, slider->maximum);
+ int tickLength = (v_ == slider->minimum || v_ >= slider->maximum) ? 4 : 3;
+ pos = QStyle::sliderPositionFromValue(slider->minimum, slider->maximum,
+ v_, available) + fudge;
+ if (slider->orientation == Qt::Horizontal) {
+ if (ticks & QSlider::TicksAbove) {
+ lines.append(QLine(pos, tickOffset - 1 - bothOffset,
+ pos, tickOffset - 1 - bothOffset - tickLength));
+ }
+
+ if (ticks & QSlider::TicksBelow) {
+ lines.append(QLine(pos, tickOffset + thickness + bothOffset,
+ pos, tickOffset + thickness + bothOffset + tickLength));
+ }
+ } else {
+ if (ticks & QSlider::TicksAbove) {
+ lines.append(QLine(tickOffset - 1 - bothOffset, pos,
+ tickOffset - 1 - bothOffset - tickLength, pos));
+ }
+
+ if (ticks & QSlider::TicksBelow) {
+ lines.append(QLine(tickOffset + thickness + bothOffset, pos,
+ tickOffset + thickness + bothOffset + tickLength, pos));
+ }
+ }
+ // in the case where maximum is max int
+ int nextInterval = v + interval;
+ if (nextInterval < v)
+ break;
+ v = nextInterval;
+ }
+ if (!lines.isEmpty()) {
+ painter->save();
+ painter->translate(slrect.topLeft());
+ painter->drawLines(lines.constData(), lines.size());
+ painter->restore();
+ }
+ }
+ if (sub & SC_SliderHandle) {
+ if (const auto *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ const QRectF rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ const QPointF center = rect.center();
+
+ const QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation*>(d->animation(option->styleObject));
+
+ if (animation != nullptr)
+ option->styleObject->setProperty("_q_inner_radius", animation->currentValue());
+ else
+ option->styleObject->setProperty("_q_inner_radius", option->styleObject->property("_q_end_radius"));
+
+ const qreal outerRadius = qMin(8.0,(slider->orientation == Qt::Horizontal ? rect.height() / 2.0 : rect.width() / 2.0) - 1);
+ const float innerRadius = option->styleObject->property("_q_inner_radius").toFloat();
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(QBrush(WINUI3Colors[colorSchemeIndex][controlFillSolid]));
+ painter->drawEllipse(center, outerRadius, outerRadius);
+ painter->setBrush(option->palette.accent());
+ painter->drawEllipse(center, innerRadius, innerRadius);
+
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawEllipse(center, outerRadius + 0.5, outerRadius + 0.5);
+ painter->drawEllipse(center, innerRadius + 0.5, innerRadius + 0.5);
+ }
+ }
+ if (slider->state & State_HasFocus) {
+ QStyleOptionFocusRect fropt;
+ fropt.QStyleOption::operator=(*slider);
+ fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ }
+ }
+ break;
+#endif
+#if QT_CONFIG(combobox)
+ case CC_ComboBox:
+ if (const QStyleOptionComboBox *combobox = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
+ QBrush fillColor = combobox->palette.brush(QPalette::Base);
+ QRectF rect = option->rect.adjusted(2,2,-2,-2);
+ painter->setBrush(fillColor);
+ painter->setPen(Qt::NoPen);
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+
+ // In case the QComboBox is hovered overdraw the background with a alpha mask to
+ // highlight the QComboBox.
+ if (state & State_MouseOver) {
+ fillColor = QBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ painter->setBrush(fillColor);
+ painter->setPen(Qt::NoPen);
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+
+ rect.adjust(0.5,0.5,-0.5,-0.5);
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(highContrastTheme == true ? 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,"\uE019", Qt::AlignVCenter | Qt::AlignHCenter);
+ }
+ if (combobox->editable) {
+ QColor lineColor = state & State_HasFocus ? option->palette.accent().color() : QColor(0,0,0);
+ painter->setPen(QPen(lineColor));
+ painter->drawLine(rect.bottomLeft() + QPoint(2,1), rect.bottomRight() + QPoint(-2,1));
+ if (state & State_HasFocus)
+ painter->drawLine(rect.bottomLeft() + QPoint(3,2), rect.bottomRight() + QPoint(-3,2));
+ }
+ }
+ break;
+#endif // QT_CONFIG(combobox)
+ case QStyle::CC_ScrollBar:
+ if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ QRectF rect = scrollbar->rect;
+ QPointF center = rect.center();
+
+ if (scrollbar->orientation == Qt::Vertical && rect.width()>24)
+ rect.marginsRemoved(QMargins(0,2,2,2));
+ else if (scrollbar->orientation == Qt::Horizontal && rect.height()>24)
+ rect.marginsRemoved(QMargins(2,0,2,2));
+
+ if (state & State_MouseOver) {
+ if (scrollbar->orientation == Qt::Vertical && rect.width()>24)
+ rect.setWidth(rect.width()/2);
+ else if (scrollbar->orientation == Qt::Horizontal && rect.height()>24)
+ rect.setHeight(rect.height()/2);
+ rect.moveCenter(center);
+ painter->setBrush(scrollbar->palette.base());
+ painter->setPen(Qt::NoPen);
+ painter->drawRoundedRect(rect, topLevelRoundingRadius, topLevelRoundingRadius);
+
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(WINUI3Colors[colorSchemeIndex][frameColorLight]);
+ painter->drawRoundedRect(rect.marginsRemoved(QMarginsF(0.5,0.5,0.5,0.5)), topLevelRoundingRadius + 0.5, topLevelRoundingRadius + 0.5);
+ }
+ if (sub & SC_ScrollBarSlider) {
+ QRectF rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ QPointF center = rect.center();
+ if (flags & State_MouseOver) {
+ if (scrollbar->orientation == Qt::Vertical)
+ rect.setWidth(rect.width()/2);
+ else
+ rect.setHeight(rect.height()/2);
+ }
+ else {
+ if (scrollbar->orientation == Qt::Vertical)
+ rect.setWidth(1);
+ else
+ rect.setHeight(1);
+
+ }
+ rect.moveCenter(center);
+ painter->setBrush(Qt::gray);
+ painter->setPen(Qt::NoPen);
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+ if (sub & SC_ScrollBarAddLine) {
+ QRectF rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
+ if (flags & State_MouseOver) {
+ painter->setFont(QFont("Segoe Fluent Icons",6));
+ painter->setPen(Qt::gray);
+ if (scrollbar->orientation == Qt::Vertical)
+ painter->drawText(rect,"\uEDDC", Qt::AlignVCenter | Qt::AlignHCenter);
+ else
+ painter->drawText(rect,"\uEDDA", Qt::AlignVCenter | Qt::AlignHCenter);
+ }
+ }
+ if (sub & SC_ScrollBarSubLine) {
+ QRectF rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
+ if (flags & State_MouseOver) {
+ painter->setPen(Qt::gray);
+ if (scrollbar->orientation == Qt::Vertical)
+ painter->drawText(rect,"\uEDDB", Qt::AlignVCenter | Qt::AlignHCenter);
+ else
+ painter->drawText(rect,"\uEDD9", Qt::AlignVCenter | Qt::AlignHCenter);
+ }
+ }
+ }
+ break;
+ case CC_TitleBar:
+ if (const auto* titlebar = qstyleoption_cast<const QStyleOptionTitleBar*>(option)) {
+ painter->setPen(Qt::NoPen);
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]));
+ painter->setBrush(titlebar->palette.button());
+ painter->drawRect(titlebar->rect);
+
+ // draw title
+ QRect textRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarLabel, widget);
+ painter->setPen(titlebar->palette.text().color());
+ // Note workspace also does elliding but it does not use the correct font
+ QString title = painter->fontMetrics().elidedText(titlebar->text, Qt::ElideRight, textRect.width() - 14);
+ painter->drawText(textRect.adjusted(1, 1, 1, 1), title, QTextOption(Qt::AlignHCenter | Qt::AlignVCenter));
+
+ QFont buttonFont = QFont(assetFont);
+ buttonFont.setPointSize(8);
+ // min button
+ if ((titlebar->subControls & SC_TitleBarMinButton) && (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
+ !(titlebar->titleBarState& Qt::WindowMinimized)) {
+ const QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarMinButton, widget);
+ if (minButtonRect.isValid()) {
+ bool hover = (titlebar->activeSubControls & SC_TitleBarMinButton) && (titlebar->state & State_MouseOver);
+ if (hover)
+ painter->fillRect(minButtonRect,WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ const QString textToDraw("\uE921");
+ painter->setPen(QPen(titlebar->palette.text().color()));
+ painter->setFont(buttonFont);
+ painter->drawText(minButtonRect, Qt::AlignVCenter | Qt::AlignHCenter, textToDraw);
+ }
+ }
+ // max button
+ if ((titlebar->subControls & SC_TitleBarMaxButton) && (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
+ !(titlebar->titleBarState & Qt::WindowMaximized)) {
+ const QRectF maxButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarMaxButton, widget);
+ if (maxButtonRect.isValid()) {
+ bool hover = (titlebar->activeSubControls & SC_TitleBarMaxButton) && (titlebar->state & State_MouseOver);
+ if (hover)
+ painter->fillRect(maxButtonRect,WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ const QString textToDraw("\uE922");
+ painter->setPen(QPen(titlebar->palette.text().color()));
+ painter->setFont(buttonFont);
+ painter->drawText(maxButtonRect, Qt::AlignVCenter | Qt::AlignHCenter, textToDraw);
+ }
+ }
+
+ // close button
+ if ((titlebar->subControls & SC_TitleBarCloseButton) && (titlebar->titleBarFlags & Qt::WindowSystemMenuHint)) {
+ const QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarCloseButton, widget);
+ if (closeButtonRect.isValid()) {
+ bool hover = (titlebar->activeSubControls & SC_TitleBarCloseButton) && (titlebar->state & State_MouseOver);
+ if (hover)
+ painter->fillRect(closeButtonRect,shellCloseButtonColor);
+ const QString textToDraw("\uE8BB");
+ painter->setPen(QPen(hover ? titlebar->palette.highlightedText().color() : titlebar->palette.text().color()));
+ painter->setFont(buttonFont);
+ painter->drawText(closeButtonRect, Qt::AlignVCenter | Qt::AlignHCenter, textToDraw);
+ }
+ }
+
+ // normalize button
+ if ((titlebar->subControls & SC_TitleBarNormalButton) &&
+ (((titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
+ (titlebar->titleBarState & Qt::WindowMinimized)) ||
+ ((titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
+ (titlebar->titleBarState & Qt::WindowMaximized)))) {
+ const QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarNormalButton, widget);
+ if (normalButtonRect.isValid()) {
+ bool hover = (titlebar->activeSubControls & SC_TitleBarNormalButton) && (titlebar->state & State_MouseOver);
+ if (hover)
+ painter->fillRect(normalButtonRect,WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ const QString textToDraw("\uE923");
+ painter->setPen(QPen(titlebar->palette.text().color()));
+ painter->setFont(buttonFont);
+ painter->drawText(normalButtonRect, Qt::AlignVCenter | Qt::AlignHCenter, textToDraw);
+ }
+ }
+
+ // context help button
+ if (titlebar->subControls & SC_TitleBarContextHelpButton
+ && (titlebar->titleBarFlags & Qt::WindowContextHelpButtonHint)) {
+ const QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarContextHelpButton, widget);
+ if (contextHelpButtonRect.isValid()) {
+ bool hover = (titlebar->activeSubControls & SC_TitleBarCloseButton) && (titlebar->state & State_MouseOver);
+ if (hover)
+ painter->fillRect(contextHelpButtonRect,WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ const QString textToDraw("\uE897");
+ painter->setPen(QPen(titlebar->palette.text().color()));
+ painter->setFont(buttonFont);
+ painter->drawText(contextHelpButtonRect, Qt::AlignVCenter | Qt::AlignHCenter, textToDraw);
+ }
+ }
+
+ // shade button
+ if (titlebar->subControls & SC_TitleBarShadeButton && (titlebar->titleBarFlags & Qt::WindowShadeButtonHint)) {
+ const QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarShadeButton, widget);
+ if (shadeButtonRect.isValid()) {
+ bool hover = (titlebar->activeSubControls & SC_TitleBarShadeButton) && (titlebar->state & State_MouseOver);
+ if (hover)
+ painter->fillRect(shadeButtonRect,WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ const QString textToDraw("\uE010");
+ painter->setPen(QPen(titlebar->palette.text().color()));
+ painter->setFont(buttonFont);
+ painter->drawText(shadeButtonRect, Qt::AlignVCenter | Qt::AlignHCenter, textToDraw);
+ }
+ }
+
+ // unshade button
+ if (titlebar->subControls & SC_TitleBarUnshadeButton && (titlebar->titleBarFlags & Qt::WindowShadeButtonHint)) {
+ const QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarUnshadeButton, widget);
+ if (unshadeButtonRect.isValid()) {
+ bool hover = (titlebar->activeSubControls & SC_TitleBarUnshadeButton) && (titlebar->state & State_MouseOver);
+ if (hover)
+ painter->fillRect(unshadeButtonRect,WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ const QString textToDraw("\uE011");
+ painter->setPen(QPen(titlebar->palette.text().color()));
+ painter->setFont(buttonFont);
+ painter->drawText(unshadeButtonRect, Qt::AlignVCenter | Qt::AlignHCenter, textToDraw);
+ }
+ }
+
+ // window icon for system menu
+ if ((titlebar->subControls & SC_TitleBarSysMenu) && (titlebar->titleBarFlags & Qt::WindowSystemMenuHint)) {
+ const QRect iconRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarSysMenu, widget);
+ if (iconRect.isValid()) {
+ if (!titlebar->icon.isNull()) {
+ titlebar->icon.paint(painter, iconRect);
+ } else {
+ QStyleOption tool = *titlebar;
+ QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16);
+ tool.rect = iconRect;
+ painter->save();
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
+ painter->restore();
+ }
+ }
+ }
+ }
+ break;
+ default:
+ QWindowsVistaStyle::drawComplexControl(control, option, painter, widget);
+ }
+ painter->restore();
+}
+
+void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
+ QPainter *painter,
+ const QWidget *widget) const {
+ QWindows11StylePrivate *d = const_cast<QWindows11StylePrivate*>(d_func());
+
+ int state = option->state;
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+ if (d->transitionsEnabled() && (element == PE_IndicatorCheckBox || element == PE_IndicatorRadioButton)) {
+ QObject *styleObject = option->styleObject; // Can be widget or qquickitem
+ if (styleObject) {
+ int oldState = styleObject->property("_q_stylestate").toInt();
+ styleObject->setProperty("_q_stylestate", int(option->state));
+ styleObject->setProperty("_q_stylerect", option->rect);
+ bool doTransition = (((state & State_Sunken) != (oldState & State_Sunken)
+ || ((state & State_MouseOver) != (oldState & State_MouseOver))
+ || (state & State_On) != (oldState & State_On))
+ && state & State_Enabled);
+ if (doTransition) {
+ if (element == PE_IndicatorRadioButton) {
+ QNumberStyleAnimation *t = new QNumberStyleAnimation(styleObject);
+ t->setStartValue(styleObject->property("_q_inner_radius").toFloat());
+ t->setEndValue(7.0f);
+ if (option->state & State_Sunken)
+ t->setEndValue(2.0f);
+ else if (option->state & State_MouseOver && !(option->state & State_On))
+ t->setEndValue(7.0f);
+ else if (option->state & State_MouseOver && (option->state & State_On))
+ t->setEndValue(5.0f);
+ else if (option->state & State_On)
+ t->setEndValue(4.0f);
+ styleObject->setProperty("_q_end_radius", t->endValue());
+ t->setStartTime(d->animationTime());
+ t->setDuration(150);
+ d->startAnimation(t);
+ }
+ else if (element == PE_IndicatorCheckBox) {
+ if ((oldState & State_Off && state & State_On) || (oldState & State_NoChange && state & State_On)) {
+ QNumberStyleAnimation *t = new QNumberStyleAnimation(styleObject);
+ t->setStartValue(0.0f);
+ t->setEndValue(1.0f);
+ t->setStartTime(d->animationTime());
+ t->setDuration(150);
+ d->startAnimation(t);
+ }
+ }
+ }
+ }
+ } else if (!d->transitionsEnabled() && element == PE_IndicatorRadioButton) {
+ QObject *styleObject = option->styleObject; // Can be widget or qquickitem
+ if (styleObject) {
+ styleObject->setProperty("_q_end_radius",7.0);
+ if (option->state & State_Sunken)
+ styleObject->setProperty("_q_end_radius",2.0);
+ else if (option->state & State_MouseOver && !(option->state & State_On))
+ styleObject->setProperty("_q_end_radius",7.0);
+ else if (option->state & State_MouseOver && (option->state & State_On))
+ styleObject->setProperty("_q_end_radius",5.0);
+ else if (option->state & State_On)
+ styleObject->setProperty("_q_end_radius",4.0);
+ }
+ }
+
+ switch (element) {
+ case PE_PanelTipLabel: {
+ QRectF tipRect = option->rect.marginsRemoved(QMargins(1,1,1,1));
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(option->palette.toolTipBase());
+ painter->drawRoundedRect(tipRect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+
+ painter->setPen(highContrastTheme == true ? option->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
+ painter->setBrush(Qt::NoBrush);
+ painter->drawRoundedRect(tipRect.marginsAdded(QMarginsF(0.5,0.5,0.5,0.5)), secondLevelRoundingRadius, secondLevelRoundingRadius);
+ break;
+ }
+ case PE_FrameTabWidget:
+ if (const QStyleOptionTabWidgetFrame *frame = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(option)) {
+ QRectF frameRect = frame->rect.marginsRemoved(QMargins(0,0,0,0));
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(frame->palette.base());
+ painter->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+
+ painter->setPen(highContrastTheme == true ? frame->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
+ painter->setBrush(Qt::NoBrush);
+ painter->drawRoundedRect(frameRect.marginsRemoved(QMarginsF(0.5,0.5,0.5,0.5)), secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+ break;
+ case PE_FrameGroupBox:
+ if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+ QRectF frameRect = frame->rect;
+ frameRect.adjust(0.5,0.5,-0.5,-0.5);
+ painter->setPen(highContrastTheme == true ? frame->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong]);
+ painter->setBrush(Qt::NoBrush);
+ if (frame->features & QStyleOptionFrame::Flat) {
+ QRect fr = frame->rect;
+ QPoint p1(fr.x(), fr.y() + 1);
+ QPoint p2(fr.x() + fr.width(), p1.y());
+ painter->drawLine(p1,p2);
+ } else {
+ painter->drawRoundedRect(frameRect.marginsRemoved(QMargins(1,1,1,1)), secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+ }
+ break;
+ case PE_IndicatorCheckBox:
+ {
+ QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation*>(d->animation(option->styleObject));
+ QFontMetrics fm(assetFont);
+
+ QRectF rect = option->rect;
+ QPointF center = QPointF(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2);
+ rect.setWidth(15);
+ rect.setHeight(15);
+ rect.moveCenter(center);
+
+ float clipWidth = animation != nullptr ? animation->currentValue() : 1.0f;
+ QRectF clipRect = fm.boundingRect("\uE001");
+ clipRect.moveCenter(center);
+ clipRect.setLeft(rect.x() + (rect.width() - clipRect.width()) / 2.0);
+ clipRect.setWidth(clipWidth * clipRect.width());
+
+
+ QBrush fillBrush = (option->state & State_On || option->state & State_NoChange) ? option->palette.accent() : option->palette.window();
+ if (state & State_MouseOver && (option->state & State_On || option->state & State_NoChange))
+ fillBrush.setColor(fillBrush.color().lighter(107));
+ else if (state & State_MouseOver && !(option->state & State_On || option->state & State_NoChange))
+ fillBrush.setColor(fillBrush.color().darker(107));
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(fillBrush);
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius, Qt::AbsoluteSize);
+
+ painter->setPen(QPen(highContrastTheme == true ? option->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong]));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius + 0.5, secondLevelRoundingRadius + 0.5, Qt::AbsoluteSize);
+
+ painter->setFont(assetFont);
+ painter->setPen(option->palette.highlightedText().color());
+ painter->setBrush(option->palette.highlightedText().color());
+ if (option->state & State_On)
+ painter->drawText(clipRect, Qt::AlignVCenter | Qt::AlignLeft,"\uE001");
+ else if (option->state & State_NoChange)
+ painter->drawText(rect, Qt::AlignVCenter | Qt::AlignHCenter,"\uE108");
+ }
+ break;
+
+ case PE_IndicatorRadioButton:
+ {
+ if (option->styleObject->property("_q_end_radius").isNull())
+ option->styleObject->setProperty("_q_end_radius", option->state & State_On ? 4.0f :7.0f);
+ QNumberStyleAnimation* animation = qobject_cast<QNumberStyleAnimation*>(d->animation(option->styleObject));
+ if (animation != nullptr)
+ option->styleObject->setProperty("_q_inner_radius", animation->currentValue());
+ else
+ option->styleObject->setProperty("_q_inner_radius", option->styleObject->property("_q_end_radius"));
+ int innerRadius = option->styleObject->property("_q_inner_radius").toFloat();
+
+ QRectF rect = option->rect;
+ QPointF center = QPoint(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2);
+ rect.setWidth(15);
+ rect.setHeight(15);
+ rect.moveCenter(center);
+ QRectF innerRect = rect;
+ innerRect.setWidth(8);
+ innerRect.setHeight(8);
+ innerRect.moveCenter(center);
+
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(option->palette.accent());
+ if (option->state & State_MouseOver && option->state & State_Enabled)
+ painter->setBrush(QBrush(option->palette.accent().color().lighter(107)));
+ painter->drawEllipse(center, 7, 7);
+
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][frameColorStrong]));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawEllipse(center, 7.5, 7.5);
+
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(QBrush(option->palette.window()));
+ painter->drawEllipse(center,innerRadius, innerRadius);
+
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][frameColorStrong]));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawEllipse(center,innerRadius + 0.5, innerRadius + 0.5);
+
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(QBrush(option->palette.window()));
+ if (option->state & State_MouseOver && option->state & State_Enabled)
+ painter->setBrush(QBrush(option->palette.window().color().darker(107)));
+ painter->drawEllipse(center,innerRadius, innerRadius);
+ }
+ break;
+ case PE_PanelButtonBevel:{
+ QRectF rect = option->rect.marginsRemoved(QMargins(2,2,2,2));
+ rect.adjust(-0.5,-0.5,0.5,0.5);
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][controlStrokePrimary]));
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+
+ rect = option->rect.marginsRemoved(QMargins(2,2,2,2));
+ painter->setPen(Qt::NoPen);
+ if (!(state & (State_Raised)))
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][controlFillTertiary]);
+ else if (state & State_MouseOver)
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][controlFillSecondary]);
+ else
+ painter->setBrush(option->palette.button());
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]));
+ if (state & State_Raised)
+ painter->drawLine(rect.bottomLeft() + QPoint(2,1), rect.bottomRight() + QPoint(-2,1));
+ }
+ break;
+ case PE_FrameDefaultButton:
+ painter->setPen(option->palette.accent().color());
+ painter->setBrush(Qt::NoBrush);
+ painter->drawRoundedRect(option->rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ break;
+ case QStyle::PE_FrameMenu:
+ break;
+ case QStyle::PE_PanelMenu: {
+ QRect rect = option->rect;
+ QPen pen(WINUI3Colors[colorSchemeIndex][frameColorLight]);
+ painter->save();
+ painter->setPen(pen);
+ painter->setBrush(QBrush(WINUI3Colors[colorSchemeIndex][menuPanelFill]));
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->drawRoundedRect(rect.marginsRemoved(QMargins(2,2,12,2)), topLevelRoundingRadius, topLevelRoundingRadius);
+ painter->restore();
+ break;
+ }
+ case PE_PanelLineEdit:
+ if (widget && widget->objectName() == "qt_spinbox_lineedit")
+ break;
+ if (const auto *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+ QRectF frameRect = option->rect;
+ frameRect.adjust(0.5,0.5,-0.5,-0.5);
+ QBrush fillColor = option->palette.brush(QPalette::Base);
+ painter->setBrush(fillColor);
+ 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)) {
+ fillColor = QBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ painter->setBrush(fillColor);
+ painter->setPen(Qt::NoPen);
+ painter->drawRoundedRect(frameRect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+ if (panel->lineWidth > 0)
+ proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
+ }
+ break;
+ case PE_FrameLineEdit: {
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(highContrastTheme == true ? option->palette.buttonText().color() : QPen(WINUI3Colors[colorSchemeIndex][frameColorLight]));
+ painter->drawRoundedRect(option->rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ QRegion clipRegion = option->rect;
+ clipRegion -= option->rect.adjusted(2, 2, -2, -2);
+ painter->setClipRegion(clipRegion);
+ QColor lineColor = state & State_HasFocus ? option->palette.accent().color() : QColor(0,0,0);
+ painter->setPen(QPen(lineColor));
+ painter->drawLine(option->rect.bottomLeft() + QPointF(1,0.5), option->rect.bottomRight() + QPointF(-1,0.5));
+ }
+ break;
+ case PE_Frame: {
+ if (const auto *frame = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+ if (frame->frameShape == QFrame::NoFrame)
+ break;
+ QRectF rect = option->rect.adjusted(1,1,-1,-1);
+ if (widget && widget->inherits("QComboBoxPrivateContainer")) {
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][menuPanelFill]);
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+
+ }
+ painter->setBrush(option->palette.base());
+ painter->setPen(Qt::NoPen);
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][frameColorLight]));
+ painter->drawRoundedRect(rect.marginsRemoved(QMarginsF(0.5,0.5,0.5,0.5)), secondLevelRoundingRadius, secondLevelRoundingRadius);
+
+ if (qobject_cast<const QTextEdit *>(widget)) {
+ QRegion clipRegion = option->rect;
+ QColor lineColor = state & State_HasFocus ? option->palette.accent().color() : QColor(0,0,0,255);
+ painter->setPen(QPen(lineColor));
+ painter->drawLine(option->rect.bottomLeft() + QPoint(1,-1), option->rect.bottomRight() + QPoint(-1,-1));
+ }
+ }
+ break;
+ }
+ case QStyle::PE_PanelItemViewRow:
+ if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
+ if ((vopt->state & State_Selected || vopt->state & State_MouseOver) && vopt->showDecorationSelected) {
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ painter->setPen(Qt::NoPen);
+ painter->drawRoundedRect(vopt->rect.marginsRemoved(QMargins(0,2,-2,2)),2,2);
+ const int offset = qobject_cast<const QTreeView *>(widget) ? 2 : 0;
+ if (vopt->viewItemPosition == QStyleOptionViewItem::Beginning && option->state & State_Selected) {
+ painter->setPen(QPen(option->palette.accent().color()));
+ painter->drawLine(option->rect.x(),option->rect.y()+offset,option->rect.x(),option->rect.y() + option->rect.height()-2);
+ painter->drawLine(option->rect.x()+1,option->rect.y()+2,option->rect.x()+1,option->rect.y() + option->rect.height()-2);
+ }
+ }
+ }
+ break;
+ case QStyle::PE_Widget: {
+#if QT_CONFIG(dialogbuttonbox)
+ const QDialogButtonBox *buttonBox = nullptr;
+ if (qobject_cast<const QMessageBox *> (widget))
+ buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_msgbox_buttonbox"));
+#if QT_CONFIG(inputdialog)
+ else if (qobject_cast<const QInputDialog *> (widget))
+ buttonBox = widget->findChild<const QDialogButtonBox *>(QLatin1String("qt_inputdlg_buttonbox"));
+#endif // QT_CONFIG(inputdialog)
+ if (buttonBox) {
+ painter->fillRect(option->rect,option->palette.window());
+ }
+#endif
+ break;
+ }
+ case QStyle::PE_FrameWindow:
+ if (const auto *frm = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+
+ QRectF rect= option->rect;
+ int fwidth = int((frm->lineWidth + frm->midLineWidth) / QWindowsStylePrivate::nativeMetricScaleFactor(widget));
+
+ QRectF bottomLeftCorner = QRectF(rect.left() + 1.0,
+ rect.bottom() - 1.0 - secondLevelRoundingRadius,
+ secondLevelRoundingRadius,
+ secondLevelRoundingRadius);
+ QRectF bottomRightCorner = QRectF(rect.right() - 1.0 - secondLevelRoundingRadius,
+ rect.bottom() - 1.0 - secondLevelRoundingRadius,
+ secondLevelRoundingRadius,
+ secondLevelRoundingRadius);
+
+ //Draw Mask
+ if (widget != nullptr) {
+ QBitmap mask(widget->width(), widget->height());
+ mask.clear();
+
+ QPainter maskPainter(&mask);
+ maskPainter.setRenderHint(QPainter::Antialiasing);
+ maskPainter.setBrush(Qt::color1);
+ maskPainter.setPen(Qt::NoPen);
+ maskPainter.drawRoundedRect(option->rect,secondLevelRoundingRadius,secondLevelRoundingRadius);
+ const_cast<QWidget*>(widget)->setMask(mask);
+ }
+
+ //Draw Window
+ painter->setPen(QPen(frm->palette.base(), fwidth));
+ painter->drawLine(QPointF(rect.left(), rect.top()),
+ QPointF(rect.left(), rect.bottom() - fwidth));
+ painter->drawLine(QPointF(rect.left() + fwidth, rect.bottom()),
+ QPointF(rect.right() - fwidth, rect.bottom()));
+ painter->drawLine(QPointF(rect.right(), rect.top()),
+ QPointF(rect.right(), rect.bottom() - fwidth));
+
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]));
+ painter->drawLine(QPointF(rect.left() + 0.5, rect.top() + 0.5),
+ QPointF(rect.left() + 0.5, rect.bottom() - 0.5 - secondLevelRoundingRadius));
+ painter->drawLine(QPointF(rect.left() + 0.5 + secondLevelRoundingRadius, rect.bottom() - 0.5),
+ QPointF(rect.right() - 0.5 - secondLevelRoundingRadius, rect.bottom() - 0.5));
+ painter->drawLine(QPointF(rect.right() - 0.5, rect.top() + 1.5),
+ QPointF(rect.right() - 0.5, rect.bottom() - 0.5 - secondLevelRoundingRadius));
+
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(frm->palette.base());
+ painter->drawPie(bottomRightCorner.marginsAdded(QMarginsF(2.5,2.5,0.0,0.0)),
+ 270 * 16,90 * 16);
+ painter->drawPie(bottomLeftCorner.marginsAdded(QMarginsF(0.0,2.5,2.5,0.0)),
+ -90 * 16,-90 * 16);
+
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][surfaceStroke]));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawArc(bottomRightCorner,
+ 0 * 16,-90 * 16);
+ painter->drawArc(bottomLeftCorner,
+ -90 * 16,-90 * 16);
+ }
+ break;
+ default:
+ QWindowsVistaStyle::drawPrimitive(element, option, painter, widget);
+ }
+ painter->restore();
+}
+
+/*!
+ \internal
+*/
+void QWindows11Style::drawControl(ControlElement element, const QStyleOption *option,
+ QPainter *painter, const QWidget *widget) const
+{
+ Q_D(const QWindows11Style);
+ QRect rect(option->rect);
+ State flags = option->state;
+
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+ switch (element) {
+ case QStyle::CE_TabBarTabShape:
+ if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(option)) {
+ QRectF tabRect = tab->rect.marginsRemoved(QMargins(2,2,0,0));
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(tab->palette.base());
+ if (tab->state & State_MouseOver){
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ } else if (tab->state & State_Selected) {
+ painter->setBrush(tab->palette.base());
+ } else {
+ painter->setBrush(tab->palette.window());
+ }
+ painter->drawRoundedRect(tabRect,2,2);
+
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(highContrastTheme == true ? tab->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
+ painter->drawRoundedRect(tabRect.adjusted(0.5,0.5,-0.5,-0.5),2,2);
+
+ }
+ break;
+ case CE_ToolButtonLabel:
+ if (const QStyleOptionToolButton *toolbutton
+ = qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
+ QRect rect = toolbutton->rect;
+ int shiftX = 0;
+ int shiftY = 0;
+ if (toolbutton->state & (State_Sunken | State_On)) {
+ shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
+ shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
+ }
+ // Arrow type always overrules and is always shown
+ bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow;
+ if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty())
+ || toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) {
+ int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
+ if (!proxy()->styleHint(SH_UnderlineShortcut, toolbutton, widget))
+ alignment |= Qt::TextHideMnemonic;
+ rect.translate(shiftX, shiftY);
+ painter->setFont(toolbutton->font);
+ const QString text = d->toolButtonElideText(toolbutton, rect, alignment);
+ if (toolbutton->state & State_Raised || toolbutton->palette.isBrushSet(QPalette::Current, QPalette::ButtonText))
+ painter->setPen(QPen(toolbutton->palette.buttonText().color()));
+ else
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][controlTextSecondary]));
+ proxy()->drawItemText(painter, rect, alignment, toolbutton->palette,
+ toolbutton->state & State_Enabled, text);
+ } else {
+ QPixmap pm;
+ QSize pmSize = toolbutton->iconSize;
+ if (!toolbutton->icon.isNull()) {
+ QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off;
+ QIcon::Mode mode;
+ if (!(toolbutton->state & State_Enabled))
+ mode = QIcon::Disabled;
+ else if ((toolbutton->state & State_MouseOver) && (toolbutton->state & State_AutoRaise))
+ mode = QIcon::Active;
+ else
+ mode = QIcon::Normal;
+ pm = toolbutton->icon.pixmap(toolbutton->rect.size().boundedTo(toolbutton->iconSize), painter->device()->devicePixelRatio(),
+ mode, state);
+ pmSize = pm.size() / pm.devicePixelRatio();
+ }
+
+ if (toolbutton->toolButtonStyle != Qt::ToolButtonIconOnly) {
+ painter->setFont(toolbutton->font);
+ QRect pr = rect,
+ tr = rect;
+ int alignment = Qt::TextShowMnemonic;
+ if (!proxy()->styleHint(SH_UnderlineShortcut, toolbutton, widget))
+ alignment |= Qt::TextHideMnemonic;
+
+ if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
+ pr.setHeight(pmSize.height() + 4); //### 4 is currently hardcoded in QToolButton::sizeHint()
+ tr.adjust(0, pr.height() - 1, 0, -1);
+ pr.translate(shiftX, shiftY);
+ if (!hasArrow) {
+ proxy()->drawItemPixmap(painter, pr, Qt::AlignCenter, pm);
+ } else {
+ drawArrow(proxy(), toolbutton, pr, painter, widget);
+ }
+ alignment |= Qt::AlignCenter;
+ } else {
+ pr.setWidth(pmSize.width() + 4); //### 4 is currently hardcoded in QToolButton::sizeHint()
+ tr.adjust(pr.width(), 0, 0, 0);
+ pr.translate(shiftX, shiftY);
+ if (!hasArrow) {
+ proxy()->drawItemPixmap(painter, QStyle::visualRect(toolbutton->direction, rect, pr), Qt::AlignCenter, pm);
+ } else {
+ drawArrow(proxy(), toolbutton, pr, painter, widget);
+ }
+ alignment |= Qt::AlignLeft | Qt::AlignVCenter;
+ }
+ tr.translate(shiftX, shiftY);
+ const QString text = d->toolButtonElideText(toolbutton, tr, alignment);
+ if (toolbutton->state & State_Raised || toolbutton->palette.isBrushSet(QPalette::Current, QPalette::ButtonText))
+ painter->setPen(QPen(toolbutton->palette.buttonText().color()));
+ else
+ painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][controlTextSecondary]));
+ proxy()->drawItemText(painter, QStyle::visualRect(toolbutton->direction, rect, tr), alignment, toolbutton->palette,
+ toolbutton->state & State_Enabled, text);
+ } else {
+ rect.translate(shiftX, shiftY);
+ if (hasArrow) {
+ drawArrow(proxy(), toolbutton, rect, painter, widget);
+ } else {
+ proxy()->drawItemPixmap(painter, rect, Qt::AlignCenter, pm);
+ }
+ }
+ }
+ }
+ break;
+ case QStyle::CE_ShapedFrame:
+ if (const QStyleOptionFrame *f = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
+ int frameShape = f->frameShape;
+ int frameShadow = QFrame::Plain;
+ if (f->state & QStyle::State_Sunken)
+ frameShadow = QFrame::Sunken;
+ else if (f->state & QStyle::State_Raised)
+ frameShadow = QFrame::Raised;
+
+ int lw = f->lineWidth;
+ int mlw = f->midLineWidth;
+
+ switch (frameShape) {
+ case QFrame::Box:
+ if (frameShadow == QFrame::Plain)
+ qDrawPlainRoundedRect(painter, f->rect, secondLevelRoundingRadius, secondLevelRoundingRadius, highContrastTheme == true ? f->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong], lw);
+ else
+ qDrawShadeRect(painter, f->rect, f->palette, frameShadow == QFrame::Sunken, lw, mlw);
+ break;
+ case QFrame::Panel:
+ if (frameShadow == QFrame::Plain)
+ qDrawPlainRoundedRect(painter, f->rect, secondLevelRoundingRadius, secondLevelRoundingRadius, highContrastTheme == true ? f->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorStrong], lw);
+ else
+ qDrawShadePanel(painter, f->rect, f->palette, frameShadow == QFrame::Sunken, lw);
+ break;
+ default:
+ QWindowsVistaStyle::drawControl(element, option, painter, widget);
+ }
+ }
+ break;
+ case QStyle::CE_ProgressBarGroove:{
+ if (const QStyleOptionProgressBar* progbaropt = qstyleoption_cast<const QStyleOptionProgressBar*>(option)) {
+ QRect rect = subElementRect(SE_ProgressBarContents, progbaropt, widget);
+ QPointF center = rect.center();
+ if (progbaropt->state & QStyle::State_Horizontal) {
+ rect.setHeight(1);
+ rect.moveTop(center.y());
+ } else {
+ rect.setWidth(1);
+ rect.moveLeft(center.x());
+ }
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(Qt::gray);
+ painter->drawRect(rect);
+ }
+ break;
+ }
+ case QStyle::CE_ProgressBarContents:
+ if (const QStyleOptionProgressBar* progbaropt = qstyleoption_cast<const QStyleOptionProgressBar*>(option)) {
+ const qreal progressBarThickness = 3;
+ const qreal progressBarHalfThickness = progressBarThickness / 2.0;
+ QRectF rect = subElementRect(SE_ProgressBarContents, progbaropt, widget);
+ QRectF originalRect = rect;
+ QPointF center = rect.center();
+ bool isIndeterminate = progbaropt->maximum == 0 && progbaropt->minimum == 0;
+ float fillPercentage = 0;
+ const Qt::Orientation orientation = (progbaropt->state & QStyle::State_Horizontal) ? Qt::Horizontal : Qt::Vertical;
+ const qreal offset = (orientation == Qt::Horizontal && int(rect.height()) % 2 == 0)
+ || (orientation == Qt::Vertical && int(rect.width()) % 2 == 0) ? 0.5 : 0.0;
+
+ if (!isIndeterminate) {
+ fillPercentage = ((float(progbaropt->progress) - float(progbaropt->minimum)) / (float(progbaropt->maximum) - float(progbaropt->minimum)));
+ if (orientation == Qt::Horizontal) {
+ rect.setHeight(progressBarThickness);
+ rect.moveTop(center.y() - progressBarHalfThickness - offset);
+ rect.setWidth(rect.width() * fillPercentage);
+ } else {
+ float oldHeight = rect.height();
+ rect.setWidth(progressBarThickness);
+ rect.moveLeft(center.x() - progressBarHalfThickness - offset);
+ rect.moveTop(oldHeight * (1.0f - fillPercentage));
+ rect.setHeight(oldHeight * fillPercentage);
+ }
+ } else {
+ auto elapsedTime = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
+ fillPercentage = (elapsedTime.time_since_epoch().count() % 5000)/(5000.0f*0.75);
+ if (orientation == Qt::Horizontal) {
+ float barBegin = qMin(qMax(fillPercentage-0.25,0.0) * rect.width(), float(rect.width()));
+ float barEnd = qMin(fillPercentage * rect.width(), float(rect.width()));
+ rect = QRect(QPoint(rect.left() + barBegin, rect.top()), QPoint(rect.left() + barEnd, rect.bottom()));
+ rect.setHeight(progressBarThickness);
+ rect.moveTop(center.y() - progressBarHalfThickness - offset);
+ } else {
+ float barBegin = qMin(qMax(fillPercentage-0.25,0.0) * rect.height(), float(rect.height()));
+ float barEnd = qMin(fillPercentage * rect.height(), float(rect.height()));
+ rect = QRect(QPoint(rect.left(), rect.bottom() - barEnd), QPoint(rect.right(), rect.bottom() - barBegin));
+ rect.setWidth(progressBarThickness);
+ rect.moveLeft(center.x() - progressBarHalfThickness - offset);
+ }
+ const_cast<QWidget*>(widget)->update();
+ }
+ if (progbaropt->invertedAppearance && orientation == Qt::Horizontal)
+ rect.moveLeft(originalRect.width() * (1.0 - fillPercentage));
+ else if (progbaropt->invertedAppearance && orientation == Qt::Vertical)
+ rect.moveBottom(originalRect.height() * fillPercentage);
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(progbaropt->palette.accent());
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+ break;
+ case QStyle::CE_ProgressBarLabel:
+ if (const QStyleOptionProgressBar* progbaropt = qstyleoption_cast<const QStyleOptionProgressBar*>(option)) {
+ QRect rect = subElementRect(SE_ProgressBarLabel, progbaropt, widget);
+ painter->setPen(progbaropt->palette.text().color());
+ painter->drawText(rect, progbaropt->text,Qt::AlignVCenter|Qt::AlignLeft);
+ }
+ break;
+ case CE_PushButtonLabel:
+ if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
+ QRect textRect = btn->rect;
+
+ int tf = Qt::AlignVCenter|Qt::TextShowMnemonic;
+ if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget))
+ tf |= Qt::TextHideMnemonic;
+
+ if (btn->features & QStyleOptionButton::HasMenu) {
+ int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
+ if (btn->direction == Qt::LeftToRight)
+ textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
+ else
+ textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
+ }
+ if (!btn->icon.isNull()) {
+ //Center both icon and text
+ QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
+ if (mode == QIcon::Normal && btn->state & State_HasFocus)
+ mode = QIcon::Active;
+ QIcon::State state = QIcon::Off;
+ if (btn->state & State_On)
+ state = QIcon::On;
+
+ QPixmap pixmap = btn->icon.pixmap(btn->iconSize, painter->device()->devicePixelRatio(), mode, state);
+ int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
+ int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
+ int labelWidth = pixmapWidth;
+ int labelHeight = pixmapHeight;
+ int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
+ if (!btn->text.isEmpty()) {
+ int textWidth = btn->fontMetrics.boundingRect(option->rect, tf, btn->text).width();
+ labelWidth += (textWidth + iconSpacing);
+ }
+
+ QRect iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
+ textRect.y() + (textRect.height() - labelHeight) / 2,
+ pixmapWidth, pixmapHeight);
+
+ iconRect = visualRect(btn->direction, textRect, iconRect);
+
+ if (btn->direction == Qt::RightToLeft) {
+ tf |= Qt::AlignRight;
+ textRect.setRight(iconRect.left() - iconSpacing / 2);
+ } else {
+ tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead
+ textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing / 2);
+ }
+
+ if (btn->state & (State_On | State_Sunken))
+ iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, option, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
+ painter->drawPixmap(iconRect, pixmap);
+ } else {
+ tf |= Qt::AlignHCenter;
+ }
+
+
+ if (btn->state & State_Sunken)
+ painter->setPen(flags & State_On ? QPen(WINUI3Colors[colorSchemeIndex][textOnAccentSecondary]) : QPen(WINUI3Colors[colorSchemeIndex][controlTextSecondary]));
+ else
+ painter->setPen(flags & State_On ? QPen(WINUI3Colors[colorSchemeIndex][textOnAccentPrimary]) : QPen(btn->palette.buttonText().color()));
+ proxy()->drawItemText(painter, textRect, tf, option->palette,btn->state & State_Enabled, btn->text);
+ }
+ break;
+ case CE_PushButtonBevel:
+ if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
+ if (btn->features.testFlag(QStyleOptionButton::Flat)) {
+ painter->setPen(Qt::NoPen);
+ if (flags & (State_Sunken | State_On)) {
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][subtlePressedColor]);
+ }
+ else if (flags & State_MouseOver) {
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ }
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ } else {
+ QRectF rect = btn->rect.marginsRemoved(QMargins(2,2,2,2));
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(flags & State_On ? option->palette.accent() : option->palette.button());
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ if (flags.testFlags(State_Sunken | State_MouseOver)) {
+ if (flags & (State_Sunken))
+ painter->setBrush(flags & State_On ? option->palette.accent().color().lighter(120) : WINUI3Colors[colorSchemeIndex][controlFillTertiary]);
+ else if (flags & State_MouseOver)
+ painter->setBrush(flags & State_On ? option->palette.accent().color().lighter(110) : WINUI3Colors[colorSchemeIndex][controlFillSecondary]);
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+ }
+
+ rect.adjust(0.5,0.5,-0.5,-0.5);
+ painter->setBrush(Qt::NoBrush);
+ painter->setPen(btn->features.testFlag(QStyleOptionButton::DefaultButton) ? QPen(option->palette.accent().color()) : QPen(WINUI3Colors[colorSchemeIndex][controlStrokePrimary]));
+ painter->drawRoundedRect(rect, secondLevelRoundingRadius, secondLevelRoundingRadius);
+
+ painter->setPen(btn->features.testFlag(QStyleOptionButton::DefaultButton) ? QPen(WINUI3Colors[colorSchemeIndex][controlStrokeOnAccentSecondary]) : QPen(WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]));
+ if (flags & State_Raised)
+ painter->drawLine(rect.bottomLeft() + QPointF(4.0,0.0), rect.bottomRight() + QPointF(-4,0.0));
+ }
+ }
+ break;
+ case CE_MenuBarItem:
+ if (const auto *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
+ constexpr int hPadding = 11;
+ constexpr int topPadding = 4;
+ constexpr int bottomPadding = 6;
+ bool active = mbi->state & State_Selected;
+ bool hasFocus = mbi->state & State_HasFocus;
+ bool down = mbi->state & State_Sunken;
+ bool enabled = mbi->state & State_Enabled;
+ QStyleOptionMenuItem newMbi = *mbi;
+ newMbi.font.setPointSize(10);
+ if (enabled && (active || hasFocus)) {
+ if (active && down)
+ painter->setBrushOrigin(painter->brushOrigin() + QPoint(1, 1));
+ if (active && hasFocus) {
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ painter->setPen(Qt::NoPen);
+ QRect rect = mbi->rect.marginsRemoved(QMargins(5,0,5,0));
+ painter->drawRoundedRect(rect,secondLevelRoundingRadius,secondLevelRoundingRadius,Qt::AbsoluteSize);
+ }
+ }
+ newMbi.rect.adjust(hPadding,topPadding,-hPadding,-bottomPadding);
+ painter->setFont(newMbi.font);
+ QCommonStyle::drawControl(element, &newMbi, painter, widget);
+ }
+ break;
+
+#if QT_CONFIG(menu)
+ case CE_MenuEmptyArea:
+ break;
+
+ case CE_MenuItem:
+ if (const auto *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) {
+ int x, y, w, h;
+ menuitem->rect.getRect(&x, &y, &w, &h);
+ int tab = menuitem->reservedShortcutWidth;
+ bool dis = !(menuitem->state & State_Enabled);
+ bool checked = menuitem->checkType != QStyleOptionMenuItem::NotCheckable
+ ? menuitem->checked : false;
+ bool act = menuitem->state & State_Selected;
+
+ // windows always has a check column, regardless whether we have an icon or not
+ int checkcol = qMax<int>(menuitem->maxIconWidth, 32);
+
+ QBrush fill = (act == true && dis == false) ? QBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]) : menuitem->palette.brush(QPalette::Button);
+ painter->setBrush(fill);
+ painter->setPen(Qt::NoPen);
+ QRect rect = menuitem->rect;
+ rect = rect.marginsRemoved(QMargins(2,2,2,2));
+ if (act && dis == false)
+ painter->drawRoundedRect(rect,secondLevelRoundingRadius,secondLevelRoundingRadius,Qt::AbsoluteSize);
+
+ if (menuitem->menuItemType == QStyleOptionMenuItem::Separator){
+ int yoff = 4;
+ painter->setPen(highContrastTheme == true ? menuitem->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
+ painter->drawLine(x, y + yoff, x + w, y + yoff );
+ break;
+ }
+
+ QRect vCheckRect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x(), menuitem->rect.y(), checkcol, menuitem->rect.height()));
+ if (!menuitem->icon.isNull() && checked) {
+ if (act) {
+ qDrawShadePanel(painter, vCheckRect,
+ menuitem->palette, true, 1,
+ &menuitem->palette.brush(QPalette::Button));
+ } else {
+ QBrush fill(menuitem->palette.light().color(), Qt::Dense4Pattern);
+ qDrawShadePanel(painter, vCheckRect, menuitem->palette, true, 1, &fill);
+ }
+ }
+ // On Windows Style, if we have a checkable item and an icon we
+ // draw the icon recessed to indicate an item is checked. If we
+ // have no icon, we draw a checkmark instead.
+ if (!menuitem->icon.isNull()) {
+ QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
+ if (act && !dis)
+ mode = QIcon::Active;
+ QPixmap pixmap;
+ if (checked)
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
+ else
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
+ QRect pmr(QPoint(0, 0), pixmap.deviceIndependentSize().toSize());
+ pmr.moveCenter(vCheckRect.center());
+ painter->setPen(menuitem->palette.text().color());
+ painter->drawPixmap(pmr.topLeft(), pixmap);
+ } else if (checked) {
+ QStyleOptionMenuItem newMi = *menuitem;
+ newMi.state = State_None;
+ if (!dis)
+ newMi.state |= State_Enabled;
+ if (act)
+ newMi.state |= State_On | State_Selected;
+ newMi.rect = visualRect(option->direction, menuitem->rect, QRect(menuitem->rect.x() + QWindowsStylePrivate::windowsItemFrame,
+ menuitem->rect.y() + QWindowsStylePrivate::windowsItemFrame,
+ checkcol - 2 * QWindowsStylePrivate::windowsItemFrame,
+ menuitem->rect.height() - 2 * QWindowsStylePrivate::windowsItemFrame));
+
+ QColor discol;
+ if (dis) {
+ discol = menuitem->palette.text().color();
+ painter->setPen(discol);
+ }
+ int xm = int(QWindowsStylePrivate::windowsItemFrame) + checkcol / 4 + int(QWindowsStylePrivate::windowsItemHMargin);
+ int xpos = menuitem->rect.x() + xm;
+ QRect textRect(xpos, y + QWindowsStylePrivate::windowsItemVMargin,
+ w - xm - QWindowsStylePrivate::windowsRightBorder - tab + 1, h - 2 * QWindowsStylePrivate::windowsItemVMargin);
+ QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
+
+ painter->save();
+ painter->setFont(assetFont);
+ int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
+ text_flags |= Qt::TextHideMnemonic;
+ text_flags |= Qt::AlignLeft;
+
+ const QString textToDraw("\uE001");
+ painter->setPen(option->palette.text().color());
+ painter->drawText(vTextRect, text_flags, textToDraw);
+ painter->restore();
+ }
+ painter->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color());
+
+ QColor discol = menuitem->palette.text().color();
+ if (dis) {
+ discol = menuitem->palette.color(QPalette::Disabled, QPalette::WindowText);
+ painter->setPen(discol);
+ }
+
+ int xm = int(QWindowsStylePrivate::windowsItemFrame) + checkcol + int(QWindowsStylePrivate::windowsItemHMargin);
+ int xpos = menuitem->rect.x() + xm;
+ QRect textRect(xpos, y + QWindowsStylePrivate::windowsItemVMargin,
+ w - xm - QWindowsStylePrivate::windowsRightBorder - tab + 1, h - 2 * QWindowsStylePrivate::windowsItemVMargin);
+ QRect vTextRect = visualRect(option->direction, menuitem->rect, textRect);
+ QStringView s(menuitem->text);
+ if (!s.isEmpty()) { // draw text
+ painter->save();
+ qsizetype t = s.indexOf(u'\t');
+ int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
+ text_flags |= Qt::TextHideMnemonic;
+ text_flags |= Qt::AlignLeft;
+ if (t >= 0) {
+ QRect vShortcutRect = visualRect(option->direction, menuitem->rect,
+ QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
+ const QString textToDraw = s.mid(t + 1).toString();
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
+ painter->setPen(menuitem->palette.light().color());
+ painter->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, textToDraw);
+ painter->setPen(discol);
+ }
+ painter->setPen(menuitem->palette.color(QPalette::Disabled, QPalette::Text));
+ painter->drawText(vShortcutRect, text_flags, textToDraw);
+ s = s.left(t);
+ }
+ QFont font = menuitem->font;
+ if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
+ font.setBold(true);
+ painter->setFont(font);
+ const QString textToDraw = s.left(t).toString();
+ painter->setPen(discol);
+ painter->drawText(vTextRect, text_flags, textToDraw);
+ painter->restore();
+ }
+ if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
+ int dim = (h - 2 * QWindowsStylePrivate::windowsItemFrame) / 2;
+ xpos = x + w - QWindowsStylePrivate::windowsArrowHMargin - QWindowsStylePrivate::windowsItemFrame - dim;
+ QRect vSubMenuRect = visualRect(option->direction, menuitem->rect, QRect(xpos, y + h / 2 - dim / 2, dim, dim));
+ QStyleOptionMenuItem newMI = *menuitem;
+ newMI.rect = vSubMenuRect;
+ newMI.state = dis ? State_None : State_Enabled;
+ if (act)
+ newMI.palette.setColor(QPalette::ButtonText,
+ newMI.palette.highlightedText().color());
+ painter->save();
+ painter->setFont(assetFont);
+ int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
+ text_flags |= Qt::TextHideMnemonic;
+ text_flags |= Qt::AlignLeft;
+ const QString textToDraw("\uE013");
+ painter->setPen(option->palette.text().color());
+ painter->drawText(vSubMenuRect, text_flags, textToDraw);
+ painter->restore();
+ }
+ }
+ break;
+#endif // QT_CONFIG(menu)
+ case CE_MenuBarEmptyArea: {
+ break;
+ }
+ case CE_HeaderEmptyArea:
+ break;
+ case CE_HeaderSection: {
+ if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
+ painter->setPen(Qt::NoPen);
+ painter->setBrush(header->palette.button());
+ painter->drawRect(header->rect);
+
+ painter->setPen(highContrastTheme == true ? header->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
+ painter->setBrush(Qt::NoBrush);
+
+ if (header->position == QStyleOptionHeader::OnlyOneSection) {
+ break;
+ }
+ else if (header->position == QStyleOptionHeader::Beginning) {
+ painter->drawLine(QPointF(option->rect.topRight()) + QPointF(0.5,0.0),
+ QPointF(option->rect.bottomRight()) + QPointF(0.5,0.0));
+ }
+ else if (header->position == QStyleOptionHeader::End) {
+ painter->drawLine(QPointF(option->rect.topLeft()) - QPointF(0.5,0.0),
+ QPointF(option->rect.bottomLeft()) - QPointF(0.5,0.0));
+ } else {
+ painter->drawLine(QPointF(option->rect.topRight()) + QPointF(0.5,0.0),
+ QPointF(option->rect.bottomRight()) + QPointF(0.5,0.0));
+ painter->drawLine(QPointF(option->rect.topLeft()) - QPointF(0.5,0.0),
+ QPointF(option->rect.bottomLeft()) - QPointF(0.5,0.0));
+ }
+ painter->drawLine(QPointF(option->rect.bottomLeft()) + QPointF(0.0,0.5),
+ QPointF(option->rect.bottomRight()) + QPointF(0.0,0.5));
+ }
+ break;
+ }
+ case QStyle::CE_ItemViewItem: {
+ if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
+ if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView *>(widget)) {
+ QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
+ QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
+ QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget);
+
+ QRect rect = vopt->rect;
+
+ painter->setPen(highContrastTheme == true ? vopt->palette.buttonText().color() : WINUI3Colors[colorSchemeIndex][frameColorLight]);
+ if (vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne || vopt->viewItemPosition == QStyleOptionViewItem::Invalid) {
+ } else if (vopt->viewItemPosition == QStyleOptionViewItem::Beginning) {
+ painter->drawLine(QPointF(option->rect.topRight()) + QPointF(0.5,0.0),
+ QPointF(option->rect.bottomRight()) + QPointF(0.5,0.0));
+ } else if (vopt->viewItemPosition == QStyleOptionViewItem::End) {
+ painter->drawLine(QPointF(option->rect.topLeft()) - QPointF(0.5,0.0),
+ QPointF(option->rect.bottomLeft()) - QPointF(0.5,0.0));
+ } else {
+ painter->drawLine(QPointF(option->rect.topRight()) + QPointF(0.5,0.0),
+ QPointF(option->rect.bottomRight()) + QPointF(0.5,0.0));
+ painter->drawLine(QPointF(option->rect.topLeft()) - QPointF(0.5,0.0),
+ QPointF(option->rect.bottomLeft()) - QPointF(0.5,0.0));
+ }
+ painter->setPen(QPen(option->palette.buttonText().color()));
+
+ const bool isTreeView = qobject_cast<const QTreeView *>(widget);
+
+ if ((vopt->state & State_Selected || vopt->state & State_MouseOver) && !(isTreeView && vopt->state & State_MouseOver) && vopt->showDecorationSelected) {
+ painter->setBrush(WINUI3Colors[colorSchemeIndex][subtleHighlightColor]);
+ QWidget *editorWidget = view ? view->indexWidget(view->currentIndex()) : nullptr;
+ if (editorWidget) {
+ QPalette pal = editorWidget->palette();
+ QColor editorBgColor = vopt->backgroundBrush == Qt::NoBrush ? vopt->palette.color(widget->backgroundRole()) : vopt->backgroundBrush.color();
+ editorBgColor.setAlpha(255);
+ pal.setColor(editorWidget->backgroundRole(),editorBgColor);
+ editorWidget->setPalette(pal);
+ }
+ } else {
+ painter->setBrush(vopt->backgroundBrush);
+ }
+ painter->setPen(Qt::NoPen);
+
+ if (vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne || vopt->viewItemPosition == QStyleOptionViewItem::Invalid) {
+ painter->drawRoundedRect(vopt->rect.marginsRemoved(QMargins(2,2,2,2)),secondLevelRoundingRadius,secondLevelRoundingRadius);
+ } else if (vopt->viewItemPosition == QStyleOptionViewItem::Beginning) {
+ painter->drawRoundedRect(rect.marginsRemoved(QMargins(2,2,0,2)),secondLevelRoundingRadius,secondLevelRoundingRadius);
+ } else if (vopt->viewItemPosition == QStyleOptionViewItem::End) {
+ painter->drawRoundedRect(vopt->rect.marginsRemoved(QMargins(0,2,2,2)),secondLevelRoundingRadius,secondLevelRoundingRadius);
+ } else {
+ painter->drawRect(vopt->rect.marginsRemoved(QMargins(0,2,0,2)));
+ }
+
+ // draw the check mark
+ if (vopt->features & QStyleOptionViewItem::HasCheckIndicator) {
+ QStyleOptionViewItem option(*vopt);
+ option.rect = checkRect;
+ option.state = option.state & ~QStyle::State_HasFocus;
+
+ switch (vopt->checkState) {
+ case Qt::Unchecked:
+ option.state |= QStyle::State_Off;
+ break;
+ case Qt::PartiallyChecked:
+ option.state |= QStyle::State_NoChange;
+ break;
+ case Qt::Checked:
+ option.state |= QStyle::State_On;
+ break;
+ }
+ proxy()->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &option, painter, widget);
+ }
+
+ // draw the icon
+ QIcon::Mode mode = QIcon::Normal;
+ if (!(vopt->state & QStyle::State_Enabled))
+ mode = QIcon::Disabled;
+ else if (vopt->state & QStyle::State_Selected)
+ mode = QIcon::Selected;
+ QIcon::State state = vopt->state & QStyle::State_Open ? QIcon::On : QIcon::Off;
+ vopt->icon.paint(painter, iconRect, vopt->decorationAlignment, mode, state);
+
+ painter->setPen(QPen(option->palette.buttonText().color()));
+ if (!view || !view->isPersistentEditorOpen(vopt->index))
+ d->viewItemDrawText(painter, vopt, textRect);
+ if (vopt->state & State_Selected
+ && (vopt->viewItemPosition == QStyleOptionViewItem::Beginning
+ || vopt->viewItemPosition == QStyleOptionViewItem::OnlyOne
+ || vopt->viewItemPosition == QStyleOptionViewItem::Invalid)) {
+ if (const QListView *lv = qobject_cast<const QListView *>(widget);
+ lv && lv->viewMode() != QListView::IconMode) {
+ painter->setPen(QPen(vopt->palette.accent().color()));
+ painter->drawLine(option->rect.x(), option->rect.y() + 2,
+ option->rect.x(),option->rect.y() + option->rect.height() - 2);
+ painter->drawLine(option->rect.x() + 1, option->rect.y() + 2,
+ option->rect.x() + 1,option->rect.y() + option->rect.height() - 2);
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ QWindowsVistaStyle::drawControl(element, option, painter, widget);
+ }
+ painter->restore();
+}
+
+int QWindows11Style::styleHint(StyleHint hint, const QStyleOption *opt,
+ const QWidget *widget, QStyleHintReturn *returnData) const {
+ switch (hint) {
+ case SH_GroupBox_TextLabelColor:
+ if (opt!=nullptr && widget!=nullptr)
+ return opt->palette.text().color().rgba();
+ return 0;
+ case QStyle::SH_ItemView_ShowDecorationSelected:
+ return 1;
+ case QStyle::SH_Slider_AbsoluteSetButtons:
+ return Qt::LeftButton;
+ case QStyle::SH_Slider_PageSetButtons:
+ return 0;
+ default:
+ return QWindowsVistaStyle::styleHint(hint, opt, widget, returnData);
+ }
+}
+
+QRect QWindows11Style::subElementRect(QStyle::SubElement element, const QStyleOption *option,
+ const QWidget *widget) const
+{
+ QRect ret;
+ switch (element) {
+ case QStyle::SE_LineEditContents:
+ ret = option->rect.adjusted(8,0,-8,0);
+ break;
+ case QStyle::SE_ItemViewItemText:
+ if (const auto *item = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
+ const int decorationOffset = item->features.testFlag(QStyleOptionViewItem::HasDecoration) ? item->decorationSize.width() : 0;
+ if (widget && widget->parentWidget()
+ && widget->parentWidget()->inherits("QComboBoxPrivateContainer")) {
+ ret = option->rect.adjusted(decorationOffset + 5, 0, -5, 0);
+ } else {
+ ret = QWindowsVistaStyle::subElementRect(element, option, widget);
+ }
+ } else {
+ ret = QWindowsVistaStyle::subElementRect(element, option, widget);
+ }
+ break;
+ default:
+ ret = QWindowsVistaStyle::subElementRect(element, option, widget);
+ }
+ return ret;
+}
+
+/*!
+ \internal
+ */
+QRect QWindows11Style::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
+ SubControl subControl, const QWidget *widget) const
+{
+ QRect ret;
+
+ switch (control) {
+#if QT_CONFIG(spinbox)
+ case CC_SpinBox:
+ if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ QSize bs;
+ int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ bs.setHeight(qMax(8, spinbox->rect.height() - fw));
+ bs.setWidth(qMin(24.0, spinbox->rect.width()*(1.0/4.0)));
+ int y = fw + spinbox->rect.y();
+ int x, lx, rx;
+ x = spinbox->rect.x() + spinbox->rect.width() - fw - 2 * bs.width();
+ lx = fw;
+ rx = x - fw;
+ switch (subControl) {
+ case SC_SpinBoxUp:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
+ return QRect();
+ ret = QRect(x, y, bs.width(), bs.height());
+ break;
+ case SC_SpinBoxDown:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
+ return QRect();
+ ret = QRect(x + bs.width(), y, bs.width(), bs.height());
+ break;
+ case SC_SpinBoxEditField:
+ if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons) {
+ ret = QRect(lx, fw, spinbox->rect.width() - 2*fw, spinbox->rect.height() - 2*fw);
+ } else {
+ ret = QRect(lx, fw, rx, spinbox->rect.height() - 2*fw);
+ }
+ break;
+ case SC_SpinBoxFrame:
+ ret = spinbox->rect;
+ default:
+ break;
+ }
+ ret = visualRect(spinbox->direction, spinbox->rect, ret);
+ }
+ break;
+ case CC_TitleBar:
+ if (const QStyleOptionTitleBar *titlebar = qstyleoption_cast<const QStyleOptionTitleBar *>(option)) {
+ SubControl sc = subControl;
+ ret = QCommonStyle::subControlRect(control, option, subControl, widget);
+ static constexpr int indent = 3;
+ static constexpr int controlWidthMargin = 2;
+ const int controlHeight = titlebar->rect.height();
+ const int controlWidth = 46;
+ const int iconSize = proxy()->pixelMetric(QStyle::PM_TitleBarButtonIconSize, option, widget);
+ int offset = -(controlWidthMargin + indent);
+
+ bool isMinimized = titlebar->titleBarState & Qt::WindowMinimized;
+ bool isMaximized = titlebar->titleBarState & Qt::WindowMaximized;
+
+ switch (sc) {
+ case SC_TitleBarLabel:
+ if (titlebar->titleBarFlags & (Qt::WindowTitleHint | Qt::WindowSystemMenuHint)) {
+ ret = titlebar->rect;
+ if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint)
+ ret.adjust(iconSize + controlWidthMargin + indent, 0, -controlWidth, 0);
+ if (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint)
+ ret.adjust(0, 0, -controlWidth, 0);
+ if (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint)
+ ret.adjust(0, 0, -controlWidth, 0);
+ if (titlebar->titleBarFlags & Qt::WindowShadeButtonHint)
+ ret.adjust(0, 0, -controlWidth, 0);
+ if (titlebar->titleBarFlags & Qt::WindowContextHelpButtonHint)
+ ret.adjust(0, 0, -controlWidth, 0);
+ }
+ break;
+ case SC_TitleBarContextHelpButton:
+ if (titlebar->titleBarFlags & Qt::WindowContextHelpButtonHint)
+ offset += controlWidth;
+ Q_FALLTHROUGH();
+ case SC_TitleBarMinButton:
+ if (!isMinimized && (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint))
+ offset += controlWidth;
+ else if (sc == SC_TitleBarMinButton)
+ break;
+ Q_FALLTHROUGH();
+ case SC_TitleBarNormalButton:
+ if (isMinimized && (titlebar->titleBarFlags & Qt::WindowMinimizeButtonHint))
+ offset += controlWidth;
+ else if (isMaximized && (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint))
+ offset += controlWidth;
+ else if (sc == SC_TitleBarNormalButton)
+ break;
+ Q_FALLTHROUGH();
+ case SC_TitleBarMaxButton:
+ if (!isMaximized && (titlebar->titleBarFlags & Qt::WindowMaximizeButtonHint))
+ offset += controlWidth;
+ else if (sc == SC_TitleBarMaxButton)
+ break;
+ Q_FALLTHROUGH();
+ case SC_TitleBarShadeButton:
+ if (!isMinimized && (titlebar->titleBarFlags & Qt::WindowShadeButtonHint))
+ offset += controlWidth;
+ else if (sc == SC_TitleBarShadeButton)
+ break;
+ Q_FALLTHROUGH();
+ case SC_TitleBarUnshadeButton:
+ if (isMinimized && (titlebar->titleBarFlags & Qt::WindowShadeButtonHint))
+ offset += controlWidth;
+ else if (sc == SC_TitleBarUnshadeButton)
+ break;
+ Q_FALLTHROUGH();
+ case SC_TitleBarCloseButton:
+ if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint)
+ offset += controlWidth;
+ else if (sc == SC_TitleBarCloseButton)
+ break;
+ ret.setRect(titlebar->rect.right() - offset, titlebar->rect.top(),
+ controlWidth, controlHeight);
+ break;
+ case SC_TitleBarSysMenu:
+ if (titlebar->titleBarFlags & Qt::WindowSystemMenuHint) {
+ ret.setRect(titlebar->rect.left() + controlWidthMargin + indent, titlebar->rect.top() + iconSize/2,
+ iconSize, iconSize);
+ }
+ break;
+ default:
+ break;
+ }
+ if (widget && isMinimized && titlebar->rect.width() < offset)
+ const_cast<QWidget*>(widget)->resize(controlWidthMargin + indent + offset + iconSize + controlWidthMargin, controlWidth);
+ ret = visualRect(titlebar->direction, titlebar->rect, ret);
+ }
+ break;
+#endif // Qt_NO_SPINBOX
+ case CC_ScrollBar:
+ {
+ ret = QCommonStyle::subControlRect(control, option, subControl, widget);
+
+ switch (subControl) {
+ case QStyle::SC_ScrollBarAddLine:
+ if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ if (scrollbar->orientation == Qt::Vertical) {
+ ret = ret.adjusted(2,2,-2,-3);
+ } else {
+ ret = ret.adjusted(3,2,-2,-2);
+ }
+ }
+ break;
+ case QStyle::SC_ScrollBarSubLine:
+ if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
+ if (scrollbar->orientation == Qt::Vertical) {
+ ret = ret.adjusted(2,2,-2,-3);
+ } else {
+ ret = ret.adjusted(3,2,-2,-2);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
+ }
+ return ret;
+}
+
+/*!
+ \internal
+ */
+QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *option,
+ const QSize &size, const QWidget *widget) const
+{
+ QSize contentSize(size);
+
+ switch (type) {
+
+ case CT_Menu:
+ contentSize += QSize(10, 0);
+ break;
+
+#if QT_CONFIG(menubar)
+ case CT_MenuBarItem:
+ if (!contentSize.isEmpty()) {
+ constexpr int hMargin = 2 * 6;
+ constexpr int hPadding = 2 * 11;
+ constexpr int itemHeight = 32;
+ contentSize.setWidth(contentSize.width() + hMargin + hPadding);
+ contentSize.setHeight(itemHeight);
+ }
+ break;
+#endif
+
+ default:
+ contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
+ break;
+ }
+
+ return contentSize;
+}
+
+
+/*!
+ \internal
+ */
+int QWindows11Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
+{
+ int res = 0;
+
+ switch (metric) {
+ case QStyle::PM_IndicatorWidth:
+ case QStyle::PM_IndicatorHeight:
+ case QStyle::PM_ExclusiveIndicatorWidth:
+ case QStyle::PM_ExclusiveIndicatorHeight:
+ res = 16;
+ break;
+ case QStyle::PM_SliderLength:
+ res = int(QStyleHelper::dpiScaled(16, option));
+ break;
+ case QStyle::PM_TitleBarButtonIconSize:
+ res = 16;
+ break;
+ case QStyle::PM_TitleBarButtonSize:
+ res = 32;
+ break;
+ case QStyle::PM_ScrollBarExtent:
+ res = 12;
+ break;
+ default:
+ res = QWindowsVistaStyle::pixelMetric(metric, option, widget);
+ }
+
+ return res;
+}
+
+void QWindows11Style::polish(QWidget* widget)
+{
+ QWindowsVistaStyle::polish(widget);
+ const bool isScrollBar = qobject_cast<QScrollBar *>(widget);
+ if (isScrollBar || qobject_cast<QMenu *>(widget) || widget->inherits("QComboBoxPrivateContainer")) {
+ bool wasCreated = widget->testAttribute(Qt::WA_WState_Created);
+ bool layoutDirection = widget->testAttribute(Qt::WA_RightToLeft);
+ widget->setAttribute(Qt::WA_OpaquePaintEvent,false);
+ widget->setAttribute(Qt::WA_TranslucentBackground);
+ widget->setWindowFlag(Qt::FramelessWindowHint);
+ widget->setWindowFlag(Qt::NoDropShadowWindowHint);
+ widget->setAttribute(Qt::WA_RightToLeft, layoutDirection);
+ widget->setAttribute(Qt::WA_WState_Created, wasCreated);
+ auto pal = widget->palette();
+ pal.setColor(widget->backgroundRole(), Qt::transparent);
+ widget->setPalette(pal);
+ if (!isScrollBar) { // for menus and combobox containers...
+ QGraphicsDropShadowEffect* dropshadow = new QGraphicsDropShadowEffect(widget);
+ dropshadow->setBlurRadius(3);
+ dropshadow->setXOffset(3);
+ dropshadow->setYOffset(3);
+ widget->setGraphicsEffect(dropshadow);
+ }
+ } else if (QComboBox* cb = qobject_cast<QComboBox*>(widget)) {
+ if (cb->isEditable()) {
+ QLineEdit *le = cb->lineEdit();
+ le->setFrame(false);
+ }
+ } else if (widget->inherits("QAbstractSpinBox")) {
+ const int minWidth = 2 * 24 + 40;
+ const int originalWidth = widget->size().width();
+ if (originalWidth < minWidth) {
+ widget->resize(minWidth, widget->size().height());
+ widget->setProperty(originalWidthProperty.constData(), originalWidth);
+ }
+ } else if (widget->inherits("QAbstractButton") || widget->inherits("QToolButton")) {
+ widget->setAutoFillBackground(false);
+ } else if (qobject_cast<QGraphicsView *>(widget) && !qobject_cast<QTextEdit *>(widget)) {
+ QPalette pal = widget->palette();
+ pal.setColor(QPalette::Base, pal.window().color());
+ widget->setPalette(pal);
+ } else if (const auto *scrollarea = qobject_cast<QAbstractScrollArea *>(widget);
+ scrollarea
+#if QT_CONFIG(mdiarea)
+ && !qobject_cast<QMdiArea *>(widget)
+#endif
+ ) {
+ QPalette pal = scrollarea->viewport()->palette();
+ const QPalette originalPalette = pal;
+ pal.setColor(scrollarea->viewport()->backgroundRole(), Qt::transparent);
+ scrollarea->viewport()->setPalette(pal);
+ scrollarea->viewport()->setProperty("_q_original_background_palette", originalPalette);
+ } else if (qobject_cast<QCommandLinkButton *>(widget)) {
+ widget->setProperty("_qt_usingVistaStyle",false);
+ QPalette pal = widget->palette();
+ pal.setColor(QPalette::ButtonText, pal.text().color());
+ pal.setColor(QPalette::BrightText, pal.text().color());
+ widget->setPalette(pal);
+ }
+}
+
+void QWindows11Style::unpolish(QWidget *widget)
+{
+ QWindowsVistaStyle::unpolish(widget);
+ if (const auto *scrollarea = qobject_cast<QAbstractScrollArea *>(widget);
+ scrollarea
+#if QT_CONFIG(mdiarea)
+ && !qobject_cast<QMdiArea *>(widget)
+#endif
+ ) {
+ const QPalette pal = scrollarea->viewport()->property("_q_original_background_palette").value<QPalette>();
+ scrollarea->viewport()->setPalette(pal);
+ scrollarea->viewport()->setProperty("_q_original_background_palette", QVariant());
+ }
+ if (widget->inherits("QAbstractSpinBox")) {
+ const QVariant originalWidth = widget->property(originalWidthProperty.constData());
+ if (originalWidth.isValid()) {
+ widget->resize(originalWidth.toInt(), widget->size().height());
+ widget->setProperty(originalWidthProperty.constData(), QVariant());
+ }
+ }
+}
+
+/*
+The colors for Windows 11 are taken from the official WinUI3 Figma style at
+https://www.figma.com/community/file/1159947337437047524
+*/
+#define SET_IF_UNRESOLVED(GROUP, ROLE, VALUE) \
+ if (!result.isBrushSet(QPalette::Inactive, ROLE) || styleSheetChanged) \
+ result.setColor(GROUP, ROLE, VALUE)
+
+static void populateLightSystemBasePalette(QPalette &result)
+{
+ static QString oldStyleSheet;
+ const bool styleSheetChanged = oldStyleSheet != qApp->styleSheet();
+
+ const QColor textColor = QColor(0x00,0x00,0x00,0xE4);
+ const QColor btnFace = QColor(0xFF,0xFF,0xFF,0xB3);
+ const QColor btnHighlight = result.accent().color();
+ const QColor btnColor = result.button().color();
+
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Highlight, btnHighlight);
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::WindowText, textColor);
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Button, btnFace);
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Light, btnColor.lighter(150));
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Dark, btnColor.darker(200));
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Mid, btnColor.darker(150));
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Text, textColor);
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::BrightText, btnHighlight);
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Base, btnFace);
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Window, QColor(0xF3,0xF3,0xF3,0xFF));
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::ButtonText, textColor);
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Midlight, btnColor.lighter(125));
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::Shadow, Qt::black);
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::ToolTipBase, result.window().color());
+ SET_IF_UNRESOLVED(QPalette::All, QPalette::ToolTipText, result.windowText().color());
+
+ if (result.midlight() == result.button())
+ result.setColor(QPalette::Midlight, btnColor.lighter(110));
+ oldStyleSheet = qApp->styleSheet();
+}
+
+/*!
+ \internal
+ */
+void QWindows11Style::polish(QPalette& result)
+{
+ highContrastTheme = QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Unknown;
+ colorSchemeIndex = QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light ? 0 : 1;
+
+ if (!highContrastTheme && colorSchemeIndex == 0)
+ populateLightSystemBasePalette(result);
+
+ const bool styleSheetChanged = false; // so the macro works
+
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Button, result.button().color());
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Window, result.window().color());
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Light, result.light().color());
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Dark, result.dark().color());
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Accent, result.accent().color());
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Highlight, result.highlight().color());
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::HighlightedText, result.highlightedText().color());
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Text, result.text().color());
+ SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::WindowText, result.windowText().color());
+
+ if (highContrastTheme)
+ result.setColor(QPalette::Active, QPalette::HighlightedText, result.windowText().color());
+}
+
+#undef SET_IF_UNRESOLVED
+
+QT_END_NAMESPACE
diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h
new file mode 100644
index 0000000000..9c54afd967
--- /dev/null
+++ b/src/plugins/styles/modernwindows/qwindows11style_p.h
@@ -0,0 +1,70 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWS11STYLE_P_H
+#define QWINDOWS11STYLE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <qwindowsvistastyle_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWindows11StylePrivate;
+class QWindows11Style;
+
+class QWindows11Style : public QWindowsVistaStyle
+{
+ Q_OBJECT
+public:
+ QWindows11Style();
+ ~QWindows11Style() override;
+ void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option,
+ QPainter *painter, const QWidget *widget) const override;
+ void drawPrimitive(PrimitiveElement element, const QStyleOption *option,
+ QPainter *painter, const QWidget *widget) const override;
+ QRect subElementRect(QStyle::SubElement element, const QStyleOption *option,
+ const QWidget *widget = nullptr) const override;
+ QRect subControlRect(ComplexControl control, const QStyleOptionComplex *option,
+ SubControl subControl, const QWidget *widget) const override;
+ void drawControl(ControlElement element, const QStyleOption *option,
+ QPainter *painter, const QWidget *widget) const override;
+ int styleHint(StyleHint hint, const QStyleOption *opt = nullptr,
+ const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const override;
+ void polish(QWidget* widget) override;
+
+ QSize sizeFromContents(ContentsType type, const QStyleOption *option,
+ const QSize &size, const QWidget *widget) const override;
+ int pixelMetric(PixelMetric metric, const QStyleOption *option = nullptr,
+ const QWidget *widget = nullptr) const override;
+ void polish(QPalette &pal) override;
+ void unpolish(QWidget *widget) override;
+protected:
+ QWindows11Style(QWindows11StylePrivate &dd);
+private:
+ Q_DISABLE_COPY_MOVE(QWindows11Style)
+ Q_DECLARE_PRIVATE(QWindows11Style)
+ friend class QStyleFactory;
+
+ bool highContrastTheme = false;
+ int colorSchemeIndex = 0;
+ const QFont assetFont = QFont("Segoe Fluent Icons"); //Font to load icons from
+};
+
+class QWindows11StylePrivate : public QWindowsVistaStylePrivate {
+ Q_DECLARE_PUBLIC(QWindows11Style)
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWS11STYLE_P_H
diff --git a/src/plugins/styles/windowsvista/qwindowsthemedata.cpp b/src/plugins/styles/modernwindows/qwindowsthemedata.cpp
index 44569e054d..44569e054d 100644
--- a/src/plugins/styles/windowsvista/qwindowsthemedata.cpp
+++ b/src/plugins/styles/modernwindows/qwindowsthemedata.cpp
diff --git a/src/plugins/styles/windowsvista/qwindowsthemedata_p.h b/src/plugins/styles/modernwindows/qwindowsthemedata_p.h
index 5de2bcbdea..5de2bcbdea 100644
--- a/src/plugins/styles/windowsvista/qwindowsthemedata_p.h
+++ b/src/plugins/styles/modernwindows/qwindowsthemedata_p.h
diff --git a/src/plugins/styles/windowsvista/qwindowsvistaanimation.cpp b/src/plugins/styles/modernwindows/qwindowsvistaanimation.cpp
index ac9a5ad8c0..ac9a5ad8c0 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistaanimation.cpp
+++ b/src/plugins/styles/modernwindows/qwindowsvistaanimation.cpp
diff --git a/src/plugins/styles/windowsvista/qwindowsvistaanimation_p.h b/src/plugins/styles/modernwindows/qwindowsvistaanimation_p.h
index 817fa5f4b5..817fa5f4b5 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistaanimation_p.h
+++ b/src/plugins/styles/modernwindows/qwindowsvistaanimation_p.h
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
index 283a5bdaa9..beee1d6f31 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
@@ -6,11 +6,14 @@
#include "qwindowsvistaanimation_p.h"
#include <qoperatingsystemversion.h>
#include <qscreen.h>
+#include <qstylehints.h>
#include <qwindow.h>
#include <private/qstyleanimation_p.h>
#include <private/qstylehelper_p.h>
#include <qpa/qplatformnativeinterface.h>
#include <private/qapplication_p.h>
+#include <private/qsystemlibrary_p.h>
+#include <private/qwindowsthemecache_p.h>
#include "qdrawutil.h" // for now
#include <qbackingstore.h>
@@ -18,6 +21,8 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
static const int windowsItemFrame = 2; // menu item frame width
static const int windowsItemHMargin = 3; // menu item hor text margin
static const int windowsItemVMargin = 4; // menu item ver text margin
@@ -47,34 +52,12 @@ static const int windowsRightBorder = 15; // right border on windows
# define CMDLGS_DISABLED 4
#endif
-/* \internal
- Checks if we should use Vista style , or if we should
- fall back to Windows style.
-*/
-// Theme names matching the QWindowsVistaStylePrivate::Theme enumeration.
-static const wchar_t *themeNames[QWindowsVistaStylePrivate::NThemes] =
-{
- L"BUTTON", L"COMBOBOX", L"EDIT", L"HEADER", L"LISTVIEW",
- L"MENU", L"PROGRESS", L"REBAR", L"SCROLLBAR", L"SPIN",
- L"TAB", L"TASKDIALOG", L"TOOLBAR", L"TOOLTIP", L"TRACKBAR",
- L"WINDOW", L"STATUS", L"TREEVIEW"
-};
-
// QWindowsVistaStylePrivate -------------------------------------------------------------------------
// Static initializations
HWND QWindowsVistaStylePrivate::m_vistaTreeViewHelper = nullptr;
-HTHEME QWindowsVistaStylePrivate::m_themes[NThemes];
bool QWindowsVistaStylePrivate::useVistaTheme = false;
Q_CONSTINIT QBasicAtomicInt QWindowsVistaStylePrivate::ref = Q_BASIC_ATOMIC_INITIALIZER(-1); // -1 based refcounting
-namespace QOSWorkaround {
- // Due to a mingw bug being confused by static constexpr variables in an exported class,
- // we cannot use QOperatingSystemVersion::Windows11 in libraries outside of QtCore.
- // ### TODO Remove this when that problem is fixed.
- static constexpr QOperatingSystemVersionBase Windows11 { QOperatingSystemVersionBase::Windows,
- 10, 0, 22000 };
-}
-
static void qt_add_rect(HRGN &winRegion, QRect r)
{
HRGN rgn = CreateRectRgn(r.left(), r.top(), r.x() + r.width(), r.y() + r.height());
@@ -172,10 +155,8 @@ static QRegion scaleRegion(const QRegion &region, qreal factor)
*/
bool QWindowsVistaStylePrivate::useVista(bool update)
{
- if (update) {
- useVistaTheme = IsThemeActive() && (IsAppThemed() || !QCoreApplication::instance())
- && !QWindowsStylePrivate::isDarkMode();
- }
+ if (update)
+ useVistaTheme = IsThemeActive() && (IsAppThemed() || !QCoreApplication::instance());
return useVistaTheme;
}
@@ -190,7 +171,6 @@ void QWindowsVistaStylePrivate::init(bool force)
ref.ref();
useVista(true);
- std::fill(m_themes, m_themes + NThemes, nullptr);
}
/* \internal
@@ -246,11 +226,8 @@ int QWindowsVistaStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, c
: QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::ProgressTheme, PP_CHUNKVERT).height();
case QStyle::PM_SliderThickness:
return QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::TrackBarTheme, TKP_THUMB).height();
- case QStyle::PM_TitleBarHeight: {
- return widget && (widget->windowType() == Qt::Tool)
- ? GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME)
- : GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME);
- }
+ case QStyle::PM_TitleBarHeight:
+ return QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PM_TitleBarHeight, option, widget);
case QStyle::PM_MdiSubWindowFrameWidth:
return QWindowsThemeData::themeSize(widget, nullptr, QWindowsVistaStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE).width();
case QStyle::PM_DockWidgetFrameWidth:
@@ -313,31 +290,15 @@ void QWindowsVistaStylePrivate::cleanupVistaTreeViewTheming()
*/
void QWindowsVistaStylePrivate::cleanupHandleMap()
{
- for (auto &theme : m_themes) {
- if (theme) {
- CloseThemeData(theme);
- theme = nullptr;
- }
- }
+ QWindowsThemeCache::clearAllThemeCaches();
QWindowsVistaStylePrivate::cleanupVistaTreeViewTheming();
}
HTHEME QWindowsVistaStylePrivate::createTheme(int theme, HWND hwnd)
{
- if (Q_UNLIKELY(theme < 0 || theme >= NThemes || !hwnd)) {
- qWarning("Invalid parameters #%d, %p", theme, hwnd);
- return nullptr;
- }
- if (!m_themes[theme]) {
- const wchar_t *name = themeNames[theme];
- if (theme == VistaTreeViewTheme && QWindowsVistaStylePrivate::initVistaTreeViewTheming())
- hwnd = QWindowsVistaStylePrivate::m_vistaTreeViewHelper;
- m_themes[theme] = OpenThemeData(hwnd, name);
- if (Q_UNLIKELY(!m_themes[theme]))
- qErrnoWarning("OpenThemeData() failed for theme %d (%s).",
- theme, qPrintable(themeName(theme)));
- }
- return m_themes[theme];
+ if (theme == VistaTreeViewTheme && QWindowsVistaStylePrivate::initVistaTreeViewTheming())
+ hwnd = QWindowsVistaStylePrivate::m_vistaTreeViewHelper;
+ return QWindowsThemeCache::createTheme(theme, hwnd);
}
QBackingStore *QWindowsVistaStylePrivate::backingStoreForWidget(const QWidget *widget)
@@ -362,8 +323,7 @@ HDC QWindowsVistaStylePrivate::hdcForWidgetBackingStore(const QWidget *widget)
QString QWindowsVistaStylePrivate::themeName(int theme)
{
- return theme >= 0 && theme < NThemes
- ? QString::fromWCharArray(themeNames[theme]) : QString();
+ return QWindowsThemeCache::themeName(theme);
}
bool QWindowsVistaStylePrivate::isItemViewDelegateLineEdit(const QWidget *widget)
@@ -513,29 +473,29 @@ QRegion QWindowsVistaStylePrivate::region(QWindowsThemeData &themeData)
QRegion region;
if (success) {
- const auto numBytes = GetRegionData(dest, 0, nullptr);
- if (numBytes == 0)
- return QRegion();
-
- char *buf = new (std::nothrow) char[numBytes];
- if (!buf)
- return QRegion();
-
- RGNDATA *rd = reinterpret_cast<RGNDATA*>(buf);
- if (GetRegionData(dest, numBytes, rd) == 0) {
- delete [] buf;
- return QRegion();
+ QVarLengthArray<char> buf(256);
+ RGNDATA *rd = reinterpret_cast<RGNDATA *>(buf.data());
+ if (GetRegionData(dest, buf.size(), rd) == 0) {
+ const auto numBytes = GetRegionData(dest, 0, nullptr);
+ if (numBytes > 0) {
+ buf.resize(numBytes);
+ rd = reinterpret_cast<RGNDATA *>(buf.data());
+ if (GetRegionData(dest, numBytes, rd) == 0)
+ rd = nullptr;
+ } else {
+ rd = nullptr;
+ }
}
-
- RECT *r = reinterpret_cast<RECT*>(rd->Buffer);
- for (uint i = 0; i < rd->rdh.nCount; ++i) {
- QRect rect;
- rect.setCoords(int(r->left * factor), int(r->top * factor), int((r->right - 1) * factor), int((r->bottom - 1) * factor));
- ++r;
- region |= rect;
+ if (rd) {
+ RECT *r = reinterpret_cast<RECT *>(rd->Buffer);
+ for (uint i = 0; i < rd->rdh.nCount; ++i) {
+ QRect rect;
+ rect.setCoords(int(r->left * factor), int(r->top * factor),
+ int((r->right - 1) * factor), int((r->bottom - 1) * factor));
+ ++r;
+ region |= rect;
+ }
}
-
- delete [] buf;
}
DeleteObject(hRgn);
@@ -1314,6 +1274,14 @@ QWindowsVistaStyle::QWindowsVistaStyle() : QWindowsStyle(*new QWindowsVistaStyle
}
/*!
+ \internal
+ Constructs a QWindowsStyle object.
+*/
+QWindowsVistaStyle::QWindowsVistaStyle(QWindowsVistaStylePrivate &dd) : QWindowsStyle(dd)
+{
+}
+
+/*!
Destructor.
*/
QWindowsVistaStyle::~QWindowsVistaStyle() = default;
@@ -1431,17 +1399,17 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
theme = OpenThemeData(nullptr, L"Edit");
partId = EP_EDITBORDER_NOSCROLL;
- if (oldState & State_MouseOver)
+ if (oldState & State_HasFocus)
+ fromState = ETS_SELECTED;
+ else if (oldState & State_MouseOver)
fromState = ETS_HOT;
- else if (oldState & State_HasFocus)
- fromState = ETS_FOCUSED;
else
fromState = ETS_NORMAL;
- if (state & State_MouseOver)
+ if (state & State_HasFocus)
+ toState = ETS_SELECTED;
+ else if (state & State_MouseOver)
toState = ETS_HOT;
- else if (state & State_HasFocus)
- toState = ETS_FOCUSED;
else
toState = ETS_NORMAL;
@@ -1946,10 +1914,10 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
stateId = ETS_DISABLED;
else if (state & State_ReadOnly)
stateId = ETS_READONLY;
- else if (state & State_MouseOver)
- stateId = ETS_HOT;
else if (state & State_HasFocus)
stateId = ETS_SELECTED;
+ else if (state & State_MouseOver)
+ stateId = ETS_HOT;
QWindowsThemeData theme(widget, painter,
QWindowsVistaStylePrivate::EditTheme,
EP_EDITBORDER_NOSCROLL, stateId, option->rect);
@@ -2316,10 +2284,6 @@ int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, co
ret = 1;
break;
- case SH_SupportsDarkAppearance:
- ret = 0;
- break;
-
default:
ret = QWindowsStyle::styleHint(hint, option, widget, returnData);
break;
@@ -2944,9 +2908,6 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
else
theme.stateId = bullet ? MC_BULLETNORMAL: MC_CHECKMARKNORMAL;
d->drawBackground(theme);
- } else if (QOperatingSystemVersion::current() >= QOSWorkaround::Windows11
- && !act) {
- painter->fillRect(checkRect, menuitem->palette.highlight().color().lighter(200));
}
}
@@ -2954,11 +2915,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
if (act && !dis)
mode = QIcon::Active;
- QPixmap pixmap;
- if (checked)
- pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
- else
- pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
+ const auto size = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
+ const auto dpr = painter->device()->devicePixelRatio();
+ const auto pixmap = menuitem->icon.pixmap({size, size}, dpr, mode,
+ checked ? QIcon::On : QIcon::Off);
QRect pmr(QPoint(0, 0), pixmap.deviceIndependentSize().toSize());
pmr.moveCenter(vCheckRect.center());
painter->setPen(menuitem->palette.text().color());
@@ -3030,7 +2990,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
partId, stateId, option->rect);
d->drawBackground(theme);
}
- return;
+ return;
case CE_MenuBarEmptyArea: {
stateId = MBI_NORMAL;
@@ -3146,7 +3106,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QColor textShadow = qRgb(GetRValue(textShadowRef), GetGValue(textShadowRef), GetBValue(textShadowRef));
painter->setPen(textShadow);
drawItemText(painter, titleRect.adjusted(1, 1, 1, 1),
- Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette,
+ Qt::AlignLeft | Qt::AlignBottom | Qt::TextHideMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, titleText);
}
@@ -3154,7 +3114,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QColor textColor = qRgb(GetRValue(captionText), GetGValue(captionText), GetBValue(captionText));
painter->setPen(textColor);
drawItemText(painter, titleRect,
- Qt::AlignLeft | Qt::AlignBottom, dwOpt->palette,
+ Qt::AlignLeft | Qt::AlignBottom | Qt::TextHideMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, titleText);
painter->setFont(oldFont);
painter->setPen(oldPen);
@@ -3169,7 +3129,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
verticalTitleBar ? titleRect.height() : titleRect.width());
const int indent = 4;
drawItemText(painter, rect.adjusted(indent + 1, 1, -indent - 1, -1),
- Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic,
+ Qt::AlignLeft | Qt::AlignVCenter | Qt::TextHideMnemonic,
dwOpt->palette,
dwOpt->state & State_Enabled, titleText,
QPalette::WindowText);
@@ -4502,8 +4462,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
#endif // QT_CONFIG(mdiarea)
default:
- return visualRect(option->direction, option->rect,
- QWindowsStyle::subControlRect(control, option, subControl, widget));
+ return QWindowsStyle::subControlRect(control, option, subControl, widget);
}
return visualRect(option->direction, option->rect, rect);
@@ -4656,8 +4615,8 @@ void QWindowsVistaStyle::polish(QWidget *widget)
buttonFont.setFamilies(QStringList{QLatin1String("Segoe UI")});
widget->setFont(buttonFont);
QPalette pal = widget->palette();
- pal.setColor(QPalette::ButtonText, QColor(21, 28, 85));
- pal.setColor(QPalette::BrightText, QColor(7, 64, 229));
+ pal.setColor(QPalette::Active, QPalette::ButtonText, QColor(21, 28, 85));
+ pal.setColor(QPalette::Active, QPalette::BrightText, QColor(7, 64, 229));
widget->setPalette(pal);
}
#endif // QT_CONFIG(commandlinkbutton)
@@ -4671,6 +4630,7 @@ void QWindowsVistaStyle::polish(QWidget *widget)
QColor textColor = QColor::fromRgb(bgRef);
QPalette pal;
pal.setColor(QPalette::All, QPalette::ToolTipText, textColor);
+ pal.setResolveMask(0);
widget->setPalette(pal);
}
} else if (qobject_cast<QMessageBox *> (widget)) {
@@ -4795,6 +4755,14 @@ void QWindowsVistaStyle::polish(QPalette &pal)
{
Q_D(QWindowsVistaStyle);
+ if (QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Dark) {
+ // System runs in dark mode, but the Vista style cannot use a dark palette.
+ // Overwrite with the light system palette.
+ using QWindowsApplication = QNativeInterface::Private::QWindowsApplication;
+ if (auto nativeWindowsApp = dynamic_cast<QWindowsApplication *>(QGuiApplicationPrivate::platformIntegration()))
+ nativeWindowsApp->populateLightSystemPalette(pal);
+ }
+
QPixmapCache::clear();
d->alphaCache.clear();
d->hasInitColors = false;
@@ -4820,6 +4788,41 @@ void QWindowsVistaStyle::polish(QPalette &pal)
/*!
\internal
*/
+void QWindowsVistaStyle::polish(QApplication *app)
+{
+ // Override windows theme palettes to light
+ if (qApp->styleHints()->colorScheme() == Qt::ColorScheme::Dark) {
+ static const char* themedWidgets[] = {
+ "QToolButton",
+ "QAbstractButton",
+ "QCheckBox",
+ "QRadioButton",
+ "QHeaderView",
+ "QAbstractItemView",
+ "QMessageBoxLabel",
+ "QTabBar",
+ "QLabel",
+ "QGroupBox",
+ "QMenu",
+ "QMenuBar",
+ "QTextEdit",
+ "QTextControl",
+ "QLineEdit"
+ };
+ for (const auto& themedWidget : std::as_const(themedWidgets)) {
+ auto defaultResolveMask = QApplication::palette().resolveMask();
+ auto widgetResolveMask = QApplication::palette(themedWidget).resolveMask();
+ if (widgetResolveMask != defaultResolveMask)
+ QApplication::setPalette(QApplication::palette(), themedWidget);
+ }
+ }
+
+ QWindowsStyle::polish(app);
+}
+
+/*!
+ \internal
+ */
QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option,
const QWidget *widget) const
{
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h b/src/plugins/styles/modernwindows/qwindowsvistastyle_p.h
index b600491248..ff5300beca 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle_p.h
@@ -58,7 +58,9 @@ public:
void polish(QWidget *widget) override;
void unpolish(QWidget *widget) override;
void polish(QPalette &pal) override;
-
+ void polish(QApplication *app) override;
+protected:
+ QWindowsVistaStyle(QWindowsVistaStylePrivate &dd);
private:
Q_DISABLE_COPY_MOVE(QWindowsVistaStyle)
Q_DECLARE_PRIVATE(QWindowsVistaStyle)
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h b/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h
index 2c38ff4b3b..053e98b68d 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h
@@ -77,6 +77,7 @@
#endif
#include <qlabel.h>
#include <qheaderview.h>
+#include <uxtheme.h>
QT_BEGIN_NAMESPACE
@@ -115,7 +116,6 @@ public:
static HTHEME createTheme(int theme, HWND hwnd);
static QString themeName(int theme);
- static inline bool hasTheme(int theme) { return theme >= 0 && theme < NThemes && m_themes[theme]; }
static bool isItemViewDelegateLineEdit(const QWidget *widget);
static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = nullptr, const QWidget *widget = nullptr);
static int fixedPixelMetric(QStyle::PixelMetric pm);
@@ -169,7 +169,6 @@ private:
int bufferH = 0;
static HWND m_vistaTreeViewHelper;
- static HTHEME m_themes[NThemes];
};
QT_END_NAMESPACE
diff --git a/src/plugins/styles/windowsvista/main.cpp b/src/plugins/styles/windowsvista/main.cpp
deleted file mode 100644
index af832be0a8..0000000000
--- a/src/plugins/styles/windowsvista/main.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2017 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#include <QtWidgets/private/qtwidgetsglobal_p.h>
-#include <QtWidgets/qstyleplugin.h>
-#include "qwindowsvistastyle_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QWindowsVistaStylePlugin : public QStylePlugin
-{
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "windowsvistastyle.json")
-public:
- QStyle *create(const QString &key) override;
-};
-
-QStyle *QWindowsVistaStylePlugin::create(const QString &key)
-{
- if (key.compare(QLatin1String("windowsvista"), Qt::CaseInsensitive) == 0)
- return new QWindowsVistaStyle();
-
- return nullptr;
-}
-
-QT_END_NAMESPACE
-
-#include "main.moc"
diff --git a/src/plugins/styles/windowsvista/windowsvistastyle.json b/src/plugins/styles/windowsvista/windowsvistastyle.json
deleted file mode 100644
index 771aa0c600..0000000000
--- a/src/plugins/styles/windowsvista/windowsvistastyle.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "Keys": [ "windowsvista" ]
-}