diff --git a/Cargo.lock b/Cargo.lock index 265619a..0bcd08f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -733,7 +733,7 @@ dependencies = [ [[package]] name = "cosmic-bg-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-bg?branch=master_jammy#749f3ea139519fffaa2641f80b6fba1379b3ad63" +source = "git+https://github.com/pop-os/cosmic-bg?branch=master_jammy#1e0d51cf6c95d913763cefc60714406236a8a0de" dependencies = [ "colorgrad", "cosmic-config", diff --git a/src/locker.rs b/src/locker.rs index a8e7a96..9e295f2 100644 --- a/src/locker.rs +++ b/src/locker.rs @@ -3,6 +3,7 @@ use cosmic::app::{message, Command, Core, Settings}; use cosmic::{ + cosmic_config::CosmicConfigEntry, executor, iced::{ self, alignment, @@ -45,34 +46,25 @@ pub fn main(current_user: pwd::Passwd) -> Result<(), Box> None }; - //TODO: remove statically configured background - let mut background = - widget::image::Handle::from_memory(include_bytes!("../res/background.png")); - - match cosmic_bg_config::Config::helper() { - Ok(helper) => match cosmic_bg_config::Config::load(&helper) { - Ok(config) => { - log::info!("config: {:#?}", config); - match config.default_background.source { - cosmic_bg_config::Source::Path(path) if path.is_file() => { - background = widget::image::Handle::from_path(path); - } - _ => {} - } + let mut wallpapers = Vec::new(); + match cosmic_bg_config::state::State::state() { + Ok(helper) => match cosmic_bg_config::state::State::get_entry(&helper) { + Ok(state) => { + wallpapers = state.wallpapers; } Err(err) => { - log::error!("failed to load cosmic-bg config: {:?}", err); + log::error!("failed to load cosmic-bg state: {:?}", err); } }, Err(err) => { - log::error!("failed to create cosmic-bg config helper: {:?}", err); + log::error!("failed to create cosmic-bg state helper: {:?}", err); } } let flags = Flags { current_user, icon_opt, - background, + wallpapers, }; let settings = Settings::default() @@ -205,7 +197,7 @@ impl pam_client::ConversationHandler for Conversation { pub struct Flags { current_user: pwd::Passwd, icon_opt: Option, - background: widget::image::Handle, + wallpapers: Vec<(String, cosmic_bg_config::Source)>, } /// Messages that are used specifically by our [`App`]. @@ -228,6 +220,7 @@ pub struct App { next_surface_id: SurfaceId, surface_ids: HashMap, active_surface_id_opt: Option, + surface_images: HashMap, value_tx_opt: Option>, prompt_opt: Option<(String, bool, Option)>, error_opt: Option, @@ -272,6 +265,7 @@ impl cosmic::Application for App { next_surface_id: SurfaceId(1), surface_ids: HashMap::new(), active_surface_id_opt: None, + surface_images: HashMap::new(), value_tx_opt: None, prompt_opt: None, error_opt: None, @@ -285,62 +279,110 @@ impl cosmic::Application for App { fn update(&mut self, message: Self::Message) -> Command { match message { Message::None => {} - Message::OutputEvent(output_event, output) => match output_event { - OutputEvent::Created(_output_info_opt) => { - log::info!("output {}: created", output.id()); + Message::OutputEvent(output_event, output) => { + match output_event { + OutputEvent::Created(output_info_opt) => { + log::info!("output {}: created", output.id()); - let surface_id = self.next_surface_id; - self.next_surface_id.0 += 1; + let surface_id = self.next_surface_id; + self.next_surface_id.0 += 1; - match self.surface_ids.insert(output.clone(), surface_id) { - Some(old_surface_id) => { - //TODO: remove old surface? - log::warn!( - "output {}: already had surface ID {}", - output.id(), - old_surface_id.0 - ); + match self.surface_ids.insert(output.clone(), surface_id) { + Some(old_surface_id) => { + //TODO: remove old surface? + log::warn!( + "output {}: already had surface ID {}", + output.id(), + old_surface_id.0 + ); + } + None => {} } - None => {} + + match output_info_opt { + Some(output_info) => { + match output_info.name { + Some(output_name) => { + for (wallpaper_output_name, wallpaper_source) in + self.flags.wallpapers.iter() + { + if wallpaper_output_name == &output_name { + match wallpaper_source { + cosmic_bg_config::Source::Path(path) => { + match fs::read(path) { + Ok(bytes) => { + let image = widget::image::Handle::from_memory(bytes); + self.surface_images + .insert(surface_id, image); + //TODO: what to do about duplicates? + break; + } + Err(err) => { + log::warn!("output {}: failed to load wallpaper {:?}: {:?}", output.id(), path, err); + } + } + } + cosmic_bg_config::Source::Color(color) => { + //TODO: support color sources + log::warn!( + "output {}: unsupported source {:?}", + output.id(), + color + ); + } + } + } + } + } + None => { + log::warn!("output {}: no output name", output.id()); + } + } + } + None => { + log::warn!("output {}: no output info", output.id()); + } + } + + return Command::batch([ + get_layer_surface(SctkLayerSurfaceSettings { + id: surface_id, + layer: Layer::Overlay, + keyboard_interactivity: KeyboardInteractivity::Exclusive, + pointer_interactivity: true, + anchor: Anchor::TOP | Anchor::BOTTOM | Anchor::LEFT | Anchor::RIGHT, + output: IcedOutput::Output(output), + namespace: "cosmic-locker".into(), + size: Some((None, None)), + margin: IcedMargin { + top: 0, + bottom: 0, + left: 0, + right: 0, + }, + exclusive_zone: -1, + size_limits: iced::Limits::NONE.min_width(1.0).min_height(1.0), + }), + widget::text_input::focus(text_input_id(surface_id)), + ]); } - - return Command::batch([ - get_layer_surface(SctkLayerSurfaceSettings { - id: surface_id, - layer: Layer::Overlay, - keyboard_interactivity: KeyboardInteractivity::Exclusive, - pointer_interactivity: true, - anchor: Anchor::TOP | Anchor::BOTTOM | Anchor::LEFT | Anchor::RIGHT, - output: IcedOutput::Output(output), - namespace: "cosmic-locker".into(), - size: Some((None, None)), - margin: IcedMargin { - top: 0, - bottom: 0, - left: 0, - right: 0, - }, - exclusive_zone: -1, - size_limits: iced::Limits::NONE.min_width(1.0).min_height(1.0), - }), - widget::text_input::focus(text_input_id(surface_id)), - ]); - } - OutputEvent::Removed => { - log::info!("output {}: removed", output.id()); - match self.surface_ids.remove(&output) { - Some(surface_id) => { - return destroy_layer_surface(surface_id); - } - None => { - log::warn!("output {}: no surface found", output.id()); + OutputEvent::Removed => { + log::info!("output {}: removed", output.id()); + match self.surface_ids.remove(&output) { + Some(surface_id) => { + self.surface_images.remove(&surface_id); + return destroy_layer_surface(surface_id); + } + None => { + log::warn!("output {}: no surface found", output.id()); + } } } + OutputEvent::InfoUpdate(output_info) => { + log::info!("output {}: info update {:#?}", output.id(), output_info); + } } - OutputEvent::InfoUpdate(output_info) => { - log::info!("output {}: info update {:#?}", output.id(), output_info); - } - }, + } Message::LayerEvent(layer_event, surface_id) => match layer_event { LayerEvent::Focused => { log::info!("focus surface {}", surface_id.0); @@ -392,6 +434,7 @@ impl cosmic::Application for App { let mut commands = Vec::new(); for (_output, surface_id) in self.surface_ids.drain() { + self.surface_images.remove(&surface_id); commands.push(destroy_layer_surface(surface_id)); } //TODO: cleaner method to exit? @@ -567,7 +610,11 @@ impl cosmic::Application for App { .align_y(alignment::Vertical::Top) .style(cosmic::theme::Container::Transparent), ) - .image(self.flags.background.clone()) + .image(match self.surface_images.get(&surface_id) { + Some(some) => some.clone(), + //TODO: default image + None => widget::image::Handle::from_pixels(1, 1, vec![0x00, 0x00, 0x00, 0xFF]), + }) .content_fit(iced::ContentFit::Cover) .into() }