Don't restart animations timer.

This commit is contained in:
John Preston 2019-04-09 14:17:58 +04:00
parent 7808620764
commit 392d90dc1d
2 changed files with 55 additions and 58 deletions

View File

@ -14,7 +14,7 @@ namespace Ui {
namespace Animations {
namespace {
constexpr auto kAnimationTimeout = crl::time(1000) / 60;
constexpr auto kAnimationTick = crl::time(1000) / 60;
constexpr auto kIgnoreUpdatesTimeout = crl::time(4);
} // namespace
@ -53,21 +53,22 @@ void Basic::markStopped() {
Manager::Manager() {
Core::Sandbox::Instance().widgetUpdateRequests(
) | rpl::filter([=] {
/*) | rpl::filter([=] {
return (_lastUpdateTime + kIgnoreUpdatesTimeout < crl::now());
}) | rpl::start_with_next([=] {
update();
}*/) | rpl::start_with_next([=] {
update(UpdateSource::RepaintRequest);
}, _lifetime);
}
void Manager::start(not_null<Basic*> animation) {
_forceImmediateUpdate = true;
_forceUpdateProcessing = true;
if (_updating) {
_starting.emplace_back(animation.get());
} else {
schedule();
_active.emplace_back(animation.get());
return;
}
_active.emplace_back(animation.get());
startTimer();
updateQueued();
}
void Manager::stop(not_null<Basic*> animation) {
@ -89,15 +90,16 @@ void Manager::stop(not_null<Basic*> animation) {
}
}
void Manager::update() {
if (_active.empty() || _updating || _scheduled) {
void Manager::update(UpdateSource source) {
if (_active.empty() || _updating) {
return;
}
const auto now = crl::now();
if (_forceImmediateUpdate) {
_forceImmediateUpdate = false;
if (_forceUpdateProcessing) {
_forceUpdateProcessing = false;
} else if (now < _lastUpdateTime + kIgnoreUpdatesTimeout) {
return;
}
schedule();
_updating = true;
const auto guard = gsl::finally([&] { _updating = false; });
@ -108,48 +110,30 @@ void Manager::update() {
};
_active.erase(ranges::remove_if(_active, isFinished), end(_active));
if (!empty(_starting)) {
_active.insert(
end(_active),
std::make_move_iterator(begin(_starting)),
std::make_move_iterator(end(_starting)));
_starting.clear();
if (empty(_starting)) {
if (empty(_active)) {
stopTimer();
}
return;
}
_active.insert(
end(_active),
std::make_move_iterator(begin(_starting)),
std::make_move_iterator(end(_starting)));
_starting.clear();
if (_forceUpdateProcessing) {
updateQueued();
}
}
void Manager::updateQueued() {
Expects(_timerId == 0);
_timerId = -1;
crl::on_main(delayedCallGuard(), [=] {
Expects(_timerId < 0);
_timerId = 0;
update();
});
}
void Manager::schedule() {
if (_scheduled || _timerId < 0) {
if (_queued) {
return;
}
stopTimer();
_scheduled = true;
Ui::PostponeCall(delayedCallGuard(), [=] {
_scheduled = false;
if (_forceImmediateUpdate) {
_forceImmediateUpdate = false;
updateQueued();
} else {
const auto next = _lastUpdateTime + kAnimationTimeout;
const auto now = crl::now();
if (now < next) {
_timerId = startTimer(next - now, Qt::PreciseTimer);
} else {
updateQueued();
}
}
_queued = true;
crl::on_main(delayedCallGuard(), [=] {
_queued = false;
update(UpdateSource::Queued);
});
}
@ -157,14 +141,22 @@ not_null<const QObject*> Manager::delayedCallGuard() const {
return static_cast<const QObject*>(this);
}
void Manager::stopTimer() {
if (_timerId > 0) {
killTimer(base::take(_timerId));
void Manager::startTimer() {
if (_timerId) {
return;
}
_timerId = QObject::startTimer(kAnimationTick, Qt::PreciseTimer);
}
void Manager::stopTimer() {
if (!_timerId) {
return;
}
killTimer(base::take(_timerId));
}
void Manager::timerEvent(QTimerEvent *e) {
update();
update(UpdateSource::TimerEvent);
}
} // namespace Animations

View File

@ -101,9 +101,13 @@ class Manager final : private QObject {
public:
Manager();
void update();
private:
enum class UpdateSource {
Queued,
TimerEvent,
RepaintRequest,
};
class ActiveBasicPointer {
public:
ActiveBasicPointer(Basic *value = nullptr) : _value(value) {
@ -151,20 +155,21 @@ private:
friend class Basic;
void timerEvent(QTimerEvent *e) override;
void update(UpdateSource source);
void start(not_null<Basic*> animation);
void stop(not_null<Basic*> animation);
void schedule();
void updateQueued();
void startTimer();
void stopTimer();
not_null<const QObject*> delayedCallGuard() const;
crl::time _lastUpdateTime = 0;
int _timerId = 0;
bool _updating = false;
bool _scheduled = false;
bool _forceImmediateUpdate = false;
bool _queued = false;
bool _forceUpdateProcessing = false;
std::vector<ActiveBasicPointer> _active;
std::vector<ActiveBasicPointer> _starting;
rpl::lifetime _lifetime;