mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-21 02:01:55 +07:00
Damage window on corner radius changes
This commit is contained in:
+22
-1
@@ -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(|| {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user