diff --git a/src/config/ConfigDataValues.hpp b/src/config/ConfigDataValues.hpp index 14b5e51d..13277d10 100644 --- a/src/config/ConfigDataValues.hpp +++ b/src/config/ConfigDataValues.hpp @@ -1,10 +1,12 @@ #pragma once #include "../defines.hpp" +#include "helpers/VarList.hpp" #include enum eConfigValueDataTypes { - CVD_TYPE_INVALID = -1, - CVD_TYPE_GRADIENT = 0 + CVD_TYPE_INVALID = -1, + CVD_TYPE_GRADIENT = 0, + CVD_TYPE_CSS_VALUE = 1 }; class ICustomConfigValueData { @@ -50,3 +52,55 @@ class CGradientValueData : public ICustomConfigValueData { return true; } }; + +class CCssGapData : public ICustomConfigValueData { + public: + CCssGapData() : top(0), right(0), bottom(0), left(0){}; + CCssGapData(int64_t global) : top(global), right(global), bottom(global), left(global){}; + CCssGapData(int64_t vertical, int64_t horizontal) : top(vertical), right(horizontal), bottom(vertical), left(horizontal){}; + CCssGapData(int64_t top, int64_t horizontal, int64_t bottom) : top(top), right(horizontal), bottom(bottom), left(horizontal){}; + CCssGapData(int64_t top, int64_t right, int64_t bottom, int64_t left) : top(top), right(right), bottom(bottom), left(left){}; + + /* Css like directions */ + int64_t top; + int64_t right; + int64_t bottom; + int64_t left; + + void parseGapData(CVarList varlist) { + switch (varlist.size()) { + case 1: { + *this = CCssGapData(std::stoi(varlist[0])); + break; + } + case 2: { + *this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1])); + break; + } + case 3: { + *this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2])); + break; + } + case 4: { + *this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]), std::stoi(varlist[3])); + break; + } + default: { + Debug::log(WARN, "Too many arguments provided for gaps."); + *this = CCssGapData(std::stoi(varlist[0]), std::stoi(varlist[1]), std::stoi(varlist[2]), std::stoi(varlist[3])); + break; + } + } + } + + void reset(int64_t global) { + top = global; + right = global; + bottom = global; + left = global; + } + + virtual eConfigValueDataTypes getDataType() { + return CVD_TYPE_CSS_VALUE; + } +}; diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 3f6d58ae..6b54e984 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -2,6 +2,8 @@ #include "../managers/KeybindManager.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "config/ConfigDataValues.hpp" +#include "helpers/VarList.hpp" #include #include @@ -76,6 +78,31 @@ static void configHandleGradientDestroy(void** data) { delete reinterpret_cast(*data); } +static Hyprlang::CParseResult configHandleGapSet(const char* VALUE, void** data) { + std::string V = VALUE; + + if (!*data) + *data = new CCssGapData(); + + const auto DATA = reinterpret_cast(*data); + CVarList varlist(V); + Hyprlang::CParseResult result; + + try { + DATA->parseGapData(varlist); + } catch (...) { + std::string parseError = "Error parsing gaps " + V; + result.setError(parseError.c_str()); + } + + return result; +} + +static void configHandleGapDestroy(void** data) { + if (*data) + delete reinterpret_cast(*data); +} + static Hyprlang::CParseResult handleRawExec(const char* c, const char* v) { const std::string VALUE = v; const std::string COMMAND = c; @@ -279,8 +306,8 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("general:border_size", {1L}); m_pConfig->addConfigValue("general:no_border_on_floating", {0L}); m_pConfig->addConfigValue("general:border_part_of_window", {1L}); - m_pConfig->addConfigValue("general:gaps_in", {5L}); - m_pConfig->addConfigValue("general:gaps_out", {20L}); + m_pConfig->addConfigValue("general:gaps_in", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "5"}); + m_pConfig->addConfigValue("general:gaps_out", Hyprlang::CConfigCustomValueType{configHandleGapSet, configHandleGapDestroy, "20"}); m_pConfig->addConfigValue("general:gaps_workspaces", {0L}); m_pConfig->addConfigValue("general:cursor_inactive_timeout", {0L}); m_pConfig->addConfigValue("general:no_cursor_warps", {0L}); @@ -2116,12 +2143,22 @@ std::optional CConfigManager::handleWorkspaceRules(const std::strin auto assignRule = [&](std::string rule) -> std::optional { size_t delim = std::string::npos; - if ((delim = rule.find("gapsin:")) != std::string::npos) - wsRule.gapsIn = std::stoi(rule.substr(delim + 7)); - else if ((delim = rule.find("gapsout:")) != std::string::npos) - wsRule.gapsOut = std::stoi(rule.substr(delim + 8)); - else if ((delim = rule.find("bordersize:")) != std::string::npos) - wsRule.borderSize = std::stoi(rule.substr(delim + 11)); + if ((delim = rule.find("gapsin:")) != std::string::npos) { + CVarList varlist = CVarList(rule.substr(delim + 7), 0, ' '); + wsRule.gapsIn = CCssGapData(); + try { + wsRule.gapsIn->parseGapData(varlist); + } catch (...) { return "Error parsing workspace rule gaps: {}", rule.substr(delim + 7); } + } else if ((delim = rule.find("gapsout:")) != std::string::npos) { + CVarList varlist = CVarList(rule.substr(delim + 8), 0, ' '); + wsRule.gapsOut = CCssGapData(); + try { + wsRule.gapsOut->parseGapData(varlist); + } catch (...) { return "Error parsing workspace rule gaps: {}", rule.substr(delim + 8); } + } else if ((delim = rule.find("bordersize:")) != std::string::npos) + try { + wsRule.borderSize = std::stoi(rule.substr(delim + 11)); + } catch (...) { return "Error parsing workspace rule bordersize: {}", rule.substr(delim + 11); } else if ((delim = rule.find("border:")) != std::string::npos) wsRule.border = configStringToInt(rule.substr(delim + 7)); else if ((delim = rule.find("shadow:")) != std::string::npos) @@ -2264,4 +2301,4 @@ std::optional CConfigManager::handlePlugin(const std::string& comma m_vDeclaredPlugins.push_back(path); return {}; -} \ No newline at end of file +} diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 8bf2f7be..3784fa91 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -35,8 +35,8 @@ struct SWorkspaceRule { int workspaceId = -1; bool isDefault = false; bool isPersistent = false; - std::optional gapsIn; - std::optional gapsOut; + std::optional gapsIn; + std::optional gapsOut; std::optional borderSize; std::optional border; std::optional rounding; diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 70df8acd..c77e5e50 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -250,8 +249,11 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputF const std::string monitor = r.monitor.empty() ? "" : std::format(",\n \"monitor\": \"{}\"", escapeJSONStrings(r.monitor)); const std::string default_ = (bool)(r.isDefault) ? std::format(",\n \"default\": {}", boolToString(r.isDefault)) : ""; const std::string persistent = (bool)(r.isPersistent) ? std::format(",\n \"persistent\": {}", boolToString(r.isPersistent)) : ""; - const std::string gapsIn = (bool)(r.gapsIn) ? std::format(",\n \"gapsIn\": {}", r.gapsIn.value()) : ""; - const std::string gapsOut = (bool)(r.gapsOut) ? std::format(",\n \"gapsOut\": {}", r.gapsOut.value()) : ""; + const std::string gapsIn = + (bool)(r.gapsIn) ? std::format(",\n \"gapsIn\": {} {} {} {}", r.gapsIn.value().top, r.gapsIn.value().right, r.gapsIn.value().bottom, r.gapsIn.value().left) : ""; + const std::string gapsOut = (bool)(r.gapsOut) ? + std::format(",\n \"gapsOut\": {} {} {} {}", r.gapsOut.value().top, r.gapsOut.value().right, r.gapsOut.value().bottom, r.gapsOut.value().left) : + ""; const std::string borderSize = (bool)(r.borderSize) ? std::format(",\n \"borderSize\": {}", r.borderSize.value()) : ""; const std::string border = (bool)(r.border) ? std::format(",\n \"border\": {}", boolToString(r.border.value())) : ""; const std::string rounding = (bool)(r.rounding) ? std::format(",\n \"rounding\": {}", boolToString(r.rounding.value())) : ""; @@ -268,8 +270,12 @@ static std::string getWorkspaceRuleData(const SWorkspaceRule& r, eHyprCtlOutputF const std::string monitor = std::format("\tmonitor: {}\n", r.monitor.empty() ? "" : escapeJSONStrings(r.monitor)); const std::string default_ = std::format("\tdefault: {}\n", (bool)(r.isDefault) ? boolToString(r.isDefault) : ""); const std::string persistent = std::format("\tpersistent: {}\n", (bool)(r.isPersistent) ? boolToString(r.isPersistent) : ""); - const std::string gapsIn = std::format("\tgapsIn: {}\n", (bool)(r.gapsIn) ? std::to_string(r.gapsIn.value()) : ""); - const std::string gapsOut = std::format("\tgapsOut: {}\n", (bool)(r.gapsOut) ? std::to_string(r.gapsOut.value()) : ""); + const std::string gapsIn = (bool)(r.gapsIn) ? std::format("\tgapsIn: {} {} {} {}\n", std::to_string(r.gapsIn.value().top), std::to_string(r.gapsIn.value().right), + std::to_string(r.gapsIn.value().bottom), std::to_string(r.gapsIn.value().left)) : + std::format("\tgapsIn: \n"); + const std::string gapsOut = (bool)(r.gapsOut) ? std::format("\tgapsOut: {} {} {} {}\n", std::to_string(r.gapsOut.value().top), std::to_string(r.gapsOut.value().right), + std::to_string(r.gapsOut.value().bottom), std::to_string(r.gapsOut.value().left)) : + std::format("\tgapsOut: \n"); const std::string borderSize = std::format("\tborderSize: {}\n", (bool)(r.borderSize) ? std::to_string(r.borderSize.value()) : ""); const std::string border = std::format("\tborder: {}\n", (bool)(r.border) ? boolToString(r.border.value()) : ""); const std::string rounding = std::format("\trounding: {}\n", (bool)(r.rounding) ? boolToString(r.rounding.value()) : ""); diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index 5bdf8748..0f4a5f87 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -134,12 +134,14 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for PWINDOW->updateSpecialRenderData(); - static auto* const PGAPSIN = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in"); - static auto* const PGAPSOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out"); static auto* const PNOGAPSWHENONLY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("dwindle:no_gaps_when_only"); + static auto* const PGAPSINDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in"); + static auto* const PGAPSOUTDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out"); + auto* const PGAPSIN = (CCssGapData*)(*PGAPSINDATA)->getData(); + auto* const PGAPSOUT = (CCssGapData*)(*PGAPSOUTDATA)->getData(); - auto gapsIn = WORKSPACERULE.gapsIn.value_or(**PGAPSIN); - auto gapsOut = WORKSPACERULE.gapsOut.value_or(**PGAPSOUT); + auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); + auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); if (!g_pCompositor->windowExists(PWINDOW) || !PWINDOW->m_bIsMapped) { Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW); @@ -178,9 +180,9 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for auto calcPos = PWINDOW->m_vPosition; auto calcSize = PWINDOW->m_vSize; - const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn); + const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top); - const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut : gapsIn, DISPLAYBOTTOM ? gapsOut : gapsIn); + const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom); calcPos = calcPos + OFFSETTOPLEFT; calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 2f09396b..6a3cd492 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -1,6 +1,7 @@ #include "MasterLayout.hpp" #include "../Compositor.hpp" #include "../render/decorations/CHyprGroupBarDecoration.hpp" +#include "config/ConfigDataValues.hpp" #include SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(CWindow* pWindow) { @@ -633,13 +634,15 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { PWINDOW->updateSpecialRenderData(); - static auto* const PGAPSIN = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in"); - static auto* const PGAPSOUT = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out"); static auto* const PNOGAPSWHENONLY = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only"); static auto* const PANIMATE = (Hyprlang::INT* const*)g_pConfigManager->getConfigValuePtr("misc:animate_manual_resizes"); + static auto* const PGAPSINDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_in"); + static auto* const PGAPSOUTDATA = (Hyprlang::CUSTOMTYPE* const*)g_pConfigManager->getConfigValuePtr("general:gaps_out"); + auto* const PGAPSIN = (CCssGapData*)(*PGAPSINDATA)->getData(); + auto* const PGAPSOUT = (CCssGapData*)(*PGAPSOUTDATA)->getData(); - auto gapsIn = WORKSPACERULE.gapsIn.value_or(**PGAPSIN); - auto gapsOut = WORKSPACERULE.gapsOut.value_or(**PGAPSOUT); + auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN); + auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT); if (!g_pCompositor->windowValidMapped(PWINDOW)) { Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW); @@ -673,9 +676,9 @@ void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { auto calcPos = PWINDOW->m_vPosition; auto calcSize = PWINDOW->m_vSize; - const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut : gapsIn, DISPLAYTOP ? gapsOut : gapsIn); + const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top); - const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut : gapsIn, DISPLAYBOTTOM ? gapsOut : gapsIn); + const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom); calcPos = calcPos + OFFSETTOPLEFT; calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;