aboutsummaryrefslogtreecommitdiff
path: root/src/window
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-03-01 09:45:57 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-03-10 07:59:14 +0300
commitb351f6ff220560d96a260d8dd3ad794000923481 (patch)
treef2bd1a777fe9f932fea2cfeba3677cbb39b634eb /src/window
parent12817a682d666e81e30b5a723d6419baf74cdb1c (diff)
downloadniri-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/window')
-rw-r--r--src/window/mapped.rs33
1 files changed, 25 insertions, 8 deletions
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<Option<Id>>,
+ offscreen_data: RefCell<Option<OffscreenData>>,
/// 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<Option<Id>> {
- self.offscreen_element_id.borrow()
+ pub fn offscreen_data(&self) -> Ref<Option<OffscreenData>> {
+ 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<Id>) {
- self.offscreen_element_id.replace(id);
+ fn set_offscreen_data(&self, data: Option<OffscreenData>) {
+ 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) {