From 5ba33f846129f3e6c0505b19f94634b24505e828 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sun, 26 Apr 2026 15:16:36 +0100 Subject: config/lua: init lua config manager, use lua if available (#13817) Adds a new lua config manager, which will automatically be used if there is a lua config present. --- src/debug/HyprCtl.cpp | 126 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 95 insertions(+), 31 deletions(-) (limited to 'src/debug/HyprCtl.cpp') diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index fd9cad75..bb575ce5 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -34,13 +34,14 @@ using namespace Hyprutils::OS; #include "../config/shared/complex/ComplexDataTypes.hpp" #include "../config/legacy/ConfigManager.hpp" +#include "../config/lua/ConfigManager.hpp" #include "../config/ConfigValue.hpp" #include "../config/shared/complex/ComplexDataTypes.hpp" #include "../config/shared/inotify/ConfigWatcher.hpp" #include "../config/shared/workspace/WorkspaceRuleManager.hpp" #include "../config/shared/monitor/MonitorRuleManager.hpp" #include "../config/shared/animation/AnimationTree.hpp" -#include "../config/supplementary/ConfigDescriptions.hpp" +#include "../config/values/ConfigValues.hpp" #include "../managers/CursorManager.hpp" #include "../errorOverlay/Overlay.hpp" #include "../devices/IPointer.hpp" @@ -1013,7 +1014,7 @@ static std::string bindsRequest(eHyprCtlOutputFormat format, std::string request ret += "d"; ret += std::format("\n\tmodmask: {}\n\tsubmap: {}\n\tkey: {}\n\tkeycode: {}\n\tcatchall: {}\n\tdescription: {}\n\tdispatcher: {}\n\targ: {}\n\n", kb->modmask, - kb->submap.name, kb->key, kb->keycode, kb->catchAll, kb->description, kb->handler, kb->arg); + kb->submap.name, kb->key.empty() ? kb->displayKey : kb->key, kb->keycode, kb->catchAll, kb->description, kb->handler, kb->arg); } } else { // json @@ -1246,10 +1247,39 @@ std::string systemInfoRequest(eHyprCtlOutputFormat format, std::string request) return result; } +static std::string evalRequest(eHyprCtlOutputFormat format, std::string request) { + if (Config::mgr()->type() != Config::CONFIG_LUA) + return "eval is only supported with the lua config manager"; + + auto luaMgr = dynamicPointerCast(WP(Config::mgr())); + + // strip the command name ("eval ") from the request + auto code = request.substr(request.find_first_of(' ') + 1); + + auto err = luaMgr->eval(code); + if (err) + return std::format("error: {}", *err); + + return "ok"; +} + static std::string dispatchRequest(eHyprCtlOutputFormat format, std::string in) { // get rid of the dispatch keyword in = in.substr(in.find_first_of(' ') + 1); + if (Config::mgr()->type() == Config::CONFIG_LUA) { + // For lua, this is just a wrapper for `eval("hl.dispatch(in)") + std::string evalStr = std::format("hl.dispatch({})", in); + auto luaMgr = dynamicPointerCast(WP(Config::mgr())); + auto ret = luaMgr->eval(evalStr).value_or("ok"); + + if (ret.starts_with("ok") || in.contains("(") /* this likely means the user is passing a valid lua dispatch string */) + return ret; + + // the user likely is trying to dispatch old hyprlang stuff via lua, let them know + return ret + "\n\n → Note: dispatch in lua is a shorthand for hl.dispatch(...), your syntax might need to be updated."; + } + const auto DISPATCHSTR = in.substr(0, in.find_first_of(' ')); auto DISPATCHARG = std::string(); @@ -1335,7 +1365,7 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in) // decorations will probably need a repaint if (COMMAND.contains("decoration:") || COMMAND.contains("border") || COMMAND == "workspace" || COMMAND.contains("zoom_factor") || COMMAND == "source") { - static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); + static auto PZOOMFACTOR = CConfigValue("cursor:zoom_factor"); for (auto const& m : g_pCompositor->m_monitors) { *(m->m_cursorZoom) = *PZOOMFACTOR; g_pHyprRenderer->damageMonitor(m); @@ -1599,22 +1629,22 @@ static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string requ }; auto borderColorToString = [&](bool active) -> std::string { - static auto PACTIVECOL = CConfigValue("general:col.active_border"); - static auto PINACTIVECOL = CConfigValue("general:col.inactive_border"); - static auto PNOGROUPACTIVECOL = CConfigValue("general:col.nogroup_border_active"); - static auto PNOGROUPINACTIVECOL = CConfigValue("general:col.nogroup_border"); - static auto PGROUPACTIVECOL = CConfigValue("group:col.border_active"); - static auto PGROUPINACTIVECOL = CConfigValue("group:col.border_inactive"); - static auto PGROUPACTIVELOCKEDCOL = CConfigValue("group:col.border_locked_active"); - static auto PGROUPINACTIVELOCKEDCOL = CConfigValue("group:col.border_locked_inactive"); + static auto PACTIVECOL = CConfigValue("general:col.active_border"); + static auto PINACTIVECOL = CConfigValue("general:col.inactive_border"); + static auto PNOGROUPACTIVECOL = CConfigValue("general:col.nogroup_border_active"); + static auto PNOGROUPINACTIVECOL = CConfigValue("general:col.nogroup_border"); + static auto PGROUPACTIVECOL = CConfigValue("group:col.border_active"); + static auto PGROUPINACTIVECOL = CConfigValue("group:col.border_inactive"); + static auto PGROUPACTIVELOCKEDCOL = CConfigValue("group:col.border_locked_active"); + static auto PGROUPINACTIVELOCKEDCOL = CConfigValue("group:col.border_locked_inactive"); const bool GROUPLOCKED = PWINDOW->m_group ? PWINDOW->m_group->locked() : false; if (active) { - auto* const ACTIVECOL = (Config::CGradientValueData*)(PACTIVECOL.ptr())->getData(); - auto* const NOGROUPACTIVECOL = (Config::CGradientValueData*)(PNOGROUPACTIVECOL.ptr())->getData(); - auto* const GROUPACTIVECOL = (Config::CGradientValueData*)(PGROUPACTIVECOL.ptr())->getData(); - auto* const GROUPACTIVELOCKEDCOL = (Config::CGradientValueData*)(PGROUPACTIVELOCKEDCOL.ptr())->getData(); + auto* const ACTIVECOL = (Config::CGradientValueData*)(PACTIVECOL.ptr()); + auto* const NOGROUPACTIVECOL = (Config::CGradientValueData*)(PNOGROUPACTIVECOL.ptr()); + auto* const GROUPACTIVECOL = (Config::CGradientValueData*)(PGROUPACTIVECOL.ptr()); + auto* const GROUPACTIVELOCKEDCOL = (Config::CGradientValueData*)(PGROUPACTIVELOCKEDCOL.ptr()); const auto* const ACTIVECOLOR = !PWINDOW->m_group ? (!(PWINDOW->m_groupRules & Desktop::View::GROUP_DENY) ? ACTIVECOL : NOGROUPACTIVECOL) : (GROUPLOCKED ? GROUPACTIVELOCKEDCOL : GROUPACTIVECOL); @@ -1624,10 +1654,10 @@ static std::string dispatchGetProp(eHyprCtlOutputFormat format, std::string requ else return std::format(R"({{"{}": "{}"}})", PROP, borderColorString); } else { - auto* const INACTIVECOL = (Config::CGradientValueData*)(PINACTIVECOL.ptr())->getData(); - auto* const NOGROUPINACTIVECOL = (Config::CGradientValueData*)(PNOGROUPINACTIVECOL.ptr())->getData(); - auto* const GROUPINACTIVECOL = (Config::CGradientValueData*)(PGROUPINACTIVECOL.ptr())->getData(); - auto* const GROUPINACTIVELOCKEDCOL = (Config::CGradientValueData*)(PGROUPINACTIVELOCKEDCOL.ptr())->getData(); + auto* const INACTIVECOL = (Config::CGradientValueData*)(PINACTIVECOL.ptr()); + auto* const NOGROUPINACTIVECOL = (Config::CGradientValueData*)(PNOGROUPINACTIVECOL.ptr()); + auto* const GROUPINACTIVECOL = (Config::CGradientValueData*)(PGROUPINACTIVECOL.ptr()); + auto* const GROUPINACTIVELOCKEDCOL = (Config::CGradientValueData*)(PGROUPINACTIVELOCKEDCOL.ptr()); const auto* const INACTIVECOLOR = !PWINDOW->m_group ? (!(PWINDOW->m_groupRules & Desktop::View::GROUP_DENY) ? INACTIVECOL : NOGROUPINACTIVECOL) : (GROUPLOCKED ? GROUPINACTIVELOCKEDCOL : GROUPINACTIVECOL); @@ -1771,6 +1801,8 @@ static std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string re return std::format("float: {:2f}\nset: {}", **rc(VAL), VAR.setByUser); else if (TYPE == typeid(Config::VEC2)) return std::format("vec2: [{}, {}]\nset: {}", (*rc(VAL))->x, (*rc(VAL))->y, VAR.setByUser); + else if (TYPE == typeid(Hyprlang::VEC2)) + return std::format("vec2: [{}, {}]\nset: {}", (*rc(VAL))->x, (*rc(VAL))->y, VAR.setByUser); else if (TYPE == typeid(Hyprlang::STRING)) return std::format("str: {}\nset: {}", *rc(VAL), VAR.setByUser); else if (TYPE == typeid(Config::STRING)) @@ -1785,6 +1817,9 @@ static std::string dispatchGetOption(eHyprCtlOutputFormat format, std::string re else if (TYPE == typeid(Config::VEC2)) return std::format(R"({{"option": "{}", "vec2": [{},{}], "set": {} }})", curitem, (*rc(VAL))->x, (*rc(VAL))->y, VAR.setByUser); + else if (TYPE == typeid(Hyprlang::VEC2)) + return std::format(R"({{"option": "{}", "vec2": [{},{}], "set": {} }})", curitem, (*rc(VAL))->x, (*rc(VAL))->y, + VAR.setByUser); else if (TYPE == typeid(Hyprlang::STRING)) return std::format(R"({{"option": "{}", "str": "{}", "set": {} }})", curitem, escapeJSONStrings(*rc(VAL)), VAR.setByUser); else if (TYPE == typeid(Config::STRING)) @@ -2043,18 +2078,7 @@ static std::string getIsLocked(eHyprCtlOutputFormat format, std::string request) } static std::string getDescriptions(eHyprCtlOutputFormat format, std::string request) { - std::string json = "["; - const auto& DESCS = Config::Supplementary::CONFIG_OPTIONS; - - for (const auto& d : DESCS) { - json += d.jsonify() + ",\n"; - } - - json.pop_back(); - json.pop_back(); - - json += "]\n"; - return json; + return Config::Values::getAsJson(); } static std::string submapRequest(eHyprCtlOutputFormat format, std::string request) { @@ -2065,6 +2089,43 @@ static std::string submapRequest(eHyprCtlOutputFormat format, std::string reques return format == FORMAT_JSON ? std::format("\"{}\"\n", escapeJSONStrings(submap)) : (submap + "\n"); } +static std::string statusRequest(eHyprCtlOutputFormat format, std::string request) { + Aquamarine::eBackendType backendType = Aquamarine::eBackendType::AQ_BACKEND_NULL; + + for (const auto& i : g_pCompositor->m_aqBackend->getImplementations()) { + if (i->type() == Aquamarine::eBackendType::AQ_BACKEND_NULL || i->type() == Aquamarine::eBackendType::AQ_BACKEND_HEADLESS) + continue; + + backendType = i->type(); + break; + } + + std::string backendStr; + + switch (backendType) { + case Aquamarine::AQ_BACKEND_DRM: backendStr = "drm"; break; + case Aquamarine::AQ_BACKEND_WAYLAND: backendStr = "wayland"; break; + default: backendStr = "error"; break; + } + + if (format == eHyprCtlOutputFormat::FORMAT_JSON) { + + return std::format(R"#( +{{ + "configProvider": "{}", + "backend": "{}" +}} +)#", + Config::typeToString(Config::mgr()->type()), backendStr); + } + + return std::format(R"#( +configProvider: {} +backend: {} +)#", + Config::typeToString(Config::mgr()->type()), backendStr); +} + static std::string reloadShaders(eHyprCtlOutputFormat format, std::string request) { CVarList vars(request, 0, ' '); @@ -2098,6 +2159,7 @@ CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"locked", true, getIsLocked}); registerCommand(SHyprCtlCommand{"descriptions", true, getDescriptions}); registerCommand(SHyprCtlCommand{"submap", true, submapRequest}); + registerCommand(SHyprCtlCommand{"status", true, statusRequest}); registerCommand(SHyprCtlCommand{.name = "reloadshaders", .exact = false, .fn = reloadShaders}); registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest}); @@ -2115,6 +2177,7 @@ CHyprCtl::CHyprCtl() { registerCommand(SHyprCtlCommand{"getoption", false, dispatchGetOption}); registerCommand(SHyprCtlCommand{"decorations", false, decorationRequest}); registerCommand(SHyprCtlCommand{"[[BATCH]]", false, dispatchBatch}); + registerCommand(SHyprCtlCommand{"eval", false, evalRequest}); startHyprCtlSocket(); } @@ -2200,6 +2263,7 @@ std::string CHyprCtl::getReply(std::string request) { if (reloadAll) { Config::monitorRuleMgr()->scheduleReload(); + Layout::Supplementary::algoMatcher()->updateWorkspaceLayouts(); g_pInputManager->setKeyboardLayout(); // update kb layout g_pInputManager->setPointerConfigs(); // update mouse cfgs -- cgit v1.2.3