diff options
Diffstat (limited to 'src/layout/closing_window.rs')
| -rw-r--r-- | src/layout/closing_window.rs | 79 |
1 files changed, 72 insertions, 7 deletions
diff --git a/src/layout/closing_window.rs b/src/layout/closing_window.rs index cbaf29be..8bbf0258 100644 --- a/src/layout/closing_window.rs +++ b/src/layout/closing_window.rs @@ -12,6 +12,7 @@ use smithay::backend::renderer::element::{Kind, RenderElement}; use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture, Uniform}; use smithay::backend::renderer::Texture; use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform}; +use smithay::wayland::compositor::{Blocker, BlockerState}; use crate::animation::Animation; use crate::niri_render_elements; @@ -21,6 +22,7 @@ use crate::render_helpers::shaders::{mat3_uniform, ProgramType, Shaders}; use crate::render_helpers::snapshot::RenderSnapshot; use crate::render_helpers::texture::{TextureBuffer, TextureRenderElement}; use crate::render_helpers::{render_to_encompassing_texture, RenderTarget}; +use crate::utils::transaction::TransactionBlocker; #[derive(Debug)] pub struct ClosingWindow { @@ -46,7 +48,7 @@ pub struct ClosingWindow { blocked_out_buffer_offset: Point<f64, Logical>, /// The closing animation. - anim: Animation, + anim_state: AnimationState, /// Random seed for the shader. random_seed: f32, @@ -59,6 +61,29 @@ niri_render_elements! { } } +#[derive(Debug)] +enum AnimationState { + Waiting { + /// Blocker for a transaction before starting the animation. + blocker: TransactionBlocker, + anim: Animation, + }, + Animating(Animation), +} + +impl AnimationState { + pub fn new(blocker: TransactionBlocker, anim: Animation) -> Self { + if blocker.state() == BlockerState::Pending { + Self::Waiting { blocker, anim } + } else { + // This actually doesn't normally happen because the window is removed only after the + // closing animation is created. Though, it does happen with disable-transactions debug + // flag. + Self::Animating(anim) + } + } +} + impl ClosingWindow { pub fn new<E: RenderElement<GlesRenderer>>( renderer: &mut GlesRenderer, @@ -66,6 +91,7 @@ impl ClosingWindow { scale: Scale<f64>, geo_size: Size<f64, Logical>, pos: Point<f64, Logical>, + blocker: TransactionBlocker, anim: Animation, ) -> anyhow::Result<Self> { let _span = tracy_client::span!("ClosingWindow::new"); @@ -107,17 +133,29 @@ impl ClosingWindow { pos, buffer_offset, blocked_out_buffer_offset, - anim, + anim_state: AnimationState::new(blocker, anim), random_seed: fastrand::f32(), }) } pub fn advance_animations(&mut self, current_time: Duration) { - self.anim.set_current_time(current_time); + match &mut self.anim_state { + AnimationState::Waiting { blocker, anim } => { + if blocker.state() != BlockerState::Pending { + let mut anim = anim.restarted(0., 1., 0.); + anim.set_current_time(current_time); + self.anim_state = AnimationState::Animating(anim); + } + } + AnimationState::Animating(anim) => anim.set_current_time(current_time), + } } pub fn are_animations_ongoing(&self) -> bool { - !self.anim.is_done() + match &self.anim_state { + AnimationState::Waiting { .. } => true, + AnimationState::Animating(anim) => !anim.is_done(), + } } pub fn render( @@ -127,15 +165,42 @@ impl ClosingWindow { scale: Scale<f64>, target: RenderTarget, ) -> ClosingWindowRenderElement { - let progress = self.anim.value(); - let clamped_progress = self.anim.clamped_value().clamp(0., 1.); - let (buffer, offset) = if target.should_block_out(self.block_out_from) { (&self.blocked_out_buffer, self.blocked_out_buffer_offset) } else { (&self.buffer, self.buffer_offset) }; + let anim = match &self.anim_state { + AnimationState::Waiting { .. } => { + let elem = TextureRenderElement::from_texture_buffer( + buffer.clone(), + Point::from((0., 0.)), + 1., + None, + None, + Kind::Unspecified, + ); + + let elem = PrimaryGpuTextureRenderElement(elem); + let elem = RescaleRenderElement::from_element(elem, Point::from((0, 0)), 1.); + + let mut location = self.pos + offset; + location.x -= view_rect.loc.x; + let elem = RelocateRenderElement::from_element( + elem, + location.to_physical_precise_round(scale), + Relocate::Relative, + ); + + return elem.into(); + } + AnimationState::Animating(anim) => anim, + }; + + let progress = anim.value(); + let clamped_progress = anim.clamped_value().clamp(0., 1.); + if Shaders::get(renderer).program(ProgramType::Close).is_some() { let area_loc = Vec2::new(view_rect.loc.x as f32, view_rect.loc.y as f32); let area_size = Vec2::new(view_rect.size.w as f32, view_rect.size.h as f32); |
