diff --git a/client/cmake/sources.cmake b/client/cmake/sources.cmake index 41f5388b1..75c0cdbd6 100644 --- a/client/cmake/sources.cmake +++ b/client/cmake/sources.cmake @@ -347,10 +347,12 @@ if(LINUX) ${CLIENT_ROOT_DIR}/platforms/linux/linuxutils.h ${CLIENT_ROOT_DIR}/platforms/linux/linuxtrayiconbackend.h ${CLIENT_ROOT_DIR}/platforms/linux/linuxtraytheme.h + ${CLIENT_ROOT_DIR}/ui/utils/trayThemeChangeFilter.h ) set(SOURCES ${SOURCES} ${CLIENT_ROOT_DIR}/platforms/linux/linuxutils.cpp ${CLIENT_ROOT_DIR}/platforms/linux/linuxtrayiconbackend.cpp ${CLIENT_ROOT_DIR}/platforms/linux/linuxtraytheme.cpp + ${CLIENT_ROOT_DIR}/ui/utils/trayThemeChangeFilter.cpp ) endif() diff --git a/client/platforms/linux/linuxtrayiconbackend.cpp b/client/platforms/linux/linuxtrayiconbackend.cpp index a19b91f13..7bf326d02 100644 --- a/client/platforms/linux/linuxtrayiconbackend.cpp +++ b/client/platforms/linux/linuxtrayiconbackend.cpp @@ -34,7 +34,13 @@ void LinuxTrayIconBackend::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)); + const QIcon icon = buildTrayIcon(opacity, visual.darkTheme, indicatorColor); + + // Some tray implementations cache the first icon; clear before applying an update. + if (m_trayIcon.isVisible()) { + m_trayIcon.setIcon(QIcon()); + } + m_trayIcon.setIcon(icon); } void LinuxTrayIconBackend::showMessage(const QString &title, const QString &message, const TrayIconVisual &visual, diff --git a/client/platforms/linux/linuxtraytheme.cpp b/client/platforms/linux/linuxtraytheme.cpp index 8e823e23b..290b53de8 100644 --- a/client/platforms/linux/linuxtraytheme.cpp +++ b/client/platforms/linux/linuxtraytheme.cpp @@ -1,7 +1,9 @@ #include "linuxtraytheme.h" #include "platforms/linux/linuxutils.h" +#include "ui/utils/trayThemeChangeFilter.h" +#include #include #include #include @@ -16,5 +18,7 @@ void LinuxTrayTheme::installThemeObserver(const std::function &onThemeCh QObject::connect(styleHints, &QStyleHints::colorSchemeChanged, parent, [onThemeChanged]() { onThemeChanged(); }); } + qApp->installEventFilter(new TrayThemeChangeFilter(onThemeChanged, parent)); + LinuxUtils::installThemeChangeObserver(onThemeChanged); } diff --git a/client/platforms/linux/linuxutils.cpp b/client/platforms/linux/linuxutils.cpp index 7aaf2756b..80fa46c8f 100644 --- a/client/platforms/linux/linuxutils.cpp +++ b/client/platforms/linux/linuxutils.cpp @@ -51,6 +51,11 @@ public: SLOT(onPortalSettingChanged(QString, QString, QDBusVariant))); } + void setCallback(std::function callback) + { + m_callback = std::move(callback); + } + private slots: void onPortalSettingChanged(const QString &namespaceName, const QString &key, const QDBusVariant &value) { @@ -114,7 +119,10 @@ void LinuxUtils::installThemeChangeObserver(std::function callback) if (!g_themeObserver) { g_themeObserver = new LinuxThemeObserver(std::move(callback), qApp); + return; } + + g_themeObserver->setCallback(std::move(callback)); } #include "linuxutils.moc" diff --git a/client/ui/utils/systemTrayNotificationHandler.cpp b/client/ui/utils/systemTrayNotificationHandler.cpp index f0b10c7ce..5c87462ad 100644 --- a/client/ui/utils/systemTrayNotificationHandler.cpp +++ b/client/ui/utils/systemTrayNotificationHandler.cpp @@ -78,12 +78,17 @@ void SystemTrayNotificationHandler::updateWebsiteUrl(const QString &newWebsiteUr void SystemTrayNotificationHandler::refreshTheme() { const bool isDarkTheme = platformIsDarkTheme(); - if (isDarkTheme == m_isDarkTheme) { - return; - } - + const bool themeChanged = (isDarkTheme != m_isDarkTheme); 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) { + updateTrayIcon(); + } +#endif } TrayIconVisual SystemTrayNotificationHandler::currentTrayVisual() const