diff --git a/src/debug/HyprNotificationOverlay.hpp b/src/debug/HyprNotificationOverlay.hpp index b04cb73bc..cc4ebcc61 100644 --- a/src/debug/HyprNotificationOverlay.hpp +++ b/src/debug/HyprNotificationOverlay.hpp @@ -1,7 +1,7 @@ #pragma once #include "../defines.hpp" -#include "../helpers/Timer.hpp" +#include "../helpers/time/Timer.hpp" #include "../render/Texture.hpp" #include "../SharedDefs.hpp" diff --git a/src/desktop/Window.cpp b/src/desktop/Window.cpp index 323aa03a4..059453f4d 100644 --- a/src/desktop/Window.cpp +++ b/src/desktop/Window.cpp @@ -417,10 +417,10 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { if (TOKEN) { if (*PINITIALWSTRACKING == 2) { // persistent - SInitialWorkspaceToken token = std::any_cast(TOKEN->data); + SInitialWorkspaceToken token = std::any_cast(TOKEN->m_data); if (token.primaryOwner == m_pSelf) { token.workspace = pWorkspace->getConfigName(); - TOKEN->data = token; + TOKEN->m_data = token; } } } @@ -507,7 +507,7 @@ void CWindow::onUnmap() { if (TOKEN) { if (*PINITIALWSTRACKING == 2) { // persistent token, but the first window got removed so the token is gone - SInitialWorkspaceToken token = std::any_cast(TOKEN->data); + SInitialWorkspaceToken token = std::any_cast(TOKEN->m_data); if (token.primaryOwner == m_pSelf) g_pTokenManager->removeToken(TOKEN); } diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 452e977dc..2d8bdc351 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -85,7 +85,7 @@ void Events::listener_mapWindow(void* owner, void* data) { const auto TOKEN = g_pTokenManager->getToken(SZTOKEN); if (TOKEN) { // find workspace and use it - SInitialWorkspaceToken WS = std::any_cast(TOKEN->data); + SInitialWorkspaceToken WS = std::any_cast(TOKEN->m_data); Debug::log(LOG, "HL_INITIAL_WORKSPACE_TOKEN {} -> {}", SZTOKEN, WS.workspace); @@ -99,7 +99,7 @@ void Events::listener_mapWindow(void* owner, void* data) { else if (*PINITIALWSTRACKING == 2) { // persistent if (WS.primaryOwner.expired()) { WS.primaryOwner = PWINDOW; - TOKEN->data = WS; + TOKEN->m_data = WS; } PWINDOW->m_szInitialWorkspaceToken = SZTOKEN; diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 0a16643ec..5e2fedd57 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -24,6 +24,7 @@ #include "../managers/LayoutManager.hpp" #include "../managers/input/InputManager.hpp" #include "sync/SyncTimeline.hpp" +#include "time/Time.hpp" #include "../desktop/LayerSurface.hpp" #include #include "debug/Log.hpp" @@ -32,6 +33,7 @@ #include #include #include + using namespace Hyprutils::String; using namespace Hyprutils::Utils; using namespace Hyprutils::OS; @@ -72,8 +74,15 @@ void CMonitor::onConnect(bool noRule) { output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); listeners.presented = output->events.present.registerListener([this](std::any d) { - auto E = std::any_cast(d); - PROTO::presentation->onPresented(self.lock(), E.when, E.refresh, E.seq, E.flags); + auto E = std::any_cast(d); + + timespec* ts = E.when; + if (!ts) { + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + PROTO::presentation->onPresented(self.lock(), Time::fromTimespec(&now), E.refresh, E.seq, E.flags); + } else + PROTO::presentation->onPresented(self.lock(), Time::fromTimespec(E.when), E.refresh, E.seq, E.flags); }); listeners.destroy = output->events.destroy.registerListener([this](std::any d) { @@ -1377,9 +1386,7 @@ bool CMonitor::attemptDirectScanout() { auto PBUFFER = PSURFACE->current.buffer.buffer; if (PBUFFER == output->state->state().buffer) { - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - PSURFACE->presentFeedback(&now, self.lock()); + PSURFACE->presentFeedback(Time::steadyNow(), self.lock()); if (scanoutNeedsCursorUpdate) { if (!state.test()) { @@ -1420,9 +1427,7 @@ bool CMonitor::attemptDirectScanout() { return false; } - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - PSURFACE->presentFeedback(&now, self.lock()); + PSURFACE->presentFeedback(Time::steadyNow(), self.lock()); output->state->addDamage(PSURFACE->current.accumulateBufferDamage()); output->state->resetExplicitFences(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index a7d97c8d6..2ce6b626a 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -9,7 +9,7 @@ #include #include -#include "Timer.hpp" +#include "time/Timer.hpp" #include "math/Math.hpp" #include #include "../protocols/types/ColorManagement.hpp" diff --git a/src/helpers/Timer.cpp b/src/helpers/Timer.cpp deleted file mode 100644 index e00c5918f..000000000 --- a/src/helpers/Timer.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "Timer.hpp" -#include - -void CTimer::reset() { - m_tpLastReset = std::chrono::steady_clock::now(); -} - -std::chrono::steady_clock::duration CTimer::getDuration() { - return std::chrono::steady_clock::now() - m_tpLastReset; -} - -float CTimer::getMillis() { - return std::chrono::duration_cast(getDuration()).count() / 1000.f; -} - -float CTimer::getSeconds() { - return std::chrono::duration_cast(getDuration()).count() / 1000.f; -} - -const std::chrono::steady_clock::time_point& CTimer::chrono() const { - return m_tpLastReset; -} \ No newline at end of file diff --git a/src/helpers/Timer.hpp b/src/helpers/Timer.hpp deleted file mode 100644 index a58225d08..000000000 --- a/src/helpers/Timer.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -class CTimer { - public: - void reset(); - float getSeconds(); - float getMillis(); - const std::chrono::steady_clock::time_point& chrono() const; - - private: - std::chrono::steady_clock::time_point m_tpLastReset; - - std::chrono::steady_clock::duration getDuration(); -}; \ No newline at end of file diff --git a/src/helpers/time/Time.cpp b/src/helpers/time/Time.cpp new file mode 100644 index 000000000..791f5ea11 --- /dev/null +++ b/src/helpers/time/Time.cpp @@ -0,0 +1,139 @@ +#include "Time.hpp" + +#define chr std::chrono +#define TIMESPEC_NSEC_PER_SEC 1000000000L + +using s_ns = std::pair; + +// HAS to be a > b +static s_ns timediff(const s_ns& a, const s_ns& b) { + s_ns d; + + d.first = a.first - b.first; + if (a.second >= b.second) + d.second = a.second - b.second; + else { + d.second = b.second - a.second; + d.first -= 1; + } + + return d; +} + +static s_ns timeadd(const s_ns& a, const s_ns& b) { + s_ns d; + + d.first = a.first + b.first; + if (a.second + b.second >= TIMESPEC_NSEC_PER_SEC) { + d.second = a.second + b.second - TIMESPEC_NSEC_PER_SEC; + d.first += 1; + } else + d.second = a.second + b.second; + + return d; +} + +Time::steady_tp Time::steadyNow() { + return chr::steady_clock::now(); +} + +Time::system_tp Time::systemNow() { + return chr::system_clock::now(); +} + +uint64_t Time::millis(const steady_tp& tp) { + return chr::duration_cast(tp.time_since_epoch()).count(); +} + +s_ns Time::secNsec(const steady_tp& tp) { + const uint64_t sec = chr::duration_cast(tp.time_since_epoch()).count(); + const chr::steady_clock::duration nsecdur = tp - chr::steady_clock::time_point(chr::seconds(sec)); + return std::make_pair<>(sec, chr::duration_cast(nsecdur).count()); +} + +uint64_t Time::millis(const system_tp& tp) { + return chr::duration_cast(tp.time_since_epoch()).count(); +} + +s_ns Time::secNsec(const system_tp& tp) { + const uint64_t sec = chr::duration_cast(tp.time_since_epoch()).count(); + const chr::steady_clock::duration nsecdur = tp - chr::system_clock::time_point(chr::seconds(sec)); + return std::make_pair<>(sec, chr::duration_cast(nsecdur).count()); +} + +// TODO: this is a mess, but C++ doesn't define what steady_clock is. +// At least on Linux, system_clock == CLOCK_REALTIME +// and steady_clock == CLOCK_MONOTONIC, +// or at least it seems so with gcc and gcc's stl. +// but, since we can't *ever* be sure, we have to guess. +// In general, this may shift the time around by a couple hundred ns. Doesn't matter, realistically. + +Time::steady_tp Time::fromTimespec(const timespec* ts) { + struct timespec mono, real; + clock_gettime(CLOCK_MONOTONIC, &mono); + clock_gettime(CLOCK_REALTIME, &real); + Time::steady_tp now = Time::steadyNow(); + Time::system_tp nowSys = Time::systemNow(); + s_ns stdSteady, stdReal; + stdSteady = Time::secNsec(now); + stdReal = Time::secNsec(nowSys); + + // timespec difference, REAL - MONO + s_ns diff; + diff.first = real.tv_sec - mono.tv_sec; + if (real.tv_nsec >= mono.tv_nsec) + diff.second = real.tv_nsec - mono.tv_nsec; + else { + diff.second = mono.tv_nsec - real.tv_nsec; + diff.first -= 1; + } + + // STD difference, REAL - MONO + s_ns diff2 = timediff(stdReal, stdSteady); + + s_ns diffFinal; + s_ns monotime = {ts->tv_sec, ts->tv_nsec}; + + if (diff.first >= diff2.first || (diff.first == diff2.first && diff.second >= diff2.second)) + diffFinal = timediff(diff, diff2); + else + diffFinal = timediff(diff2, diff); + + auto sum = timeadd(monotime, diffFinal); + return chr::steady_clock::time_point(std::chrono::seconds(sum.first)) + chr::nanoseconds(sum.second); +} + +struct timespec Time::toTimespec(const steady_tp& tp) { + struct timespec mono, real; + clock_gettime(CLOCK_MONOTONIC, &mono); + clock_gettime(CLOCK_REALTIME, &real); + Time::steady_tp now = Time::steadyNow(); + Time::system_tp nowSys = Time::systemNow(); + s_ns stdSteady, stdReal; + stdSteady = Time::secNsec(now); + stdReal = Time::secNsec(nowSys); + + // timespec difference, REAL - MONO + s_ns diff; + diff.first = real.tv_sec - mono.tv_sec; + if (real.tv_nsec >= mono.tv_nsec) + diff.second = real.tv_nsec - mono.tv_nsec; + else { + diff.second = mono.tv_nsec - real.tv_nsec; + diff.first -= 1; + } + + // STD difference, REAL - MONO + s_ns diff2 = timediff(stdReal, stdSteady); + + s_ns diffFinal; + s_ns tpTime = secNsec(tp); + + if (diff.first >= diff2.first || (diff.first == diff2.first && diff.second >= diff2.second)) + diffFinal = timediff(diff, diff2); + else + diffFinal = timediff(diff2, diff); + + auto sum = timeadd(tpTime, diffFinal); + return timespec{.tv_sec = sum.first, .tv_nsec = sum.second}; +} diff --git a/src/helpers/time/Time.hpp b/src/helpers/time/Time.hpp new file mode 100644 index 000000000..eb3b57715 --- /dev/null +++ b/src/helpers/time/Time.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include +#include + +//NOLINTNEXTLINE +namespace Time { + using steady_tp = std::chrono::steady_clock::time_point; + using system_tp = std::chrono::system_clock::time_point; + using steady_dur = std::chrono::steady_clock::duration; + using system_dur = std::chrono::system_clock::duration; + + steady_tp steadyNow(); + system_tp systemNow(); + + steady_tp fromTimespec(const timespec*); + struct timespec toTimespec(const steady_tp& tp); + + uint64_t millis(const steady_tp& tp); + uint64_t millis(const system_tp& tp); + std::pair secNsec(const steady_tp& tp); + std::pair secNsec(const system_tp& tp); +}; \ No newline at end of file diff --git a/src/helpers/time/Timer.cpp b/src/helpers/time/Timer.cpp new file mode 100644 index 000000000..95f754410 --- /dev/null +++ b/src/helpers/time/Timer.cpp @@ -0,0 +1,23 @@ +#include "Timer.hpp" + +#define chr std::chrono + +void CTimer::reset() { + m_lastReset = Time::steadyNow(); +} + +Time::steady_dur CTimer::getDuration() { + return Time::steadyNow() - m_lastReset; +} + +float CTimer::getMillis() { + return chr::duration_cast(getDuration()).count() / 1000.F; +} + +float CTimer::getSeconds() { + return chr::duration_cast(getDuration()).count() / 1000.F; +} + +const Time::steady_tp& CTimer::chrono() const { + return m_lastReset; +} \ No newline at end of file diff --git a/src/helpers/time/Timer.hpp b/src/helpers/time/Timer.hpp new file mode 100644 index 000000000..c21f78db7 --- /dev/null +++ b/src/helpers/time/Timer.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "Time.hpp" + +class CTimer { + public: + void reset(); + float getSeconds(); + float getMillis(); + const Time::steady_tp& chrono() const; + + private: + Time::steady_tp m_lastReset; + + Time::steady_dur getDuration(); +}; \ No newline at end of file diff --git a/src/managers/AnimationManager.cpp b/src/managers/AnimationManager.cpp index 18dae2a4f..d3b4ab22a 100644 --- a/src/managers/AnimationManager.cpp +++ b/src/managers/AnimationManager.cpp @@ -264,7 +264,7 @@ void CHyprAnimationManager::scheduleTick() { float refreshDelayMs = std::floor(1000.f / PMOSTHZ->refreshRate); - const float SINCEPRES = std::chrono::duration_cast(std::chrono::steady_clock::now() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.f; + const float SINCEPRES = std::chrono::duration_cast(Time::steadyNow() - PMOSTHZ->lastPresentationTimer.chrono()).count() / 1000.F; const auto TOPRES = std::clamp(refreshDelayMs - SINCEPRES, 1.1f, 1000.f); // we can't send 0, that will disarm it diff --git a/src/managers/KeybindManager.hpp b/src/managers/KeybindManager.hpp index 0040d7610..ede164029 100644 --- a/src/managers/KeybindManager.hpp +++ b/src/managers/KeybindManager.hpp @@ -8,7 +8,7 @@ #include #include "../devices/IPointer.hpp" #include "eventLoop/EventLoopTimer.hpp" -#include "../helpers/Timer.hpp" +#include "../helpers/time/Timer.hpp" class CInputManager; class CConfigManager; diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index e116aa963..c16650be3 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -15,6 +15,7 @@ #include "../render/Renderer.hpp" #include "../render/OpenGL.hpp" #include "SeatManager.hpp" +#include "../helpers/time/Time.hpp" #include #include #include @@ -160,9 +161,7 @@ void CPointerManager::setCursorSurface(SP surf, const Vector2D& hots if (surf->resource()->current.texture) { currentCursorImage.size = surf->resource()->current.bufferSize; - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - surf->resource()->frame(&now); + surf->resource()->frame(Time::steadyNow()); } } @@ -592,7 +591,7 @@ SP CPointerManager::renderHWCursorBuffer(SP overridePos) { +void CPointerManager::renderSoftwareCursorsFor(PHLMONITOR pMonitor, const Time::steady_tp& now, CRegion& damage, std::optional overridePos) { if (!hasCursor()) return; diff --git a/src/managers/PointerManager.hpp b/src/managers/PointerManager.hpp index 4bdd309c9..10726bc6f 100644 --- a/src/managers/PointerManager.hpp +++ b/src/managers/PointerManager.hpp @@ -6,6 +6,7 @@ #include "../helpers/math/Math.hpp" #include "../desktop/WLSurface.hpp" #include "../helpers/sync/SyncTimeline.hpp" +#include "../helpers/time/Time.hpp" #include class CMonitor; @@ -48,7 +49,7 @@ class CPointerManager { void unlockSoftwareAll(); bool softwareLockedFor(PHLMONITOR pMonitor); - void renderSoftwareCursorsFor(PHLMONITOR pMonitor, timespec* now, CRegion& damage /* logical */, std::optional overridePos = {} /* monitor-local */); + void renderSoftwareCursorsFor(PHLMONITOR pMonitor, const Time::steady_tp& now, CRegion& damage /* logical */, std::optional overridePos = {} /* monitor-local */); // this is needed e.g. during screensharing where // the software cursors aren't locked during the cursor move, but they diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index 51d4cefb1..b80da2fd4 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -1,7 +1,7 @@ #pragma once #include "../defines.hpp" -#include "../helpers/Timer.hpp" +#include "../helpers/time/Timer.hpp" #include "../helpers/signal/Signal.hpp" #include #include diff --git a/src/managers/TokenManager.cpp b/src/managers/TokenManager.cpp index 5efa2eb88..446b87cea 100644 --- a/src/managers/TokenManager.cpp +++ b/src/managers/TokenManager.cpp @@ -2,12 +2,12 @@ #include #include -CUUIDToken::CUUIDToken(const std::string& uuid_, std::any data_, std::chrono::steady_clock::duration expires) : data(data_), uuid(uuid_) { - expiresAt = std::chrono::steady_clock::now() + expires; +CUUIDToken::CUUIDToken(const std::string& uuid_, std::any data_, Time::steady_dur expires) : m_data(data_), m_uuid(uuid_) { + m_expiresAt = Time::steadyNow() + expires; } std::string CUUIDToken::getUUID() { - return uuid; + return m_uuid; } std::string CTokenManager::getRandomUUID() { @@ -23,7 +23,7 @@ std::string CTokenManager::getRandomUUID() { return uuid; } -std::string CTokenManager::registerNewToken(std::any data, std::chrono::steady_clock::duration expires) { +std::string CTokenManager::registerNewToken(std::any data, Time::steady_dur expires) { std::string uuid = getRandomUUID(); m_mTokens[uuid] = makeShared(uuid, data, expires); @@ -33,8 +33,8 @@ std::string CTokenManager::registerNewToken(std::any data, std::chrono::steady_c SP CTokenManager::getToken(const std::string& uuid) { // cleanup expired tokens - const auto NOW = std::chrono::steady_clock::now(); - std::erase_if(m_mTokens, [&NOW](const auto& el) { return el.second->expiresAt < NOW; }); + const auto NOW = Time::steadyNow(); + std::erase_if(m_mTokens, [&NOW](const auto& el) { return el.second->m_expiresAt < NOW; }); if (!m_mTokens.contains(uuid)) return {}; @@ -45,5 +45,5 @@ SP CTokenManager::getToken(const std::string& uuid) { void CTokenManager::removeToken(SP token) { if (!token) return; - m_mTokens.erase(token->uuid); + m_mTokens.erase(token->m_uuid); } diff --git a/src/managers/TokenManager.hpp b/src/managers/TokenManager.hpp index aaf068bc9..cccb9bd98 100644 --- a/src/managers/TokenManager.hpp +++ b/src/managers/TokenManager.hpp @@ -1,24 +1,23 @@ #pragma once -#include #include #include #include #include "../helpers/memory/Memory.hpp" +#include "../helpers/time/Time.hpp" class CUUIDToken { public: - CUUIDToken(const std::string& uuid_, std::any data_, std::chrono::steady_clock::duration expires); + CUUIDToken(const std::string& uuid_, std::any data_, Time::steady_dur expires); std::string getUUID(); - std::any data; + std::any m_data; private: - std::string uuid; - - std::chrono::steady_clock::time_point expiresAt; + std::string m_uuid; + Time::steady_tp m_expiresAt; friend class CTokenManager; }; diff --git a/src/managers/XCursorManager.cpp b/src/managers/XCursorManager.cpp index 0f0c9e807..198bc2a5a 100644 --- a/src/managers/XCursorManager.cpp +++ b/src/managers/XCursorManager.cpp @@ -1,3 +1,9 @@ +#define Time XTime__ +extern "C" { +#include +} +#undef Time + #include #include #include @@ -176,8 +182,9 @@ SP CXCursorManager::getShape(std::string const& shape, int size, floa return defaultCursor; } -SP CXCursorManager::createCursor(std::string const& shape, XcursorImages* xImages) { - auto xcursor = makeShared(); +SP CXCursorManager::createCursor(std::string const& shape, void* ximages) { + auto xcursor = makeShared(); + XcursorImages* xImages = (XcursorImages*)ximages; for (int i = 0; i < xImages->nimage; i++) { auto xImage = xImages->images[i]; diff --git a/src/managers/XCursorManager.hpp b/src/managers/XCursorManager.hpp index 3052206f3..8e804a0cb 100644 --- a/src/managers/XCursorManager.hpp +++ b/src/managers/XCursorManager.hpp @@ -7,10 +7,6 @@ #include #include "helpers/memory/Memory.hpp" -extern "C" { -#include -} - // gangsta bootleg XCursor impl. adidas balkanized struct SXCursorImage { Hyprutils::Math::Vector2D size; @@ -34,7 +30,7 @@ class CXCursorManager { void syncGsettings(); private: - SP createCursor(std::string const& shape, XcursorImages* xImages); + SP createCursor(std::string const& shape, void* /* XcursorImages* */ xImages); std::set themePaths(std::string const& theme); std::string getLegacyShapeName(std::string const& shape); std::vector> loadStandardCursors(std::string const& name, int size); diff --git a/src/managers/eventLoop/EventLoopTimer.cpp b/src/managers/eventLoop/EventLoopTimer.cpp index b8943b7ce..d4633b0d8 100644 --- a/src/managers/eventLoop/EventLoopTimer.cpp +++ b/src/managers/eventLoop/EventLoopTimer.cpp @@ -1,55 +1,55 @@ #include "EventLoopTimer.hpp" #include #include "EventLoopManager.hpp" +#include "../../helpers/time/Time.hpp" -CEventLoopTimer::CEventLoopTimer(std::optional timeout, std::function self, void* data)> cb_, void* data_) : - cb(cb_), data(data_) { +CEventLoopTimer::CEventLoopTimer(std::optional timeout, std::function self, void* data)> cb_, void* data_) : m_cb(cb_), m_data(data_) { if (!timeout.has_value()) - expires.reset(); + m_expires.reset(); else - expires = std::chrono::steady_clock::now() + *timeout; + m_expires = Time::steadyNow() + *timeout; } -void CEventLoopTimer::updateTimeout(std::optional timeout) { +void CEventLoopTimer::updateTimeout(std::optional timeout) { if (!timeout.has_value()) { - expires.reset(); + m_expires.reset(); g_pEventLoopManager->nudgeTimers(); return; } - expires = std::chrono::steady_clock::now() + *timeout; + m_expires = Time::steadyNow() + *timeout; g_pEventLoopManager->nudgeTimers(); } bool CEventLoopTimer::passed() { - if (!expires.has_value()) + if (!m_expires.has_value()) return false; - return std::chrono::steady_clock::now() > *expires; + return Time::steadyNow() > *m_expires; } void CEventLoopTimer::cancel() { - wasCancelled = true; - expires.reset(); + m_wasCancelled = true; + m_expires.reset(); } bool CEventLoopTimer::cancelled() { - return wasCancelled; + return m_wasCancelled; } void CEventLoopTimer::call(SP self) { - expires.reset(); - cb(self, data); + m_expires.reset(); + m_cb(self, m_data); } float CEventLoopTimer::leftUs() { - if (!expires.has_value()) + if (!m_expires.has_value()) return std::numeric_limits::max(); - return std::chrono::duration_cast(*expires - std::chrono::steady_clock::now()).count(); + return std::chrono::duration_cast(*m_expires - Time::steadyNow()).count(); } bool CEventLoopTimer::armed() { - return expires.has_value(); + return m_expires.has_value(); } diff --git a/src/managers/eventLoop/EventLoopTimer.hpp b/src/managers/eventLoop/EventLoopTimer.hpp index e5a8c5e38..d093cd6e6 100644 --- a/src/managers/eventLoop/EventLoopTimer.hpp +++ b/src/managers/eventLoop/EventLoopTimer.hpp @@ -5,14 +5,15 @@ #include #include "../../helpers/memory/Memory.hpp" +#include "../../helpers/time/Time.hpp" class CEventLoopTimer { public: - CEventLoopTimer(std::optional timeout, std::function self, void* data)> cb_, void* data_); + CEventLoopTimer(std::optional timeout, std::function self, void* data)> cb_, void* data_); // if not specified, disarms. // if specified, arms. - void updateTimeout(std::optional timeout); + void updateTimeout(std::optional timeout); void cancel(); bool passed(); @@ -25,8 +26,8 @@ class CEventLoopTimer { void call(SP self); private: - std::function self, void* data)> cb; - void* data = nullptr; - std::optional expires; - bool wasCancelled = false; + std::function self, void* data)> m_cb; + void* m_data = nullptr; + std::optional m_expires; + bool m_wasCancelled = false; }; diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index 4c5de729c..0665e0d2d 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -36,6 +36,8 @@ #include "../../managers/EventManager.hpp" #include "../../managers/LayoutManager.hpp" +#include "../../helpers/time/Time.hpp" + #include CInputManager::CInputManager() { @@ -142,10 +144,8 @@ void CInputManager::onMouseWarp(IPointer::SMotionAbsoluteEvent e) { } void CInputManager::simulateMouseMovement() { - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); m_vLastCursorPosFloored = m_vLastCursorPosFloored - Vector2D(1, 1); // hack: force the mouseMoveUnified to report without making this a refocus. - mouseMoveUnified(now.tv_sec * 1000 + now.tv_nsec / 10000000); + mouseMoveUnified(Time::millis(Time::steadyNow())); } void CInputManager::sendMotionEventsToFocused() { @@ -156,9 +156,6 @@ void CInputManager::sendMotionEventsToFocused() { const auto PWINDOW = g_pCompositor->getWindowFromSurface(g_pCompositor->m_pLastFocus.lock()); const auto PLS = g_pCompositor->getLayerSurfaceFromSurface(g_pCompositor->m_pLastFocus.lock()); - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - const auto LOCAL = getMouseCoordsInternal() - (PWINDOW ? PWINDOW->m_vRealPosition->goal() : (PLS ? Vector2D{PLS->geometry.x, PLS->geometry.y} : Vector2D{})); m_bEmptyFocusCursorSet = false; @@ -1746,11 +1743,8 @@ void CInputManager::releaseAllMouseButtons() { if (PROTO::data->dndActive()) return; - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - for (auto const& mb : buttonsCopy) { - g_pSeatManager->sendPointerButton(now.tv_sec * 1000 + now.tv_nsec / 1000000, mb, WL_POINTER_BUTTON_STATE_RELEASED); + g_pSeatManager->sendPointerButton(Time::millis(Time::steadyNow()), mb, WL_POINTER_BUTTON_STATE_RELEASED); } m_lCurrentlyHeldButtons.clear(); diff --git a/src/managers/input/InputManager.hpp b/src/managers/input/InputManager.hpp index 406e18456..62483c41e 100644 --- a/src/managers/input/InputManager.hpp +++ b/src/managers/input/InputManager.hpp @@ -4,7 +4,7 @@ #include #include #include "../../helpers/WLClasses.hpp" -#include "../../helpers/Timer.hpp" +#include "../../helpers/time/Timer.hpp" #include "InputMethodRelay.hpp" #include "../../helpers/signal/Signal.hpp" #include "../../devices/IPointer.hpp" diff --git a/src/protocols/GlobalShortcuts.cpp b/src/protocols/GlobalShortcuts.cpp index 9f8f422c1..04e4e0910 100644 --- a/src/protocols/GlobalShortcuts.cpp +++ b/src/protocols/GlobalShortcuts.cpp @@ -1,4 +1,5 @@ #include "GlobalShortcuts.hpp" +#include "../helpers/time/Time.hpp" CShortcutClient::CShortcutClient(SP resource_) : resource(resource_) { if UNLIKELY (!good()) @@ -68,14 +69,13 @@ void CGlobalShortcutsProtocol::sendGlobalShortcutEvent(std::string appid, std::s for (auto const& c : m_vClients) { for (auto const& sh : c->shortcuts) { if (sh->appid == appid && sh->id == trigger) { - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0; - uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF; + const auto [sec, nsec] = Time::secNsec(Time::steadyNow()); + uint32_t tvSecHi = (sizeof(sec) > 4) ? sec >> 32 : 0; + uint32_t tvSecLo = sec & 0xFFFFFFFF; if (pressed) - sh->resource->sendPressed(tvSecHi, tvSecLo, now.tv_nsec); + sh->resource->sendPressed(tvSecHi, tvSecLo, nsec); else - sh->resource->sendReleased(tvSecHi, tvSecLo, now.tv_nsec); + sh->resource->sendReleased(tvSecHi, tvSecLo, nsec); } } } diff --git a/src/protocols/PresentationTime.cpp b/src/protocols/PresentationTime.cpp index 05fda8ea9..b8f06cd38 100644 --- a/src/protocols/PresentationTime.cpp +++ b/src/protocols/PresentationTime.cpp @@ -40,7 +40,7 @@ bool CPresentationFeedback::good() { return resource->resource(); } -void CPresentationFeedback::sendQueued(SP data, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { +void CPresentationFeedback::sendQueued(SP data, const Time::steady_tp& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { auto client = resource->client(); if LIKELY (PROTO::outputs.contains(data->pMonitor->szName)) { @@ -58,12 +58,14 @@ void CPresentationFeedback::sendQueued(SP data, timespe if (reportedFlags & Aquamarine::IOutput::AQ_OUTPUT_PRESENT_HW_COMPLETION) flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION; - time_t tv_sec = 0; + const auto TIMESPEC = Time::toTimespec(when); + + time_t tv_sec = 0; if (sizeof(time_t) > 4) - tv_sec = when->tv_sec >> 32; + tv_sec = TIMESPEC.tv_sec >> 32; if (data->wasPresented) - resource->sendPresented((uint32_t)tv_sec, (uint32_t)(when->tv_sec & 0xFFFFFFFF), (uint32_t)(when->tv_nsec), untilRefreshNs, (uint32_t)(seq >> 32), + resource->sendPresented((uint32_t)tv_sec, (uint32_t)(TIMESPEC.tv_sec & 0xFFFFFFFF), (uint32_t)(TIMESPEC.tv_nsec), untilRefreshNs, (uint32_t)(seq >> 32), (uint32_t)(seq & 0xFFFFFFFF), (wpPresentationFeedbackKind)flags); else resource->sendDiscarded(); @@ -107,15 +109,7 @@ void CPresentationProtocol::onGetFeedback(CWpPresentation* pMgr, wl_resource* su } } -void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { - timespec now; - timespec* presentedAt = when; - if (!presentedAt) { - // just put the current time, we don't have anything better - clock_gettime(CLOCK_MONOTONIC, &now); - when = &now; - } - +void CPresentationProtocol::onPresented(PHLMONITOR pMonitor, const Time::steady_tp& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags) { for (auto const& feedback : m_vFeedbacks) { if (!feedback->surface) continue; diff --git a/src/protocols/PresentationTime.hpp b/src/protocols/PresentationTime.hpp index 03b59b897..aa93068b8 100644 --- a/src/protocols/PresentationTime.hpp +++ b/src/protocols/PresentationTime.hpp @@ -4,6 +4,7 @@ #include #include "WaylandProtocol.hpp" #include "presentation-time.hpp" +#include "../helpers/time/Time.hpp" class CMonitor; class CWLSurfaceResource; @@ -36,7 +37,7 @@ class CPresentationFeedback { bool good(); - void sendQueued(SP data, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); + void sendQueued(SP data, const Time::steady_tp& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); private: SP resource; @@ -52,7 +53,7 @@ class CPresentationProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); - void onPresented(PHLMONITOR pMonitor, timespec* when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); + void onPresented(PHLMONITOR pMonitor, const Time::steady_tp& when, uint32_t untilRefreshNs, uint64_t seq, uint32_t reportedFlags); void queueData(SP data); private: diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index d5a5f816f..11aa5957e 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -11,6 +11,7 @@ #include "types/WLBuffer.hpp" #include "types/Buffer.hpp" #include "../helpers/Format.hpp" +#include "../helpers/time/Time.hpp" #include #include @@ -166,10 +167,9 @@ void CScreencopyFrame::share() { if (!buffer || !pMonitor) return; - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); + const auto NOW = Time::steadyNow(); - auto callback = [this, now, weak = self](bool success) { + auto callback = [this, NOW, weak = self](bool success) { if (weak.expired()) return; @@ -185,9 +185,11 @@ void CScreencopyFrame::share() { resource->sendDamage(0, 0, buffer->size.x, buffer->size.y); } - uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0; - uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF; - resource->sendReady(tvSecHi, tvSecLo, now.tv_nsec); + const auto [sec, nsec] = Time::secNsec(NOW); + + uint32_t tvSecHi = (sizeof(sec) > 4) ? sec >> 32 : 0; + uint32_t tvSecLo = sec & 0xFFFFFFFF; + resource->sendReady(tvSecHi, tvSecLo, nsec); }; if (bufferDMA) diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index 99dbcc2b7..2d3ccab0c 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -8,7 +8,8 @@ #include #include #include "../managers/HookSystemManager.hpp" -#include "../helpers/Timer.hpp" +#include "../helpers/time/Timer.hpp" +#include "../helpers/time/Time.hpp" #include "../managers/eventLoop/EventLoopTimer.hpp" #include @@ -102,7 +103,7 @@ class CScreencopyProtocol : public IWaylandProtocol { void shareFrame(CScreencopyFrame* frame); void sendFrameDamage(CScreencopyFrame* frame); bool copyFrameDmabuf(CScreencopyFrame* frame); - bool copyFrameShm(CScreencopyFrame* frame, timespec* now); + bool copyFrameShm(CScreencopyFrame* frame, const Time::steady_tp& now); friend class CScreencopyFrame; friend class CScreencopyClient; diff --git a/src/protocols/Tablet.cpp b/src/protocols/Tablet.cpp index de2ed71bf..449fb576b 100644 --- a/src/protocols/Tablet.cpp +++ b/src/protocols/Tablet.cpp @@ -3,6 +3,7 @@ #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "../managers/input/InputManager.hpp" +#include "../helpers/time/Time.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" #include @@ -222,9 +223,7 @@ void CTabletToolV2Resource::sendFrame(bool removeSource) { if (!current) return; - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - resource->sendFrame(now.tv_sec * 1000 + now.tv_nsec / 1000000); + resource->sendFrame(Time::millis(Time::steadyNow())); } CTabletSeat::CTabletSeat(SP resource_) : resource(resource_) { diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 8f18afbc0..fc0dc9d51 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -205,16 +205,13 @@ void CToplevelExportFrame::share() { if (!buffer || !validMapped(pWindow)) return; - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - if (bufferDMA) { - if (!copyDmabuf(&now)) { + if (!copyDmabuf(Time::steadyNow())) { resource->sendFailed(); return; } } else { - if (!copyShm(&now)) { + if (!copyShm(Time::steadyNow())) { resource->sendFailed(); return; } @@ -222,16 +219,17 @@ void CToplevelExportFrame::share() { resource->sendFlags((hyprlandToplevelExportFrameV1Flags)0); - if (!m_ignoreDamage) { + if (!m_ignoreDamage) resource->sendDamage(0, 0, box.width, box.height); - } - uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0; - uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF; - resource->sendReady(tvSecHi, tvSecLo, now.tv_nsec); + const auto [sec, nsec] = Time::secNsec(Time::steadyNow()); + + uint32_t tvSecHi = (sizeof(sec) > 4) ? sec >> 32 : 0; + uint32_t tvSecLo = sec & 0xFFFFFFFF; + resource->sendReady(tvSecHi, tvSecLo, nsec); } -bool CToplevelExportFrame::copyShm(timespec* now) { +bool CToplevelExportFrame::copyShm(const Time::steady_tp& now) { const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(resource->client(), PERMISSION_TYPE_SCREENCOPY); auto shm = buffer->shm(); auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); // no need for end, cuz it's shm @@ -329,7 +327,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { return true; } -bool CToplevelExportFrame::copyDmabuf(timespec* now) { +bool CToplevelExportFrame::copyDmabuf(const Time::steady_tp& now) { const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(resource->client(), PERMISSION_TYPE_SCREENCOPY); const auto PMONITOR = pWindow->m_pMonitor.lock(); diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index 21aafde58..907f62366 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -4,6 +4,7 @@ #include "hyprland-toplevel-export-v1.hpp" #include "WaylandProtocol.hpp" #include "Screencopy.hpp" +#include "../helpers/time/Time.hpp" #include @@ -62,8 +63,8 @@ class CToplevelExportFrame { CBox box = {}; void copy(CHyprlandToplevelExportFrameV1* pFrame, wl_resource* buffer, int32_t ignoreDamage); - bool copyDmabuf(timespec* now); - bool copyShm(timespec* now); + bool copyDmabuf(const Time::steady_tp& now); + bool copyShm(const Time::steady_tp& now); void share(); bool shouldOverlayCursor() const; @@ -87,8 +88,8 @@ class CToplevelExportProtocol : IWaylandProtocol { std::vector> m_vFramesAwaitingWrite; void shareFrame(CToplevelExportFrame* frame); - bool copyFrameDmabuf(CToplevelExportFrame* frame, timespec* now); - bool copyFrameShm(CToplevelExportFrame* frame, timespec* now); + bool copyFrameDmabuf(CToplevelExportFrame* frame, const Time::steady_tp& now); + bool copyFrameShm(CToplevelExportFrame* frame, const Time::steady_tp& now); void sendDamage(CToplevelExportFrame* frame); friend class CToplevelExportClient; diff --git a/src/protocols/VirtualKeyboard.cpp b/src/protocols/VirtualKeyboard.cpp index 00aca0411..e57d66c84 100644 --- a/src/protocols/VirtualKeyboard.cpp +++ b/src/protocols/VirtualKeyboard.cpp @@ -1,6 +1,7 @@ #include "VirtualKeyboard.hpp" #include #include "../devices/IKeyboard.hpp" +#include "../helpers/time/Time.hpp" using namespace Hyprutils::OS; CVirtualKeyboardV1Resource::CVirtualKeyboardV1Resource(SP resource_) : resource(resource_) { @@ -103,12 +104,9 @@ wl_client* CVirtualKeyboardV1Resource::client() { } void CVirtualKeyboardV1Resource::releasePressed() { - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - for (auto const& p : pressed) { events.key.emit(IKeyboard::SKeyEvent{ - .timeMs = now.tv_sec * 1000 + now.tv_nsec / 1000000, + .timeMs = Time::millis(Time::steadyNow()), .keycode = p, .state = WL_KEYBOARD_KEY_STATE_RELEASED, }); diff --git a/src/protocols/core/Compositor.cpp b/src/protocols/core/Compositor.cpp index 827ec3112..23b14dd34 100644 --- a/src/protocols/core/Compositor.cpp +++ b/src/protocols/core/Compositor.cpp @@ -33,8 +33,8 @@ bool CWLCallbackResource::good() { return resource->resource(); } -void CWLCallbackResource::send(timespec* now) { - resource->sendDone(now->tv_sec * 1000 + now->tv_nsec / 1000000); +void CWLCallbackResource::send(const Time::steady_tp& now) { + resource->sendDone(Time::millis(now)); } CWLRegionResource::CWLRegionResource(SP resource_) : resource(resource_) { @@ -323,7 +323,7 @@ void CWLSurfaceResource::sendPreferredScale(int32_t scale) { resource->sendPreferredBufferScale(scale); } -void CWLSurfaceResource::frame(timespec* now) { +void CWLSurfaceResource::frame(const Time::steady_tp& now) { if (callbacks.empty()) return; @@ -436,9 +436,7 @@ void CWLSurfaceResource::map() { mapped = true; - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - frame(&now); + frame(Time::steadyNow()); current.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}}; pending.bufferDamage = CBox{{}, {INT32_MAX, INT32_MAX}}; @@ -565,7 +563,7 @@ void CWLSurfaceResource::updateCursorShm(CRegion damage) { } } -void CWLSurfaceResource::presentFeedback(timespec* when, PHLMONITOR pMonitor, bool discarded) { +void CWLSurfaceResource::presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded) { frame(when); auto FEEDBACK = makeShared(self.lock()); FEEDBACK->attachMonitor(pMonitor); diff --git a/src/protocols/core/Compositor.hpp b/src/protocols/core/Compositor.hpp index ccfcf0cc1..7415b4f5b 100644 --- a/src/protocols/core/Compositor.hpp +++ b/src/protocols/core/Compositor.hpp @@ -16,6 +16,7 @@ #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" #include "../../helpers/math/Math.hpp" +#include "../../helpers/time/Time.hpp" #include "../types/Buffer.hpp" #include "../types/SurfaceRole.hpp" #include "../types/SurfaceState.hpp" @@ -36,7 +37,7 @@ class CWLCallbackResource { CWLCallbackResource(SP resource_); bool good(); - void send(timespec* now); + void send(const Time::steady_tp& now); private: SP resource; @@ -69,7 +70,7 @@ class CWLSurfaceResource { void leave(PHLMONITOR monitor); void sendPreferredTransform(wl_output_transform t); void sendPreferredScale(int32_t scale); - void frame(timespec* now); + void frame(const Time::steady_tp& now); uint32_t id(); void map(); void unmap(); @@ -104,7 +105,7 @@ class CWLSurfaceResource { void breadthfirst(std::function, const Vector2D&, void*)> fn, void* data); SP findFirstPreorder(std::function)> fn); - void presentFeedback(timespec* when, PHLMONITOR pMonitor, bool discarded = false); + void presentFeedback(const Time::steady_tp& when, PHLMONITOR pMonitor, bool discarded = false); void commitState(SSurfaceState& state); // returns a pair: found surface (null if not found) and surface local coords. diff --git a/src/protocols/core/DataDevice.cpp b/src/protocols/core/DataDevice.cpp index d1a98fb5d..2915be75c 100644 --- a/src/protocols/core/DataDevice.cpp +++ b/src/protocols/core/DataDevice.cpp @@ -604,10 +604,7 @@ void CWLDataDeviceProtocol::initiateDrag(WP currentSource if (!box.has_value()) return; - timespec timeNow; - clock_gettime(CLOCK_MONOTONIC, &timeNow); - - dnd.focusedDevice->sendMotion(timeNow.tv_sec * 1000 + timeNow.tv_nsec / 1000000, V - box->pos()); + dnd.focusedDevice->sendMotion(Time::millis(Time::steadyNow()), V - box->pos()); LOGM(LOG, "Drag motion {}", V - box->pos()); } }); @@ -802,7 +799,7 @@ void CWLDataDeviceProtocol::abortDrag() { g_pSeatManager->resendEnterEvents(); } -void CWLDataDeviceProtocol::renderDND(PHLMONITOR pMonitor, timespec* when) { +void CWLDataDeviceProtocol::renderDND(PHLMONITOR pMonitor, const Time::steady_tp& when) { if (!dnd.dndSurface || !dnd.dndSurface->current.texture) return; diff --git a/src/protocols/core/DataDevice.hpp b/src/protocols/core/DataDevice.hpp index fa5de091e..0c53111b9 100644 --- a/src/protocols/core/DataDevice.hpp +++ b/src/protocols/core/DataDevice.hpp @@ -15,6 +15,7 @@ #include "wayland.hpp" #include "../../helpers/signal/Signal.hpp" #include "../../helpers/math/Math.hpp" +#include "../../helpers/time/Time.hpp" #include "../types/DataDevice.hpp" #include @@ -138,7 +139,7 @@ class CWLDataDeviceProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); // renders and damages the dnd icon, if present - void renderDND(PHLMONITOR pMonitor, timespec* when); + void renderDND(PHLMONITOR pMonitor, const Time::steady_tp& when); // for inputmgr to force refocus // TODO: move handling to seatmgr bool dndActive(); diff --git a/src/protocols/core/Seat.cpp b/src/protocols/core/Seat.cpp index f6eee6e1a..5faabedc2 100644 --- a/src/protocols/core/Seat.cpp +++ b/src/protocols/core/Seat.cpp @@ -4,6 +4,7 @@ #include "../../devices/IKeyboard.hpp" #include "../../devices/IHID.hpp" #include "../../managers/SeatManager.hpp" +#include "../../helpers/time/Time.hpp" #include "../../config/ConfigValue.hpp" #include @@ -174,10 +175,8 @@ void CWLPointerResource::sendLeave() { // release all buttons unless we have a dnd going on in which case // the events shall be lost. if (!PROTO::data->dndActive()) { - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); for (auto const& b : pressedButtons) { - sendButton(now.tv_sec * 1000 + now.tv_nsec / 1000000, b, WL_POINTER_BUTTON_STATE_RELEASED); + sendButton(Time::millis(Time::steadyNow()), b, WL_POINTER_BUTTON_STATE_RELEASED); } } diff --git a/src/render/OpenGL.hpp b/src/render/OpenGL.hpp index ab091f24b..17ef4f5fc 100644 --- a/src/render/OpenGL.hpp +++ b/src/render/OpenGL.hpp @@ -3,7 +3,7 @@ #include "../defines.hpp" #include "../helpers/Monitor.hpp" #include "../helpers/Color.hpp" -#include "../helpers/Timer.hpp" +#include "../helpers/time/Timer.hpp" #include "../helpers/math/Math.hpp" #include "../helpers/Format.hpp" #include "../helpers/sync/SyncTimeline.hpp" diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 1ce717bca..8a2d45550 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -135,9 +135,6 @@ CHyprRenderer::CHyprRenderer() { if (m_vRenderUnfocused.empty()) return; - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - bool dirty = false; for (auto& w : m_vRenderUnfocused) { if (!w) { @@ -148,7 +145,7 @@ CHyprRenderer::CHyprRenderer() { if (!w->m_pWLSurface || !w->m_pWLSurface->resource() || shouldRenderWindow(w.lock())) continue; - w->m_pWLSurface->resource()->frame(&now); + w->m_pWLSurface->resource()->frame(Time::steadyNow()); auto FEEDBACK = makeShared(w->m_pWLSurface->resource()); FEEDBACK->attachMonitor(g_pCompositor->m_pLastMonitor.lock()); FEEDBACK->discarded(); @@ -265,7 +262,7 @@ bool CHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) { return false; } -void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { +void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& time) { PHLWINDOW pWorkspaceWindow = nullptr; EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); @@ -356,7 +353,7 @@ void CHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWOR } } -void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time) { +void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& time) { PHLWINDOW lastWindow; EMIT_HOOK_EVENT("render", RENDER_PRE_WINDOWS); @@ -454,7 +451,7 @@ void CHyprRenderer::renderWorkspaceWindows(PHLMONITOR pMonitor, PHLWORKSPACE pWo } } -void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespec* time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool standalone) { +void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, const Time::steady_tp& time, bool decorate, eRenderPassMode mode, bool ignorePosition, bool standalone) { if (pWindow->isHidden() && !standalone) return; @@ -692,7 +689,7 @@ void CHyprRenderer::renderWindow(PHLWINDOW pWindow, PHLMONITOR pMonitor, timespe g_pHyprOpenGL->m_RenderData.currentWindow.reset(); } -void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* time, bool popups) { +void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, const Time::steady_tp& time, bool popups) { if (!pLayer) return; @@ -770,7 +767,7 @@ void CHyprRenderer::renderLayer(PHLLS pLayer, PHLMONITOR pMonitor, timespec* tim } } -void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, timespec* time) { +void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, const Time::steady_tp& time) { const auto POS = pPopup->globalBox().pos(); CSurfacePassElement::SRenderData renderdata = {pMonitor, time, POS}; @@ -804,7 +801,7 @@ void CHyprRenderer::renderIMEPopup(CInputPopup* pPopup, PHLMONITOR pMonitor, tim &renderdata); } -void CHyprRenderer::renderSessionLockSurface(WP pSurface, PHLMONITOR pMonitor, timespec* time) { +void CHyprRenderer::renderSessionLockSurface(WP pSurface, PHLMONITOR pMonitor, const Time::steady_tp& time) { CSurfacePassElement::SRenderData renderdata = {pMonitor, time, pMonitor->vecPosition, pMonitor->vecPosition}; renderdata.blur = false; @@ -825,7 +822,7 @@ void CHyprRenderer::renderSessionLockSurface(WP pSurface, P &renderdata); } -void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) { +void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& time, const Vector2D& translate, const float& scale) { static auto PDIMSPECIAL = CConfigValue("decoration:dim_special"); static auto PBLURSPECIAL = CConfigValue("decoration:blur:special"); static auto PBLUR = CConfigValue("decoration:blur:enabled"); @@ -988,7 +985,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPA //g_pHyprOpenGL->restoreMatrix(); } -void CHyprRenderer::renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry) { +void CHyprRenderer::renderLockscreen(PHLMONITOR pMonitor, const Time::steady_tp& now, const CBox& geometry) { TRACY_GPU_ZONE("RenderLockscreen"); if (g_pSessionLockManager->isSessionLocked()) { @@ -1246,8 +1243,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) { EMIT_HOOK_EVENT("preRender", pMonitor); - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); + const auto NOW = Time::steadyNow(); // check the damage bool hasChanged = pMonitor->output->needsFrame || pMonitor->damage.hasChanged(); @@ -1328,9 +1324,9 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) { renderCursor = false; } else { CBox renderBox = {0, 0, (int)pMonitor->vecPixelSize.x, (int)pMonitor->vecPixelSize.y}; - renderWorkspace(pMonitor, pMonitor->activeWorkspace, &now, renderBox); + renderWorkspace(pMonitor, pMonitor->activeWorkspace, NOW, renderBox); - renderLockscreen(pMonitor, &now, renderBox); + renderLockscreen(pMonitor, NOW, renderBox); if (pMonitor == g_pCompositor->m_pLastMonitor) { g_pHyprNotificationOverlay->draw(pMonitor); @@ -1357,18 +1353,18 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor) { } } } else - renderWindow(pMonitor->solitaryClient.lock(), pMonitor, &now, false, RENDER_PASS_MAIN /* solitary = no popups */); + renderWindow(pMonitor->solitaryClient.lock(), pMonitor, NOW, false, RENDER_PASS_MAIN /* solitary = no popups */); } else if (!pMonitor->isMirror()) { - sendFrameEventsToWorkspace(pMonitor, pMonitor->activeWorkspace, &now); + sendFrameEventsToWorkspace(pMonitor, pMonitor->activeWorkspace, NOW); if (pMonitor->activeSpecialWorkspace) - sendFrameEventsToWorkspace(pMonitor, pMonitor->activeSpecialWorkspace, &now); + sendFrameEventsToWorkspace(pMonitor, pMonitor->activeSpecialWorkspace, NOW); } renderCursor = renderCursor && shouldRenderCursor(); if (renderCursor) { TRACY_GPU_ZONE("RenderCursor"); - g_pPointerManager->renderSoftwareCursorsFor(pMonitor->self.lock(), &now, g_pHyprOpenGL->m_RenderData.damage); + g_pPointerManager->renderSoftwareCursorsFor(pMonitor->self.lock(), NOW, g_pHyprOpenGL->m_RenderData.damage); } EMIT_HOOK_EVENT("render", RENDER_LAST_MOMENT); @@ -1578,7 +1574,7 @@ bool CHyprRenderer::commitPendingAndDoExplicitSync(PHLMONITOR pMonitor) { return ok; } -void CHyprRenderer::renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry) { +void CHyprRenderer::renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const CBox& geometry) { Vector2D translate = {geometry.x, geometry.y}; float scale = (float)geometry.width / pMonitor->vecPixelSize.x; @@ -1593,7 +1589,7 @@ void CHyprRenderer::renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace renderAllClientsForWorkspace(pMonitor, pWorkspace, now, translate, scale); } -void CHyprRenderer::sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now) { +void CHyprRenderer::sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now) { for (auto const& w : g_pCompositor->m_vWindows) { if (w->isHidden() || !w->m_bIsMapped || w->m_bFadingOut || !w->m_pWLSurface->resource()) continue; @@ -1962,7 +1958,7 @@ void CHyprRenderer::damageMirrorsWith(PHLMONITOR pMonitor, const CRegion& pRegio } } -void CHyprRenderer::renderDragIcon(PHLMONITOR pMonitor, timespec* time) { +void CHyprRenderer::renderDragIcon(PHLMONITOR pMonitor, const Time::steady_tp& time) { PROTO::data->renderDND(pMonitor, time); } @@ -2426,9 +2422,6 @@ void CHyprRenderer::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFram g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - // this is a hack but it works :P // we need to disable blur or else we will get a black background, as the shader // will try to copy the bg to apply blur. @@ -2445,7 +2438,7 @@ void CHyprRenderer::makeRawWindowSnapshot(PHLWINDOW pWindow, CFramebuffer* pFram g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC - renderWindow(pWindow, PMONITOR, &now, false, RENDER_PASS_ALL, true); + renderWindow(pWindow, PMONITOR, Time::steadyNow(), false, RENDER_PASS_ALL, true); **PBLUR = BLURVAL; @@ -2481,9 +2474,6 @@ void CHyprRenderer::makeWindowSnapshot(PHLWINDOW pWindow) { g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - // this is a hack but it works :P // we need to disable blur or else we will get a black background, as the shader // will try to copy the bg to apply blur. @@ -2495,7 +2485,7 @@ void CHyprRenderer::makeWindowSnapshot(PHLWINDOW pWindow) { g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC - renderWindow(pWindow, PMONITOR, &now, !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL); + renderWindow(pWindow, PMONITOR, Time::steadyNow(), !pWindow->m_bX11DoesntWantBorders, RENDER_PASS_ALL); **PBLUR = BLURVAL; @@ -2528,14 +2518,11 @@ void CHyprRenderer::makeLayerSnapshot(PHLLS pLayer) { g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 0)); // JIC - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - const auto BLURLSSTATUS = pLayer->forceBlur; pLayer->forceBlur = false; // draw the layer - renderLayer(pLayer, PMONITOR, &now); + renderLayer(pLayer, PMONITOR, Time::steadyNow()); pLayer->forceBlur = BLURLSSTATUS; diff --git a/src/render/Renderer.hpp b/src/render/Renderer.hpp index 731ed926c..1d0df2a5b 100644 --- a/src/render/Renderer.hpp +++ b/src/render/Renderer.hpp @@ -6,8 +6,9 @@ #include "../desktop/LayerSurface.hpp" #include "OpenGL.hpp" #include "Renderbuffer.hpp" -#include "../helpers/Timer.hpp" +#include "../helpers/time/Timer.hpp" #include "../helpers/math/Math.hpp" +#include "../helpers/time/Time.hpp" struct SMonitorRule; class CWorkspace; @@ -66,7 +67,7 @@ class CHyprRenderer { void calculateUVForSurface(PHLWINDOW, SP, PHLMONITOR pMonitor, bool main = false, const Vector2D& projSize = {}, const Vector2D& projSizeUnscaled = {}, bool fixMisalignedFSV1 = false); std::tuple getRenderTimes(PHLMONITOR pMonitor); // avg max min - void renderLockscreen(PHLMONITOR pMonitor, timespec* now, const CBox& geometry); + void renderLockscreen(PHLMONITOR pMonitor, const Time::steady_tp& now, const CBox& geometry); void recheckSolitaryForMonitor(PHLMONITOR pMonitor); void setCursorSurface(SP surf, int hotspotX, int hotspotY, bool force = false); void setCursorFromName(const std::string& name, bool force = false); @@ -115,27 +116,27 @@ class CHyprRenderer { CRenderPass m_sRenderPass = {}; private: - void arrangeLayerArray(PHLMONITOR, const std::vector&, bool, CBox*); - void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) - void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, timespec*); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) - void renderWindow(PHLWINDOW, PHLMONITOR, timespec*, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false); - void renderLayer(PHLLS, PHLMONITOR, timespec*, bool popups = false); - void renderSessionLockSurface(WP, PHLMONITOR, timespec*); - void renderDragIcon(PHLMONITOR, timespec*); - void renderIMEPopup(CInputPopup*, PHLMONITOR, timespec*); - void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const CBox& geometry); - void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now); // sends frame displayed events but doesn't actually render anything - void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, timespec* now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); - void renderSessionLockMissing(PHLMONITOR pMonitor); + void arrangeLayerArray(PHLMONITOR, const std::vector&, bool, CBox*); + void renderWorkspaceWindowsFullscreen(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (fullscreen) (tiled, floating, pinned, but no special) + void renderWorkspaceWindows(PHLMONITOR, PHLWORKSPACE, const Time::steady_tp&); // renders workspace windows (no fullscreen) (tiled, floating, pinned, but no special) + void renderWindow(PHLWINDOW, PHLMONITOR, const Time::steady_tp&, bool, eRenderPassMode, bool ignorePosition = false, bool standalone = false); + void renderLayer(PHLLS, PHLMONITOR, const Time::steady_tp&, bool popups = false); + void renderSessionLockSurface(WP, PHLMONITOR, const Time::steady_tp&); + void renderDragIcon(PHLMONITOR, const Time::steady_tp&); + void renderIMEPopup(CInputPopup*, PHLMONITOR, const Time::steady_tp&); + void renderWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const CBox& geometry); + void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything + void renderAllClientsForWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& now, const Vector2D& translate = {0, 0}, const float& scale = 1.f); + void renderSessionLockMissing(PHLMONITOR pMonitor); - bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor); + bool commitPendingAndDoExplicitSync(PHLMONITOR pMonitor); - bool m_bCursorHidden = false; - bool m_bCursorHasSurface = false; - SP m_pCurrentRenderbuffer = nullptr; - SP m_pCurrentBuffer = nullptr; - eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; - bool m_bNvidia = false; + bool m_bCursorHidden = false; + bool m_bCursorHasSurface = false; + SP m_pCurrentRenderbuffer = nullptr; + SP m_pCurrentBuffer = nullptr; + eRenderMode m_eRenderMode = RENDER_MODE_NORMAL; + bool m_bNvidia = false; struct { bool hiddenOnTouch = false; diff --git a/src/render/pass/SurfacePassElement.hpp b/src/render/pass/SurfacePassElement.hpp index 1b6ddb0ba..4d51f8041 100644 --- a/src/render/pass/SurfacePassElement.hpp +++ b/src/render/pass/SurfacePassElement.hpp @@ -1,6 +1,7 @@ #pragma once #include "PassElement.hpp" #include +#include "../../helpers/time/Time.hpp" class CWLSurfaceResource; class CTexture; @@ -10,7 +11,7 @@ class CSurfacePassElement : public IPassElement { public: struct SRenderData { PHLMONITORREF pMonitor; - timespec* when = nullptr; + Time::steady_tp when = Time::steadyNow(); Vector2D pos, localPos; void* data = nullptr; diff --git a/src/xwayland/XSurface.cpp b/src/xwayland/XSurface.cpp index 30e38ac26..1ef1c6732 100644 --- a/src/xwayland/XSurface.cpp +++ b/src/xwayland/XSurface.cpp @@ -3,6 +3,7 @@ #include "../protocols/XWaylandShell.hpp" #include "../protocols/core/Compositor.hpp" #include "../managers/ANRManager.hpp" +#include "../helpers/time/Time.hpp" #ifndef NO_XWAYLAND @@ -253,12 +254,9 @@ void CXWaylandSurface::ping() { return; } - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - xcb_client_message_data_t msg = {}; msg.data32[0] = HYPRATOMS["_NET_WM_PING"]; - msg.data32[1] = now.tv_sec * 1000 + now.tv_nsec / 1000000; + msg.data32[1] = Time::millis(Time::steadyNow()); msg.data32[2] = xID; lastPingSeq = msg.data32[1];