feat(hyprland/workspaces): grouping icons
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user