diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 1379018793b..63d14756291 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -822,7 +822,6 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz { int resourceId = -1; SHSTOCKICONID stockId = SIID_INVALID; - UINT stockFlags = 0; LPCTSTR iconName = nullptr; switch (sp) { case DriveCDIcon: @@ -846,14 +845,12 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz resourceId = 7; break; case FileLinkIcon: - stockFlags = SHGSI_LINKOVERLAY; Q_FALLTHROUGH(); case FileIcon: stockId = SIID_DOCNOASSOC; resourceId = 1; break; case DirLinkIcon: - stockFlags = SHGSI_LINKOVERLAY; Q_FALLTHROUGH(); case DirClosedIcon: case DirIcon: @@ -867,7 +864,6 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz resourceId = 16; break; case DirLinkOpenIcon: - stockFlags = SHGSI_LINKOVERLAY; Q_FALLTHROUGH(); case DirOpenIcon: stockId = SIID_FOLDEROPEN; @@ -907,16 +903,34 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz break; } + // Even with SHGSI_LINKOVERLAY flag set, loaded Icon with SHDefExtractIcon doesn't have + // any overlay, so we avoid SHGSI_LINKOVERLAY flag and draw it manually (QTBUG-131843) + const auto drawLinkOverlayIcon = [](StandardPixmap sp, QPixmap &pixmap, QSizeF pixmapSize) { + if (sp == FileLinkIcon || sp == DirLinkIcon || sp == DirLinkOpenIcon) { + QPainter painter(&pixmap); + const QSizeF linkSize = pixmapSize / (pixmapSize.height() >= 48 ? 3 : 2); + const QPixmap link = loadIconFromShell32(16769, linkSize.toSize()); // 16769 = LinkOverlayIcon + const int yPos = pixmap.height() - link.size().height(); + painter.drawPixmap(0, yPos, int(linkSize.width()), int(linkSize.height()), link); + } + }; + + 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; + constexpr UINT stockFlags = SHGSI_ICONLOCATION; if (SHGetStockIconInfo(stockId, stockFlags, &iconInfo) == S_OK) { const auto iconSize = pixmapSize.width(); HICON icon; if (SHDefExtractIcon(iconInfo.szPath, iconInfo.iIcon, 0, &icon, nullptr, iconSize) == S_OK) { QPixmap pixmap = qt_pixmapFromWinHICON(icon); + if (!pixmap.isNull()) { + drawLinkOverlayIcon(sp, pixmap, pixmap.size()); + pixmap.setDevicePixelRatio(dpr); + } DestroyIcon(icon); return pixmap; } @@ -926,11 +940,8 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz if (resourceId != -1) { 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); - } + drawLinkOverlayIcon(sp, pixmap, pixmapSize); + pixmap.setDevicePixelRatio(dpr); return pixmap; } }