Extract TimeLine into its own header

This commit is contained in:
Vlad Zahorodnii 2023-11-14 15:12:23 +02:00
parent 889180b685
commit 56e384e527
16 changed files with 492 additions and 455 deletions

View file

@ -7,7 +7,7 @@
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/timeline.h"
#include <QTest>

View file

@ -117,6 +117,7 @@ target_sources(kwin PRIVATE
libkwineffects/kwinoffscreenquickview.cpp
libkwineffects/kwinquickeffect.cpp
libkwineffects/logging.cpp
libkwineffects/timeline.cpp
lidswitchtracker.cpp
main.cpp
modifier_only_shortcuts.cpp
@ -440,6 +441,7 @@ install(FILES
libkwineffects/kwinoffscreeneffect.h
libkwineffects/kwinoffscreenquickview.h
libkwineffects/kwinquickeffect.h
libkwineffects/timeline.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/kwin/libkwineffects COMPONENT Devel)
install(FILES

View file

@ -11,6 +11,7 @@
#pragma once
#include "libkwineffects/kwinanimationeffect.h"
#include "libkwineffects/timeline.h"
#include <QEasingCurve>

View file

@ -1713,207 +1713,6 @@ EffectWindow *WindowMotionManager::windowAtPoint(QPoint point, bool useStackingO
return nullptr;
}
/***************************************************************
TimeLine
***************************************************************/
class Q_DECL_HIDDEN TimeLine::Data : public QSharedData
{
public:
std::chrono::milliseconds duration;
Direction direction;
QEasingCurve easingCurve;
std::chrono::milliseconds elapsed = std::chrono::milliseconds::zero();
std::optional<std::chrono::milliseconds> lastTimestamp = std::nullopt;
bool done = false;
RedirectMode sourceRedirectMode = RedirectMode::Relaxed;
RedirectMode targetRedirectMode = RedirectMode::Strict;
};
TimeLine::TimeLine(std::chrono::milliseconds duration, Direction direction)
: d(new Data)
{
Q_ASSERT(duration > std::chrono::milliseconds::zero());
d->duration = duration;
d->direction = direction;
}
TimeLine::TimeLine(const TimeLine &other)
: d(other.d)
{
}
TimeLine::~TimeLine() = default;
qreal TimeLine::progress() const
{
return static_cast<qreal>(d->elapsed.count()) / d->duration.count();
}
qreal TimeLine::value() const
{
const qreal t = progress();
return d->easingCurve.valueForProgress(
d->direction == Backward ? 1.0 - t : t);
}
void TimeLine::advance(std::chrono::milliseconds timestamp)
{
if (d->done) {
return;
}
std::chrono::milliseconds delta = std::chrono::milliseconds::zero();
if (d->lastTimestamp.has_value()) {
delta = timestamp - d->lastTimestamp.value();
}
Q_ASSERT(delta >= std::chrono::milliseconds::zero());
d->lastTimestamp = timestamp;
d->elapsed += delta;
if (d->elapsed >= d->duration) {
d->elapsed = d->duration;
d->done = true;
d->lastTimestamp = std::nullopt;
}
}
std::chrono::milliseconds TimeLine::elapsed() const
{
return d->elapsed;
}
void TimeLine::setElapsed(std::chrono::milliseconds elapsed)
{
Q_ASSERT(elapsed >= std::chrono::milliseconds::zero());
if (elapsed == d->elapsed) {
return;
}
reset();
d->elapsed = elapsed;
if (d->elapsed >= d->duration) {
d->elapsed = d->duration;
d->done = true;
d->lastTimestamp = std::nullopt;
}
}
std::chrono::milliseconds TimeLine::duration() const
{
return d->duration;
}
void TimeLine::setDuration(std::chrono::milliseconds duration)
{
Q_ASSERT(duration > std::chrono::milliseconds::zero());
if (duration == d->duration) {
return;
}
d->elapsed = std::chrono::milliseconds(qRound(progress() * duration.count()));
d->duration = duration;
if (d->elapsed == d->duration) {
d->done = true;
d->lastTimestamp = std::nullopt;
}
}
TimeLine::Direction TimeLine::direction() const
{
return d->direction;
}
void TimeLine::setDirection(TimeLine::Direction direction)
{
if (d->direction == direction) {
return;
}
d->direction = direction;
if (d->elapsed > std::chrono::milliseconds::zero()
|| d->sourceRedirectMode == RedirectMode::Strict) {
d->elapsed = d->duration - d->elapsed;
}
if (d->done && d->targetRedirectMode == RedirectMode::Relaxed) {
d->done = false;
}
if (d->elapsed >= d->duration) {
d->done = true;
d->lastTimestamp = std::nullopt;
}
}
void TimeLine::toggleDirection()
{
setDirection(d->direction == Forward ? Backward : Forward);
}
QEasingCurve TimeLine::easingCurve() const
{
return d->easingCurve;
}
void TimeLine::setEasingCurve(const QEasingCurve &easingCurve)
{
d->easingCurve = easingCurve;
}
void TimeLine::setEasingCurve(QEasingCurve::Type type)
{
d->easingCurve.setType(type);
}
bool TimeLine::running() const
{
return d->elapsed != std::chrono::milliseconds::zero()
&& d->elapsed != d->duration;
}
bool TimeLine::done() const
{
return d->done;
}
void TimeLine::reset()
{
d->lastTimestamp = std::nullopt;
d->elapsed = std::chrono::milliseconds::zero();
d->done = false;
}
TimeLine::RedirectMode TimeLine::sourceRedirectMode() const
{
return d->sourceRedirectMode;
}
void TimeLine::setSourceRedirectMode(RedirectMode mode)
{
d->sourceRedirectMode = mode;
}
TimeLine::RedirectMode TimeLine::targetRedirectMode() const
{
return d->targetRedirectMode;
}
void TimeLine::setTargetRedirectMode(RedirectMode mode)
{
d->targetRedirectMode = mode;
}
TimeLine &TimeLine::operator=(const TimeLine &other)
{
d = other.d;
return *this;
}
} // namespace
#include "moc_kwineffects.cpp"

View file

@ -3473,257 +3473,6 @@ private:
QSet<EffectWindow *> m_movingWindowsSet;
};
/**
* The TimeLine class is a helper for controlling animations.
*/
class KWIN_EXPORT TimeLine
{
public:
/**
* Direction of the timeline.
*
* When the direction of the timeline is Forward, the progress
* value will go from 0.0 to 1.0.
*
* When the direction of the timeline is Backward, the progress
* value will go from 1.0 to 0.0.
*/
enum Direction {
Forward,
Backward
};
/**
* Constructs a new instance of TimeLine.
*
* @param duration Duration of the timeline, in milliseconds
* @param direction Direction of the timeline
* @since 5.14
*/
explicit TimeLine(std::chrono::milliseconds duration = std::chrono::milliseconds(1000),
Direction direction = Forward);
TimeLine(const TimeLine &other);
~TimeLine();
/**
* Returns the current value of the timeline.
*
* @since 5.14
*/
qreal value() const;
/**
* Advances the timeline to the specified @a timestamp.
*/
void advance(std::chrono::milliseconds timestamp);
/**
* Returns the number of elapsed milliseconds.
*
* @see setElapsed
* @since 5.14
*/
std::chrono::milliseconds elapsed() const;
/**
* Sets the number of elapsed milliseconds.
*
* This method overwrites previous value of elapsed milliseconds.
* If the new value of elapsed milliseconds is greater or equal
* to duration of the timeline, the timeline will be finished, i.e.
* proceeding TimeLine::done method calls will return @c true.
* Please don't use it. Instead, use TimeLine::update.
*
* @note The new number of elapsed milliseconds should be a non-negative
* number, i.e. it should be greater or equal to 0.
*
* @param elapsed The new number of elapsed milliseconds
* @see elapsed
* @since 5.14
*/
void setElapsed(std::chrono::milliseconds elapsed);
/**
* Returns the duration of the timeline.
*
* @returns Duration of the timeline, in milliseconds
* @see setDuration
* @since 5.14
*/
std::chrono::milliseconds duration() const;
/**
* Sets the duration of the timeline.
*
* In addition to setting new value of duration, the timeline will
* try to retarget the number of elapsed milliseconds to match
* as close as possible old progress value. If the new duration
* is much smaller than old duration, there is a big chance that
* the timeline will be finished after setting new duration.
*
* @note The new duration should be a positive number, i.e. it
* should be greater or equal to 1.
*
* @param duration The new duration of the timeline, in milliseconds
* @see duration
* @since 5.14
*/
void setDuration(std::chrono::milliseconds duration);
/**
* Returns the direction of the timeline.
*
* @returns Direction of the timeline(TimeLine::Forward or TimeLine::Backward)
* @see setDirection
* @see toggleDirection
* @since 5.14
*/
Direction direction() const;
/**
* Sets the direction of the timeline.
*
* @param direction The new direction of the timeline
* @see direction
* @see toggleDirection
* @since 5.14
*/
void setDirection(Direction direction);
/**
* Toggles the direction of the timeline.
*
* If the direction of the timeline was TimeLine::Forward, it becomes
* TimeLine::Backward, and vice verca.
*
* @see direction
* @see setDirection
* @since 5.14
*/
void toggleDirection();
/**
* Returns the easing curve of the timeline.
*
* @see setEasingCurve
* @since 5.14
*/
QEasingCurve easingCurve() const;
/**
* Sets new easing curve.
*
* @param easingCurve An easing curve to be set
* @see easingCurve
* @since 5.14
*/
void setEasingCurve(const QEasingCurve &easingCurve);
/**
* Sets new easing curve by providing its type.
*
* @param type Type of the easing curve(e.g. QEasingCurve::InCubic, etc)
* @see easingCurve
* @since 5.14
*/
void setEasingCurve(QEasingCurve::Type type);
/**
* Returns whether the timeline is currently in progress.
*
* @see done
* @since 5.14
*/
bool running() const;
/**
* Returns whether the timeline is finished.
*
* @see reset
* @since 5.14
*/
bool done() const;
/**
* Resets the timeline to initial state.
*
* @since 5.14
*/
void reset();
enum class RedirectMode {
Strict,
Relaxed
};
/**
* Returns the redirect mode for the source position.
*
* The redirect mode controls behavior of the timeline when its direction is
* changed at the source position, e.g. what should we do when the timeline
* initially goes forward and we change its direction to go backward.
*
* In the strict mode, the timeline will stop.
*
* In the relaxed mode, the timeline will go in the new direction. For example,
* if the timeline goes forward(from 0 to 1), then with the new direction it
* will go backward(from 1 to 0).
*
* The default is RedirectMode::Relaxed.
*
* @see targetRedirectMode
* @since 5.15
*/
RedirectMode sourceRedirectMode() const;
/**
* Sets the redirect mode for the source position.
*
* @param mode The new mode.
* @since 5.15
*/
void setSourceRedirectMode(RedirectMode mode);
/**
* Returns the redirect mode for the target position.
*
* The redirect mode controls behavior of the timeline when its direction is
* changed at the target position.
*
* In the strict mode, subsequent update calls won't have any effect on the
* current value of the timeline.
*
* In the relaxed mode, the timeline will go in the new direction.
*
* The default is RedirectMode::Strict.
*
* @see sourceRedirectMode
* @since 5.15
*/
RedirectMode targetRedirectMode() const;
/**
* Sets the redirect mode for the target position.
*
* @param mode The new mode.
* @since 5.15
*/
void setTargetRedirectMode(RedirectMode mode);
TimeLine &operator=(const TimeLine &other);
/**
* @returns a value between 0 and 1 defining the progress of the timeline
*
* @since 5.23
*/
qreal progress() const;
private:
class Data;
QSharedDataPointer<Data> d;
};
/**
* Pointer to the global EffectsHandler object.
*/
@ -3905,7 +3654,5 @@ inline void EffectWindow::addLayerRepaint(int x, int y, int w, int h)
} // namespace
Q_DECLARE_METATYPE(KWin::EffectWindow *)
Q_DECLARE_METATYPE(KWin::EffectWindowList)
Q_DECLARE_METATYPE(KWin::TimeLine)
Q_DECLARE_METATYPE(KWin::TimeLine::Direction)
/** @} */

