From 8d057e6f96beaf5429e3c251f32f46135787f715 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 9 Oct 2023 13:53:00 -0300 Subject: [PATCH 1/8] refactor: separate regex rule matching and caching in separate class --- include/modules/hyprland/workspaces.hpp | 13 +++-- include/util/regex_collection.hpp | 37 +++++++++++++ meson.build | 3 +- src/modules/hyprland/workspaces.cpp | 61 ++++++++++++---------- src/util/regex_collection.cpp | 69 +++++++++++++++++++++++++ src/util/rewrite_string.cpp | 28 ---------- 6 files changed, 149 insertions(+), 62 deletions(-) create mode 100644 include/util/regex_collection.hpp create mode 100644 src/util/regex_collection.cpp diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 1a01758e..67fa6fc8 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -16,8 +16,10 @@ #include "bar.hpp" #include "modules/hyprland/backend.hpp" #include "util/enum.hpp" +#include "util/regex_collection.hpp" using WindowAddress = std::string; + namespace waybar::modules::hyprland { class Workspaces; @@ -47,7 +49,7 @@ class Workspace { void set_windows(uint value) { windows_ = value; }; void set_name(std::string value) { name_ = value; }; bool contains_window(WindowAddress addr) { return window_map_.contains(addr); } - void insert_window(WindowAddress addr, std::string window_repr); + void insert_window(WindowAddress addr, std::string window_class, std::string window_title); std::string remove_window(WindowAddress addr); void initialize_window_map(const Json::Value& clients_data); @@ -92,7 +94,7 @@ class Workspaces : public AModule, public EventHandler { auto get_bar_output() const -> std::string { return bar_.output->name; } - std::string get_rewrite(std::string window_class); + std::string get_rewrite(std::string window_class, std::string window_title); std::string& get_window_separator() { return format_window_separator_; } private: @@ -129,11 +131,12 @@ class Workspaces : public AModule, public EventHandler { bool persistent_created_ = false; std::string format_; + std::map icons_map_; - Json::Value window_rewrite_rules_; - std::map regex_cache_; + util::RegexCollection window_rewrite_rules_; + bool any_window_rewrite_rule_uses_title_ = false; std::string format_window_separator_; - std::string window_rewrite_default_; + bool with_icon_; uint64_t monitor_id_; std::string active_workspace_name_; diff --git a/include/util/regex_collection.hpp b/include/util/regex_collection.hpp new file mode 100644 index 00000000..267bb726 --- /dev/null +++ b/include/util/regex_collection.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include + +#include +#include +#include + +namespace waybar::util { + +struct Rule { + std::regex rule; + std::string repr; + int priority; +}; + +int default_priority_function(std::string& key); + +class RegexCollection { + private: + std::vector rules; + std::map regex_cache; + std::string default_repr; + + std::string& find_match(std::string& value, bool& matched_any); + + public: + RegexCollection() = default; + RegexCollection(const Json::Value& map, std::string default_repr = "", + std::function priority_function = default_priority_function); + ~RegexCollection() = default; + + std::string& get(std::string& value, bool& matched_any); + std::string& get(std::string& value); +}; + +} // namespace waybar::util \ No newline at end of file diff --git a/meson.build b/meson.build index 9ccd83d8..15bab87c 100644 --- a/meson.build +++ b/meson.build @@ -177,7 +177,8 @@ src_files = files( 'src/util/ustring_clen.cpp', 'src/util/sanitize_str.cpp', 'src/util/rewrite_string.cpp', - 'src/util/gtk_icon.cpp' + 'src/util/gtk_icon.cpp', + 'src/util/regex_collection.cpp' ) inc_dirs = ['include'] diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 277a83ea..c3ddb4e5 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -1,19 +1,34 @@ #include "modules/hyprland/workspaces.hpp" -#include #include #include #include #include #include -#include #include -#include "util/rewrite_string.hpp" +#include "util/regex_collection.hpp" namespace waybar::modules::hyprland { +int window_rewrite_priority_function(std::string &window_rule) { + // Rules that match against title are prioritized + // Rules that don't specify if they're matching against either title or class are deprioritized + bool has_title = window_rule.find("title") != std::string::npos; + bool has_class = window_rule.find("class") != std::string::npos; + + if (has_title && has_class) { + return 3; + } else if (has_title) { + return 2; + } else if (has_class) { + return 1; + } else { + return 0; + } +} + Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config) : AModule(config, "workspaces", id, false, false), bar_(bar), @@ -77,11 +92,14 @@ auto Workspaces::parse_config(const Json::Value &config) -> void { format_window_separator_ = format_window_separator.isString() ? format_window_separator.asString() : " "; - window_rewrite_rules_ = config["window-rewrite"]; + Json::Value window_rewrite = config["window-rewrite"]; - Json::Value window_rewrite_default = config["window-rewrite-default"]; - window_rewrite_default_ = - window_rewrite_default.isString() ? window_rewrite_default.asString() : "?"; + Json::Value window_rewrite_default_config = config["window-rewrite-default"]; + std::string window_rewrite_default = + window_rewrite_default_config.isString() ? window_rewrite_default_config.asString() : "?"; + + window_rewrite_rules_ = util::RegexCollection(window_rewrite, window_rewrite_default, + window_rewrite_priority_function); } auto Workspaces::register_ipc() -> void { @@ -323,13 +341,14 @@ void Workspace::initialize_window_map(const Json::Value &clients_data) { // {ADDR} WindowAddress client_address = client["address"].asString(); client_address = client_address.substr(2, client_address.length() - 2); - insert_window(client_address, client["class"].asString()); + insert_window(client_address, client["class"].asString(), client["title"].asString()); } } } -void Workspace::insert_window(WindowAddress addr, std::string window_class) { - auto window_repr = workspace_manager_.get_rewrite(window_class); +void Workspace::insert_window(WindowAddress addr, std::string window_class, + std::string window_title) { + auto window_repr = workspace_manager_.get_rewrite(window_class, window_title); if (!window_repr.empty()) { window_map_.emplace(addr, window_repr); } @@ -355,7 +374,7 @@ bool Workspace::on_window_opened(WindowAddress &addr, std::string &workspace_nam bool Workspace::on_window_opened(WindowAddress &addr, std::string &workspace_name, std::string &window_class, std::string &window_title) { if (workspace_name == name()) { - insert_window(addr, window_class); + insert_window(addr, window_class, window_title); return true; } else { return false; @@ -766,23 +785,9 @@ void Workspaces::set_urgent_workspace(std::string windowaddress) { } } -std::string Workspaces::get_rewrite(std::string window_class) { - if (regex_cache_.contains(window_class)) { - return regex_cache_[window_class]; - } - - bool matched_any; - - std::string window_class_rewrite = - waybar::util::rewriteStringOnce(window_class, window_rewrite_rules_, matched_any); - - if (!matched_any) { - window_class_rewrite = window_rewrite_default_; - } - - regex_cache_.emplace(window_class, window_class_rewrite); - - return window_class_rewrite; +std::string Workspaces::get_rewrite(std::string window_class, std::string window_title) { + std::string window_repr_key = fmt::format("class<{}> title<{}>", window_class, window_title); + return window_rewrite_rules_.get(window_repr_key); } } // namespace waybar::modules::hyprland diff --git a/src/util/regex_collection.cpp b/src/util/regex_collection.cpp new file mode 100644 index 00000000..df0879c1 --- /dev/null +++ b/src/util/regex_collection.cpp @@ -0,0 +1,69 @@ +#include "util/regex_collection.hpp" + +#include +#include + +namespace waybar::util { + +int default_priority_function(std::string& key) { return 0; } + +RegexCollection::RegexCollection(const Json::Value& map, std::string default_repr, + std::function priority_function) + : default_repr(default_repr) { + if (!map.isObject()) { + spdlog::warn("Mapping is not an object"); + return; + } + + for (auto it = map.begin(); it != map.end(); ++it) { + if (it.key().isString() && it->isString()) { + std::string key = it.key().asString(); + int priority = priority_function(key); + try { + const std::regex rule{key, std::regex_constants::icase}; + rules.emplace_back(rule, it->asString(), priority); + } catch (const std::regex_error& e) { + spdlog::error("Invalid rule '{}': {}", key, e.what()); + } + } + } + + std::sort(rules.begin(), rules.end(), [](Rule& a, Rule& b) { return a.priority > b.priority; }); +} + +std::string& RegexCollection::find_match(std::string& value, bool& matched_any) { + for (auto& rule : rules) { + if (std::regex_search(value, rule.rule)) { + matched_any = true; + return rule.repr; + } + } + + return value; +} + +std::string& RegexCollection::get(std::string& value, bool& matched_any) { + if (regex_cache.contains(value)) { + return regex_cache[value]; + } + + // std::string repr = + // waybar::util::find_match(value, window_rewrite_rules_, matched_any); + + std::string repr = find_match(value, matched_any); + + if (!matched_any) { + repr = default_repr; + } + + regex_cache.emplace(value, repr); + + return regex_cache[value]; // Necessary in order to return a reference to the heap +} + +std::string& RegexCollection::get(std::string& value) { + bool matched_any = false; + return get(value, matched_any); +} + +} // namespace waybar::util \ No newline at end of file diff --git a/src/util/rewrite_string.cpp b/src/util/rewrite_string.cpp index 475f8a3d..3f6ae4ca 100644 --- a/src/util/rewrite_string.cpp +++ b/src/util/rewrite_string.cpp @@ -1,6 +1,5 @@ #include "util/rewrite_string.hpp" -#include #include #include @@ -30,31 +29,4 @@ std::string rewriteString(const std::string& value, const Json::Value& rules) { return res; } - -std::string rewriteStringOnce(const std::string& value, const Json::Value& rules, - bool& matched_any) { - if (!rules.isObject()) { - return value; - } - - matched_any = false; - - std::string res = value; - - for (auto it = rules.begin(); it != rules.end(); ++it) { - if (it.key().isString() && it->isString()) { - try { - const std::regex rule{it.key().asString(), std::regex_constants::icase}; - if (std::regex_match(value, rule)) { - matched_any = true; - return std::regex_replace(res, rule, it->asString()); - } - } catch (const std::regex_error& e) { - spdlog::error("Invalid rule {}: {}", it.key().asString(), e.what()); - } - } - } - - return value; -} } // namespace waybar::util From fad43d4b1676390dd6ec86da73c6ca89ae08a84f Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 9 Oct 2023 14:42:53 -0300 Subject: [PATCH 2/8] feat: listen to windowtitle IPC event condiationally to update window rules --- include/modules/hyprland/workspaces.hpp | 4 ++- src/modules/hyprland/workspaces.cpp | 40 +++++++++++++++++++++---- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 67fa6fc8..1ab90457 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -48,7 +48,7 @@ class Workspace { void set_visible(bool value = true) { is_visible_ = value; }; void set_windows(uint value) { windows_ = value; }; void set_name(std::string value) { name_ = value; }; - bool contains_window(WindowAddress addr) { return window_map_.contains(addr); } + bool contains_window(WindowAddress addr) const { return window_map_.contains(addr); } void insert_window(WindowAddress addr, std::string window_class, std::string window_title); std::string remove_window(WindowAddress addr); void initialize_window_map(const Json::Value& clients_data); @@ -113,6 +113,8 @@ class Workspaces : public AModule, public EventHandler { void on_window_closed(std::string payload); void on_window_moved(std::string payload); + int window_rewrite_priority_function(std::string& window_rule); + bool all_outputs_ = false; bool show_special_ = false; bool active_only_ = false; diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index c3ddb4e5..ebd0e67b 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -12,15 +12,17 @@ namespace waybar::modules::hyprland { -int window_rewrite_priority_function(std::string &window_rule) { +int Workspaces::window_rewrite_priority_function(std::string &window_rule) { // Rules that match against title are prioritized // Rules that don't specify if they're matching against either title or class are deprioritized bool has_title = window_rule.find("title") != std::string::npos; bool has_class = window_rule.find("class") != std::string::npos; if (has_title && has_class) { + any_window_rewrite_rule_uses_title_ = true; return 3; } else if (has_title) { + any_window_rewrite_rule_uses_title_ = true; return 2; } else if (has_class) { return 1; @@ -98,8 +100,10 @@ auto Workspaces::parse_config(const Json::Value &config) -> void { std::string window_rewrite_default = window_rewrite_default_config.isString() ? window_rewrite_default_config.asString() : "?"; - window_rewrite_rules_ = util::RegexCollection(window_rewrite, window_rewrite_default, - window_rewrite_priority_function); + window_rewrite_rules_ = util::RegexCollection( + window_rewrite, window_rewrite_default, [this](std::string &window_rule) { + return this->window_rewrite_priority_function(window_rule); + }); } auto Workspaces::register_ipc() -> void { @@ -119,6 +123,13 @@ auto Workspaces::register_ipc() -> void { gIPC->registerForIPC("closewindow", this); gIPC->registerForIPC("movewindow", this); gIPC->registerForIPC("urgent", this); + + if (any_window_rewrite_rule_uses_title_) { + spdlog::info( + "Registering for Hyprland's 'windowtitle' events because a user-defined window " + "rewrite rule uses the 'title' field."); + gIPC->registerForIPC("windowtitle", this); + } } auto Workspaces::update() -> void { @@ -240,6 +251,25 @@ void Workspaces::onEvent(const std::string &ev) { break; } } + } else if (eventName == "windowtitle") { + auto window_workspace = + std::find_if(workspaces_.begin(), workspaces_.end(), + [payload](auto &workspace) { return workspace->contains_window(payload); }); + + if (window_workspace != workspaces_.end()) { + Json::Value clients_data = gIPC->getSocket1JsonReply("clients"); + std::string json_window_address = fmt::format("0x{}", payload); + + auto client = std::find_if(clients_data.begin(), clients_data.end(), + [json_window_address](auto &client) { + return client["address"].asString() == json_window_address; + }); + + if (!client->empty()) { + (*window_workspace) + ->insert_window(payload, (*client)["class"].asString(), (*client)["title"].asString()); + } + } } dp.emit(); @@ -350,7 +380,7 @@ void Workspace::insert_window(WindowAddress addr, std::string window_class, std::string window_title) { auto window_repr = workspace_manager_.get_rewrite(window_class, window_title); if (!window_repr.empty()) { - window_map_.emplace(addr, window_repr); + window_map_[addr] = window_repr; } }; @@ -364,7 +394,7 @@ std::string Workspace::remove_window(WindowAddress addr) { bool Workspace::on_window_opened(WindowAddress &addr, std::string &workspace_name, std::string window_repr) { if (workspace_name == name()) { - window_map_.emplace(addr, window_repr); + window_map_[addr] = window_repr; return true; } else { return false; From 387e54498e60736eea136551aaa2dd78f096eedc Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 9 Oct 2023 14:46:57 -0300 Subject: [PATCH 3/8] docs: document new regex collection class --- include/util/regex_collection.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/util/regex_collection.hpp b/include/util/regex_collection.hpp index 267bb726..14f28611 100644 --- a/include/util/regex_collection.hpp +++ b/include/util/regex_collection.hpp @@ -16,6 +16,14 @@ struct Rule { int default_priority_function(std::string& key); +/* A collection of regexes and strings, with a default string to return if no regexes. + * When a regex is matched, the corresponding string is returned. + * All regexes that are matched are cached, so that the regexes are only + * evaluated once against a given string. + * Regexes may be given a higher priority than others, so that they are matched + * first. The priority function is given the regex string, and should return a + * higher number for higher priority regexes. + */ class RegexCollection { private: std::vector rules; From f9a7ecf3a9a82bb4f48da3df87e5fd64631395fa Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 9 Oct 2023 14:49:38 -0300 Subject: [PATCH 4/8] feat: optimize cache usage when window titles aren't involved --- src/modules/hyprland/workspaces.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index ebd0e67b..b8dc5e00 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -816,7 +816,12 @@ void Workspaces::set_urgent_workspace(std::string windowaddress) { } std::string Workspaces::get_rewrite(std::string window_class, std::string window_title) { - std::string window_repr_key = fmt::format("class<{}> title<{}>", window_class, window_title); + std::string window_repr_key; + if (any_window_rewrite_rule_uses_title_) { + window_repr_key = fmt::format("class<{}> title<{}>", window_class, window_title); + } else { + window_repr_key = fmt::format("class<{}>", window_class); + } return window_rewrite_rules_.get(window_repr_key); } From 592d5645a5d684cab18fe3e0688ac24329acfe26 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 9 Oct 2023 14:58:21 -0300 Subject: [PATCH 5/8] docs: include new feature in manual --- man/waybar-hyprland-workspaces.5.scd | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/man/waybar-hyprland-workspaces.5.scd b/man/waybar-hyprland-workspaces.5.scd index 02be176d..6bbc1407 100644 --- a/man/waybar-hyprland-workspaces.5.scd +++ b/man/waybar-hyprland-workspaces.5.scd @@ -25,6 +25,7 @@ Addressed by *hyprland/workspaces* typeof: object ++ Regex rules to map window class to an icon or preferred method of representation for a workspace's window. Keys are the rules, while the values are the methods of representation. + Rules may specify `class<...>`, `title<...>` or both in order to fine-tune the matching. *window-rewrite-default*: typeof: string ++ @@ -124,8 +125,10 @@ Additional to workspace name matching, the following *format-icons* can be set. "format-window-separator": "\n", "window-rewrite-default": "", "window-rewrite": { - "firefox": "", - "foot": "", + "title<.*youtube.*>": "", // Windows whose titles contain "youtube" + "class": "", // Windows whose classes are "firefox" + "class title<.*github.*>": "", // Windows whose class is "firefox" and title contains "github". Note that "class" always comes first. + "foot": "", // Windows that contain "foot" in either class or title. For optimization reasons, it will only match against a title if at least one other window explicitly matches against a title. "code": "󰨞", } } From f8340d88be67ed4492eca45dc24667fa5393c4c2 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Mon, 9 Oct 2023 15:26:07 -0300 Subject: [PATCH 6/8] chore: lint unrelated file this file was edited in #2558 but not linted --- src/modules/disk.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/disk.cpp b/src/modules/disk.cpp index ae1e5cf5..ef257b72 100644 --- a/src/modules/disk.cpp +++ b/src/modules/disk.cpp @@ -49,9 +49,9 @@ auto waybar::modules::Disk::update() -> void { float specific_free, specific_used, specific_total, divisor; divisor = calc_specific_divisor(unit_); - specific_free = (stats.f_bavail * stats.f_frsize)/divisor; - specific_used = ((stats.f_blocks - stats.f_bfree) * stats.f_frsize)/divisor; - specific_total = (stats.f_blocks * stats.f_frsize)/divisor; + specific_free = (stats.f_bavail * stats.f_frsize) / divisor; + specific_used = ((stats.f_blocks - stats.f_bfree) * stats.f_frsize) / divisor; + specific_total = (stats.f_blocks * stats.f_frsize) / divisor; auto free = pow_format(stats.f_bavail * stats.f_frsize, "B", true); auto used = pow_format((stats.f_blocks - stats.f_bfree) * stats.f_frsize, "B", true); @@ -72,7 +72,7 @@ auto waybar::modules::Disk::update() -> void { fmt::runtime(format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), fmt::arg("total", total), - fmt::arg("path", path_), fmt::arg("specific_free", specific_free), + fmt::arg("path", path_), fmt::arg("specific_free", specific_free), fmt::arg("specific_used", specific_used), fmt::arg("specific_total", specific_total))); } @@ -85,7 +85,7 @@ auto waybar::modules::Disk::update() -> void { fmt::runtime(tooltip_format), stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), fmt::arg("total", total), - fmt::arg("path", path_), fmt::arg("specific_free", specific_free), + fmt::arg("path", path_), fmt::arg("specific_free", specific_free), fmt::arg("specific_used", specific_used), fmt::arg("specific_total", specific_total))); } // Call parent update @@ -109,7 +109,7 @@ float waybar::modules::Disk::calc_specific_divisor(std::string divisor) { return 1000.0 * 1000.0 * 1000.0 * 1000.0; } else if (divisor == "TiB") { return 1024.0 * 1024.0 * 1024.0 * 1024.0; - } else { //default to Bytes if it is anything that we don't recongnise + } else { // default to Bytes if it is anything that we don't recongnise return 1.0; } } \ No newline at end of file From ee652677a6fed6b4579e2eec3e93adac138db914 Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Wed, 11 Oct 2023 11:40:49 -0300 Subject: [PATCH 7/8] feat: ignore windows with empty classes or titles (if any rule uses title) --- include/modules/hyprland/workspaces.hpp | 2 ++ src/modules/hyprland/workspaces.cpp | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index 1ab90457..9f259614 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -97,6 +97,8 @@ class Workspaces : public AModule, public EventHandler { std::string get_rewrite(std::string window_class, std::string window_title); std::string& get_window_separator() { return format_window_separator_; } + bool window_rewrite_config_uses_title() const { return any_window_rewrite_rule_uses_title_; } + private: void onEvent(const std::string&) override; void update_window_count(); diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index b8dc5e00..3be2acf2 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -124,7 +124,7 @@ auto Workspaces::register_ipc() -> void { gIPC->registerForIPC("movewindow", this); gIPC->registerForIPC("urgent", this); - if (any_window_rewrite_rule_uses_title_) { + if (window_rewrite_config_uses_title()) { spdlog::info( "Registering for Hyprland's 'windowtitle' events because a user-defined window " "rewrite rule uses the 'title' field."); @@ -378,7 +378,13 @@ void Workspace::initialize_window_map(const Json::Value &clients_data) { void Workspace::insert_window(WindowAddress addr, std::string window_class, std::string window_title) { + if (window_class.empty() && + (!workspace_manager_.window_rewrite_config_uses_title() || window_title.empty())) { + return; + } + auto window_repr = workspace_manager_.get_rewrite(window_class, window_title); + if (!window_repr.empty()) { window_map_[addr] = window_repr; } @@ -817,7 +823,7 @@ void Workspaces::set_urgent_workspace(std::string windowaddress) { std::string Workspaces::get_rewrite(std::string window_class, std::string window_title) { std::string window_repr_key; - if (any_window_rewrite_rule_uses_title_) { + if (window_rewrite_config_uses_title()) { window_repr_key = fmt::format("class<{}> title<{}>", window_class, window_title); } else { window_repr_key = fmt::format("class<{}>", window_class); From c59264d6b4447663e3886f79741b531bffd4b74c Mon Sep 17 00:00:00 2001 From: Brenno Lemos Date: Thu, 12 Oct 2023 17:30:32 -0300 Subject: [PATCH 8/8] fix: clang < 16 can't emplace back struct with no constructor --- include/util/regex_collection.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/include/util/regex_collection.hpp b/include/util/regex_collection.hpp index 14f28611..5ea2882e 100644 --- a/include/util/regex_collection.hpp +++ b/include/util/regex_collection.hpp @@ -12,6 +12,12 @@ struct Rule { std::regex rule; std::string repr; int priority; + + // Fix for Clang < 16 + // See https://en.cppreference.com/w/cpp/compiler_support/20 "Parenthesized initialization of + // aggregates" + Rule(std::regex rule, std::string repr, int priority) + : rule(rule), repr(repr), priority(priority) {} }; int default_priority_function(std::string& key);