From 04ccdc4b30f39541fab749831bbd95aa627401da Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 1 Mar 2026 08:52:54 +0300 Subject: [PATCH] Added initial support of system accent color. --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/core/core_settings.cpp | 12 ++- Telegram/SourceFiles/core/core_settings.h | 10 +++ .../settings/sections/settings_chat.cpp | 89 +++++++++++++++++-- .../window/themes/window_theme.cpp | 22 +++++ .../window/themes/window_themes_embedded.cpp | 21 ++++- .../window/themes/window_themes_embedded.h | 1 + 7 files changed, 148 insertions(+), 8 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index b643c1e348..ee568a35ef 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -829,6 +829,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_theme_tinted" = "Tinted"; "lng_settings_theme_night" = "Night"; "lng_settings_theme_accent_title" = "Choose accent color"; +"lng_settings_theme_system_accent_color" = "System accent color"; "lng_settings_data_storage" = "Data and storage"; "lng_settings_information" = "Edit profile"; "lng_settings_my_account" = "My Account"; diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index 2c94567b59..6e4b91d035 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -246,7 +246,7 @@ QByteArray Settings::serialize() const { + sizeof(ushort) + sizeof(qint32) // _notificationsDisplayChecksum + Serialize::bytearraySize(callPanelPosition) - + sizeof(qint32); + + sizeof(qint32) * 2; // _cornerReply + _systemAccentColorEnabled auto result = QByteArray(); result.reserve(size); @@ -412,7 +412,8 @@ QByteArray Settings::serialize() const { << _notificationsVolume << _notificationsDisplayChecksum << callPanelPosition - << qint32(_cornerReply.current() ? 1 : 0); + << qint32(_cornerReply.current() ? 1 : 0) + << qint32(_systemAccentColorEnabled ? 1 : 0); } Ensures(result.size() == size); @@ -546,6 +547,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) { quint32 chatFiltersHorizontal = _chatFiltersHorizontal.current() ? 1 : 0; quint32 quickDialogAction = quint32(_quickDialogAction); ushort notificationsVolume = _notificationsVolume; + qint32 systemAccentColorEnabled = _systemAccentColorEnabled + ? 1 + : 0; stream >> themesAccentColors; if (!stream.atEnd()) { @@ -889,6 +893,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) { if (!stream.atEnd()) { stream >> cornerReply; } + if (!stream.atEnd()) { + stream >> systemAccentColorEnabled; + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for Core::Settings::constructFromSerialized()")); @@ -929,6 +936,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { case ScreenCorner::BottomLeft: _notificationsCorner = uncheckedNotificationsCorner; break; } _notificationsDisplayChecksum = notificationsDisplayChecksum; + _systemAccentColorEnabled = (systemAccentColorEnabled == 1); _includeMutedCounter = (includeMutedCounter == 1); _includeMutedCounterFolders = (includeMutedCounterFolders == 1); _countUnreadMessages = (countUnreadMessages == 1); diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h index b6fc5e01f5..9525364652 100644 --- a/Telegram/SourceFiles/core/core_settings.h +++ b/Telegram/SourceFiles/core/core_settings.h @@ -390,6 +390,9 @@ public: [[nodiscard]] Window::Theme::AccentColors &themesAccentColors() { return _themesAccentColors; } + [[nodiscard]] const Window::Theme::AccentColors &themesAccentColors() const { + return _themesAccentColors; + } void setThemesAccentColors(Window::Theme::AccentColors &&colors) { _themesAccentColors = std::move(colors); } @@ -703,6 +706,12 @@ public: [[nodiscard]] rpl::producer systemDarkModeEnabledChanges() const { return _systemDarkModeEnabled.changes(); } + void setSystemAccentColorEnabled(bool value) { + _systemAccentColorEnabled = value; + } + [[nodiscard]] bool systemAccentColorEnabled() const { + return _systemAccentColorEnabled; + } [[nodiscard]] WindowTitleContent windowTitleContent() const { return _windowTitleContent.current(); } @@ -1068,6 +1077,7 @@ private: rpl::variable _nativeWindowFrame = false; rpl::variable> _systemDarkMode = std::nullopt; rpl::variable _systemDarkModeEnabled = true; + bool _systemAccentColorEnabled = false; rpl::variable _windowTitleContent; WindowPosition _windowPosition; // per-window bool _disableOpenGL = false; diff --git a/Telegram/SourceFiles/settings/sections/settings_chat.cpp b/Telegram/SourceFiles/settings/sections/settings_chat.cpp index 812bb4aa0b..2cac29431a 100644 --- a/Telegram/SourceFiles/settings/sections/settings_chat.cpp +++ b/Telegram/SourceFiles/settings/sections/settings_chat.cpp @@ -98,6 +98,14 @@ using namespace Builder; const auto kSchemesList = Window::Theme::EmbeddedThemes(); constexpr auto kCustomColorButtonParts = 7; +[[nodiscard]] bool IsSystemAccentColorSupported() { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + return true; +#else + return !Platform::IsWindows() || !Platform::IsWindows8OrGreater(); +#endif +} + class ColorsPalette final { public: using Type = Window::Theme::EmbeddedType; @@ -277,8 +285,12 @@ void ColorsPalette::show(Type type) { return; } list.insert(list.begin(), scheme->accentColor); - const auto color = Core::App().settings().themesAccentColors().get(type); - const auto current = color.value_or(scheme->accentColor); + const auto &settings = Core::App().settings(); + const auto color = settings.themesAccentColors().get(type); + const auto current = (settings.systemAccentColorEnabled() + ? Window::Theme::SystemAccentColor() + : std::optional()).value_or( + color.value_or(scheme->accentColor)); const auto i = ranges::find(list, current); if (i == end(list)) { list.back() = current; @@ -804,6 +816,22 @@ void BuildThemeOptionsSection(SectionBuilder &builder) { .keywords = { u"accent"_q, u"color"_q, u"customize"_q }, }; }); + + if (IsSystemAccentColorSupported()) { + builder.add(nullptr, [] { + return SearchEntry{ + .id = u"chat/themes-system-accent"_q, + .title = tr::lng_settings_theme_system_accent_color(tr::now), + .keywords = { + u"system"_q, + u"accent"_q, + u"color"_q, + u"theme"_q, + u"os"_q, + }, + }; + }); + } } void BuildThemeSettingsSection(SectionBuilder &builder) { @@ -2320,6 +2348,16 @@ void SetupDefaultThemes( const auto palette = Ui::CreateChild( container.get(), container.get()); + const auto systemAccentWrap = container->add( + object_ptr>( + container, + object_ptr( + container, + tr::lng_settings_theme_system_accent_color(tr::now), + Core::App().settings().systemAccentColorEnabled(), + st::settingsCheckbox)), + st::settingsCheckboxPadding); + systemAccentWrap->setDuration(0); const auto chosen = [] { const auto &object = Background()->themeObject(); @@ -2395,14 +2433,17 @@ void SetupDefaultThemes( palette->show(type); } - const auto &colors = Core::App().settings().themesAccentColors(); + const auto &settings = Core::App().settings(); const auto i = checks.find(type); const auto scheme = ranges::find(kSchemesList, type, &Scheme::type); if (scheme == end(kSchemesList)) { return; } + const auto color = settings.systemAccentColorEnabled() + ? Window::Theme::SystemAccentColor() + : settings.themesAccentColors().get(type); if (i != end(checks)) { - if (const auto color = colors.get(type)) { + if (color) { const auto colorizer = ColorizerFrom(*scheme, *color); i->second->setColors(ColorsFromScheme(*scheme, colorizer)); } else { @@ -2410,6 +2451,11 @@ void SetupDefaultThemes( } } }; + const auto refreshSystemAccentVisibility = [=](Type type) { + systemAccentWrap->toggle( + IsSystemAccentColorSupported() && (type != Type(-1)), + anim::type::instant); + }; group->setChangedCallback([=](Type type) { const auto scheme = ranges::find( kSchemesList, @@ -2424,6 +2470,22 @@ void SetupDefaultThemes( for (const auto &scheme : kSchemesList) { refreshColorizer(scheme.type); } + refreshSystemAccentVisibility(chosen()); + systemAccentWrap->entity()->checkedChanges( + ) | rpl::on_next([=](bool checked) { + auto &settings = Core::App().settings(); + if (settings.systemAccentColorEnabled() == checked) { + return; + } + settings.setSystemAccentColorEnabled(checked); + Local::writeSettings(); + + const auto type = chosen(); + const auto scheme = ranges::find(kSchemesList, type, &Scheme::type); + if (scheme != end(kSchemesList)) { + apply(*scheme); + } + }, container->lifetime()); if (highlights) { const auto add = st::roundRadiusSmall; @@ -2434,6 +2496,12 @@ void SetupDefaultThemes( .shape = HighlightShape::Ellipse, }, } }); + if (IsSystemAccentColorSupported()) { + highlights->push_back({ u"chat/themes-system-accent"_q, { + systemAccentWrap->entity(), + { .radius = st::boxRadius } + } }); + } } Background()->updates( @@ -2443,6 +2511,7 @@ void SetupDefaultThemes( return chosen(); }) | rpl::on_next([=](Type type) { refreshColorizer(type); + refreshSystemAccentVisibility(type); group->setValue(type); }, container->lifetime()); @@ -2492,9 +2561,19 @@ void SetupDefaultThemes( if (scheme == end(kSchemesList)) { return; } - auto &colors = Core::App().settings().themesAccentColors(); + auto &settings = Core::App().settings(); + auto changed = false; + if (settings.systemAccentColorEnabled()) { + settings.setSystemAccentColorEnabled(false); + systemAccentWrap->entity()->setChecked(false); + changed = true; + } + auto &colors = settings.themesAccentColors(); if (colors.get(type) != color) { colors.set(type, color); + changed = true; + } + if (changed) { Local::writeSettings(); } apply(*scheme); diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index f51fd766a8..f6d7d8ace0 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -566,6 +566,28 @@ void ChatBackground::start() { ) | rpl::on_next([](bool dark) { Core::App().settings().setSystemDarkMode(dark); }, _lifetime); + + rpl::single( + QGuiApplication::palette() + ) | rpl::then( + base::qt_signal_producer( + qApp, + &QGuiApplication::paletteChanged + ) + ) | rpl::on_next([=] { + const auto &settings = Core::App().settings(); + if (!settings.systemAccentColorEnabled() + || _themeObject.cloud.id + || editingTheme()) { + return; + } + const auto path = _themeObject.pathAbsolute; + if (!IsEmbeddedTheme(path)) { + return; + } + ApplyDefaultWithPath(path); + KeepApplied(); + }, _lifetime); } void ChatBackground::refreshThemeWatcher() { diff --git a/Telegram/SourceFiles/window/themes/window_themes_embedded.cpp b/Telegram/SourceFiles/window/themes/window_themes_embedded.cpp index 541534662d..58ebea3240 100644 --- a/Telegram/SourceFiles/window/themes/window_themes_embedded.cpp +++ b/Telegram/SourceFiles/window/themes/window_themes_embedded.cpp @@ -14,6 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/core_settings.h" #include "ui/style/style_palette_colorizer.h" +#include +#include + namespace Window { namespace Theme { namespace { @@ -175,6 +178,16 @@ style::colorizer ColorizerFrom( return result; } +std::optional SystemAccentColor() { +#if QT_VERSION >= QT_VERSION_CHECK(6, 6, 0) + constexpr auto kAccentRole = QPalette::ColorRole::Accent; +#else + constexpr auto kAccentRole = QPalette::ColorRole::Highlight; +#endif + const auto accent = QGuiApplication::palette().color(kAccentRole); + return accent.isValid() ? std::make_optional(accent) : std::nullopt; +} + style::colorizer ColorizerForTheme(const QString &absolutePath) { if (!IsEmbeddedTheme(absolutePath)) { return {}; @@ -187,7 +200,13 @@ style::colorizer ColorizerForTheme(const QString &absolutePath) { if (i == end(schemes)) { return {}; } - const auto &colors = Core::App().settings().themesAccentColors(); + const auto &settings = Core::App().settings(); + if (settings.systemAccentColorEnabled()) { + if (const auto accent = SystemAccentColor()) { + return ColorizerFrom(*i, *accent); + } + } + const auto &colors = settings.themesAccentColors(); if (const auto accent = colors.get(i->type)) { return ColorizerFrom(*i, *accent); } diff --git a/Telegram/SourceFiles/window/themes/window_themes_embedded.h b/Telegram/SourceFiles/window/themes/window_themes_embedded.h index cbef706e09..fd0a9ba6f6 100644 --- a/Telegram/SourceFiles/window/themes/window_themes_embedded.h +++ b/Telegram/SourceFiles/window/themes/window_themes_embedded.h @@ -50,6 +50,7 @@ private: [[nodiscard]] style::colorizer ColorizerFrom( const EmbeddedScheme &scheme, const QColor &color); +[[nodiscard]] std::optional SystemAccentColor(); [[nodiscard]] style::colorizer ColorizerForTheme(const QString &absolutePath); void Colorize(