View file

@ -0,0 +1,209 @@
/*
SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "libkwineffects/timeline.h"
namespace KWin
{
class Q_DECL_HIDDEN TimeLine::Data : public QSharedData
{
public:
std::chrono::milliseconds duration;
Direction direction;
QEasingCurve easingCurve;
std::chrono::milliseconds elapsed = std::chrono::milliseconds::zero();
std::optional<std::chrono::milliseconds> lastTimestamp = std::nullopt;
bool done = false;
RedirectMode sourceRedirectMode = RedirectMode::Relaxed;
RedirectMode targetRedirectMode = RedirectMode::Strict;
};
TimeLine::TimeLine(std::chrono::milliseconds duration, Direction direction)
: d(new Data)
{
Q_ASSERT(duration > std::chrono::milliseconds::zero());
d->duration = duration;
d->direction = direction;
}
TimeLine::TimeLine(const TimeLine &other)
: d(other.d)
{
}
TimeLine::~TimeLine() = default;
qreal TimeLine::progress() const
{
return static_cast<qreal>(d->elapsed.count()) / d->duration.count();
}
qreal TimeLine::value() const
{
const qreal t = progress();
return d->easingCurve.valueForProgress(
d->direction == Backward ? 1.0 - t : t);
}
void TimeLine::advance(std::chrono::milliseconds timestamp)
{
if (d->done) {
return;
}
std::chrono::milliseconds delta = std::chrono::milliseconds::zero();
if (d->lastTimestamp.has_value()) {
delta = timestamp - d->lastTimestamp.value();
}
Q_ASSERT(delta >= std::chrono::milliseconds::zero());
d->lastTimestamp = timestamp;
d->elapsed += delta;
if (d->elapsed >= d->duration) {
d->elapsed = d->duration;
d->done = true;
d->lastTimestamp = std::nullopt;
}
}
std::chrono::milliseconds TimeLine::elapsed() const
{
return d->elapsed;
}
void TimeLine::setElapsed(std::chrono::milliseconds elapsed)
{
Q_ASSERT(elapsed >= std::chrono::milliseconds::zero());
if (elapsed == d->elapsed) {
return;
}
reset();
d->elapsed = elapsed;
if (d->elapsed >= d->duration) {
d->elapsed = d->duration;
d->done = true;
d->lastTimestamp = std::nullopt;
}
}
std::chrono::milliseconds TimeLine::duration() const
{
return d->duration;
}
void TimeLine::setDuration(std::chrono::milliseconds duration)
{
Q_ASSERT(duration > std::chrono::milliseconds::zero());
if (duration == d->duration) {
return;
}
d->elapsed = std::chrono::milliseconds(qRound(progress() * duration.count()));
d->duration = duration;
if (d->elapsed == d->duration) {
d->done = true;
d->lastTimestamp = std::nullopt;
}
}
TimeLine::Direction TimeLine::direction() const
{
return d->direction;
}
void TimeLine::setDirection(TimeLine::Direction direction)
{
if (d->direction == direction) {
return;
}
d->direction = direction;
if (d->elapsed > std::chrono::milliseconds::zero()
|| d->sourceRedirectMode == RedirectMode::Strict) {
d->elapsed = d->duration - d->elapsed;
}
if (d->done && d->targetRedirectMode == RedirectMode::Relaxed) {
d->done = false;
}
if (d->elapsed >= d->duration) {
d->done = true;
d->lastTimestamp = std::nullopt;
}
}
void TimeLine::toggleDirection()
{
setDirection(d->direction == Forward ? Backward : Forward);
}
QEasingCurve TimeLine::easingCurve() const
{
return d->easingCurve;
}
void TimeLine::setEasingCurve(const QEasingCurve &easingCurve)
{
d->easingCurve = easingCurve;
}
void TimeLine::setEasingCurve(QEasingCurve::Type type)
{
d->easingCurve.setType(type);
}
bool TimeLine::running() const
{
return d->elapsed != std::chrono::milliseconds::zero()
&& d->elapsed != d->duration;
}
bool TimeLine::done() const
{
return d->done;
}
void TimeLine::reset()
{
d->lastTimestamp = std::nullopt;
d->elapsed = std::chrono::milliseconds::zero();
d->done = false;
}
TimeLine::RedirectMode TimeLine::sourceRedirectMode() const
{
return d->sourceRedirectMode;
}
void TimeLine::setSourceRedirectMode(RedirectMode mode)
{
d->sourceRedirectMode = mode;
}
TimeLine::RedirectMode TimeLine::targetRedirectMode() const
{
return d->targetRedirectMode;
}
void TimeLine::setTargetRedirectMode(RedirectMode mode)
{
d->targetRedirectMode = mode;
}
TimeLine &TimeLine::operator=(const TimeLine &other)
{
d = other.d;
return *this;
}
} // namespace KWin

View file

@ -0,0 +1,270 @@
/*
SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "kwin_export.h"
#include <QEasingCurve>
#include <QSharedDataPointer>
#include <chrono>
namespace KWin
{
/**
* The TimeLine class is a helper for controlling animations.
*/
class KWIN_EXPORT TimeLine
{
public:
/**
* Direction of the timeline.
*
* When the direction of the timeline is Forward, the progress
* value will go from 0.0 to 1.0.
*
* When the direction of the timeline is Backward, the progress
* value will go from 1.0 to 0.0.
*/
enum Direction {
Forward,
Backward
};
/**
* Constructs a new instance of TimeLine.
*
* @param duration Duration of the timeline, in milliseconds
* @param direction Direction of the timeline
* @since 5.14
*/
explicit TimeLine(std::chrono::milliseconds duration = std::chrono::milliseconds(1000),
Direction direction = Forward);
TimeLine(const TimeLine &other);
~TimeLine();
/**
* Returns the current value of the timeline.
*
* @since 5.14
*/
qreal value() const;
/**
* Advances the timeline to the specified @a timestamp.
*/
void advance(std::chrono::milliseconds timestamp);
/**
* Returns the number of elapsed milliseconds.
*
* @see setElapsed
* @since 5.14
*/
std::chrono::milliseconds elapsed() const;
/**
* Sets the number of elapsed milliseconds.
*
* This method overwrites previous value of elapsed milliseconds.
* If the new value of elapsed milliseconds is greater or equal
* to duration of the timeline, the timeline will be finished, i.e.
* proceeding TimeLine::done method calls will return @c true.
* Please don't use it. Instead, use TimeLine::update.
*
* @note The new number of elapsed milliseconds should be a non-negative
* number, i.e. it should be greater or equal to 0.
*
* @param elapsed The new number of elapsed milliseconds
* @see elapsed
* @since 5.14
*/
void setElapsed(std::chrono::milliseconds elapsed);
/**
* Returns the duration of the timeline.
*
* @returns Duration of the timeline, in milliseconds
* @see setDuration
* @since 5.14
*/
std::chrono::milliseconds duration() const;
/**
* Sets the duration of the timeline.
*
* In addition to setting new value of duration, the timeline will
* try to retarget the number of elapsed milliseconds to match
* as close as possible old progress value. If the new duration
* is much smaller than old duration, there is a big chance that
* the timeline will be finished after setting new duration.
*
* @note The new duration should be a positive number, i.e. it
* should be greater or equal to 1.
*
* @param duration The new duration of the timeline, in milliseconds
* @see duration
* @since 5.14
*/
void setDuration(std::chrono::milliseconds duration);
/**
* Returns the direction of the timeline.
*
* @returns Direction of the timeline(TimeLine::Forward or TimeLine::Backward)
* @see setDirection
* @see toggleDirection
* @since 5.14
*/
Direction direction() const;
/**
* Sets the direction of the timeline.
*
* @param direction The new direction of the timeline
* @see direction
* @see toggleDirection
* @since 5.14
*/
void setDirection(Direction direction);
/**
* Toggles the direction of the timeline.
*
* If the direction of the timeline was TimeLine::Forward, it becomes
* TimeLine::Backward, and vice verca.
*
* @see direction
* @see setDirection
* @since 5.14
*/
void toggleDirection();
/**
* Returns the easing curve of the timeline.
*
* @see setEasingCurve
* @since 5.14
*/
QEasingCurve easingCurve() const;
/**
* Sets new easing curve.
*
* @param easingCurve An easing curve to be set
* @see easingCurve
* @since 5.14
*/
void setEasingCurve(const QEasingCurve &easingCurve);
/**
* Sets new easing curve by providing its type.
*
* @param type Type of the easing curve(e.g. QEasingCurve::InCubic, etc)
* @see easingCurve
* @since 5.14
*/
void setEasingCurve(QEasingCurve::Type type);
/**
* Returns whether the timeline is currently in progress.
*
* @see done
* @since 5.14
*/
bool running() const;
/**
* Returns whether the timeline is finished.
*
* @see reset
* @since 5.14
*/
bool done() const;
/**
* Resets the timeline to initial state.
*
* @since 5.14
*/
void reset();
enum class RedirectMode {
Strict,
Relaxed
};
/**
* Returns the redirect mode for the source position.
*
* The redirect mode controls behavior of the timeline when its direction is
* changed at the source position, e.g. what should we do when the timeline
* initially goes forward and we change its direction to go backward.
*
* In the strict mode, the timeline will stop.
*
* In the relaxed mode, the timeline will go in the new direction. For example,
* if the timeline goes forward(from 0 to 1), then with the new direction it
* will go backward(from 1 to 0).
*
* The default is RedirectMode::Relaxed.
*
* @see targetRedirectMode
* @since 5.15
*/
RedirectMode sourceRedirectMode() const;
/**
* Sets the redirect mode for the source position.
*
* @param mode The new mode.
* @since 5.15
*/
void setSourceRedirectMode(RedirectMode mode);
/**
* Returns the redirect mode for the target position.
*
* The redirect mode controls behavior of the timeline when its direction is
* changed at the target position.
*
* In the strict mode, subsequent update calls won't have any effect on the
* current value of the timeline.
*
* In the relaxed mode, the timeline will go in the new direction.
*
* The default is RedirectMode::Strict.
*
* @see sourceRedirectMode
* @since 5.15
*/
RedirectMode targetRedirectMode() const;
/**
* Sets the redirect mode for the target position.
*
* @param mode The new mode.
* @since 5.15
*/
void setTargetRedirectMode(RedirectMode mode);
TimeLine &operator=(const TimeLine &other);
/**
* @returns a value between 0 and 1 defining the progress of the timeline
*
* @since 5.23
*/
qreal progress() const;
private:
class Data;
QSharedDataPointer<Data> d;
};
} // namespace KWin

View file

@ -9,6 +9,7 @@
#pragma once
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/kwinoffscreeneffect.h"
#include "libkwineffects/timeline.h"
#include <chrono>
namespace KWin

View file

@ -13,6 +13,7 @@
// kwineffects
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/timeline.h"
namespace KWin
{

View file

@ -14,6 +14,7 @@
// kwineffects
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/timeline.h"
namespace KWin
{

View file

@ -9,6 +9,7 @@
#pragma once
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/timeline.h"
namespace KWin
{

View file

@ -10,6 +10,7 @@
#pragma once
#include "libkwineffects/kwinoffscreeneffect.h"
#include "libkwineffects/timeline.h"
namespace KWin
{

View file

@ -10,6 +10,7 @@
#include "core/output.h"
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/timeline.h"
namespace KWin
{

View file

@ -13,6 +13,7 @@
// kwineffects
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/timeline.h"
namespace KWin
{

View file

@ -12,6 +12,7 @@
// Include with base class for effects.
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/timeline.h"
namespace KWin
{

View file

@ -11,6 +11,7 @@
#pragma once
#include "libkwineffects/kwineffects.h"
#include "libkwineffects/timeline.h"
namespace KWin
{