aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/niri.rs64
-rw-r--r--src/render_helpers/solid_color.rs4
-rw-r--r--src/window/mapped.rs61
3 files changed, 85 insertions, 44 deletions
diff --git a/src/niri.rs b/src/niri.rs
index 7314bdb4..856f4fc5 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -1270,11 +1270,10 @@ impl State {
};
let scale = Scale::from(output.current_scale().fractional_scale());
- let bbox = window.bbox_with_popups();
- let size = bbox.size.to_physical_precise_ceil(scale);
+ let bbox = window.bbox_with_popups().to_physical_precise_up(scale);
let refresh = output.current_mode().unwrap().refresh as u32;
- (CastTarget::Window { id }, size, refresh, true)
+ (CastTarget::Window { id }, bbox.size, refresh, true)
}
};
@@ -3502,10 +3501,12 @@ impl Niri {
continue;
};
- let bbox = mapped.window.bbox_with_popups();
- let size = bbox.size.to_physical_precise_ceil(scale);
+ let bbox = mapped
+ .window
+ .bbox_with_popups()
+ .to_physical_precise_up(scale);
- match cast.ensure_size(size) {
+ match cast.ensure_size(bbox.size) {
Ok(CastSizeChange::Ready) => (),
Ok(CastSizeChange::Pending) => continue,
Err(err) => {
@@ -3519,23 +3520,9 @@ impl Niri {
}
// FIXME: pointer.
- let elements = mapped.render(
- renderer,
- mapped.window.geometry().loc.to_f64(),
- scale,
- 1.,
- RenderTarget::Screencast,
- );
- let geo = elements
- .iter()
- .map(|ele| ele.geometry(scale))
- .reduce(|a, b| a.merge(b))
- .unwrap_or_default();
- let elements = elements.iter().rev().map(|elem| {
- RelocateRenderElement::from_element(elem, geo.loc.upscale(-1), Relocate::Relative)
- });
+ let elements = mapped.render_for_screen_cast(renderer, scale).rev();
- if cast.dequeue_buffer_and_render(renderer, elements, size, scale) {
+ if cast.dequeue_buffer_and_render(renderer, elements, bbox.size, scale) {
cast.last_frame_time = target_presentation_time;
}
}
@@ -3580,8 +3567,10 @@ impl Niri {
.unwrap();
let scale = Scale::from(output.current_scale().fractional_scale());
- let bbox = mapped.window.bbox_with_popups();
- let size = bbox.size.to_physical_precise_ceil(scale);
+ let bbox = mapped
+ .window
+ .bbox_with_popups()
+ .to_physical_precise_up(scale);
let mut elements = None;
let mut casts_to_stop = vec![];
@@ -3596,7 +3585,7 @@ impl Niri {
continue;
}
- match cast.ensure_size(size) {
+ match cast.ensure_size(bbox.size) {
Ok(CastSizeChange::Ready) => (),
Ok(CastSizeChange::Pending) => continue,
Err(err) => {
@@ -3609,27 +3598,16 @@ impl Niri {
continue;
}
- let (elements, geo) = elements.get_or_insert_with(|| {
+ let elements = elements.get_or_insert_with(|| {
// FIXME: pointer.
- let elements = mapped.render(
- renderer,
- mapped.window.geometry().loc.to_f64(),
- scale,
- 1.,
- RenderTarget::Screencast,
- );
- let geo = elements
- .iter()
- .map(|ele| ele.geometry(scale))
- .reduce(|a, b| a.merge(b))
- .unwrap_or_default();
- (elements, geo)
- });
- let elements = elements.iter().rev().map(|elem| {
- RelocateRenderElement::from_element(elem, geo.loc.upscale(-1), Relocate::Relative)
+ mapped
+ .render_for_screen_cast(renderer, scale)
+ .rev()
+ .collect::<Vec<_>>()
});
+ let elements = elements.iter();
- if cast.dequeue_buffer_and_render(renderer, elements, size, scale) {
+ if cast.dequeue_buffer_and_render(renderer, elements, bbox.size, scale) {
cast.last_frame_time = target_presentation_time;
}
}
diff --git a/src/render_helpers/solid_color.rs b/src/render_helpers/solid_color.rs
index 82144785..83923dbb 100644
--- a/src/render_helpers/solid_color.rs
+++ b/src/render_helpers/solid_color.rs
@@ -112,6 +112,10 @@ impl SolidColorRenderElement {
pub fn color(&self) -> [f32; 4] {
self.color
}
+
+ pub fn geo(&self) -> Rectangle<f64, Logical> {
+ self.geometry
+ }
}
impl Element for SolidColorRenderElement {
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 {