diff --git a/Cargo.lock b/Cargo.lock index da2869a..85be461 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1606,7 +1606,7 @@ dependencies = [ [[package]] name = "cosmic-pipewire" -version = "1.0.0-beta6" +version = "1.0.0" dependencies = [ "intmap", "libspa", @@ -1657,7 +1657,7 @@ dependencies = [ [[package]] name = "cosmic-settings" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "accounts-zbus", "anyhow", @@ -1739,7 +1739,7 @@ dependencies = [ [[package]] name = "cosmic-settings-a11y-manager-subscription" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "cosmic-protocols", "iced_futures", @@ -1752,7 +1752,7 @@ dependencies = [ [[package]] name = "cosmic-settings-accessibility-subscription" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "cosmic-dbus-a11y", "futures", @@ -1764,7 +1764,7 @@ dependencies = [ [[package]] name = "cosmic-settings-airplane-mode-subscription" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "futures", "iced_futures", @@ -1775,7 +1775,7 @@ dependencies = [ [[package]] name = "cosmic-settings-bluetooth-subscription" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "bluez-zbus", "futures", @@ -1817,7 +1817,7 @@ dependencies = [ [[package]] name = "cosmic-settings-daemon-subscription" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "futures", "iced_futures", @@ -1829,7 +1829,7 @@ dependencies = [ [[package]] name = "cosmic-settings-network-manager-subscription" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "bitflags 2.10.0", "cosmic-dbus-networkmanager", @@ -1847,7 +1847,7 @@ dependencies = [ [[package]] name = "cosmic-settings-page" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "derive_setters", "downcast-rs 2.0.2", @@ -1860,7 +1860,7 @@ dependencies = [ [[package]] name = "cosmic-settings-sound-subscription" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "cosmic-pipewire", "futures", @@ -1874,7 +1874,7 @@ dependencies = [ [[package]] name = "cosmic-settings-upower-subscription" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "futures", "iced_futures", @@ -1887,7 +1887,7 @@ dependencies = [ [[package]] name = "cosmic-settings-wallpaper" -version = "1.0.0-beta6" +version = "1.0.2" dependencies = [ "cosmic-bg-config", "cosmic-randr-shell", diff --git a/cosmic-settings/Cargo.toml b/cosmic-settings/Cargo.toml index 98fbb3a..c95d8a0 100644 --- a/cosmic-settings/Cargo.toml +++ b/cosmic-settings/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" license = "GPL-3.0-only" publish = false diff --git a/cosmic-settings/src/pages/accessibility/mod.rs b/cosmic-settings/src/pages/accessibility/mod.rs index 4213a7a..fbaf3d0 100644 --- a/cosmic-settings/src/pages/accessibility/mod.rs +++ b/cosmic-settings/src/pages/accessibility/mod.rs @@ -9,9 +9,7 @@ use cosmic::{ pub use cosmic_comp_config::ZoomMovement; use cosmic_config::CosmicConfigEntry; use cosmic_settings_a11y_manager_subscription as cosmic_a11y_manager; -use cosmic_settings_accessibility_subscription::{ - DBusRequest, DBusUpdate, subscription as a11y_subscription, -}; +use cosmic_settings_accessibility_subscription as a11y_bus; use cosmic_settings_daemon_config::CosmicSettingsDaemonConfig; use cosmic_settings_page::{ self as page, Insert, @@ -39,7 +37,7 @@ pub struct Page { high_contrast: Option, daemon_config: CosmicSettingsDaemonConfig, daemon_helper: cosmic_config::Config, - dbus_sender: Option>, + dbus_sender: Option>, reader_enabled: bool, } @@ -76,18 +74,18 @@ impl Default for Page { #[derive(Debug, Clone)] pub enum Message { + A11yBus(a11y_bus::Response), Event(cosmic_a11y_manager::AccessibilityEvent), + HighContrast(bool), ProtocolUnavailable, Return, - HighContrast(bool), - SystemTheme(Box), - SetScreenInverted(bool), + ScreenReaderEnabled(bool), SetScreenFilterActive(bool), SetScreenFilterSelection(ColorFilter), - Surface(surface::Action), + SetScreenInverted(bool), SetSoundMono(bool), - DBusUpdate(DBusUpdate), - ScreenReaderEnabled(bool), + Surface(surface::Action), + SystemTheme(Box), } impl From for crate::pages::Message { @@ -169,7 +167,7 @@ impl page::Page for Page { &self, _core: &cosmic::Core, ) -> cosmic::iced::Subscription { - a11y_subscription().map(|m| super::Message::Accessibility(Message::DBusUpdate(m))) + a11y_bus::subscription().map(|m| super::Message::Accessibility(Message::A11yBus(m))) } } @@ -434,16 +432,17 @@ impl Page { tracing::error!("{err:?}"); } } - Message::DBusUpdate(update) => match update { - DBusUpdate::Error(err) => { + Message::A11yBus(update) => match update { + a11y_bus::Response::Error(err) => { tracing::error!("{err}"); let _ = self.dbus_sender.take(); self.reader_enabled = false; } - DBusUpdate::Status(enabled) => { + a11y_bus::Response::ScreenReader(enabled) => { self.reader_enabled = enabled; } - DBusUpdate::Init(enabled, tx) => { + a11y_bus::Response::IsEnabled(_) => (), + a11y_bus::Response::Init(enabled, tx) => { self.reader_enabled = enabled; self.dbus_sender = Some(tx); } @@ -451,7 +450,7 @@ impl Page { Message::ScreenReaderEnabled(enabled) => { if let Some(tx) = &self.dbus_sender { self.reader_enabled = enabled; - let _ = tx.send(DBusRequest::Status(enabled)); + let _ = tx.send(a11y_bus::Request::ScreenReader(enabled)); } else { self.reader_enabled = false; } diff --git a/crates/cosmic-pipewire/Cargo.toml b/crates/cosmic-pipewire/Cargo.toml index 9e8cc2a..34a93b6 100644 --- a/crates/cosmic-pipewire/Cargo.toml +++ b/crates/cosmic-pipewire/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "cosmic-pipewire" -version = "1.0.0-beta6" +version = "1.0.0" edition = "2024" +repository = "https://github.com/pop-os/cosmic-settings" rust-version.workspace = true license = "MPL-2.0" publish = true diff --git a/debian/changelog b/debian/changelog index fde597a..198e6e9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +cosmic-settings (1.0.2) noble; urgency=medium + + * Released version + + -- Michael Murphy Fri, 09 Jan 2026 21:31:17 +0100 + cosmic-settings (0.1.0) jammy; urgency=medium * Project in development diff --git a/page/Cargo.toml b/page/Cargo.toml index c4b64a1..82b9f9e 100644 --- a/page/Cargo.toml +++ b/page/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-page" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" [dependencies] diff --git a/pages/wallpapers/Cargo.toml b/pages/wallpapers/Cargo.toml index 8381c5e..7c5af72 100644 --- a/pages/wallpapers/Cargo.toml +++ b/pages/wallpapers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-wallpaper" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" rust-version.workspace = true diff --git a/subscriptions/a11y-manager/Cargo.toml b/subscriptions/a11y-manager/Cargo.toml index c702525..70785a7 100644 --- a/subscriptions/a11y-manager/Cargo.toml +++ b/subscriptions/a11y-manager/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-a11y-manager-subscription" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" license = "MPL-2.0" rust-version.workspace = true diff --git a/subscriptions/accessibility/Cargo.toml b/subscriptions/accessibility/Cargo.toml index a49dd2f..295a3ee 100644 --- a/subscriptions/accessibility/Cargo.toml +++ b/subscriptions/accessibility/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-accessibility-subscription" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" license = "MPL-2.0" rust-version.workspace = true @@ -10,6 +10,6 @@ publish = true cosmic-dbus-a11y = { git = "https://github.com/pop-os/dbus-settings-bindings" } futures = "0.3.31" iced_futures = { git = "https://github.com/pop-os/libcosmic" } -tokio = "1.48.0" +tokio = { version = "1.48.0", features = ["sync", "time"] } tracing = "0.1.41" -zbus = "5.12.0" +zbus = "5" diff --git a/subscriptions/accessibility/src/lib.rs b/subscriptions/accessibility/src/lib.rs index b7908bc..e2ad484 100644 --- a/subscriptions/accessibility/src/lib.rs +++ b/subscriptions/accessibility/src/lib.rs @@ -2,132 +2,154 @@ // SPDX-License-Identifier: GPL-3.0-only use cosmic_dbus_a11y::*; -use futures::FutureExt; -use futures::{self, SinkExt, StreamExt, select}; +use futures::{self, SinkExt, StreamExt}; use iced_futures::{Subscription, stream}; use std::fmt::Debug; use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender}; use zbus::Connection; #[derive(Debug, Clone)] -pub enum DBusUpdate { +pub enum Response { Error(String), - Status(bool), - Init(bool, UnboundedSender), + IsEnabled(bool), + ScreenReader(bool), + Init(bool, UnboundedSender), } -pub enum DBusRequest { - Status(bool), +pub enum Request { + /// Enable the org.a11y.Bus + Enable(bool), + /// Enable the screen reader feature of org.a11y.Bus + ScreenReader(bool), } #[derive(Debug)] -pub enum State { - Ready, - Waiting(Connection, u8, bool, UnboundedReceiver), - Finished, +pub struct State { + conn: Connection, + retry: u8, + enabled: bool, + rx: UnboundedReceiver, } -pub fn subscription() -> Subscription { +pub fn subscription() -> Subscription { struct MyId; Subscription::run_with_id( std::any::TypeId::of::(), - stream::channel(50, move |mut output| async move { - let mut state = State::Ready; - - loop { - state = start_listening(state, &mut output).await; + stream::channel(1, move |mut output| async move { + if let Some(state) = State::new(&mut output).await { + state.listen(&mut output).await; } + + futures::future::pending::<()>().await; }), ) } -async fn start_listening( - state: State, - output: &mut futures::channel::mpsc::Sender, -) -> State { - match state { - State::Ready => { - let conn = match Connection::session().await.map_err(|e| e.to_string()) { - Ok(conn) => conn, - Err(e) => { - _ = output.send(DBusUpdate::Error(e)).await; - return State::Finished; - } - }; - let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); - let mut enabled = false; - if let Ok(proxy) = StatusProxy::new(&conn).await { - if let Ok(status) = proxy.screen_reader_enabled().await { - enabled = status; - } +impl State { + pub async fn new(output: &mut futures::channel::mpsc::Sender) -> Option { + let conn = match Connection::session().await.map_err(|e| e.to_string()) { + Ok(conn) => conn, + Err(e) => { + _ = output.send(Response::Error(e)).await; + return None; } - _ = output.send(DBusUpdate::Init(enabled, tx)).await; - State::Waiting(conn, 20, enabled, rx) - } - State::Waiting(conn, mut retry, mut enabled, mut rx) => { - let Ok(proxy) = StatusProxy::new(&conn).await else { - if retry == 0 { - tracing::error!("Accessibility Status is unavailable."); - return State::Finished; - } else { - _ = tokio::time::sleep(tokio::time::Duration::from_secs( - 2_u64.pow(retry as u32), - )) - .await; - retry -= 1; - return State::Waiting(conn, retry, enabled, rx); - } - }; - retry = 20; - - let mut watch_changes = proxy.receive_screen_reader_enabled_changed().await; - + }; + let (tx, rx) = tokio::sync::mpsc::unbounded_channel(); + let mut enabled = false; + if let Ok(proxy) = StatusProxy::new(&conn).await { if let Ok(status) = proxy.screen_reader_enabled().await { - if enabled != status { - _ = output.send(DBusUpdate::Status(enabled)); - } enabled = status; } + } + _ = output.send(Response::Init(enabled, tx)).await; + Some(State { + conn, + retry: 20, + enabled, + rx, + }) + } - loop { - if let Ok(status) = proxy.screen_reader_enabled().await { - if enabled != status { - _ = output.send(DBusUpdate::Status(enabled)); - } - enabled = status; + pub async fn listen(mut self, output: &mut futures::channel::mpsc::Sender) { + loop { + let Ok(proxy) = StatusProxy::new(&self.conn).await else { + if self.retry == 0 { + tracing::error!("Accessibility Status is unavailable."); + return; + } else { + _ = tokio::time::sleep(tokio::time::Duration::from_secs( + 2_u64.pow(self.retry as u32), + )) + .await; + self.retry -= 1; + continue; } + }; - let mut next_change = Box::pin(watch_changes.next()).fuse(); - let mut next_request = Box::pin(rx.recv()).fuse(); + self.retry = 20; - select! { - v = next_request => { - match v { - Some(DBusRequest::Status(is_enabled)) => { - // Set status - enabled = is_enabled; - _ = proxy.set_is_enabled(is_enabled).await; - _ = proxy.set_screen_reader_enabled(is_enabled).await; - } - None => return State::Finished, - } - } - v = next_change => { - match v { - Some(f) => { - if let Ok(enabled) = f.get().await { - _ = output.send(DBusUpdate::Status(enabled)); - } - } - None => break, - }; - } + let Ok(properties_proxy) = + zbus::fdo::PropertiesProxy::new(&self.conn, "org.a11y.Bus", "/org/a11y/bus").await + else { + tracing::error!("org.a11y.Bus properties proxy failed"); + return; + }; + + let Ok(mut properties_changed_stream) = + properties_proxy.receive_properties_changed().await + else { + tracing::error!("org.a11y.Bus receive properties changed failed"); + return; + }; + + if let Ok(status) = proxy.screen_reader_enabled().await { + if self.enabled != status { + _ = output.send(Response::ScreenReader(self.enabled)).await; } + self.enabled = status; } - State::Waiting(conn, retry, enabled, rx) + let requests_fut = Box::pin(async { + while let Some(request) = self.rx.recv().await { + match request { + Request::ScreenReader(is_enabled) => { + _ = proxy.set_is_enabled(is_enabled).await; + _ = proxy.set_screen_reader_enabled(is_enabled).await; + } + + Request::Enable(is_enabled) => { + _ = proxy.set_is_enabled(is_enabled).await; + } + } + } + }); + + let properties_fut = Box::pin(async { + while let Some(signal) = properties_changed_stream.next().await { + if let Ok(args) = signal.args() { + for (name, value) in args.changed_properties().iter() { + match *name { + "IsEnabled" => { + if let Ok(status) = value.downcast_ref::() { + _ = output.send(Response::IsEnabled(status)).await; + } + } + + "ScreenReaderEnabled" => { + if let Ok(status) = value.downcast_ref::() { + _ = output.send(Response::ScreenReader(status)).await; + } + } + + _ => (), + } + } + } + } + }); + + futures::future::select(properties_fut, requests_fut).await; } - State::Finished => futures::future::pending().await, } } diff --git a/subscriptions/airplane-mode/Cargo.toml b/subscriptions/airplane-mode/Cargo.toml index 0cd4fb8..6c74b48 100644 --- a/subscriptions/airplane-mode/Cargo.toml +++ b/subscriptions/airplane-mode/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-airplane-mode-subscription" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" license = "MPL-2.0" rust-version.workspace = true diff --git a/subscriptions/bluetooth/Cargo.toml b/subscriptions/bluetooth/Cargo.toml index 141eb3c..2ef6560 100644 --- a/subscriptions/bluetooth/Cargo.toml +++ b/subscriptions/bluetooth/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-bluetooth-subscription" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" license = "MPL-2.0" rust-version.workspace = true diff --git a/subscriptions/network-manager/Cargo.toml b/subscriptions/network-manager/Cargo.toml index 7500052..fdf2d05 100644 --- a/subscriptions/network-manager/Cargo.toml +++ b/subscriptions/network-manager/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-network-manager-subscription" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" license = "MPL-2.0" rust-version.workspace = true diff --git a/subscriptions/network-manager/src/nm_secret_agent.rs b/subscriptions/network-manager/src/nm_secret_agent.rs index 4435cc8..4a39ab0 100644 --- a/subscriptions/network-manager/src/nm_secret_agent.rs +++ b/subscriptions/network-manager/src/nm_secret_agent.rs @@ -496,7 +496,7 @@ impl SettingsSecretAgent { setting_attributes.insert("uuid", &conn_uuid); setting_attributes.insert("setting_name", &setting_name); - let mut search_items = collection + let search_items = collection .search_items(setting_attributes.clone()) .await .map_err(|e| Arc::new(e))?; diff --git a/subscriptions/settings-daemon/Cargo.toml b/subscriptions/settings-daemon/Cargo.toml index f6a6e21..4f79241 100644 --- a/subscriptions/settings-daemon/Cargo.toml +++ b/subscriptions/settings-daemon/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-daemon-subscription" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" rust-version.workspace = true publish = true diff --git a/subscriptions/sound/Cargo.toml b/subscriptions/sound/Cargo.toml index 0865fe0..60cae71 100644 --- a/subscriptions/sound/Cargo.toml +++ b/subscriptions/sound/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-sound-subscription" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" rust-version.workspace = true license = "MPL-2.0" diff --git a/subscriptions/upower/Cargo.toml b/subscriptions/upower/Cargo.toml index d0c752f..4e72b73 100644 --- a/subscriptions/upower/Cargo.toml +++ b/subscriptions/upower/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cosmic-settings-upower-subscription" -version = "1.0.0-beta6" +version = "1.0.2" edition = "2024" license = "MPL-2.0" rust-version.workspace = true