From 49232eed8df6fa3384b7fbfb08b566923cce90f8 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 20 Aug 2018 14:50:45 +0200 Subject: [PATCH] Clean (#31) --- include/ALabel.hpp | 4 +- include/IModule.hpp | 3 +- include/bar.hpp | 6 +- include/factory.hpp | 8 +-- include/modules/battery.hpp | 7 ++- include/modules/clock.hpp | 2 +- include/modules/cpu.hpp | 2 +- include/modules/custom.hpp | 6 +- include/modules/memory.hpp | 2 +- include/modules/network.hpp | 2 +- include/modules/pulseaudio.hpp | 2 +- include/modules/sway/ipc/client.hpp | 60 +++++++++++-------- include/modules/sway/ipc/ipc.hpp | 2 +- include/modules/sway/window.hpp | 8 +-- include/modules/sway/workspaces.hpp | 10 ++-- include/util/chrono.hpp | 15 +---- include/util/json.hpp | 19 ++---- src/ALabel.cpp | 4 +- src/bar.cpp | 19 +++--- src/factory.cpp | 24 ++++---- src/modules/battery.cpp | 26 ++++---- src/modules/clock.cpp | 7 +-- src/modules/cpu.cpp | 7 +-- src/modules/custom.cpp | 13 ++-- src/modules/memory.cpp | 7 +-- src/modules/network.cpp | 36 ++++------- src/modules/pulseaudio.cpp | 6 +- src/modules/sway/ipc/client.cpp | 93 ++++++++++++++++++++--------- src/modules/sway/window.cpp | 30 ++++------ src/modules/sway/workspaces.cpp | 66 ++++++++++---------- 30 files changed, 261 insertions(+), 235 deletions(-) diff --git a/include/ALabel.hpp b/include/ALabel.hpp index 991a006..ef94b92 100644 --- a/include/ALabel.hpp +++ b/include/ALabel.hpp @@ -7,13 +7,13 @@ namespace waybar { class ALabel : public IModule { public: - ALabel(Json::Value); + ALabel(const Json::Value&); virtual ~ALabel() = default; virtual auto update() -> void; virtual operator Gtk::Widget &(); protected: Gtk::Label label_; - Json::Value config_; + const Json::Value& config_; }; } diff --git a/include/IModule.hpp b/include/IModule.hpp index d21c44c..4b3aafe 100644 --- a/include/IModule.hpp +++ b/include/IModule.hpp @@ -6,9 +6,10 @@ namespace waybar { class IModule { public: - virtual ~IModule() {} + virtual ~IModule() = default; virtual auto update() -> void = 0; virtual operator Gtk::Widget &() = 0; + Glib::Dispatcher dp; // Hmmm Maybe I should create an abstract class ? }; } diff --git a/include/bar.hpp b/include/bar.hpp index 5f09f6c..a948eac 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -13,12 +13,12 @@ class Factory; class Bar { public: - Bar(Client&, std::unique_ptr&&, uint32_t wl_name); + Bar(const Client&, std::unique_ptr&&, uint32_t); Bar(const Bar&) = delete; auto toggle() -> void; - Client& client; + const Client& client; Gtk::Window window; struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; @@ -43,7 +43,7 @@ class Bar { auto setupConfig() -> void; auto setupWidgets() -> void; auto setupCss() -> void; - void getModules(Factory factory, const std::string& pos); + void getModules(const Factory&, const std::string&); uint32_t width_ = 0; uint32_t height_ = 30; diff --git a/include/factory.hpp b/include/factory.hpp index de12926..7ea8c2c 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -15,11 +15,11 @@ namespace waybar { class Factory { public: - Factory(Bar &bar, Json::Value config); - IModule* makeModule(const std::string &name); + Factory(Bar& bar, const Json::Value& config); + IModule* makeModule(const std::string &name) const; private: - Bar &_bar; - Json::Value _config; + Bar& bar_; + const Json::Value& config_; }; } diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index 22a02a8..da9e758 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -15,13 +15,14 @@ namespace fs = std::filesystem; class Battery : public ALabel { public: - Battery(Json::Value); + Battery(const Json::Value&); ~Battery(); auto update() -> void; private: - std::string getIcon(uint16_t percentage); - static inline const fs::path data_dir_ = "/sys/class/power_supply/"; + + void worker(); + std::string getIcon(uint16_t percentage); util::SleeperThread thread_; std::vector batteries_; diff --git a/include/modules/clock.hpp b/include/modules/clock.hpp index 2634e7b..fba52cd 100644 --- a/include/modules/clock.hpp +++ b/include/modules/clock.hpp @@ -9,7 +9,7 @@ namespace waybar::modules { class Clock : public ALabel { public: - Clock(Json::Value); + Clock(const Json::Value&); auto update() -> void; private: waybar::util::SleeperThread thread_; diff --git a/include/modules/cpu.hpp b/include/modules/cpu.hpp index e9c9fdf..1854346 100644 --- a/include/modules/cpu.hpp +++ b/include/modules/cpu.hpp @@ -9,7 +9,7 @@ namespace waybar::modules { class Cpu : public ALabel { public: - Cpu(Json::Value); + Cpu(const Json::Value&); auto update() -> void; private: waybar::util::SleeperThread thread_; diff --git a/include/modules/custom.hpp b/include/modules/custom.hpp index 79bd760..52cd651 100644 --- a/include/modules/custom.hpp +++ b/include/modules/custom.hpp @@ -10,10 +10,12 @@ namespace waybar::modules { class Custom : public ALabel { public: - Custom(std::string, Json::Value); + Custom(const std::string&, const Json::Value&); auto update() -> void; private: - std::string name_; + void worker(); + + const std::string& name_; waybar::util::SleeperThread thread_; }; diff --git a/include/modules/memory.hpp b/include/modules/memory.hpp index 94bc6fd..7fd984d 100644 --- a/include/modules/memory.hpp +++ b/include/modules/memory.hpp @@ -9,7 +9,7 @@ namespace waybar::modules { class Memory : public ALabel { public: - Memory(Json::Value); + Memory(const Json::Value&); auto update() -> void; private: waybar::util::SleeperThread thread_; diff --git a/include/modules/network.hpp b/include/modules/network.hpp index cd5eb89..fba9152 100644 --- a/include/modules/network.hpp +++ b/include/modules/network.hpp @@ -13,7 +13,7 @@ namespace waybar::modules { class Network : public ALabel { public: - Network(Json::Value); + Network(const Json::Value&); ~Network(); auto update() -> void; private: diff --git a/include/modules/pulseaudio.hpp b/include/modules/pulseaudio.hpp index 17a1907..3e35371 100644 --- a/include/modules/pulseaudio.hpp +++ b/include/modules/pulseaudio.hpp @@ -9,7 +9,7 @@ namespace waybar::modules { class Pulseaudio : public ALabel { public: - Pulseaudio(Json::Value); + Pulseaudio(const Json::Value&); ~Pulseaudio(); auto update() -> void; private: diff --git a/include/modules/sway/ipc/client.hpp b/include/modules/sway/ipc/client.hpp index 231bda6..268ab01 100644 --- a/include/modules/sway/ipc/client.hpp +++ b/include/modules/sway/ipc/client.hpp @@ -1,33 +1,41 @@ #pragma once #include +#include +#include +#include #include "ipc.hpp" -/** - * IPC response including type of IPC response, size of payload and the json - * encoded payload string. - */ -struct ipc_response { - uint32_t size; - uint32_t type; - std::string payload; +namespace waybar::modules::sway { + +class Ipc { + public: + Ipc(); + ~Ipc(); + + struct ipc_response { + uint32_t size; + uint32_t type; + std::string payload; + }; + + void connect(); + struct ipc_response sendCmd(uint32_t type, + const std::string& payload = "") const; + void subscribe(const std::string& payload) const; + struct ipc_response handleEvent() const; + protected: + static inline const std::string ipc_magic_ = "i3-ipc"; + static inline const size_t ipc_header_size_ = ipc_magic_.size() + 8; + + const std::string getSocketPath() const; + int open(const std::string&) const; + struct ipc_response send(int fd, uint32_t type, + const std::string& payload = "") const; + struct ipc_response recv(int fd) const; + + int fd_; + int fd_event_; }; -/** - * Gets the path to the IPC socket from sway. - */ -std::string getSocketPath(void); -/** - * Opens the sway socket. - */ -int ipcOpenSocket(const std::string &socketPath); -/** - * Issues a single IPC command and returns the buffer. len will be updated with - * the length of the buffer returned from sway. - */ -struct ipc_response ipcSingleCommand(int socketfd, uint32_t type, - const std::string& payload); -/** - * Receives a single IPC response and returns an ipc_response. - */ -struct ipc_response ipcRecvResponse(int socketfd); +} diff --git a/include/modules/sway/ipc/ipc.hpp b/include/modules/sway/ipc/ipc.hpp index 45bacbb..ba3439e 100644 --- a/include/modules/sway/ipc/ipc.hpp +++ b/include/modules/sway/ipc/ipc.hpp @@ -1,6 +1,6 @@ #pragma once -#define event_mask(ev) (1 << (ev & 0x7F)) +#define event_mask(ev) (1u << (ev & 0x7F)) enum ipc_command_type { // i3 command types - see i3's I3_REPLY_TYPE constants diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp index 73200e1..81cd086 100644 --- a/include/modules/sway/window.hpp +++ b/include/modules/sway/window.hpp @@ -6,23 +6,23 @@ #include "util/chrono.hpp" #include "util/json.hpp" #include "ALabel.hpp" +#include "modules/sway/ipc/client.hpp" namespace waybar::modules::sway { class Window : public ALabel { public: - Window(waybar::Bar&, Json::Value); - ~Window(); + Window(waybar::Bar&, const Json::Value&); auto update() -> void; private: + void worker(); std::string getFocusedNode(Json::Value nodes); void getFocusedWindow(); Bar& bar_; waybar::util::SleeperThread thread_; util::JsonParser parser_; - int ipcfd_; - int ipc_eventfd_; + Ipc ipc_; std::string window_; }; diff --git a/include/modules/sway/workspaces.hpp b/include/modules/sway/workspaces.hpp index 3f56c58..14adeed 100644 --- a/include/modules/sway/workspaces.hpp +++ b/include/modules/sway/workspaces.hpp @@ -6,16 +6,17 @@ #include "util/chrono.hpp" #include "util/json.hpp" #include "IModule.hpp" +#include "modules/sway/ipc/client.hpp" namespace waybar::modules::sway { class Workspaces : public IModule { public: - Workspaces(waybar::Bar&, Json::Value); - ~Workspaces(); + Workspaces(waybar::Bar&, const Json::Value&); auto update() -> void; operator Gtk::Widget &(); private: + void worker(); void addWorkspace(Json::Value); std::string getIcon(std::string); bool handleScroll(GdkEventScroll*); @@ -23,7 +24,7 @@ class Workspaces : public IModule { int getNextWorkspace(); Bar& bar_; - Json::Value config_; + const Json::Value& config_; waybar::util::SleeperThread thread_; Gtk::Box box_; util::JsonParser parser_; @@ -31,8 +32,7 @@ class Workspaces : public IModule { bool scrolling_; std::unordered_map buttons_; Json::Value workspaces_; - int ipcfd_; - int ipc_eventfd_; + Ipc ipc_; }; } diff --git a/include/util/chrono.hpp b/include/util/chrono.hpp index e12a9a8..e33f9d3 100644 --- a/include/util/chrono.hpp +++ b/include/util/chrono.hpp @@ -70,26 +70,13 @@ struct SleeperThread { condvar_.notify_all(); } - void emit() - { - Glib::signal_idle().connect_once([this] { - sig_update.emit(); - }); - } - ~SleeperThread() { do_run_ = false; condvar_.notify_all(); - auto native_handle = thread_.native_handle(); - pthread_cancel(native_handle); - if (thread_.joinable()) { - thread_.join(); - } + thread_.detach(); } - sigc::signal sig_update; - private: std::thread thread_; std::condition_variable condvar_; diff --git a/include/util/json.hpp b/include/util/json.hpp index 2930644..279936f 100644 --- a/include/util/json.hpp +++ b/include/util/json.hpp @@ -7,32 +7,25 @@ namespace waybar::util { struct JsonParser { JsonParser() - : _reader(_builder.newCharReader()) + : reader_(builder_.newCharReader()) {} - Json::Value parse(const std::string data) + const Json::Value parse(const std::string data) const { Json::Value root; std::string err; - if (_reader == nullptr) { - throw std::runtime_error("Unable to parse"); - } bool res = - _reader->parse(data.c_str(), data.c_str() + data.size(), &root, &err); + reader_->parse(data.c_str(), data.c_str() + data.size(), &root, &err); if (!res) throw std::runtime_error(err); return root; } - ~JsonParser() - { - delete _reader; - _reader = nullptr; - } + ~JsonParser() = default; private: - Json::CharReaderBuilder _builder; - Json::CharReader *_reader; + Json::CharReaderBuilder builder_; + std::unique_ptr const reader_; }; } diff --git a/src/ALabel.cpp b/src/ALabel.cpp index 1f72136..cd66b7b 100644 --- a/src/ALabel.cpp +++ b/src/ALabel.cpp @@ -1,7 +1,7 @@ #include "ALabel.hpp" -waybar::ALabel::ALabel(Json::Value config) - : config_(std::move(config)) +waybar::ALabel::ALabel(const Json::Value& config) + : config_(config) { if (config_["max-length"]) { label_.set_max_width_chars(config_["max-length"].asUInt()); diff --git a/src/bar.cpp b/src/bar.cpp index 03f1bbd..750816c 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -3,10 +3,11 @@ #include "factory.hpp" #include "util/json.hpp" -waybar::Bar::Bar(Client &client, +waybar::Bar::Bar(const Client& client, std::unique_ptr &&p_output, uint32_t p_wl_name) : client(client), window{Gtk::WindowType::WINDOW_TOPLEVEL}, - output(std::move(p_output)), wl_name(std::move(p_wl_name)) + surface(nullptr), layer_surface(nullptr), + output(std::move(p_output)), wl_name(p_wl_name) { static const struct zxdg_output_v1_listener xdgOutputListener = { .logical_position = handleLogicalPosition, @@ -135,13 +136,13 @@ auto waybar::Bar::toggle() -> void auto waybar::Bar::setupConfig() -> void { - util::JsonParser parser; std::ifstream file(client.config_file); if (!file.is_open()) { throw std::runtime_error("Can't open config file"); } std::string str((std::istreambuf_iterator(file)), std::istreambuf_iterator()); + util::JsonParser parser; config_ = parser.parse(str); } @@ -150,7 +151,7 @@ auto waybar::Bar::setupCss() -> void css_provider_ = Gtk::CssProvider::create(); style_context_ = Gtk::StyleContext::create(); - // load our css file, wherever that may be hiding + // Load our css file, wherever that may be hiding if (css_provider_->load_from_path(client.css_file)) { Glib::RefPtr screen = window.get_screen(); style_context_->add_provider_for_screen(screen, css_provider_, @@ -158,20 +159,22 @@ auto waybar::Bar::setupCss() -> void } } -void waybar::Bar::getModules(Factory factory, const std::string& pos) +void waybar::Bar::getModules(const Factory& factory, const std::string& pos) { if (config_[pos]) { for (const auto &name : config_[pos]) { try { + auto module = factory.makeModule(name.asString()); if (pos == "modules-left") { - modules_left_.emplace_back(factory.makeModule(name.asString())); + modules_left_.emplace_back(module); } if (pos == "modules-center") { - modules_center_.emplace_back(factory.makeModule(name.asString())); + modules_center_.emplace_back(module); } if (pos == "modules-right") { - modules_right_.emplace_back(factory.makeModule(name.asString())); + modules_right_.emplace_back(module); } + module->dp.connect([module] { module->update(); }); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } diff --git a/src/factory.cpp b/src/factory.cpp index 98b1fd2..1a190f2 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -1,38 +1,38 @@ #include "factory.hpp" -waybar::Factory::Factory(Bar &bar, Json::Value config) - : _bar(bar), _config(std::move(config)) +waybar::Factory::Factory(Bar& bar, const Json::Value& config) + : bar_(bar), config_(config) {} -waybar::IModule* waybar::Factory::makeModule(const std::string &name) +waybar::IModule* waybar::Factory::makeModule(const std::string &name) const { try { if (name == "battery") { - return new waybar::modules::Battery(_config[name]); + return new waybar::modules::Battery(config_[name]); } if (name == "sway/workspaces") { - return new waybar::modules::sway::Workspaces(_bar, _config[name]); + return new waybar::modules::sway::Workspaces(bar_, config_[name]); } if (name == "sway/window") { - return new waybar::modules::sway::Window(_bar, _config[name]); + return new waybar::modules::sway::Window(bar_, config_[name]); } if (name == "memory") { - return new waybar::modules::Memory(_config[name]); + return new waybar::modules::Memory(config_[name]); } if (name == "cpu") { - return new waybar::modules::Cpu(_config[name]); + return new waybar::modules::Cpu(config_[name]); } if (name == "clock") { - return new waybar::modules::Clock(_config[name]); + return new waybar::modules::Clock(config_[name]); } if (name == "network") { - return new waybar::modules::Network(_config[name]); + return new waybar::modules::Network(config_[name]); } if (name == "pulseaudio") { - return new waybar::modules::Pulseaudio(_config[name]); + return new waybar::modules::Pulseaudio(config_[name]); } if (name.compare(0, 7, "custom/") == 0 && name.size() > 7) { - return new waybar::modules::Custom(name.substr(7), _config[name]); + return new waybar::modules::Custom(name.substr(7), config_[name]); } } catch (const std::exception& e) { auto err = fmt::format("Disabling module \"{}\", {}", name, e.what()); diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 715af3f..5372665 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -1,7 +1,7 @@ #include "modules/battery.hpp" -waybar::modules::Battery::Battery(Json::Value config) - : ALabel(std::move(config)) +waybar::modules::Battery::Battery(const Json::Value& config) + : ALabel(config) { try { for (auto &node : fs::directory_iterator(data_dir_)) { @@ -23,25 +23,29 @@ waybar::modules::Battery::Battery(Json::Value config) for (auto &bat : batteries_) { inotify_add_watch(fd_, (bat / "uevent").c_str(), IN_ACCESS); } - // Trigger first values - update(); label_.set_name("battery"); - thread_.sig_update.connect(sigc::mem_fun(*this, &Battery::update)); + worker(); +} + +waybar::modules::Battery::~Battery() +{ + close(fd_); +} + +void waybar::modules::Battery::worker() +{ + // Trigger first values + dp.emit(); thread_ = [this] { struct inotify_event event = {0}; int nbytes = read(fd_, &event, sizeof(event)); if (nbytes != sizeof(event)) { return; } - thread_.emit(); + dp.emit(); }; } -waybar::modules::Battery::~Battery() -{ - close(fd_); -} - auto waybar::modules::Battery::update() -> void { try { diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 3fd3b58..0fa79f4 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -1,14 +1,13 @@ #include "modules/clock.hpp" -waybar::modules::Clock::Clock(Json::Value config) - : ALabel(std::move(config)) +waybar::modules::Clock::Clock(const Json::Value& config) + : ALabel(config) { label_.set_name("clock"); uint32_t interval = config_["interval"] ? config_["inveral"].asUInt() : 60; - thread_.sig_update.connect(sigc::mem_fun(*this, &Clock::update)); thread_ = [this, interval] { auto now = waybar::chrono::clock::now(); - thread_.emit(); + dp.emit(); auto timeout = std::chrono::floor(now + std::chrono::seconds(interval)); thread_.sleep_until(timeout); diff --git a/src/modules/cpu.cpp b/src/modules/cpu.cpp index 6c9e485..20c6e15 100644 --- a/src/modules/cpu.cpp +++ b/src/modules/cpu.cpp @@ -1,13 +1,12 @@ #include "modules/cpu.hpp" -waybar::modules::Cpu::Cpu(Json::Value config) - : ALabel(std::move(config)) +waybar::modules::Cpu::Cpu(const Json::Value& config) + : ALabel(config) { label_.set_name("cpu"); uint32_t interval = config_["interval"] ? config_["inveral"].asUInt() : 10; - thread_.sig_update.connect(sigc::mem_fun(*this, &Cpu::update)); thread_ = [this, interval] { - thread_.emit(); + dp.emit(); thread_.sleep_for(chrono::seconds(interval)); }; } diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index 19c6bea..1067034 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -1,11 +1,17 @@ #include "modules/custom.hpp" -waybar::modules::Custom::Custom(std::string name, Json::Value config) - : ALabel(std::move(config)), name_(std::move(name)) +waybar::modules::Custom::Custom(const std::string& name, + const Json::Value& config) + : ALabel(config), name_(name) { if (!config_["exec"]) { throw std::runtime_error(name_ + " has no exec path."); } + worker(); +} + +void waybar::modules::Custom::worker() +{ uint32_t interval = config_["interval"] ? config_["inveral"].asUInt() : 30; thread_ = [this, interval] { bool can_update = true; @@ -16,11 +22,10 @@ waybar::modules::Custom::Custom(std::string name, Json::Value config) } } if (can_update) { - thread_.emit(); + dp.emit(); } thread_.sleep_for(chrono::seconds(interval)); }; - thread_.sig_update.connect(sigc::mem_fun(*this, &Custom::update)); } auto waybar::modules::Custom::update() -> void diff --git a/src/modules/memory.cpp b/src/modules/memory.cpp index 668ebf4..135457b 100644 --- a/src/modules/memory.cpp +++ b/src/modules/memory.cpp @@ -1,13 +1,12 @@ #include "modules/memory.hpp" -waybar::modules::Memory::Memory(Json::Value config) - : ALabel(std::move(config)) +waybar::modules::Memory::Memory(const Json::Value& config) + : ALabel(config) { label_.set_name("memory"); uint32_t interval = config_["interval"] ? config_["inveral"].asUInt() : 30; - thread_.sig_update.connect(sigc::mem_fun(*this, &Memory::update)); thread_ = [this, interval] { - thread_.emit(); + dp.emit(); thread_.sleep_for(chrono::seconds(interval)); }; } diff --git a/src/modules/network.cpp b/src/modules/network.cpp index b37ec29..d698092 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -1,7 +1,7 @@ #include "modules/network.hpp" -waybar::modules::Network::Network(Json::Value config) - : ALabel(std::move(config)), family_(AF_INET), +waybar::modules::Network::Network(const Json::Value& config) + : ALabel(config), family_(AF_INET), signal_strength_dbm_(0), signal_strength_(0) { sock_fd_ = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); @@ -31,8 +31,7 @@ waybar::modules::Network::Network(Json::Value config) label_.set_name("network"); // Trigger first values getInfo(); - update(); - thread_.sig_update.connect(sigc::mem_fun(*this, &Network::update)); + dp.emit(); thread_ = [this] { char buf[4096]; uint64_t len = netlinkResponse(sock_fd_, buf, sizeof(buf), @@ -69,7 +68,7 @@ waybar::modules::Network::Network(Json::Value config) } if (need_update) { getInfo(); - thread_.emit(); + dp.emit(); } }; } @@ -116,20 +115,18 @@ void waybar::modules::Network::disconnected() // Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698 int waybar::modules::Network::getExternalInterface() { + static const uint32_t route_buffer_size = 8192; struct nlmsghdr *hdr = nullptr; struct rtmsg *rt = nullptr; - void *resp = nullptr; + char resp[route_buffer_size] = {0}; int ifidx = -1; - /* Allocate space for the request. */ + /* Prepare request. */ uint32_t reqlen = NLMSG_SPACE(sizeof(*rt)); - void *req = nullptr; - if ((req = calloc(1, reqlen)) == nullptr) { - goto out; /* ENOBUFS */ - } + char req[reqlen] = {0}; /* Build the RTM_GETROUTE request. */ - hdr = static_cast(req); + hdr = reinterpret_cast(req); hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*rt)); hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; hdr->nlmsg_type = RTM_GETROUTE; @@ -142,12 +139,6 @@ int waybar::modules::Network::getExternalInterface() goto out; } - /* Allocate space for the response. */ - static const uint32_t route_buffer_size = 8192; - if ((resp = calloc(1, route_buffer_size)) == nullptr) { - goto out; /* ENOBUFS */ - } - /* Read the response(s). * * WARNING: All the packets generated by the request must be consumed (as in, @@ -160,7 +151,7 @@ int waybar::modules::Network::getExternalInterface() } /* Parse the response payload into netlink messages. */ - for (hdr = static_cast(resp); NLMSG_OK(hdr, len); + for (hdr = reinterpret_cast(resp); NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) { if (hdr->nlmsg_type == NLMSG_DONE) { goto out; @@ -241,10 +232,6 @@ int waybar::modules::Network::getExternalInterface() } while (true); out: - if (req != nullptr) - free(req); - if (resp != nullptr) - free(resp); return ifidx; } @@ -269,8 +256,9 @@ uint64_t waybar::modules::Network::netlinkResponse(int fd, void *resp, struct iovec iov = { resp, resplen }; struct msghdr msg = { &sa, sizeof(sa), &iov, 1, nullptr, 0, 0 }; ret = recvmsg(fd, &msg, 0); - if (msg.msg_flags & MSG_TRUNC) + if (msg.msg_flags & MSG_TRUNC) { return -1; + } return ret; } diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index a857120..fb3925a 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -1,7 +1,7 @@ #include "modules/pulseaudio.hpp" -waybar::modules::Pulseaudio::Pulseaudio(Json::Value config) - : ALabel(std::move(config)), mainloop_(nullptr), mainloop_api_(nullptr), +waybar::modules::Pulseaudio::Pulseaudio(const Json::Value& config) + : ALabel(config), mainloop_(nullptr), mainloop_api_(nullptr), context_(nullptr), sink_idx_(0), volume_(0), muted_(false) { label_.set_name("pulseaudio"); @@ -89,7 +89,7 @@ void waybar::modules::Pulseaudio::sinkInfoCb(pa_context* /*context*/, pa->volume_ = volume * 100.0f; pa->muted_ = i->mute != 0; pa->desc_ = i->description; - Glib::signal_idle().connect_once(sigc::mem_fun(*pa, &Pulseaudio::update)); + pa->dp.emit(); } } diff --git a/src/modules/sway/ipc/client.cpp b/src/modules/sway/ipc/client.cpp index 60b61db..da26b56 100644 --- a/src/modules/sway/ipc/client.cpp +++ b/src/modules/sway/ipc/client.cpp @@ -1,14 +1,17 @@ -#define _POSIX_C_SOURCE 200809L #include "modules/sway/ipc/client.hpp" -#include -#include -#include -#include -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(&addr), l) == -1) { + if (::connect(fd, reinterpret_cast(&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(header.data() + ipc_magic.size()); + header.reserve(ipc_header_size_); + auto data32 = reinterpret_cast(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(header.data() + ipc_magic.size()); - memcpy(header.data(), ipc_magic.c_str(), ipc_magic.size()); + header.reserve(ipc_header_size_); + auto data32 = reinterpret_cast(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_); +} \ No newline at end of file diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index a2e3e4a..306103c 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -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)); diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index 3e004f9..45be744 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -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 lock(mutex_); - auto res = ipcSingleCommand(ipcfd_, IPC_GET_WORKSPACES, ""); - workspaces_ = parser_.parse(res.payload); - thread_.emit(); + { + std::lock_guard 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 lock(mutex_); bool needReorder = false; + std::lock_guard 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 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 lock(mutex_); - for (; idx < workspaces_.size(); idx += 1) { - if (workspaces_[idx]["focused"].asBool()) { - id = workspaces_[idx]["num"].asInt(); - break; + { + std::lock_guard 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 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; }