From 79de997dc13d8545ae8f05186242becb12ab3e58 Mon Sep 17 00:00:00 2001 From: aybe Date: Fri, 7 Nov 2025 04:12:21 +0100 Subject: [PATCH] Fix spurious folder icon overlay --- third_party/ImFileDialog/ImFileDialog.cpp | 96 ++++++++++++++++++----- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/third_party/ImFileDialog/ImFileDialog.cpp b/third_party/ImFileDialog/ImFileDialog.cpp index 5d0255969..c819f0123 100644 --- a/third_party/ImFileDialog/ImFileDialog.cpp +++ b/third_party/ImFileDialog/ImFileDialog.cpp @@ -17,8 +17,11 @@ #ifdef _WIN32 #include +#include +#include #include #include +#pragma comment(lib, "Comctl32.lib") #pragma comment(lib, "Shell32.lib") #else #include @@ -33,6 +36,74 @@ static std::string u8StringToString(const std::u8string& str) { return reinterpret_cast(str.c_str()); } + +namespace +{ + struct Image + { + std::vector Pixels; + int Width, Height; + }; + +#ifdef _WIN32 + std::optional GetFileIconWin32(const SHFILEINFOW& sfi) + { + auto list = static_cast(nullptr); + + if (FAILED(SHGetImageList(SHIL_LARGE, IID_IImageList, reinterpret_cast(&list)))) + { + return std::nullopt; + } + + const auto icon = ImageList_GetIcon(list, sfi.iIcon, ILD_NORMAL); + + if (icon == nullptr) + { + return std::nullopt; + } + + std::optional image; + + ICONINFO info = {}; + + if (GetIconInfo(icon, &info)) + { + if (info.hbmColor != nullptr) + { + DIBSECTION ds = {}; + + if (GetObject(info.hbmColor, sizeof(ds), &ds)) + { + const auto bm = ds.dsBm; + const auto bw = bm.bmWidth; + const auto bh = bm.bmHeight; + + if (const auto size = bw * bh * (bm.bmBitsPixel / 8); size > 0) + { + auto bits = std::vector(); + + bits.resize(size); + + if (GetBitmapBits(info.hbmColor, size, bits.data())) + { + image = Image{.Pixels = bits, .Width = bw, .Height = bh}; + } + } + } + } + + DeleteObject(info.hbmColor); + + DeleteObject(info.hbmMask); + } + + DestroyIcon(icon); + + return image; + } +#endif +} + namespace ifd { static const char* GetDefaultFolderIcon(); static const char* GetDefaultFileIcon(); @@ -748,27 +819,12 @@ namespace ifd { m_iconIndices.push_back(fileInfo.iIcon); m_iconFilepaths.push_back(pathU8); - ICONINFO iconInfo = { 0 }; - GetIconInfo(fileInfo.hIcon, &iconInfo); - - if (iconInfo.hbmColor == nullptr) - return nullptr; - - DIBSECTION ds; - GetObject(iconInfo.hbmColor, sizeof(ds), &ds); - int byteSize = ds.dsBm.bmWidth * ds.dsBm.bmHeight * (ds.dsBm.bmBitsPixel / 8); - - if (byteSize == 0) - return nullptr; - - uint8_t* data = (uint8_t*)malloc(byteSize); - GetBitmapBits(iconInfo.hbmColor, byteSize, data); - - m_icons[pathU8] = this->CreateTexture(data, ds.dsBm.bmWidth, ds.dsBm.bmHeight, 0); - - free(data); + if (auto image = GetFileIconWin32(fileInfo); image.has_value()) + { + return m_icons[pathU8] = this->CreateTexture(image->Pixels.data(), image->Width, image->Height, 0); + } - return m_icons[pathU8]; + return nullptr; #else if (m_icons.count(u8StringToString(path.u8string())) > 0) return m_icons[u8StringToString(path.u8string())];