#pragma once #include #include #include #include #include #include #include #include "../../helpers/memory/Memory.hpp" #include "../../helpers/signal/Signal.hpp" #include "../../desktop/DesktopTypes.hpp" extern "C" { #include } namespace Config::Lua { // Manages hl.on() event subscriptions for a single Lua state lifetime. // Destroyed (and recreated) on every config reload so callbacks never double-up. // // Hyprland objects (window, workspace, monitor, layer surface) are exposed to Lua // as typed userdata holding a weak pointer. Field accesses read live C++ state via // __index; accessing a field on a destroyed object raises a Lua error. class CLuaEventHandler { public: explicit CLuaEventHandler(lua_State* L); ~CLuaEventHandler(); // Store a Lua function (as a registry ref) to be called when `name` fires. // Returns a subscription handle, or std::nullopt if the event name is unknown. std::optional registerEvent(const std::string& name, int luaRef); bool unregisterEvent(uint64_t handle); void clearEvents(); static const std::unordered_set& knownEvents(); private: struct SSubscription { std::string eventName; int luaRef = -1; }; lua_State* m_lua = nullptr; std::unordered_map> m_callbacks; std::unordered_map m_subscriptions; std::unordered_set m_activeHandles; std::unordered_set m_reentrancyWarnedHandles; uint64_t m_nextHandle = 1; size_t m_dispatchDepth = 0; std::vector m_listeners; static constexpr size_t MAX_DISPATCH_DEPTH = 32; void dispatch(const std::string& name, int nargs, const std::function& pushArgs); }; }