diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index 5f7c3f61..fd2ad43d 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -1,9 +1,28 @@ #include "modules/sway/workspaces.hpp" +#include +#include #include + namespace waybar::modules::sway { +// this is the code that sway uses to assign a number to a workspace. This is +// taken quite verbatim from `sway/ipc-json.c`. +int sway_wsname_to_num(std::string name) { + if (isdigit(name[0])) { + errno = 0; + char * endptr = NULL; + long long parsed_num = strtoll(name.c_str(), &endptr, 10); + if (errno != 0 || parsed_num > INT32_MAX || parsed_num < 0 || endptr == name.c_str()) { + return -1; + } else { + return (int)parsed_num; + } + } + return -1; +} + Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config) : AModule(config, "workspaces", id, false, !config["disable-scroll"].asBool()), bar_(bar), @@ -102,13 +121,27 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) { // the "num" property (integer type): // The workspace number or -1 for workspaces that do // not start with a number. - auto l = lhs["num"].asInt(); - auto r = rhs["num"].asInt(); + //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 sway_wsname_to_num). This way the + // sorting should work out even when we include workspaces + // that do not currently exist. + auto lname = lhs["name"].asString(); + auto rname = rhs["name"].asString(); + auto l = sway_wsname_to_num(lname); + auto r = sway_wsname_to_num(rname); + if (l == r) { // in case both integers are the same, lexicographical // sort. This also covers the case when both don't have a // number (i.e., l == r == -1). - return lhs["name"].asString() < rhs["name"].asString(); + return lname < rname; } // one of the workspaces doesn't begin with a number, so