add windows theme source and platform icon resolvers

This commit is contained in:
2026-10-31 08:56:57 +07:00
parent c45f939211
commit d53f4e290d
13 changed files with 895 additions and 36 deletions
+15 -20
View File
@@ -12,6 +12,7 @@ use super::ThemeSource;
use super::kde;
use super::omarchy;
use super::portal;
use super::signal::ReapplySignal;
use crate::ThemeVariant;
use crate::system::{PartialPalette, SourceKind, SystemTheme};
@@ -20,7 +21,8 @@ pub(crate) struct LinuxSource {
portal: Option<portal::io::PortalClient>,
gsettings: Option<GSettingsSnapshot>,
file_watcher: Option<notify::RecommendedWatcher>,
reapply_task: Option<gpui::Task<()>>,
/// Keeps the main-thread channel loop alive.
_signal: Option<ReapplySignal>,
}
/// Which payload the source reads.
@@ -106,11 +108,13 @@ fn read_gsettings() -> Option<GSettingsSnapshot> {
pub(crate) fn platform_source() -> Box<dyn ThemeSource> {
let portal = portal::io::PortalClient::connect();
let gsettings = if portal.is_none() {
read_gsettings()
} else {
None
};
let backend = home_dir()
.map(|home| detect(&home, portal.is_some(), gsettings.is_some()))
.unwrap_or(Backend::Fallback);
@@ -120,7 +124,7 @@ pub(crate) fn platform_source() -> Box<dyn ThemeSource> {
portal,
gsettings,
file_watcher: None,
reapply_task: None,
_signal: None,
})
}
@@ -185,18 +189,10 @@ impl ThemeSource for LinuxSource {
}
fn install_watchers(&mut self, async_cx: gpui::AsyncApp) {
let (reapply_signal, reapply_events) = async_channel::unbounded::<()>();
async_cx.update(|cx| {
self.reapply_task = Some(cx.spawn(async move |cx| {
while reapply_events.recv().await.is_ok() {
cx.update(crate::reapply);
}
}));
});
let signal = ReapplySignal::install(&async_cx);
if let Some(portal) = &self.portal {
portal.spawn_watch(reapply_signal.clone());
portal.spawn_watch(signal.sender());
}
match self.backend {
@@ -204,14 +200,11 @@ impl ThemeSource for LinuxSource {
let Some(current) = omarchy::io::current_dir() else {
return;
};
let reapply_signal = signal.sender();
let watcher = notify::recommended_watcher(
move |event: std::result::Result<notify::Event, notify::Error>| match event {
Ok(_) => {
if let Err(error) = reapply_signal.try_send(()) {
eprintln!("theme: omarchy reapply signal failed: {error}");
}
}
Ok(_) => ReapplySignal::poke(&reapply_signal),
Err(error) => eprintln!("theme: omarchy watch error: {error}"),
},
);
@@ -231,15 +224,15 @@ impl ThemeSource for LinuxSource {
let Some(config) = home_dir().map(|home| home.join(".config")) else {
return;
};
let reapply_signal = signal.sender();
let watcher = notify::recommended_watcher(
move |event: std::result::Result<notify::Event, notify::Error>| match event {
Ok(event) => {
if event.paths.iter().any(|path| {
path.file_name().is_some_and(|name| name == "kdeglobals")
}) && let Err(error) = reapply_signal.try_send(())
{
eprintln!("theme: kde reapply signal failed: {error}");
}) {
ReapplySignal::poke(&reapply_signal);
}
}
Err(error) => eprintln!("theme: kde watch error: {error}"),
@@ -258,6 +251,8 @@ impl ThemeSource for LinuxSource {
}
Backend::Portal | Backend::Fallback => {}
}
self._signal = Some(signal);
}
fn label(&self) -> &'static str {