refactor(Workspaces, IPC): no more mutex in the workspaces modules, moved to the IPC client for a proper handling
parent
e77c155ede
commit
cbb6f2a307
|
@ -6,6 +6,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
#include "ipc.hpp"
|
#include "ipc.hpp"
|
||||||
|
|
||||||
namespace waybar::modules::sway {
|
namespace waybar::modules::sway {
|
||||||
|
@ -24,9 +25,9 @@ class Ipc {
|
||||||
sigc::signal<void, const struct ipc_response> signal_event;
|
sigc::signal<void, const struct ipc_response> signal_event;
|
||||||
sigc::signal<void, const struct ipc_response> signal_cmd;
|
sigc::signal<void, const struct ipc_response> signal_cmd;
|
||||||
|
|
||||||
void sendCmd(uint32_t type, const std::string &payload = "") const;
|
void sendCmd(uint32_t type, const std::string &payload = "");
|
||||||
void subscribe(const std::string &payload) const;
|
void subscribe(const std::string &payload);
|
||||||
void handleEvent() const;
|
void handleEvent();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static inline const std::string ipc_magic_ = "i3-ipc";
|
static inline const std::string ipc_magic_ = "i3-ipc";
|
||||||
|
@ -34,11 +35,13 @@ class Ipc {
|
||||||
|
|
||||||
const std::string getSocketPath() const;
|
const std::string getSocketPath() const;
|
||||||
int open(const std::string &) const;
|
int open(const std::string &) const;
|
||||||
struct ipc_response send(int fd, uint32_t type, const std::string &payload = "") const;
|
struct ipc_response send(int fd, uint32_t type, const std::string &payload = "");
|
||||||
struct ipc_response recv(int fd) const;
|
struct ipc_response recv(int fd);
|
||||||
|
|
||||||
int fd_;
|
int fd_;
|
||||||
int fd_event_;
|
int fd_event_;
|
||||||
|
std::mutex mutex_;
|
||||||
|
std::mutex mutex_event_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace waybar::modules::sway
|
} // namespace waybar::modules::sway
|
||||||
|
|
|
@ -21,25 +21,24 @@ class Workspaces : public IModule {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onCmd(const struct Ipc::ipc_response);
|
void onCmd(const struct Ipc::ipc_response);
|
||||||
|
void onEvent(const struct Ipc::ipc_response);
|
||||||
void worker();
|
void worker();
|
||||||
void addWorkspace(const Json::Value&);
|
bool filterButtons();
|
||||||
|
Gtk::Button& addButton(const Json::Value&);
|
||||||
void onButtonReady(const Json::Value&, Gtk::Button&);
|
void onButtonReady(const Json::Value&, Gtk::Button&);
|
||||||
std::string getIcon(const std::string&, const Json::Value&);
|
std::string getIcon(const std::string&, const Json::Value&);
|
||||||
bool handleScroll(GdkEventScroll*);
|
bool handleScroll(GdkEventScroll*);
|
||||||
const std::string getCycleWorkspace(const Json::Value& workspaces, uint8_t current,
|
const std::string getCycleWorkspace(std::vector<Json::Value>::iterator, bool prev) const;
|
||||||
bool prev) const;
|
uint16_t getWorkspaceIndex(const std::string& name) const;
|
||||||
uint16_t getWorkspaceIndex(const Json::Value& workspaces, const std::string& name) const;
|
|
||||||
std::string trimWorkspaceName(std::string);
|
std::string trimWorkspaceName(std::string);
|
||||||
const Json::Value getWorkspaces();
|
|
||||||
|
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
const Json::Value& config_;
|
const Json::Value& config_;
|
||||||
Json::Value workspaces_;
|
std::vector<Json::Value> workspaces_;
|
||||||
waybar::util::SleeperThread thread_;
|
waybar::util::SleeperThread thread_;
|
||||||
Gtk::Box box_;
|
Gtk::Box box_;
|
||||||
util::JsonParser parser_;
|
util::JsonParser parser_;
|
||||||
Ipc ipc_;
|
Ipc ipc_;
|
||||||
std::mutex mutex_;
|
|
||||||
bool scrolling_;
|
bool scrolling_;
|
||||||
std::unordered_map<std::string, Gtk::Button> buttons_;
|
std::unordered_map<std::string, Gtk::Button> buttons_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -69,7 +69,7 @@ int Ipc::open(const std::string& socketPath) const {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Ipc::ipc_response Ipc::recv(int fd) const {
|
struct Ipc::ipc_response Ipc::recv(int fd) {
|
||||||
std::string header;
|
std::string header;
|
||||||
header.resize(ipc_header_size_);
|
header.resize(ipc_header_size_);
|
||||||
auto data32 = reinterpret_cast<uint32_t*>(header.data() + ipc_magic_.size());
|
auto data32 = reinterpret_cast<uint32_t*>(header.data() + ipc_magic_.size());
|
||||||
|
@ -86,7 +86,6 @@ struct Ipc::ipc_response Ipc::recv(int fd) const {
|
||||||
}
|
}
|
||||||
total += res;
|
total += res;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto magic = std::string(header.data(), header.data() + ipc_magic_.size());
|
auto magic = std::string(header.data(), header.data() + ipc_magic_.size());
|
||||||
if (magic != ipc_magic_) {
|
if (magic != ipc_magic_) {
|
||||||
throw std::runtime_error("Invalid IPC magic");
|
throw std::runtime_error("Invalid IPC magic");
|
||||||
|
@ -105,7 +104,7 @@ struct Ipc::ipc_response Ipc::recv(int fd) const {
|
||||||
return {data32[0], data32[1], &payload.front()};
|
return {data32[0], data32[1], &payload.front()};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Ipc::ipc_response Ipc::send(int fd, uint32_t type, const std::string& payload) const {
|
struct Ipc::ipc_response Ipc::send(int fd, uint32_t type, const std::string& payload) {
|
||||||
std::string header;
|
std::string header;
|
||||||
header.resize(ipc_header_size_);
|
header.resize(ipc_header_size_);
|
||||||
auto data32 = reinterpret_cast<uint32_t*>(header.data() + ipc_magic_.size());
|
auto data32 = reinterpret_cast<uint32_t*>(header.data() + ipc_magic_.size());
|
||||||
|
@ -122,19 +121,22 @@ struct Ipc::ipc_response Ipc::send(int fd, uint32_t type, const std::string& pay
|
||||||
return Ipc::recv(fd);
|
return Ipc::recv(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ipc::sendCmd(uint32_t type, const std::string& payload) const {
|
void Ipc::sendCmd(uint32_t type, const std::string& payload) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
const auto res = Ipc::send(fd_, type, payload);
|
const auto res = Ipc::send(fd_, type, payload);
|
||||||
signal_cmd.emit(res);
|
signal_cmd.emit(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ipc::subscribe(const std::string& payload) const {
|
void Ipc::subscribe(const std::string& payload) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_event_);
|
||||||
auto res = Ipc::send(fd_event_, IPC_SUBSCRIBE, payload);
|
auto res = Ipc::send(fd_event_, IPC_SUBSCRIBE, payload);
|
||||||
if (res.payload != "{\"success\": true}") {
|
if (res.payload != "{\"success\": true}") {
|
||||||
throw std::runtime_error("Unable to subscribe ipc event");
|
throw std::runtime_error("Unable to subscribe ipc event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ipc::handleEvent() const {
|
void Ipc::handleEvent() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_event_);
|
||||||
const auto res = Ipc::recv(fd_event_);
|
const auto res = Ipc::recv(fd_event_);
|
||||||
signal_event.emit(res);
|
signal_event.emit(res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,47 +12,52 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
|
||||||
box_.get_style_context()->add_class(id);
|
box_.get_style_context()->add_class(id);
|
||||||
}
|
}
|
||||||
ipc_.subscribe("[ \"workspace\" ]");
|
ipc_.subscribe("[ \"workspace\" ]");
|
||||||
|
ipc_.signal_event.connect(sigc::mem_fun(*this, &Workspaces::onEvent));
|
||||||
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd));
|
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd));
|
||||||
|
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||||
// Launch worker
|
// Launch worker
|
||||||
worker();
|
worker();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::onCmd(const struct Ipc::ipc_response res) {
|
void Workspaces::onEvent(const struct Ipc::ipc_response res) { ipc_.sendCmd(IPC_GET_WORKSPACES); }
|
||||||
if (thread_.isRunning()) {
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
|
||||||
workspaces_ = parser_.parse(res.payload);
|
|
||||||
dp.emit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const Json::Value Workspaces::getWorkspaces() {
|
void Workspaces::onCmd(const struct Ipc::ipc_response res) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
if (res.type == IPC_GET_WORKSPACES) {
|
||||||
return workspaces_;
|
auto workspaces = parser_.parse(res.payload);
|
||||||
|
workspaces_.clear();
|
||||||
|
std::copy_if(workspaces.begin(),
|
||||||
|
workspaces.end(),
|
||||||
|
std::back_inserter(workspaces_),
|
||||||
|
[&](const auto &workspace) {
|
||||||
|
return !config_["all-outputs"].asBool()
|
||||||
|
? workspace["output"].asString() == bar_.output->name
|
||||||
|
: true;
|
||||||
|
});
|
||||||
|
dp.emit();
|
||||||
|
} else {
|
||||||
|
if (scrolling_) {
|
||||||
|
scrolling_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::worker() {
|
void Workspaces::worker() {
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
try {
|
try {
|
||||||
if (!getWorkspaces().empty()) {
|
ipc_.handleEvent();
|
||||||
ipc_.handleEvent();
|
|
||||||
}
|
|
||||||
if (thread_.isRunning()) {
|
|
||||||
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
|
||||||
}
|
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << "Workspaces: " << e.what() << std::endl;
|
std::cerr << "Workspaces: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Workspaces::update() -> void {
|
bool Workspaces::filterButtons() {
|
||||||
bool needReorder = false;
|
bool needReorder = false;
|
||||||
auto workspaces = getWorkspaces();
|
|
||||||
for (auto it = buttons_.begin(); it != buttons_.end();) {
|
for (auto it = buttons_.begin(); it != buttons_.end();) {
|
||||||
auto ws = std::find_if(workspaces.begin(), workspaces.end(), [it](auto node) -> bool {
|
auto ws = std::find_if(workspaces_.begin(), workspaces_.end(), [it](const auto &node) {
|
||||||
return node["name"].asString() == it->first;
|
return node["name"].asString() == it->first;
|
||||||
});
|
});
|
||||||
if (ws == workspaces.end() ||
|
if (ws == workspaces_.end() ||
|
||||||
(!config_["all-outputs"].asBool() && (*ws)["output"].asString() != bar_.output->name)) {
|
(!config_["all-outputs"].asBool() && (*ws)["output"].asString() != bar_.output->name)) {
|
||||||
it = buttons_.erase(it);
|
it = buttons_.erase(it);
|
||||||
needReorder = true;
|
needReorder = true;
|
||||||
|
@ -60,75 +65,60 @@ auto Workspaces::update() -> void {
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto const &node : workspaces) {
|
return needReorder;
|
||||||
if (!config_["all-outputs"].asBool() && bar_.output->name != node["output"].asString()) {
|
}
|
||||||
continue;
|
|
||||||
}
|
auto Workspaces::update() -> void {
|
||||||
auto it = buttons_.find(node["name"].asString());
|
bool needReorder = filterButtons();
|
||||||
if (it == buttons_.end()) {
|
for (auto it = workspaces_.begin(); it != workspaces_.end(); ++it) {
|
||||||
addWorkspace(node);
|
auto bit = buttons_.find((*it)["name"].asString());
|
||||||
|
if (bit == buttons_.end()) {
|
||||||
needReorder = true;
|
needReorder = true;
|
||||||
} else {
|
|
||||||
auto &button = it->second;
|
|
||||||
if (node["focused"].asBool()) {
|
|
||||||
button.get_style_context()->add_class("focused");
|
|
||||||
} else {
|
|
||||||
button.get_style_context()->remove_class("focused");
|
|
||||||
}
|
|
||||||
if (node["visible"].asBool()) {
|
|
||||||
button.get_style_context()->add_class("visible");
|
|
||||||
} else {
|
|
||||||
button.get_style_context()->remove_class("visible");
|
|
||||||
}
|
|
||||||
if (node["urgent"].asBool()) {
|
|
||||||
button.get_style_context()->add_class("urgent");
|
|
||||||
} else {
|
|
||||||
button.get_style_context()->remove_class("urgent");
|
|
||||||
}
|
|
||||||
if (needReorder) {
|
|
||||||
box_.reorder_child(button, getWorkspaceIndex(workspaces, node["name"].asString()));
|
|
||||||
}
|
|
||||||
auto icon = getIcon(node["name"].asString(), node);
|
|
||||||
std::string output = icon;
|
|
||||||
if (config_["format"].isString()) {
|
|
||||||
auto format = config_["format"].asString();
|
|
||||||
output = fmt::format(format,
|
|
||||||
fmt::arg("icon", icon),
|
|
||||||
fmt::arg("name", trimWorkspaceName(node["name"].asString())),
|
|
||||||
fmt::arg("index", node["num"].asString()));
|
|
||||||
}
|
|
||||||
if (!config_["disable-markup"].asBool()) {
|
|
||||||
static_cast<Gtk::Label *>(button.get_children()[0])->set_markup(output);
|
|
||||||
} else {
|
|
||||||
button.set_label(output);
|
|
||||||
}
|
|
||||||
onButtonReady(node, button);
|
|
||||||
}
|
}
|
||||||
}
|
auto &button = bit == buttons_.end() ? addButton(*it) : bit->second;
|
||||||
if (scrolling_) {
|
if ((*it)["focused"].asBool()) {
|
||||||
scrolling_ = false;
|
button.get_style_context()->add_class("focused");
|
||||||
|
} else {
|
||||||
|
button.get_style_context()->remove_class("focused");
|
||||||
|
}
|
||||||
|
if ((*it)["visible"].asBool()) {
|
||||||
|
button.get_style_context()->add_class("visible");
|
||||||
|
} else {
|
||||||
|
button.get_style_context()->remove_class("visible");
|
||||||
|
}
|
||||||
|
if ((*it)["urgent"].asBool()) {
|
||||||
|
button.get_style_context()->add_class("urgent");
|
||||||
|
} else {
|
||||||
|
button.get_style_context()->remove_class("urgent");
|
||||||
|
}
|
||||||
|
if (needReorder) {
|
||||||
|
box_.reorder_child(button, it - workspaces_.begin());
|
||||||
|
}
|
||||||
|
std::string output = getIcon((*it)["name"].asString(), *it);
|
||||||
|
if (config_["format"].isString()) {
|
||||||
|
auto format = config_["format"].asString();
|
||||||
|
output = fmt::format(format,
|
||||||
|
fmt::arg("icon", output),
|
||||||
|
fmt::arg("name", trimWorkspaceName((*it)["name"].asString())),
|
||||||
|
fmt::arg("index", (*it)["num"].asString()));
|
||||||
|
}
|
||||||
|
if (!config_["disable-markup"].asBool()) {
|
||||||
|
static_cast<Gtk::Label *>(button.get_children()[0])->set_markup(output);
|
||||||
|
} else {
|
||||||
|
button.set_label(output);
|
||||||
|
}
|
||||||
|
onButtonReady(*it, button);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspaces::addWorkspace(const Json::Value &node) {
|
Gtk::Button &Workspaces::addButton(const Json::Value &node) {
|
||||||
auto icon = getIcon(node["name"].asString(), node);
|
auto pair = buttons_.emplace(node["name"].asString(), node["name"].asString());
|
||||||
auto format = config_["format"].isString()
|
|
||||||
? fmt::format(config_["format"].asString(),
|
|
||||||
fmt::arg("icon", icon),
|
|
||||||
fmt::arg("name", trimWorkspaceName(node["name"].asString())),
|
|
||||||
fmt::arg("index", node["num"].asString()))
|
|
||||||
: icon;
|
|
||||||
auto pair = buttons_.emplace(node["name"].asString(), format);
|
|
||||||
auto &button = pair.first->second;
|
auto &button = pair.first->second;
|
||||||
if (!config_["disable-markup"].asBool()) {
|
|
||||||
static_cast<Gtk::Label *>(button.get_children()[0])->set_markup(format);
|
|
||||||
}
|
|
||||||
box_.pack_start(button, false, false, 0);
|
box_.pack_start(button, false, false, 0);
|
||||||
button.set_relief(Gtk::RELIEF_NONE);
|
button.set_relief(Gtk::RELIEF_NONE);
|
||||||
button.signal_clicked().connect([this, pair] {
|
button.signal_clicked().connect([this, pair] {
|
||||||
try {
|
try {
|
||||||
auto cmd = fmt::format("workspace \"{}\"", pair.first->first);
|
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", pair.first->first));
|
||||||
ipc_.sendCmd(IPC_COMMAND, cmd);
|
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -137,19 +127,7 @@ void Workspaces::addWorkspace(const Json::Value &node) {
|
||||||
button.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
button.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
|
||||||
button.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll));
|
button.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll));
|
||||||
}
|
}
|
||||||
auto workspaces = getWorkspaces();
|
return button;
|
||||||
box_.reorder_child(button, getWorkspaceIndex(workspaces, node["name"].asString()));
|
|
||||||
if (node["focused"].asBool()) {
|
|
||||||
button.get_style_context()->add_class("focused");
|
|
||||||
}
|
|
||||||
if (node["visible"].asBool()) {
|
|
||||||
button.get_style_context()->add_class("visible");
|
|
||||||
}
|
|
||||||
if (node["urgent"].asBool()) {
|
|
||||||
button.get_style_context()->add_class("urgent");
|
|
||||||
}
|
|
||||||
|
|
||||||
onButtonReady(node, button);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Workspaces::getIcon(const std::string &name, const Json::Value &node) {
|
std::string Workspaces::getIcon(const std::string &name, const Json::Value &node) {
|
||||||
|
@ -171,82 +149,57 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
|
||||||
if (scrolling_) {
|
if (scrolling_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto workspaces = getWorkspaces();
|
|
||||||
uint8_t idx;
|
|
||||||
scrolling_ = true;
|
scrolling_ = true;
|
||||||
for (idx = 0; idx < workspaces.size(); idx += 1) {
|
std::string name;
|
||||||
if (workspaces[idx]["focused"].asBool()) {
|
auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) {
|
||||||
break;
|
return workspace["focused"].asBool();
|
||||||
}
|
});
|
||||||
}
|
if (it == workspaces_.end()) {
|
||||||
if (idx == workspaces.size()) {
|
|
||||||
scrolling_ = false;
|
scrolling_ = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string name;
|
switch (e->direction) {
|
||||||
if (e->direction == GDK_SCROLL_UP) {
|
case GDK_SCROLL_DOWN:
|
||||||
name = getCycleWorkspace(workspaces, idx, true);
|
case GDK_SCROLL_RIGHT:
|
||||||
|
name = getCycleWorkspace(it, false);
|
||||||
|
break;
|
||||||
|
case GDK_SCROLL_UP:
|
||||||
|
case GDK_SCROLL_LEFT:
|
||||||
|
name = getCycleWorkspace(it, true);
|
||||||
|
break;
|
||||||
|
case GDK_SCROLL_SMOOTH:
|
||||||
|
gdouble delta_x, delta_y;
|
||||||
|
gdk_event_get_scroll_deltas(reinterpret_cast<const GdkEvent *>(e), &delta_x, &delta_y);
|
||||||
|
if (delta_y < 0) {
|
||||||
|
name = getCycleWorkspace(it, true);
|
||||||
|
} else if (delta_y > 0) {
|
||||||
|
name = getCycleWorkspace(it, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (e->direction == GDK_SCROLL_DOWN) {
|
if (name.empty() || name == (*it)["name"].asString()) {
|
||||||
name = getCycleWorkspace(workspaces, idx, false);
|
|
||||||
}
|
|
||||||
if (e->direction == GDK_SCROLL_SMOOTH) {
|
|
||||||
gdouble delta_x, delta_y;
|
|
||||||
gdk_event_get_scroll_deltas(reinterpret_cast<const GdkEvent *>(e), &delta_x, &delta_y);
|
|
||||||
if (delta_y < 0) {
|
|
||||||
name = getCycleWorkspace(workspaces, idx, true);
|
|
||||||
} else if (delta_y > 0) {
|
|
||||||
name = getCycleWorkspace(workspaces, idx, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (name.empty() || name == workspaces[idx]["name"].asString()) {
|
|
||||||
scrolling_ = false;
|
scrolling_ = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", name));
|
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", name));
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string Workspaces::getCycleWorkspace(const Json::Value &workspaces,
|
const std::string Workspaces::getCycleWorkspace(std::vector<Json::Value>::iterator it,
|
||||||
uint8_t focused_workspace, bool prev) const {
|
bool prev) const {
|
||||||
auto inc = prev ? -1 : 1;
|
if (prev && it == workspaces_.begin()) {
|
||||||
int size = workspaces.size();
|
return (*(--workspaces_.end()))["name"].asString();
|
||||||
uint8_t idx = 0;
|
|
||||||
for (int i = focused_workspace; i < size && i >= 0; i += inc) {
|
|
||||||
bool same_output = (workspaces[i]["output"].asString() == bar_.output->name &&
|
|
||||||
!config_["all-outputs"].asBool()) ||
|
|
||||||
config_["all-outputs"].asBool();
|
|
||||||
bool same_name =
|
|
||||||
workspaces[i]["name"].asString() == workspaces[focused_workspace]["name"].asString();
|
|
||||||
if (same_output && !same_name) {
|
|
||||||
return workspaces[i]["name"].asString();
|
|
||||||
}
|
|
||||||
if (prev && i - 1 < 0) {
|
|
||||||
i = size;
|
|
||||||
} else if (!prev && i + 1 >= size) {
|
|
||||||
i = -1;
|
|
||||||
} else if (idx >= workspaces.size()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
idx += 1;
|
|
||||||
}
|
}
|
||||||
return "";
|
if (prev && it != workspaces_.begin())
|
||||||
}
|
--it;
|
||||||
|
else if (!prev && it != workspaces_.end())
|
||||||
uint16_t Workspaces::getWorkspaceIndex(const Json::Value &workspaces,
|
++it;
|
||||||
const std::string &name) const {
|
if (!prev && it == workspaces_.end()) {
|
||||||
uint16_t idx = 0;
|
return (*(++workspaces_.begin()))["name"].asString();
|
||||||
for (const auto &workspace : workspaces) {
|
|
||||||
if (workspace["name"].asString() == name) {
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
if (!(!config_["all-outputs"].asBool() &&
|
|
||||||
workspace["output"].asString() != bar_.output->name)) {
|
|
||||||
idx += 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return workspaces.size();
|
return (*it)["name"].asString();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Workspaces::trimWorkspaceName(std::string name) {
|
std::string Workspaces::trimWorkspaceName(std::string name) {
|
||||||
|
|
Loading…
Reference in New Issue