aboutsummaryrefslogtreecommitdiff
path: root/src/window
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-06-28 12:35:12 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-06-28 12:35:12 +0400
commit4d60eae82e7ce9ccb5e6d06c8f98f77dcde866ab (patch)
tree4233749864fed2b4115b058a9e483968611d8e88 /src/window
parent2b5215c2447cc0a4bfac9903cd919b4c6a782107 (diff)
downloadniri-4d60eae82e7ce9ccb5e6d06c8f98f77dcde866ab.tar.gz
niri-4d60eae82e7ce9ccb5e6d06c8f98f77dcde866ab.tar.bz2
niri-4d60eae82e7ce9ccb5e6d06c8f98f77dcde866ab.zip
Fix blocked-out + popups and rounded corners window screencasts
Diffstat (limited to 'src/window')
-rw-r--r--src/window/mapped.rs61
1 files changed, 60 insertions, 1 deletions
diff --git a/src/window/mapped.rs b/src/window/mapped.rs
index 18ace780..8b6b8e61 100644
--- a/src/window/mapped.rs
+++ b/src/window/mapped.rs
@@ -2,7 +2,7 @@ use std::cell::{Cell, RefCell};
use std::cmp::{max, min};
use std::time::Duration;
-use niri_config::WindowRule;
+use niri_config::{CornerRadius, WindowRule};
use smithay::backend::renderer::element::surface::render_elements_from_surface_tree;
use smithay::backend::renderer::element::{Id, Kind};
use smithay::backend::renderer::gles::GlesRenderer;
@@ -22,6 +22,8 @@ use crate::layout::{
InteractiveResizeData, LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot,
};
use crate::niri::WindowOffscreenId;
+use crate::niri_render_elements;
+use crate::render_helpers::border::BorderRenderElement;
use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::snapshot::RenderSnapshot;
use crate::render_helpers::solid_color::{SolidColorBuffer, SolidColorRenderElement};
@@ -76,6 +78,14 @@ pub struct Mapped {
last_interactive_resize_start: Cell<Option<(Duration, ResizeEdge)>>,
}
+niri_render_elements! {
+ WindowCastRenderElements<R> => {
+ Layout = LayoutElementRenderElement<R>,
+ // Blocked-out window with rounded corners.
+ Border = BorderRenderElement,
+ }
+}
+
static MAPPED_ID_COUNTER: IdCounter = IdCounter::new();
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -246,6 +256,55 @@ impl Mapped {
pub fn last_interactive_resize_start(&self) -> &Cell<Option<(Duration, ResizeEdge)>> {
&self.last_interactive_resize_start
}
+
+ pub fn render_for_screen_cast<R: NiriRenderer>(
+ &self,
+ renderer: &mut R,
+ scale: Scale<f64>,
+ ) -> impl DoubleEndedIterator<Item = WindowCastRenderElements<R>> {
+ let bbox = self.window.bbox_with_popups().to_physical_precise_up(scale);
+
+ let has_border_shader = BorderRenderElement::has_shader(renderer);
+ let rules = self.rules();
+ let radius = rules.geometry_corner_radius.unwrap_or_default();
+ let window_size = self
+ .size()
+ .to_f64()
+ .to_physical_precise_round(scale)
+ .to_logical(scale);
+ let radius = radius.fit_to(window_size.w as f32, window_size.h as f32);
+
+ let location = self.window.geometry().loc.to_f64() - bbox.loc.to_logical(scale);
+ let elements = self.render(renderer, location, scale, 1., RenderTarget::Screencast);
+
+ elements.into_iter().map(move |elem| {
+ if let LayoutElementRenderElement::SolidColor(elem) = &elem {
+ // In this branch we're rendering a blocked-out window with a solid color. We need
+ // to render it with a rounded corner shader even if clip_to_geometry is false,
+ // because in this case we're assuming that the unclipped window CSD already has
+ // corners rounded to the user-provided radius, so our blocked-out rendering should
+ // match that radius.
+ if radius != CornerRadius::default() && has_border_shader {
+ let geo = elem.geo();
+ return BorderRenderElement::new(
+ geo.size,
+ Rectangle::from_loc_and_size((0., 0.), geo.size),
+ elem.color(),
+ elem.color(),
+ 0.,
+ Rectangle::from_loc_and_size((0., 0.), geo.size),
+ 0.,
+ radius,
+ scale.x as f32,
+ )
+ .with_location(geo.loc)
+ .into();
+ }
+ }
+
+ WindowCastRenderElements::from(elem)
+ })
+ }
}
impl Drop for Mapped {