config: Config error limit/hyprctl (#5165)

* Add error_limit to limit the number of config error messages shown in notification

* Add configerrors hyprctl command

* Formatting

* Formatting for not my code

* Use CVarList, add escapeJSONStrings

* Add indication there are more undisplayed errors

* Restore suppress_errors; move getErrors() to ConfigManager

* Formatting, wtf

* Format
This commit is contained in:
zakk4223 2024-03-20 21:55:13 -04:00 committed by GitHub
parent 214ec82ba7
commit 4c796683c0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 54 additions and 3 deletions

View file

@ -372,6 +372,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("debug:damage_tracking", {(Hyprlang::INT)DAMAGE_TRACKING_FULL});
m_pConfig->addConfigValue("debug:manual_crash", Hyprlang::INT{0});
m_pConfig->addConfigValue("debug:suppress_errors", Hyprlang::INT{0});
m_pConfig->addConfigValue("debug:error_limit", Hyprlang::INT{5});
m_pConfig->addConfigValue("debug:watchdog_timeout", Hyprlang::INT{5});
m_pConfig->addConfigValue("debug:disable_scale_checks", Hyprlang::INT{0});
@ -609,6 +610,10 @@ std::string CConfigManager::getMainConfigPath() {
return getConfigDir() + "/hypr/" + (ISDEBUG ? "hyprlandd.conf" : "hyprland.conf");
}
std::string CConfigManager::getErrors() {
return m_szConfigErrors;
}
void CConfigManager::reload() {
EMIT_HOOK_EVENT("preConfigReload", nullptr);
setDefaultAnimationVars();
@ -740,6 +745,12 @@ void CConfigManager::postConfigReload(const Hyprlang::CParseResult& result) {
g_pHyprOpenGL->m_bReloadScreenShader = true;
// parseError will be displayed next frame
if (result.error)
m_szConfigErrors = result.getError();
else
m_szConfigErrors = "";
if (result.error && !std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("debug:suppress_errors")))
g_pHyprError->queueCreate(result.getError(), CColor(1.0, 50.0 / 255.0, 50.0 / 255.0, 1.0));
else if (std::any_cast<Hyprlang::INT>(m_pConfig->getConfigValue("autogenerated")) == 1)

View file

@ -142,6 +142,7 @@ class CConfigManager {
void addExecRule(const SExecRequestedRule&);
void handlePluginLoads();
std::string getErrors();
// keywords
std::optional<std::string> handleRawExec(const std::string&, const std::string&);
@ -193,6 +194,7 @@ class CConfigManager {
std::deque<std::string> firstExecRequests;
std::vector<std::pair<std::string, std::string>> m_vFailedPluginConfigValues; // for plugin values of unloaded plugins
std::string m_szConfigErrors = "";
// internal methods
void setAnimForChildren(SAnimationPropertyConfig* const);

View file

@ -17,6 +17,7 @@
#include "../config/ConfigValue.hpp"
#include "../managers/CursorManager.hpp"
#include "../hyprerror/HyprError.hpp"
static void trimTrailingComma(std::string& str) {
if (!str.empty() && str.back() == ',')
@ -497,6 +498,29 @@ std::string layoutsRequest(eHyprCtlOutputFormat format, std::string request) {
return result;
}
std::string configErrorsRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = "";
std::string currErrors = g_pConfigManager->getErrors();
CVarList errLines(currErrors, 0, '\n');
if (format == eHyprCtlOutputFormat::FORMAT_JSON) {
result += "[";
for (auto line : errLines) {
result += std::format(
R"#(
"{}",)#",
escapeJSONStrings(line));
}
trimTrailingComma(result);
result += "\n]\n";
} else {
for (auto line : errLines) {
result += std::format("{}\n", line);
}
}
return result;
}
std::string devicesRequest(eHyprCtlOutputFormat format, std::string request) {
std::string result = "";
@ -1531,6 +1555,7 @@ CHyprCtl::CHyprCtl() {
registerCommand(SHyprCtlCommand{"animations", true, animationsRequest});
registerCommand(SHyprCtlCommand{"rollinglog", true, rollinglogRequest});
registerCommand(SHyprCtlCommand{"layouts", true, layoutsRequest});
registerCommand(SHyprCtlCommand{"configerrors", true, configErrorsRequest});
registerCommand(SHyprCtlCommand{"monitors", false, monitorsRequest});
registerCommand(SHyprCtlCommand{"reload", false, reloadRequest});

View file

@ -1,5 +1,6 @@
#include "HyprError.hpp"
#include "../Compositor.hpp"
#include "../config/ConfigValue.hpp"
CHyprError::CHyprError() {
m_fFadeOpacity.create(AVARTYPE_FLOAT, g_pConfigManager->getAnimationPropertyConfig("fadeIn"), nullptr, AVARDAMAGE_NONE);
@ -58,6 +59,10 @@ void CHyprError::createQueued() {
cairo_restore(CAIRO);
const auto LINECOUNT = 1 + std::count(m_szQueued.begin(), m_szQueued.end(), '\n');
static auto LINELIMIT = CConfigValue<Hyprlang::INT>("debug:error_limit");
const auto VISLINECOUNT = std::min(LINECOUNT, *LINELIMIT);
const auto EXTRALINES = (VISLINECOUNT < LINECOUNT) ? 1 : 0;
const double DEGREES = M_PI / 180.0;
@ -66,7 +71,7 @@ void CHyprError::createQueued() {
const double X = PAD;
const double Y = PAD;
const double WIDTH = PMONITOR->vecPixelSize.x - PAD * 2;
const double HEIGHT = (FONTSIZE + 2 * (FONTSIZE / 10.0)) * LINECOUNT + 3;
const double HEIGHT = (FONTSIZE + 2 * (FONTSIZE / 10.0)) * (VISLINECOUNT + EXTRALINES) + 3;
const double RADIUS = PAD > HEIGHT / 2 ? HEIGHT / 2 - 1 : PAD;
m_bDamageBox = {0, 0, (int)PMONITOR->vecPixelSize.x, (int)HEIGHT + (int)PAD * 2};
@ -91,8 +96,9 @@ void CHyprError::createQueued() {
cairo_set_font_size(CAIRO, FONTSIZE);
cairo_set_source_rgba(CAIRO, textColor.r, textColor.g, textColor.b, textColor.a);
float yoffset = FONTSIZE;
while (m_szQueued != "") {
float yoffset = FONTSIZE;
int renderedcnt = 0;
while (m_szQueued != "" && renderedcnt < VISLINECOUNT) {
std::string current = m_szQueued.substr(0, m_szQueued.find('\n'));
if (const auto NEWLPOS = m_szQueued.find('\n'); NEWLPOS != std::string::npos)
m_szQueued = m_szQueued.substr(NEWLPOS + 1);
@ -101,7 +107,14 @@ void CHyprError::createQueued() {
cairo_move_to(CAIRO, PAD + 1 + RADIUS, yoffset + PAD + 1);
cairo_show_text(CAIRO, current.c_str());
yoffset += FONTSIZE + (FONTSIZE / 10.f);
renderedcnt++;
}
if (VISLINECOUNT < LINECOUNT) {
std::string moreString = std::format("({} more...)", LINECOUNT - VISLINECOUNT);
cairo_move_to(CAIRO, PAD + 1 + RADIUS, yoffset + PAD + 1);
cairo_show_text(CAIRO, moreString.c_str());
}
m_szQueued = "";
cairo_surface_flush(CAIROSURFACE);