diff --git a/src/main.rs b/src/main.rs index da40566..4b33fd3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,21 +50,21 @@ use crate::{ wayland::BackgroundLayer, }; -pub struct State { - pub connection: Rc, - pub compositor_state: CompositorState, - pub registry_state: RegistryState, - pub output_state: OutputState, - pub shm: Shm, - pub layer_shell: LayerShell, - pub viewporter: WpViewporter, - pub wallpaper_dir: PathBuf, - pub shm_format: Option, - pub background_layers: Vec, - pub compositor_connection_task: ConnectionTask, - pub color_transform: ColorTransform, - pub dmabuf_state: DmabufState, - pub gpu: Option, +struct State { + connection: Rc, + compositor_state: CompositorState, + registry_state: RegistryState, + output_state: OutputState, + shm: Shm, + layer_shell: LayerShell, + viewporter: WpViewporter, + wallpaper_dir: PathBuf, + shm_format: Option, + background_layers: Vec, + compositor_connection_task: ConnectionTask, + color_transform: ColorTransform, + dmabuf_state: DmabufState, + gpu: Option, } impl State { diff --git a/src/wayland.rs b/src/wayland.rs index 0414de6..2bc00e8 100644 --- a/src/wayland.rs +++ b/src/wayland.rs @@ -59,6 +59,145 @@ use crate::{ const MAX_FDS_OUT: usize = 28; +pub struct BackgroundLayer { + pub output_name: String, + width: i32, + height: i32, + layer: LayerSurface, + configured: bool, + workspace_backgrounds: Vec, + current_wallpaper: Option>>, + queued_wallpaper: Option>>, + transform: Transform, + viewport: Option, + dmabuf_feedback: Option, +} + +impl BackgroundLayer { + pub fn draw_workspace_bg(&mut self, workspace_name: &str) { + if !self.configured { + error!("Cannot draw wallpaper image on the not yet configured \ + layer for output: {}", self.output_name); + return + } + + let Some(workspace_bg) = self.workspace_backgrounds.iter() + .find(|workspace_bg| workspace_bg.workspace_name == workspace_name) + .or_else(|| self.workspace_backgrounds.iter() + .find(|workspace_bg| workspace_bg.workspace_name == "_default") + ) + else { + error!( + "There is no wallpaper image on output {} for workspace {}, \ + only for: {}", + self.output_name, + workspace_name, + self.workspace_backgrounds.iter() + .map(|workspace_bg| workspace_bg.workspace_name.as_str()) + .collect::>().join(", ") + ); + return + }; + let wallpaper = &workspace_bg.wallpaper; + + if let Some(current) = &self.current_wallpaper { + if Rc::ptr_eq(current, wallpaper) { + debug!("Skipping draw on output {} for workspace {} \ + because its wallpaper is already set", + self.output_name, workspace_name); + return + } + } + + let mut wallpaper_borrow = wallpaper.borrow_mut(); + let Some(wl_buffer) = wallpaper_borrow.wl_buffer.as_ref() else { + debug!("Wallpaper for output {} workspace {} is not ready yet", + self.output_name, workspace_name); + self.queued_wallpaper = Some(Rc::downgrade(wallpaper)); + return + }; + + // Attach and commit to new workspace background + self.layer.attach(Some(wl_buffer), 0, 0); + wallpaper_borrow.active_count += 1; + + // Damage the entire surface + self.layer.wl_surface().damage_buffer(0, 0, self.width, self.height); + + self.layer.commit(); + + self.current_wallpaper = Some(Rc::clone(wallpaper)); + self.queued_wallpaper = None; + + debug!("Setting wallpaper on output {} for workspace: {}", + self.output_name, workspace_name); + } +} + +struct WorkspaceBackground { + workspace_name: String, + wallpaper: Rc>, +} + +struct Wallpaper { + wl_buffer: Option, + active_count: usize, + memory: Memory, + canon_path: PathBuf, + canon_modified: u128, +} + +impl Drop for Wallpaper { + fn drop(&mut self) { + if let Some(wl_buffer) = &self.wl_buffer { + if self.active_count != 0 { + warn!("Destroying a {} times active wl_buffer of \ + wallpaper {:?}", self.active_count, self.canon_path); + } + wl_buffer.destroy(); + } + } +} + +enum Memory { + WlShm { pool: RawPool }, + Dmabuf { gpu_memory: GpuMemory, params: Option }, +} + +impl Memory { + fn gpu_uploader_eq(&self, gpu_uploader: Option<&GpuUploader>) -> bool { + if let Some(gpu_uploader) = gpu_uploader { + match self { + Memory::WlShm { .. } => false, + Memory::Dmabuf { gpu_memory, .. } => { + gpu_memory.gpu_uploader_eq(gpu_uploader) + }, + } + } else { + match self { + Memory::WlShm { .. } => true, + Memory::Dmabuf { .. } => false, + } + } + } + + fn dmabuf_params_destroy_eq( + &mut self, + other_params: &ZwpLinuxBufferParamsV1, + ) -> bool { + if let Memory::Dmabuf { params: params_option, .. } = self { + if let Some(params) = params_option { + if params == other_params { + params.destroy(); + *params_option = None; + return true + } + } + } + false + } +} + impl CompositorHandler for State { fn scale_factor_changed( &mut self, @@ -669,145 +808,6 @@ impl Dispatch for State { } } -pub struct BackgroundLayer { - pub output_name: String, - pub width: i32, - pub height: i32, - pub layer: LayerSurface, - pub configured: bool, - pub workspace_backgrounds: Vec, - pub current_wallpaper: Option>>, - pub queued_wallpaper: Option>>, - pub transform: Transform, - pub viewport: Option, - pub dmabuf_feedback: Option, -} - -impl BackgroundLayer { - pub fn draw_workspace_bg(&mut self, workspace_name: &str) { - if !self.configured { - error!("Cannot draw wallpaper image on the not yet configured \ - layer for output: {}", self.output_name); - return - } - - let Some(workspace_bg) = self.workspace_backgrounds.iter() - .find(|workspace_bg| workspace_bg.workspace_name == workspace_name) - .or_else(|| self.workspace_backgrounds.iter() - .find(|workspace_bg| workspace_bg.workspace_name == "_default") - ) - else { - error!( - "There is no wallpaper image on output {} for workspace {}, \ - only for: {}", - self.output_name, - workspace_name, - self.workspace_backgrounds.iter() - .map(|workspace_bg| workspace_bg.workspace_name.as_str()) - .collect::>().join(", ") - ); - return - }; - let wallpaper = &workspace_bg.wallpaper; - - if let Some(current) = &self.current_wallpaper { - if Rc::ptr_eq(current, wallpaper) { - debug!("Skipping draw on output {} for workspace {} \ - because its wallpaper is already set", - self.output_name, workspace_name); - return - } - } - - let mut wallpaper_borrow = wallpaper.borrow_mut(); - let Some(wl_buffer) = wallpaper_borrow.wl_buffer.as_ref() else { - debug!("Wallpaper for output {} workspace {} is not ready yet", - self.output_name, workspace_name); - self.queued_wallpaper = Some(Rc::downgrade(wallpaper)); - return - }; - - // Attach and commit to new workspace background - self.layer.attach(Some(wl_buffer), 0, 0); - wallpaper_borrow.active_count += 1; - - // Damage the entire surface - self.layer.wl_surface().damage_buffer(0, 0, self.width, self.height); - - self.layer.commit(); - - self.current_wallpaper = Some(Rc::clone(wallpaper)); - self.queued_wallpaper = None; - - debug!("Setting wallpaper on output {} for workspace: {}", - self.output_name, workspace_name); - } -} - -pub struct WorkspaceBackground { - pub workspace_name: String, - pub wallpaper: Rc>, -} - -pub struct Wallpaper { - pub wl_buffer: Option, - pub active_count: usize, - pub memory: Memory, - pub canon_path: PathBuf, - pub canon_modified: u128, -} - -impl Drop for Wallpaper { - fn drop(&mut self) { - if let Some(wl_buffer) = &self.wl_buffer { - if self.active_count != 0 { - warn!("Destroying a {} times active wl_buffer of \ - wallpaper {:?}", self.active_count, self.canon_path); - } - wl_buffer.destroy(); - } - } -} - -pub enum Memory { - WlShm { pool: RawPool }, - Dmabuf { gpu_memory: GpuMemory, params: Option }, -} - -impl Memory { - fn gpu_uploader_eq(&self, gpu_uploader: Option<&GpuUploader>) -> bool { - if let Some(gpu_uploader) = gpu_uploader { - match self { - Memory::WlShm { .. } => false, - Memory::Dmabuf { gpu_memory, .. } => { - gpu_memory.gpu_uploader_eq(gpu_uploader) - }, - } - } else { - match self { - Memory::WlShm { .. } => true, - Memory::Dmabuf { .. } => false, - } - } - } - - fn dmabuf_params_destroy_eq( - &mut self, - other_params: &ZwpLinuxBufferParamsV1, - ) -> bool { - if let Memory::Dmabuf { params: params_option, .. } = self { - if let Some(params) = params_option { - if params == other_params { - params.destroy(); - *params_option = None; - return true - } - } - } - false - } -} - fn layer_surface_name(output_name: &str) -> Option { Some([env!("CARGO_PKG_NAME"), "_wallpaper_", output_name].concat()) }