From 06b46f455b0e97f8156be1a1a7296207c2a0f62a Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 1 Mar 2024 20:21:52 -0500 Subject: [PATCH] wip: support desktop portal color-scheme, and accent variables --- examples/application/Cargo.toml | 3 +- examples/application/src/main.rs | 6 ++- src/app/cosmic.rs | 29 ++++++++---- src/app/mod.rs | 18 +++++++ src/theme/mod.rs | 4 +- src/theme/portal.rs | 81 ++++++++++++++++++++++++-------- 6 files changed, 107 insertions(+), 34 deletions(-) diff --git a/examples/application/Cargo.toml b/examples/application/Cargo.toml index 33ba450..e19f1d3 100644 --- a/examples/application/Cargo.toml +++ b/examples/application/Cargo.toml @@ -6,8 +6,9 @@ edition = "2021" [dependencies] tracing = "0.1.37" tracing-subscriber = "0.3.17" +tracing-log = "0.2.0" [dependencies.libcosmic] path = "../../" default-features = false -features = ["debug", "winit", "tokio"] +features = ["debug", "winit", "tokio", "xdg-portal"] diff --git a/examples/application/src/main.rs b/examples/application/src/main.rs index a84eca1..142363b 100644 --- a/examples/application/src/main.rs +++ b/examples/application/src/main.rs @@ -30,6 +30,9 @@ impl Page { /// Runs application with these settings #[rustfmt::skip] fn main() -> Result<(), Box> { + tracing_subscriber::fmt::init(); + let _ = tracing_log::LogTracer::init(); + let input = vec![ (Page::Page1, "🖖 Hello from libcosmic.".into()), (Page::Page2, "🌟 This is an example application.".into()), @@ -44,8 +47,7 @@ fn main() -> Result<(), Box> { .default_icon_theme("Pop") .default_text_size(16.0) .scale_factor(1.0) - .size(Size::new(1024., 768.)) - .theme(cosmic::Theme::dark()); + .size(Size::new(1024., 768.)); cosmic::app::run::(settings, input)?; diff --git a/src/app/cosmic.rs b/src/app/cosmic.rs index 88a06dc..e2e497f 100644 --- a/src/app/cosmic.rs +++ b/src/app/cosmic.rs @@ -18,9 +18,9 @@ use iced::event::PlatformSpecific; use iced::multi_window::Application as IcedApplication; #[cfg(feature = "wayland")] use iced::wayland::Application as IcedApplication; -use iced::window; #[cfg(not(any(feature = "multi-window", feature = "wayland")))] use iced::Application as IcedApplication; +use iced::{window, Command}; use iced_futures::event::listen_with; #[cfg(not(feature = "wayland"))] use iced_runtime::command::Action; @@ -54,9 +54,9 @@ pub enum Message { /// Toggles the condensed status of the nav bar. ToggleNavBarCondensed, /// Notification of system theme changes. - SystemThemeChange(Theme), + SystemThemeChange(Vec<&'static str>, Theme), /// Notification of system theme mode changes. - SystemThemeModeChange(ThemeMode), + SystemThemeModeChange(Vec<&'static str>, ThemeMode), /// Updates the window maximized state WindowMaximized(window::Id, bool), /// Updates the tracked window geometry. @@ -193,7 +193,10 @@ where for e in update.errors { tracing::error!("{e}"); } - Message::SystemThemeChange(crate::theme::Theme::system(Arc::new(update.config))) + Message::SystemThemeChange( + update.keys, + crate::theme::Theme::system(Arc::new(update.config)), + ) }) .map(super::Message::Cosmic), self.app @@ -203,7 +206,7 @@ where for e in update.errors { tracing::error!("{e}"); } - Message::SystemThemeModeChange(update.config) + Message::SystemThemeModeChange(update.keys, update.config) }) .map(super::Message::Cosmic), window_events.map(super::Message::Cosmic), @@ -215,7 +218,7 @@ where .unwrap_or_else(Subscription::none), #[cfg(feature = "xdg-portal")] crate::theme::portal::desktop_settings() - .map(|e| Message::DesktopSettings(e)) + .map(Message::DesktopSettings) .map(super::Message::Cosmic), ]; @@ -387,7 +390,8 @@ impl Cosmic { }); } - Message::SystemThemeChange(theme) => { + Message::SystemThemeChange(keys, theme) => { + let cmd = self.app.system_theme_update(&keys, theme.cosmic()); // Record the last-known system theme in event that the current theme is custom. self.app.core_mut().system_theme = theme.clone(); let portal_accent = self.app.core().portal_accent; @@ -409,6 +413,8 @@ impl Cosmic { cosmic_theme.set_theme(new_theme.theme_type); } }); + + return cmd; } Message::ScaleFactor(factor) => { @@ -419,7 +425,9 @@ impl Cosmic { self.app.on_app_exit(); return self.close(); } - Message::SystemThemeModeChange(mode) => { + Message::SystemThemeModeChange(keys, mode) => { + let mut cmds = vec![self.app.system_theme_mode_update(&keys, &mode)]; + let core = self.app.core_mut(); let prev_is_dark = core.system_is_dark(); core.system_theme_mode = mode; @@ -432,7 +440,9 @@ impl Cosmic { } else { crate::theme::system_light() }; + cmds.push(self.app.system_theme_update(&[], new_theme.cosmic())); + let core = self.app.core_mut(); new_theme = if let Some(a) = core.portal_accent { let t_inner = new_theme.cosmic(); if a.distance_squared(*t_inner.accent_color()) > 0.00001 { @@ -454,6 +464,7 @@ impl Cosmic { } }); } + return Command::batch(cmds); } Message::Activate(_token) => { #[cfg(feature = "wayland")] @@ -505,7 +516,7 @@ impl Cosmic { } #[cfg(feature = "xdg-portal")] Message::DesktopSettings(crate::theme::portal::Desktop::Accent(c)) => { - use palette::{IntoColor, Oklch, Oklcha, Srgb, Srgba}; + use palette::Srgba; let c = Srgba::new(c.red() as f32, c.green() as f32, c.blue() as f32, 1.0); let core = self.app.core_mut(); diff --git a/src/app/mod.rs b/src/app/mod.rs index 5eb7bc7..6ac5234 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -511,6 +511,24 @@ where iced::Command::none() } + /// Respond to a system theme change + fn system_theme_update( + &mut self, + keys: &[&'static str], + new_theme: &cosmic_theme::Theme, + ) -> iced::Command> { + iced::Command::none() + } + + /// Respond to a system theme mode change + fn system_theme_mode_update( + &mut self, + keys: &[&'static str], + new_theme: &cosmic_theme::ThemeMode, + ) -> iced::Command> { + iced::Command::none() + } + /// Constructs the view for the main window. fn view(&self) -> Element; diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 1dae5b5..815a870 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -112,8 +112,8 @@ pub fn system_dark() -> Theme { } pub fn system_light() -> Theme { - let Ok(helper) = crate::cosmic_theme::Theme::dark_config() else { - return Theme::dark(); + let Ok(helper) = crate::cosmic_theme::Theme::light_config() else { + return Theme::light(); }; let t = crate::cosmic_theme::Theme::get_entry(&helper).unwrap_or_else(|(errors, theme)| { diff --git a/src/theme/portal.rs b/src/theme/portal.rs index b37dfe4..b1875d6 100644 --- a/src/theme/portal.rs +++ b/src/theme/portal.rs @@ -1,7 +1,9 @@ use ashpd::desktop::settings::{ColorScheme, Contrast}; use ashpd::desktop::Color; use iced::futures::{self, select, FutureExt, SinkExt, StreamExt}; +use iced::Subscription; use iced_futures::subscription; +use tracing::error; #[derive(Debug, Clone)] pub enum Desktop { @@ -15,12 +17,56 @@ pub fn desktop_settings() -> iced_futures::Subscription { async move { let Ok(settings) = ashpd::desktop::settings::Settings::new().await else { // wait forever + error!("Failed to create the settings proxy"); futures::future::pending::<()>().await; unreachable!() }; + + match settings.color_scheme().await { + Ok(color_scheme) => { + dbg!(color_scheme); + let _ = tx.send(Desktop::ColorScheme(color_scheme)).await; + } + Err(err) => error!("Failed to get the color scheme {err:?}"), + }; + // match settings + // .read::("org.freedesktop.appearance", "accent-color") + // .await + // { + // Ok(accent_color) => { + // dbg!(&accent_color); + // // let _ = tx.send(Desktop::Accent(accent_color)).await; + // } + // Err(err) => error!("Failed to get the accent color {err:?}"), + // }; + match settings.contrast().await { + Ok(contrast) => { + dbg!(contrast); + let _ = tx.send(Desktop::Contrast(contrast)).await; + } + Err(err) => error!("Failed to get the contrast {err:?}"), + }; + let mut color_scheme_stream = settings.receive_color_scheme_changed().await.ok(); - let mut accent_stream = settings.receive_accent_color_changed().await.ok(); + if color_scheme_stream.is_none() { + error!("Failed to receive color scheme changes"); + } + // Item type is wrong in this version + // updating requires updating to zbus 4 + let mut accent_stream = settings + .receive_setting_changed_with_args::( + "org.freedesktop.appearance", + "accent-color", + ) + .await + .ok(); + if accent_stream.is_none() { + error!("Failed to receive accent color changes"); + } let mut contrast_stream = settings.receive_contrast_changed().await.ok(); + if contrast_stream.is_none() { + error!("Failed to receive contrast changes"); + } loop { let next_color_scheme = async { @@ -29,18 +75,12 @@ pub fn desktop_settings() -> iced_futures::Subscription { } futures::future::pending().await }; - let next_accent = async { - if let Some(s) = accent_stream.as_mut() { - // Item type is wrong in this version - // updating requires updating to zbus 4 - return if s.next().await.is_some() { - settings.accent_color().await.ok() - } else { - None - }; - } - futures::future::pending().await - }; + // let next_accent = async { + // if let Some(s) = accent_stream.as_mut() { + // return s.next().await.and_then(std::result::Result::ok); + // } + // futures::future::pending().await + // }; let next_contrast = async { if let Some(s) = contrast_stream.as_mut() { return s.next().await; @@ -56,13 +96,14 @@ pub fn desktop_settings() -> iced_futures::Subscription { color_scheme_stream = None; } }, - a = next_accent.fuse() => { - if let Some(a) = a { - _ = tx.send(Desktop::Accent(a)).await; - } else { - accent_stream = None; - } - }, + // a = next_accent.fuse() => { + // dbg!(a); + // if let Some(a) = a { + // _ = tx.send(Desktop::Accent(a)).await; + // } else { + // accent_stream = None; + // } + // }, c = next_contrast.fuse() => { if let Some(c) = c { _ = tx.send(Desktop::Contrast(c)).await;