Added initial support of system accent color.

This commit is contained in:
23rd
2026-03-01 08:52:54 +03:00
parent ad5b451182
commit 04ccdc4b30
7 changed files with 148 additions and 8 deletions
+1
View File
@@ -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";
+10 -2
View File
@@ -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);
+10
View File
@@ -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<bool> 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<bool> _nativeWindowFrame = false;
rpl::variable<std::optional<bool>> _systemDarkMode = std::nullopt;
rpl::variable<bool> _systemDarkModeEnabled = true;
bool _systemAccentColorEnabled = false;
rpl::variable<WindowTitleContent> _windowTitleContent;
WindowPosition _windowPosition; // per-window
bool _disableOpenGL = false;
@@ -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<QColor>()).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<ColorsPalette>(
container.get(),
container.get());
const auto systemAccentWrap = container->add(
object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
container,
object_ptr<Ui::Checkbox>(
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);
@@ -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() {
@@ -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 <QtGui/QGuiApplication>
#include <QtGui/QPalette>
namespace Window {
namespace Theme {
namespace {
@@ -175,6 +178,16 @@ style::colorizer ColorizerFrom(
return result;
}
std::optional<QColor> 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);
}
@@ -50,6 +50,7 @@ private:
[[nodiscard]] style::colorizer ColorizerFrom(
const EmbeddedScheme &scheme,
const QColor &color);
[[nodiscard]] std::optional<QColor> SystemAccentColor();
[[nodiscard]] style::colorizer ColorizerForTheme(const QString &absolutePath);
void Colorize(