diff --git a/include/modules/hyprland/workspaces.hpp b/include/modules/hyprland/workspaces.hpp index fb8003f8..453849d8 100644 --- a/include/modules/hyprland/workspaces.hpp +++ b/include/modules/hyprland/workspaces.hpp @@ -43,6 +43,7 @@ class Workspaces : public AModule, public EventHandler { auto specialVisibleOnly() const -> bool { return m_specialVisibleOnly; } auto persistentOnly() const -> bool { return m_persistentOnly; } auto moveToMonitor() const -> bool { return m_moveToMonitor; } + auto uniqueIcons() const -> bool { return m_uniqueIcons; } auto enableTaskbar() const -> bool { return m_enableTaskbar; } auto taskbarWithIcon() const -> bool { return m_taskbarWithIcon; } auto barScroll() const -> bool { return m_barScroll; } @@ -156,6 +157,7 @@ class Workspaces : public AModule, public EventHandler { bool m_specialVisibleOnly = false; bool m_persistentOnly = false; bool m_moveToMonitor = false; + bool m_uniqueIcons = false; bool m_barScroll = false; Json::Value m_persistentWorkspaceConfig; diff --git a/man/waybar-hyprland-workspaces.5.scd b/man/waybar-hyprland-workspaces.5.scd index fda536a7..350ee745 100644 --- a/man/waybar-hyprland-workspaces.5.scd +++ b/man/waybar-hyprland-workspaces.5.scd @@ -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. 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*: ++ typeof: bool ++ default: false ++ diff --git a/src/modules/hyprland/workspace.cpp b/src/modules/hyprland/workspace.cpp index 72e4aaf4..aa0243bf 100644 --- a/src/modules/hyprland/workspace.cpp +++ b/src/modules/hyprland/workspace.cpp @@ -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 (it != m_windowMap.end()) { *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); } } diff --git a/src/modules/hyprland/workspaces.cpp b/src/modules/hyprland/workspaces.cpp index 79d618c8..031938be 100644 --- a/src/modules/hyprland/workspaces.cpp +++ b/src/modules/hyprland/workspaces.cpp @@ -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 if (allOutputs() || m_bar.output->name == monitor || monitor.empty()) { // => skip ignore-workspaces even if its a persistent - if(isWorkspaceIgnored(workspace)) { + if (isWorkspaceIgnored(workspace)) { continue; } // => persistent workspace should be shown on this monitor @@ -390,15 +390,17 @@ void Workspaces::onEvent(const std::string& ev) { } m_updatePending = true; - m_debounceTimer = Glib::signal_timeout().connect([this]() { - if (!m_updatePending) return false; - std::lock_guard lock(m_mutex); - if (m_updatePending) { - dp.emit(); - m_updatePending = false; - } - return false; - }, 7); + m_debounceTimer = Glib::signal_timeout().connect( + [this]() { + if (!m_updatePending) return false; + std::lock_guard lock(m_mutex); + if (m_updatePending) { + dp.emit(); + m_updatePending = false; + } + return false; + }, + 7); } 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, "hide-active", m_hideActive); populateBoolConfig(config, "move-to-monitor", m_moveToMonitor); + populateBoolConfig(config, "unique-icons", m_uniqueIcons); populateBoolConfig(config, "enable-bar-scroll", m_barScroll); m_persistentWorkspaceConfig = config.get("persistent-workspaces", Json::Value()); diff --git a/test/config.cpp b/test/config.cpp index 638d9663..28e7c2de 100644 --- a/test/config.cpp +++ b/test/config.cpp @@ -166,6 +166,7 @@ TEST_CASE("Load Hyprland Workspaces bar config", "[config]") { REQUIRE(hyprland["active-only"].asBool() == true); REQUIRE(hyprland["all-outputs"].asBool() == false); REQUIRE(hyprland["move-to-monitor"].asBool() == true); + REQUIRE(hyprland["unique-icons"].asBool() == true); REQUIRE(hyprland["format"].asString() == "{icon} {windows}"); REQUIRE(hyprland["format-window-separator"].asString() == " "); REQUIRE(hyprland["on-scroll-down"].asString() == "hyprctl dispatch workspace e-1"); diff --git a/test/config/hyprland-workspaces.json b/test/config/hyprland-workspaces.json index dd733897..903e94f9 100644 --- a/test/config/hyprland-workspaces.json +++ b/test/config/hyprland-workspaces.json @@ -29,6 +29,7 @@ "window-rewrite": { "title": "" }, + "unique-icons": true, "window-rewrite-default": "", "window-rewrite-separator": " ", "sort-by": "number"