From 41926e873fe46c0c049c12ed9dac1274efddaa26 Mon Sep 17 00:00:00 2001 From: Esensats Date: Thu, 9 Oct 2025 06:43:39 +0500 Subject: [PATCH] feat: add custom workspace sorting functionality --- include/modules/sway/workspaces.hpp | 3 ++ man/waybar-sway-workspaces.5.scd | 5 +++ src/modules/sway/workspaces.cpp | 47 +++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/include/modules/sway/workspaces.hpp b/include/modules/sway/workspaces.hpp index cea8ade5..8b902f03 100644 --- a/include/modules/sway/workspaces.hpp +++ b/include/modules/sway/workspaces.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -44,6 +45,7 @@ class Workspaces : public AModule, public sigc::trackable { std::string getCycleWorkspace(std::vector::iterator, bool prev) const; uint16_t getWorkspaceIndex(const std::string& name) const; static std::string trimWorkspaceName(const std::string&); + std::optional getCustomSortIndex(const std::string& name) const; bool handleScroll(GdkEventScroll* /*unused*/) override; const Bar& bar_; @@ -56,6 +58,7 @@ class Workspaces : public AModule, public sigc::trackable { util::RegexCollection m_windowRewriteRules; util::JsonParser parser_; std::unordered_map buttons_; + std::unordered_map custom_sort_priorities_; std::mutex mutex_; Ipc ipc_; }; diff --git a/man/waybar-sway-workspaces.5.scd b/man/waybar-sway-workspaces.5.scd index d7050ddc..7a1bd4d5 100644 --- a/man/waybar-sway-workspaces.5.scd +++ b/man/waybar-sway-workspaces.5.scd @@ -96,6 +96,11 @@ Addressed by *sway/workspaces* typeof: bool ++ Whether to sort workspaces alphabetically. Please note this can make "swaymsg workspace prev/next" move to workspaces inconsistent with the ordering shown in Waybar. +*custom-sort*: ++ + typeof: array ++ + default: [] ++ + Defines an explicit ordering for workspace names. Entries earlier in the array appear first. Both full names and the trimmed portion after ":" are matched. Any workspace not listed here falls back to the default ordering (or alphabetical ordering when *alphabetical_sort* is true). + warp-on-scroll: ++ typeof: bool ++ default: true ++ diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index 957187a0..86902ef5 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -50,6 +50,21 @@ Workspaces::Workspaces(const std::string& id, const Bar& bar, const Json::Value& high_priority_named_.push_back(it.asString()); } } + if (config_["custom-sort"].isArray()) { + uint16_t priority = 0; + for (const auto& entry : config_["custom-sort"]) { + if (!entry.isString()) { + continue; + } + auto const name = entry.asString(); + custom_sort_priorities_.insert_or_assign(name, priority); + auto const trimmed = trimWorkspaceName(name); + if (trimmed != name) { + custom_sort_priorities_.insert_or_assign(trimmed, priority); + } + ++priority; + } + } box_.set_name("workspaces"); if (!id.empty()) { box_.get_style_context()->add_class(id); @@ -236,6 +251,20 @@ void Workspaces::onCmd(const struct Ipc::ipc_response& res) { int l = lhs["sort"].asInt(); int r = rhs["sort"].asInt(); + if (!custom_sort_priorities_.empty()) { + auto const lcustom = getCustomSortIndex(lname); + auto const rcustom = getCustomSortIndex(rname); + if (lcustom && rcustom) { + if (*lcustom != *rcustom) { + return *lcustom < *rcustom; + } + } else if (lcustom) { + return true; + } else if (rcustom) { + return false; + } + } + if (l == r || config_["alphabetical_sort"].asBool()) { // In case both integers are the same, lexicographical // sort. The code above already ensure that this will only @@ -572,6 +601,24 @@ std::string Workspaces::trimWorkspaceName(const std::string& name) { return name; } +std::optional Workspaces::getCustomSortIndex(const std::string& name) const { + if (custom_sort_priorities_.empty()) { + return std::nullopt; + } + auto it = custom_sort_priorities_.find(name); + if (it != custom_sort_priorities_.end()) { + return it->second; + } + auto trimmed = trimWorkspaceName(name); + if (trimmed != name) { + auto trimmed_it = custom_sort_priorities_.find(trimmed); + if (trimmed_it != custom_sort_priorities_.end()) { + return trimmed_it->second; + } + } + return std::nullopt; +} + bool is_focused_recursive(const Json::Value& node) { // If a workspace has a focused container then get_tree will say // that the workspace itself isn't focused. Therefore we need to