From d18dce7941890ed6f59599e9b1ee0596720f688c Mon Sep 17 00:00:00 2001 From: Reupen Shah Date: Thu, 19 Dec 2024 21:50:36 +0000 Subject: [PATCH] Work around different handling of ampersands in Windows 11 system tray Windows 11 handles ampersands in system tray icon tooltips differently from earlier versions of Windows. Microsoft has shown no interest in fixing the problem (or even accepting that the problem exists), therefore this adds a nasty `if ` to work around the problem. --- CHANGELOG.md | 4 +++ foo_ui_columns/dark_mode.cpp | 35 +++---------------- foo_ui_columns/foo_ui_columns.vcxproj | 2 ++ foo_ui_columns/foo_ui_columns.vcxproj.filters | 6 ++++ foo_ui_columns/system_tray.cpp | 15 +++++--- foo_ui_columns/win32.cpp | 27 ++++++++++++++ foo_ui_columns/win32.h | 8 +++++ 7 files changed, 62 insertions(+), 35 deletions(-) create mode 100644 foo_ui_columns/win32.cpp create mode 100644 foo_ui_columns/win32.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 104888dae..08a7244f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -132,6 +132,10 @@ view using the context menu was fixed. [[#873](https://github.com/reupen/columns_ui/pull/873)] +- Different handling of ampersands in system tray icon tooltips in Windows 11 + compared to previous versions of Windows was worked around. + [[#1040](https://github.com/reupen/columns_ui/pull/1040)] + - Various rendering glitches in Playlist tabs and Tab stack when dark mode is active were fixed. [[#851](https://github.com/reupen/columns_ui/pull/851)] diff --git a/foo_ui_columns/dark_mode.cpp b/foo_ui_columns/dark_mode.cpp index 99e97e26f..e1b74d519 100644 --- a/foo_ui_columns/dark_mode.cpp +++ b/foo_ui_columns/dark_mode.cpp @@ -2,45 +2,20 @@ #include "dark_mode.h" #include "system_appearance_manager.h" +#include "win32.h" namespace cui::dark { -namespace { - -bool check_windows_10_build(DWORD build_number) -{ - OSVERSIONINFOEX osviex{}; - osviex.dwOSVersionInfoSize = sizeof(osviex); - - DWORDLONG mask = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); - mask = VerSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL); - mask = VerSetConditionMask(mask, VER_BUILDNUMBER, VER_GREATER_EQUAL); - - osviex.dwMajorVersion = 10; - osviex.dwMinorVersion = 0; - osviex.dwBuildNumber = build_number; - - return VerifyVersionInfoW(&osviex, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, mask) != FALSE; -} - -bool is_windows_11_rtm_or_newer() -{ - static auto is_22000_or_newer = check_windows_10_build(22'000); - return is_22000_or_newer; -} - -} // namespace - bool does_os_support_dark_mode() { - static auto is_19041_or_newer = check_windows_10_build(19'041); + static auto is_19041_or_newer = win32::check_windows_10_build(19'041); return is_19041_or_newer; } bool is_native_dark_spin_available() { // Earliest known build number – exact build number unknown. - return check_windows_10_build(22'579); + return win32::check_windows_10_build(22'579); } bool are_private_apis_allowed() @@ -76,7 +51,7 @@ void set_titlebar_mode(HWND wnd, bool is_dark) void force_titlebar_redraw(HWND wnd) { - if (is_windows_11_rtm_or_newer() || !IsWindowVisible(wnd)) + if (win32::is_windows_11_rtm_or_newer() || !IsWindowVisible(wnd)) return; // The below is a hack to force the titlebar to redraw on Windows 10 (little else works). @@ -128,7 +103,7 @@ COLORREF get_base_dark_colour(DarkColourID colour_id) { switch (colour_id) { case DarkColourID::DARK_000: - return is_windows_11_rtm_or_newer() ? create_grey(25) : create_grey(32); + return win32::is_windows_11_rtm_or_newer() ? create_grey(25) : create_grey(32); case DarkColourID::DARK_200: return create_grey(51); case DarkColourID::DARK_250: diff --git a/foo_ui_columns/foo_ui_columns.vcxproj b/foo_ui_columns/foo_ui_columns.vcxproj index e3b8b912d..492baf090 100644 --- a/foo_ui_columns/foo_ui_columns.vcxproj +++ b/foo_ui_columns/foo_ui_columns.vcxproj @@ -430,6 +430,7 @@ + @@ -532,6 +533,7 @@ + diff --git a/foo_ui_columns/foo_ui_columns.vcxproj.filters b/foo_ui_columns/foo_ui_columns.vcxproj.filters index 27eb1b544..6cb5bc348 100644 --- a/foo_ui_columns/foo_ui_columns.vcxproj.filters +++ b/foo_ui_columns/foo_ui_columns.vcxproj.filters @@ -629,6 +629,9 @@ Utilities + + Utilities + @@ -927,6 +930,9 @@ Utilities + + Utilities + diff --git a/foo_ui_columns/system_tray.cpp b/foo_ui_columns/system_tray.cpp index bbf85eae5..90af42007 100644 --- a/foo_ui_columns/system_tray.cpp +++ b/foo_ui_columns/system_tray.cpp @@ -2,6 +2,7 @@ #include "system_tray.h" #include "main_window.h" +#include "win32.h" extern HWND g_status; extern HICON g_icon; @@ -13,7 +14,7 @@ void update_systray(bool balloon, int btitle, bool force_balloon) metadb_handle_ptr track; const auto play_api = play_control::get(); play_api->get_now_playing(track); - pfc::string8 sys; + pfc::string8 escaped_title; pfc::string8 title; if (track.is_valid()) { @@ -28,14 +29,18 @@ void update_systray(bool balloon, int btitle, bool force_balloon) title = core_version_info_v2::get()->get_name(); } - uFixAmpersandChars(title, sys); + if (cui::win32::is_windows_11_rtm_or_newer()) + escaped_title = title; + else + uFixAmpersandChars(title, escaped_title); if (balloon && (cfg_balloon || force_balloon)) { - uShellNotifyIconEx(NIM_MODIFY, cui::main_window.get_wnd(), 1, MSG_SYSTEM_TRAY_ICON, g_icon, sys, "", ""); - uShellNotifyIconEx(NIM_MODIFY, cui::main_window.get_wnd(), 1, MSG_SYSTEM_TRAY_ICON, g_icon, sys, + uShellNotifyIconEx( + NIM_MODIFY, cui::main_window.get_wnd(), 1, MSG_SYSTEM_TRAY_ICON, g_icon, escaped_title, "", ""); + uShellNotifyIconEx(NIM_MODIFY, cui::main_window.get_wnd(), 1, MSG_SYSTEM_TRAY_ICON, g_icon, escaped_title, (btitle == 0 ? "Now playing:" : (btitle == 1 ? "Unpaused:" : "Paused:")), title); } else - uShellNotifyIcon(NIM_MODIFY, cui::main_window.get_wnd(), 1, MSG_SYSTEM_TRAY_ICON, g_icon, sys); + uShellNotifyIcon(NIM_MODIFY, cui::main_window.get_wnd(), 1, MSG_SYSTEM_TRAY_ICON, g_icon, escaped_title); } } diff --git a/foo_ui_columns/win32.cpp b/foo_ui_columns/win32.cpp new file mode 100644 index 000000000..f28415446 --- /dev/null +++ b/foo_ui_columns/win32.cpp @@ -0,0 +1,27 @@ +#include "pch.h" + +namespace cui::win32 { + +bool check_windows_10_build(DWORD build_number) +{ + OSVERSIONINFOEX osviex{}; + osviex.dwOSVersionInfoSize = sizeof(osviex); + + DWORDLONG mask = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); + mask = VerSetConditionMask(mask, VER_MINORVERSION, VER_GREATER_EQUAL); + mask = VerSetConditionMask(mask, VER_BUILDNUMBER, VER_GREATER_EQUAL); + + osviex.dwMajorVersion = 10; + osviex.dwMinorVersion = 0; + osviex.dwBuildNumber = build_number; + + return VerifyVersionInfoW(&osviex, VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER, mask) != FALSE; +} + +bool is_windows_11_rtm_or_newer() +{ + static auto is_22000_or_newer = check_windows_10_build(22'000); + return is_22000_or_newer; +} + +} // namespace cui::win32 diff --git a/foo_ui_columns/win32.h b/foo_ui_columns/win32.h new file mode 100644 index 000000000..eef87eb6e --- /dev/null +++ b/foo_ui_columns/win32.h @@ -0,0 +1,8 @@ +#pragma once + +namespace cui::win32 { + +bool check_windows_10_build(DWORD build_number); +bool is_windows_11_rtm_or_newer(); + +} // namespace cui::win32