wip: support desktop portal color-scheme, and accent variables
This commit is contained in:
parent
c390b2614d
commit
06b46f455b
6 changed files with 107 additions and 34 deletions
|
|
@ -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"]
|
||||||
|
|
|
||||||
|
|
@ -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)?;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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>;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)| {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue