feat: add custom workspace sorting functionality

This commit is contained in:
Esensats
2026-07-04 01:35:05 +02:00
committed by Alex
parent 46e96dfbaa
commit 41926e873f
3 changed files with 55 additions and 0 deletions
+3
View File
@@ -4,6 +4,7 @@
#include <gtkmm/button.h>
#include <gtkmm/label.h>
#include <optional>
#include <string_view>
#include <unordered_map>
@@ -44,6 +45,7 @@ class Workspaces : public AModule, public sigc::trackable {
std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
uint16_t getWorkspaceIndex(const std::string& name) const;
static std::string trimWorkspaceName(const std::string&);
std::optional<uint16_t> 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<std::string, Gtk::Button> buttons_;
std::unordered_map<std::string, uint16_t> custom_sort_priorities_;
std::mutex mutex_;
Ipc ipc_;
};
+5
View File
@@ -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 ++
+47
View File
@@ -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<uint16_t> 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