fix: match sway workspace order with sway one
Ensure that sway workspaces are always displayed in the same order as used internally by sway. The previous sorting code always sorted unnumbered workspaces lexicographically. This isn't the order used by sway internally. Therefore, commands such as "workspace next" might have jumped arbitrarily in waybar. This commit reworks the sorting code such that the internal order is always obeyed. Additionally, numbered persistent workspaces are inserted at their natural position at the front of the workspace list while unnumbered ones are appended. This should match the expectations of workspace ordering known from sway's behavior. The changes make the configuration property "numeric-first" unnecessary as this will always be the case now. There's also no reasonable way around this behavior now. Otherwise, persistent workspaces would jump around in the visual representation as soon as they become known to sway. Fixes #802
This commit is contained in:
parent
621d686310
commit
4a85ec0f59
|
@ -69,10 +69,6 @@ Addressed by *sway/workspaces*
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
Command to execute when the module is updated.
|
Command to execute when the module is updated.
|
||||||
|
|
||||||
*numeric-first*: ++
|
|
||||||
typeof: bool ++
|
|
||||||
Whether to put workspaces starting with numbers before workspaces that do not start with a number.
|
|
||||||
|
|
||||||
*disable-auto-back-and-forth*: ++
|
*disable-auto-back-and-forth*: ++
|
||||||
typeof: bool ++
|
typeof: bool ++
|
||||||
Whether to disable *workspace_auto_back_and_forth* when clicking on workspaces. If this is set to *true*, clicking on a workspace you are already on won't do anything, even if *workspace_auto_back_and_forth* is enabled in the Sway configuration.
|
Whether to disable *workspace_auto_back_and_forth* when clicking on workspaces. If this is set to *true*, clicking on a workspace you are already on won't do anything, even if *workspace_auto_back_and_forth* is enabled in the Sway configuration.
|
||||||
|
@ -120,7 +116,6 @@ n.b.: the list of outputs can be obtained from command line using *swaymsg -t ge
|
||||||
"sway/workspaces": {
|
"sway/workspaces": {
|
||||||
"disable-scroll": true,
|
"disable-scroll": true,
|
||||||
"all-outputs": true,
|
"all-outputs": true,
|
||||||
"numeric-first": false,
|
|
||||||
"format": "{name}: {icon}",
|
"format": "{name}: {icon}",
|
||||||
"format-icons": {
|
"format-icons": {
|
||||||
"1": "",
|
"1": "",
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -98,6 +99,7 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
||||||
Json::Value v;
|
Json::Value v;
|
||||||
v["name"] = p_w_name;
|
v["name"] = p_w_name;
|
||||||
v["target_output"] = bar_.output->name;
|
v["target_output"] = bar_.output->name;
|
||||||
|
v["num"] = convertWorkspaceNameToNum(p_w_name);
|
||||||
workspaces_.emplace_back(std::move(v));
|
workspaces_.emplace_back(std::move(v));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -107,57 +109,59 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
||||||
Json::Value v;
|
Json::Value v;
|
||||||
v["name"] = p_w_name;
|
v["name"] = p_w_name;
|
||||||
v["target_output"] = "";
|
v["target_output"] = "";
|
||||||
|
v["num"] = convertWorkspaceNameToNum(p_w_name);
|
||||||
workspaces_.emplace_back(std::move(v));
|
workspaces_.emplace_back(std::move(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// config option to sort numeric workspace names before others
|
// sway has a defined ordering of workspaces that should be preserved in
|
||||||
bool config_numeric_first = config_["numeric-first"].asBool();
|
// the representation displayed by waybar to ensure that commands such
|
||||||
|
// as "workspace prev" or "workspace next" make sense when looking at
|
||||||
|
// the workspace representation in the bar.
|
||||||
|
// Due to waybar's own feature of persistent workspaces unknown to sway,
|
||||||
|
// custom sorting logic is necessary to make these workspaces appear
|
||||||
|
// naturally in the list of workspaces without messing up sway's
|
||||||
|
// sorting. For this purpose, a custom numbering property is created
|
||||||
|
// that preserves the order provided by sway while inserting numbered
|
||||||
|
// persistent workspaces at their natural positions.
|
||||||
|
//
|
||||||
|
// All of this code assumes that sway provides numbered workspaces first
|
||||||
|
// and other workspaces are sorted by their creation time.
|
||||||
|
//
|
||||||
|
// In a first pass, the maximum "num" value is computed to enqueue
|
||||||
|
// unnumbered workspaces behind numbered ones when computing the sort
|
||||||
|
// attribute.
|
||||||
|
int max_num = -1;
|
||||||
|
for (auto & workspace : workspaces_) {
|
||||||
|
max_num = std::max(workspace["num"].asInt(), max_num);
|
||||||
|
}
|
||||||
|
for (auto & workspace : workspaces_) {
|
||||||
|
auto workspace_num = workspace["num"].asInt();
|
||||||
|
if (workspace_num > -1) {
|
||||||
|
workspace["sort"] = workspace_num;
|
||||||
|
} else {
|
||||||
|
workspace["sort"] = ++max_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
std::sort(workspaces_.begin(),
|
std::sort(workspaces_.begin(),
|
||||||
workspaces_.end(),
|
workspaces_.end(),
|
||||||
[config_numeric_first](const Json::Value &lhs, const Json::Value &rhs) {
|
[](const Json::Value &lhs, const Json::Value &rhs) {
|
||||||
// the "num" property (integer type):
|
|
||||||
// The workspace number or -1 for workspaces that do
|
|
||||||
// not start with a number.
|
|
||||||
// We could rely on sway providing this property:
|
|
||||||
//
|
|
||||||
// auto l = lhs["num"].asInt();
|
|
||||||
// auto r = rhs["num"].asInt();
|
|
||||||
//
|
|
||||||
// We cannot rely on the "num" property as provided by sway
|
|
||||||
// via IPC, because persistent workspace might not exist in
|
|
||||||
// sway's view. However, we need this property also for
|
|
||||||
// not-yet created persistent workspace. As such, we simply
|
|
||||||
// duplicate sway's logic of assigning the "num" property
|
|
||||||
// into waybar (see convertWorkspaceNameToNum). This way the
|
|
||||||
// sorting should work out even when we include workspaces
|
|
||||||
// that do not currently exist.
|
|
||||||
auto lname = lhs["name"].asString();
|
auto lname = lhs["name"].asString();
|
||||||
auto rname = rhs["name"].asString();
|
auto rname = rhs["name"].asString();
|
||||||
int l = convertWorkspaceNameToNum(lname);
|
int l = lhs["sort"].asInt();
|
||||||
int r = convertWorkspaceNameToNum(rname);
|
int r = rhs["sort"].asInt();
|
||||||
|
|
||||||
if (l == r) {
|
if (l == r) {
|
||||||
// in case both integers are the same, lexicographical
|
// In case both integers are the same, lexicographical
|
||||||
// sort. This also covers the case when both don't have a
|
// sort. The code above already ensure that this will only
|
||||||
// number (i.e., l == r == -1).
|
// happend in case of explicitly numbered workspaces.
|
||||||
return lname < rname;
|
return lname < rname;
|
||||||
}
|
}
|
||||||
|
|
||||||
// one of the workspaces doesn't begin with a number, so
|
|
||||||
// num is -1.
|
|
||||||
if (l < 0 || r < 0) {
|
|
||||||
if (config_numeric_first) {
|
|
||||||
return r < 0;
|
|
||||||
}
|
|
||||||
return l < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// both workspaces have a "num" so let's just compare those
|
|
||||||
return l < r;
|
return l < r;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
dp.emit();
|
dp.emit();
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
|
|
Loading…
Reference in New Issue