diff options
Diffstat (limited to 'src/plugins')
18 files changed, 266 insertions, 55 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index 08c9f5d5ba2..2989b4d6df3 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -161,6 +161,7 @@ static void populateRoleMap() roleMap[QAccessible::Graphic] = NSAccessibilityImageRole; roleMap[QAccessible::Tree] = NSAccessibilityOutlineRole; roleMap[QAccessible::BlockQuote] = NSAccessibilityGroupRole; + roleMap[QAccessible::LayeredPane] = NSAccessibilityGroupRole; } /* diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 144c0519155..238f2ea2307 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -714,6 +714,25 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of iface->setText(QAccessible::Description, QString::fromNSString(label)); } +- (NSAccessibilityOrientation)accessibilityOrientation { + QAccessibleInterface *iface = self.qtInterface; + if (!iface) + return NSAccessibilityOrientationUnknown; + + NSAccessibilityOrientation nsOrientation = NSAccessibilityOrientationUnknown; + if (QAccessibleAttributesInterface *attributesIface = iface->attributesInterface()) { + const QVariant orientationVariant = + attributesIface->attributeValue(QAccessible::Attribute::Orientation); + if (orientationVariant.isValid()) { + Q_ASSERT(orientationVariant.canConvert<Qt::Orientation>()); + const Qt::Orientation orientation = orientationVariant.value<Qt::Orientation>(); + nsOrientation = orientation == Qt::Horizontal ? NSAccessibilityOrientationHorizontal + : NSAccessibilityOrientationVertical; + } + } + return nsOrientation; +} + - (id) accessibilityValue { if (QAccessibleInterface *iface = self.qtInterface) { // VoiceOver asks for the value attribute for all elements. Return nil diff --git a/src/plugins/platforms/ios/qiostheme.h b/src/plugins/platforms/ios/qiostheme.h index b7ff3bb2a58..7af9cf80355 100644 --- a/src/plugins/platforms/ios/qiostheme.h +++ b/src/plugins/platforms/ios/qiostheme.h @@ -26,6 +26,7 @@ public: Qt::ColorScheme colorScheme() const override; void requestColorScheme(Qt::ColorScheme scheme) override; + Qt::ContrastPreference contrastPreference() const override; #if !defined(Q_OS_TVOS) && !defined(Q_OS_VISIONOS) QPlatformMenuItem* createPlatformMenuItem() const override; diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm index cdf669f921c..435c21bf579 100644 --- a/src/plugins/platforms/ios/qiostheme.mm +++ b/src/plugins/platforms/ios/qiostheme.mm @@ -202,6 +202,12 @@ void QIOSTheme::requestColorScheme(Qt::ColorScheme scheme) #endif } +Qt::ContrastPreference QIOSTheme::contrastPreference() const +{ + return UIAccessibilityDarkerSystemColorsEnabled() ? Qt::ContrastPreference::HighContrast : Qt::ContrastPreference::NoPreference; +} + + void QIOSTheme::applyTheme(UIWindow *window) { const UIUserInterfaceStyle style = []{ diff --git a/src/plugins/platforms/ios/quiwindow.mm b/src/plugins/platforms/ios/quiwindow.mm index bb4268e1c88..62fd9c5d770 100644 --- a/src/plugins/platforms/ios/quiwindow.mm +++ b/src/plugins/platforms/ios/quiwindow.mm @@ -54,7 +54,9 @@ if (self.screen == UIScreen.mainScreen) { // Check if the current userInterfaceStyle reports a different appearance than // the platformTheme's appearance. We might have set that one based on the UIScreen + // Check for changes in the "Increase contrast" setting too. if (previousTraitCollection.userInterfaceStyle != self.traitCollection.userInterfaceStyle + || previousTraitCollection.accessibilityContrast != self.traitCollection.accessibilityContrast || QGuiApplicationPrivate::platformTheme()->colorScheme() != colorScheme) { QIOSTheme::initializeSystemPalette(); QWindowSystemInterface::handleThemeChange<QWindowSystemInterface::SynchronousDelivery>(); diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp index 5fa79482217..a87c33c8346 100644 --- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp +++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp @@ -401,6 +401,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac case QAccessible::PageTabList:{ element = document.call<emscripten::val>("createElement", std::string("div")); setAttribute(element, "role", "tablist"); + setHtmlElementOrientation(element, iface); m_elements[iface] = element; @@ -423,6 +424,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac element = document.call<emscripten::val>("createElement", std::string("div")); setAttribute(element, "role", "scrollbar"); setAttribute(element, "aria-valuenow", valueString); + setHtmlElementOrientation(element, iface); addEventListener(iface, element, "change"); } break; @@ -437,6 +439,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac element = document.call<emscripten::val>("createElement", std::string("div")); setAttribute(element, "role", "toolbar"); setAttribute(element, "title", text.toStdString()); + setHtmlElementOrientation(element, iface); addEventListener(iface, element, "click"); }break; case QAccessible::MenuItem: @@ -453,6 +456,7 @@ emscripten::val QWasmAccessibility::createHtmlElement(QAccessibleInterface *ifac element = document.call<emscripten::val>("createElement", std::string("div")); setAttribute(element, "role", "menubar"); setAttribute(element, "title", text.toStdString()); + setHtmlElementOrientation(element, iface); m_elements[iface] = element; for (int i = 0; i < iface->childCount(); ++i) { @@ -661,6 +665,21 @@ void QWasmAccessibility::setHtmlElementDisabled(QAccessibleInterface *iface) setAttribute(element, "aria-disabled", iface->state().disabled); } +void QWasmAccessibility::setHtmlElementOrientation(emscripten::val element, QAccessibleInterface *iface) +{ + Q_ASSERT(iface); + if (QAccessibleAttributesInterface *attributesIface = iface->attributesInterface()) { + const QVariant orientationVariant = + attributesIface->attributeValue(QAccessible::Attribute::Orientation); + if (orientationVariant.isValid()) { + Q_ASSERT(orientationVariant.canConvert<Qt::Orientation>()); + const Qt::Orientation orientation = orientationVariant.value<Qt::Orientation>(); + const std::string value = orientation == Qt::Horizontal ? "horizontal" : "vertical"; + setAttribute(element, "aria-orientation", value); + } + } +} + void QWasmAccessibility::handleStaticTextUpdate(QAccessibleEvent *event) { switch (event->type()) { diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.h b/src/plugins/platforms/wasm/qwasmaccessibility.h index 26f3e0e9afe..ddbfec918d6 100644 --- a/src/plugins/platforms/wasm/qwasmaccessibility.h +++ b/src/plugins/platforms/wasm/qwasmaccessibility.h @@ -77,6 +77,7 @@ private: void setHtmlElementTextNameLE(QAccessibleInterface *iface); void setHtmlElementFocus(QAccessibleInterface *iface); void setHtmlElementDisabled(QAccessibleInterface *iface); + void setHtmlElementOrientation(emscripten::val element, QAccessibleInterface *iface); void handleStaticTextUpdate(QAccessibleEvent *event); void handleButtonUpdate(QAccessibleEvent *event); diff --git a/src/plugins/platforms/wayland/CMakeLists.txt b/src/plugins/platforms/wayland/CMakeLists.txt index 7e3589def6b..0ce9a4b091c 100644 --- a/src/plugins/platforms/wayland/CMakeLists.txt +++ b/src/plugins/platforms/wayland/CMakeLists.txt @@ -17,14 +17,6 @@ qt_internal_add_module(WaylandGlobalPrivate NO_GENERATE_CPP_EXPORTS ) -# Work around 115101. -# If nothing depends on the WaylandGlobalPrivate target it doesn't run custom commands that the -# target depends on. WaylandGlobalPrivate_ensure_sync_headers makes sure that 'all' depends on -# WaylandGlobalPrivate_sync_headers. -# TODO: This needs to be removed once the fix for QTBUG-115101 is merged in qtbase. -add_custom_target(WaylandGlobalPrivate_ensure_sync_headers ALL) -add_dependencies(WaylandGlobalPrivate_ensure_sync_headers WaylandGlobalPrivate_sync_headers) - # special case begin # TODO: Ideally these macros would be part of the qtwaylandscanner tool, and not the compositor/client include(../../../../src/tools/qtwaylandscanner/Qt6WaylandClientMacros.cmake) diff --git a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp index 84ecc289c59..9aa8af39090 100644 --- a/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp +++ b/src/plugins/platforms/wayland/plugins/shellintegration/xdg-shell/qwaylandxdgtopleveliconv1.cpp @@ -2,7 +2,6 @@ // Copyright (C) 2024 David Edmundson <[email protected]> // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#include "qwaylandshmbackingstore_p.h" #include "qwaylandxdgtopleveliconv1_p.h" #include <QtWaylandClient/private/qwaylanddisplay_p.h> diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp index 6ce43714a35..34b32da289c 100644 --- a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -729,11 +729,11 @@ public: void QWaylandInputDevice::Pointer::pointer_leave(uint32_t serial, struct wl_surface *surface) { + Q_UNUSED(serial); + invalidateFocus(); mButtons = Qt::NoButton; - mParent->mSerial = serial; - // The event may arrive after destroying the window, indicated by // a null surface. if (!surface) diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 53548622dfc..482810d5b7e 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -553,12 +553,14 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData) const bool orientationChanged = m_data.orientation != newData.orientation; const bool primaryChanged = (newData.flags & QWindowsScreenData::PrimaryScreen) && !(m_data.flags & QWindowsScreenData::PrimaryScreen); + const bool refreshRateChanged = m_data.refreshRateHz != newData.refreshRateHz; m_data.dpi = newData.dpi; m_data.orientation = newData.orientation; m_data.geometry = newData.geometry; m_data.availableGeometry = newData.availableGeometry; m_data.flags = (m_data.flags & ~QWindowsScreenData::PrimaryScreen) | (newData.flags & QWindowsScreenData::PrimaryScreen); + m_data.refreshRateHz = newData.refreshRateHz; if (dpiChanged) { QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), @@ -573,6 +575,9 @@ void QWindowsScreen::handleChanges(const QWindowsScreenData &newData) } if (primaryChanged) QWindowSystemInterface::handlePrimaryScreenChanged(this); + + if (refreshRateChanged) + QWindowSystemInterface::handleScreenRefreshRateChange(screen(), newData.refreshRateHz); } HMONITOR QWindowsScreen::handle() const diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 0144786ce5e..b7bf97f5c4b 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -654,6 +654,21 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR *pRetVal = QComVariant{ name }.release(); break; } + case UIA_OrientationPropertyId: { + OrientationType orientationType = OrientationType_None; + if (QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface()) { + const QVariant orientationVariant = + attributesIface->attributeValue(QAccessible::Attribute::Orientation); + if (orientationVariant.isValid()) { + Q_ASSERT(orientationVariant.canConvert<Qt::Orientation>()); + const Qt::Orientation orientation = orientationVariant.value<Qt::Orientation>(); + orientationType = orientation == Qt::Horizontal ? OrientationType_Horizontal + : OrientationType_Vertical; + } + } + *pRetVal = QComVariant{ long(orientationType) }.release(); + break; + } case UIA_StyleIdAttributeId: setStyle(accessible, pRetVal); break; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp index b2675d5b884..835499d3554 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp @@ -154,6 +154,7 @@ long roleToControlTypeId(QAccessible::Role role) {QAccessible::WebDocument, UIA_DocumentControlTypeId}, {QAccessible::Heading, UIA_TextControlTypeId}, {QAccessible::BlockQuote, UIA_GroupControlTypeId}, + {QAccessible::LayeredPane, UIA_PaneControlTypeId}, }; long controlType = mapping.value(role, UIA_CustomControlTypeId); diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp index 5f712d33d56..e609b84ad5f 100644 --- a/src/plugins/platforms/xcb/qxcbatom.cpp +++ b/src/plugins/platforms/xcb/qxcbatom.cpp @@ -9,6 +9,7 @@ #include <string.h> #include <algorithm> +#include <cstdlib> static const char *xcb_atomnames = { // window-manager <-> client protocols diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp index 27a944a33e2..f79dea194e8 100644 --- a/src/plugins/styles/modernwindows/qwindows11style.cpp +++ b/src/plugins/styles/modernwindows/qwindows11style.cpp @@ -107,6 +107,7 @@ inline ControlState calcControlState(const QStyleOption *option) #define ChromeRestore u"\uE923"_s #define ChromeClose u"\uE8BB"_s +#define More u"\uE712"_s #define Help u"\uE897"_s template <typename R, typename P, typename B> @@ -579,21 +580,18 @@ void QWindows11Style::drawComplexControl(ComplexControl control, const QStyleOpt if (combobox->frame) drawLineEditFrame(painter, frameRect, combobox, combobox->editable); - const bool isMouseOver = state & State_MouseOver; const bool hasFocus = state & State_HasFocus; - if (isMouseOver && !hasFocus && !highContrastTheme) - drawRoundedRect(painter, frameRect, Qt::NoPen, winUI3Color(subtleHighlightColor)); + QStyleOption opt(*option); + opt.state.setFlag(QStyle::State_On, false); + drawRoundedRect(painter, frameRect, Qt::NoPen, controlFillBrush(&opt, ControlType::Control)); if (sub & SC_ComboBoxArrow) { QRectF rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget).adjusted(4, 0, -4, 1); painter->setFont(d->assetFont); - painter->setPen(combobox->palette.text().color()); + painter->setPen(controlTextColor(option)); painter->drawText(rect, Qt::AlignCenter, ChevronDownMed); } - if (state & State_HasFocus) { - drawPrimitive(PE_FrameFocusRect, option, painter, widget); - } - if (state & State_KeyboardFocusChange && state & State_HasFocus) { + if (state & State_KeyboardFocusChange && hasFocus) { QStyleOptionFocusRect fropt; fropt.QStyleOption::operator=(*option); proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget); @@ -870,17 +868,13 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption } break; case PE_IndicatorCheckBox: { - const bool isRtl = option->direction == Qt::RightToLeft; const bool isOn = option->state & State_On; const bool isPartial = option->state & State_NoChange; - QRectF rect = isRtl ? option->rect.adjusted(0, 0, -2, 0) : option->rect.adjusted(2, 0, 0, 0); + const QRectF rect = option->rect; const QPointF center = rect.center(); - rect.setWidth(15); - rect.setHeight(15); - rect.moveCenter(center); - drawRoundedRect(painter, rect, borderPenControlAlt(option), + drawRoundedRect(painter, option->rect, borderPenControlAlt(option), controlFillBrush(option, ControlType::ControlAlt)); if (isOn) { @@ -924,7 +918,6 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption } break; case PE_IndicatorRadioButton: { - const bool isRtl = option->direction == Qt::RightToLeft; const bool isOn = option->state & State_On; qreal innerRadius = radioButtonInnerRadius(state); if (d->transitionsEnabled() && option->styleObject) { @@ -935,7 +928,7 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption option->styleObject->setProperty("_q_inner_radius", innerRadius); } - QRectF rect = isRtl ? option->rect.adjusted(0, 0, -2, 0) : option->rect.adjusted(2, 0, 0, 0); + const QRectF rect = option->rect; const QPointF center = rect.center(); painter->setPen(borderPenControlAlt(option)); @@ -1059,6 +1052,18 @@ void QWindows11Style::drawPrimitive(PrimitiveElement element, const QStyleOption painter->setBrush(vopt->palette.base()); painter->drawRect(rect); + if (option->state & State_Selected && !highContrastTheme) { + // keep in sync with CE_ItemViewItem QListView indicator painting + const auto col = option->palette.accent().color(); + painter->setBrush(col); + painter->setPen(col); + const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f; + const auto yOfs = rect.height() / 4.; + QRectF r(QPointF(xPos, rect.y() + yOfs), + QPointF(xPos + 1, rect.y() + rect.height() - yOfs)); + painter->drawRoundedRect(r, 1, 1); + } + const bool isTreeDecoration = vopt->features.testFlag( QStyleOptionViewItem::IsDecorationForRootColumn); if (isTreeDecoration && vopt->state.testAnyFlags(State_Selected | State_MouseOver) && @@ -1186,11 +1191,14 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op painter->setRenderHint(QPainter::Antialiasing); switch (element) { case QStyle::CE_ComboBoxLabel: +#if QT_CONFIG(combobox) if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { + painter->setPen(controlTextColor(option)); QStyleOptionComboBox newOption = *cb; newOption.rect.adjust(4,0,-4,0); QCommonStyle::drawControl(element, &newOption, painter, widget); } +#endif // QT_CONFIG(combobox) break; case QStyle::CE_TabBarTabShape: #if QT_CONFIG(tabbar) @@ -1433,26 +1441,6 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget)) tf |= Qt::TextHideMnemonic; - if (btn->features & QStyleOptionButton::HasMenu) { - QPainterStateGuard psg(painter); - - const auto indSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget); - const auto indRect = QRect(btn->rect.right() - indSize - contentItemHMargin, textRect.top(), - indSize + contentItemHMargin, btn->rect.height()); - const auto vindRect = visualRect(btn->direction, btn->rect, indRect); - textRect.setWidth(textRect.width() - indSize); - - int fontSize = painter->font().pointSize(); - QFont f(d->assetFont); - f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller - painter->setFont(f); - QColor penColor = option->palette.color(isEnabled ? QPalette::Active : QPalette::Disabled, - QPalette::Text); - if (isEnabled) - penColor.setAlpha(percentToAlpha(60.63)); // fillColorTextSecondary - painter->setPen(penColor); - painter->drawText(vindRect, Qt::AlignCenter, ChevronDownMed); - } if (!btn->icon.isNull()) { //Center both icon and text QIcon::Mode mode = isEnabled ? QIcon::Normal : QIcon::Disabled; @@ -1479,6 +1467,8 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op break; case CE_PushButtonBevel: if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) { + using namespace StyleOptionHelper; + QRectF rect = btn->rect.marginsRemoved(QMargins(2, 2, 2, 2)); painter->setPen(Qt::NoPen); if (btn->features.testFlag(QStyleOptionButton::Flat)) { @@ -1505,6 +1495,29 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op painter->setPen(defaultButton ? WINUI3Colors[colorSchemeIndex][controlStrokeOnAccentSecondary] : WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]); } + if (btn->features.testFlag(QStyleOptionButton::HasMenu)) { + QPainterStateGuard psg(painter); + + const bool isEnabled = !isDisabled(option); + QRect textRect = btn->rect.marginsRemoved(QMargins(contentHMargin, 0, contentHMargin, 0)); + const auto indSize = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget); + const auto indRect = + QRect(btn->rect.right() - indSize - contentItemHMargin, textRect.top(), + indSize + contentItemHMargin, btn->rect.height()); + const auto vindRect = visualRect(btn->direction, btn->rect, indRect); + textRect.setWidth(textRect.width() - indSize); + + int fontSize = painter->font().pointSize(); + QFont f(d->assetFont); + f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller + painter->setFont(f); + QColor penColor = option->palette.color( + isEnabled ? QPalette::Active : QPalette::Disabled, QPalette::Text); + if (isEnabled) + penColor.setAlpha(percentToAlpha(60.63)); // fillColorTextSecondary + painter->setPen(penColor); + painter->drawText(vindRect, Qt::AlignCenter, ChevronDownMed); + } } break; case CE_MenuBarItem: @@ -1856,7 +1869,7 @@ QRect QWindows11Style::subElementRect(QStyle::SubElement element, const QStyleOp case QStyle::SE_RadioButtonIndicator: case QStyle::SE_CheckBoxIndicator: ret = QWindowsVistaStyle::subElementRect(element, option, widget); - ret = ret.marginsRemoved(QMargins(4,0,0,0)); + ret.moveLeft(contentItemHMargin); break; case QStyle::SE_ComboBoxFocusRect: case QStyle::SE_CheckBoxFocusRect: @@ -2061,6 +2074,20 @@ QRect QWindows11Style::subControlRect(ComplexControl control, const QStyleOption } break; } + case CC_ComboBox: { + if (subControl == SC_ComboBoxArrow) { + const auto indicatorWidth = + proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget); + const int endX = option->rect.right() - contentHMargin - 2; + const int startX = endX - indicatorWidth; + const QRect rect(QPoint(startX, option->rect.top()), + QPoint(endX, option->rect.bottom())); + ret = visualRect(option->direction, option->rect, rect); + } else { + ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget); + } + break; + } default: ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget); } @@ -2151,14 +2178,18 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o break; } #endif +#if QT_CONFIG(combobox) case CT_ComboBox: if (const auto *comboBoxOpt = qstyleoption_cast<const QStyleOptionComboBox *>(option)) { contentSize = QWindowsStyle::sizeFromContents(type, option, size, widget); // don't rely on QWindowsThemeData contentSize += QSize(4, 4); // default win11 style margins - if (comboBoxOpt->subControls & SC_ComboBoxArrow) - contentSize += QSize(8, 0); // arrow margins + if (comboBoxOpt->subControls & SC_ComboBoxArrow) { + const auto w = proxy()->pixelMetric(PM_MenuButtonIndicator, option, widget); + contentSize.rwidth() += w + contentItemHMargin; + } } break; +#endif case CT_HeaderSection: // windows vista does not honor the indicator (as it was drawn above the text, not on the // side) so call QWindowsStyle::styleHint directly to get the correct size hint @@ -2166,6 +2197,27 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o break; case CT_RadioButton: case CT_CheckBox: + if (const auto *buttonOpt = qstyleoption_cast<const QStyleOptionButton *>(option)) { + const auto p = proxy(); + const bool isRadio = (type == CT_RadioButton); + + const int width = p->pixelMetric( + isRadio ? PM_ExclusiveIndicatorWidth : PM_IndicatorWidth, option, widget); + const int height = p->pixelMetric( + isRadio ? PM_ExclusiveIndicatorHeight : PM_IndicatorHeight, option, widget); + + int margins = 2 * contentItemHMargin; + if (!buttonOpt->icon.isNull() || !buttonOpt->text.isEmpty()) { + margins += p->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing + : PM_CheckBoxLabelSpacing, + option, widget); + } + + contentSize += QSize(width + margins, 4); + contentSize.setHeight(qMax(size.height(), height + 2 * contentItemHMargin)); + } + break; + // the indicator needs 2px more in width when there is no text, not needed when // the style draws the text contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget); @@ -2217,12 +2269,24 @@ int QWindows11Style::pixelMetric(PixelMetric metric, const QStyleOption *option, case PM_SliderLength: // same because handle is a circle with r=8 res += 2 * 8; break; + case PM_RadioButtonLabelSpacing: + case PM_CheckBoxLabelSpacing: + res = 2 * contentItemHMargin; + break; case QStyle::PM_TitleBarButtonIconSize: res = 16; break; case QStyle::PM_TitleBarButtonSize: res = 32; break; +#if QT_CONFIG(toolbar) + case PM_ToolBarExtensionExtent: + res = int(QStyleHelper::dpiScaled(32., option)); + break; + case PM_ToolBarHandleExtent: + res = int(QStyleHelper::dpiScaled(8., option)); + break; +#endif // QT_CONFIG(toolbar) case QStyle::PM_ScrollBarExtent: res = 12; break; @@ -2233,10 +2297,17 @@ int QWindows11Style::pixelMetric(PixelMetric metric, const QStyleOption *option, res = contentItemHMargin; if (widget) { const int fontSize = widget->font().pointSize(); - QFont f(d->assetFont); - f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller - QFontMetrics fm(f); - res += fm.horizontalAdvance(ChevronDownMed); + auto it = m_fontPoint2ChevronDownMedWidth.find(fontSize); + if (it == m_fontPoint2ChevronDownMedWidth.end()) { + QFont f(d->assetFont); + f.setPointSize(qRound(fontSize * 0.9f)); // a little bit smaller + QFontMetrics fm(f); + const auto width = fm.horizontalAdvance(ChevronDownMed); + m_fontPoint2ChevronDownMedWidth.insert(fontSize, width); + res += width; + } else { + res += it.value(); + } } else { res += 12; } @@ -2249,6 +2320,9 @@ int QWindows11Style::pixelMetric(PixelMetric metric, const QStyleOption *option, case PM_ButtonShiftVertical: res = 0; break; + case PM_TreeViewIndentation: + res = 30; + break; default: res = QWindowsVistaStyle::pixelMetric(metric, option, widget); } @@ -2336,6 +2410,13 @@ void QWindows11Style::unpolish(QWidget *widget) widget->setProperty("_q_original_menubar_maxheight", QVariant()); } #endif + const auto comboBoxContainer = qobject_cast<const QComboBoxPrivateContainer *>(widget); + if (comboBoxContainer) { + widget->setAttribute(Qt::WA_OpaquePaintEvent, true); + widget->setAttribute(Qt::WA_TranslucentBackground, false); + widget->setWindowFlag(Qt::FramelessWindowHint, false); + widget->setWindowFlag(Qt::NoDropShadowWindowHint, false); + } if (const auto *scrollarea = qobject_cast<QAbstractScrollArea *>(widget); scrollarea @@ -2459,6 +2540,44 @@ void QWindows11Style::polish(QPalette& result) d->m_titleBarMaxIcon = QIcon(); d->m_titleBarCloseIcon = QIcon(); d->m_titleBarNormalIcon = QIcon(); + d->m_toolbarExtensionButton = QIcon(); +} + +QPixmap QWindows11Style::standardPixmap(StandardPixmap standardPixmap, + const QStyleOption *option, + const QWidget *widget) const +{ + switch (standardPixmap) { + case SP_ToolBarHorizontalExtensionButton: + case SP_ToolBarVerticalExtensionButton: { + const int size = proxy()->pixelMetric(PM_ToolBarExtensionExtent, option, widget); + return standardIcon(standardPixmap, option, widget).pixmap(size); + } + default: + break; + } + return QWindowsVistaStyle::standardPixmap(standardPixmap, option, widget); +} + +QIcon QWindows11Style::standardIcon(StandardPixmap standardIcon, + const QStyleOption *option, + const QWidget *widget) const +{ + auto *d = const_cast<QWindows11StylePrivate*>(d_func()); + switch (standardIcon) { + case SP_ToolBarHorizontalExtensionButton: + case SP_ToolBarVerticalExtensionButton: { + if (d->m_toolbarExtensionButton.isNull()) { + auto e = new WinFontIconEngine(More.at(0), d->assetFont); + e->setScale(1.0); + d->m_toolbarExtensionButton = QIcon(e); + } + return d->m_toolbarExtensionButton; + } + default: + break; + } + return QWindowsVistaStyle::standardIcon(standardIcon, option, widget); } QColor QWindows11Style::calculateAccentColor(const QStyleOption *option) const diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h index 130a96430da..736caae956c 100644 --- a/src/plugins/styles/modernwindows/qwindows11style_p.h +++ b/src/plugins/styles/modernwindows/qwindows11style_p.h @@ -85,6 +85,10 @@ public: const QWidget *widget = nullptr) const override; void polish(QPalette &pal) override; void unpolish(QWidget *widget) override; + QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option = nullptr, + const QWidget *widget = nullptr) const override; + QIcon standardIcon(StandardPixmap standardIcon, const QStyleOption *option = nullptr, + const QWidget *widget = nullptr) const override; protected: QWindows11Style(QWindows11StylePrivate &dd); @@ -110,10 +114,15 @@ private: bool highContrastTheme = false; int colorSchemeIndex = 0; + + mutable QVarLengthFlatMap<int, int, 8> m_fontPoint2ChevronDownMedWidth; }; class QWindows11StylePrivate : public QWindowsVistaStylePrivate { Q_DECLARE_PUBLIC(QWindows11Style) + +protected: + QIcon m_toolbarExtensionButton; }; QT_END_NAMESPACE diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp index 85d55f27bb7..22ca18b10bf 100644 --- a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp +++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp @@ -1626,6 +1626,12 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt break; case PE_Frame: + if (widget && widget->inherits("QComboBoxPrivateContainer")){ + QStyleOption copy = *option; + copy.state |= State_Raised; + proxy()->drawPrimitive(PE_PanelMenu, ©, painter, widget); + break; + } #if QT_CONFIG(accessibility) if (QStyleHelper::isInstanceOf(option->styleObject, QAccessible::EditableText) || QStyleHelper::isInstanceOf(option->styleObject, QAccessible::StaticText) || @@ -1704,6 +1710,14 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt return; } + case PE_PanelMenu: + if (widget && widget->inherits("QComboBoxPrivateContainer")){ + //fill combobox popup background + QWindowsThemeData popupbackgroundTheme(widget, painter, QWindowsVistaStylePrivate::MenuTheme, + MENU_POPUPBACKGROUND, stateId, option->rect); + d->drawBackground(popupbackgroundTheme); + } + case PE_PanelMenuBar: break; @@ -4968,6 +4982,11 @@ QString WinFontIconEngine::string() const return m_glyph; } +void WinFontIconEngine::setScale(double scale) +{ + m_scale = scale; +} + void WinFontIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State) { @@ -4994,7 +5013,7 @@ void WinFontIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode break; } QFont renderFont(m_font); - renderFont.setPixelSize(rect.height() * 0.7f); + renderFont.setPixelSize(rect.height() * m_scale); painter->save(); painter->setFont(renderFont); painter->setPen(color); diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h b/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h index e8aad528f90..cf982ceb133 100644 --- a/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h +++ b/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h @@ -189,11 +189,13 @@ public: QString key() const override; QIconEngine *clone() const override; QString string() const override; + void setScale(double scale); void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override; protected: QFont m_font; QChar m_glyph; + double m_scale = 0.7; }; QT_END_NAMESPACE |
