Implement monochrome tray icon on Windows

This commit is contained in:
Ilya Fedin 2023-10-19 11:34:28 +04:00 committed by John Preston
parent 1f25301283
commit cd0f58fa65
4 changed files with 85 additions and 11 deletions

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h" #include "core/application.h"
#include "core/core_settings.h" #include "core/core_settings.h"
#include "core/sandbox.h" #include "core/sandbox.h"
#include "tray.h"
#include "base/platform/win/base_windows_winrt.h" #include "base/platform/win/base_windows_winrt.h"
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
@ -78,11 +79,12 @@ bool WindowsIntegration::processEvent(
} }
break; break;
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
case WM_SETTINGCHANGE: case WM_SETTINGCHANGE:
#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
Core::App().settings().setSystemDarkMode(Platform::IsDarkMode()); Core::App().settings().setSystemDarkMode(Platform::IsDarkMode());
break;
#endif // Qt < 6.5.0 #endif // Qt < 6.5.0
Core::App().tray().updateIconCounters();
break;
} }
return false; return false;
} }

View File

@ -510,10 +510,12 @@ void MainWindow::updateTaskbarAndIconCounters() {
auto iconSmallPixmap16 = Tray::IconWithCounter( auto iconSmallPixmap16 = Tray::IconWithCounter(
Tray::CounterLayerArgs(16, counter, muted), Tray::CounterLayerArgs(16, counter, muted),
true, true,
false,
supportMode); supportMode);
auto iconSmallPixmap32 = Tray::IconWithCounter( auto iconSmallPixmap32 = Tray::IconWithCounter(
Tray::CounterLayerArgs(32, counter, muted), Tray::CounterLayerArgs(32, counter, muted),
true, true,
false,
supportMode); supportMode);
QIcon iconSmall, iconBig; QIcon iconSmall, iconBig;
iconSmall.addPixmap(iconSmallPixmap16); iconSmall.addPixmap(iconSmallPixmap16);
@ -524,10 +526,12 @@ void MainWindow::updateTaskbarAndIconCounters() {
iconBig.addPixmap(Tray::IconWithCounter( iconBig.addPixmap(Tray::IconWithCounter(
Tray::CounterLayerArgs(32, bigCounter, muted), Tray::CounterLayerArgs(32, bigCounter, muted),
false, false,
false,
supportMode)); supportMode));
iconBig.addPixmap(Tray::IconWithCounter( iconBig.addPixmap(Tray::IconWithCounter(
Tray::CounterLayerArgs(64, bigCounter, muted), Tray::CounterLayerArgs(64, bigCounter, muted),
false, false,
false,
supportMode)); supportMode));
destroyCachedIcons(); destroyCachedIcons();

View File

@ -30,13 +30,47 @@ namespace {
constexpr auto kTooltipDelay = crl::time(10000); constexpr auto kTooltipDelay = crl::time(10000);
[[nodiscard]] std::optional<bool> IsDarkTaskbar() {
static const auto kSystemVersion = QOperatingSystemVersion::current();
static const auto kDarkModeAddedVersion = QOperatingSystemVersion(
QOperatingSystemVersion::Windows,
10,
0,
17763);
static const auto kSupported = (kSystemVersion >= kDarkModeAddedVersion);
if (!kSupported) {
return std::nullopt;
}
const auto keyName = L""
"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize";
const auto valueName = L"SystemUsesLightTheme";
auto key = HKEY();
auto result = RegOpenKeyEx(HKEY_CURRENT_USER, keyName, 0, KEY_READ, &key);
if (result != ERROR_SUCCESS) {
return std::nullopt;
}
DWORD value = 0, type = 0, size = sizeof(value);
result = RegQueryValueEx(key, valueName, 0, &type, (LPBYTE)&value, &size);
RegCloseKey(key);
if (result != ERROR_SUCCESS) {
return std::nullopt;
}
return (value == 0);
}
[[nodiscard]] QImage ImageIconWithCounter( [[nodiscard]] QImage ImageIconWithCounter(
Window::CounterLayerArgs &&args, Window::CounterLayerArgs &&args,
bool supportMode, bool supportMode,
bool smallIcon) { bool smallIcon,
bool monochrome) {
static constexpr auto kCount = 3; static constexpr auto kCount = 3;
static auto ScaledLogo = std::array<QImage, kCount>(); static auto ScaledLogo = std::array<QImage, kCount>();
static auto ScaledLogoNoMargin = std::array<QImage, kCount>(); static auto ScaledLogoNoMargin = std::array<QImage, kCount>();
static auto ScaledLogoDark = std::array<QImage, kCount>();
static auto ScaledLogoLight = std::array<QImage, kCount>();
struct Dimensions { struct Dimensions {
int index = 0; int index = 0;
@ -63,19 +97,49 @@ constexpr auto kTooltipDelay = crl::time(10000);
}(); }();
Assert(d.index < kCount); Assert(d.index < kCount);
auto &scaled = smallIcon ? ScaledLogoNoMargin : ScaledLogo; const auto darkMode = IsDarkTaskbar();
auto &scaled = (monochrome && darkMode)
? (*darkMode
? ScaledLogoDark
: ScaledLogoLight)
: smallIcon
? ScaledLogoNoMargin
: ScaledLogo;
auto result = [&] { auto result = [&] {
auto &image = scaled[d.index]; auto &image = scaled[d.index];
if (image.isNull()) { if (image.isNull()) {
image = (smallIcon if (monochrome && darkMode) {
? Window::LogoNoMargin() const auto withColor = [&](QColor color) {
: Window::Logo()).scaledToWidth( switch (d.size) {
d.size, case 16:
Qt::SmoothTransformation); return st::macTrayIcon.instance(color, 100 / cIntRetinaFactor());
case 32:
return st::macTrayIcon.instance(color, 200 / cIntRetinaFactor());
default:
return st::macTrayIcon.instance(color, 300 / cIntRetinaFactor());
}
};
const auto darkModeResult = withColor({ 255, 255, 255 });
const auto lightModeResult = withColor({ 0, 0, 0, 228 });
image = *darkMode ? darkModeResult : lightModeResult;
const auto monochromeMargin = QPoint(
(image.width() - d.size) / 2,
(image.height() - d.size) / 2);
image = image.copy(
QRect(monochromeMargin, QSize(d.size, d.size)));
image.setDevicePixelRatio(1);
} else {
image = (smallIcon
? Window::LogoNoMargin()
: Window::Logo()).scaledToWidth(
d.size,
Qt::SmoothTransformation);
}
} }
return image; return image;
}(); }();
if (supportMode) { if ((!monochrome || !darkMode) && supportMode) {
Window::ConvertIconToBlack(result); Window::ConvertIconToBlack(result);
} }
if (!args.count) { if (!args.count) {
@ -163,10 +227,12 @@ void Tray::updateIcon() {
auto iconSmallPixmap16 = Tray::IconWithCounter( auto iconSmallPixmap16 = Tray::IconWithCounter(
CounterLayerArgs(16, counter, muted), CounterLayerArgs(16, counter, muted),
true, true,
true,
supportMode); supportMode);
auto iconSmallPixmap32 = Tray::IconWithCounter( auto iconSmallPixmap32 = Tray::IconWithCounter(
CounterLayerArgs(32, counter, muted), CounterLayerArgs(32, counter, muted),
true, true,
true,
supportMode); supportMode);
auto iconSmall = QIcon(); auto iconSmall = QIcon();
iconSmall.addPixmap(iconSmallPixmap16); iconSmall.addPixmap(iconSmallPixmap16);
@ -271,9 +337,10 @@ Window::CounterLayerArgs Tray::CounterLayerArgs(
QPixmap Tray::IconWithCounter( QPixmap Tray::IconWithCounter(
Window::CounterLayerArgs &&args, Window::CounterLayerArgs &&args,
bool smallIcon, bool smallIcon,
bool monochrome,
bool supportMode) { bool supportMode) {
return Ui::PixmapFromImage( return Ui::PixmapFromImage(
ImageIconWithCounter(std::move(args), supportMode, smallIcon)); ImageIconWithCounter(std::move(args), supportMode, smallIcon, monochrome));
} }
} // namespace Platform } // namespace Platform

View File

@ -57,6 +57,7 @@ public:
[[nodiscard]] static QPixmap IconWithCounter( [[nodiscard]] static QPixmap IconWithCounter(
Window::CounterLayerArgs &&args, Window::CounterLayerArgs &&args,
bool smallIcon, bool smallIcon,
bool monochrome,
bool supportMode); bool supportMode);
private: private: