feat(theme): exportación a GTK + inyección de entorno en el compositor

Segunda mitad de la uniformización del tema. nahual-theme::toolkit
traduce el Theme activo a gtk-3.0/gtk.css y gtk-4.0/gtk.css con overrides
@define-color (acento exacto + neutro claro/oscuro sintetizado).
Theme::set/install_default exportan best-effort; guarda de no-pisar
respeta un gtk.css ajeno. El compositor inyecta XDG_CURRENT_DESKTOP=mirada
y QT_QPA_PLATFORMTHEME=gtk3 a cada hijo, así GTK y Qt siguen el tema.

8 tests nuevos en toolkit; ejemplo dump-toolkit-css.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 17:41:35 +00:00
parent 5369c307e4
commit af3be482a9
6 changed files with 439 additions and 7 deletions
+17 -4
View File
@@ -8,7 +8,9 @@
//! ningún widget concreto. Cada widget pide slots semánticos (panel_bg,
//! row_hover, accent…) sin acoplarse a colores hex específicos.
use gpui::{Background, Global, Hsla, hsla, linear_color_stop, linear_gradient};
use gpui::{hsla, linear_color_stop, linear_gradient, Background, Global, Hsla};
pub mod toolkit;
/// Paleta semántica del theme. Cada slot tiene un nombre funcional, no
/// cromático — así los widgets piden "fondo de panel" sin acoplarse a
@@ -121,6 +123,8 @@ impl Theme {
/// theme cambia (típicamente vía `theme_switcher`).
pub fn install_default(cx: &mut gpui::App) {
let theme = load_persisted().unwrap_or_else(Self::nebula);
// Asegura que GTK/Qt arranquen con el `gtk.css` del tema activo.
let _ = toolkit::export_toolkit_configs(&theme);
cx.set_global(theme);
}
@@ -134,6 +138,8 @@ impl Theme {
/// por un I/O secundario.
pub fn set(cx: &mut gpui::App, theme: Self) {
let _ = persist(&theme);
// Reexporta `gtk.css` para que las apps GTK/Qt sigan el cambio.
let _ = toolkit::export_toolkit_configs(&theme);
cx.set_global(theme);
}
@@ -484,7 +490,15 @@ const CONFIG_FILE: &str = "theme";
/// sino `$HOME/.config/nahual/theme`. `None` si ni `XDG_CONFIG_HOME`
/// ni `HOME` están definidos (típicamente en sandboxes / CI).
pub fn config_path() -> Option<PathBuf> {
let base = std::env::var("XDG_CONFIG_HOME")
Some(config_home()?.join(CONFIG_SUBDIR).join(CONFIG_FILE))
}
/// Directorio base de configuración del usuario: `$XDG_CONFIG_HOME` si
/// está definido, sino `$HOME/.config`. `None` si ninguno está set
/// (típicamente en sandboxes / CI). Lo usan [`config_path`] y el módulo
/// [`toolkit`] para ubicar `gtk-3.0/gtk.css` y `gtk-4.0/gtk.css`.
pub(crate) fn config_home() -> Option<PathBuf> {
std::env::var("XDG_CONFIG_HOME")
.ok()
.filter(|s| !s.is_empty())
.map(PathBuf::from)
@@ -493,8 +507,7 @@ pub fn config_path() -> Option<PathBuf> {
.ok()
.filter(|s| !s.is_empty())
.map(|h| PathBuf::from(h).join(".config"))
})?;
Some(base.join(CONFIG_SUBDIR).join(CONFIG_FILE))
})
}
/// Lee el theme persistido. `None` si: no hay config dir, file no