From b351f6ff220560d96a260d8dd3ad794000923481 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Sat, 1 Mar 2025 09:45:57 +0300 Subject: 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. --- src/window/mapped.rs | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'src/window') diff --git a/src/window/mapped.rs b/src/window/mapped.rs index 8263c078..6b539e46 100644 --- a/src/window/mapped.rs +++ b/src/window/mapped.rs @@ -3,7 +3,7 @@ use std::time::Duration; use niri_config::{Color, CornerRadius, GradientInterpolation, WindowRule}; use smithay::backend::renderer::element::surface::render_elements_from_surface_tree; -use smithay::backend::renderer::element::{Id, Kind}; +use smithay::backend::renderer::element::Kind; use smithay::backend::renderer::gles::GlesRenderer; use smithay::desktop::space::SpaceElement as _; use smithay::desktop::{PopupManager, Window}; @@ -26,6 +26,7 @@ use crate::layout::{ }; use crate::niri_render_elements; use crate::render_helpers::border::BorderRenderElement; +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}; @@ -70,10 +71,10 @@ pub struct Mapped { /// resizes immediately, without waiting for a 1 second throttled callback. needs_frame_callback: bool, - /// Id of the offscreen element rendered in place of this window. + /// Data of the offscreen element rendered in place of this window. /// /// If `None`, then the window is not offscreened. - offscreen_element_id: RefCell>, + offscreen_data: RefCell>, /// Whether this window has the keyboard focus. is_focused: bool, @@ -192,7 +193,7 @@ impl Mapped { need_to_recompute_rules: false, needs_configure: false, needs_frame_callback: false, - offscreen_element_id: RefCell::new(None), + offscreen_data: RefCell::new(None), is_focused: false, is_active_in_column: true, is_floating: false, @@ -257,8 +258,8 @@ impl Mapped { self.credentials.as_ref() } - pub fn offscreen_element_id(&self) -> Ref> { - self.offscreen_element_id.borrow() + pub fn offscreen_data(&self) -> Ref> { + self.offscreen_data.borrow() } pub fn is_focused(&self) -> bool { @@ -751,8 +752,24 @@ impl LayoutElement for Mapped { self.window.output_leave(output) } - fn set_offscreen_element_id(&self, id: Option) { - self.offscreen_element_id.replace(id); + fn set_offscreen_data(&self, data: Option) { + let Some(data) = data else { + self.offscreen_data.replace(None); + return; + }; + + let mut offscreen_data = self.offscreen_data.borrow_mut(); + match &mut *offscreen_data { + None => { + *offscreen_data = Some(data); + } + Some(existing) => { + // Replace the id, amend existing element states. This is necessary to handle + // multiple layers of offscreen (e.g. resize animation + alpha animation). + existing.id = data.id; + existing.states.states.extend(data.states.states); + } + } } fn set_activated(&mut self, active: bool) { -- cgit