Merge pull request #2568 from Syndelis/feat/hyprland-ignore-workspaces

This commit is contained in:
Alexis Rouillard 2023-10-12 07:32:56 +02:00 committed by GitHub
commit a3774dc586
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 9 deletions

View File

@ -9,6 +9,7 @@
#include <map>
#include <memory>
#include <optional>
#include <regex>
#include <string>
#include <vector>
@ -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<std::unique_ptr<Workspace>> workspaces_;
std::vector<Json::Value> workspaces_to_create_;
std::vector<std::string> workspaces_to_remove_;
std::vector<std::regex> ignore_workspaces_;
std::mutex mutex_;
const Bar& bar_;
Gtk::Box box_;

View File

@ -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*

View File

@ -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<std::mutex> 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);
}
}