From d5b1e28a371493671a102ee75ea4d68293fef25e Mon Sep 17 00:00:00 2001 From: Armin Sander Date: Mon, 25 May 2026 15:50:36 +0200 Subject: [PATCH 1/3] Remove the Mutex from Animated --- animation/src/animated.rs | 51 +++++++++++--------- desktop/src/desktop_system.rs | 2 +- desktop/src/desktop_system/layout_effects.rs | 2 +- desktop/src/desktop_system/presentation.rs | 2 +- examples/logs/examples/logs.rs | 2 +- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/animation/src/animated.rs b/animation/src/animated.rs index f67ab358..86705c99 100644 --- a/animation/src/animated.rs +++ b/animation/src/animated.rs @@ -1,7 +1,5 @@ use std::time::Duration; -use parking_lot::Mutex; - use crate::{AnimationCoordinator, BlendedAnimation, Interpolatable, Interpolation}; /// `Animated` represents an animated value over time. @@ -12,20 +10,14 @@ use crate::{AnimationCoordinator, BlendedAnimation, Interpolatable, Interpolatio pub struct Animated { coordinator: AnimationCoordinator, /// The current value and the current state of the animation. - /// - /// A mutex, because we want to access it through `&self` but modify it through the animator. - inner: Mutex>, + inner: AnimatedInner, } impl Animated { pub(crate) fn new(coordinator: AnimationCoordinator, value: T) -> Self { Self { coordinator, - inner: AnimatedInner { - value, - animation: Default::default(), - } - .into(), + inner: AnimatedInner::new(value), } } @@ -40,7 +32,7 @@ impl Animated { ) where T: 'static + PartialEq, { - self.inner.lock().animate_if_changed( + self.inner.animate_if_changed( &self.coordinator, target_value, duration, @@ -59,13 +51,12 @@ impl Animated { T: 'static, { self.inner - .lock() .animate(&self.coordinator, target_value, duration, interpolation); } /// Stop all animations, and set the current value. pub fn set_immediately(&mut self, value: T) { - self.inner.lock().set_immediately(value); + self.inner.set_immediately(value); } /// Finish all animations. @@ -75,20 +66,23 @@ impl Animated { /// /// Does nothing when no animation is active. pub fn finish(&mut self) { - self.inner.lock().finish(); + self.inner.finish(); } - /// The current value of this animated value. - /// - /// If an animation is active, this computes the current value from the animation. - pub fn value(&self) -> T { - self.inner.lock().value(&self.coordinator) + /// The current value of this animated value, progressing active animations first. + pub fn value(&mut self) -> T { + self.inner.progressed_value(&self.coordinator) + } + + /// The latest stored value of this animated value without progressing active animations. + pub fn latest_value(&self) -> T { + self.inner.value() } /// The final value of this animated value after all current animations ran through or the /// current value one if no animations are active. pub fn final_value(&self) -> T { - self.inner.lock().final_value().clone() + self.inner.final_value().clone() } /// `true` if this is currently animating. @@ -102,12 +96,12 @@ impl Animated { /// /// Ergonomics: Foolproof! pub fn is_animating(&self) -> bool { - self.inner.lock().is_animating() + self.inner.is_animating() } /// Returns the number of active animation blendings. pub fn animation_count(&self) -> usize { - self.inner.lock().animation_count() + self.inner.animation_count() } } @@ -123,6 +117,13 @@ where } impl AnimatedInner { + pub fn new(value: T) -> Self { + Self { + value, + animation: Default::default(), + } + } + pub fn animate_if_changed( &mut self, coordinator: &AnimationCoordinator, @@ -169,7 +170,11 @@ impl AnimatedInner { self.animation.final_value().unwrap_or(&self.value) } - pub fn value(&mut self, coordinator: &AnimationCoordinator) -> T { + pub fn value(&self) -> T { + self.value.clone() + } + + pub fn progressed_value(&mut self, coordinator: &AnimationCoordinator) -> T { if self.animation.is_active() { let instant = coordinator.current_cycle_time(); if let Some(new_value) = self.animation.proceed(instant) { diff --git a/desktop/src/desktop_system.rs b/desktop/src/desktop_system.rs index c5aa9ce3..4f14c3ec 100644 --- a/desktop/src/desktop_system.rs +++ b/desktop/src/desktop_system.rs @@ -280,7 +280,7 @@ impl DesktopSystem { self.aggregates.instances.contains_key(instance) } - pub fn camera(&self) -> PixelCamera { + pub fn camera(&mut self) -> PixelCamera { self.camera.value() } diff --git a/desktop/src/desktop_system/layout_effects.rs b/desktop/src/desktop_system/layout_effects.rs index 17d43cb4..5bfc1f6e 100644 --- a/desktop/src/desktop_system/layout_effects.rs +++ b/desktop/src/desktop_system/layout_effects.rs @@ -360,7 +360,7 @@ impl DesktopSystem { placement.transform = Transform::compose_with_anchor( launcher_placement.transform, launcher_anchor, - instance_presenter.layout_transform_animation.value(), + instance_presenter.layout_transform_animation.latest_value(), instance_anchor, ); diff --git a/desktop/src/desktop_system/presentation.rs b/desktop/src/desktop_system/presentation.rs index ecec62d0..698d8f2f 100644 --- a/desktop/src/desktop_system/presentation.rs +++ b/desktop/src/desktop_system/presentation.rs @@ -36,7 +36,7 @@ impl DesktopSystem { }; let initial_center_translation = - originating_presenter.map(|op| op.layout_transform_animation.value().translate); + originating_presenter.map(|op| op.layout_transform_animation.latest_value().translate); let presenter = InstancePresenter::new( initial_center_translation, diff --git a/examples/logs/examples/logs.rs b/examples/logs/examples/logs.rs index d8bda743..6602ada2 100644 --- a/examples/logs/examples/logs.rs +++ b/examples/logs/examples/logs.rs @@ -270,7 +270,7 @@ impl Logs { while let Some(line) = self.lines.front() { if line.fading_out && !line.fader.is_animating() { - debug!("faded out at: {}", line.fader.value()); + debug!("faded out at: {}", line.fader.latest_value()); self.lines.pop_front(); update_v_alignment = true; } else { From 38cd0e378185de151fec50d554f9afab7b2d607e Mon Sep 17 00:00:00 2001 From: Armin Sander Date: Mon, 25 May 2026 16:21:32 +0200 Subject: [PATCH 2/3] Animated values can now be returned by reference --- animation/src/animated.rs | 26 +++++++++----------- desktop/src/desktop.rs | 2 +- desktop/src/desktop_system.rs | 2 +- desktop/src/desktop_system/layout_effects.rs | 8 ++++-- desktop/src/instance_presenter.rs | 4 +-- desktop/src/projects/launcher_presenter.rs | 6 ++--- desktop/src/projects/project_presenter.rs | 2 +- examples/logs/examples/logs.rs | 7 +++--- 8 files changed, 29 insertions(+), 28 deletions(-) diff --git a/animation/src/animated.rs b/animation/src/animated.rs index 86705c99..480c8c0b 100644 --- a/animation/src/animated.rs +++ b/animation/src/animated.rs @@ -32,12 +32,8 @@ impl Animated { ) where T: 'static + PartialEq, { - self.inner.animate_if_changed( - &self.coordinator, - target_value, - duration, - interpolation, - ); + self.inner + .animate_if_changed(&self.coordinator, target_value, duration, interpolation); } /// Animate to a target value in the given duration. @@ -70,19 +66,20 @@ impl Animated { } /// The current value of this animated value, progressing active animations first. - pub fn value(&mut self) -> T { - self.inner.progressed_value(&self.coordinator) + pub fn value(&mut self) -> &T { + self.inner.progress(&self.coordinator); + self.latest_value() } /// The latest stored value of this animated value without progressing active animations. - pub fn latest_value(&self) -> T { + pub fn latest_value(&self) -> &T { self.inner.value() } /// The final value of this animated value after all current animations ran through or the /// current value one if no animations are active. - pub fn final_value(&self) -> T { - self.inner.final_value().clone() + pub fn final_value(&self) -> &T { + self.inner.final_value() } /// `true` if this is currently animating. @@ -170,18 +167,17 @@ impl AnimatedInner { self.animation.final_value().unwrap_or(&self.value) } - pub fn value(&self) -> T { - self.value.clone() + pub fn value(&self) -> &T { + &self.value } - pub fn progressed_value(&mut self, coordinator: &AnimationCoordinator) -> T { + pub fn progress(&mut self, coordinator: &AnimationCoordinator) { if self.animation.is_active() { let instant = coordinator.current_cycle_time(); if let Some(new_value) = self.animation.proceed(instant) { self.value = new_value; } } - self.value.clone() } pub fn is_animating(&self) -> bool { diff --git a/desktop/src/desktop.rs b/desktop/src/desktop.rs index f2cc8e08..f148abd2 100644 --- a/desktop/src/desktop.rs +++ b/desktop/src/desktop.rs @@ -224,7 +224,7 @@ impl Desktop { // Get the camera, build the frame, and submit it to the renderer. { - let camera = self.system.camera(); + let camera = self.system.camera().clone(); let mut frame = self.scene.begin_frame().with_camera(camera); if self.instance_manager.effective_pacing() == RenderPacing::Smooth { frame = frame.with_pacing(RenderPacing::Smooth); diff --git a/desktop/src/desktop_system.rs b/desktop/src/desktop_system.rs index 4f14c3ec..fcd0cea1 100644 --- a/desktop/src/desktop_system.rs +++ b/desktop/src/desktop_system.rs @@ -280,7 +280,7 @@ impl DesktopSystem { self.aggregates.instances.contains_key(instance) } - pub fn camera(&mut self) -> PixelCamera { + pub fn camera(&mut self) -> &PixelCamera { self.camera.value() } diff --git a/desktop/src/desktop_system/layout_effects.rs b/desktop/src/desktop_system/layout_effects.rs index 5bfc1f6e..b5aaa741 100644 --- a/desktop/src/desktop_system/layout_effects.rs +++ b/desktop/src/desktop_system/layout_effects.rs @@ -27,7 +27,8 @@ impl DesktopSystem { ) -> Result<()> { if !effects_mode.permit_camera_moves() { // Lock camera motion immediately, including already running camera animations. - let camera = self.camera.value(); + // Ergonomics: There should probably be a function for that in Animated. + let camera = self.camera.value().clone(); self.camera.set_immediately(camera); } @@ -360,7 +361,10 @@ impl DesktopSystem { placement.transform = Transform::compose_with_anchor( launcher_placement.transform, launcher_anchor, - instance_presenter.layout_transform_animation.latest_value(), + instance_presenter + .layout_transform_animation + .latest_value() + .clone(), instance_anchor, ); diff --git a/desktop/src/instance_presenter.rs b/desktop/src/instance_presenter.rs index cc149829..5e3211b5 100644 --- a/desktop/src/instance_presenter.rs +++ b/desktop/src/instance_presenter.rs @@ -212,7 +212,7 @@ impl InstancePresenter { pub fn apply_animations(&mut self) { let layout_transform = self.layout_transform_animation.value(); - self.instance_transform.update_if_changed(layout_transform); + self.instance_transform.update_if_changed(*layout_transform); // Feature: Hiding animation. let Some(view) = self.state.view_mut() else { @@ -222,7 +222,7 @@ impl InstancePresenter { let alpha = view.alpha.value(); location.update_if_changed_with(|location| { - location.alpha = alpha; + location.alpha = *alpha; }); } } diff --git a/desktop/src/projects/launcher_presenter.rs b/desktop/src/projects/launcher_presenter.rs index e6640abd..4b20caea 100644 --- a/desktop/src/projects/launcher_presenter.rs +++ b/desktop/src/projects/launcher_presenter.rs @@ -277,7 +277,7 @@ impl LauncherPresenter { } fn presents_instance(&self) -> bool { - self.fader.final_value() == 0.0 + *self.fader.final_value() == 0.0 } pub fn set_layout(&mut self, size: SizePx, layout_transform: Transform, animate: bool) { @@ -332,7 +332,7 @@ impl LauncherPresenter { self.background.update_if_changed_with(|visual| { visual.shapes = [background_shape( size.to_rect(), - BACKGROUND_COLOR.with_alpha(alpha), + BACKGROUND_COLOR.with_alpha(*alpha), )] .into() }); @@ -342,7 +342,7 @@ impl LauncherPresenter { visual.shapes = match &*visual.shapes { [Shape::GlyphRun(gr)] => [gr .clone() - .with_color(TEXT_COLOR.with_alpha(alpha)) + .with_color(TEXT_COLOR.with_alpha(*alpha)) .into_shape()] .into(), rest => rest.into(), diff --git a/desktop/src/projects/project_presenter.rs b/desktop/src/projects/project_presenter.rs index db439487..c4e8cc0c 100644 --- a/desktop/src/projects/project_presenter.rs +++ b/desktop/src/projects/project_presenter.rs @@ -87,7 +87,7 @@ impl DesktopPresenter { let size = hover_placement.rect.size; let local_rect = Rect::from_size((size[0] as f64, size[1] as f64)); - let rect_alpha = (alpha != 0.0).then_some((local_rect, alpha)); + let rect_alpha = (*alpha != 0.0).then_some((local_rect, *alpha)); // Position the hover visual in world space using the placement's center-based transform. let local_center = local_rect.center(); diff --git a/examples/logs/examples/logs.rs b/examples/logs/examples/logs.rs index 6602ada2..0750bbe7 100644 --- a/examples/logs/examples/logs.rs +++ b/examples/logs/examples/logs.rs @@ -260,7 +260,7 @@ impl Logs { } fn apply_animations(&mut self) { - let v_center = self.vertical_center.value(); + let v_center = *self.vertical_center.value(); self.vertical_center_transform .update((0., v_center, 0.).into()); @@ -290,9 +290,10 @@ impl Logs { } fn update_content_transform(&mut self) { + let content_height = *self.content_height.value(); let new_transform = self .application - .get_transform((self.content_width, self.content_height.value() as u32)); + .get_transform((self.content_width, content_height as u32)); self.content_transform.update_if_changed(new_transform); } } @@ -348,7 +349,7 @@ impl LogLine { return; } - let fading = self.fader.value(); + let fading = *self.fader.value(); self.visual.update_with(|v| { v.shapes = v From 6daf9fa9f5fe155d6b800922457b635b6635ae9c Mon Sep 17 00:00:00 2001 From: Armin Sander Date: Tue, 26 May 2026 07:54:57 +0200 Subject: [PATCH 3/3] Fix more compilation errors --- desktop/src/desktop.rs | 2 +- desktop/src/desktop_system/layout_effects.rs | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/desktop/src/desktop.rs b/desktop/src/desktop.rs index f148abd2..108f7af4 100644 --- a/desktop/src/desktop.rs +++ b/desktop/src/desktop.rs @@ -224,7 +224,7 @@ impl Desktop { // Get the camera, build the frame, and submit it to the renderer. { - let camera = self.system.camera().clone(); + let camera = *self.system.camera(); let mut frame = self.scene.begin_frame().with_camera(camera); if self.instance_manager.effective_pacing() == RenderPacing::Smooth { frame = frame.with_pacing(RenderPacing::Smooth); diff --git a/desktop/src/desktop_system/layout_effects.rs b/desktop/src/desktop_system/layout_effects.rs index b5aaa741..3dfed820 100644 --- a/desktop/src/desktop_system/layout_effects.rs +++ b/desktop/src/desktop_system/layout_effects.rs @@ -28,7 +28,7 @@ impl DesktopSystem { if !effects_mode.permit_camera_moves() { // Lock camera motion immediately, including already running camera animations. // Ergonomics: There should probably be a function for that in Animated. - let camera = self.camera.value().clone(); + let camera = *self.camera.value(); self.camera.set_immediately(camera); } @@ -361,10 +361,7 @@ impl DesktopSystem { placement.transform = Transform::compose_with_anchor( launcher_placement.transform, launcher_anchor, - instance_presenter - .layout_transform_animation - .latest_value() - .clone(), + *instance_presenter.layout_transform_animation.latest_value(), instance_anchor, );