feat(theme): implement Auto mode via system color-scheme

This commit is contained in:
Ly-sec
2026-05-06 16:34:29 +02:00
parent 7556f23a58
commit e096b56f88
3 changed files with 55 additions and 1 deletions
+16
View File
@@ -330,6 +330,22 @@ void Application::initServices() {
m_themeService.apply();
m_configService.addReloadCallback([this]() { m_themeService.onConfigReload(); });
// Watch the dconf user database so Auto mode reacts immediately to system
// color-scheme changes (org.gnome.desktop.interface color-scheme).
{
const char* xdg = std::getenv("XDG_CONFIG_HOME");
const char* home = std::getenv("HOME");
std::filesystem::path dconfDb;
if (xdg != nullptr && xdg[0] != '\0') {
dconfDb = std::filesystem::path(xdg) / "dconf" / "user";
} else if (home != nullptr && home[0] != '\0') {
dconfDb = std::filesystem::path(home) / ".config" / "dconf" / "user";
}
if (!dconfDb.empty()) {
m_fileWatcher.watch(dconfDb, [this]() { m_themeService.onAutoSchemeChanged(); });
}
}
if (!m_wayland.connect()) {
throw std::runtime_error("failed to connect to Wayland display");
}
+38 -1
View File
@@ -17,6 +17,7 @@
#include <exception>
#include <filesystem>
#include <fstream>
#include <gio/gio.h>
#include <json.hpp>
#include <sstream>
#include <string>
@@ -38,7 +39,37 @@ namespace noctalia::theme {
std::string mode;
};
std::string resolvedModeName(const ThemeConfig& cfg) { return cfg.mode == ThemeMode::Light ? "light" : "dark"; }
// Returns "light" or "dark" from org.gnome.desktop.interface color-scheme.
std::string_view readSystemColorScheme() {
static GSettings* settings = []() -> GSettings* {
GSettingsSchemaSource* source = g_settings_schema_source_get_default();
if (source == nullptr)
return nullptr;
GSettingsSchema* schema = g_settings_schema_source_lookup(source, "org.gnome.desktop.interface", TRUE);
if (schema == nullptr)
return nullptr;
const bool hasKey = g_settings_schema_has_key(schema, "color-scheme") != FALSE;
g_settings_schema_unref(schema);
if (!hasKey)
return nullptr;
return g_settings_new("org.gnome.desktop.interface");
}();
if (settings == nullptr)
return "dark";
gchar* raw = g_settings_get_string(settings, "color-scheme");
if (raw == nullptr)
return "dark";
const bool isLight = (std::string_view(raw) == "prefer-light");
g_free(raw);
return isLight ? "light" : "dark";
}
std::string resolvedModeName(const ThemeConfig& cfg) {
if (cfg.mode == ThemeMode::Auto)
return std::string(readSystemColorScheme());
return cfg.mode == ThemeMode::Light ? "light" : "dark";
}
ResolvedTheme resolveBuiltin(const ThemeConfig& cfg) {
const auto* palette = findBuiltinPalette(cfg.builtinPalette);
@@ -240,6 +271,12 @@ namespace noctalia::theme {
}
}
void ThemeService::onAutoSchemeChanged() {
if (m_config.config().theme.mode == ThemeMode::Auto) {
resolveAndSet(/*animate=*/true);
}
}
void ThemeService::toggleLightDark() {
const auto next = m_isLightMode ? ThemeMode::Dark : ThemeMode::Light;
// Persist via ConfigService → StateService. The resulting overrides-change
+1
View File
@@ -31,6 +31,7 @@ namespace noctalia::theme {
// Resolves the target theme and cross-fades to it.
void onConfigReload();
void onWallpaperChange();
void onAutoSchemeChanged();
void toggleLightDark();
void cycleMode();
[[nodiscard]] ThemeMode configuredMode() const noexcept;