diff --git a/contrib/src/qt/0001-QWindowsSystemTrayIcon-fix-notification-icon-dpi-han.patch b/contrib/src/qt/0001-QWindowsSystemTrayIcon-fix-notification-icon-dpi-han.patch new file mode 100644 index 0000000000000000000000000000000000000000..853f503de8e7748afdd1383e4ed75878a3e26231 --- /dev/null +++ b/contrib/src/qt/0001-QWindowsSystemTrayIcon-fix-notification-icon-dpi-han.patch @@ -0,0 +1,61 @@ +From 241f6e9dcf1bba7c384f7f9752b9281122540589 Mon Sep 17 00:00:00 2001 +From: Fatih Uzunoglu <fuzun54@outlook.com> +Date: Sat, 22 Feb 2025 20:37:29 +0200 +Subject: [PATCH] QWindowsSystemTrayIcon: fix notification icon dpi handling + +Using fixed 256x256 does not make any sense. It is not recommended, +and Windows downscales the bitmap without linear transformation +leading to pixelated results. + +We should use the recommended `SM_CXICON`x`SM_CYICON`, which is +expected to be scaled as per the screen DPI since the application +is made DPI aware. +--- + .../windows/qwindowssystemtrayicon.cpp | 31 +++++++++++++++++-- + 1 file changed, 29 insertions(+), 2 deletions(-) + +diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +index 11eb3507f9f..df3e35f21b0 100644 +--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp ++++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +@@ -226,8 +226,35 @@ void QWindowsSystemTrayIcon::showMessage(const QString &title, const QString &me + + tnd.uID = q_uNOTIFYICONID; + +- const auto size = icon.actualSize(QSize(256, 256)); +- QPixmap pm = icon.pixmap(size); ++ // Qt makes the application DPI aware, `GetSystemMetrics()` is expected to take the screen ++ // dpi into account: ++ QSize size(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); ++ ++ // This is not official, but Windows 11 seems to display the icon at 50x50 with standard DPI, ++ // which is contrary to the recommended `SM_CXICON`/`SM_CYICON` that is 32x32 with standard ++ // DPI. We can pick the higher of 50x50 and `SM_CXICON`/`SMCYICON` to prevent upscaling. ++ const int min = std::ceil(50 * std::max((size.width() / 32.0), (size.height() / 32.0))); ++ if (size.width() < min || size.height() < min) { ++ const auto ratio = static_cast<qreal>(size.width()) / size.height(); ++ // Do not spoil the aspect ratio: ++ if (ratio > 1.0) { ++ size.setWidth(std::ceil(min * ratio)); ++ size.setHeight(min); ++ } else if (ratio < 1.0) { ++ size.setHeight(std::ceil(min / ratio)); ++ size.setWidth(min); ++ } else { ++ size.setHeight(min); ++ size.setWidth(min); ++ } ++ } ++ ++ // Use 1.0 as the DPR, because `QIcon` uses the screen (application) DPR (if not supplied), ++ // and we don't want the size to be manipulated based on that because the fed size already ++ // considers the screen DPR (as explained in the note above): `QIcon::pixmap()`: "The pixmap ++ // might be smaller than requested, but never larger, unless the device-pixel ratio of the ++ // returned pixmap is larger than 1." ++ QPixmap pm = icon.pixmap(size, 1.0); + if (m_hMessageIcon) { + DestroyIcon(m_hMessageIcon); + m_hMessageIcon = nullptr; +-- +2.48.1 + diff --git a/contrib/src/qt/rules.mak b/contrib/src/qt/rules.mak index 3c44998e035f8b42331c3cce729ca6f0383c543f..f435d704ae9d24bcc50949681394b9602fbe887b 100644 --- a/contrib/src/qt/rules.mak +++ b/contrib/src/qt/rules.mak @@ -54,6 +54,7 @@ qt: qtbase-everywhere-src-$(QTBASE_VERSION_FULL).tar.xz .sum-qt $(APPLY) $(SRC)/qt/0001-disable-precompiled-headers-when-forcing-WINVER-inte.patch $(APPLY) $(SRC)/qt/0001-Use-DirectWrite-font-database-only-with-Windows-10-a.patch $(APPLY) $(SRC)/qt/0003-Do-not-link-D3D9.patch + $(APPLY) $(SRC)/qt/0001-QWindowsSystemTrayIcon-fix-notification-icon-dpi-han.patch $(MOVE) ifdef HAVE_WIN32