diff --git a/example/hypr.conf b/example/hypr.conf index 15c69c6..dc548f0 100644 --- a/example/hypr.conf +++ b/example/hypr.conf @@ -53,6 +53,11 @@ Animations { borders=0 } +# window rules +windowrule=float,class:krunner +windowrule=float,role:pop-up +windowrule=float,role:task_dialog + # keybinds bind=SUPER,R,exec,dmenu_run bind=SUPER,Q,exec,kitty diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 1f5938b..c2928cd 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -249,6 +249,26 @@ void parseAnimLine(const std::string& line) { configSetValueSafe("anim:" + COMMAND, VALUE); } +void handleWindowRule(const std::string& command, const std::string& value) { + const auto RULE = value.substr(0, value.find_first_of(",")); + const auto VALUE = value.substr(value.find_first_of(",") + 1); + + // check rule and value + if (RULE == "" || VALUE == "") { + return; + } + + // verify we support a rule + if (RULE != "float" + && RULE != "tile") { + Debug::log(ERR, "Invalid rule found: " + RULE); + ConfigManager::parseError = "Invalid rule found: " + RULE; + return; + } + + ConfigManager::windowRules.push_back({RULE, VALUE}); +} + void parseLine(std::string& line) { // first check if its not a comment const auto COMMENTSTART = line.find_first_of('#'); @@ -312,6 +332,9 @@ void parseLine(std::string& line) { } else if (COMMAND == "status_command") { handleStatusCommand(COMMAND, VALUE); return; + } else if (COMMAND == "windowrule") { + handleWindowRule(COMMAND, VALUE); + return; } configSetValueSafe(COMMAND, VALUE); @@ -322,6 +345,7 @@ void ConfigManager::loadConfigLoadVars() { Debug::log(LOG, "Reloading the config!"); ConfigManager::parseError = ""; // reset the error ConfigManager::currentCategory = ""; // reset the category + ConfigManager::windowRules.clear(); // Clear rules if (loadBar && g_pWindowManager->statusBar) { // clear modules as we overwrite them diff --git a/src/config/ConfigManager.hpp b/src/config/ConfigManager.hpp index 8ed21b3..4920241 100644 --- a/src/config/ConfigManager.hpp +++ b/src/config/ConfigManager.hpp @@ -3,6 +3,7 @@ #include #include "../utilities/Debug.hpp" #include +#include enum ELayouts { LAYOUT_DWINDLE = 0, @@ -15,6 +16,11 @@ struct SConfigValue { std::string strValue = ""; }; +struct SWindowRule { + std::string szRule; + std::string szValue; +}; + namespace ConfigManager { inline std::unordered_map configValues; inline time_t lastModifyTime = 0; @@ -27,6 +33,8 @@ namespace ConfigManager { inline std::string parseError = ""; // For storing a parse error to display later + inline std::vector windowRules; + void init(); void loadConfigLoadVars(); void tick(); diff --git a/src/defines.hpp b/src/defines.hpp index 95a39b5..a437088 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include "./helpers/Vector.hpp" #include "./utilities/Debug.hpp" diff --git a/src/windowManager.cpp b/src/windowManager.cpp index 3f5e4ca..49584a8 100644 --- a/src/windowManager.cpp +++ b/src/windowManager.cpp @@ -1579,8 +1579,25 @@ bool CWindowManager::shouldBeFloatedOnInit(int64_t window) { xcb_change_property(DisplayConnection, XCB_PROP_MODE_REPLACE, window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen("hypr"), "hypr"); - if (((std::string)CLASSNAME).find("krunner") != std::string::npos) { - return true; + // Verify the class (rules) + for (auto& rule : ConfigManager::windowRules) { + // check if we have a class rule + if (rule.szValue.find("class:") != 0) + continue; + + // regex check the arg + std::regex classCheck(rule.szValue.substr(strlen("class:"))); + + if (!std::regex_search(CLASSNAME, classCheck)) + continue; + + // applies. Read the rule and behave accordingly + Debug::log(LOG, "Window rule " + rule.szRule + "," + rule.szValue + " matched."); + + if (rule.szRule == "tile") + return false; + else if (rule.szRule == "float") + return true; } @@ -1589,10 +1606,25 @@ bool CWindowManager::shouldBeFloatedOnInit(int64_t window) { Debug::log(LOG, "Window opened with a role of " + WINROLE); - if (WINROLE.find("pop-up") != std::string::npos || WINROLE.find("task_dialog") != std::string::npos) { - return true; - } + for (auto& rule : ConfigManager::windowRules) { + // check if we have a role rule + if (rule.szValue.find("role:") != 0) + continue; + // regex check the arg + std::regex roleCheck(rule.szValue.substr(strlen("role:"))); + + if (!std::regex_search(WINROLE, roleCheck)) + continue; + + // applies. Read the rule and behave accordingly + Debug::log(LOG, "Window rule " + rule.szRule + "," + rule.szValue + " matched."); + + if (rule.szRule == "tile") + return false; + else if (rule.szRule == "float") + return true; + } // // Type stuff