hyprctl: add config full-reload for performing a ground-up reload (#14748)

allows to switch to/from lua at runtime
This commit is contained in:
Vaxry
2026-05-30 10:28:37 +01:00
committed by GitHub
parent 08b5c22b8f
commit e43b163f79
6 changed files with 97 additions and 36 deletions
+36 -1
View File
@@ -1,6 +1,8 @@
#include "ConfigValue.hpp"
#include "ConfigManager.hpp"
#include <algorithm>
void local__configValuePopulate(void* const** p, void* const** hlangp, std::type_index* ti, const std::string& val) {
const auto BIGP = Config::mgr()->getConfigValue(val);
@@ -18,4 +20,37 @@ void local__configValuePopulate(void* const** p, void* const** hlangp, std::type
std::type_index local__configValueTypeIdx(const std::string& val) {
const auto BIGP = Config::mgr()->getConfigValue(val);
return std::type_index(*BIGP.type);
}
}
CConfigValueBase::CConfigValueBase() {
registry().emplace_back(this);
}
CConfigValueBase::~CConfigValueBase() {
std::erase(registry(), this);
}
void CConfigValueBase::populateFromName() {
m_p = nullptr;
m_hlangp = nullptr;
m_typeIndex = typeid(void);
if (!m_valueName.empty())
local__configValuePopulate(&m_p, &m_hlangp, &m_typeIndex, m_valueName);
}
void CConfigValueBase::bindInternal(const std::string& val) {
m_valueName = val;
registry().push_back(this);
populateFromName();
}
std::vector<CConfigValueBase*>& CConfigValueBase::registry() {
static std::vector<CConfigValueBase*> r;
return r;
}
void CConfigValueBase::flushCaches() {
for (const auto& v : registry()) {
v->bindInternal(v->m_valueName);
}
}
+24 -21
View File
@@ -16,27 +16,35 @@
void local__configValuePopulate(void* const** p, void* const** hlangp, std::type_index* ti, const std::string& val);
std::type_index local__configValueTypeIdx(const std::string& val);
class CConfigValueBase {
protected:
std::string m_valueName;
void* const* m_p = nullptr;
void* const* m_hlangp = nullptr;
std::type_index m_typeIndex = typeid(void);
CConfigValueBase();
~CConfigValueBase();
void populateFromName();
void bindInternal(const std::string& val);
public:
static std::vector<CConfigValueBase*>& registry();
static void flushCaches();
};
template <typename T>
class CConfigValue {
class CConfigValue : private CConfigValueBase {
public:
// creates an empty value. Deref'ing this will be a crash
CConfigValue() = default;
explicit CConfigValue(const std::string& val) {
bind(val);
}
CConfigValue(const std::string& val) {
#ifdef HYPRLAND_DEBUG
// verify type
// TODO: fix this or leave it idk I'm tired.
// const auto TYPE = local__configValueTypeIdx(val);
// // exceptions
// const bool STRINGEX = (typeid(T) == typeid(std::string) && TYPE == typeid(Hyprlang::STRING));
// const bool CUSTOMEX = ((typeid(T) == typeid(Hyprlang::CUSTOMTYPE) || typeid(T) == typeid(Config::IComplexConfigValue)) &&
// (TYPE == typeid(Hyprlang::CUSTOMTYPE*) || TYPE == typeid(Config::IComplexConfigValue*) || TYPE == typeid(void*) /* dunno why it does this? */));
// RASSERT(typeid(T) == TYPE || STRINGEX || CUSTOMEX, "Mismatched type in CConfigValue<T>, got {} but has {}", typeid(T).name(), TYPE.name());
#endif
local__configValuePopulate(&m_p, &m_hlangp, &m_typeIndex, val);
void bind(const std::string& val) {
bindInternal(val);
}
T* ptr() const {
@@ -50,11 +58,6 @@ class CConfigValue {
bool good() const {
return m_p || m_hlangp;
}
private:
void* const* m_p = nullptr;
void* const* m_hlangp = nullptr;
std::type_index m_typeIndex = typeid(void);
};
template <>
+10 -12
View File
@@ -183,7 +183,16 @@ CConfigManager::SDeviceConfig::SDeviceConfig() {
}
CConfigManager::CConfigManager() : m_mainConfigPath(Supplementary::Jeremy::getMainConfigPath()->path) {
;
for (const auto& v : Values::CONFIG_VALUES) {
m_configValues.emplace(luaConfigValueName(v->name()), fromGenericValue(v));
}
m_configValues["autogenerated"] = fromGenericValue(makeShared<Values::CIntValue>("autogenerated", "whether the config is autogenerated or not", 0));
Config::watcher()->setOnChange([this](const CConfigWatcher::SConfigWatchEvent& e) {
Log::logger->log(Log::DEBUG, "[lua] file {} modified, reloading", e.file);
reload();
});
}
CConfigManager* CConfigManager::fromLuaState(lua_State* L) {
@@ -330,17 +339,6 @@ void CConfigManager::reinitLuaState() {
void CConfigManager::init() {
reinitLuaState();
for (const auto& v : Values::CONFIG_VALUES) {
m_configValues.emplace(luaConfigValueName(v->name()), fromGenericValue(v));
}
m_configValues["autogenerated"] = fromGenericValue(makeShared<Values::CIntValue>("autogenerated", "whether the config is autogenerated or not", 0));
Config::watcher()->setOnChange([this](const CConfigWatcher::SConfigWatchEvent& e) {
Log::logger->log(Log::DEBUG, "[lua] file {} modified, reloading", e.file);
reload();
});
reload();
}
+10 -2
View File
@@ -9,11 +9,19 @@ using namespace Config;
using namespace Config::Supplementary;
using namespace Config::Supplementary::Jeremy;
static bool needsPathRecheck = false;
//
void Jeremy::flushCachedCfgPath() {
needsPathRecheck = true;
}
std::expected<SConfigStateReply, std::string> Jeremy::getMainConfigPath() {
static bool lastSafeMode = g_pCompositor->m_safeMode;
static auto getCfgPath = []() -> std::expected<SConfigStateReply, std::string> {
lastSafeMode = g_pCompositor->m_safeMode;
lastSafeMode = g_pCompositor->m_safeMode;
needsPathRecheck = false;
if (g_pCompositor->m_safeMode)
return SConfigStateReply{.path = (std::filesystem::path{g_pCompositor->m_instancePath} / "recoverycfg.conf").string(), .type = CONFIG_TYPE_SPECIAL};
@@ -39,7 +47,7 @@ std::expected<SConfigStateReply, std::string> Jeremy::getMainConfigPath() {
};
static auto CONFIG_PATH = getCfgPath();
if (lastSafeMode != g_pCompositor->m_safeMode)
if (lastSafeMode != g_pCompositor->m_safeMode || needsPathRecheck)
CONFIG_PATH = getCfgPath();
return CONFIG_PATH;
@@ -18,4 +18,5 @@ namespace Config::Supplementary::Jeremy {
};
std::expected<SConfigStateReply, std::string> getMainConfigPath();
void flushCachedCfgPath();
};
+16
View File
@@ -42,6 +42,7 @@ using namespace Hyprutils::OS;
#include "../config/shared/workspace/WorkspaceRuleManager.hpp"
#include "../config/shared/monitor/MonitorRuleManager.hpp"
#include "../config/shared/animation/AnimationTree.hpp"
#include "../config/supplementary/jeremy/Jeremy.hpp"
#include "../config/values/ConfigValues.hpp"
#include "../managers/CursorManager.hpp"
#include "../errorOverlay/Overlay.hpp"
@@ -1233,6 +1234,21 @@ static std::string dispatchKeyword(eHyprCtlOutputFormat format, std::string in)
}
static std::string reloadRequest(eHyprCtlOutputFormat format, std::string request) {
if (request.ends_with("full-reset")) {
// perform a full config reset. First, reset config manager and load it anew. Then,
// flush all config value caches. This will momentarily degrade performance
// but a config load will be slow enough for this not to matter probably
Config::mgr().reset();
Config::Supplementary::Jeremy::flushCachedCfgPath();
Config::initConfigManager();
CConfigValueBase::flushCaches();
Config::mgr()->init();
CConfigValueBase::flushCaches();
return "ok";
}
Config::mgr()->reload();
return "ok";