From cc98594c3aed0b542e03818371a4636f549f80e1 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Fri, 5 Jul 2024 23:05:03 +0200 Subject: [PATCH] pointer: update geometry after unplug events fixes #6700 fixes #6740 --- src/Compositor.cpp | 4 +-- src/managers/PointerManager.cpp | 5 +-- src/managers/eventLoop/EventLoopManager.cpp | 38 ++++++++++++++++----- src/managers/eventLoop/EventLoopManager.hpp | 14 ++++++-- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/Compositor.cpp b/src/Compositor.cpp index 2ed1a951..f0a2887a 100644 --- a/src/Compositor.cpp +++ b/src/Compositor.cpp @@ -413,7 +413,7 @@ void CCompositor::initManagers(eManagersInitStage stage) { switch (stage) { case STAGE_PRIORITY: { Debug::log(LOG, "Creating the EventLoopManager!"); - g_pEventLoopManager = std::make_unique(); + g_pEventLoopManager = std::make_unique(m_sWLDisplay, m_sWLEventLoop); Debug::log(LOG, "Creating the HookSystem!"); g_pHookSystem = std::make_unique(); @@ -604,7 +604,7 @@ void CCompositor::startCompositor() { // This blocks until we are done. Debug::log(LOG, "Hyprland is ready, running the event loop!"); - g_pEventLoopManager->enterLoop(m_sWLDisplay, m_sWLEventLoop); + g_pEventLoopManager->enterLoop(); } CMonitor* CCompositor::getMonitorFromID(const int& id) { diff --git a/src/managers/PointerManager.cpp b/src/managers/PointerManager.cpp index 8b4ba0ee..e34aa54b 100644 --- a/src/managers/PointerManager.cpp +++ b/src/managers/PointerManager.cpp @@ -4,6 +4,7 @@ #include "../protocols/PointerGestures.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/core/Compositor.hpp" +#include "eventLoop/EventLoopManager.hpp" #include "SeatManager.hpp" #include #include @@ -139,8 +140,8 @@ CPointerManager::CPointerManager() { onMonitorLayoutChange(); - PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr); - PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { onMonitorLayoutChange(); }, nullptr); + PMONITOR->events.modeChanged.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); + PMONITOR->events.disconnect.registerStaticListener([this](void* owner, std::any data) { g_pEventLoopManager->doLater([this]() { onMonitorLayoutChange(); }); }, nullptr); PMONITOR->events.destroy.registerStaticListener( [this](void* owner, std::any data) { if (g_pCompositor && !g_pCompositor->m_bIsShuttingDown) diff --git a/src/managers/eventLoop/EventLoopManager.cpp b/src/managers/eventLoop/EventLoopManager.cpp index 1193ffb8..0d1b0223 100644 --- a/src/managers/eventLoop/EventLoopManager.cpp +++ b/src/managers/eventLoop/EventLoopManager.cpp @@ -9,8 +9,10 @@ #define TIMESPEC_NSEC_PER_SEC 1000000000L -CEventLoopManager::CEventLoopManager() { - m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); +CEventLoopManager::CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop) { + m_sTimers.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + m_sWayland.loop = wlEventLoop; + m_sWayland.display = display; } CEventLoopManager::~CEventLoopManager() { @@ -23,13 +25,10 @@ static int timerWrite(int fd, uint32_t mask, void* data) { return 1; } -void CEventLoopManager::enterLoop(wl_display* display, wl_event_loop* wlEventLoop) { - m_sWayland.loop = wlEventLoop; - m_sWayland.display = display; +void CEventLoopManager::enterLoop() { + m_sWayland.eventSource = wl_event_loop_add_fd(m_sWayland.loop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); - m_sWayland.eventSource = wl_event_loop_add_fd(wlEventLoop, m_sTimers.timerfd, WL_EVENT_READABLE, timerWrite, nullptr); - - wl_display_run(display); + wl_display_run(m_sWayland.display); Debug::log(LOG, "Kicked off the event loop! :("); } @@ -86,4 +85,25 @@ void CEventLoopManager::nudgeTimers() { itimerspec ts = {.it_value = now}; timerfd_settime(m_sTimers.timerfd, TFD_TIMER_ABSTIME, &ts, nullptr); -} \ No newline at end of file +} + +void CEventLoopManager::doLater(const std::function& fn) { + m_sIdle.fns.emplace_back(fn); + + if (m_sIdle.eventSource) + return; + + m_sIdle.eventSource = wl_event_loop_add_idle( + m_sWayland.loop, + [](void* data) { + auto IDLE = (CEventLoopManager::SIdleData*)data; + auto cpy = IDLE->fns; + IDLE->fns.clear(); + IDLE->eventSource = nullptr; + for (auto& c : cpy) { + if (c) + c(); + } + }, + &m_sIdle); +} diff --git a/src/managers/eventLoop/EventLoopManager.hpp b/src/managers/eventLoop/EventLoopManager.hpp index 7a4fa19e..0b2f9578 100644 --- a/src/managers/eventLoop/EventLoopManager.hpp +++ b/src/managers/eventLoop/EventLoopManager.hpp @@ -9,10 +9,10 @@ class CEventLoopManager { public: - CEventLoopManager(); + CEventLoopManager(wl_display* display, wl_event_loop* wlEventLoop); ~CEventLoopManager(); - void enterLoop(wl_display* display, wl_event_loop* wlEventLoop); + void enterLoop(); // Note: will remove the timer if the ptr is lost. void addTimer(SP timer); @@ -23,6 +23,14 @@ class CEventLoopManager { // recalculates timers void nudgeTimers(); + // schedules a function to run later, aka in a wayland idle event. + void doLater(const std::function& fn); + + struct SIdleData { + wl_event_source* eventSource = nullptr; + std::vector> fns; + }; + private: struct { wl_event_loop* loop = nullptr; @@ -34,6 +42,8 @@ class CEventLoopManager { std::vector> timers; int timerfd = -1; } m_sTimers; + + SIdleData m_sIdle; }; inline std::unique_ptr g_pEventLoopManager; \ No newline at end of file