aboutsummaryrefslogtreecommitdiff
path: root/src/layout/closing_window.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout/closing_window.rs')
-rw-r--r--src/layout/closing_window.rs79
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);