wip: support desktop portal color-scheme, and accent variables

This commit is contained in:
Ashley Wulber 2024-03-01 20:21:52 -05:00 committed by Ashley Wulber
parent c390b2614d
commit 06b46f455b
6 changed files with 107 additions and 34 deletions

View file

@ -6,8 +6,9 @@ edition = "2021"
[dependencies] [dependencies]
tracing = "0.1.37" tracing = "0.1.37"
tracing-subscriber = "0.3.17" tracing-subscriber = "0.3.17"
tracing-log = "0.2.0"
[dependencies.libcosmic] [dependencies.libcosmic]
path = "../../" path = "../../"
default-features = false default-features = false
features = ["debug", "winit", "tokio"] features = ["debug", "winit", "tokio", "xdg-portal"]

View file

@ -30,6 +30,9 @@ impl Page {
/// Runs application with these settings /// Runs application with these settings
#[rustfmt::skip] #[rustfmt::skip]
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
let _ = tracing_log::LogTracer::init();
let input = vec![ let input = vec![
(Page::Page1, "🖖 Hello from libcosmic.".into()), (Page::Page1, "🖖 Hello from libcosmic.".into()),
(Page::Page2, "🌟 This is an example application.".into()), (Page::Page2, "🌟 This is an example application.".into()),
@ -44,8 +47,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
.default_icon_theme("Pop") .default_icon_theme("Pop")
.default_text_size(16.0) .default_text_size(16.0)
.scale_factor(1.0) .scale_factor(1.0)
.size(Size::new(1024., 768.)) .size(Size::new(1024., 768.));
.theme(cosmic::Theme::dark());
cosmic::app::run::<App>(settings, input)?; cosmic::app::run::<App>(settings, input)?;

View file

@ -18,9 +18,9 @@ use iced::event::PlatformSpecific;
use iced::multi_window::Application as IcedApplication; use iced::multi_window::Application as IcedApplication;
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
use iced::wayland::Application as IcedApplication; use iced::wayland::Application as IcedApplication;
use iced::window;
#[cfg(not(any(feature = "multi-window", feature = "wayland")))] #[cfg(not(any(feature = "multi-window", feature = "wayland")))]
use iced::Application as IcedApplication; use iced::Application as IcedApplication;
use iced::{window, Command};
use iced_futures::event::listen_with; use iced_futures::event::listen_with;
#[cfg(not(feature = "wayland"))] #[cfg(not(feature = "wayland"))]
use iced_runtime::command::Action; use iced_runtime::command::Action;
@ -54,9 +54,9 @@ pub enum Message {
/// Toggles the condensed status of the nav bar. /// Toggles the condensed status of the nav bar.
ToggleNavBarCondensed, ToggleNavBarCondensed,
/// Notification of system theme changes. /// Notification of system theme changes.
SystemThemeChange(Theme), SystemThemeChange(Vec<&'static str>, Theme),
/// Notification of system theme mode changes. /// Notification of system theme mode changes.
SystemThemeModeChange(ThemeMode), SystemThemeModeChange(Vec<&'static str>, ThemeMode),
/// Updates the window maximized state /// Updates the window maximized state
WindowMaximized(window::Id, bool), WindowMaximized(window::Id, bool),
/// Updates the tracked window geometry. /// Updates the tracked window geometry.
@ -193,7 +193,10 @@ where
for e in update.errors { for e in update.errors {
tracing::error!("{e}"); 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), .map(super::Message::Cosmic),
self.app self.app
@ -203,7 +206,7 @@ where
for e in update.errors { for e in update.errors {
tracing::error!("{e}"); tracing::error!("{e}");
} }
Message::SystemThemeModeChange(update.config) Message::SystemThemeModeChange(update.keys, update.config)
}) })
.map(super::Message::Cosmic), .map(super::Message::Cosmic),
window_events.map(super::Message::Cosmic), window_events.map(super::Message::Cosmic),
@ -215,7 +218,7 @@ where
.unwrap_or_else(Subscription::none), .unwrap_or_else(Subscription::none),
#[cfg(feature = "xdg-portal")] #[cfg(feature = "xdg-portal")]
crate::theme::portal::desktop_settings() crate::theme::portal::desktop_settings()
.map(|e| Message::DesktopSettings(e)) .map(Message::DesktopSettings)
.map(super::Message::Cosmic), .map(super::Message::Cosmic),
]; ];
@ -387,7 +390,8 @@ impl<T: Application> Cosmic<T> {
}); });
} }
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. // Record the last-known system theme in event that the current theme is custom.
self.app.core_mut().system_theme = theme.clone(); self.app.core_mut().system_theme = theme.clone();
let portal_accent = self.app.core().portal_accent; let portal_accent = self.app.core().portal_accent;
@ -409,6 +413,8 @@ impl<T: Application> Cosmic<T> {
cosmic_theme.set_theme(new_theme.theme_type); cosmic_theme.set_theme(new_theme.theme_type);
} }
}); });
return cmd;
} }
Message::ScaleFactor(factor) => { Message::ScaleFactor(factor) => {
@ -419,7 +425,9 @@ impl<T: Application> Cosmic<T> {
self.app.on_app_exit(); self.app.on_app_exit();
return self.close(); 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 core = self.app.core_mut();
let prev_is_dark = core.system_is_dark(); let prev_is_dark = core.system_is_dark();
core.system_theme_mode = mode; core.system_theme_mode = mode;
@ -432,7 +440,9 @@ impl<T: Application> Cosmic<T> {
} else { } else {
crate::theme::system_light() 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 { new_theme = if let Some(a) = core.portal_accent {
let t_inner = new_theme.cosmic(); let t_inner = new_theme.cosmic();
if a.distance_squared(*t_inner.accent_color()) > 0.00001 { if a.distance_squared(*t_inner.accent_color()) > 0.00001 {
@ -454,6 +464,7 @@ impl<T: Application> Cosmic<T> {
} }
}); });
} }
return Command::batch(cmds);
} }
Message::Activate(_token) => { Message::Activate(_token) => {
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
@ -505,7 +516,7 @@ impl<T: Application> Cosmic<T> {
} }
#[cfg(feature = "xdg-portal")] #[cfg(feature = "xdg-portal")]
Message::DesktopSettings(crate::theme::portal::Desktop::Accent(c)) => { 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 c = Srgba::new(c.red() as f32, c.green() as f32, c.blue() as f32, 1.0);
let core = self.app.core_mut(); let core = self.app.core_mut();

View file

@ -511,6 +511,24 @@ where
iced::Command::none() 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<Message<Self::Message>> {
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<Message<Self::Message>> {
iced::Command::none()
}
/// Constructs the view for the main window. /// Constructs the view for the main window.
fn view(&self) -> Element<Self::Message>; fn view(&self) -> Element<Self::Message>;

View file

@ -112,8 +112,8 @@ pub fn system_dark() -> Theme {
} }
pub fn system_light() -> Theme { pub fn system_light() -> Theme {
let Ok(helper) = crate::cosmic_theme::Theme::dark_config() else { let Ok(helper) = crate::cosmic_theme::Theme::light_config() else {
return Theme::dark(); return Theme::light();
}; };
let t = crate::cosmic_theme::Theme::get_entry(&helper).unwrap_or_else(|(errors, theme)| { let t = crate::cosmic_theme::Theme::get_entry(&helper).unwrap_or_else(|(errors, theme)| {

View file

@ -1,7 +1,9 @@
use ashpd::desktop::settings::{ColorScheme, Contrast}; use ashpd::desktop::settings::{ColorScheme, Contrast};
use ashpd::desktop::Color; use ashpd::desktop::Color;
use iced::futures::{self, select, FutureExt, SinkExt, StreamExt}; use iced::futures::{self, select, FutureExt, SinkExt, StreamExt};
use iced::Subscription;
use iced_futures::subscription; use iced_futures::subscription;
use tracing::error;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Desktop { pub enum Desktop {
@ -15,12 +17,56 @@ pub fn desktop_settings() -> iced_futures::Subscription<Desktop> {
async move { async move {
let Ok(settings) = ashpd::desktop::settings::Settings::new().await else { let Ok(settings) = ashpd::desktop::settings::Settings::new().await else {
// wait forever // wait forever
error!("Failed to create the settings proxy");
futures::future::pending::<()>().await; futures::future::pending::<()>().await;
unreachable!() 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::<ashpd::zvariant::OwnedValue>("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 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::<Color>(
"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(); let mut contrast_stream = settings.receive_contrast_changed().await.ok();
if contrast_stream.is_none() {
error!("Failed to receive contrast changes");
}
loop { loop {
let next_color_scheme = async { let next_color_scheme = async {
@ -29,18 +75,12 @@ pub fn desktop_settings() -> iced_futures::Subscription<Desktop> {
} }
futures::future::pending().await futures::future::pending().await
}; };
let next_accent = async { // let next_accent = async {
if let Some(s) = accent_stream.as_mut() { // if let Some(s) = accent_stream.as_mut() {
// Item type is wrong in this version // return s.next().await.and_then(std::result::Result::ok);
// updating requires updating to zbus 4 // }
return if s.next().await.is_some() { // futures::future::pending().await
settings.accent_color().await.ok() // };
} else {
None
};
}
futures::future::pending().await
};
let next_contrast = async { let next_contrast = async {
if let Some(s) = contrast_stream.as_mut() { if let Some(s) = contrast_stream.as_mut() {
return s.next().await; return s.next().await;
@ -56,13 +96,14 @@ pub fn desktop_settings() -> iced_futures::Subscription<Desktop> {
color_scheme_stream = None; color_scheme_stream = None;
} }
}, },
a = next_accent.fuse() => { // a = next_accent.fuse() => {
if let Some(a) = a { // dbg!(a);
_ = tx.send(Desktop::Accent(a)).await; // if let Some(a) = a {
} else { // _ = tx.send(Desktop::Accent(a)).await;
accent_stream = None; // } else {
} // accent_stream = None;
}, // }
// },
c = next_contrast.fuse() => { c = next_contrast.fuse() => {
if let Some(c) = c { if let Some(c) = c {
_ = tx.send(Desktop::Contrast(c)).await; _ = tx.send(Desktop::Contrast(c)).await;