forked from quickshell/quickshell
		
	core/clock: fix instability causing timer to fire multiple times
If the signal was fired slightly before the scheduled time, it would schedule itself again a couple ms in the future.
This commit is contained in:
		
							parent
							
								
									a4903eaefc
								
							
						
					
					
						commit
						9555b201fe
					
				
					 2 changed files with 58 additions and 30 deletions
				
			
		| 
						 | 
				
			
			@ -8,7 +8,7 @@
 | 
			
		|||
#include "util.hpp"
 | 
			
		||||
 | 
			
		||||
SystemClock::SystemClock(QObject* parent): QObject(parent) {
 | 
			
		||||
	QObject::connect(&this->timer, &QTimer::timeout, this, &SystemClock::update);
 | 
			
		||||
	QObject::connect(&this->timer, &QTimer::timeout, this, &SystemClock::onTimeout);
 | 
			
		||||
	this->update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -30,10 +30,21 @@ void SystemClock::setPrecision(SystemClock::Enum precision) {
 | 
			
		|||
	this->update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SystemClock::update() {
 | 
			
		||||
	auto time = QTime::currentTime();
 | 
			
		||||
void SystemClock::onTimeout() {
 | 
			
		||||
	this->setTime(this->nextTime);
 | 
			
		||||
	this->schedule(this->nextTime);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SystemClock::update() {
 | 
			
		||||
	if (this->mEnabled) {
 | 
			
		||||
		this->setTime(QTime::currentTime());
 | 
			
		||||
		this->schedule(QTime::currentTime());
 | 
			
		||||
	} else {
 | 
			
		||||
		this->timer.stop();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SystemClock::setTime(QTime time) {
 | 
			
		||||
	auto secondPrecision = this->mPrecision >= SystemClock::Seconds;
 | 
			
		||||
	auto secondChanged = this->setSeconds(secondPrecision ? time.second() : 0);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -44,25 +55,36 @@ void SystemClock::update() {
 | 
			
		|||
	auto hourChanged = this->setHours(hourPrecision ? time.hour() : 0);
 | 
			
		||||
 | 
			
		||||
	DropEmitter::call(secondChanged, minuteChanged, hourChanged);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SystemClock::schedule(QTime floor) {
 | 
			
		||||
	auto secondPrecision = this->mPrecision >= SystemClock::Seconds;
 | 
			
		||||
	auto minutePrecision = this->mPrecision >= SystemClock::Minutes;
 | 
			
		||||
	auto hourPrecision = this->mPrecision >= SystemClock::Hours;
 | 
			
		||||
 | 
			
		||||
setnext:
 | 
			
		||||
	auto nextTime = QTime(
 | 
			
		||||
		    hourPrecision ? time.hour() : 0,
 | 
			
		||||
		    minutePrecision ? time.minute() : 0,
 | 
			
		||||
		    secondPrecision ? time.second() : 0
 | 
			
		||||
	    hourPrecision ? floor.hour() : 0,
 | 
			
		||||
	    minutePrecision ? floor.minute() : 0,
 | 
			
		||||
	    secondPrecision ? floor.second() : 0
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	if (secondPrecision) nextTime = nextTime.addSecs(1);
 | 
			
		||||
	else if (minutePrecision) nextTime = nextTime.addSecs(60);
 | 
			
		||||
	else if (hourPrecision) nextTime = nextTime.addSecs(3600);
 | 
			
		||||
 | 
			
		||||
		auto delay = time.msecsTo(nextTime);
 | 
			
		||||
		// day rollover
 | 
			
		||||
		if (delay < 0) delay += 86400000;
 | 
			
		||||
	auto delay = QTime::currentTime().msecsTo(nextTime);
 | 
			
		||||
 | 
			
		||||
	// If off by more than 2 hours we likely wrapped around midnight.
 | 
			
		||||
	if (delay < -7200000) delay += 86400000;
 | 
			
		||||
	else if (delay < 0) {
 | 
			
		||||
		// Otherwise its just the timer being unstable.
 | 
			
		||||
		floor = QTime::currentTime();
 | 
			
		||||
		goto setnext;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this->timer.start(delay);
 | 
			
		||||
	} else {
 | 
			
		||||
		this->timer.stop();
 | 
			
		||||
	}
 | 
			
		||||
	this->nextTime = nextTime;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFINE_MEMBER_GETSET(SystemClock, hours, setHours);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,6 @@
 | 
			
		|||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <qdatetime.h>
 | 
			
		||||
#include <qobject.h>
 | 
			
		||||
#include <qqmlintegration.h>
 | 
			
		||||
#include <qtimer.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -49,7 +50,7 @@ signals:
 | 
			
		|||
	void secondsChanged();
 | 
			
		||||
 | 
			
		||||
private slots:
 | 
			
		||||
	void update();
 | 
			
		||||
	void onTimeout();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	bool mEnabled = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +59,11 @@ private:
 | 
			
		|||
	quint32 mMinutes = 0;
 | 
			
		||||
	quint32 mSeconds = 0;
 | 
			
		||||
	QTimer timer;
 | 
			
		||||
	QTime nextTime;
 | 
			
		||||
 | 
			
		||||
	void update();
 | 
			
		||||
	void setTime(QTime time);
 | 
			
		||||
	void schedule(QTime floor);
 | 
			
		||||
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(SystemClock, hours, setHours, mHours, hoursChanged);
 | 
			
		||||
	DECLARE_PRIVATE_MEMBER(SystemClock, minutes, setMinutes, mMinutes, minutesChanged);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue