From ab9f13b36f7fd5ba5378e7d6c4d55ebfe3639d46 Mon Sep 17 00:00:00 2001 From: Victoria Brekenfeld Date: Tue, 21 Apr 2026 18:16:43 +0200 Subject: [PATCH] iced: Handle blur internally --- src/backend/render/element.rs | 8 ++-- src/shell/element/mod.rs | 12 +++--- src/utils/iced/mod.rs | 69 ++++++++++++++++++++++++++++++++--- 3 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/backend/render/element.rs b/src/backend/render/element.rs index 103fa52f..51d282c1 100644 --- a/src/backend/render/element.rs +++ b/src/backend/render/element.rs @@ -1,6 +1,7 @@ use crate::{ backend::render::{GlMultiError, wayland::SurfaceRenderElement}, shell::{CosmicMappedRenderElement, WorkspaceRenderElement}, + utils::iced::IcedRenderElement, }; #[cfg(feature = "debug")] @@ -12,7 +13,6 @@ use smithay::{ Bind, Blit, ExportMem, ImportAll, ImportMem, Offscreen, Renderer, element::{ Element, Id, Kind, RenderElement, UnderlyingStorage, - memory::MemoryRenderBufferRenderElement, utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement}, }, gles::{GlesError, GlesRenderbuffer, GlesTexture, element::TextureShaderElement}, @@ -42,7 +42,7 @@ where Postprocess( CropRenderElement>>, ), - Zoom(MemoryRenderBufferRenderElement), + Zoom(IcedRenderElement), Damage(DamageElement), #[cfg(feature = "debug")] Egui(TextureRenderElement), @@ -344,13 +344,13 @@ where } } -impl From> for CosmicElement +impl From> for CosmicElement where R: AsGlowRenderer, R::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { - fn from(value: MemoryRenderBufferRenderElement) -> Self { + fn from(value: IcedRenderElement) -> Self { Self::Zoom(value) } } diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 11861591..f5691b29 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -1,7 +1,10 @@ use crate::{ backend::render::element::AsGlowRenderer, state::State, - utils::{iced::IcedElementInternal, prelude::*}, + utils::{ + iced::{IcedElementInternal, IcedRenderElement}, + prelude::*, + }, }; use calloop::LoopHandle; use cosmic_comp_config::AppearanceConfig; @@ -13,7 +16,6 @@ use smithay::{ renderer::{ element::{ Element, Kind, RenderElement, UnderlyingStorage, - memory::MemoryRenderBufferRenderElement, utils::{CropRenderElement, RelocateRenderElement, RescaleRenderElement}, }, gles::element::PixelShaderElement, @@ -1127,7 +1129,7 @@ where GrabbedWindow(RescaleRenderElement>), FocusIndicator(PixelShaderElement), Overlay(PixelShaderElement), - StackHoverIndicator(MemoryRenderBufferRenderElement), + StackHoverIndicator(IcedRenderElement), #[cfg(feature = "debug")] Egui(TextureRenderElement), } @@ -1581,13 +1583,13 @@ where } } -impl From> for CosmicMappedRenderElement +impl From> for CosmicMappedRenderElement where R: AsGlowRenderer, R::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { - fn from(elem: MemoryRenderBufferRenderElement) -> Self { + fn from(elem: IcedRenderElement) -> Self { CosmicMappedRenderElement::StackHoverIndicator(elem) } } diff --git a/src/utils/iced/mod.rs b/src/utils/iced/mod.rs index 9d57b46d..b03e1682 100644 --- a/src/utils/iced/mod.rs +++ b/src/utils/iced/mod.rs @@ -33,7 +33,7 @@ use smithay::{ allocator::Fourcc, input::{ButtonState, KeyState}, renderer::{ - ImportMem, Renderer, + ImportMem, element::{ Kind, memory::{MemoryRenderBuffer, MemoryRenderBufferRenderElement}, @@ -57,13 +57,20 @@ use smithay::{ }, output::Output, reexports::calloop::{self, LoopHandle, RegistrationToken, futures::Scheduler}, + render_elements, utils::{ Buffer as BufferCoords, IsAlive, Logical, Physical, Point, Rectangle, Scale, Serial, Size, Transform, }, }; -use crate::utils::iced::state::State; +use crate::{ + backend::render::{ + element::AsGlowRenderer, + wayland::blur_effect::{BlurElement, BlurState}, + }, + utils::iced::state::State, +}; static ID: LazyLock = LazyLock::new(|| Id::new("Program")); @@ -173,6 +180,7 @@ pub(crate) struct IcedElementInternal { outputs: HashSet, buffers: HashMap, (MemoryRenderBuffer, Option<(Vec, Color)>)>, pending_realloc: bool, + blur: BlurState, // state size: Size, @@ -225,6 +233,7 @@ impl Clone for IcedElementInternal

