Skip to content

Commit

Permalink
Windows: Return high-DPI pixmaps from QWindowsTheme::standardPixmap
Browse files Browse the repository at this point in the history
Most consumers feed the pixmaps into a QIcon, pulling out pixmaps
of sizes 32, 64, 128, 256, 512, so consumers of that QIcon will
not see low-resolution pixmaps for the common sizes like 64x64.

However if someone uses standardPixmap directly, or request an
icon with size 512x512, we won't have a high-DPI pixmap.

Unlike QStyle::standardPixmap we don't have a QWidget/QWindow
argument we can use to resolve the target DPR, so we have to
assume the pixmap can be used anywhere, and use the highest
DPR we've seen so far, via QGuiApplication::devicePixelRatio().

Pick-to: 6.9
Change-Id: Ib7fb08ab4932da1ca3f3325e25a7022c1cd17435
Reviewed-by: Volker Hilsheimer <[email protected]>
  • Loading branch information
torarnv committed Dec 11, 2024
1 parent 9b924a4 commit 59bbfb1
Showing 1 changed file with 11 additions and 6 deletions.
17 changes: 11 additions & 6 deletions src/plugins/platforms/windows/qwindowstheme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,12 +803,12 @@ void QWindowsTheme::refreshIconPixmapSizes()
// Defined in qpixmap_win.cpp
Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon);

static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
static QPixmap loadIconFromShell32(int resourceId, QSize size)
{
if (const HMODULE hmod = QSystemLibrary::load(L"shell32")) {
auto iconHandle =
static_cast<HICON>(LoadImage(hmod, MAKEINTRESOURCE(resourceId),
IMAGE_ICON, int(size.width()), int(size.height()), 0));
IMAGE_ICON, size.width(), size.height(), 0));
if (iconHandle) {
QPixmap iconpixmap = qt_pixmapFromWinHICON(iconHandle);
DestroyIcon(iconHandle);
Expand All @@ -818,7 +818,7 @@ static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
return QPixmap();
}

QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSize) const
QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const
{
int resourceId = -1;
SHSTOCKICONID stockId = SIID_INVALID;
Expand Down Expand Up @@ -907,30 +907,35 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
break;
}

const auto dpr = qGuiApp->devicePixelRatio(); // Highest in the system

if (stockId != SIID_INVALID) {
SHSTOCKICONINFO iconInfo;
memset(&iconInfo, 0, sizeof(iconInfo));
iconInfo.cbSize = sizeof(iconInfo);
stockFlags |= SHGSI_ICONLOCATION;
if (SHGetStockIconInfo(stockId, stockFlags, &iconInfo) == S_OK) {
const auto iconSize = pixmapSize.width();
const auto iconSize = size.width() * dpr;
HICON icon;
if (SHDefExtractIcon(iconInfo.szPath, iconInfo.iIcon, 0, &icon, nullptr, iconSize) == S_OK) {
QPixmap pixmap = qt_pixmapFromWinHICON(icon);
pixmap.setDevicePixelRatio(dpr);
DestroyIcon(icon);
return pixmap;
}
}
}

if (resourceId != -1) {
const QSize pixmapSize(size.width() * dpr, size.height() * dpr);
QPixmap pixmap = loadIconFromShell32(resourceId, pixmapSize);
if (!pixmap.isNull()) {
if (sp == FileLinkIcon || sp == DirLinkIcon || sp == DirLinkOpenIcon) {
QPainter painter(&pixmap);
QPixmap link = loadIconFromShell32(30, pixmapSize);
painter.drawPixmap(0, 0, int(pixmapSize.width()), int(pixmapSize.height()), link);
painter.drawPixmap(0, 0, pixmapSize.width(), pixmapSize.height(), link);
}
pixmap.setDevicePixelRatio(dpr);
return pixmap;
}
}
Expand All @@ -943,7 +948,7 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
return pixmap;
}

return QPlatformTheme::standardPixmap(sp, pixmapSize);
return QPlatformTheme::standardPixmap(sp, size);
}

enum { // Shell image list ids
Expand Down

0 comments on commit 59bbfb1

Please sign in to comment.