diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-08-29 17:38:25 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-09-05 12:14:23 +0200 |
commit | 176bd1edfadcb68b914a27de75502edeb1081253 (patch) | |
tree | 828d63a130e4f3bcfc6427ee4c79a8b5ec7f0464 | |
parent | b858e7af4fefeed051f5a7e0795872fd1b834220 (diff) |
Windows styles: Add device pixel scaling for system metrics.
Metrics obtained from the system must be scaled down
when device pixel ration scaling is in effect. Factor out
functions to return the device pixel values which might still
be used for drawing.
Task-number: QTBUG-38993
Task-number: QTBUG-38858
Change-Id: I6b90629e4979436bbb46f8c1fa1ee2253ada7ece
Reviewed-by: Alessandro Portale <alessandro.portale@digia.com>
-rw-r--r-- | src/widgets/styles/qwindowsstyle.cpp | 139 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsstyle_p_p.h | 10 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsvistastyle.cpp | 102 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsxpstyle.cpp | 269 | ||||
-rw-r--r-- | src/widgets/styles/qwindowsxpstyle_p_p.h | 68 |
5 files changed, 291 insertions, 297 deletions
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index cf0afd8031..44242177dc 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -118,6 +118,9 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; /* \internal */ + +int QWindowsStylePrivate::m_appDevicePixelRatio = 0; + QWindowsStylePrivate::QWindowsStylePrivate() : alt_down(false), menuBarTimer(0) { @@ -130,6 +133,13 @@ QWindowsStylePrivate::QWindowsStylePrivate() #endif } +int QWindowsStylePrivate::appDevicePixelRatio() +{ + if (!QWindowsStylePrivate::m_appDevicePixelRatio) + QWindowsStylePrivate::m_appDevicePixelRatio = qRound(qApp->devicePixelRatio()); + return QWindowsStylePrivate::m_appDevicePixelRatio; +} + // Returns \c true if the toplevel parent of \a widget has seen the Alt-key bool QWindowsStylePrivate::hasSeenAlt(const QWidget *widget) const { @@ -295,19 +305,76 @@ void QWindowsStyle::polish(QPalette &pal) QCommonStyle::polish(pal); } +int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget) +{ + switch (pm) { +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + case QStyle::PM_DockWidgetFrameWidth: +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CXFRAME); +# else + return GetSystemMetrics(SM_CXDLGFRAME); +# endif + break; + + case QStyle::PM_TitleBarHeight: + if (widget && (widget->windowType() == Qt::Tool)) { + // MS always use one less than they say +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CYSMCAPTION) - 1; +# else + return GetSystemMetrics(SM_CYCAPTION) - 1; +# endif + } + return GetSystemMetrics(SM_CYCAPTION) - 1; + +# ifndef Q_OS_WINCE + case QStyle::PM_ScrollBarExtent: + { + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) + return qMax(ncm.iScrollHeight, ncm.iScrollWidth); + } + break; +# endif // !Q_OS_WINCE + + case QStyle::PM_MdiSubWindowFrameWidth: +# ifndef Q_OS_WINCE + return GetSystemMetrics(SM_CYFRAME); +# else + return GetSystemMetrics(SM_CYDLGFRAME); +# endif +#else + Q_UNUSED(widget) +#endif // Q_OS_WIN + + default: + break; + } + return QWindowsStylePrivate::InvalidMetric; +} + /*! \reimp */ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QWidget *widget) const { - int ret; + int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget); + if (ret != QWindowsStylePrivate::InvalidMetric) + return ret / QWindowsStylePrivate::devicePixelRatio(widget); + + ret = 0; switch (pm) { + case PM_ToolBarItemSpacing: + break; case PM_ButtonDefaultIndicator: case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: case PM_MenuHMargin: case PM_MenuVMargin: + case PM_ToolBarItemMargin: ret = 1; break; case PM_DockWidgetSeparatorExtent: @@ -315,7 +382,6 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW break; #ifndef QT_NO_TABBAR case PM_TabBarTabShiftHorizontal: - ret = 0; break; case PM_TabBarTabShiftVertical: ret = 2; @@ -357,23 +423,14 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW if (space > 0) thick += (space * 2) / (n + 2); ret = thick; - } else { - ret = 0; } break; #endif // QT_NO_SLIDER #ifndef QT_NO_MENU case PM_MenuBarHMargin: - ret = 0; - break; - case PM_MenuBarVMargin: - ret = 0; - break; - case PM_MenuBarPanelWidth: - ret = 0; break; case PM_SmallIconSize: @@ -394,76 +451,16 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW case PM_DockWidgetTitleBarButtonMargin: ret = int(QStyleHelper::dpiScaled(4.)); break; -#if defined(Q_WS_WIN) - case PM_DockWidgetFrameWidth: -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CXDLGFRAME); -#else - ret = GetSystemMetrics(SM_CXFRAME); -#endif - break; -#else case PM_DockWidgetFrameWidth: ret = 4; break; -#endif // Q_WS_WIN break; #endif // QT_NO_MENU - - -#if defined(Q_OS_WIN) -#ifndef Q_OS_WINRT // There is no title bar in Windows Runtime applications - case PM_TitleBarHeight: - if (widget && (widget->windowType() == Qt::Tool)) { - // MS always use one less than they say -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CYCAPTION) - 1; -#else - ret = GetSystemMetrics(SM_CYSMCAPTION) - 1; -#endif - } else { - ret = GetSystemMetrics(SM_CYCAPTION) - 1; - } - - break; -#endif // !Q_OS_WINRT - - case PM_ScrollBarExtent: - { -#if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); - if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) - ret = qMax(ncm.iScrollHeight, ncm.iScrollWidth); - else -#endif // !Q_OS_WINCE && !Q_OS_WINRT - ret = QCommonStyle::pixelMetric(pm, opt, widget); - } - break; -#endif // Q_OS_WIN - case PM_SplitterWidth: ret = qMax(4, QApplication::globalStrut().width()); break; -#if defined(Q_OS_WIN) -#ifndef Q_OS_WINRT // Mdi concept not available for WinRT applications - case PM_MdiSubWindowFrameWidth: -#if defined(Q_OS_WINCE) - ret = GetSystemMetrics(SM_CYDLGFRAME); -#else - ret = GetSystemMetrics(SM_CYFRAME); -#endif - break; -#endif // !Q_OS_WINRT -#endif // Q_OS_WIN - case PM_ToolBarItemMargin: - ret = 1; - break; - case PM_ToolBarItemSpacing: - ret = 0; - break; case PM_ToolBarHandleExtent: ret = int(QStyleHelper::dpiScaled(10.)); break; diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h index 872b6f0e9e..8f70271357 100644 --- a/src/widgets/styles/qwindowsstyle_p_p.h +++ b/src/widgets/styles/qwindowsstyle_p_p.h @@ -68,7 +68,13 @@ class QWindowsStylePrivate : public QCommonStylePrivate { Q_DECLARE_PUBLIC(QWindowsStyle) public: + enum { InvalidMetric = -23576 }; + QWindowsStylePrivate(); + static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static int devicePixelRatio(const QWidget *widget = 0) + { return widget ? widget->devicePixelRatio() : QWindowsStylePrivate::appDevicePixelRatio(); } + bool hasSeenAlt(const QWidget *widget) const; bool altDown() const { return alt_down; } bool alt_down; @@ -90,6 +96,10 @@ public: windowsRightBorder = 15, // right border on windows windowsCheckMarkWidth = 12 // checkmarks width on windows }; + +private: + static int appDevicePixelRatio(); + static int m_appDevicePixelRatio; }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index 672f5c78ac..69e21d0f56 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -409,9 +409,11 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt XPThemeData theme(0, painter, QWindowsXPStylePrivate::TreeViewTheme); static int decoration_size = 0; if (d->initTreeViewTheming() && theme.isValid() && !decoration_size) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, TVP_HOTGLYPH, GLPS_OPENED, 0, TS_TRUE, &size); - decoration_size = qMax(size.cx, size.cy); + XPThemeData themeSize = theme; + themeSize.partId = TVP_HOTGLYPH; + themeSize.stateId = GLPS_OPENED; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + decoration_size = qMax(size.width(), size.height()); } int mid_h = option->rect.x() + option->rect.width() / 2; int mid_v = option->rect.y() + option->rect.height() / 2; @@ -990,10 +992,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme, TP_DROPDOWNBUTTON); if (theme.isValid()) { - SIZE size; - if (QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { - mbiw = size.cx; - mbih = size.cy; + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!size.isEmpty()) { + mbiw = size.width(); + mbih = size.height(); } } QRect ir = subElementRect(SE_PushButtonContents, option, 0); @@ -1183,13 +1185,14 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption // windows always has a check column, regardless whether we have an icon or not int checkcol = 25; { - SIZE size; - MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); - checkcol = qMax(menuitem->maxIconWidth, int(3 + size.cx + margins.cxLeftWidth + margins.cxRightWidth)); + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + checkcol = qMax(menuitem->maxIconWidth, int(3 + size.width() + margins.left() + margins.right())); } QRect rect = option->rect; @@ -1241,20 +1244,20 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, menuitem->icon.isNull() ? MBI_HOT : MBI_PUSHED, vCheckRect); - SIZE size; - MARGINS margins; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, - TMT_CONTENTMARGINS, NULL, &margins); - QRect checkRect(0, 0, size.cx + margins.cxLeftWidth + margins.cxRightWidth , - size.cy + margins.cyBottomHeight + margins.cyTopHeight); + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QRect checkRect(0, 0, size.width() + margins.left() + margins.right(), + size.height() + margins.bottom() + margins.top()); checkRect.moveCenter(vCheckRect.center()); theme.rect = checkRect; d->drawBackground(theme); if (menuitem->icon.isNull()) { - checkRect = QRect(0, 0, size.cx, size.cy); + checkRect = QRect(QPoint(0, 0), size); checkRect.moveCenter(theme.rect.center()); theme.rect = checkRect; @@ -1763,29 +1766,21 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle const int swidth = theme.rect.width(); const int sheight = theme.rect.height(); - MARGINS contentsMargin; - RECT rect = theme.toRECT(theme.rect); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + const QMargins contentsMargin = theme.margins(theme.rect, TMT_SIZINGMARGINS) + / QWindowsXPStylePrivate::devicePixelRatio(widget); - SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - int gw = size.cx, gh = size.cy; - + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) { - QRect gripperBounds; - if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); - } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); + QPoint gripperBoundsPos(0, 0); + if ((flags & State_Horizontal + && swidth - contentsMargin.left() - contentsMargin.right() > size.width()) + || sheight - contentsMargin.top() - contentsMargin.bottom() > size.height()) { + gripperBoundsPos = QPoint(theme.rect.left() + (swidth - size.width()) / 2, + theme.rect.top() + (sheight - size.height()) / 2); } + const QRect gripperBounds(gripperBoundsPos, size); // Draw gripper if there is enough space if (!gripperBounds.isEmpty() && flags & State_Enabled) { @@ -1883,15 +1878,16 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption sz = QWindowsXPStyle::sizeFromContents(type, option, size, widget); int minimumHeight; { - SIZE size; - MARGINS margins; XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), NULL, MENU_POPUPCHECK, 0, NULL,TS_TRUE, &size); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), NULL, MENU_POPUPCHECK, 0, TMT_CONTENTMARGINS, NULL, &margins); - minimumHeight = qMax<qint32>(size.cy + margins.cyBottomHeight+ margins.cyTopHeight, sz.height()); - sz.rwidth() += size.cx + margins.cxLeftWidth + margins.cxRightWidth; + XPThemeData themeSize = theme; + themeSize.partId = MENU_POPUPCHECK; + themeSize.stateId = 0; + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMargins margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + minimumHeight = qMax(size.height() + margins.bottom() + margins.top(), sz.height()); + sz.rwidth() += size.width() + margins.left() + margins.right(); } if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { @@ -1999,10 +1995,10 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int arrowWidth = 13; int arrowHeight = 5; if (theme.isValid()) { - SIZE size; - if (QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size) == S_OK) { - arrowWidth = size.cx; - arrowHeight = size.cy; + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!size.isEmpty()) { + arrowWidth = size.width(); + arrowHeight = size.height(); } } if (option->state & State_Horizontal) { @@ -2195,7 +2191,8 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - 4; const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0; @@ -2531,14 +2528,13 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon, QWindowsXPStylePrivate::ButtonTheme, BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); QIcon linkGlyph; - QPixmap pm = QPixmap(size.cx, size.cy); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); linkGlyph.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index 2e3586db42..424a1f7234 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -411,22 +411,21 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) height of the screen. This way the theme engine doesn't need to scale the body for every time we ask for it. (Speed optimization) */ -const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *) +const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget) { if (!tabbody) { - SIZE sz; XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY); - pGetThemePartSize(theme.handle(), qt_win_display_dc(), TABP_BODY, 0, 0, TS_TRUE, &sz); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); - tabbody = new QPixmap(sz.cx, QApplication::desktop()->screenGeometry().height()); + tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height()); QPainter painter(tabbody); - theme.rect = QRect(0, 0, sz.cx, sz.cy); + theme.rect = QRect(QPoint(0, 0), size); drawBackground(theme); // We fill with the last line of the themedata, that // way we don't get a tiled pixmap inside big tabs - QPixmap temp(sz.cx, 1); - painter.drawPixmap(0, 0, temp, 0, sz.cy-1, -1, -1); - painter.drawTiledPixmap(0, sz.cy, sz.cx, tabbody->height()-sz.cy, temp); + QPixmap temp(size.width(), 1); + painter.drawPixmap(0, 0, temp, 0, size.height() - 1, -1, -1); + painter.drawTiledPixmap(0, size.height(), size.width(), tabbody->height() - size.height(), temp); } return tabbody; } @@ -2002,25 +2001,24 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op { themeNumber = QWindowsXPStylePrivate::StatusTheme; partId = SP_GRIPPER; - SIZE sz; XPThemeData theme(0, p, themeNumber, partId, 0); - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, partId, 0, 0, TS_TRUE, &sz); - --sz.cy; + QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + size.rheight()--; if (const QStyleOptionSizeGrip *sg = qstyleoption_cast<const QStyleOptionSizeGrip *>(option)) { switch (sg->corner) { case Qt::BottomRightCorner: - rect = QRect(rect.right() - sz.cx, rect.bottom() - sz.cy, sz.cx, sz.cy); + rect = QRect(QPoint(rect.right() - size.width(), rect.bottom() - size.height()), size); break; case Qt::BottomLeftCorner: - rect = QRect(rect.left() + 1, rect.bottom() - sz.cy, sz.cx, sz.cy); + rect = QRect(QPoint(rect.left() + 1, rect.bottom() - size.height()), size); hMirrored = true; break; case Qt::TopRightCorner: - rect = QRect(rect.right() - sz.cx, rect.top() + 1, sz.cx, sz.cy); + rect = QRect(QPoint(rect.right() - size.width(), rect.top() + 1), size); vMirrored = true; break; case Qt::TopLeftCorner: - rect = QRect(rect.left() + 1, rect.top() + 1, sz.cx, sz.cy); + rect = QRect(rect.topLeft() + QPoint(1, 1), size); hMirrored = vMirrored = true; } } @@ -2075,10 +2073,9 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op QWindowsXPStylePrivate::ToolBarTheme, TP_SPLITBUTTONDROPDOWN); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - mbiw = size.cx; - mbih = size.cy; + const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + mbiw = size.width(); + mbih = size.height(); } QRect ir = btn->rect; @@ -2770,28 +2767,19 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo const int swidth = theme.rect.width(); const int sheight = theme.rect.height(); - MARGINS contentsMargin; - RECT rect = theme.toRECT(theme.rect); - QWindowsXPStylePrivate::pGetThemeMargins(theme.handle(), 0, theme.partId, theme.stateId, TMT_SIZINGMARGINS, &rect, &contentsMargin); + const QMargins contentsMargin = theme.margins(theme.rect, TMT_SIZINGMARGINS) + / QWindowsStylePrivate::devicePixelRatio(widget); - SIZE size; theme.partId = flags & State_Horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - int gw = size.cx, gh = size.cy; - - - QRect gripperBounds; - if (flags & State_Horizontal && ((swidth - contentsMargin.cxLeftWidth - contentsMargin.cxRightWidth) > gw)) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); - } else if ((sheight - contentsMargin.cyTopHeight - contentsMargin.cyBottomHeight) > gh) { - gripperBounds.setLeft(theme.rect.left() + swidth/2 - gw/2); - gripperBounds.setTop(theme.rect.top() + sheight/2 - gh/2); - gripperBounds.setWidth(gw); - gripperBounds.setHeight(gh); + const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QPoint gripperBoundsPos(0, 0); + if ((flags & State_Horizontal + && swidth - contentsMargin.left() - contentsMargin.right() > size.width()) + || sheight - contentsMargin.top() - contentsMargin.bottom() > size.height()) { + gripperBoundsPos = QPoint(theme.rect.left() + (swidth - size.width()) / 2, + theme.rect.top() + (sheight - size.height()) /2); } + const QRect gripperBounds(gripperBoundsPos, size); // Draw gripper if there is enough space if (!gripperBounds.isEmpty()) { @@ -3113,9 +3101,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } else { theme.partId = partId; theme.stateId = stateId; - SIZE sz; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz); - if (sz.cx == 0 || sz.cy == 0) { + if (theme.size().isEmpty()) { int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget); QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize); p->save(); @@ -3330,23 +3316,63 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } } +static inline Qt::Orientation progressBarOrientation(const QStyleOption *option = 0) +{ + if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) + return pb2->orientation; + return Qt::Horizontal; +} + +int QWindowsXPStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option, const QWidget *widget) +{ + switch (pm) { + case QStyle::PM_IndicatorWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).width(); + case QStyle::PM_IndicatorHeight: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL).height(); + case QStyle::PM_ExclusiveIndicatorWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).width(); + case QStyle::PM_ExclusiveIndicatorHeight: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL).height(); + case QStyle::PM_ProgressBarChunkWidth: + return progressBarOrientation(option) == Qt::Horizontal + ? XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNK).width() + : XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::ProgressTheme, PP_CHUNKVERT).height(); + case QStyle::PM_SliderThickness: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::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_MdiSubWindowFrameWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE).width(); + case QStyle::PM_DockWidgetFrameWidth: + return XPThemeData::themeSize(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE).width(); + default: + break; + } + return QWindowsXPStylePrivate::InvalidMetric; +} + /*! \reimp */ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, const QWidget *widget) const { if (!QWindowsXPStylePrivate::useXP()) return QWindowsStyle::pixelMetric(pm, option, widget); - int res = 0; + int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget); + if (res != QWindowsStylePrivate::InvalidMetric) + return res / QWindowsStylePrivate::devicePixelRatio(widget); + + res = 0; switch (pm) { case PM_MenuBarPanelWidth: + case PM_ButtonDefaultIndicator: res = 0; break; case PM_DefaultFrameWidth: - if (qobject_cast<const QListView*>(widget)) - res = 2; - else - res = 1; + res = qobject_cast<const QListView*>(widget) ? 2 : 1; break; case PM_MenuPanelWidth: case PM_SpinBoxFrameWidth: @@ -3364,6 +3390,8 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con switch (tab->shape) { case QTabBar::RoundedNorth: case QTabBar::TriangularNorth: + case QTabBar::RoundedWest: + case QTabBar::TriangularWest: res = 1; break; case QTabBar::RoundedSouth: @@ -3374,10 +3402,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con case QTabBar::TriangularEast: res = 3; break; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - res = 1; - break; } } break; @@ -3386,77 +3410,6 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con res = qMax(int(QStyleHelper::dpiScaled(5.)), QApplication::globalStrut().width()); break; - case PM_IndicatorWidth: - case PM_IndicatorHeight: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_CHECKBOX, CBS_UNCHECKEDNORMAL); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (pm == PM_IndicatorWidth) ? size.cx : size.cy; - } - } - break; - - case PM_ExclusiveIndicatorWidth: - case PM_ExclusiveIndicatorHeight: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_RADIOBUTTON, RBS_UNCHECKEDNORMAL); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (pm == PM_ExclusiveIndicatorWidth) ? size.cx : size.cy; - } - } - break; - - case PM_ProgressBarChunkWidth: - { - Qt::Orientation orient = Qt::Horizontal; - if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(option)) - orient = pb2->orientation; - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ProgressTheme, - (orient == Qt::Horizontal) ? PP_CHUNK : PP_CHUNKVERT); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = (orient == Qt::Horizontal) ? size.cx : size.cy; - } - } - break; - - case PM_SliderThickness: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::TrackBarTheme, - TKP_THUMB); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cy; - } - } - break; - - case PM_TitleBarHeight: - { - if (widget && (widget->windowType() == Qt::Tool)) - res = GetSystemMetrics(SM_CYSMCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - else - res = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXSIZEFRAME); - } - break; - - case PM_MdiSubWindowFrameWidth: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_FRAMELEFT, FS_ACTIVE); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, WP_FRAMELEFT, FS_ACTIVE, 0, TS_TRUE, &size); - res = size.cx-1; - } - } - break; - case PM_MdiSubWindowMinimizedWidth: res = 160; break; @@ -3467,33 +3420,14 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con break; #endif // QT_NO_TOOLBAR - case PM_DockWidgetFrameWidth: - { - XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLFRAMERIGHT, FS_ACTIVE); - if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - res = size.cx; - } - } - break; case PM_DockWidgetSeparatorExtent: - res = int(QStyleHelper::dpiScaled(4.)); - break; case PM_DockWidgetTitleMargin: res = int(QStyleHelper::dpiScaled(4.)); break; case PM_ButtonShiftHorizontal: case PM_ButtonShiftVertical: - if (qstyleoption_cast<const QStyleOptionToolButton *>(option)) - res = 1; - else - res = 0; - break; - - case PM_ButtonDefaultIndicator: - res = 0; + res = qstyleoption_cast<const QStyleOptionToolButton *>(option) ? 1 : 0; break; default: @@ -3573,8 +3507,11 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl const bool isToolTitle = false; const int height = tb->rect.height(); const int width = tb->rect.width(); - int buttonHeight = GetSystemMetrics(SM_CYSIZE) - 4; - int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4; + const int buttonMargin = 4; + int buttonHeight = GetSystemMetrics(SM_CYSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - buttonMargin; + int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + - buttonMargin; const int delta = buttonWidth + 2; int controlTop = option->rect.bottom() - buttonHeight - 2; const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget); @@ -3766,20 +3703,12 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt case CT_LineEdit: case CT_ComboBox: { - XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme); - HTHEME theme = buttontheme.handle(); - MARGINS borderSize; - if (theme) { - int result = QWindowsXPStylePrivate::pGetThemeMargins(theme, - NULL, - BP_PUSHBUTTON, - PBS_NORMAL, - TMT_CONTENTMARGINS, - NULL, - &borderSize); - if (result == S_OK) { - sz += QSize(borderSize.cxLeftWidth + borderSize.cxRightWidth - 2, - borderSize.cyBottomHeight + borderSize.cyTopHeight - 2); + XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); + if (buttontheme.isValid()) { + const QMargins borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + if (!borderSize.isNull()) { + sz.rwidth() += borderSize.left() + borderSize.right() - 2; + sz.rheight() += borderSize.bottom() + borderSize.top() - 2; } const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) @@ -3949,9 +3878,8 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt if (widget && widget->isWindow()) { XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - SIZE sz; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &sz); - return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(QSize(sz.cx, sz.cy)); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size); } } } @@ -3984,13 +3912,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_MAXBUTTON, MAXBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); @@ -4019,14 +3946,13 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(theme.handle(), 0, theme.partId, theme.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; theme.partId = WP_CLOSEBUTTON; // #### - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockClose.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); @@ -4056,13 +3982,12 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_RESTOREBUTTON, RBS_NORMAL); if (theme.isValid()) { - SIZE size; - QWindowsXPStylePrivate::pGetThemePartSize(themeSize.handle(), 0, themeSize.partId, themeSize.stateId, 0, TS_TRUE, &size); - QPixmap pm = QPixmap(size.cx, size.cy); + const QSize size = themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); theme.painter = &p; - theme.rect = QRect(0, 0, size.cx, size.cy); + theme.rect = QRect(QPoint(0, 0), size); d->drawBackground(theme); d->dockFloat.addPixmap(pm, QIcon::Normal, QIcon::Off); // Normal pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index 190055b24b..0ead58393f 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -219,9 +219,19 @@ public: HRGN mask(QWidget *widget); HTHEME handle(); - RECT toRECT(const QRect &qr); + static RECT toRECT(const QRect &qr); bool isValid(); + QSize size(); + QMargins margins(const QRect &rect, int propId = TMT_CONTENTMARGINS); + QMargins margins(int propId = TMT_CONTENTMARGINS); + + static QSize themeSize(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, int part = 0, int state = 0); + static QMargins themeMargins(const QRect &rect, const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, + int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); + static QMargins themeMargins(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, + int part = 0, int state = 0, int propId = TMT_CONTENTMARGINS); + const QWidget *widget; QPainter *painter; @@ -374,6 +384,8 @@ public: ~QWindowsXPStylePrivate() { cleanup(); } + static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); + static HWND winId(const QWidget *widget); void init(bool force = false); @@ -432,6 +444,60 @@ private: static HTHEME m_themes[NThemes]; }; +inline QSize XPThemeData::size() +{ + QSize result(0, 0); + if (isValid()) { + SIZE size; + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemePartSize(handle(), 0, partId, stateId, 0, TS_TRUE, &size))) + result = QSize(size.cx, size.cy); + } + return result; +} + +inline QMargins XPThemeData::margins(const QRect &qRect, int propId) +{ + QMargins result(0, 0, 0 ,0); + if (isValid()) { + MARGINS margins; + RECT rect = XPThemeData::toRECT(qRect); + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, &rect, &margins))) + result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); + } + return result; +} + +inline QMargins XPThemeData::margins(int propId) +{ + QMargins result(0, 0, 0 ,0); + if (isValid()) { + MARGINS margins; + if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, NULL, &margins))) + result = QMargins(margins.cxLeftWidth, margins.cyTopHeight, margins.cxRightWidth, margins.cyBottomHeight); + } + return result; +} + +inline QSize XPThemeData::themeSize(const QWidget *w, QPainter *p, int themeIn, int part, int state) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.size(); +} + +inline QMargins XPThemeData::themeMargins(const QRect &rect, const QWidget *w, QPainter *p, int themeIn, + int part, int state, int propId) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.margins(rect, propId); +} + +inline QMargins XPThemeData::themeMargins(const QWidget *w, QPainter *p, int themeIn, + int part, int state, int propId) +{ + XPThemeData theme(w, p, themeIn, part, state); + return theme.margins(propId); +} + #endif // QT_NO_STYLE_WINDOWS QT_END_NAMESPACE |