mirror of
https://github.com/hyprwm/Hyprland.git
synced 2025-07-25 17:21:54 -07:00
core: add --verify-config to verify the config with Hyprland
fixes #9135
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <ranges>
|
||||
#include <print>
|
||||
#include <unordered_set>
|
||||
#include "debug/HyprCtl.hpp"
|
||||
#include "debug/CrashReporter.hpp"
|
||||
@@ -162,7 +163,10 @@ void CCompositor::restoreNofile() {
|
||||
Debug::log(ERR, "Failed restoring NOFILE limits");
|
||||
}
|
||||
|
||||
CCompositor::CCompositor() : m_iHyprlandPID(getpid()) {
|
||||
CCompositor::CCompositor(bool onlyConfig) : m_bOnlyConfigVerification(onlyConfig), m_iHyprlandPID(getpid()) {
|
||||
if (onlyConfig)
|
||||
return;
|
||||
|
||||
m_szHyprTempDataRoot = std::string{getenv("XDG_RUNTIME_DIR")} + "/hypr";
|
||||
|
||||
if (m_szHyprTempDataRoot.starts_with("/hypr")) {
|
||||
@@ -226,7 +230,7 @@ CCompositor::CCompositor() : m_iHyprlandPID(getpid()) {
|
||||
}
|
||||
|
||||
CCompositor::~CCompositor() {
|
||||
if (!m_bIsShuttingDown)
|
||||
if (!m_bIsShuttingDown && !m_bOnlyConfigVerification)
|
||||
cleanup();
|
||||
}
|
||||
|
||||
@@ -262,6 +266,16 @@ static bool filterGlobals(const wl_client* client, const wl_global* global, void
|
||||
//
|
||||
void CCompositor::initServer(std::string socketName, int socketFd) {
|
||||
|
||||
if (m_bOnlyConfigVerification) {
|
||||
g_pHookSystem = makeUnique<CHookSystemManager>();
|
||||
g_pKeybindManager = makeUnique<CKeybindManager>();
|
||||
g_pAnimationManager = makeUnique<CHyprAnimationManager>();
|
||||
g_pConfigManager = makeUnique<CConfigManager>();
|
||||
|
||||
std::println("\n\n======== Config parsing result:\n\n{}", g_pConfigManager->verify());
|
||||
return;
|
||||
}
|
||||
|
||||
m_sWLDisplay = wl_display_create();
|
||||
|
||||
wl_display_set_global_filter(m_sWLDisplay, ::filterGlobals, nullptr);
|
||||
|
@@ -24,7 +24,7 @@ enum eManagersInitStage : uint8_t {
|
||||
|
||||
class CCompositor {
|
||||
public:
|
||||
CCompositor();
|
||||
CCompositor(bool onlyConfig = false);
|
||||
~CCompositor();
|
||||
|
||||
wl_display* m_sWLDisplay;
|
||||
@@ -71,10 +71,11 @@ class CCompositor {
|
||||
bool m_bUnsafeState = false; // unsafe state is when there is no monitors.
|
||||
bool m_bNextIsUnsafe = false;
|
||||
PHLMONITORREF m_pUnsafeOutput; // fallback output for the unsafe state
|
||||
bool m_bIsShuttingDown = false;
|
||||
bool m_bFinalRequests = false;
|
||||
bool m_bDesktopEnvSet = false;
|
||||
bool m_bWantsXwayland = true;
|
||||
bool m_bIsShuttingDown = false;
|
||||
bool m_bFinalRequests = false;
|
||||
bool m_bDesktopEnvSet = false;
|
||||
bool m_bWantsXwayland = true;
|
||||
bool m_bOnlyConfigVerification = false;
|
||||
|
||||
// ------------------------------------------------- //
|
||||
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include "../render/Renderer.hpp"
|
||||
#include "../hyprerror/HyprError.hpp"
|
||||
#include "../managers/input/InputManager.hpp"
|
||||
#include "../managers/eventLoop/EventLoopManager.hpp"
|
||||
#include "../managers/LayoutManager.hpp"
|
||||
#include "../managers/EventManager.hpp"
|
||||
#include "../debug/HyprNotificationOverlay.hpp"
|
||||
@@ -730,15 +731,18 @@ CConfigManager::CConfigManager() {
|
||||
|
||||
resetHLConfig();
|
||||
|
||||
Debug::log(INFO,
|
||||
"!!!!HEY YOU, YES YOU!!!!: further logs to stdout / logfile are disabled by default. BEFORE SENDING THIS LOG, ENABLE THEM. Use debug:disable_logs = false to do so: "
|
||||
"https://wiki.hyprland.org/Configuring/Variables/#debug");
|
||||
if (!g_pCompositor->m_bOnlyConfigVerification) {
|
||||
Debug::log(
|
||||
INFO,
|
||||
"!!!!HEY YOU, YES YOU!!!!: further logs to stdout / logfile are disabled by default. BEFORE SENDING THIS LOG, ENABLE THEM. Use debug:disable_logs = false to do so: "
|
||||
"https://wiki.hyprland.org/Configuring/Variables/#debug");
|
||||
}
|
||||
|
||||
Debug::disableLogs = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:disable_logs")->getDataStaticPtr());
|
||||
Debug::disableTime = reinterpret_cast<int64_t* const*>(m_pConfig->getConfigValuePtr("debug:disable_time")->getDataStaticPtr());
|
||||
|
||||
if (ERR.has_value())
|
||||
g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0});
|
||||
if (g_pEventLoopManager && ERR.has_value())
|
||||
g_pEventLoopManager->doLater([ERR] { g_pHyprError->queueCreate(ERR.value(), CHyprColor{1.0, 0.1, 0.1, 1.0}); });
|
||||
}
|
||||
|
||||
std::optional<std::string> CConfigManager::generateConfig(std::string configPath) {
|
||||
@@ -820,11 +824,23 @@ void CConfigManager::reload() {
|
||||
EMIT_HOOK_EVENT("preConfigReload", nullptr);
|
||||
setDefaultAnimationVars();
|
||||
resetHLConfig();
|
||||
configCurrentPath = getMainConfigPath();
|
||||
const auto ERR = m_pConfig->parse();
|
||||
configCurrentPath = getMainConfigPath();
|
||||
const auto ERR = m_pConfig->parse();
|
||||
m_bLastConfigVerificationWasSuccessful = !ERR.error;
|
||||
postConfigReload(ERR);
|
||||
}
|
||||
|
||||
std::string CConfigManager::verify() {
|
||||
setDefaultAnimationVars();
|
||||
resetHLConfig();
|
||||
configCurrentPath = getMainConfigPath();
|
||||
const auto ERR = m_pConfig->parse();
|
||||
m_bLastConfigVerificationWasSuccessful = !ERR.error;
|
||||
if (ERR.error)
|
||||
return ERR.getError();
|
||||
return "config ok";
|
||||
}
|
||||
|
||||
void CConfigManager::setDefaultAnimationVars() {
|
||||
m_AnimationTree.createNode("__internal_fadeCTM");
|
||||
m_AnimationTree.createNode("global");
|
||||
|
@@ -144,6 +144,7 @@ class CConfigManager {
|
||||
|
||||
void init();
|
||||
void reload();
|
||||
std::string verify();
|
||||
|
||||
int getDeviceInt(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
float getDeviceFloat(const std::string&, const std::string&, const std::string& fallback = "");
|
||||
@@ -257,9 +258,10 @@ class CConfigManager {
|
||||
{"scrollmouse", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollMouse; }},
|
||||
{"scrolltouchpad", [](const PHLWINDOW& pWindow) { return &pWindow->m_sWindowData.scrollTouchpad; }}};
|
||||
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
|
||||
bool m_bWantsMonitorReload = false;
|
||||
bool m_bNoMonitorReload = false;
|
||||
bool isLaunchingExecOnce = false; // For exec-once to skip initial ws tracking
|
||||
bool m_bLastConfigVerificationWasSuccessful = true;
|
||||
|
||||
private:
|
||||
UP<Hyprlang::CConfig> m_pConfig;
|
||||
|
17
src/main.cpp
17
src/main.cpp
@@ -27,6 +27,7 @@ static void help() {
|
||||
--wayland-fd FD - Sets the Wayland socket fd (for Wayland socket handover)
|
||||
--systeminfo - Prints system infos
|
||||
--i-am-really-stupid - Omits root user privileges check (why would you do that?)
|
||||
--verify-config - Do not run Hyprland, only print if the config has any errors
|
||||
--version -v - Print this binary's version)");
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ int main(int argc, char** argv) {
|
||||
std::string configPath;
|
||||
std::string socketName;
|
||||
int socketFd = -1;
|
||||
bool ignoreSudo = false;
|
||||
bool ignoreSudo = false, verifyConfig = false;
|
||||
|
||||
std::vector<std::string> args{argv + 1, argv + argc};
|
||||
|
||||
@@ -124,6 +125,9 @@ int main(int argc, char** argv) {
|
||||
} else if (*it == "--systeminfo") {
|
||||
std::println("{}", systemInfoRequest(eHyprCtlOutputFormat::FORMAT_NORMAL, ""));
|
||||
return 0;
|
||||
} else if (*it == "--verify-config") {
|
||||
verifyConfig = true;
|
||||
continue;
|
||||
} else {
|
||||
std::println(stderr, "[ ERROR ] Unknown option '{}' !", *it);
|
||||
help();
|
||||
@@ -138,9 +142,8 @@ int main(int argc, char** argv) {
|
||||
" Hint: Use the --i-am-really-stupid flag to omit that check.");
|
||||
|
||||
return 1;
|
||||
} else if (ignoreSudo && NInit::isSudo()) {
|
||||
} else if (ignoreSudo && NInit::isSudo())
|
||||
std::println("Superuser privileges check is omitted. I hope you know what you're doing.");
|
||||
}
|
||||
|
||||
if (socketName.empty() ^ (socketFd == -1)) {
|
||||
std::println(stderr,
|
||||
@@ -150,12 +153,13 @@ int main(int argc, char** argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::println("Welcome to Hyprland!");
|
||||
if (!verifyConfig)
|
||||
std::println("Welcome to Hyprland!");
|
||||
|
||||
// let's init the compositor.
|
||||
// it initializes basic Wayland stuff in the constructor.
|
||||
try {
|
||||
g_pCompositor = makeUnique<CCompositor>();
|
||||
g_pCompositor = makeUnique<CCompositor>(verifyConfig);
|
||||
g_pCompositor->explicitConfigPath = configPath;
|
||||
} catch (const std::exception& e) {
|
||||
std::println(stderr, "Hyprland threw in ctor: {}\nCannot continue.", e.what());
|
||||
@@ -164,6 +168,9 @@ int main(int argc, char** argv) {
|
||||
|
||||
g_pCompositor->initServer(socketName, socketFd);
|
||||
|
||||
if (verifyConfig)
|
||||
return !g_pConfigManager->m_bLastConfigVerificationWasSuccessful;
|
||||
|
||||
if (!envEnabled("HYPRLAND_NO_RT"))
|
||||
NInit::gainRealTime();
|
||||
|
||||
|
@@ -34,7 +34,8 @@ static int wlTick(SP<CEventLoopTimer> self, void* data) {
|
||||
|
||||
CHyprAnimationManager::CHyprAnimationManager() {
|
||||
m_pAnimationTimer = SP<CEventLoopTimer>(new CEventLoopTimer(std::chrono::microseconds(500), wlTick, nullptr));
|
||||
g_pEventLoopManager->addTimer(m_pAnimationTimer);
|
||||
if (g_pEventLoopManager) // null in --verify-config mode
|
||||
g_pEventLoopManager->addTimer(m_pAnimationTimer);
|
||||
|
||||
addBezierWithName("linear", Vector2D(0.0, 0.0), Vector2D(1.0, 1.0));
|
||||
}
|
||||
|
@@ -172,8 +172,11 @@ CKeybindManager::CKeybindManager() {
|
||||
},
|
||||
nullptr);
|
||||
|
||||
g_pEventLoopManager->addTimer(m_pLongPressTimer);
|
||||
g_pEventLoopManager->addTimer(m_pRepeatKeyTimer);
|
||||
// null in --verify-config mode
|
||||
if (g_pEventLoopManager) {
|
||||
g_pEventLoopManager->addTimer(m_pLongPressTimer);
|
||||
g_pEventLoopManager->addTimer(m_pRepeatKeyTimer);
|
||||
}
|
||||
|
||||
static auto P = g_pHookSystem->hookDynamic("configReloaded", [this](void* hk, SCallbackInfo& info, std::any param) {
|
||||
// clear cuz realloc'd
|
||||
|
Reference in New Issue
Block a user