diff --git a/include/modules/sway/workspaces.hpp b/include/modules/sway/workspaces.hpp index 8c7875cc..d6244c42 100644 --- a/include/modules/sway/workspaces.hpp +++ b/include/modules/sway/workspaces.hpp @@ -35,6 +35,7 @@ class Workspaces : public IModule, public sigc::trackable { const Bar& bar_; const Json::Value& config_; std::vector workspaces_; + std::vector workspaces_order_; waybar::util::SleeperThread thread_; std::mutex mutex_; Gtk::Box box_; diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index 6fbbfd5c..8c8ed72e 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -17,7 +17,7 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd)); ipc_.sendCmd(IPC_GET_WORKSPACES); if (!config["disable-bar-scroll"].asBool()) { - auto &window = const_cast(bar_).window; + auto &window = const_cast(bar_).window; window.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK); window.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll)); } @@ -48,6 +48,79 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) { ? workspace["output"].asString() == bar_.output->name : true; }); + + // adding persistant workspaces (as per the config file) + const Json::Value & p_workspaces = config_["persistant_workspaces"]; + const std::vector p_workspaces_names = p_workspaces.getMemberNames(); + + auto first_persistant_ws_idx = workspaces_.size(); + for (const std::string &p_w_name : p_workspaces_names) { + const Json::Value &p_w = p_workspaces[p_w_name]; + auto it = + std::find_if(payload.begin(), payload.end(), [&p_w_name](const Json::Value &node) { + return node["name"].asString() == p_w_name; + }); + + if (it != payload.end()) { + continue; // already displayed by some bar + } + + if (p_w.isArray() && !p_w.empty()) { + // Adding to target outputs + for (const Json::Value &output : p_w) { + if (output.asString() == bar_.output->name) { + Json::Value v; + v["name"] = p_w_name; + v["target_output"] = bar_.output->name; + workspaces_.emplace_back(std::move(v)); + break; + } + } + } else { + // Adding to all outputs + Json::Value v; + v["name"] = p_w_name; + workspaces_.emplace_back(std::move(v)); + } + } + + if (workspaces_order_.empty()) { + // Saving starting order + workspaces_order_.reserve(payload.size() + workspaces_.size() - first_persistant_ws_idx); + for (const Json::Value &workspace : payload) { + workspaces_order_.emplace_back(workspace["name"].asString()); + } + for (auto i = first_persistant_ws_idx; i < workspaces_.size() ; ++i) { + workspaces_order_.emplace_back(workspaces_[i]["name"].asString()); + } + } else { + // Ordering workspaces as it was before for current output + std::vector sorted_workspaces; + sorted_workspaces.reserve(workspaces_.size()); + auto ws_end = workspaces_.end(); + for (const std::string &name_by_order : workspaces_order_) { + auto it = + std::find_if(workspaces_.begin(), ws_end, [&name_by_order](const Json::Value &ws) { + return ws["name"].asString() == name_by_order; + }); + if (it != ws_end) { + sorted_workspaces.emplace_back(*it); + --ws_end; + if (ws_end == workspaces_.begin()) { // we've extracted everything + break; + } + ws_end->swap(*it); + } + } + + // Adding new workspaces to the output (those were never showed in this output before) + for (int i = 0; workspaces_.size() > sorted_workspaces.size(); ++i) { + workspaces_order_.emplace_back(workspaces_[i]["name"].asString()); + sorted_workspaces.emplace_back(workspaces_[i]); + } + workspaces_.swap(sorted_workspaces); + } + dp.emit(); } } catch (const std::exception &e) { @@ -136,9 +209,18 @@ Gtk::Button &Workspaces::addButton(const Json::Value &node) { auto &button = pair.first->second; box_.pack_start(button, false, false, 0); button.set_relief(Gtk::RELIEF_NONE); - button.signal_clicked().connect([this, pair] { + button.signal_clicked().connect([this, node] { try { - ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", pair.first->first)); + if (node["target_output"].isString()) { + ipc_.sendCmd( + IPC_COMMAND, + fmt::format("workspace \"{}\"; move workspace to output \"{}\"; workspace \"{}\"", + node["name"].asString(), + node["target_output"].asString(), + node["name"].asString())); + } else { + ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", node["name"].asString())); + } } catch (const std::exception &e) { spdlog::error("Workspaces: {}", e.what()); }