diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index f682bde..73eee7a 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -1,7 +1,8 @@ #include "Timer.hpp" -CTimer::CTimer(std::chrono::system_clock::duration timeout, std::function self, void* data)> cb_, void* data_) : cb(cb_), data(data_) { - expires = std::chrono::system_clock::now() + timeout; +CTimer::CTimer(std::chrono::system_clock::duration timeout, std::function self, void* data)> cb_, void* data_, bool force) : cb(cb_), data(data_) { + expires = std::chrono::system_clock::now() + timeout; + allowForceUpdate = force; } bool CTimer::passed() { @@ -22,4 +23,8 @@ void CTimer::call(std::shared_ptr self) { float CTimer::leftMs() { return std::chrono::duration_cast(expires - std::chrono::system_clock::now()).count(); -} \ No newline at end of file +} + +bool CTimer::canForceUpdate() { + return allowForceUpdate; +} diff --git a/src/core/Timer.hpp b/src/core/Timer.hpp index 3028674..a7a5a3d 100644 --- a/src/core/Timer.hpp +++ b/src/core/Timer.hpp @@ -5,10 +5,11 @@ class CTimer { public: - CTimer(std::chrono::system_clock::duration timeout, std::function self, void* data)> cb_, void* data_); + CTimer(std::chrono::system_clock::duration timeout, std::function self, void* data)> cb_, void* data_, bool force); void cancel(); bool passed(); + bool canForceUpdate(); float leftMs(); @@ -19,5 +20,6 @@ class CTimer { std::function self, void* data)> cb; void* data = nullptr; std::chrono::system_clock::time_point expires; - bool wasCancelled = false; -}; \ No newline at end of file + bool wasCancelled = false; + bool allowForceUpdate = false; +}; diff --git a/src/core/hyprlock.cpp b/src/core/hyprlock.cpp index 6b8ceb2..f13a174 100644 --- a/src/core/hyprlock.cpp +++ b/src/core/hyprlock.cpp @@ -307,6 +307,17 @@ static void handleUnlockSignal(int sig) { } } +static void handleForceUpdateSignal(int sig) { + if (sig == SIGUSR2) { + for (auto& t : g_pHyprlock->getTimers()) { + if (t->canForceUpdate()) { + t->call(t); + t->cancel(); + } + } + } +} + static void handlePollTerminate(int sig) { ; } @@ -355,7 +366,8 @@ void CHyprlock::run() { lockSession(); registerSignalAction(SIGUSR1, handleUnlockSignal, SA_RESTART); - registerSignalAction(SIGUSR2, handlePollTerminate); + registerSignalAction(SIGUSR2, handleForceUpdateSignal); + registerSignalAction(SIGRTMIN, handlePollTerminate); registerSignalAction(SIGSEGV, handleCriticalSignal); registerSignalAction(SIGABRT, handleCriticalSignal); @@ -371,7 +383,7 @@ void CHyprlock::run() { int ret = poll(pollfds, 1, 5000 /* 5 seconds, reasonable. Just in case we need to terminate and the signal fails */); if (ret < 0) { - if (errno == EINTR) + if (errno == EINTR) continue; Debug::log(CRIT, "[core] Polling fds failed with {}", errno); @@ -493,7 +505,7 @@ void CHyprlock::run() { wl_display_disconnect(m_sWaylandState.display); - pthread_kill(pollThr.native_handle(), SIGUSR2); + pthread_kill(pollThr.native_handle(), SIGRTMIN); // wait for threads to exit cleanly to avoid a coredump pollThr.join(); @@ -834,14 +846,19 @@ size_t CHyprlock::getPasswordFailedAttempts() { return m_sPasswordState.failedAttempts; } -std::shared_ptr CHyprlock::addTimer(const std::chrono::system_clock::duration& timeout, std::function self, void* data)> cb_, void* data) { +std::shared_ptr CHyprlock::addTimer(const std::chrono::system_clock::duration& timeout, std::function self, void* data)> cb_, void* data, + bool force) { std::lock_guard lg(m_sLoopState.timersMutex); - const auto T = m_vTimers.emplace_back(std::make_shared(timeout, cb_, data)); + const auto T = m_vTimers.emplace_back(std::make_shared(timeout, cb_, data, force)); m_sLoopState.timerEvent = true; m_sLoopState.timerCV.notify_all(); return T; } +std::vector> CHyprlock::getTimers() { + return m_vTimers; +} + void CHyprlock::spawnAsync(const std::string& args) { Debug::log(LOG, "Executing (async) {}", args); diff --git a/src/core/hyprlock.hpp b/src/core/hyprlock.hpp index 9dc5425..9841a5c 100644 --- a/src/core/hyprlock.hpp +++ b/src/core/hyprlock.hpp @@ -35,7 +35,8 @@ class CHyprlock { void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version); void onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name); - std::shared_ptr addTimer(const std::chrono::system_clock::duration& timeout, std::function self, void* data)> cb_, void* data); + std::shared_ptr addTimer(const std::chrono::system_clock::duration& timeout, std::function self, void* data)> cb_, void* data, + bool force = false); void onLockLocked(); void onLockFinished(); @@ -83,6 +84,7 @@ class CHyprlock { Vector2D m_vLastEnterCoords = {}; std::vector> m_vOutputs; + std::vector> getTimers(); struct { void* linuxDmabuf = nullptr; diff --git a/src/renderer/widgets/IWidget.cpp b/src/renderer/widgets/IWidget.cpp index 92a6161..aaa5e27 100644 --- a/src/renderer/widgets/IWidget.cpp +++ b/src/renderer/widgets/IWidget.cpp @@ -79,6 +79,11 @@ IWidget::SFormatResult IWidget::formatString(std::string in) { for (const auto& v : vars) { if (v.starts_with("update:")) { try { + if (v.substr(7).contains(':')) { + auto str = v.substr(v.substr(7).find_first_of(':') + 8); + result.allowForceUpdate = str == "true" || std::stoull(str) == 1; + } + result.updateEveryMs = std::stoull(v.substr(7)); } catch (std::exception& e) { Debug::log(ERR, "Error parsing {} in cmd[]", v); } } else { @@ -93,4 +98,4 @@ IWidget::SFormatResult IWidget::formatString(std::string in) { result.formatted = in; return result; -} \ No newline at end of file +} diff --git a/src/renderer/widgets/IWidget.hpp b/src/renderer/widgets/IWidget.hpp index e81b53a..8886ab2 100644 --- a/src/renderer/widgets/IWidget.hpp +++ b/src/renderer/widgets/IWidget.hpp @@ -15,10 +15,11 @@ class IWidget { struct SFormatResult { std::string formatted; - float updateEveryMs = 0; // 0 means don't (static) - bool alwaysUpdate = false; - bool cmd = false; + float updateEveryMs = 0; // 0 means don't (static) + bool alwaysUpdate = false; + bool cmd = false; + bool allowForceUpdate = false; }; virtual SFormatResult formatString(std::string in); -}; \ No newline at end of file +}; diff --git a/src/renderer/widgets/Label.cpp b/src/renderer/widgets/Label.cpp index 04530b5..f8b3cc8 100644 --- a/src/renderer/widgets/Label.cpp +++ b/src/renderer/widgets/Label.cpp @@ -53,7 +53,9 @@ void CLabel::onTimerUpdate() { void CLabel::plantTimer() { if (label.updateEveryMs != 0) - labelTimer = g_pHyprlock->addTimer(std::chrono::milliseconds((int)label.updateEveryMs), onTimer, this); + labelTimer = g_pHyprlock->addTimer(std::chrono::milliseconds((int)label.updateEveryMs), onTimer, this, label.allowForceUpdate); + else if (label.updateEveryMs == 0 && label.allowForceUpdate) + labelTimer = g_pHyprlock->addTimer(std::chrono::hours(1), onTimer, this, true); } CLabel::CLabel(const Vector2D& viewport_, const std::unordered_map& props, const std::string& output) : @@ -139,4 +141,4 @@ void CLabel::renderSuper() { if (!pendingResourceID.empty()) /* did not consume the pending resource */ g_pHyprlock->addTimer(std::chrono::milliseconds(100), onAssetCallbackTimer, this); -} \ No newline at end of file +}