diff options
author | Ali Mohammad Pur <ali.mpfard@gmail.com> | 2023-05-27 09:03:58 +0330 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-05-29 05:35:41 +0200 |
commit | 2e71263c5cc47ba2cc3e235b2cd6cb8c9ed169cd (patch) | |
tree | 6f73fc5e3807b6b12068e54c06f8dc6e6f173c4a | |
parent | e90752cc21961b531a94abb4b33e238670dd6d48 (diff) | |
download | serenity-2e71263c5cc47ba2cc3e235b2cd6cb8c9ed169cd.zip |
LibWeb: Make sure finished animations are not restarted
This commit makes the StyleComputer avoid restarting finished animations
(e.g. animations with finite iteration counts that have run to
completion).
As a bonus, it also disables the animation timer when all animations
have finished running.
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleComputer.cpp | 24 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleComputer.h | 1 |
2 files changed, 21 insertions, 4 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 88b029a002..012a4267b1 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -1004,7 +1004,7 @@ StyleComputer::AnimationStepTransition StyleComputer::Animation::step(CSS::Time auto changed_iteration = false; if (new_progress >= 1) { if (iteration_count.has_value()) { - if (iteration_count.value() == 0) { + if (iteration_count.value() <= 1) { progress = CSS::Percentage(100); return AnimationStepTransition::ActiveToAfter; } @@ -1221,6 +1221,12 @@ void StyleComputer::ensure_animation_timer() const constexpr static auto timer_delay_ms = 1000 / 60; if (!m_animation_driver_timer) { m_animation_driver_timer = Platform::Timer::create_repeating(timer_delay_ms, [this] { + // If we run out of animations, stop the timer - it'll turn back on the next time we have an active animation. + if (m_active_animations.is_empty()) { + m_animation_driver_timer->stop(); + return; + } + HashTable<AnimationKey> animations_to_remove; HashTable<DOM::Element*> owning_elements_to_invalidate; @@ -1242,24 +1248,29 @@ void StyleComputer::ensure_animation_timer() const break; case AnimationStepTransition::IdleOrBeforeToAfter: // FIXME: Dispatch `animationstart` then `animationend`. + m_finished_animations.set(it.key); break; case AnimationStepTransition::ActiveToBefore: // FIXME: Dispatch `animationend`. + m_finished_animations.set(it.key); break; case AnimationStepTransition::ActiveToActiveChangingTheIteration: // FIXME: Dispatch `animationiteration`. break; case AnimationStepTransition::ActiveToAfter: // FIXME: Dispatch `animationend`. + m_finished_animations.set(it.key); break; case AnimationStepTransition::AfterToActive: // FIXME: Dispatch `animationstart`. break; case AnimationStepTransition::AfterToBefore: // FIXME: Dispatch `animationstart` then `animationend`. + m_finished_animations.set(it.key); break; case AnimationStepTransition::Cancelled: // FIXME: Dispatch `animationcancel`. + m_finished_animations.set(it.key); break; } if (it.value->is_done()) @@ -1329,14 +1340,16 @@ ErrorOr<void> StyleComputer::compute_cascaded_values(StyleProperties& style, DOM // Animation declarations [css-animations-2] if (auto animation_name = style.maybe_null_property(PropertyID::AnimationName)) { - ensure_animation_timer(); - if (auto source_declaration = style.property_source_declaration(PropertyID::AnimationName)) { AnimationKey animation_key { .source_declaration = source_declaration, .element = &element, }; - if (auto name = TRY(animation_name->to_string()); !name.is_empty()) { + + if (m_finished_animations.contains(animation_key)) { + // We've already finished going through this animation, so drop it from the active animations. + m_active_animations.remove(animation_key); + } else if (auto name = TRY(animation_name->to_string()); !name.is_empty()) { auto active_animation = m_active_animations.get(animation_key); if (!active_animation.has_value()) { // New animation! @@ -1376,6 +1389,9 @@ ErrorOr<void> StyleComputer::compute_cascaded_values(StyleProperties& style, DOM m_active_animations.remove(animation_key); } } + + if (!m_active_animations.is_empty()) + ensure_animation_timer(); } // Important author declarations diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.h b/Userland/Libraries/LibWeb/CSS/StyleComputer.h index 7c9fbf711e..4410818aa5 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.h +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.h @@ -205,6 +205,7 @@ private: }; mutable HashMap<AnimationKey, NonnullOwnPtr<Animation>> m_active_animations; + mutable HashTable<AnimationKey> m_finished_animations; mutable RefPtr<Platform::Timer> m_animation_driver_timer; }; |