summaryrefslogtreecommitdiffstats
path: root/src/plugins/styles
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-01-27 11:04:14 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-02-01 17:48:37 +0100
commite56b8e1e59b6df7c7abd48b163abe6846849eb7a (patch)
tree4ddabe9efcebf8eb4a8e9b2f296c748753a3e064 /src/plugins/styles
parent0c8ff269dcda7de68c475535d575c0bb34af788b (diff)
QWindowsXPStyle: Fix MDI button size for maximized QMdiSubWindows
The controls as drawn by the UxTheme library are too tiny; add an additional correction factor to QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(), allowing to scale the result via the QImage. For the MDI button size, calulcate the factor by comparing the theme size to the subcontrol rectangle. Fixes: QTBUG-75927 Change-Id: Iab0911b51d13f3de0d9278a32cb4598ce709d745 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io> Reviewed-by: André de la Rocha <andre.rocha@qt.io>
Diffstat (limited to 'src/plugins/styles')
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp55
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h4
2 files changed, 44 insertions, 15 deletions
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index 7a7b90558b..9d143da169 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -665,7 +665,7 @@ static inline bool isFullyOpaque(const XPThemeData &themeData)
\note drawBackgroundThruNativeBuffer() can return false for large
sizes due to buffer()/CreateDIBSection() failing.
*/
-bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData)
+bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData, qreal correctionFactor)
{
if (themeData.rect.isEmpty())
return true;
@@ -710,9 +710,9 @@ bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData)
}
const HDC dc = canDrawDirectly ? hdcForWidgetBackingStore(themeData.widget) : nullptr;
- const bool result = dc
+ const bool result = dc && qFuzzyCompare(correctionFactor, qreal(1))
? drawBackgroundDirectly(dc, themeData, aditionalDevicePixelRatio)
- : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio);
+ : drawBackgroundThruNativeBuffer(themeData, aditionalDevicePixelRatio, correctionFactor);
painter->restore();
return result;
}
@@ -786,9 +786,14 @@ bool QWindowsXPStylePrivate::drawBackgroundDirectly(HDC dc, XPThemeData &themeDa
other pixmaps etc), or when special transformations are needed (e.g.
flips (horizonal mirroring only, vertical are handled by the theme
engine).
+
+ \a correctionFactor is an additional factor used to scale up controls
+ that are too small on High DPI screens, as has been observed for
+ WP_MDICLOSEBUTTON, WP_MDIRESTOREBUTTON, WP_MDIMINBUTTON (QTBUG-75927).
*/
bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeData,
- qreal additionalDevicePixelRatio)
+ qreal additionalDevicePixelRatio,
+ qreal correctionFactor)
{
QPainter *painter = themeData.painter;
QRectF rectF = scaleRect(QRectF(themeData.rect), additionalDevicePixelRatio);
@@ -797,7 +802,11 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
rectF = QRectF(0, 0, rectF.height(), rectF.width());
}
rectF.moveTo(0, 0);
+
+ const bool hasCorrectionFactor = !qFuzzyCompare(correctionFactor, qreal(1));
QRect rect = rectF.toRect();
+ QRect drawRect = hasCorrectionFactor
+ ? QRectF(rectF.topLeft() / correctionFactor, rectF.size() / correctionFactor).toRect() : rect;
int partId = themeData.partId;
int stateId = themeData.stateId;
int w = rect.width();
@@ -826,6 +835,10 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
pixmapCacheKey.append(QLatin1Char('h'));
pixmapCacheKey.append(QString::number(additionalDevicePixelRatio));
pixmapCacheKey.append(QLatin1Char('d'));
+ if (hasCorrectionFactor) {
+ pixmapCacheKey.append(QLatin1Char('c'));
+ pixmapCacheKey.append(QString::number(correctionFactor));
+ }
QPixmap cachedPixmap;
ThemeMapKey key(themeData);
@@ -884,7 +897,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
// and DTGB_OMITCONTENT
bool addBorderContentClipping = false;
QRegion extraClip;
- QRect area = rect;
+ QRect area = drawRect;
if (themeData.noBorder || themeData.noContent) {
extraClip = area;
// We are running on a system where the uxtheme.dll does not have
@@ -915,19 +928,19 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
QImage img;
if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! -------------------------
- if (!buffer(w, h)) // Ensure a buffer of at least (w, h) in size
+ if (!buffer(drawRect.width(), drawRect.height())) // Ensure a buffer of at least (w, h) in size
return false;
HDC dc = bufferHDC();
// Clear the buffer
if (alphaType != NoAlpha) {
// Consider have separate "memset" function for small chunks for more speedup
- memset(bufferPixels, 0x00, bufferW * h * 4);
+ memset(bufferPixels, 0x00, bufferW * drawRect.height() * 4);
}
// Difference between area and rect
- int dx = area.x() - rect.x();
- int dy = area.y() - rect.y();
+ int dx = area.x() - drawRect.x();
+ int dy = area.y() - drawRect.y();
// Adjust so painting rect starts from Origo
rect.moveTo(0,0);
@@ -957,7 +970,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
if (!hasAlpha && partIsTransparent)
potentialInvalidAlpha = true;
#if defined(DEBUG_XP_STYLE) && 1
- dumpNativeDIB(w, h);
+ dumpNativeDIB(drawRect.width(), drawRect.height());
#endif
}
@@ -985,6 +998,8 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
printf("Image format is: %s\n", alphaType == RealAlpha ? "Real Alpha" : alphaType == MaskAlpha ? "Masked Alpha" : "No Alpha");
#endif
img = QImage(bufferPixels, bufferW, bufferH, format);
+ if (hasCorrectionFactor)
+ img = img.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation);
img.setDevicePixelRatio(additionalDevicePixelRatio);
}
@@ -2482,6 +2497,20 @@ static void populateMdiButtonTheme(const QStyle *proxy, const QWidget *widget,
else
theme->stateId = CBS_NORMAL;
}
+
+// Calculate an small (max 2), empirical correction factor for scaling up
+// WP_MDICLOSEBUTTON, WP_MDIRESTOREBUTTON, WP_MDIMINBUTTON, which are too
+// small on High DPI screens (QTBUG-75927).
+qreal mdiButtonCorrectionFactor(XPThemeData &theme, const QPaintDevice *pd = nullptr)
+{
+ const auto dpr = pd ? pd->devicePixelRatioF() : qApp->devicePixelRatio();
+ const QSizeF nativeSize = QSizeF(theme.size()) / dpr;
+ const QSizeF requestedSize(theme.rect.size());
+ const auto rawFactor = qMin(requestedSize.width() / nativeSize.width(),
+ requestedSize.height() / nativeSize.height());
+ const auto factor = rawFactor >= qreal(2) ? qreal(2) : qreal(1);
+ return factor;
+}
#endif // QT_CONFIG(mdiarea)
static void populateTitleBarButtonTheme(const QStyle *proxy, const QWidget *widget,
@@ -3114,15 +3143,15 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
if (option->subControls.testFlag(SC_MdiCloseButton)) {
populateMdiButtonTheme(proxy(), widget, option, SC_MdiCloseButton, WP_MDICLOSEBUTTON, &theme);
- d->drawBackground(theme);
+ d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
}
if (option->subControls.testFlag(SC_MdiNormalButton)) {
populateMdiButtonTheme(proxy(), widget, option, SC_MdiNormalButton, WP_MDIRESTOREBUTTON, &theme);
- d->drawBackground(theme);
+ d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
}
if (option->subControls.testFlag(QStyle::SC_MdiMinButton)) {
populateMdiButtonTheme(proxy(), widget, option, SC_MdiMinButton, WP_MDIMINBUTTON, &theme);
- d->drawBackground(theme);
+ d->drawBackground(theme, mdiButtonCorrectionFactor(theme, widget));
}
}
break;
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
index ad7754e3d4..06b37a6e5c 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
@@ -241,8 +241,8 @@ public:
bool isTransparent(XPThemeData &themeData);
QRegion region(XPThemeData &themeData);
- bool drawBackground(XPThemeData &themeData);
- bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio);
+ bool drawBackground(XPThemeData &themeData, qreal correctionFactor = 1);
+ bool drawBackgroundThruNativeBuffer(XPThemeData &themeData, qreal aditionalDevicePixelRatio, qreal correctionFactor);
bool drawBackgroundDirectly(HDC dc, XPThemeData &themeData, qreal aditionalDevicePixelRatio);
bool hasAlphaChannel(const QRect &rect);