From 34a984c80739d034b6c0c9e0f29c73b03ddc5aa1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 1 Mar 2016 15:40:52 +0100 Subject: Windows XP style: Change theme logic to use qreal. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid rounding errors, thus preventing sizes becoming too small when High DPI scaling is in effect. Also fix division by zero crashes should a scale factor be below 1. Task-number: QTBUG-49374 Task-number: QTBUG-51552 Change-Id: I72718521bc3c7f6b0e42392ea2d2d3bbc61e2faa Reviewed-by: Marko Kangas Reviewed-by: Morten Johan Sørvig Reviewed-by: Alessandro Portale --- src/widgets/styles/qwindowsstyle.cpp | 10 ++----- src/widgets/styles/qwindowsstyle_p_p.h | 7 ++--- src/widgets/styles/qwindowsvistastyle.cpp | 47 ++++++++++++++++--------------- src/widgets/styles/qwindowsxpstyle.cpp | 32 ++++++++++----------- src/widgets/styles/qwindowsxpstyle_p_p.h | 38 ++++++++++++------------- 5 files changed, 65 insertions(+), 69 deletions(-) (limited to 'src/widgets/styles') diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 5d02bc17ae..ab3c8df256 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -111,8 +111,6 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; \internal */ -int QWindowsStylePrivate::m_appDevicePixelRatio = 0; - QWindowsStylePrivate::QWindowsStylePrivate() : alt_down(false), menuBarTimer(0) { @@ -125,11 +123,9 @@ QWindowsStylePrivate::QWindowsStylePrivate() #endif } -int QWindowsStylePrivate::appDevicePixelRatio() +qreal QWindowsStylePrivate::appDevicePixelRatio() { - if (!QWindowsStylePrivate::m_appDevicePixelRatio) - QWindowsStylePrivate::m_appDevicePixelRatio = qRound(qApp->devicePixelRatio()); - return QWindowsStylePrivate::m_appDevicePixelRatio; + return qApp->devicePixelRatio(); } // Returns \c true if the toplevel parent of \a widget has seen the Alt-key @@ -406,7 +402,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW { int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget); if (ret != QWindowsStylePrivate::InvalidMetric) - return ret / QWindowsStylePrivate::devicePixelRatio(widget); + return qRound(qreal(ret) / QWindowsStylePrivate::devicePixelRatio(widget)); ret = QWindowsStylePrivate::fixedPixelMetric(pm); if (ret != QWindowsStylePrivate::InvalidMetric) diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h index c8778cc914..7971b84923 100644 --- a/src/widgets/styles/qwindowsstyle_p_p.h +++ b/src/widgets/styles/qwindowsstyle_p_p.h @@ -64,8 +64,8 @@ public: QWindowsStylePrivate(); static int pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *option = 0, const QWidget *widget = 0); static int fixedPixelMetric(QStyle::PixelMetric pm); - static int devicePixelRatio(const QWidget *widget = 0) - { return widget ? int(widget->devicePixelRatioF()) : QWindowsStylePrivate::appDevicePixelRatio(); } + static qreal devicePixelRatio(const QWidget *widget = 0) + { return widget ? widget->devicePixelRatioF() : QWindowsStylePrivate::appDevicePixelRatio(); } bool hasSeenAlt(const QWidget *widget) const; bool altDown() const { return alt_down; } @@ -90,8 +90,7 @@ public: }; private: - static int appDevicePixelRatio(); - static int m_appDevicePixelRatio; + static qreal appDevicePixelRatio(); }; QT_END_NAMESPACE diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index d900e4d181..2266c03484 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -419,8 +419,8 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt 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()); + const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + decoration_size = qRound(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; @@ -985,10 +985,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme, TP_DROPDOWNBUTTON); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSizeF size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (!size.isEmpty()) { - mbiw = size.width(); - mbih = size.height(); + mbiw = qRound(size.width()); + mbih = qRound(size.height()); } } QRect ir = subElementRect(SE_PushButtonContents, option, 0); @@ -1172,17 +1172,18 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption case CE_MenuItem: if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { // windows always has a check column, regardless whether we have an icon or not - int checkcol = 25 / QWindowsXPStylePrivate::devicePixelRatio(widget); - const int gutterWidth = 3 / QWindowsXPStylePrivate::devicePixelRatio(widget); + const qreal devicePixelRatio = QWindowsXPStylePrivate::devicePixelRatio(widget); + int checkcol = qRound(qreal(25) / devicePixelRatio); + const int gutterWidth = qRound(qreal(3) / devicePixelRatio); { XPThemeData theme(widget, 0, QWindowsXPStylePrivate::MenuTheme, MENU_POPUPCHECKBACKGROUND, MBI_HOT); 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, gutterWidth + size.width() + margins.left() + margins.right()); + const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + checkcol = qMax(menuitem->maxIconWidth, qRound(gutterWidth + size.width() + margins.left() + margins.right())); } QRect rect = option->rect; @@ -1239,17 +1240,17 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption 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()); + const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + QRect checkRect(0, 0, qRound(size.width() + margins.left() + margins.right()), + qRound(size.height() + margins.bottom() + margins.top())); checkRect.moveCenter(vCheckRect.center()); theme.rect = checkRect; d->drawBackground(theme); if (menuitem->icon.isNull()) { - checkRect = QRect(QPoint(0, 0), size); + checkRect = QRect(QPoint(0, 0), size.toSize()); checkRect.moveCenter(theme.rect.center()); theme.rect = checkRect; @@ -1855,10 +1856,10 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption 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(); + const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + minimumHeight = qMax(qRound(size.height() + margins.bottom() + margins.top()), sz.height()); + sz.rwidth() += qRound(size.width() + margins.left() + margins.right()); } if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast(option)) { @@ -1966,10 +1967,10 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption int arrowWidth = 13; int arrowHeight = 5; if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSizeF size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (!size.isEmpty()) { - arrowWidth = size.width(); - arrowHeight = size.height(); + arrowWidth = qRound(size.width()); + arrowHeight = qRound(size.height()); } } if (option->state & State_Horizontal) { @@ -2510,7 +2511,7 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon, QWindowsXPStylePrivate::ButtonTheme, BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); QIcon linkGlyph; QPixmap pm(size); pm.fill(Qt::transparent); diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index e68acdf5cf..88b1b41f15 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -423,7 +423,7 @@ const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget) { if (!tabbody) { XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY); - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height()); QPainter painter(tabbody); @@ -2042,7 +2042,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op themeNumber = QWindowsXPStylePrivate::StatusTheme; partId = SP_GRIPPER; XPThemeData theme(0, p, themeNumber, partId, 0); - QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + QSize size = (theme.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize(); size.rheight()--; if (const QStyleOptionSizeGrip *sg = qstyleoption_cast(option)) { switch (sg->corner) { @@ -2113,7 +2113,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op QWindowsXPStylePrivate::ToolBarTheme, TP_SPLITBUTTONDROPDOWN); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize(); mbiw = size.width(); mbih = size.height(); } @@ -2576,10 +2576,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const QWidget *widget, XPThemeData *theme) { const bool horizontal = flags & QStyle::State_Horizontal; - const QMargins contentsMargin = theme->margins(theme->rect, TMT_SIZINGMARGINS) - / QWindowsStylePrivate::devicePixelRatio(widget); + const QMargins contentsMargin = (theme->margins(theme->rect, TMT_SIZINGMARGINS) + / QWindowsStylePrivate::devicePixelRatio(widget)).toMargins(); theme->partId = horizontal ? SBP_GRIPPERHORZ : SBP_GRIPPERVERT; - const QSize size = theme->size() / QWindowsStylePrivate::devicePixelRatio(widget); + const QSize size = (theme->size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize(); const int hSpace = theme->rect.width() - size.width(); const int vSpace = theme->rect.height() - size.height(); @@ -3394,7 +3394,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget); if (res != QWindowsStylePrivate::InvalidMetric) - return res / QWindowsStylePrivate::devicePixelRatio(widget); + return qRound(qreal(res) / QWindowsStylePrivate::devicePixelRatio(widget)); res = 0; switch (pm) { @@ -3540,9 +3540,9 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl const int height = tb->rect.height(); const int width = tb->rect.width(); const int buttonMargin = int(QStyleHelper::dpiScaled(4)); - int buttonHeight = GetSystemMetrics(SM_CYSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + int buttonHeight = qRound(qreal(GetSystemMetrics(SM_CYSIZE)) / QWindowsStylePrivate::devicePixelRatio(widget)) - buttonMargin; - int buttonWidth = GetSystemMetrics(SM_CXSIZE) / QWindowsStylePrivate::devicePixelRatio(widget) + int buttonWidth = qRound(qreal(GetSystemMetrics(SM_CXSIZE)) / QWindowsStylePrivate::devicePixelRatio(widget)) - buttonMargin; const int delta = buttonWidth + 2; int controlTop = option->rect.bottom() - buttonHeight - 2; @@ -3737,10 +3737,10 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt { XPThemeData buttontheme(widget, 0, QWindowsXPStylePrivate::ButtonTheme, BP_PUSHBUTTON, PBS_NORMAL); if (buttontheme.isValid()) { - const QMargins borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QMarginsF borderSize = buttontheme.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); if (!borderSize.isNull()) { - sz.rwidth() += borderSize.left() + borderSize.right() - 2; - sz.rheight() += borderSize.bottom() + borderSize.top() - 2; + sz.rwidth() += qRound(borderSize.left() + borderSize.right() - 2); + sz.rheight() += qRound(borderSize.bottom() + borderSize.top() - 2); } const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1); sz += QSize(qMax(pixelMetric(QStyle::PM_ScrollBarExtent, option, widget) @@ -3910,7 +3910,7 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt if (widget && widget->isWindow()) { XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size); } } @@ -3944,7 +3944,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_MAXBUTTON, MAXBS_NORMAL); if (theme.isValid()) { - const QSize size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); @@ -3978,7 +3978,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); if (theme.isValid()) { - const QSize size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); + const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); @@ -4014,7 +4014,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, WP_RESTOREBUTTON, RBS_NORMAL); if (theme.isValid()) { - const QSize size = themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget); + const QSize size = (themeSize.size() / QWindowsStylePrivate::devicePixelRatio(widget)).toSize(); QPixmap pm(size); pm.fill(Qt::transparent); QPainter p(&pm); diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/widgets/styles/qwindowsxpstyle_p_p.h index c2571b4a79..240a338c3f 100644 --- a/src/widgets/styles/qwindowsxpstyle_p_p.h +++ b/src/widgets/styles/qwindowsxpstyle_p_p.h @@ -202,15 +202,15 @@ public: 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); + QSizeF size(); + QMarginsF margins(const QRect &rect, int propId = TMT_CONTENTMARGINS); + QMarginsF 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); + static QSizeF themeSize(const QWidget *w = 0, QPainter *p = 0, int themeIn = -1, int part = 0, int state = 0); + static QMarginsF 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 QMarginsF 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; @@ -427,9 +427,9 @@ private: static HTHEME m_themes[NThemes]; }; -inline QSize XPThemeData::size() +inline QSizeF XPThemeData::size() { - QSize result(0, 0); + QSizeF result(0, 0); if (isValid()) { SIZE size; if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemePartSize(handle(), 0, partId, stateId, 0, TS_TRUE, &size))) @@ -438,9 +438,9 @@ inline QSize XPThemeData::size() return result; } -inline QMargins XPThemeData::margins(const QRect &qRect, int propId) +inline QMarginsF XPThemeData::margins(const QRect &qRect, int propId) { - QMargins result(0, 0, 0 ,0); + QMarginsF result(0, 0, 0 ,0); if (isValid()) { MARGINS margins; RECT rect = XPThemeData::toRECT(qRect); @@ -450,9 +450,9 @@ inline QMargins XPThemeData::margins(const QRect &qRect, int propId) return result; } -inline QMargins XPThemeData::margins(int propId) +inline QMarginsF XPThemeData::margins(int propId) { - QMargins result(0, 0, 0 ,0); + QMarginsF result(0, 0, 0 ,0); if (isValid()) { MARGINS margins; if (SUCCEEDED(QWindowsXPStylePrivate::pGetThemeMargins(handle(), 0, partId, stateId, propId, NULL, &margins))) @@ -461,21 +461,21 @@ inline QMargins XPThemeData::margins(int propId) return result; } -inline QSize XPThemeData::themeSize(const QWidget *w, QPainter *p, int themeIn, int part, int state) +inline QSizeF 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) +inline QMarginsF 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) +inline QMarginsF 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); -- cgit v1.2.3