Merge pull request #4320 from LoricAndre/master

feat(hyprland/workspaces): add uniqueIcons option
This commit is contained in:
Alexis Rouillard
2026-07-04 01:12:05 +02:00
committed by GitHub
6 changed files with 26 additions and 11 deletions
+2
View File
@@ -43,6 +43,7 @@ class Workspaces : public AModule, public EventHandler {
auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; } auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; }
auto persistentOnly() const -> bool { return m_persistentOnly; } auto persistentOnly() const -> bool { return m_persistentOnly; }
auto moveToMonitor() const -> bool { return m_moveToMonitor; } auto moveToMonitor() const -> bool { return m_moveToMonitor; }
auto uniqueIcons() const -> bool { return m_uniqueIcons; }
auto enableTaskbar() const -> bool { return m_enableTaskbar; } auto enableTaskbar() const -> bool { return m_enableTaskbar; }
auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; } auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; }
auto barScroll() const -> bool { return m_barScroll; } auto barScroll() const -> bool { return m_barScroll; }
@@ -156,6 +157,7 @@ class Workspaces : public AModule, public EventHandler {
bool m_specialVisibleOnly = false; bool m_specialVisibleOnly = false;
bool m_persistentOnly = false; bool m_persistentOnly = false;
bool m_moveToMonitor = false; bool m_moveToMonitor = false;
bool m_uniqueIcons = false;
bool m_barScroll = false; bool m_barScroll = false;
Json::Value m_persistentWorkspaceConfig; Json::Value m_persistentWorkspaceConfig;
+5
View File
@@ -163,6 +163,11 @@ This setting is ignored if *workspace-taskbar.enable* is set to true.
Otherwise, the workspace will open on the monitor where it was previously assigned. Otherwise, the workspace will open on the monitor where it was previously assigned.
Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland. Analog to using `focusworkspaceoncurrentmonitor` dispatcher instead of `workspace` in Hyprland.
*unique-icons*: ++
typeof: bool ++
default: false ++
If set to true, only one instance of each window icon will be shown per workspace.
*enable-bar-scroll*: ++ *enable-bar-scroll*: ++
typeof: bool ++ typeof: bool ++
default: false ++ default: false ++
+4 -1
View File
@@ -278,7 +278,10 @@ void Workspace::insertWindow(WindowCreationPayload create_window_payload) {
// If the vector contains the address, update the window representation, otherwise insert it // If the vector contains the address, update the window representation, otherwise insert it
if (it != m_windowMap.end()) { if (it != m_windowMap.end()) {
*it = repr; *it = repr;
} else { } else if (!m_workspaceManager.uniqueIcons() || repr.repr_rewrite.empty() ||
std::ranges::find_if(m_windowMap, [&repr](const auto& window) {
return window.repr_rewrite == repr.repr_rewrite;
}) == m_windowMap.end()) {
m_windowMap.emplace_back(repr); m_windowMap.emplace_back(repr);
} }
} }
+13 -10
View File
@@ -328,7 +328,7 @@ void Workspaces::loadPersistentWorkspacesFromWorkspaceRules(const Json::Value& c
// 3. no monitor is specified in the rule => assume it needs to be persistent on every monitor // 3. no monitor is specified in the rule => assume it needs to be persistent on every monitor
if (allOutputs() || m_bar.output->name == monitor || monitor.empty()) { if (allOutputs() || m_bar.output->name == monitor || monitor.empty()) {
// => skip ignore-workspaces even if its a persistent // => skip ignore-workspaces even if its a persistent
if(isWorkspaceIgnored(workspace)) { if (isWorkspaceIgnored(workspace)) {
continue; continue;
} }
// => persistent workspace should be shown on this monitor // => persistent workspace should be shown on this monitor
@@ -390,15 +390,17 @@ void Workspaces::onEvent(const std::string& ev) {
} }
m_updatePending = true; m_updatePending = true;
m_debounceTimer = Glib::signal_timeout().connect([this]() { m_debounceTimer = Glib::signal_timeout().connect(
if (!m_updatePending) return false; [this]() {
std::lock_guard<std::mutex> lock(m_mutex); if (!m_updatePending) return false;
if (m_updatePending) { std::lock_guard<std::mutex> lock(m_mutex);
dp.emit(); if (m_updatePending) {
m_updatePending = false; dp.emit();
} m_updatePending = false;
return false; }
}, 7); return false;
},
7);
} }
void Workspaces::onWorkspaceActivated(std::string const& payload) { void Workspaces::onWorkspaceActivated(std::string const& payload) {
@@ -680,6 +682,7 @@ auto Workspaces::parseConfig(const Json::Value& config) -> void {
populateBoolConfig(config, "active-only", m_activeOnly); populateBoolConfig(config, "active-only", m_activeOnly);
populateBoolConfig(config, "hide-active", m_hideActive); populateBoolConfig(config, "hide-active", m_hideActive);
populateBoolConfig(config, "move-to-monitor", m_moveToMonitor); populateBoolConfig(config, "move-to-monitor", m_moveToMonitor);
populateBoolConfig(config, "unique-icons", m_uniqueIcons);
populateBoolConfig(config, "enable-bar-scroll", m_barScroll); populateBoolConfig(config, "enable-bar-scroll", m_barScroll);
m_persistentWorkspaceConfig = config.get("persistent-workspaces", Json::Value()); m_persistentWorkspaceConfig = config.get("persistent-workspaces", Json::Value());
+1
View File
@@ -166,6 +166,7 @@ TEST_CASE("Load Hyprland Workspaces bar config", "[config]") {
REQUIRE(hyprland["active-only"].asBool() == true); REQUIRE(hyprland["active-only"].asBool() == true);
REQUIRE(hyprland["all-outputs"].asBool() == false); REQUIRE(hyprland["all-outputs"].asBool() == false);
REQUIRE(hyprland["move-to-monitor"].asBool() == true); REQUIRE(hyprland["move-to-monitor"].asBool() == true);
REQUIRE(hyprland["unique-icons"].asBool() == true);
REQUIRE(hyprland["format"].asString() == "{icon} {windows}"); REQUIRE(hyprland["format"].asString() == "{icon} {windows}");
REQUIRE(hyprland["format-window-separator"].asString() == " "); REQUIRE(hyprland["format-window-separator"].asString() == " ");
REQUIRE(hyprland["on-scroll-down"].asString() == "hyprctl dispatch workspace e-1"); REQUIRE(hyprland["on-scroll-down"].asString() == "hyprctl dispatch workspace e-1");
+1
View File
@@ -29,6 +29,7 @@
"window-rewrite": { "window-rewrite": {
"title<Steam>": "" "title<Steam>": ""
}, },
"unique-icons": true,
"window-rewrite-default": "", "window-rewrite-default": "",
"window-rewrite-separator": " ", "window-rewrite-separator": " ",
"sort-by": "number" "sort-by": "number"