iced: Handle blur internally

This commit is contained in:
Victoria Brekenfeld 2026-04-21 18:16:43 +02:00 committed by Victoria Brekenfeld
parent 5ee2fa911a
commit ab9f13b36f
3 changed files with 74 additions and 15 deletions

View file

@ -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<RelocateRenderElement<RescaleRenderElement<TextureShaderElement>>>,
),
Zoom(MemoryRenderBufferRenderElement<R>),
Zoom(IcedRenderElement<R>),
Damage(DamageElement),
#[cfg(feature = "debug")]
Egui(TextureRenderElement<GlesTexture>),
@ -344,13 +344,13 @@ where
}
}
impl<R> From<MemoryRenderBufferRenderElement<R>> for CosmicElement<R>
impl<R> From<IcedRenderElement<R>> for CosmicElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(value: MemoryRenderBufferRenderElement<R>) -> Self {
fn from(value: IcedRenderElement<R>) -> Self {
Self::Zoom(value)
}
}

View file

@ -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<self::window::CosmicWindowRenderElement<R>>),
FocusIndicator(PixelShaderElement),
Overlay(PixelShaderElement),
StackHoverIndicator(MemoryRenderBufferRenderElement<R>),
StackHoverIndicator(IcedRenderElement<R>),
#[cfg(feature = "debug")]
Egui(TextureRenderElement<GlesTexture>),
}
@ -1581,13 +1583,13 @@ where
}
}
impl<R> From<MemoryRenderBufferRenderElement<R>> for CosmicMappedRenderElement<R>
impl<R> From<IcedRenderElement<R>> for CosmicMappedRenderElement<R>
where
R: AsGlowRenderer,
R::TextureId: 'static,
CosmicMappedRenderElement<R>: RenderElement<R>,
{
fn from(elem: MemoryRenderBufferRenderElement<R>) -> Self {
fn from(elem: IcedRenderElement<R>) -> Self {
CosmicMappedRenderElement::StackHoverIndicator(elem)
}
}

View file

@ -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<Id> = LazyLock::new(|| Id::new("Program"));
@ -173,6 +180,7 @@ pub(crate) struct IcedElementInternal<P: Program + Send + 'static> {
outputs: HashSet<Output>,
buffers: HashMap<OrderedFloat<f64>, (MemoryRenderBuffer, Option<(Vec<Layer>, Color)>)>,
pending_realloc: bool,
blur: BlurState,
// state
size: Size<i32, Logical>,
@ -225,6 +233,7 @@ impl<P: Program + Send + Clone + 'static> Clone for IcedElementInternal<P> {
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<P: Program + Send + 'static> IcedElement<P> {
outputs: HashSet::new(),
buffers: HashMap::new(),
pending_realloc: false,
blur: BlurState::default(),
size,
cursor_pos: None,
last_seat,
@ -342,7 +352,6 @@ impl<P: Program + Send + 'static> IcedElement<P> {
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<P: Program + Send + 'static> IcedElement<P> {
self.0.lock().unwrap().update(true);
}
pub fn with_theme<R: 'static>(&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<P: Program + Send + 'static> IcedElement<P> {
location: Point<i32, Physical>,
mut scale: Scale<f64>,
alpha: f32,
push: &mut dyn FnMut(MemoryRenderBufferRenderElement<R>),
mut radii: [u8; 4],
push_above: &mut dyn FnMut(IcedRenderElement<R>),
push_below: Option<&mut dyn FnMut(IcedRenderElement<R>)>,
) where
R: Renderer + ImportMem,
R: AsGlowRenderer + ImportMem,
R::TextureId: Send + Clone + 'static,
{
let mut internal = self.0.lock().unwrap();
@ -1052,10 +1068,51 @@ impl<P: Program + Send + 'static> IcedElement<P> {
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<R> where R: ImportMem + AsGlowRenderer;
UI=MemoryRenderBufferRenderElement<R>,
Blur=BlurElement,
}