aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-05-02 08:14:21 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-02 14:27:53 +0400
commit2f42f8ac75f459cba16482bebcbb58df265971cb (patch)
tree6dd566e9c147b78f635fcd1073307195bcaebdce
parent42cef79c699c0f03b4bb99c4278169c48d9a5bd0 (diff)
downloadniri-2f42f8ac75f459cba16482bebcbb58df265971cb.tar.gz
niri-2f42f8ac75f459cba16482bebcbb58df265971cb.tar.bz2
niri-2f42f8ac75f459cba16482bebcbb58df265971cb.zip
Damage window on corner radius changes
-rw-r--r--src/layout/tile.rs23
-rw-r--r--src/render_helpers/clipped_surface.rs29
-rw-r--r--src/render_helpers/damage.rs75
-rw-r--r--src/render_helpers/mod.rs1
4 files changed, 126 insertions, 2 deletions
diff --git a/src/layout/tile.rs b/src/layout/tile.rs
index f0e770f4..a5ba6c6c 100644
--- a/src/layout/tile.rs
+++ b/src/layout/tile.rs
@@ -19,7 +19,8 @@ use super::{
use crate::animation::Animation;
use crate::niri_render_elements;
use crate::render_helpers::border::BorderRenderElement;
-use crate::render_helpers::clipped_surface::ClippedSurfaceRenderElement;
+use crate::render_helpers::clipped_surface::{ClippedSurfaceRenderElement, RoundedCornerDamage};
+use crate::render_helpers::damage::ExtraDamage;
use crate::render_helpers::offscreen::OffscreenRenderElement;
use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::resize::ResizeRenderElement;
@@ -68,6 +69,9 @@ pub struct Tile<W: LayoutElement> {
/// Snapshot of the last render for use in the close animation.
unmap_snapshot: RefCell<Option<TileRenderSnapshot>>,
+ /// Extra damage for clipped surface corner radius changes.
+ rounded_corner_damage: RoundedCornerDamage,
+
/// Configurable properties of the layout.
pub options: Rc<Options>,
}
@@ -81,6 +85,7 @@ niri_render_elements! {
Resize = ResizeRenderElement,
Border = BorderRenderElement,
ClippedSurface = ClippedSurfaceRenderElement<R>,
+ ExtraDamage = ExtraDamage,
}
}
@@ -118,6 +123,7 @@ impl<W: LayoutElement> Tile<W> {
move_x_animation: None,
move_y_animation: None,
unmap_snapshot: RefCell::new(None),
+ rounded_corner_damage: Default::default(),
options,
}
}
@@ -180,6 +186,14 @@ impl<W: LayoutElement> Tile<W> {
.focus_ring
.resolve_against(self.options.focus_ring.into());
self.focus_ring.update_config(focus_ring_config.into());
+
+ let window_size = self.window_size();
+ let radius = rules
+ .geometry_corner_radius
+ .unwrap_or_default()
+ .fit_to(window_size.w as f32, window_size.h as f32);
+ self.rounded_corner_damage.set_corner_radius(radius);
+ self.rounded_corner_damage.set_size(window_size);
}
pub fn advance_animations(&mut self, current_time: Duration, is_active: bool) {
@@ -650,6 +664,7 @@ impl<W: LayoutElement> Tile<W> {
// If we're not resizing, render the window itself.
let mut window_surface = None;
let mut window_popups = None;
+ let mut rounded_corner_damage = None;
if resize_shader.is_none() && resize_fallback.is_none() {
let window = self
.window
@@ -667,6 +682,11 @@ impl<W: LayoutElement> Tile<W> {
let clip_shader = ClippedSurfaceRenderElement::shader(renderer).cloned();
let border_shader = BorderRenderElement::shader(renderer).cloned();
+ if clip_to_geometry && clip_shader.is_some() {
+ let damage = self.rounded_corner_damage.element();
+ rounded_corner_damage = Some(damage.with_location(window_render_loc).into());
+ }
+
window_surface = Some(window.normal.into_iter().map(move |elem| match elem {
LayoutElementRenderElement::Wayland(elem) => {
// If we should clip to geometry, render a clipped window.
@@ -727,6 +747,7 @@ impl<W: LayoutElement> Tile<W> {
.chain(resize_shader)
.chain(resize_fallback)
.chain(window_popups.into_iter().flatten())
+ .chain(rounded_corner_damage)
.chain(window_surface.into_iter().flatten());
let elem = self.is_fullscreen.then(|| {
diff --git a/src/render_helpers/clipped_surface.rs b/src/render_helpers/clipped_surface.rs
index 69c2a012..43ba8594 100644
--- a/src/render_helpers/clipped_surface.rs
+++ b/src/render_helpers/clipped_surface.rs
@@ -6,8 +6,9 @@ use smithay::backend::renderer::gles::{
GlesError, GlesFrame, GlesRenderer, GlesTexProgram, Uniform,
};
use smithay::backend::renderer::utils::{CommitCounter, DamageSet};
-use smithay::utils::{Buffer, Logical, Physical, Rectangle, Scale, Transform};
+use smithay::utils::{Buffer, Logical, Physical, Rectangle, Scale, Size, Transform};
+use super::damage::ExtraDamage;
use super::renderer::{AsGlesFrame as _, NiriRenderer};
use super::shaders::{mat3_uniform, Shaders};
use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError};
@@ -21,6 +22,12 @@ pub struct ClippedSurfaceRenderElement<R: NiriRenderer> {
input_to_geo: Mat3,
}
+#[derive(Debug, Default, Clone)]
+pub struct RoundedCornerDamage {
+ damage: ExtraDamage,
+ corner_radius: CornerRadius,
+}
+
impl<R: NiriRenderer> ClippedSurfaceRenderElement<R> {
pub fn new(
elem: WaylandSurfaceRenderElement<R>,
@@ -267,3 +274,23 @@ impl<'render> RenderElement<TtyRenderer<'render>>
None
}
}
+
+impl RoundedCornerDamage {
+ pub fn set_size(&mut self, size: Size<i32, Logical>) {
+ self.damage.set_size(size);
+ }
+
+ pub fn set_corner_radius(&mut self, corner_radius: CornerRadius) {
+ if self.corner_radius == corner_radius {
+ return;
+ }
+
+ // FIXME: make the damage granular.
+ self.corner_radius = corner_radius;
+ self.damage.damage_all();
+ }
+
+ pub fn element(&self) -> ExtraDamage {
+ self.damage.clone()
+ }
+}
diff --git a/src/render_helpers/damage.rs b/src/render_helpers/damage.rs
new file mode 100644
index 00000000..ef7b125f
--- /dev/null
+++ b/src/render_helpers/damage.rs
@@ -0,0 +1,75 @@
+use smithay::backend::renderer::element::{Element, Id, RenderElement};
+use smithay::backend::renderer::utils::CommitCounter;
+use smithay::backend::renderer::Renderer;
+use smithay::utils::{Buffer, Logical, Physical, Point, Rectangle, Scale, Size};
+
+#[derive(Debug, Clone)]
+pub struct ExtraDamage {
+ id: Id,
+ commit: CommitCounter,
+ geometry: Rectangle<i32, Logical>,
+}
+
+impl ExtraDamage {
+ pub fn new() -> Self {
+ Self {
+ id: Id::new(),
+ commit: Default::default(),
+ geometry: Default::default(),
+ }
+ }
+
+ pub fn set_size(&mut self, size: Size<i32, Logical>) {
+ if self.geometry.size == size {
+ return;
+ }
+
+ self.geometry.size = size;
+ self.commit.increment();
+ }
+
+ pub fn damage_all(&mut self) {
+ self.commit.increment();
+ }
+
+ pub fn with_location(mut self, location: Point<i32, Logical>) -> Self {
+ self.geometry.loc = location;
+ self
+ }
+}
+
+impl Default for ExtraDamage {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Element for ExtraDamage {
+ fn id(&self) -> &Id {
+ &self.id
+ }
+
+ fn current_commit(&self) -> CommitCounter {
+ self.commit
+ }
+
+ fn src(&self) -> Rectangle<f64, Buffer> {
+ Rectangle::from_loc_and_size((0., 0.), (1., 1.))
+ }
+
+ fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
+ self.geometry.to_physical_precise_round(scale)
+ }
+}
+
+impl<R: Renderer> RenderElement<R> for ExtraDamage {
+ fn draw(
+ &self,
+ _frame: &mut <R as Renderer>::Frame<'_>,
+ _src: Rectangle<f64, Buffer>,
+ _dst: Rectangle<i32, Physical>,
+ _damage: &[Rectangle<i32, Physical>],
+ ) -> Result<(), R::Error> {
+ Ok(())
+ }
+}
diff --git a/src/render_helpers/mod.rs b/src/render_helpers/mod.rs
index ebc4b49e..b1f8fd03 100644
--- a/src/render_helpers/mod.rs
+++ b/src/render_helpers/mod.rs
@@ -18,6 +18,7 @@ use self::primary_gpu_texture::PrimaryGpuTextureRenderElement;
pub mod border;
pub mod clipped_surface;
+pub mod damage;
pub mod offscreen;
pub mod primary_gpu_texture;
pub mod render_elements;