mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
fix(Workspaces): fix concurrence and move json parser to ipc client
This commit is contained in:
parent
07dba791cf
commit
cccf60c30e
@ -6,8 +6,10 @@
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "ipc.hpp"
|
||||
#include "util/json.hpp"
|
||||
|
||||
namespace waybar::modules::sway {
|
||||
|
||||
@ -19,7 +21,7 @@ class Ipc {
|
||||
struct ipc_response {
|
||||
uint32_t size;
|
||||
uint32_t type;
|
||||
std::string payload;
|
||||
Json::Value payload;
|
||||
};
|
||||
|
||||
sigc::signal<void, const struct ipc_response> signal_event;
|
||||
@ -38,10 +40,11 @@ class Ipc {
|
||||
struct ipc_response send(int fd, uint32_t type, const std::string &payload = "");
|
||||
struct ipc_response recv(int fd);
|
||||
|
||||
int fd_;
|
||||
int fd_event_;
|
||||
std::mutex mutex_;
|
||||
std::mutex mutex_event_;
|
||||
int fd_;
|
||||
int fd_event_;
|
||||
std::mutex mutex_;
|
||||
std::mutex mutex_event_;
|
||||
util::JsonParser parser_;
|
||||
};
|
||||
|
||||
} // namespace waybar::modules::sway
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include "bar.hpp"
|
||||
#include "client.hpp"
|
||||
#include "modules/sway/ipc/client.hpp"
|
||||
#include "util/json.hpp"
|
||||
#include "util/sleeper_thread.hpp"
|
||||
|
||||
namespace waybar::modules::sway {
|
||||
@ -22,7 +21,6 @@ class Mode : public ALabel {
|
||||
|
||||
const Bar& bar_;
|
||||
waybar::util::SleeperThread thread_;
|
||||
util::JsonParser parser_;
|
||||
Ipc ipc_;
|
||||
std::string mode_;
|
||||
};
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "bar.hpp"
|
||||
#include "client.hpp"
|
||||
#include "modules/sway/ipc/client.hpp"
|
||||
#include "util/json.hpp"
|
||||
#include "util/sleeper_thread.hpp"
|
||||
|
||||
namespace waybar::modules::sway {
|
||||
@ -26,7 +25,6 @@ class Window : public ALabel {
|
||||
|
||||
const Bar& bar_;
|
||||
waybar::util::SleeperThread thread_;
|
||||
util::JsonParser parser_;
|
||||
Ipc ipc_;
|
||||
std::string window_;
|
||||
int windowId_;
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "bar.hpp"
|
||||
#include "client.hpp"
|
||||
#include "modules/sway/ipc/client.hpp"
|
||||
#include "util/json.hpp"
|
||||
#include "util/sleeper_thread.hpp"
|
||||
|
||||
namespace waybar::modules::sway {
|
||||
@ -36,8 +35,8 @@ class Workspaces : public IModule {
|
||||
const Json::Value& config_;
|
||||
std::vector<Json::Value> workspaces_;
|
||||
waybar::util::SleeperThread thread_;
|
||||
std::mutex mutex_;
|
||||
Gtk::Box box_;
|
||||
util::JsonParser parser_;
|
||||
Ipc ipc_;
|
||||
bool scrolling_;
|
||||
std::unordered_map<std::string, Gtk::Button> buttons_;
|
||||
|
@ -7,13 +7,14 @@ namespace waybar::util {
|
||||
struct JsonParser {
|
||||
JsonParser() : reader_(builder_.newCharReader()) {}
|
||||
|
||||
const Json::Value parse(const std::string& data) const {
|
||||
Json::Value root;
|
||||
std::string err;
|
||||
const Json::Value parse(const std::string& data, std::size_t size = 0) const {
|
||||
Json::Value root(Json::objectValue);
|
||||
if (data.empty()) {
|
||||
return root;
|
||||
}
|
||||
bool res = reader_->parse(data.c_str(), data.c_str() + data.size(), &root, &err);
|
||||
std::string err;
|
||||
auto data_size = size > 0 ? size : data.size();
|
||||
bool res = reader_->parse(data.c_str(), data.c_str() + data_size, &root, &err);
|
||||
if (!res) throw std::runtime_error(err);
|
||||
return root;
|
||||
}
|
||||
|
@ -259,13 +259,12 @@ void waybar::modules::MPD::tryConnect() {
|
||||
|
||||
try {
|
||||
checkErrors(connection_.get());
|
||||
std::cerr << module_name_ << ": Connected to MPD" << std::endl;
|
||||
} catch (std::runtime_error& e) {
|
||||
std::cerr << module_name_ << ": Failed to connect to MPD: " << e.what() << std::endl;
|
||||
connection_.reset();
|
||||
alternate_connection_.reset();
|
||||
}
|
||||
|
||||
std::cerr << module_name_ << ": Connected to MPD" << std::endl;
|
||||
}
|
||||
|
||||
void waybar::modules::MPD::checkErrors(mpd_connection* conn) {
|
||||
|
@ -97,11 +97,15 @@ struct Ipc::ipc_response Ipc::recv(int fd) {
|
||||
while (total < data32[0]) {
|
||||
auto res = ::recv(fd, payload.data() + total, data32[0] - total, 0);
|
||||
if (res < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
throw std::runtime_error("Unable to receive IPC payload");
|
||||
}
|
||||
total += res;
|
||||
}
|
||||
return {data32[0], data32[1], &payload.front()};
|
||||
auto parsed = parser_.parse(&payload.front(), data32[0]);
|
||||
return {data32[0], data32[1], parsed};
|
||||
}
|
||||
|
||||
struct Ipc::ipc_response Ipc::send(int fd, uint32_t type, const std::string& payload) {
|
||||
@ -130,7 +134,7 @@ void Ipc::sendCmd(uint32_t type, const std::string& payload) {
|
||||
void Ipc::subscribe(const std::string& payload) {
|
||||
std::lock_guard<std::mutex> lock(mutex_event_);
|
||||
auto res = Ipc::send(fd_event_, IPC_SUBSCRIBE, payload);
|
||||
if (res.payload != "{\"success\": true}") {
|
||||
if (!res.payload["success"].asBool()) {
|
||||
throw std::runtime_error("Unable to subscribe ipc event");
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,8 @@ Mode::Mode(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
}
|
||||
|
||||
void Mode::onEvent(const struct Ipc::ipc_response res) {
|
||||
auto parsed = parser_.parse(res.payload);
|
||||
if (parsed["change"] != "default") {
|
||||
mode_ = parsed["change"].asString();
|
||||
if (res.payload["change"] != "default") {
|
||||
mode_ = res.payload["change"].asString();
|
||||
} else {
|
||||
mode_.clear();
|
||||
}
|
||||
|
@ -21,18 +21,17 @@ Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
}
|
||||
|
||||
void Window::onEvent(const struct Ipc::ipc_response res) {
|
||||
auto parsed = parser_.parse(res.payload);
|
||||
auto data = res.payload;
|
||||
// Check for waybar prevents flicker when hovering window module
|
||||
if ((parsed["change"] == "focus" || parsed["change"] == "title") &&
|
||||
parsed["container"]["focused"].asBool() &&
|
||||
parsed["container"]["name"].asString() != "waybar") {
|
||||
window_ = Glib::Markup::escape_text(parsed["container"]["name"].asString());
|
||||
windowId_ = parsed["container"]["id"].asInt();
|
||||
if ((data["change"] == "focus" || data["change"] == "title") &&
|
||||
data["container"]["focused"].asBool() && data["container"]["name"].asString() != "waybar") {
|
||||
window_ = Glib::Markup::escape_text(data["container"]["name"].asString());
|
||||
windowId_ = data["container"]["id"].asInt();
|
||||
dp.emit();
|
||||
} else if ((parsed["change"] == "close" && parsed["container"]["focused"].asBool() &&
|
||||
windowId_ == parsed["container"]["id"].asInt()) ||
|
||||
(parsed["change"] == "focus" && parsed["current"]["focus"].isArray() &&
|
||||
parsed["current"]["focus"].empty())) {
|
||||
} else if ((data["change"] == "close" && data["container"]["focused"].asBool() &&
|
||||
windowId_ == data["container"]["id"].asInt()) ||
|
||||
(data["change"] == "focus" && data["current"]["focus"].isArray() &&
|
||||
data["current"]["focus"].empty())) {
|
||||
window_.clear();
|
||||
windowId_ = -1;
|
||||
dp.emit();
|
||||
@ -40,8 +39,7 @@ void Window::onEvent(const struct Ipc::ipc_response res) {
|
||||
}
|
||||
|
||||
void Window::onCmd(const struct Ipc::ipc_response res) {
|
||||
auto parsed = parser_.parse(res.payload);
|
||||
auto [id, name] = getFocusedNode(parsed["nodes"]);
|
||||
auto [id, name] = getFocusedNode(res.payload["nodes"]);
|
||||
windowId_ = id;
|
||||
window_ = name;
|
||||
dp.emit();
|
||||
|
@ -23,17 +23,19 @@ void Workspaces::onEvent(const struct Ipc::ipc_response res) { ipc_.sendCmd(IPC_
|
||||
|
||||
void Workspaces::onCmd(const struct Ipc::ipc_response res) {
|
||||
if (res.type == IPC_GET_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();
|
||||
if (res.payload.isArray()) {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
workspaces_.clear();
|
||||
std::copy_if(res.payload.begin(),
|
||||
res.payload.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;
|
||||
@ -69,7 +71,8 @@ bool Workspaces::filterButtons() {
|
||||
}
|
||||
|
||||
auto Workspaces::update() -> void {
|
||||
bool needReorder = filterButtons();
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
bool needReorder = filterButtons();
|
||||
for (auto it = workspaces_.begin(); it != workspaces_.end(); ++it) {
|
||||
auto bit = buttons_.find((*it)["name"].asString());
|
||||
if (bit == buttons_.end()) {
|
||||
@ -149,39 +152,42 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
|
||||
if (scrolling_) {
|
||||
return false;
|
||||
}
|
||||
scrolling_ = true;
|
||||
std::string name;
|
||||
auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) {
|
||||
return workspace["focused"].asBool();
|
||||
});
|
||||
if (it == workspaces_.end()) {
|
||||
scrolling_ = false;
|
||||
return false;
|
||||
}
|
||||
switch (e->direction) {
|
||||
case GDK_SCROLL_DOWN:
|
||||
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) {
|
||||
scrolling_ = true;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto it = std::find_if(workspaces_.begin(), workspaces_.end(), [](const auto &workspace) {
|
||||
return workspace["focused"].asBool();
|
||||
});
|
||||
if (it == workspaces_.end()) {
|
||||
scrolling_ = false;
|
||||
return false;
|
||||
}
|
||||
switch (e->direction) {
|
||||
case GDK_SCROLL_DOWN:
|
||||
case GDK_SCROLL_RIGHT:
|
||||
name = getCycleWorkspace(it, false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (name.empty() || name == (*it)["name"].asString()) {
|
||||
scrolling_ = false;
|
||||
return 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 (name.empty() || name == (*it)["name"].asString()) {
|
||||
scrolling_ = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", name));
|
||||
return true;
|
||||
|
Loading…
Reference in New Issue
Block a user