refactor(IPC): use sigc signal
This commit is contained in:
parent
4c8f4f82dc
commit
bb1cf7570e
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <sigc++/sigc++.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -20,9 +21,12 @@ class Ipc {
|
||||||
std::string payload;
|
std::string payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ipc_response sendCmd(uint32_t type, const std::string &payload = "") const;
|
sigc::signal<void, const struct ipc_response> signal_event;
|
||||||
void subscribe(const std::string &payload) const;
|
sigc::signal<void, const struct ipc_response> signal_cmd;
|
||||||
struct ipc_response handleEvent() const;
|
|
||||||
|
void sendCmd(uint32_t type, const std::string &payload = "") const;
|
||||||
|
void subscribe(const std::string &payload) const;
|
||||||
|
void handleEvent() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static inline const std::string ipc_magic_ = "i3-ipc";
|
static inline const std::string ipc_magic_ = "i3-ipc";
|
||||||
|
|
|
@ -17,6 +17,7 @@ class Mode : public ALabel {
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void onEvent(const struct Ipc::ipc_response);
|
||||||
void worker();
|
void worker();
|
||||||
|
|
||||||
const Bar& bar_;
|
const Bar& bar_;
|
||||||
|
|
|
@ -18,6 +18,8 @@ class Window : public ALabel {
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void onEvent(const struct Ipc::ipc_response);
|
||||||
|
void onCmd(const struct Ipc::ipc_response);
|
||||||
void worker();
|
void worker();
|
||||||
std::tuple<int, std::string> getFocusedNode(Json::Value nodes);
|
std::tuple<int, std::string> getFocusedNode(Json::Value nodes);
|
||||||
void getFocusedWindow();
|
void getFocusedWindow();
|
||||||
|
|
|
@ -20,6 +20,7 @@ class Workspaces : public IModule {
|
||||||
operator Gtk::Widget&();
|
operator Gtk::Widget&();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void onCmd(const struct Ipc::ipc_response);
|
||||||
void worker();
|
void worker();
|
||||||
void addWorkspace(const Json::Value&);
|
void addWorkspace(const Json::Value&);
|
||||||
void onButtonReady(const Json::Value&, Gtk::Button&);
|
void onButtonReady(const Json::Value&, Gtk::Button&);
|
||||||
|
|
|
@ -114,9 +114,9 @@ void waybar::modules::Network::worker() {
|
||||||
}
|
}
|
||||||
thread_timer_.sleep_for(interval_);
|
thread_timer_.sleep_for(interval_);
|
||||||
};
|
};
|
||||||
struct epoll_event events[EPOLL_MAX] = {{0}};
|
std::array<struct epoll_event, EPOLL_MAX> events;
|
||||||
thread_ = [this, &events] {
|
thread_ = [this, &events] {
|
||||||
int ec = epoll_wait(efd_, events, EPOLL_MAX, -1);
|
int ec = epoll_wait(efd_, events.data(), EPOLL_MAX, -1);
|
||||||
if (ec > 0) {
|
if (ec > 0) {
|
||||||
for (auto i = 0; i < ec; i++) {
|
for (auto i = 0; i < ec; i++) {
|
||||||
if (events[i].data.fd == nl_socket_get_fd(info_sock_)) {
|
if (events[i].data.fd == nl_socket_get_fd(info_sock_)) {
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
#include "modules/sway/ipc/client.hpp"
|
#include "modules/sway/ipc/client.hpp"
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
waybar::modules::sway::Ipc::Ipc() {
|
namespace waybar::modules::sway {
|
||||||
|
|
||||||
|
Ipc::Ipc() {
|
||||||
const std::string& socketPath = getSocketPath();
|
const std::string& socketPath = getSocketPath();
|
||||||
fd_ = open(socketPath);
|
fd_ = open(socketPath);
|
||||||
fd_event_ = open(socketPath);
|
fd_event_ = open(socketPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::modules::sway::Ipc::~Ipc() {
|
Ipc::~Ipc() {
|
||||||
// To fail the IPC header
|
// To fail the IPC header
|
||||||
write(fd_, "close-sway-ipc", 14);
|
write(fd_, "close-sway-ipc", 14);
|
||||||
write(fd_event_, "close-sway-ipc", 14);
|
write(fd_event_, "close-sway-ipc", 14);
|
||||||
|
if (fd_ > 0) {
|
||||||
close(fd_);
|
close(fd_);
|
||||||
close(fd_event_);
|
fd_ = -1;
|
||||||
|
}
|
||||||
|
if (fd_event_ > 0) {
|
||||||
|
close(fd_event_);
|
||||||
|
fd_event_ = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string waybar::modules::sway::Ipc::getSocketPath() const {
|
const std::string Ipc::getSocketPath() const {
|
||||||
const char* env = getenv("SWAYSOCK");
|
const char* env = getenv("SWAYSOCK");
|
||||||
if (env != nullptr) {
|
if (env != nullptr) {
|
||||||
return std::string(env);
|
return std::string(env);
|
||||||
|
@ -33,6 +41,9 @@ const std::string waybar::modules::sway::Ipc::getSocketPath() const {
|
||||||
}
|
}
|
||||||
pclose(in);
|
pclose(in);
|
||||||
str = str_buf;
|
str = str_buf;
|
||||||
|
if (str.empty()) {
|
||||||
|
throw std::runtime_error("Socket path is empty");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (str.back() == '\n') {
|
if (str.back() == '\n') {
|
||||||
str.pop_back();
|
str.pop_back();
|
||||||
|
@ -40,12 +51,14 @@ const std::string waybar::modules::sway::Ipc::getSocketPath() const {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
int waybar::modules::sway::Ipc::open(const std::string& socketPath) const {
|
int Ipc::open(const std::string& socketPath) const {
|
||||||
struct sockaddr_un addr = {0};
|
int32_t fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||||
int fd = -1;
|
if (fd == -1) {
|
||||||
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
|
||||||
throw std::runtime_error("Unable to open Unix socket");
|
throw std::runtime_error("Unable to open Unix socket");
|
||||||
}
|
}
|
||||||
|
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
struct sockaddr_un addr;
|
||||||
|
memset(&addr, 0, sizeof(struct sockaddr_un));
|
||||||
addr.sun_family = AF_UNIX;
|
addr.sun_family = AF_UNIX;
|
||||||
strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1);
|
strncpy(addr.sun_path, socketPath.c_str(), sizeof(addr.sun_path) - 1);
|
||||||
addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
|
addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
|
||||||
|
@ -56,7 +69,7 @@ int waybar::modules::sway::Ipc::open(const std::string& socketPath) const {
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct waybar::modules::sway::Ipc::ipc_response waybar::modules::sway::Ipc::recv(int fd) const {
|
struct Ipc::ipc_response Ipc::recv(int fd) const {
|
||||||
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());
|
||||||
|
@ -65,6 +78,10 @@ struct waybar::modules::sway::Ipc::ipc_response waybar::modules::sway::Ipc::recv
|
||||||
while (total < ipc_header_size_) {
|
while (total < ipc_header_size_) {
|
||||||
auto res = ::recv(fd, header.data() + total, ipc_header_size_ - total, 0);
|
auto res = ::recv(fd, header.data() + total, ipc_header_size_ - total, 0);
|
||||||
if (res <= 0) {
|
if (res <= 0) {
|
||||||
|
if (res <= 0 && (fd_event_ == -1 || fd_ == -1)) {
|
||||||
|
// IPC is closed so just return empty response
|
||||||
|
return {0, 0, ""};
|
||||||
|
}
|
||||||
throw std::runtime_error("Unable to receive IPC header");
|
throw std::runtime_error("Unable to receive IPC header");
|
||||||
}
|
}
|
||||||
total += res;
|
total += res;
|
||||||
|
@ -88,8 +105,7 @@ struct waybar::modules::sway::Ipc::ipc_response waybar::modules::sway::Ipc::recv
|
||||||
return {data32[0], data32[1], &payload.front()};
|
return {data32[0], data32[1], &payload.front()};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct waybar::modules::sway::Ipc::ipc_response waybar::modules::sway::Ipc::send(
|
struct Ipc::ipc_response Ipc::send(int fd, uint32_t type, const std::string& payload) const {
|
||||||
int fd, uint32_t type, const std::string& payload) const {
|
|
||||||
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());
|
||||||
|
@ -103,21 +119,24 @@ struct waybar::modules::sway::Ipc::ipc_response waybar::modules::sway::Ipc::send
|
||||||
if (::send(fd, 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");
|
throw std::runtime_error("Unable to send IPC payload");
|
||||||
}
|
}
|
||||||
return recv(fd);
|
return Ipc::recv(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct waybar::modules::sway::Ipc::ipc_response waybar::modules::sway::Ipc::sendCmd(
|
void Ipc::sendCmd(uint32_t type, const std::string& payload) const {
|
||||||
uint32_t type, const std::string& payload) const {
|
const auto res = Ipc::send(fd_, type, payload);
|
||||||
return send(fd_, type, payload);
|
signal_cmd.emit(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::sway::Ipc::subscribe(const std::string& payload) const {
|
void Ipc::subscribe(const std::string& payload) const {
|
||||||
auto res = 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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct waybar::modules::sway::Ipc::ipc_response waybar::modules::sway::Ipc::handleEvent() const {
|
void Ipc::handleEvent() const {
|
||||||
return recv(fd_event_);
|
const auto res = Ipc::recv(fd_event_);
|
||||||
|
signal_event.emit(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::sway
|
|
@ -1,35 +1,41 @@
|
||||||
#include "modules/sway/mode.hpp"
|
#include "modules/sway/mode.hpp"
|
||||||
|
|
||||||
waybar::modules::sway::Mode::Mode(const std::string& id, const Bar& bar, const Json::Value& config)
|
namespace waybar::modules::sway {
|
||||||
|
|
||||||
|
Mode::Mode(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
: ALabel(config, "{}"), bar_(bar) {
|
: ALabel(config, "{}"), bar_(bar) {
|
||||||
label_.set_name("mode");
|
label_.set_name("mode");
|
||||||
if (!id.empty()) {
|
if (!id.empty()) {
|
||||||
label_.get_style_context()->add_class(id);
|
label_.get_style_context()->add_class(id);
|
||||||
}
|
}
|
||||||
ipc_.subscribe("[ \"mode\" ]");
|
ipc_.subscribe("[ \"mode\" ]");
|
||||||
|
ipc_.signal_event.connect(sigc::mem_fun(*this, &Mode::onEvent));
|
||||||
// Launch worker
|
// Launch worker
|
||||||
worker();
|
worker();
|
||||||
dp.emit();
|
dp.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::sway::Mode::worker() {
|
void Mode::onEvent(const struct Ipc::ipc_response res) {
|
||||||
|
auto parsed = parser_.parse(res.payload);
|
||||||
|
if (parsed["change"] != "default") {
|
||||||
|
mode_ = parsed["change"].asString();
|
||||||
|
} else {
|
||||||
|
mode_.clear();
|
||||||
|
}
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mode::worker() {
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
try {
|
try {
|
||||||
auto res = ipc_.handleEvent();
|
ipc_.handleEvent();
|
||||||
auto parsed = parser_.parse(res.payload);
|
|
||||||
if (parsed["change"] != "default") {
|
|
||||||
mode_ = parsed["change"].asString();
|
|
||||||
} else {
|
|
||||||
mode_.clear();
|
|
||||||
}
|
|
||||||
dp.emit();
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << "Mode: " << e.what() << std::endl;
|
std::cerr << "Mode: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::sway::Mode::update() -> void {
|
auto Mode::update() -> void {
|
||||||
if (mode_.empty()) {
|
if (mode_.empty()) {
|
||||||
event_box_.hide();
|
event_box_.hide();
|
||||||
} else {
|
} else {
|
||||||
|
@ -39,4 +45,6 @@ auto waybar::modules::sway::Mode::update() -> void {
|
||||||
}
|
}
|
||||||
event_box_.show();
|
event_box_.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::sway
|
|
@ -1,7 +1,8 @@
|
||||||
#include "modules/sway/window.hpp"
|
#include "modules/sway/window.hpp"
|
||||||
|
|
||||||
waybar::modules::sway::Window::Window(const std::string& id, const Bar& bar,
|
namespace waybar::modules::sway {
|
||||||
const Json::Value& config)
|
|
||||||
|
Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||||
: ALabel(config, "{}"), bar_(bar), windowId_(-1) {
|
: ALabel(config, "{}"), bar_(bar), windowId_(-1) {
|
||||||
label_.set_name("window");
|
label_.set_name("window");
|
||||||
if (!id.empty()) {
|
if (!id.empty()) {
|
||||||
|
@ -12,45 +13,58 @@ waybar::modules::sway::Window::Window(const std::string& id, const Bar& bar,
|
||||||
label_.set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END);
|
label_.set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END);
|
||||||
}
|
}
|
||||||
ipc_.subscribe("[\"window\",\"workspace\"]");
|
ipc_.subscribe("[\"window\",\"workspace\"]");
|
||||||
|
ipc_.signal_event.connect(sigc::mem_fun(*this, &Window::onEvent));
|
||||||
|
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Window::onCmd));
|
||||||
getFocusedWindow();
|
getFocusedWindow();
|
||||||
// Launch worker
|
// Launch worker
|
||||||
worker();
|
worker();
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::sway::Window::worker() {
|
void Window::onEvent(const struct Ipc::ipc_response res) {
|
||||||
|
auto parsed = parser_.parse(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();
|
||||||
|
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())) {
|
||||||
|
window_.clear();
|
||||||
|
windowId_ = -1;
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::onCmd(const struct Ipc::ipc_response res) {
|
||||||
|
auto parsed = parser_.parse(res.payload);
|
||||||
|
auto [id, name] = getFocusedNode(parsed["nodes"]);
|
||||||
|
windowId_ = id;
|
||||||
|
window_ = name;
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::worker() {
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
try {
|
try {
|
||||||
auto res = ipc_.handleEvent();
|
ipc_.handleEvent();
|
||||||
auto parsed = parser_.parse(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();
|
|
||||||
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())) {
|
|
||||||
window_.clear();
|
|
||||||
windowId_ = -1;
|
|
||||||
dp.emit();
|
|
||||||
}
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << "Window: " << e.what() << std::endl;
|
std::cerr << "Window: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::sway::Window::update() -> void {
|
auto Window::update() -> void {
|
||||||
label_.set_markup(fmt::format(format_, window_));
|
label_.set_markup(fmt::format(format_, window_));
|
||||||
if (tooltipEnabled()) {
|
if (tooltipEnabled()) {
|
||||||
label_.set_tooltip_text(window_);
|
label_.set_tooltip_text(window_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<int, std::string> waybar::modules::sway::Window::getFocusedNode(Json::Value nodes) {
|
std::tuple<int, std::string> Window::getFocusedNode(Json::Value nodes) {
|
||||||
for (auto const& node : nodes) {
|
for (auto const& node : nodes) {
|
||||||
if (node["focused"].asBool() && node["type"] == "con") {
|
if (node["focused"].asBool() && node["type"] == "con") {
|
||||||
return {node["id"].asInt(), node["name"].asString()};
|
return {node["id"].asInt(), node["name"].asString()};
|
||||||
|
@ -63,15 +77,12 @@ std::tuple<int, std::string> waybar::modules::sway::Window::getFocusedNode(Json:
|
||||||
return {-1, std::string()};
|
return {-1, std::string()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::sway::Window::getFocusedWindow() {
|
void Window::getFocusedWindow() {
|
||||||
try {
|
try {
|
||||||
auto res = ipc_.sendCmd(IPC_GET_TREE);
|
ipc_.sendCmd(IPC_GET_TREE);
|
||||||
auto parsed = parser_.parse(res.payload);
|
|
||||||
auto [id, name] = getFocusedNode(parsed["nodes"]);
|
|
||||||
windowId_ = id;
|
|
||||||
window_ = name;
|
|
||||||
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Window::update));
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules::sway
|
|
@ -1,7 +1,8 @@
|
||||||
#include "modules/sway/workspaces.hpp"
|
#include "modules/sway/workspaces.hpp"
|
||||||
|
|
||||||
waybar::modules::sway::Workspaces::Workspaces(const std::string &id, const Bar &bar,
|
namespace waybar::modules::sway {
|
||||||
const Json::Value &config)
|
|
||||||
|
Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value &config)
|
||||||
: bar_(bar),
|
: bar_(bar),
|
||||||
config_(config),
|
config_(config),
|
||||||
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0),
|
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||||
|
@ -11,31 +12,35 @@ waybar::modules::sway::Workspaces::Workspaces(const std::string &id, const Bar &
|
||||||
box_.get_style_context()->add_class(id);
|
box_.get_style_context()->add_class(id);
|
||||||
}
|
}
|
||||||
ipc_.subscribe("[ \"workspace\" ]");
|
ipc_.subscribe("[ \"workspace\" ]");
|
||||||
|
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd));
|
||||||
// Launch worker
|
// Launch worker
|
||||||
worker();
|
worker();
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::sway::Workspaces::worker() {
|
void Workspaces::onCmd(const struct Ipc::ipc_response res) {
|
||||||
|
if (thread_.isRunning()) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
workspaces_ = parser_.parse(res.payload);
|
||||||
|
dp.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Workspaces::worker() {
|
||||||
thread_ = [this] {
|
thread_ = [this] {
|
||||||
try {
|
try {
|
||||||
if (!workspaces_.empty()) {
|
if (!workspaces_.empty()) {
|
||||||
ipc_.handleEvent();
|
ipc_.handleEvent();
|
||||||
}
|
}
|
||||||
{
|
if (thread_.isRunning()) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||||
auto res = ipc_.sendCmd(IPC_GET_WORKSPACES);
|
|
||||||
if (thread_.isRunning()) {
|
|
||||||
workspaces_ = parser_.parse(res.payload);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dp.emit();
|
|
||||||
} 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 waybar::modules::sway::Workspaces::update() -> void {
|
auto Workspaces::update() -> void {
|
||||||
bool needReorder = false;
|
bool needReorder = false;
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
for (auto it = buttons_.begin(); it != buttons_.end();) {
|
for (auto it = buttons_.begin(); it != buttons_.end();) {
|
||||||
|
@ -100,7 +105,7 @@ auto waybar::modules::sway::Workspaces::update() -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::sway::Workspaces::addWorkspace(const Json::Value &node) {
|
void Workspaces::addWorkspace(const Json::Value &node) {
|
||||||
auto icon = getIcon(node["name"].asString(), node);
|
auto icon = getIcon(node["name"].asString(), node);
|
||||||
auto format = config_["format"].isString()
|
auto format = config_["format"].isString()
|
||||||
? fmt::format(config_["format"].asString(),
|
? fmt::format(config_["format"].asString(),
|
||||||
|
@ -117,8 +122,7 @@ void waybar::modules::sway::Workspaces::addWorkspace(const Json::Value &node) {
|
||||||
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 {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
auto cmd = fmt::format("workspace \"{}\"", pair.first->first);
|
||||||
auto cmd = fmt::format("workspace \"{}\"", pair.first->first);
|
|
||||||
ipc_.sendCmd(IPC_COMMAND, cmd);
|
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;
|
||||||
|
@ -142,8 +146,7 @@ void waybar::modules::sway::Workspaces::addWorkspace(const Json::Value &node) {
|
||||||
onButtonReady(node, button);
|
onButtonReady(node, button);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string waybar::modules::sway::Workspaces::getIcon(const std::string &name,
|
std::string Workspaces::getIcon(const std::string &name, const Json::Value &node) {
|
||||||
const Json::Value &node) {
|
|
||||||
std::vector<std::string> keys = {name, "urgent", "focused", "visible", "default"};
|
std::vector<std::string> keys = {name, "urgent", "focused", "visible", "default"};
|
||||||
for (auto const &key : keys) {
|
for (auto const &key : keys) {
|
||||||
if (key == "focused" || key == "visible" || key == "urgent") {
|
if (key == "focused" || key == "visible" || key == "urgent") {
|
||||||
|
@ -157,7 +160,7 @@ std::string waybar::modules::sway::Workspaces::getIcon(const std::string &name,
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool waybar::modules::sway::Workspaces::handleScroll(GdkEventScroll *e) {
|
bool Workspaces::handleScroll(GdkEventScroll *e) {
|
||||||
// Avoid concurrent scroll event
|
// Avoid concurrent scroll event
|
||||||
if (scrolling_) {
|
if (scrolling_) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -199,8 +202,7 @@ bool waybar::modules::sway::Workspaces::handleScroll(GdkEventScroll *e) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string waybar::modules::sway::Workspaces::getCycleWorkspace(uint8_t focused_workspace,
|
const std::string Workspaces::getCycleWorkspace(uint8_t focused_workspace, bool prev) const {
|
||||||
bool prev) const {
|
|
||||||
auto inc = prev ? -1 : 1;
|
auto inc = prev ? -1 : 1;
|
||||||
int size = workspaces_.size();
|
int size = workspaces_.size();
|
||||||
uint8_t idx = 0;
|
uint8_t idx = 0;
|
||||||
|
@ -225,7 +227,7 @@ const std::string waybar::modules::sway::Workspaces::getCycleWorkspace(uint8_t f
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t waybar::modules::sway::Workspaces::getWorkspaceIndex(const std::string &name) const {
|
uint16_t Workspaces::getWorkspaceIndex(const std::string &name) const {
|
||||||
uint16_t idx = 0;
|
uint16_t idx = 0;
|
||||||
for (const auto &workspace : workspaces_) {
|
for (const auto &workspace : workspaces_) {
|
||||||
if (workspace["name"].asString() == name) {
|
if (workspace["name"].asString() == name) {
|
||||||
|
@ -239,7 +241,7 @@ uint16_t waybar::modules::sway::Workspaces::getWorkspaceIndex(const std::string
|
||||||
return workspaces_.size();
|
return workspaces_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string waybar::modules::sway::Workspaces::trimWorkspaceName(std::string name) {
|
std::string Workspaces::trimWorkspaceName(std::string name) {
|
||||||
std::size_t found = name.find(":");
|
std::size_t found = name.find(":");
|
||||||
if (found != std::string::npos) {
|
if (found != std::string::npos) {
|
||||||
return name.substr(found + 1);
|
return name.substr(found + 1);
|
||||||
|
@ -247,8 +249,7 @@ std::string waybar::modules::sway::Workspaces::trimWorkspaceName(std::string nam
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void waybar::modules::sway::Workspaces::onButtonReady(const Json::Value &node,
|
void Workspaces::onButtonReady(const Json::Value &node, Gtk::Button &button) {
|
||||||
Gtk::Button & button) {
|
|
||||||
if (config_["current-only"].asBool()) {
|
if (config_["current-only"].asBool()) {
|
||||||
if (node["focused"].asBool()) {
|
if (node["focused"].asBool()) {
|
||||||
button.show();
|
button.show();
|
||||||
|
@ -260,4 +261,6 @@ void waybar::modules::sway::Workspaces::onButtonReady(const Json::Value &node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
waybar::modules::sway::Workspaces::operator Gtk::Widget &() { return box_; }
|
Workspaces::operator Gtk::Widget &() { return box_; }
|
||||||
|
|
||||||
|
} // namespace waybar::modules::sway
|
Loading…
Reference in New Issue