From 0db1e52468ac15c584378d622815e263da9c769f Mon Sep 17 00:00:00 2001 From: dranik Date: Sat, 30 May 2026 14:50:18 +0300 Subject: [PATCH] fixed update icon windows & ref code --- client/cmake/sources.cmake | 4 ++ client/platforms/windows/wintrayicon.cpp | 43 +++++++++++++++++++ client/platforms/windows/wintrayicon.h | 25 +++++++++++ .../platforms/windows/wintrayiconbackend.cpp | 18 ++------ client/platforms/windows/wintrayiconbackend.h | 2 - client/platforms/windows/wintraytheme.cpp | 10 +++-- client/ui/utils/platformTrayTheme.cpp | 2 + .../utils/systemTrayNotificationHandler.cpp | 4 +- .../ui/utils/systemTrayNotificationHandler.h | 1 - client/ui/utils/trayIconCommon.cpp | 19 +++----- client/ui/utils/trayIconCommon.h | 28 ++++++------ 11 files changed, 108 insertions(+), 48 deletions(-) create mode 100644 client/platforms/windows/wintrayicon.cpp create mode 100644 client/platforms/windows/wintrayicon.h diff --git a/client/cmake/sources.cmake b/client/cmake/sources.cmake index 75c0cdbd6..9f4ba41d3 100644 --- a/client/cmake/sources.cmake +++ b/client/cmake/sources.cmake @@ -312,6 +312,7 @@ if(APPLE AND MACOS_NE) ${CLIENT_ROOT_DIR}/ui/utils/platformTrayTheme.h ${CLIENT_ROOT_DIR}/ui/utils/trayIconCommon.h ${CLIENT_ROOT_DIR}/platforms/windows/wintrayiconbackend.h + ${CLIENT_ROOT_DIR}/platforms/windows/wintrayicon.h ${CLIENT_ROOT_DIR}/platforms/windows/wintraytheme.h ${CLIENT_ROOT_DIR}/ui/utils/trayThemeChangeFilter.h ) @@ -322,6 +323,7 @@ if(APPLE AND MACOS_NE) ${CLIENT_ROOT_DIR}/ui/utils/platformTrayTheme.cpp ${CLIENT_ROOT_DIR}/ui/utils/trayIconCommon.cpp ${CLIENT_ROOT_DIR}/platforms/windows/wintrayiconbackend.cpp + ${CLIENT_ROOT_DIR}/platforms/windows/wintrayicon.cpp ${CLIENT_ROOT_DIR}/platforms/windows/wintraytheme.cpp ${CLIENT_ROOT_DIR}/ui/utils/trayThemeChangeFilter.cpp ) @@ -331,12 +333,14 @@ if(WIN32) set(HEADERS ${HEADERS} ${CLIENT_ROOT_DIR}/platforms/windows/windowsutils.h ${CLIENT_ROOT_DIR}/platforms/windows/wintrayiconbackend.h + ${CLIENT_ROOT_DIR}/platforms/windows/wintrayicon.h ${CLIENT_ROOT_DIR}/platforms/windows/wintraytheme.h ${CLIENT_ROOT_DIR}/ui/utils/trayThemeChangeFilter.h ) set(SOURCES ${SOURCES} ${CLIENT_ROOT_DIR}/platforms/windows/windowsutils.cpp ${CLIENT_ROOT_DIR}/platforms/windows/wintrayiconbackend.cpp + ${CLIENT_ROOT_DIR}/platforms/windows/wintrayicon.cpp ${CLIENT_ROOT_DIR}/platforms/windows/wintraytheme.cpp ${CLIENT_ROOT_DIR}/ui/utils/trayThemeChangeFilter.cpp ) diff --git a/client/platforms/windows/wintrayicon.cpp b/client/platforms/windows/wintrayicon.cpp new file mode 100644 index 000000000..1e1121aec --- /dev/null +++ b/client/platforms/windows/wintrayicon.cpp @@ -0,0 +1,43 @@ +#include "wintrayicon.h" + +#include "ui/utils/trayIconCommon.h" + +#include + +namespace WinTrayIcon +{ +QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor) +{ + return TrayIconCommon::buildIcon(opacity, darkTheme, indicatorColor); +} + +void applyTo(QSystemTrayIcon &trayIcon, Vpn::ConnectionState state, bool darkTheme) +{ + const qreal opacity = TrayIconCommon::opacityForState(state); + const QColor indicatorColor = TrayIconCommon::indicatorColorForState(state); + trayIcon.setIcon(buildIcon(opacity, darkTheme, indicatorColor)); +} + +QIcon buildNotifyIcon(bool darkTheme) +{ + return buildIcon(TrayIconCommon::kConnectedOpacity, darkTheme, + TrayIconCommon::indicatorColorForState(Vpn::ConnectionState::Connected)); +} + +void configure(QSystemTrayIcon &trayIcon, QMenu *menu, const QString &tooltip) +{ + trayIcon.setContextMenu(menu); + trayIcon.setToolTip(tooltip); +} + +void show(QSystemTrayIcon &trayIcon) +{ + trayIcon.show(); +} + +void showMessage(QSystemTrayIcon &trayIcon, const QString &title, const QString &message, bool darkTheme, + int timerMsec) +{ + trayIcon.showMessage(title, message, buildNotifyIcon(darkTheme), timerMsec); +} +} // namespace WinTrayIcon diff --git a/client/platforms/windows/wintrayicon.h b/client/platforms/windows/wintrayicon.h new file mode 100644 index 000000000..5d734025c --- /dev/null +++ b/client/platforms/windows/wintrayicon.h @@ -0,0 +1,25 @@ +#ifndef WINTRAYICON_H +#define WINTRAYICON_H + +#include "core/protocols/vpnProtocol.h" + +#include +#include +#include + +class QMenu; +class QString; + +namespace WinTrayIcon +{ +QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor); +void applyTo(QSystemTrayIcon &trayIcon, Vpn::ConnectionState state, bool darkTheme); +QIcon buildNotifyIcon(bool darkTheme); + +void configure(QSystemTrayIcon &trayIcon, QMenu *menu, const QString &tooltip); +void show(QSystemTrayIcon &trayIcon); +void showMessage(QSystemTrayIcon &trayIcon, const QString &title, const QString &message, bool darkTheme, + int timerMsec); +} // namespace WinTrayIcon + +#endif // WINTRAYICON_H diff --git a/client/platforms/windows/wintrayiconbackend.cpp b/client/platforms/windows/wintrayiconbackend.cpp index 5da21c2bc..0c4451c72 100644 --- a/client/platforms/windows/wintrayiconbackend.cpp +++ b/client/platforms/windows/wintrayiconbackend.cpp @@ -1,6 +1,6 @@ #include "wintrayiconbackend.h" -#include "ui/utils/trayIconCommon.h" +#include "platforms/windows/wintrayicon.h" #include @@ -20,23 +20,18 @@ void WinTrayIconBackend::setToolTip(const QString &tooltip) void WinTrayIconBackend::show() { - m_trayIcon.show(); + WinTrayIcon::show(m_trayIcon); } void WinTrayIconBackend::applyVisual(const TrayIconVisual &visual) { - const qreal opacity = TrayIconCommon::opacityForState(visual.connectionState); - const QColor indicatorColor = TrayIconCommon::indicatorColorForState(visual.connectionState); - m_trayIcon.setIcon(buildTrayIcon(opacity, visual.darkTheme, indicatorColor)); + WinTrayIcon::applyTo(m_trayIcon, visual.connectionState, visual.darkTheme); } void WinTrayIconBackend::showMessage(const QString &title, const QString &message, const TrayIconVisual &visual, int timerMsec) { - m_trayIcon.showMessage(title, message, - buildTrayIcon(TrayIconCommon::kConnectedOpacity, visual.darkTheme, - TrayIconCommon::indicatorColorForState(Vpn::ConnectionState::Connected)), - timerMsec); + WinTrayIcon::showMessage(m_trayIcon, title, message, visual.darkTheme, timerMsec); } void WinTrayIconBackend::rebuildMenu() @@ -53,11 +48,6 @@ void WinTrayIconBackend::setActivatedHandler(std::function createTrayIconBackend(QObject *parent) { return std::make_unique(parent); diff --git a/client/platforms/windows/wintrayiconbackend.h b/client/platforms/windows/wintrayiconbackend.h index 27e0c692f..618b29cb7 100644 --- a/client/platforms/windows/wintrayiconbackend.h +++ b/client/platforms/windows/wintrayiconbackend.h @@ -21,8 +21,6 @@ public: void setActivatedHandler(std::function handler) override; private: - QIcon buildTrayIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor) const; - QSystemTrayIcon m_trayIcon; }; diff --git a/client/platforms/windows/wintraytheme.cpp b/client/platforms/windows/wintraytheme.cpp index 6482426b3..933b41be9 100644 --- a/client/platforms/windows/wintraytheme.cpp +++ b/client/platforms/windows/wintraytheme.cpp @@ -15,12 +15,14 @@ void WinTrayTheme::installThemeObserver(const std::function &onThemeChan } if (QStyleHints *styleHints = QGuiApplication::styleHints()) { - QObject::connect(styleHints, &QStyleHints::colorSchemeChanged, parent, [onThemeChanged]() { onThemeChanged(); }); + QObject::connect(styleHints, &QStyleHints::colorSchemeChanged, parent, [onThemeChanged]() { + onThemeChanged(); + }); } - qApp->installEventFilter(new TrayThemeChangeFilter(onThemeChanged, parent)); + qApp->installEventFilter(new TrayThemeChangeFilter([onThemeChanged]() { + onThemeChanged(); + }, parent)); -#if defined(Q_OS_WIN) WindowsUtils::installThemeChangeObserver(onThemeChanged); -#endif } diff --git a/client/ui/utils/platformTrayTheme.cpp b/client/ui/utils/platformTrayTheme.cpp index 5f5badccc..3c2bfcd05 100644 --- a/client/ui/utils/platformTrayTheme.cpp +++ b/client/ui/utils/platformTrayTheme.cpp @@ -1,5 +1,7 @@ #include "platformTrayTheme.h" +#include + #if defined(Q_OS_MAC) && !defined(MACOS_NE) # include "platforms/macos/mactraytheme.h" #elif defined(Q_OS_WIN) || (defined(Q_OS_MAC) && defined(MACOS_NE)) diff --git a/client/ui/utils/systemTrayNotificationHandler.cpp b/client/ui/utils/systemTrayNotificationHandler.cpp index 5c87462ad..86a4d32af 100644 --- a/client/ui/utils/systemTrayNotificationHandler.cpp +++ b/client/ui/utils/systemTrayNotificationHandler.cpp @@ -82,7 +82,6 @@ void SystemTrayNotificationHandler::refreshTheme() m_isDarkTheme = isDarkTheme; #if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) - // Palette can change without gtk/portal settings updating; always repaint on Linux. updateTrayIcon(); #else if (themeChanged) { @@ -106,6 +105,9 @@ void SystemTrayNotificationHandler::updateTrayIcon() } m_trayIcon->applyVisual(currentTrayVisual()); +#if defined(Q_OS_WIN) + qDebug() << "Windows tray: setIcon darkTheme=" << m_isDarkTheme << "state=" << static_cast(m_trayState); +#endif } void SystemTrayNotificationHandler::onTrayActivated(QSystemTrayIcon::ActivationReason reason) diff --git a/client/ui/utils/systemTrayNotificationHandler.h b/client/ui/utils/systemTrayNotificationHandler.h index ec844ffdd..2ed05d05f 100644 --- a/client/ui/utils/systemTrayNotificationHandler.h +++ b/client/ui/utils/systemTrayNotificationHandler.h @@ -9,7 +9,6 @@ #include "trayIconBackend.h" #include -#include #include diff --git a/client/ui/utils/trayIconCommon.cpp b/client/ui/utils/trayIconCommon.cpp index b7341a134..91458a36c 100644 --- a/client/ui/utils/trayIconCommon.cpp +++ b/client/ui/utils/trayIconCommon.cpp @@ -5,34 +5,29 @@ #include #include -namespace TrayIconCommon { - +namespace TrayIconCommon +{ qreal opacityForState(Vpn::ConnectionState state) { switch (state) { case Vpn::ConnectionState::Connected: - case Vpn::ConnectionState::Error: - return kConnectedOpacity; + case Vpn::ConnectionState::Error: return kConnectedOpacity; case Vpn::ConnectionState::Disconnected: case Vpn::ConnectionState::Preparing: case Vpn::ConnectionState::Connecting: case Vpn::ConnectionState::Disconnecting: case Vpn::ConnectionState::Reconnecting: case Vpn::ConnectionState::Unknown: - default: - return kDisconnectedOpacity; + default: return kDisconnectedOpacity; } } QColor indicatorColorForState(Vpn::ConnectionState state) { switch (state) { - case Vpn::ConnectionState::Connected: - return QColor(52, 199, 89); - case Vpn::ConnectionState::Error: - return QColor(235, 87, 87); - default: - return QColor(); + case Vpn::ConnectionState::Connected: return QColor(52, 199, 89); + case Vpn::ConnectionState::Error: return QColor(235, 87, 87); + default: return QColor(); } } diff --git a/client/ui/utils/trayIconCommon.h b/client/ui/utils/trayIconCommon.h index 42b0d7b08..a47d24a7d 100644 --- a/client/ui/utils/trayIconCommon.h +++ b/client/ui/utils/trayIconCommon.h @@ -9,24 +9,24 @@ #include "core/protocols/vpnProtocol.h" -namespace TrayIconCommon { +namespace TrayIconCommon +{ + constexpr int kDefaultTrayIconSize = 128; + constexpr char kTrayTemplateIconPath[] = ":/images/tray/icon.svg"; -constexpr int kDefaultTrayIconSize = 128; -constexpr char kTrayTemplateIconPath[] = ":/images/tray/icon.svg"; + constexpr qreal kDisconnectedOpacity = 0.5; + constexpr qreal kConnectedOpacity = 1.0; -constexpr qreal kDisconnectedOpacity = 0.5; -constexpr qreal kConnectedOpacity = 1.0; + qreal opacityForState(Vpn::ConnectionState state); + QColor indicatorColorForState(Vpn::ConnectionState state); -qreal opacityForState(Vpn::ConnectionState state); -QColor indicatorColorForState(Vpn::ConnectionState state); + QPixmap renderTemplate(const QString &resourcePath, qreal opacity, int size); + QPixmap colorizeTemplate(const QPixmap &mask, const QColor &foreground, int size); + void drawStatusIndicator(QPainter &painter, const QColor &color, int size); -QPixmap renderTemplate(const QString &resourcePath, qreal opacity, int size); -QPixmap colorizeTemplate(const QPixmap &mask, const QColor &foreground, int size); -void drawStatusIndicator(QPainter &painter, const QColor &color, int size); - -QPixmap buildPixmap(int size, qreal opacity, bool darkTheme, const QColor &indicatorColor); -QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor); -QByteArray buildTemplatePng(qreal opacity); + QPixmap buildPixmap(int size, qreal opacity, bool darkTheme, const QColor &indicatorColor); + QIcon buildIcon(qreal opacity, bool darkTheme, const QColor &indicatorColor); + QByteArray buildTemplatePng(qreal opacity); } // namespace TrayIconCommon