From 450d8a0bf703f3ec460d367f38d61b5966daf8fe Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Thu, 30 Apr 2026 20:41:55 +0100 Subject: xdg-shell: queue state updates for toplevel (#14227) ref https://github.com/hyprwm/Hyprland/discussions/14224 --- src/managers/eventLoop/EventLoopManager.cpp | 38 +++++++++++++++++++++++++---- src/managers/eventLoop/EventLoopManager.hpp | 19 ++++++++++++--- 2 files changed, 48 insertions(+), 9 deletions(-) (limited to 'src/managers/eventLoop') diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 03a8d7c9..6c661a6f 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -16,6 +16,17 @@ using namespace Hyprutils::OS; #define TIMESPEC_NSEC_PER_SEC 1000000000L +static uint64_t LAST_DO_LATER_SEQ = 1; + +SEventLoopDoLaterLock::SEventLoopDoLaterLock(uint64_t seq_) : seq(seq_) { + ; +} + +SEventLoopDoLaterLock::~SEventLoopDoLaterLock() { + if (g_pEventLoopManager && seq > 0) + g_pEventLoopManager->removeDoLater(seq); +} + CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) { m_timers.timerfd = CFileDescriptor{timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC)}; m_wayland.loop = wlEventLoop; @@ -201,11 +212,13 @@ void CEventLoopManager::nudgeTimers() { timerfd_settime(m_timers.timerfd.get(), TFD_TIMER_ABSTIME, &ts, nullptr); } -void CEventLoopManager::doLater(const std::function& fn) { - m_idle.fns.emplace_back(fn); +uint64_t CEventLoopManager::doLater(const std::function& fn) { + const uint64_t NEW_SEQ = ++LAST_DO_LATER_SEQ; + + m_idle.fns.emplace_back(std::make_pair<>(NEW_SEQ, fn)); if (m_idle.eventSource) - return; + return NEW_SEQ; m_idle.eventSource = wl_event_loop_add_idle( m_wayland.loop, @@ -215,11 +228,26 @@ void CEventLoopManager::doLater(const std::function& fn) { IDLE->fns.clear(); IDLE->eventSource = nullptr; for (auto& f : fns) { - if (f) - f(); + if (f.second) + f.second(); } }, &m_idle); + + return NEW_SEQ; +} + +void CEventLoopManager::removeDoLater(uint64_t seq) { + std::erase_if(m_idle.fns, [&seq](const auto& e) { return e.first == seq; }); + + if (m_idle.fns.empty() && m_idle.eventSource) { + wl_event_source_remove(m_idle.eventSource); + m_idle.eventSource = nullptr; + } +} + +UP CEventLoopManager::doLaterLock(const std::function& fn) { + return makeUnique(doLater(fn)); } void CEventLoopManager::doOnReadable(CFileDescriptor fd, std::function&& fn) { diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 7999dc59..64673455 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -14,6 +14,13 @@ namespace Aquamarine { struct SPollFD; }; +struct SEventLoopDoLaterLock { + SEventLoopDoLaterLock(uint64_t seq); + ~SEventLoopDoLaterLock(); + + uint64_t seq = 0; +}; + class CEventLoopManager { public: CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop); @@ -30,12 +37,16 @@ class CEventLoopManager { // schedules a recalc of the timers void scheduleRecalc(); - // schedules a function to run later, aka in a wayland idle event. - void doLater(const std::function& fn); + // schedules a function to run later, aka in a wayland idle event. Returns a sequence which can be used to remove it. + uint64_t doLater(const std::function& fn); + void removeDoLater(uint64_t seq); + + // automatically cleaned up doLater instance + [[nodiscard]] UP doLaterLock(const std::function& fn); struct SIdleData { - wl_event_source* eventSource = nullptr; - std::vector> fns; + wl_event_source* eventSource = nullptr; + std::vector>> fns; }; struct SReadableWaiter { -- cgit v1.2.3