diff --git a/README.md b/README.md index 07941e9..13f708d 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,12 @@ plugin { # 0 = always automatically split horizontally # = pixel height to split at trigger_height = # default: 0 + + # a space or comma separated list of workspace ids where autotile should be enabled + # it's possible to create an exception rule by prefixing the definition with "not:" + # workspaces = 1,2 # autotiling will only be enabled on workspaces 1 and 2 + # workspaces = not:1,2 # autotiling will be enabled on all workspaces except 1 and 2 + workspaces = # default: all } } } diff --git a/src/Hy3Layout.cpp b/src/Hy3Layout.cpp index 6afa1b1..7da1d2f 100644 --- a/src/Hy3Layout.cpp +++ b/src/Hy3Layout.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include "globals.hpp" #include "Hy3Layout.hpp" @@ -165,9 +167,12 @@ void Hy3Layout::onWindowCreatedTiling(CWindow* window, eDirection) { static const auto* at_trigger_height = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:autotile:trigger_height")->intValue; // clang-format on + this->updateAutotileWorkspaces(); + auto& target_group = opening_into->data.as_group; if (*at_enable && opening_after != nullptr && target_group.children.size() > 1 - && target_group.layout != Hy3GroupLayout::Tabbed) + && target_group.layout != Hy3GroupLayout::Tabbed + && this->shouldAutotileWorkspace(opening_into->workspace_id)) { auto is_horizontal = target_group.layout == Hy3GroupLayout::SplitH; auto trigger = is_horizontal ? *at_trigger_width : *at_trigger_height; @@ -1714,3 +1719,51 @@ Hy3Node* Hy3Layout::shiftOrGetFocus( return nullptr; } + +void Hy3Layout::updateAutotileWorkspaces() { + static const auto* autotile_raw_workspaces + = &HyprlandAPI::getConfigValue(PHANDLE, "plugin:hy3:autotile:workspaces")->strValue; + + if (*autotile_raw_workspaces == this->autotile.raw_workspaces) { + return; + } + + this->autotile.raw_workspaces = *autotile_raw_workspaces; + this->autotile.workspaces.clear(); + + if (this->autotile.raw_workspaces == "all") { + return; + } + + this->autotile.workspace_blacklist = this->autotile.raw_workspaces.rfind("not:", 0) == 0; + + const auto autotile_raw_workspaces_filtered = (this->autotile.workspace_blacklist) + ? this->autotile.raw_workspaces.substr(4) + : this->autotile.raw_workspaces; + + // split on space and comma + const std::regex regex {R"([\s,]+)"}; + const auto begin = std::sregex_token_iterator( + autotile_raw_workspaces_filtered.begin(), + autotile_raw_workspaces_filtered.end(), + regex, + -1 + ); + const auto end = std::sregex_token_iterator(); + + for (auto s = begin; s != end; ++s) { + try { + this->autotile.workspaces.insert(std::stoi(*s)); + } catch (...) { + hy3_log(ERR, "autotile:workspaces: invalid workspace id: {}", (std::string) *s); + } + } +} + +bool Hy3Layout::shouldAutotileWorkspace(int workspace_id) { + if (this->autotile.workspace_blacklist) { + return !this->autotile.workspaces.contains(workspace_id); + } else { + return this->autotile.workspaces.empty() || this->autotile.workspaces.contains(workspace_id); + } +} diff --git a/src/Hy3Layout.hpp b/src/Hy3Layout.hpp index 885e1b6..5aef41a 100644 --- a/src/Hy3Layout.hpp +++ b/src/Hy3Layout.hpp @@ -9,6 +9,7 @@ enum class GroupEphemeralityOption { }; #include +#include #include @@ -139,5 +140,14 @@ private: // nullptr. if once is true, only one group will be broken out of / into Hy3Node* shiftOrGetFocus(Hy3Node&, ShiftDirection, bool shift, bool once, bool visible); + void updateAutotileWorkspaces(); + bool shouldAutotileWorkspace(int); + + struct { + std::string raw_workspaces; + bool workspace_blacklist; + std::set workspaces; + } autotile; + friend struct Hy3Node; }; diff --git a/src/main.cpp b/src/main.cpp index 5185f2e..138ec7f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -43,6 +43,7 @@ APICALL EXPORT PLUGIN_DESCRIPTION_INFO PLUGIN_INIT(HANDLE handle) { CONF("autotile:ephemeral_groups", int, 1); CONF("autotile:trigger_height", int, 0); CONF("autotile:trigger_width", int, 0); + CONF("autotile:workspaces", str, "all"); #undef CONF