summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/managers/eventLoop/EventLoopManager.cpp38
-rw-r--r--src/managers/eventLoop/EventLoopManager.hpp19
-rw-r--r--src/protocols/XDGShell.cpp58
-rw-r--r--src/protocols/XDGShell.hpp16
4 files changed, 93 insertions, 38 deletions
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<void()>& fn) {
- m_idle.fns.emplace_back(fn);
+uint64_t CEventLoopManager::doLater(const std::function<void()>& 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<void()>& 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<SEventLoopDoLaterLock> CEventLoopManager::doLaterLock(const std::function<void()>& fn) {
+ return makeUnique<SEventLoopDoLaterLock>(doLater(fn));
}
void CEventLoopManager::doOnReadable(CFileDescriptor fd, std::function<void()>&& 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<void()>& 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<void()>& fn);
+ void removeDoLater(uint64_t seq);
+
+ // automatically cleaned up doLater instance
+ [[nodiscard]] UP<SEventLoopDoLaterLock> doLaterLock(const std::function<void()>& fn);
struct SIdleData {
- wl_event_source* eventSource = nullptr;
- std::vector<std::function<void()>> fns;
+ wl_event_source* eventSource = nullptr;
+ std::vector<std::pair<uint64_t, std::function<void()>>> fns;
};
struct SReadableWaiter {
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<CXdgSurface> resource_, SP<CXDGWMBas
CXDGSurfaceResource::~CXDGSurfaceResource() {
m_events.destroy.emit();
- if (m_configureSource)
- wl_event_source_remove(m_configureSource);
if (m_surface)
m_surface->resetRole();
}
@@ -531,22 +546,19 @@ SP<CXDGSurfaceResource> CXDGSurfaceResource::fromResource(wl_resource* res) {
return data ? data->m_self.lock() : nullptr;
}
-static void onConfigure(void* data) {
- sc<CXDGSurfaceResource*>(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<WP<CXDGToplevelResource>> m_children;
private:
- SP<CXdgToplevel> m_resource;
- void applyState();
+ SP<CXdgToplevel> m_resource;
+
+ UP<SEventLoopDoLaterLock> m_stateUpdate;
+
+ void scheduleStateApplication();
};
class CXDGSurfaceRole : public ISurfaceRole {
@@ -202,12 +206,12 @@ class CXDGSurfaceResource {
void configure();
private:
- SP<CXdgSurface> m_resource;
+ SP<CXdgSurface> m_resource;
- uint32_t m_lastConfigureSerial = 0;
- uint32_t m_scheduledSerial = 0;
+ UP<SEventLoopDoLaterLock> m_stateUpdate;
- wl_event_source* m_configureSource = nullptr;
+ uint32_t m_lastConfigureSerial = 0;
+ uint32_t m_scheduledSerial = 0;
//
std::vector<WP<CXDGPopupResource>> m_popups;