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/protocols/XDGShell.cpp | 58 ++++++++++++++++++++++++++++------------------ src/protocols/XDGShell.hpp | 16 ++++++++----- 2 files changed, 45 insertions(+), 29 deletions(-) (limited to 'src/protocols') diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index 774346d4..3c702950 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -4,6 +4,7 @@ #include "../Compositor.hpp" #include "../managers/SeatManager.hpp" #include "../managers/ANRManager.hpp" +#include "../managers/eventLoop/EventLoopManager.hpp" #include "../helpers/Monitor.hpp" #include "core/Seat.hpp" #include "core/Compositor.hpp" @@ -286,7 +287,7 @@ bool CXDGToplevelResource::anyChildModal() { uint32_t CXDGToplevelResource::setSize(const Vector2D& size) { m_pendingApply.size = size; - applyState(); + scheduleStateApplication(); return m_owner->scheduleConfigure(); } @@ -300,7 +301,9 @@ uint32_t CXDGToplevelResource::setMaximized(bool maximized) { m_pendingApply.states.push_back(XDG_TOPLEVEL_STATE_MAXIMIZED); else if (!maximized && set) std::erase(m_pendingApply.states, XDG_TOPLEVEL_STATE_MAXIMIZED); - applyState(); + + scheduleStateApplication(); + return m_owner->scheduleConfigure(); } @@ -314,7 +317,9 @@ uint32_t CXDGToplevelResource::setFullscreen(bool fullscreen) { m_pendingApply.states.push_back(XDG_TOPLEVEL_STATE_FULLSCREEN); else if (!fullscreen && set) std::erase(m_pendingApply.states, XDG_TOPLEVEL_STATE_FULLSCREEN); - applyState(); + + scheduleStateApplication(); + return m_owner->scheduleConfigure(); } @@ -328,7 +333,9 @@ uint32_t CXDGToplevelResource::setActive(bool active) { m_pendingApply.states.push_back(XDG_TOPLEVEL_STATE_ACTIVATED); else if (!active && set) std::erase(m_pendingApply.states, XDG_TOPLEVEL_STATE_ACTIVATED); - applyState(); + + scheduleStateApplication(); + return m_owner->scheduleConfigure(); } @@ -345,22 +352,32 @@ uint32_t CXDGToplevelResource::setSuspeneded(bool sus) { m_pendingApply.states.push_back(XDG_TOPLEVEL_STATE_SUSPENDED); else if (!sus && set) std::erase(m_pendingApply.states, XDG_TOPLEVEL_STATE_SUSPENDED); - applyState(); + + scheduleStateApplication(); + return m_owner->scheduleConfigure(); } -void CXDGToplevelResource::applyState() { - wl_array arr; - wl_array_init(&arr); +void CXDGToplevelResource::scheduleStateApplication() { - if (!m_pendingApply.states.empty()) { - wl_array_add(&arr, m_pendingApply.states.size() * sizeof(int)); - memcpy(arr.data, m_pendingApply.states.data(), m_pendingApply.states.size() * sizeof(int)); - } + if (m_stateUpdate) + return; - m_resource->sendConfigure(m_pendingApply.size.x, m_pendingApply.size.y, &arr); + m_stateUpdate = g_pEventLoopManager->doLaterLock([this] { + wl_array arr; + wl_array_init(&arr); + + if (!m_pendingApply.states.empty()) { + wl_array_add(&arr, m_pendingApply.states.size() * sizeof(int)); + memcpy(arr.data, m_pendingApply.states.data(), m_pendingApply.states.size() * sizeof(int)); + } + + m_resource->sendConfigure(m_pendingApply.size.x, m_pendingApply.size.y, &arr); + + wl_array_release(&arr); - wl_array_release(&arr); + m_stateUpdate.reset(); + }); } void CXDGToplevelResource::close() { @@ -516,8 +533,6 @@ CXDGSurfaceResource::CXDGSurfaceResource(SP resource_, SPresetRole(); } @@ -531,22 +546,19 @@ SP CXDGSurfaceResource::fromResource(wl_resource* res) { return data ? data->m_self.lock() : nullptr; } -static void onConfigure(void* data) { - sc(data)->configure(); -} - uint32_t CXDGSurfaceResource::scheduleConfigure() { - if (m_configureSource) + if (m_stateUpdate) return m_scheduledSerial; - m_configureSource = wl_event_loop_add_idle(g_pCompositor->m_wlEventLoop, onConfigure, this); + m_stateUpdate = g_pEventLoopManager->doLaterLock([this] { configure(); }); + m_scheduledSerial = wl_display_next_serial(g_pCompositor->m_wlDisplay); return m_scheduledSerial; } void CXDGSurfaceResource::configure() { - m_configureSource = nullptr; + m_stateUpdate.reset(); m_resource->sendConfigure(m_scheduledSerial); } diff --git a/src/protocols/XDGShell.hpp b/src/protocols/XDGShell.hpp index 3d94d282..79f15432 100644 --- a/src/protocols/XDGShell.hpp +++ b/src/protocols/XDGShell.hpp @@ -18,6 +18,7 @@ class CXDGPopupResource; class CSeatGrab; class CWLSurfaceResource; class CXDGDialogV1Resource; +struct SEventLoopDoLaterLock; struct SXDGPositionerState { Vector2D requestedSize; @@ -149,8 +150,11 @@ class CXDGToplevelResource { std::vector> m_children; private: - SP m_resource; - void applyState(); + SP m_resource; + + UP m_stateUpdate; + + void scheduleStateApplication(); }; class CXDGSurfaceRole : public ISurfaceRole { @@ -202,12 +206,12 @@ class CXDGSurfaceResource { void configure(); private: - SP m_resource; + SP m_resource; - uint32_t m_lastConfigureSerial = 0; - uint32_t m_scheduledSerial = 0; + UP m_stateUpdate; - wl_event_source* m_configureSource = nullptr; + uint32_t m_lastConfigureSerial = 0; + uint32_t m_scheduledSerial = 0; // std::vector> m_popups; -- cgit v1.2.3