feat(hyprland/workspaces): grouping icons

This commit is contained in:
eonphi
2026-02-14 16:37:35 +01:00
parent e4e47cad5c
commit 736c053350
3 changed files with 59 additions and 6 deletions
+4
View File
@@ -61,6 +61,8 @@ class Workspaces : public AModule, public EventHandler {
std::string getRewrite(std::string window_class, std::string window_title); std::string getRewrite(std::string window_class, std::string window_title);
std::string& getWindowSeparator() { return m_formatWindowSeparator; } std::string& getWindowSeparator() { return m_formatWindowSeparator; }
auto windowRewriteGroupThreshold() const -> int { return m_windowRewriteGroupThreshold; }
auto const& getWindowRewriteGroupFormat() const { return m_windowRewriteGroupFormat; }
bool isWorkspaceIgnored(std::string const& workspace_name); bool isWorkspaceIgnored(std::string const& workspace_name);
bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; } bool windowRewriteConfigUsesTitle() const { return m_anyWindowRewriteRuleUsesTitle; }
@@ -172,6 +174,8 @@ class Workspaces : public AModule, public EventHandler {
util::RegexCollection m_windowRewriteRules; util::RegexCollection m_windowRewriteRules;
bool m_anyWindowRewriteRuleUsesTitle = false; bool m_anyWindowRewriteRuleUsesTitle = false;
std::string m_formatWindowSeparator; std::string m_formatWindowSeparator;
int m_windowRewriteGroupThreshold = 0;
std::string m_windowRewriteGroupFormat = "{icon}×{count}";
bool m_withIcon; bool m_withIcon;
uint64_t m_monitorId; uint64_t m_monitorId;
+45 -6
View File
@@ -1,6 +1,7 @@
#include <json/value.h> #include <json/value.h>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <algorithm>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
@@ -245,15 +246,53 @@ void Workspace::update(const std::string& workspace_icon) {
// need to compute this if enableTaskbar() is true // need to compute this if enableTaskbar() is true
if (!m_workspaceManager.enableTaskbar()) { if (!m_workspaceManager.enableTaskbar()) {
auto windowSeparator = m_workspaceManager.getWindowSeparator(); auto windowSeparator = m_workspaceManager.getWindowSeparator();
auto groupThreshold = m_workspaceManager.windowRewriteGroupThreshold();
bool isNotFirst = false; if (groupThreshold > 0) {
// Build ordered counts of each unique icon (including singular ones when threshold set to 1)
std::vector<std::pair<std::string, int>> iconCounts;
for (const auto& window_repr : m_windowMap) {
auto it = std::ranges::find_if(iconCounts, [&](const auto& p) {
return p.first == window_repr.repr_rewrite;
});
if (it != iconCounts.end()) {
it->second++;
} else {
iconCounts.emplace_back(window_repr.repr_rewrite, 1);
}
}
for (const auto& window_repr : m_windowMap) { // Format the group string
if (isNotFirst) { auto groupFormat = m_workspaceManager.getWindowRewriteGroupFormat();
windows.append(windowSeparator); bool isNotFirst = false;
for (const auto& [icon, count] : iconCounts) {
if (count >= groupThreshold) {
if (isNotFirst) windows.append(windowSeparator);
isNotFirst = true;
try {
windows.append(fmt::format(fmt::runtime(groupFormat),
fmt::arg("icon", icon),
fmt::arg("count", count)));
} catch (const fmt::format_error& e) {
spdlog::warn("Formatting window-rewrite-group-format error: {}", e.what());
windows.append(icon);
}
} else {
for (int i = 0; i < count; ++i) {
if (isNotFirst) windows.append(windowSeparator);
isNotFirst = true;
windows.append(icon);
}
}
}
} else {
// Not grouping icons
bool isNotFirst = false;
for (const auto& window_repr : m_windowMap) {
if (isNotFirst) windows.append(windowSeparator);
isNotFirst = true;
windows.append(window_repr.repr_rewrite);
} }
isNotFirst = true;
windows.append(window_repr.repr_rewrite);
} }
} }
+10
View File
@@ -649,6 +649,16 @@ auto Workspaces::parseConfig(const Json::Value& config) -> void {
populateSortByConfig(config); populateSortByConfig(config);
populateIgnoreWorkspacesConfig(config); populateIgnoreWorkspacesConfig(config);
populateFormatWindowSeparatorConfig(config); populateFormatWindowSeparatorConfig(config);
const auto& groupThreshold = config["window-rewrite-group-threshold"];
if (groupThreshold.isInt()) {
m_windowRewriteGroupThreshold = groupThreshold.asInt();
}
const auto& groupFormat = config["window-rewrite-group-format"];
if (groupFormat.isString()) {
m_windowRewriteGroupFormat = groupFormat.asString();
}
populateWindowRewriteConfig(config); populateWindowRewriteConfig(config);
if (withWindows) { if (withWindows) {