1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-23 12:15:06 +00:00
serenity/Userland/Services/WindowServer/Animation.h
Tom 9f59d7d9a0 WindowServer: Fix animation crash
If an Animation's on_stop handler cleared itself inside the on_stop
event handler, it would remove itself from the animation map that was
still being iterated, leading to a crash.

To solve this, we'll iterate over the animations using the
remove_all_matching function, which enables us to delete it by simply
returning true when the animation finished. In the event that the
Animation is kept alive elsewhere and the on_stop event clears its own
reference, we need to temporarily bump the reference count. Another
advantage is that we only need to bump the reference count when an
animation is finished, whereas before this we bumped it
unconditionally.
2022-03-18 20:00:30 +01:00

50 lines
1.1 KiB
C++

/*
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Forward.h>
#include <AK/Function.h>
#include <AK/NonnullRefPtr.h>
#include <AK/RefCounted.h>
#include <LibCore/ElapsedTimer.h>
#include <LibGfx/Forward.h>
namespace WindowServer {
class Compositor;
class Screen;
class Animation : public RefCounted<Animation> {
public:
static NonnullRefPtr<Animation> create() { return adopt_ref(*new Animation); }
~Animation();
bool is_running() const { return m_running; }
void start();
void stop();
void was_removed(Badge<Compositor>);
void set_duration(int duration_in_ms);
int duration() const { return m_duration; }
bool update(Badge<Compositor>, Gfx::Painter&, Screen&, Gfx::DisjointRectSet& flush_rects);
Function<void(float progress, Gfx::Painter&, Screen&, Gfx::DisjointRectSet& flush_rects)> on_update;
Function<void()> on_stop;
private:
Animation();
Core::ElapsedTimer m_timer;
int m_duration { 0 };
bool m_running { false };
bool m_was_removed { false };
};
}