{ outputs: self.outputs.clone(), buffers: self.buffers.clone(), pending_realloc: self.pending_realloc, + blur: BlurState::default(), size: self.size, last_seat: self.last_seat.clone(), cursor_pos: self.cursor_pos, @@ -310,6 +319,7 @@ impl IcedElement

{ outputs: HashSet::new(), buffers: HashMap::new(), pending_realloc: false, + blur: BlurState::default(), size, cursor_pos: None, last_seat, @@ -342,7 +352,6 @@ impl IcedElement

{ let node = element .as_widget_mut() .layout( - // TODO Avoid creating a new tree here? &mut tree, &internal.renderer, &Limits::new(IcedSize::ZERO, IcedSize::INFINITE) @@ -386,6 +395,11 @@ impl IcedElement

{ self.0.lock().unwrap().update(true); } + pub fn with_theme(&self, f: impl FnOnce(&Theme) -> R) -> R { + let guard = self.0.lock().unwrap(); + f(&guard.theme) + } + pub fn set_theme(&self, theme: cosmic::Theme) { let mut guard = self.0.lock().unwrap(); guard.theme = theme.clone(); @@ -917,9 +931,11 @@ impl IcedElement

{ location: Point, mut scale: Scale, alpha: f32, - push: &mut dyn FnMut(MemoryRenderBufferRenderElement), + mut radii: [u8; 4], + push_above: &mut dyn FnMut(IcedRenderElement), + push_below: Option<&mut dyn FnMut(IcedRenderElement)>, ) where - R: Renderer + ImportMem, + R: AsGlowRenderer + ImportMem, R::TextureId: Send + Clone + 'static, { let mut internal = self.0.lock().unwrap(); @@ -1052,10 +1068,51 @@ impl IcedElement

{ Kind::Unspecified, ) { Ok(buffer) => { - push(buffer); + push_above(buffer.into()); } Err(err) => tracing::warn!("What? {:?}", err), } + + if internal_ref.theme.transparent { + for radius in radii.iter_mut() { + *radius = ((*radius as f64) * internal_ref.additional_scale).round() as u8; + } + + match BlurElement::from_state( + renderer, + &mut internal_ref.blur, + Rectangle::new( + location + .to_f64() + .to_logical(scale) + .upscale(internal_ref.additional_scale), + internal_ref + .size + .to_f64() + .upscale(internal_ref.additional_scale) + .to_i32_round(), + ), + scale.x, + radii, + (internal_ref.theme.cosmic().frosted as u8 + 1) as usize, + ) { + Ok(Some(elem)) => { + if let Some(push_below) = push_below { + push_below(elem.into()) + } else { + push_above(elem.into()) + } + } + Ok(None) => {} + Err(err) => tracing::warn!("Blur elem error: {:?}", err), + } + } } } } + +render_elements! { + pub IcedRenderElement where R: ImportMem + AsGlowRenderer; + UI=MemoryRenderBufferRenderElement, + Blur=BlurElement, +}