diff --git a/cosmic-config/src/dbus.rs b/cosmic-config/src/dbus.rs index b2ecc272..a2c4f5af 100644 --- a/cosmic-config/src/dbus.rs +++ b/cosmic-config/src/dbus.rs @@ -1,7 +1,7 @@ use std::ops::Deref; use crate::CosmicConfigEntry; -use cosmic_settings_daemon::{Changed, ConfigProxy, CosmicSettingsDaemonProxy, Ping}; +use cosmic_settings_daemon::{ConfigProxy, CosmicSettingsDaemonProxy}; use futures_util::SinkExt; use iced_futures::futures::{future::pending, StreamExt}; pub async fn settings_daemon_proxy() -> zbus::Result> { @@ -35,10 +35,24 @@ impl Watcher { .await .map(|proxy| Self { proxy }) } + + pub async fn new_state( + settings_daemon_proxy: &CosmicSettingsDaemonProxy<'static>, + id: &str, + version: u64, + ) -> zbus::Result { + let (path, name) = settings_daemon_proxy.watch_state(id, version).await?; + ConfigProxy::builder(settings_daemon_proxy.connection()) + .path(path)? + .destination(name)? + .build() + .await + .map(|proxy| Self { proxy }) + } } #[derive(Debug)] -pub struct ConfigUpdate { +pub struct Update { pub errors: Vec, pub keys: Vec<&'static str>, pub config: T, @@ -47,11 +61,17 @@ pub struct ConfigUpdate { pub fn watcher_subscription( settings_daemon: CosmicSettingsDaemonProxy<'static>, config_id: &'static str, -) -> iced_futures::Subscription> { + is_state: bool, +) -> iced_futures::Subscription> { let id = std::any::TypeId::of::(); - iced_futures::subscription::channel((config_id, id), 5, move |mut tx| async move { + iced_futures::subscription::channel((is_state, config_id, id), 5, move |mut tx| async move { let version = T::VERSION; - let Ok(cosmic_config) = crate::Config::new(config_id, version) else { + + let Ok(cosmic_config) = (if is_state { + crate::Config::new_state(config_id, version) + } else { + crate::Config::new(config_id, version) + }) else { pending::<()>().await; unreachable!(); }; @@ -65,7 +85,7 @@ pub fn watcher_subscription().await; unreachable!(); }; loop { - let Ok(changes) = watcher.receive_changed().await else { + let Ok(mut changes) = watcher.receive_changed().await else { pending::<()>().await; unreachable!(); }; - let Ok(pings) = watcher.receive_ping().await else { - pending::<()>().await; - unreachable!(); - }; - let mut streams = futures_util::stream_select!( - changes.map(Message::ConfigChanged), - pings.map(Message::ConfigPing) - ); - while let Some(v) = streams.next().await { - match v { - Message::ConfigChanged(change) => { - let Ok(args) = change.args() else { - continue; - }; - let (errors, keys) = config.update_keys(&cosmic_config, &[args.key]); - if !keys.is_empty() { - if let Err(err) = tx - .send(ConfigUpdate { - errors, - keys, - config: config.clone(), - }) - .await - { - eprintln!("Failed to send config update: {err}"); - } - } - } - Message::ConfigPing(_) => { - // send pong - if let Err(err) = watcher.pong().await { - eprintln!("Failed to send pong: {err}"); - } + while let Some(change) = changes.next().await { + let Ok(args) = change.args() else { + continue; + }; + let (errors, keys) = config.update_keys(&cosmic_config, &[args.key]); + if !keys.is_empty() { + if let Err(err) = tx + .send(Update { + errors, + keys, + config: config.clone(), + }) + .await + { + eprintln!("Failed to send config update: {err}"); } } } } }) } - -pub enum Message { - ConfigChanged(Changed), - ConfigPing(Ping), -} diff --git a/examples/multi-window/Cargo.toml b/examples/multi-window/Cargo.toml index 97177ce3..18e0fff2 100644 --- a/examples/multi-window/Cargo.toml +++ b/examples/multi-window/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -libcosmic = { path = "../..", features = ["debug", "winit", "tokio", "single-instance", "multi-window"] } +libcosmic = { path = "../..", features = ["debug", "winit", "tokio", "single-instance", "multi-window", "dbus-config"] } diff --git a/src/app/core.rs b/src/app/core.rs index 219fc595..764063d8 100644 --- a/src/app/core.rs +++ b/src/app/core.rs @@ -218,9 +218,21 @@ impl Core { pub fn watch_config( &self, config_id: &'static str, - ) -> iced::Subscription> { + ) -> iced::Subscription> { if let Some(settings_daemon) = self.settings_daemon.clone() { - cosmic_config::dbus::watcher_subscription(settings_daemon, config_id) + cosmic_config::dbus::watcher_subscription(settings_daemon, config_id, false) + } else { + iced::Subscription::none() + } + } + + #[cfg(feature = "dbus-config")] + pub fn watch_state( + &self, + state_id: &'static str, + ) -> iced::Subscription> { + if let Some(settings_daemon) = self.settings_daemon.clone() { + cosmic_config::dbus::watcher_subscription(settings_daemon, state_id, true) } else { iced::Subscription::none() }