mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
Clean (#31)
This commit is contained in:
@ -1,14 +1,17 @@
|
||||
#define _POSIX_C_SOURCE 200809L
|
||||
#include "modules/sway/ipc/client.hpp"
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
|
||||
static const std::string ipc_magic("i3-ipc");
|
||||
static const size_t ipc_header_size = ipc_magic.size() + 8;
|
||||
waybar::modules::sway::Ipc::Ipc()
|
||||
: fd_(-1), fd_event_(-1)
|
||||
{}
|
||||
|
||||
std::string getSocketPath() {
|
||||
waybar::modules::sway::Ipc::~Ipc()
|
||||
{
|
||||
close(fd_);
|
||||
close(fd_event_);
|
||||
}
|
||||
|
||||
const std::string waybar::modules::sway::Ipc::getSocketPath() const
|
||||
{
|
||||
const char *env = getenv("SWAYSOCK");
|
||||
if (env != nullptr) {
|
||||
return std::string(env);
|
||||
@ -33,31 +36,41 @@ std::string getSocketPath() {
|
||||
return str;
|
||||
}
|
||||
|
||||
int ipcOpenSocket(const std::string &socketPath) {
|
||||
int waybar::modules::sway::Ipc::open(const std::string& socketPath) const
|
||||
{
|
||||
struct sockaddr_un addr = {0};
|
||||
int socketfd;
|
||||
if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
int fd = -1;
|
||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
||||
throw std::runtime_error("Unable to open Unix socket");
|
||||
}
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1);
|
||||
addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
|
||||
int l = sizeof(struct sockaddr_un);
|
||||
if (connect(socketfd, reinterpret_cast<struct sockaddr *>(&addr), l) == -1) {
|
||||
if (::connect(fd, reinterpret_cast<struct sockaddr *>(&addr), l) == -1) {
|
||||
throw std::runtime_error("Unable to connect to " + socketPath);
|
||||
}
|
||||
return socketfd;
|
||||
return fd;
|
||||
}
|
||||
|
||||
struct ipc_response ipcRecvResponse(int socketfd) {
|
||||
void waybar::modules::sway::Ipc::connect()
|
||||
{
|
||||
const std::string& socketPath = getSocketPath();
|
||||
fd_ = open(socketPath);
|
||||
fd_event_ = open(socketPath);
|
||||
}
|
||||
|
||||
struct waybar::modules::sway::Ipc::ipc_response
|
||||
waybar::modules::sway::Ipc::recv(int fd) const
|
||||
{
|
||||
std::string header;
|
||||
header.reserve(ipc_header_size);
|
||||
auto data32 = reinterpret_cast<uint32_t *>(header.data() + ipc_magic.size());
|
||||
header.reserve(ipc_header_size_);
|
||||
auto data32 = reinterpret_cast<uint32_t *>(header.data() + ipc_magic_.size());
|
||||
size_t total = 0;
|
||||
|
||||
while (total < ipc_header_size) {
|
||||
while (total < ipc_header_size_) {
|
||||
ssize_t res =
|
||||
::recv(socketfd, header.data() + total, ipc_header_size - total, 0);
|
||||
::recv(fd, header.data() + total, ipc_header_size_ - total, 0);
|
||||
if (res <= 0) {
|
||||
throw std::runtime_error("Unable to receive IPC response");
|
||||
}
|
||||
@ -66,32 +79,56 @@ struct ipc_response ipcRecvResponse(int socketfd) {
|
||||
|
||||
total = 0;
|
||||
std::string payload;
|
||||
payload.reserve(data32[0]);
|
||||
payload.reserve(data32[0] + 1);
|
||||
while (total < data32[0]) {
|
||||
ssize_t res =
|
||||
::recv(socketfd, payload.data() + total, data32[0] - total, 0);
|
||||
::recv(fd, payload.data() + total, data32[0] - total, 0);
|
||||
if (res < 0) {
|
||||
throw std::runtime_error("Unable to receive IPC response");
|
||||
}
|
||||
total += res;
|
||||
}
|
||||
payload[data32[0]] = 0;
|
||||
return { data32[0], data32[1], &payload.front() };
|
||||
}
|
||||
|
||||
struct ipc_response ipcSingleCommand(int socketfd, uint32_t type,
|
||||
const std::string& payload) {
|
||||
struct waybar::modules::sway::Ipc::ipc_response
|
||||
waybar::modules::sway::Ipc::send(int fd, uint32_t type,
|
||||
const std::string& payload) const
|
||||
{
|
||||
std::string header;
|
||||
header.reserve(ipc_header_size);
|
||||
auto data32 = reinterpret_cast<uint32_t *>(header.data() + ipc_magic.size());
|
||||
memcpy(header.data(), ipc_magic.c_str(), ipc_magic.size());
|
||||
header.reserve(ipc_header_size_);
|
||||
auto data32 = reinterpret_cast<uint32_t *>(header.data() + ipc_magic_.size());
|
||||
memcpy(header.data(), ipc_magic_.c_str(), ipc_magic_.size());
|
||||
data32[0] = payload.size();
|
||||
data32[1] = type;
|
||||
|
||||
if (send(socketfd, header.data(), ipc_header_size, 0) == -1) {
|
||||
if (::send(fd, header.data(), ipc_header_size_, 0) == -1) {
|
||||
throw std::runtime_error("Unable to send IPC header");
|
||||
}
|
||||
if (send(socketfd, payload.c_str(), payload.size(), 0) == -1) {
|
||||
if (::send(fd, payload.c_str(), payload.size(), 0) == -1) {
|
||||
throw std::runtime_error("Unable to send IPC payload");
|
||||
}
|
||||
return ipcRecvResponse(socketfd);
|
||||
return recv(fd);
|
||||
}
|
||||
|
||||
struct waybar::modules::sway::Ipc::ipc_response
|
||||
waybar::modules::sway::Ipc::sendCmd(uint32_t type,
|
||||
const std::string& payload) const
|
||||
{
|
||||
return send(fd_, type, payload);
|
||||
}
|
||||
|
||||
void waybar::modules::sway::Ipc::subscribe(const std::string& payload) const
|
||||
{
|
||||
auto res = send(fd_event_, IPC_SUBSCRIBE, payload);
|
||||
if (res.payload != "{\"success\": true}") {
|
||||
throw std::runtime_error("Unable to subscribe ipc event");
|
||||
}
|
||||
}
|
||||
|
||||
struct waybar::modules::sway::Ipc::ipc_response
|
||||
waybar::modules::sway::Ipc::handleEvent() const
|
||||
{
|
||||
return recv(fd_event_);
|
||||
}
|
@ -1,24 +1,26 @@
|
||||
#include "modules/sway/window.hpp"
|
||||
#include "modules/sway/ipc/client.hpp"
|
||||
|
||||
waybar::modules::sway::Window::Window(Bar &bar, Json::Value config)
|
||||
: ALabel(std::move(config)), bar_(bar)
|
||||
waybar::modules::sway::Window::Window(Bar &bar, const Json::Value& config)
|
||||
: ALabel(config), bar_(bar)
|
||||
{
|
||||
label_.set_name("window");
|
||||
std::string socketPath = getSocketPath();
|
||||
ipcfd_ = ipcOpenSocket(socketPath);
|
||||
ipc_eventfd_ = ipcOpenSocket(socketPath);
|
||||
ipcSingleCommand(ipc_eventfd_, IPC_SUBSCRIBE, "[ \"window\" ]");
|
||||
ipc_.connect();
|
||||
ipc_.subscribe("[ \"window\" ]");
|
||||
getFocusedWindow();
|
||||
thread_.sig_update.connect(sigc::mem_fun(*this, &Window::update));
|
||||
// Launch worker
|
||||
worker();
|
||||
}
|
||||
|
||||
void waybar::modules::sway::Window::worker()
|
||||
{
|
||||
thread_ = [this] {
|
||||
try {
|
||||
auto res = ipcRecvResponse(ipc_eventfd_);
|
||||
auto res = ipc_.handleEvent();
|
||||
auto parsed = parser_.parse(res.payload);
|
||||
if ((parsed["change"] == "focus" || parsed["change"] == "title")
|
||||
&& parsed["container"]["focused"].asBool()) {
|
||||
window_ = parsed["container"]["name"].asString();
|
||||
thread_.emit();
|
||||
dp.emit();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
@ -26,12 +28,6 @@ waybar::modules::sway::Window::Window(Bar &bar, Json::Value config)
|
||||
};
|
||||
}
|
||||
|
||||
waybar::modules::sway::Window::~Window()
|
||||
{
|
||||
close(ipcfd_);
|
||||
close(ipc_eventfd_);
|
||||
}
|
||||
|
||||
auto waybar::modules::sway::Window::update() -> void
|
||||
{
|
||||
label_.set_text(window_);
|
||||
@ -55,7 +51,7 @@ std::string waybar::modules::sway::Window::getFocusedNode(Json::Value nodes)
|
||||
void waybar::modules::sway::Window::getFocusedWindow()
|
||||
{
|
||||
try {
|
||||
auto res = ipcSingleCommand(ipcfd_, IPC_GET_TREE, "");
|
||||
auto res = ipc_.sendCmd(IPC_GET_TREE);
|
||||
auto parsed = parser_.parse(res.payload);
|
||||
window_ = getFocusedNode(parsed["nodes"]);
|
||||
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Window::update));
|
||||
|
@ -1,15 +1,18 @@
|
||||
#include "modules/sway/workspaces.hpp"
|
||||
#include "modules/sway/ipc/client.hpp"
|
||||
|
||||
waybar::modules::sway::Workspaces::Workspaces(Bar &bar, Json::Value config)
|
||||
: bar_(bar), config_(std::move(config)), scrolling_(false)
|
||||
waybar::modules::sway::Workspaces::Workspaces(Bar& bar,
|
||||
const Json::Value& config)
|
||||
: bar_(bar), config_(config), scrolling_(false)
|
||||
{
|
||||
box_.set_name("workspaces");
|
||||
std::string socketPath = getSocketPath();
|
||||
ipcfd_ = ipcOpenSocket(socketPath);
|
||||
ipc_eventfd_ = ipcOpenSocket(socketPath);
|
||||
ipcSingleCommand(ipc_eventfd_, IPC_SUBSCRIBE, "[ \"workspace\" ]");
|
||||
thread_.sig_update.connect(sigc::mem_fun(*this, &Workspaces::update));
|
||||
ipc_.connect();
|
||||
ipc_.subscribe("[ \"workspace\" ]");
|
||||
// Launch worker
|
||||
worker();
|
||||
}
|
||||
|
||||
void waybar::modules::sway::Workspaces::worker()
|
||||
{
|
||||
thread_ = [this] {
|
||||
try {
|
||||
// Wait for the name of the output
|
||||
@ -18,28 +21,24 @@ waybar::modules::sway::Workspaces::Workspaces(Bar &bar, Json::Value config)
|
||||
thread_.sleep_for(chrono::milliseconds(150));
|
||||
}
|
||||
} else if (!workspaces_.empty()) {
|
||||
ipcRecvResponse(ipc_eventfd_);
|
||||
ipc_.handleEvent();
|
||||
}
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto res = ipcSingleCommand(ipcfd_, IPC_GET_WORKSPACES, "");
|
||||
workspaces_ = parser_.parse(res.payload);
|
||||
thread_.emit();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto res = ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||
workspaces_ = parser_.parse(res.payload);
|
||||
}
|
||||
dp.emit();
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
waybar::modules::sway::Workspaces::~Workspaces()
|
||||
{
|
||||
close(ipcfd_);
|
||||
close(ipc_eventfd_);
|
||||
}
|
||||
|
||||
auto waybar::modules::sway::Workspaces::update() -> void
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
bool needReorder = false;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (auto it = buttons_.begin(); it != buttons_.end();) {
|
||||
auto ws = std::find_if(workspaces_.begin(), workspaces_.end(),
|
||||
[it](auto node) -> bool { return node["num"].asInt() == it->first; });
|
||||
@ -101,7 +100,7 @@ void waybar::modules::sway::Workspaces::addWorkspace(Json::Value node)
|
||||
try {
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto cmd = fmt::format("workspace \"{}\"", pair.first->first);
|
||||
ipcSingleCommand(ipcfd_, IPC_COMMAND, cmd);
|
||||
ipc_.sendCmd(IPC_COMMAND, cmd);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
}
|
||||
@ -144,11 +143,13 @@ bool waybar::modules::sway::Workspaces::handleScroll(GdkEventScroll *e)
|
||||
scrolling_ = true;
|
||||
int id = -1;
|
||||
uint16_t idx = 0;
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (; idx < workspaces_.size(); idx += 1) {
|
||||
if (workspaces_[idx]["focused"].asBool()) {
|
||||
id = workspaces_[idx]["num"].asInt();
|
||||
break;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
for (; idx < workspaces_.size(); idx += 1) {
|
||||
if (workspaces_[idx]["focused"].asBool()) {
|
||||
id = workspaces_[idx]["num"].asInt();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id == -1) {
|
||||
@ -171,12 +172,15 @@ bool waybar::modules::sway::Workspaces::handleScroll(GdkEventScroll *e)
|
||||
id = getPrevWorkspace();
|
||||
}
|
||||
}
|
||||
if (id == workspaces_[idx]["num"].asInt()) {
|
||||
scrolling_ = false;
|
||||
return false;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (id == workspaces_[idx]["num"].asInt()) {
|
||||
scrolling_ = false;
|
||||
return false;
|
||||
}
|
||||
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", id));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
||||
}
|
||||
ipcSingleCommand(ipcfd_, IPC_COMMAND, fmt::format("workspace \"{}\"", id));
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(150));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user