From d759e1d7c2e8a356a5a6ff08a83cc7976e160b3d Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 30 Apr 2024 12:49:08 -0700 Subject: [PATCH] Use `cosmic_bg_config` to get background Scaling doesn't match `cosmic-bg`? --- Cargo.lock | 25 ++++++++++++++ Cargo.toml | 1 + src/main.rs | 33 +++++++++++++++++- src/view/mod.rs | 74 ++++++++++++++++++++++++++++++++++++++++- src/widgets/image_bg.rs | 41 ++++++----------------- 5 files changed, 141 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba0fee1..6e046e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -867,6 +867,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "colorgrad" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5f405d474b9d05e0a093d3120e77e9bf26461b57a84b40aa2a221ac5617fb6" +dependencies = [ + "csscolorparser", +] + [[package]] name = "com" version = "0.6.0" @@ -967,6 +976,20 @@ dependencies = [ "libc", ] +[[package]] +name = "cosmic-bg-config" +version = "0.1.0" +source = "git+https://github.com/pop-os/cosmic-bg#742a3444cd7f599184d6f553a2a7bc91e19084a6" +dependencies = [ + "colorgrad", + "cosmic-config", + "derive_setters", + "image", + "ron", + "serde", + "tracing", +] + [[package]] name = "cosmic-client-toolkit" version = "0.1.0" @@ -994,6 +1017,7 @@ version = "0.1.0" source = "git+https://github.com/pop-os/libcosmic#a0ed887b7d73ebb69c2aff7bb230c43d9754c742" dependencies = [ "atomicwrites", + "calloop", "cosmic-config-derive", "dirs 5.0.1", "iced_futures", @@ -1073,6 +1097,7 @@ dependencies = [ "calloop", "calloop-wayland-source", "clap", + "cosmic-bg-config", "cosmic-comp-config", "cosmic-config", "delegate", diff --git a/Cargo.toml b/Cargo.toml index 099db12..87c0c62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" anyhow = "1.0.75" calloop = { version = "0.13.0", features = ["executor"] } clap = { version = "4", features = ["derive"] } +cosmic-bg-config = { git = "https://github.com/pop-os/cosmic-bg" } cosmic-comp-config = { git = "https://github.com/pop-os/cosmic-comp" } env_logger = "0.11.0" futures-channel = "0.3.25" diff --git a/src/main.rs b/src/main.rs index f6f71cd..b5ce939 100644 --- a/src/main.rs +++ b/src/main.rs @@ -176,10 +176,27 @@ enum DragSurface { }, } -#[derive(Default)] struct Conf { workspace_config: cosmic_comp_config::workspace::WorkspaceConfig, config: CosmicWorkspacesConfig, + bg_config: Option, +} + +impl Default for Conf { + fn default() -> Self { + let bg_config = cosmic::cosmic_config::Config::new_state( + cosmic_bg_config::NAME, + cosmic_bg_config::state::State::version(), + ); + if let Err(err) = &bg_config { + log::error!("failed to load bg config: {}", err); + } + Self { + workspace_config: cosmic_comp_config::workspace::WorkspaceConfig::default(), + config: CosmicWorkspacesConfig::default(), + bg_config: bg_config.ok(), + } + } } #[derive(Default)] @@ -195,6 +212,7 @@ struct App { conf: Conf, core: cosmic::app::Core, drop_target: Option<(ZcosmicWorkspaceHandleV1, wl_output::WlOutput)>, + bg_state: Option, } impl App { @@ -275,6 +293,19 @@ impl App { .collect::>(), ); self.update_capture_filter(); + + if let Some(config) = &self.conf.bg_config { + match cosmic_bg_config::state::State::get_entry(&config) { + Ok(state) => { + self.bg_state = Some(state); + } + Err((err, state)) => { + log::error!("failed to load bg config: {:?}", err); + self.bg_state = Some(state); + } + } + } + cmd } else { Command::none() diff --git a/src/view/mod.rs b/src/view/mod.rs index 3a4b322..6dcef1e 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -14,6 +14,7 @@ use cosmic::{ iced_sctk::subsurface_widget::Subsurface, widget, }; +use cosmic_bg_config::Source; use cosmic_comp_config::workspace::WorkspaceLayout; use crate::{ @@ -73,7 +74,13 @@ pub(crate) fn layer_surface<'a>( .width(iced::Length::Fill), ), }; - crate::widgets::image_bg(container).into() + let output_name = app + .outputs + .iter() + .find(|x| x.handle == surface.output) + .map_or("", |o| &o.name); + let bg = bg_element(app.bg_state.as_ref(), output_name); + crate::widgets::image_bg(container, bg).into() } fn close_button(on_press: Msg) -> cosmic::Element<'static, Msg> { @@ -322,6 +329,71 @@ fn toplevel_previews<'a>( .into() } +fn bg_element<'a>( + bg_state: Option<&'a cosmic_bg_config::state::State>, + output_name: &'a str, +) -> cosmic::Element<'a, Msg> { + let bg_source = bg_state + .into_iter() + .flat_map(|x| x.wallpapers.iter()) + .find(|(n, _)| n == output_name) + .map(|(_, v)| v.clone()); + match bg_source { + Some(Source::Path(path)) => widget::image::Image::::new( + widget::image::Handle::from_path(path), + ) + .content_fit(iced::ContentFit::Cover) + .width(iced::Length::Fill) + .height(iced::Length::Fill) + .into(), + Some(Source::Color(color)) => { + widget::layer_container(widget::horizontal_space(iced::Length::Fill)) + .width(iced::Length::Fill) + .height(iced::Length::Fill) + .style(cosmic::theme::Container::Custom(Box::new(move |_| { + let color = color.clone(); + cosmic::iced_style::container::Appearance { + background: Some(match color { + cosmic_bg_config::Color::Single(c) => iced::Background::Color( + cosmic::iced::Color::new(c[0], c[1], c[2], 1.0), + ), + cosmic_bg_config::Color::Gradient(cosmic_bg_config::Gradient { + colors, + radius, + }) => { + let stop_increment = 1.0 / (colors.len() - 1) as f32; + let mut stop = 0.0; + + let mut linear = iced::gradient::Linear::new(iced::Degrees(radius)); + + for &[r, g, b] in colors.iter() { + linear = linear + .add_stop(stop, cosmic::iced::Color::from_rgb(r, g, b)); + stop += stop_increment; + } + + iced::Background::Gradient(cosmic::iced_core::Gradient::Linear( + linear, + )) + } + }), + ..Default::default() + } + }))) + .into() + } + None => { + widget::image::Image::::new(widget::image::Handle::from_path( + "/usr/share/backgrounds/pop/kate-hazen-COSMIC-desktop-wallpaper.png", + )) + .content_fit(iced::ContentFit::Cover) + .width(iced::Length::Fill) + .height(iced::Length::Fill) + .into() + } + } +} + fn capture_image(image: Option<&CaptureImage>) -> cosmic::Element<'_, Msg> { if let Some(image) = image { #[cfg(feature = "no-subsurfaces")] diff --git a/src/widgets/image_bg.rs b/src/widgets/image_bg.rs index 9804cf5..2943ae5 100644 --- a/src/widgets/image_bg.rs +++ b/src/widgets/image_bg.rs @@ -9,23 +9,27 @@ use cosmic::{ Clipboard, Layout, Shell, Widget, }, event::{self, Event}, - widget::image::{FilterMethod, Handle}, - ContentFit, Length, Rectangle, Size, Vector, + Length, Rectangle, Size, }, iced_core::Renderer, }; use std::marker::PhantomData; -pub fn image_bg<'a, Msg, T: Into>>(content: T) -> ImageBg<'a, Msg> { +pub fn image_bg<'a, Msg, T1: Into>, T2: Into>>( + content: T1, + bg: T2, +) -> ImageBg<'a, Msg> { ImageBg { content: content.into(), + bg: bg.into(), _msg: PhantomData, } } pub struct ImageBg<'a, Msg> { content: cosmic::Element<'a, Msg>, + bg: cosmic::Element<'a, Msg>, _msg: PhantomData, } @@ -92,36 +96,11 @@ impl<'a, Msg> Widget for ImageBg<'a, Msg> cursor: mouse::Cursor, viewport: &Rectangle, ) { - use cosmic::iced_core::image::Renderer; - - // TODO desktop background? - let handle = - Handle::from_path("/usr/share/backgrounds/pop/kate-hazen-COSMIC-desktop-wallpaper.png"); - - let Size { width, height } = renderer.dimensions(&handle); - let image_size = Size::new(width as f32, height as f32); + self.bg + .as_widget() + .draw(state, renderer, theme, style, layout, cursor, viewport); let bounds = layout.bounds(); - let adjusted_fit = ContentFit::Cover.fit(image_size, bounds.size()); - - let offset = Vector::new( - (bounds.width - adjusted_fit.width).max(0.0) / 2.0, - (bounds.height - adjusted_fit.height).max(0.0) / 2.0, - ); - - let drawing_bounds = Rectangle { - width: adjusted_fit.width, - height: adjusted_fit.height, - ..bounds - }; - - renderer.draw( - handle.clone(), - FilterMethod::default(), - drawing_bounds + offset, - [0.0, 0.0, 0.0, 0.0], - ); - renderer.with_layer(bounds, |renderer| { self.content .as_widget()