diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 1a01758e..544fa1d2 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -94,6 +95,7 @@ class Workspaces : public AModule, public EventHandler { std::string get_rewrite(std::string window_class); std::string& get_window_separator() { return format_window_separator_; } + bool is_workspace_ignored(std::string& workspace_name); private: void onEvent(const std::string&) override; @@ -140,6 +142,9 @@ class Workspaces : public AModule, public EventHandler { std::vector> workspaces_; std::vector workspaces_to_create_; std::vector workspaces_to_remove_; + + std::vector ignore_workspaces_; + std::mutex mutex_; const Bar& bar_; Gtk::Box box_; diff --git a/man/waybar-hyprland-workspaces.5.scd b/man/waybar-hyprland-workspaces.5.scd index 02be176d..cdbb0fd2 100644 --- a/man/waybar-hyprland-workspaces.5.scd +++ b/man/waybar-hyprland-workspaces.5.scd @@ -51,6 +51,11 @@ Addressed by *hyprland/workspaces* default: false ++ If set to true, only the active workspace will be shown. +*ignore-workspaces*: ++ + typeof: array ++ + default: [] ++ + Regexes to match against workspaces names. If there's a match, the workspace will not be shown. This takes precedence over *show-special*, *all-outputs* and *active-only*. + *sort-by*: ++ typeof: string ++ default: "default" ++ @@ -131,6 +136,14 @@ Additional to workspace name matching, the following *format-icons* can be set. } ``` +"hyprland/workspaces": { + // Formatting omitted for brevity + "ignore-workspaces": [ + "(special:)?chrome-sharing-indicator" + ] +} +``` + # Style - *#workspaces* diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 277a83ea..7936add4 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -73,6 +73,23 @@ auto Workspaces::parse_config(const Json::Value &config) -> void { } } + Json::Value ignore_workspaces = config["ignore-workspaces"]; + if (ignore_workspaces.isArray()) { + for (Json::Value &workspace_regex : ignore_workspaces) { + if (workspace_regex.isString()) { + std::string rule_string = workspace_regex.asString(); + try { + const std::regex rule{rule_string, std::regex_constants::icase}; + ignore_workspaces_.emplace_back(rule); + } catch (const std::regex_error &e) { + spdlog::error("Invalid rule {}: {}", rule_string, e.what()); + } + } else { + spdlog::error("Not a string: '{}'", workspace_regex); + } + } + } + Json::Value format_window_separator = config["format-window-separator"]; format_window_separator_ = format_window_separator.isString() ? format_window_separator.asString() : " "; @@ -156,6 +173,17 @@ bool isDoubleSpecial(std::string &workspace_name) { return workspace_name.find("special:special:") != std::string::npos; } +bool Workspaces::is_workspace_ignored(std::string &name) { + for (auto &rule : ignore_workspaces_) { + if (std::regex_match(name, rule)) { + return true; + break; + } + } + + return false; +} + void Workspaces::onEvent(const std::string &ev) { std::lock_guard lock(mutex_); std::string eventName(begin(ev), begin(ev) + ev.find_first_of('>')); @@ -170,16 +198,18 @@ void Workspaces::onEvent(const std::string &ev) { } } else if (eventName == "createworkspace") { const Json::Value workspaces_json = gIPC->getSocket1JsonReply("workspaces"); - for (Json::Value workspace_json : workspaces_json) { - std::string name = workspace_json["name"].asString(); - if (name == payload && - (all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) && - (show_special() || !name.starts_with("special")) && !isDoubleSpecial(payload)) { - workspaces_to_create_.push_back(workspace_json); - break; + + if (!is_workspace_ignored(payload)) { + for (Json::Value workspace_json : workspaces_json) { + std::string name = workspace_json["name"].asString(); + if (name == payload && + (all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) && + (show_special() || !name.starts_with("special")) && !isDoubleSpecial(payload)) { + workspaces_to_create_.push_back(workspace_json); + break; + } } } - } else if (eventName == "focusedmon") { active_workspace_name_ = payload.substr(payload.find(',') + 1); @@ -511,8 +541,10 @@ void Workspaces::init() { const Json::Value clients_json = gIPC->getSocket1JsonReply("clients"); for (Json::Value workspace_json : workspaces_json) { + std::string workspace_name = workspace_json["name"].asString(); if ((all_outputs() || bar_.output->name == workspace_json["monitor"].asString()) && - (!workspace_json["name"].asString().starts_with("special") || show_special())) { + (!workspace_name.starts_with("special") || show_special()) && + !is_workspace_ignored(workspace_name)) { create_workspace(workspace_json, clients_json); } }