diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-03-01 09:45:57 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-03-10 07:59:14 +0300 |
| commit | b351f6ff220560d96a260d8dd3ad794000923481 (patch) | |
| tree | f2bd1a777fe9f932fea2cfeba3677cbb39b634eb /src/layout | |
| parent | 12817a682d666e81e30b5a723d6419baf74cdb1c (diff) | |
| download | niri-b351f6ff220560d96a260d8dd3ad794000923481.tar.gz niri-b351f6ff220560d96a260d8dd3ad794000923481.tar.bz2 niri-b351f6ff220560d96a260d8dd3ad794000923481.zip | |
Keep track of RenderElementStates in offscreens
This both avoids sending frame callbacks to surfaces invisible on the offscreen
(fixing Firefox with subsurface compositing in the process), and fixes
searching for split popups during the resize animation.
Diffstat (limited to 'src/layout')
| -rw-r--r-- | src/layout/mod.rs | 4 | ||||
| -rw-r--r-- | src/layout/opening_window.rs | 20 | ||||
| -rw-r--r-- | src/layout/tests.rs | 2 | ||||
| -rw-r--r-- | src/layout/tile.rs | 27 |
4 files changed, 29 insertions, 24 deletions
diff --git a/src/layout/mod.rs b/src/layout/mod.rs index ac83a0cf..dc7daa65 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -45,7 +45,6 @@ use niri_config::{ use niri_ipc::{ColumnDisplay, PositionChange, SizeChange}; use scrolling::{Column, ColumnWidth, InsertHint, InsertPosition}; use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement; -use smithay::backend::renderer::element::Id; use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture}; use smithay::output::{self, Output}; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; @@ -59,6 +58,7 @@ use self::workspace::{OutputId, Workspace}; use crate::animation::Clock; use crate::layout::scrolling::ScrollDirection; use crate::niri_render_elements; +use crate::render_helpers::offscreen::OffscreenData; use crate::render_helpers::renderer::NiriRenderer; use crate::render_helpers::snapshot::RenderSnapshot; use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement}; @@ -194,7 +194,7 @@ pub trait LayoutElement { fn set_preferred_scale_transform(&self, scale: output::Scale, transform: Transform); fn output_enter(&self, output: &Output); fn output_leave(&self, output: &Output); - fn set_offscreen_element_id(&self, id: Option<Id>); + fn set_offscreen_data(&self, data: Option<OffscreenData>); fn set_activated(&mut self, active: bool); fn set_active_in_column(&mut self, active: bool); fn set_floating(&mut self, floating: bool); diff --git a/src/layout/opening_window.rs b/src/layout/opening_window.rs index 8a1db409..19727551 100644 --- a/src/layout/opening_window.rs +++ b/src/layout/opening_window.rs @@ -5,14 +5,14 @@ use glam::{Mat3, Vec2}; use smithay::backend::renderer::element::utils::{ Relocate, RelocateRenderElement, RescaleRenderElement, }; -use smithay::backend::renderer::element::{Kind, RenderElement}; +use smithay::backend::renderer::element::{Element as _, Kind, RenderElement}; use smithay::backend::renderer::gles::{GlesRenderer, Uniform}; use smithay::backend::renderer::Texture; use smithay::utils::{Logical, Point, Rectangle, Scale, Size}; use crate::animation::Animation; use crate::niri_render_elements; -use crate::render_helpers::offscreen::{OffscreenBuffer, OffscreenRenderElement}; +use crate::render_helpers::offscreen::{OffscreenBuffer, OffscreenData, OffscreenRenderElement}; use crate::render_helpers::shader_element::ShaderRenderElement; use crate::render_helpers::shaders::{mat3_uniform, ProgramType, Shaders}; @@ -55,11 +55,11 @@ impl OpenAnimation { location: Point<f64, Logical>, scale: Scale<f64>, alpha: f32, - ) -> anyhow::Result<OpeningWindowRenderElement> { + ) -> anyhow::Result<(OpeningWindowRenderElement, OffscreenData)> { let progress = self.anim.value(); let clamped_progress = self.anim.clamped_value().clamp(0., 1.); - let (elem, _sync_point) = self + let (elem, _sync_point, mut data) = self .buffer .render(renderer, scale, elements) .context("error rendering to offscreen buffer")?; @@ -98,7 +98,7 @@ impl OpenAnimation { let geo_to_tex = Mat3::from_translation(-tex_loc / tex_size) * Mat3::from_scale(geo_size / tex_size); - return Ok(ShaderRenderElement::new( + let elem = ShaderRenderElement::new( ProgramType::Open, area.size, None, @@ -115,8 +115,12 @@ impl OpenAnimation { HashMap::from([(String::from("niri_tex"), texture.clone())]), Kind::Unspecified, ) - .with_location(area.loc) - .into()); + .with_location(area.loc); + + // We're drawing the shader, not the offscreen itself. + data.id = elem.id().clone(); + + return Ok((elem.into(), data)); } let elem = elem.with_alpha(clamped_progress as f32 * alpha); @@ -134,6 +138,6 @@ impl OpenAnimation { Relocate::Relative, ); - Ok(elem.into()) + Ok((elem.into(), data)) } } diff --git a/src/layout/tests.rs b/src/layout/tests.rs index 9d3e8634..160e4e97 100644 --- a/src/layout/tests.rs +++ b/src/layout/tests.rs @@ -162,7 +162,7 @@ impl LayoutElement for TestWindow { fn output_leave(&self, _output: &Output) {} - fn set_offscreen_element_id(&self, _id: Option<Id>) {} + fn set_offscreen_data(&self, _data: Option<OffscreenData>) {} fn set_activated(&mut self, active: bool) { self.0.pending_activated.set(active); diff --git a/src/layout/tile.rs b/src/layout/tile.rs index a93e4a6f..89f0e6ab 100644 --- a/src/layout/tile.rs +++ b/src/layout/tile.rs @@ -888,7 +888,7 @@ impl<W: LayoutElement> Tile<W> { clip_to_geometry }; - if let Some((elem_current, _sync_point)) = current { + if let Some((elem_current, _sync_point, mut data)) = current { let texture_current = elem_current.texture().clone(); // The offset and size are computed in physical pixels and converted to // logical with the same `scale`, so converting them back with rounding @@ -908,10 +908,13 @@ impl<W: LayoutElement> Tile<W> { clip_to_geometry, win_alpha, ); - // FIXME: with split popups, this will use the resize element ID for - // popups, but we want the real IDs. - self.window - .set_offscreen_element_id(Some(elem.id().clone())); + + // We're drawing the resize shader, not the offscreen directly. + data.id = elem.id().clone(); + + // This is not a problem for split popups as the code will look for them by + // original id when it doesn't find them on the offscreen. + self.window.set_offscreen_data(Some(data)); resize_shader = Some(elem.into()); } } @@ -928,7 +931,6 @@ impl<W: LayoutElement> Tile<W> { ) .into(), ); - self.window.set_offscreen_element_id(None); } } @@ -1058,6 +1060,8 @@ impl<W: LayoutElement> Tile<W> { let mut alpha_anim_elem = None; let mut window_elems = None; + self.window().set_offscreen_data(None); + if let Some(open) = &self.open_animation { let renderer = renderer.as_gles_renderer(); let elements = @@ -1071,9 +1075,8 @@ impl<W: LayoutElement> Tile<W> { scale, tile_alpha, ) { - Ok(elem) => { - self.window() - .set_offscreen_element_id(Some(elem.id().clone())); + Ok((elem, data)) => { + self.window().set_offscreen_data(Some(data)); open_anim_elem = Some(elem.into()); } Err(err) => { @@ -1086,12 +1089,11 @@ impl<W: LayoutElement> Tile<W> { self.render_inner(renderer, Point::from((0., 0.)), scale, focus_ring, target); let elements = elements.collect::<Vec<TileRenderElement<_>>>(); match alpha.offscreen.render(renderer, scale, &elements) { - Ok((elem, _sync)) => { + Ok((elem, _sync, data)) => { let offset = elem.offset(); let elem = elem.with_alpha(tile_alpha).with_offset(location + offset); - self.window() - .set_offscreen_element_id(Some(elem.id().clone())); + self.window().set_offscreen_data(Some(data)); alpha_anim_elem = Some(elem.into()); } Err(err) => { @@ -1101,7 +1103,6 @@ impl<W: LayoutElement> Tile<W> { } if open_anim_elem.is_none() && alpha_anim_elem.is_none() { - self.window().set_offscreen_element_id(None); window_elems = Some(self.render_inner(renderer, location, scale, focus_ring, target)); } |
