diff --git a/meta/generateLuaStubs.py b/meta/generateLuaStubs.py index 4bf1a7b7e..873ccdda1 100644 --- a/meta/generateLuaStubs.py +++ b/meta/generateLuaStubs.py @@ -541,7 +541,7 @@ def generate_stub(root: Path) -> str: "hl.get_workspace": "fun(selector: HL.WorkspaceSelector): HL.Workspace|nil", "hl.get_active_workspace": "fun(monitor?: HL.MonitorSelector): HL.Workspace|nil", "hl.get_active_special_workspace": "fun(monitor?: HL.MonitorSelector): HL.Workspace|nil", - "hl.get_monitors": "fun(): HL.Monitor[]", + "hl.get_monitors": "fun(options?: HL.GetMonitorsOptions): HL.Monitor[]", "hl.get_monitor": "fun(selector: HL.MonitorSelector): HL.Monitor|nil", "hl.get_active_monitor": "fun(): HL.Monitor|nil", "hl.get_monitor_at": "fun(x: number|HL.Vec2, y?: number): HL.Monitor|nil", @@ -690,6 +690,16 @@ def generate_stub(root: Path) -> str: ) lines.append("") + lines.extend( + emit_class_block( + "HL.GetMonitorsOptions", + [ + ("all", "boolean", True), + ], + ) + ) + lines.append("") + lines.extend( emit_class_block( "HL.GestureSpec", diff --git a/src/config/lua/bindings/LuaBindingsQuery.cpp b/src/config/lua/bindings/LuaBindingsQuery.cpp index d2504f817..d662fb445 100644 --- a/src/config/lua/bindings/LuaBindingsQuery.cpp +++ b/src/config/lua/bindings/LuaBindingsQuery.cpp @@ -16,6 +16,8 @@ #include "../../../state/MonitorState.hpp" #include "../../../state/WorkspaceState.hpp" +#include + using namespace Config; using namespace Config::Lua; using namespace Config::Lua::Bindings; @@ -202,12 +204,33 @@ static int hlGetActiveSpecialWorkspace(lua_State* L) { } static int hlGetMonitors(lua_State* L) { + bool allMonitors = false; + + if (!lua_isnoneornil(L, 1)) { + if (!lua_istable(L, 1)) + return Internal::configError(L, "hl.get_monitors: expected no args or a table of options"); + + { + lua_getfield(L, 1, "all"); + Hyprutils::Utils::CScopeGuard x([L] { lua_pop(L, 1); }); + + if (!lua_isnil(L, -1)) { + const auto all = Check::boolean(L, -1); + if (!all) + return Internal::configError(L, "hl.get_monitors: option 'all': {}", all.error()); + + allMonitors = *all; + } + } + } + lua_newtable(L); int i = 1; - for (const auto& mon : State::monitorState()->monitors()) { + for (const auto& mon : allMonitors ? State::monitorState()->allMonitors() : State::monitorState()->monitors()) { Objects::CLuaMonitor::push(L, mon); lua_rawseti(L, -2, i++); } + return 1; } diff --git a/src/config/lua/objects/LuaMonitor.cpp b/src/config/lua/objects/LuaMonitor.cpp index 69c5989d0..7564038ca 100644 --- a/src/config/lua/objects/LuaMonitor.cpp +++ b/src/config/lua/objects/LuaMonitor.cpp @@ -144,6 +144,8 @@ static int monitorIndex(lua_State* L) { lua_pushinteger(L, sc(mon->m_transform)); else if (key == "dpms_status") lua_pushboolean(L, mon->m_dpmsStatus); + else if (key == "enabled") + lua_pushboolean(L, mon->enabled()); else if (key == "vrr_active") lua_pushboolean(L, mon->m_vrrActive); else if (key == "is_mirror") diff --git a/tests/config/lua/LuaBindingsInternal.cpp b/tests/config/lua/LuaBindingsInternal.cpp index 71948fa8c..18836f6c0 100644 --- a/tests/config/lua/LuaBindingsInternal.cpp +++ b/tests/config/lua/LuaBindingsInternal.cpp @@ -303,6 +303,27 @@ TEST(ConfigLuaBindingsInternal, pluginBindingIsTableWithLoadFunction) { lua_pop(L, 2); } +TEST(ConfigLuaBindingsInternal, getMonitorsReadsOptionsFromArguments) { + CLuaState state; + const auto lua = state.get(); + + lua_newtable(lua); + Internal::registerQueryBindings(lua); + lua_setglobal(lua, "hl"); + + ASSERT_EQ(luaL_dostring(lua, R"( + assert(type(hl.get_monitors()) == "table") + assert(type(hl.get_monitors(nil)) == "table") + assert(type(hl.get_monitors({})) == "table") + assert(type(hl.get_monitors({ all = false })) == "table") + assert(type(hl.get_monitors({ all = true })) == "table") + assert(hl.get_monitors({ all = "true" }) == nil) + assert(hl.get_monitors(true) == nil) + )"), + LUA_OK) + << lua_tostring(lua, -1); +} + TEST(ConfigLuaBindingsInternal, deprecationNoticesOnlyIncludeUsedDeprecatedValues) { CScopedCompositor compositor; CLuaState state;