diff --git a/include/factory.hpp b/include/factory.hpp index 14b976b0..d2e5553b 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -20,6 +20,8 @@ namespace waybar { +class Bar; + class Factory { public: Factory(Bar& bar, const Json::Value& config); diff --git a/include/modules/custom.hpp b/include/modules/custom.hpp index dcab363c..f0553831 100644 --- a/include/modules/custom.hpp +++ b/include/modules/custom.hpp @@ -13,10 +13,12 @@ class Custom : public ALabel { Custom(const std::string, const Json::Value&); auto update() -> void; private: - void worker(); + void delayWorker(); + void continuousWorker(); const std::string name_; waybar::util::SleeperThread thread_; + waybar::util::command::res output_; }; } diff --git a/include/modules/network.hpp b/include/modules/network.hpp index fef64a4c..4e81c998 100644 --- a/include/modules/network.hpp +++ b/include/modules/network.hpp @@ -17,8 +17,8 @@ class Network : public ALabel { ~Network(); auto update() -> void; private: - static uint64_t netlinkRequest(int, void*, uint32_t, uint32_t groups = 0); - static uint64_t netlinkResponse(int, void*, uint32_t, uint32_t groups = 0); + static int netlinkRequest(int, void*, uint32_t, uint32_t groups = 0); + static int netlinkResponse(int, void*, uint32_t, uint32_t groups = 0); static int scanCb(struct nl_msg*, void*); void disconnected(); @@ -33,7 +33,7 @@ class Network : public ALabel { int ifid_; sa_family_t family_; int sock_fd_; - struct sockaddr_nl nladdr_ = {0}; + struct sockaddr_nl nladdr_ = {}; struct nl_sock* sk_ = nullptr; int nl80211_id_; diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp index 81cd0868..d672829f 100644 --- a/include/modules/sway/window.hpp +++ b/include/modules/sway/window.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include "bar.hpp" #include "client.hpp" #include "util/chrono.hpp" @@ -16,7 +17,7 @@ class Window : public ALabel { auto update() -> void; private: void worker(); - std::string getFocusedNode(Json::Value nodes); + std::tuple getFocusedNode(Json::Value nodes); void getFocusedWindow(); Bar& bar_; @@ -24,6 +25,7 @@ class Window : public ALabel { util::JsonParser parser_; Ipc ipc_; std::string window_; + int windowId_; }; } diff --git a/include/modules/sway/workspaces.hpp b/include/modules/sway/workspaces.hpp index 14adeed4..88d4f1ae 100644 --- a/include/modules/sway/workspaces.hpp +++ b/include/modules/sway/workspaces.hpp @@ -18,7 +18,7 @@ class Workspaces : public IModule { private: void worker(); void addWorkspace(Json::Value); - std::string getIcon(std::string); + std::string getIcon(std::string, Json::Value); bool handleScroll(GdkEventScroll*); int getPrevWorkspace(); int getNextWorkspace(); diff --git a/include/util/chrono.hpp b/include/util/chrono.hpp index 39695b4f..828273a4 100644 --- a/include/util/chrono.hpp +++ b/include/util/chrono.hpp @@ -70,7 +70,7 @@ struct SleeperThread { condvar_.notify_all(); } - ~SleeperThread() + auto stop() { do_run_ = false; condvar_.notify_all(); @@ -79,6 +79,11 @@ struct SleeperThread { } } + ~SleeperThread() + { + stop(); + } + private: std::thread thread_; std::condition_variable condvar_; diff --git a/include/util/command.hpp b/include/util/command.hpp index 80773cb5..18069580 100644 --- a/include/util/command.hpp +++ b/include/util/command.hpp @@ -4,12 +4,12 @@ namespace waybar::util::command { -struct cmd_res { +struct res { int exit_code; std::string out; }; -inline struct cmd_res exec(const std::string cmd) +inline struct res exec(const std::string cmd) { FILE* fp(popen(cmd.c_str(), "r")); if (!fp) { diff --git a/meson.build b/meson.build index 640c58e7..20f5ca81 100644 --- a/meson.build +++ b/meson.build @@ -56,7 +56,7 @@ src_files = files( 'src/client.cpp' ) -if find_program('sway').found() +if find_program('sway', required : false).found() add_project_arguments('-DHAVE_SWAY', language: 'cpp') src_files += [ 'src/modules/sway/ipc/client.cpp', diff --git a/preview-2.png b/preview-2.png index 8459ce21..c960d7ff 100644 Binary files a/preview-2.png and b/preview-2.png differ diff --git a/preview.png b/preview.png index f234d95e..6448997a 100644 Binary files a/preview.png and b/preview.png differ diff --git a/resources/config b/resources/config index 42dd753c..de1a99a8 100644 --- a/resources/config +++ b/resources/config @@ -8,17 +8,21 @@ "modules-center": ["sway/window"], "modules-right": ["pulseaudio", "network", "cpu", "memory", "battery", "clock", "tray"], // Modules configuration - "sway/workspaces": { - // "disable-scroll": true, - // "all-outputs": true, - // "format-icons": { - // "1": "", - // "2": "", - // "3": "", - // "4": "", - // "5": "" - // } - }, + // "sway/workspaces": { + // "disable-scroll": true, + // "all-outputs": true, + // "format": "{name}: {icon}", + // "format-icons": { + // "1": "", + // "2": "", + // "3": "", + // "4": "", + // "5": "", + // "urgent": "", + // "focused": "", + // "default": "" + // } + // }, "sway/window": { "max-length": 50 }, @@ -58,6 +62,7 @@ "custom/spotify": { "format": " {}", "max-length": 40, + "interval": 30, // Remove this if your script is endless and write in loop "exec": "$HOME/.config/waybar/mediaplayer.sh", // Script in resources folder "exec-if": "pgrep spotify" } diff --git a/resources/style.css b/resources/style.css index ee9b6a03..a3538d48 100644 --- a/resources/style.css +++ b/resources/style.css @@ -18,10 +18,6 @@ window { border-bottom: 3px solid transparent; } -#workspaces button.icon label { - font-size: 10px; -} - #workspaces button.focused { background: #64727D; border-bottom: 3px solid white; diff --git a/src/ALabel.cpp b/src/ALabel.cpp index 0e6bbee5..2d1ea5e8 100644 --- a/src/ALabel.cpp +++ b/src/ALabel.cpp @@ -24,7 +24,7 @@ auto waybar::ALabel::update() -> void // Nothing here } -bool waybar::ALabel::handleToggle(GdkEventButton* const& ev) +bool waybar::ALabel::handleToggle(GdkEventButton* const& /*ev*/) { alt = !alt; if (alt) { diff --git a/src/factory.cpp b/src/factory.cpp index 0259babe..d3c53f39 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -14,10 +14,10 @@ waybar::IModule* waybar::Factory::makeModule(const std::string &name) const if (name == "sway/workspaces") { return new waybar::modules::sway::Workspaces(bar_, config_[name]); } - #endif if (name == "sway/window") { return new waybar::modules::sway::Window(bar_, config_[name]); } + #endif if (name == "memory") { return new waybar::modules::Memory(config_[name]); } diff --git a/src/main.cpp b/src/main.cpp index 6646e031..85e120ed 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ int main(int argc, char* argv[]) try { waybar::Client c(argc, argv); waybar::client = &c; - std::signal(SIGUSR1, [] (int signal) { + std::signal(SIGUSR1, [] (int /*signal*/) { for (auto& bar : waybar::client->bars) { (*bar).toggle(); } diff --git a/src/modules/cpu.cpp b/src/modules/cpu.cpp index 50f77768..6f826e3e 100644 --- a/src/modules/cpu.cpp +++ b/src/modules/cpu.cpp @@ -13,7 +13,7 @@ waybar::modules::Cpu::Cpu(const Json::Value& config) auto waybar::modules::Cpu::update() -> void { - struct sysinfo info = {0}; + struct sysinfo info = {}; if (sysinfo(&info) == 0) { float f_load = 1.f / (1u << SI_LOAD_SHIFT); uint16_t load = info.loads[0] * f_load * 100 / get_nprocs(); diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index ccb9e4d2..347f51c1 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -7,12 +7,16 @@ waybar::modules::Custom::Custom(const std::string name, if (!config_["exec"]) { throw std::runtime_error(name_ + " has no exec path."); } - worker(); + if (config_["interval"]) { + delayWorker(); + } else { + continuousWorker(); + } } -void waybar::modules::Custom::worker() +void waybar::modules::Custom::delayWorker() { - uint32_t interval = config_["interval"] ? config_["inveral"].asUInt() : 30; + auto interval = config_["interval"].asUInt(); thread_ = [this, interval] { bool can_update = true; if (config_["exec-if"]) { @@ -24,25 +28,53 @@ void waybar::modules::Custom::worker() } } if (can_update) { + output_ = waybar::util::command::exec(config_["exec"].asString()); dp.emit(); } thread_.sleep_for(chrono::seconds(interval)); }; } +void waybar::modules::Custom::continuousWorker() +{ + auto cmd = config_["exec"].asString(); + FILE* fp(popen(cmd.c_str(), "r")); + if (!fp) { + throw std::runtime_error("Unable to open " + cmd); + } + thread_ = [this, fp] { + char* buff = nullptr; + size_t len = 0; + if (getline(&buff, &len, fp) == -1) { + pclose(fp); + thread_.stop(); + output_ = { 1, "" }; + dp.emit(); + return; + } + + std::string output = buff; + + // Remove last newline + if (!output.empty() && output[output.length()-1] == '\n') { + output.erase(output.length()-1); + } + output_ = { 0, output }; + dp.emit(); + }; +} + auto waybar::modules::Custom::update() -> void { - auto res = waybar::util::command::exec(config_["exec"].asString()); - // Hide label if output is empty - if (res.out.empty() || res.exit_code != 0) { + if (output_.out.empty() || output_.exit_code != 0) { label_.hide(); label_.set_name(""); } else { label_.set_name("custom-" + name_); - auto str = fmt::format(format_, res.out); + auto str = fmt::format(format_, output_.out); label_.set_text(str); label_.set_tooltip_text(str); label_.show(); } -} +} \ No newline at end of file diff --git a/src/modules/memory.cpp b/src/modules/memory.cpp index d3d9877f..4c09bdfa 100644 --- a/src/modules/memory.cpp +++ b/src/modules/memory.cpp @@ -13,7 +13,7 @@ waybar::modules::Memory::Memory(const Json::Value& config) auto waybar::modules::Memory::update() -> void { - struct sysinfo info = {0}; + struct sysinfo info = {}; if (sysinfo(&info) == 0) { auto total = info.totalram * info.mem_unit; auto freeram = info.freeram * info.mem_unit; diff --git a/src/modules/network.cpp b/src/modules/network.cpp index 94d5c7a4..1df835e9 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -165,7 +165,7 @@ int waybar::modules::Network::getExternalInterface() * consume responses till NLMSG_DONE/NLMSG_ERROR is encountered). */ do { - uint64_t len = netlinkResponse(sock_fd_, resp, route_buffer_size); + auto len = netlinkResponse(sock_fd_, resp, route_buffer_size); if (len < 0) { goto out; } @@ -255,10 +255,10 @@ out: return ifidx; } -uint64_t waybar::modules::Network::netlinkRequest(int fd, void *req, +int waybar::modules::Network::netlinkRequest(int fd, void *req, uint32_t reqlen, uint32_t groups) { - struct sockaddr_nl sa = {0}; + struct sockaddr_nl sa = {}; sa.nl_family = AF_NETLINK; sa.nl_groups = groups; struct iovec iov = { req, reqlen }; @@ -266,11 +266,11 @@ uint64_t waybar::modules::Network::netlinkRequest(int fd, void *req, return sendmsg(fd, &msg, 0); } -uint64_t waybar::modules::Network::netlinkResponse(int fd, void *resp, +int waybar::modules::Network::netlinkResponse(int fd, void *resp, uint32_t resplen, uint32_t groups) { - uint64_t ret; - struct sockaddr_nl sa = {0}; + int ret; + struct sockaddr_nl sa = {}; sa.nl_family = AF_NETLINK; sa.nl_groups = groups; struct iovec iov = { resp, resplen }; diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index aac2b43c..a2f4469b 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -1,7 +1,7 @@ #include "modules/sway/window.hpp" waybar::modules::sway::Window::Window(Bar &bar, const Json::Value& config) - : ALabel(config, "{}"), bar_(bar) + : ALabel(config, "{}"), bar_(bar), windowId_(-1) { label_.set_name("window"); ipc_.connect(); @@ -20,6 +20,13 @@ void waybar::modules::sway::Window::worker() if ((parsed["change"] == "focus" || parsed["change"] == "title") && parsed["container"]["focused"].asBool()) { window_ = 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()) { + window_.clear(); + windowId_ = -1; dp.emit(); } } catch (const std::exception& e) { @@ -34,18 +41,19 @@ auto waybar::modules::sway::Window::update() -> void label_.set_tooltip_text(window_); } -std::string waybar::modules::sway::Window::getFocusedNode(Json::Value nodes) +std::tuple waybar::modules::sway::Window::getFocusedNode( + Json::Value nodes) { for (auto &node : nodes) { if (node["focused"].asBool() && node["type"] == "con") { - return node["name"].asString(); + return { node["id"].asInt(), node["name"].asString() }; } - auto res = getFocusedNode(node["nodes"]); - if (!res.empty()) { - return res; + auto [id, name] = getFocusedNode(node["nodes"]); + if (id > -1 && !name.empty()) { + return { id, name }; } } - return std::string(); + return { -1, std::string() }; } void waybar::modules::sway::Window::getFocusedWindow() @@ -53,7 +61,9 @@ void waybar::modules::sway::Window::getFocusedWindow() try { auto res = ipc_.sendCmd(IPC_GET_TREE); auto parsed = parser_.parse(res.payload); - window_ = getFocusedNode(parsed["nodes"]); + 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) { std::cerr << e.what() << std::endl; diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index 45be744c..3e74801b 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -78,6 +78,14 @@ auto waybar::modules::sway::Workspaces::update() -> void if (needReorder) { box_.reorder_child(button, node["num"].asInt()); } + auto icon = getIcon(node["name"].asString(), node); + if (config_["format"]) { + auto format = config_["format"].asString(); + button.set_label(fmt::format(format, fmt::arg("icon", icon), + fmt::arg("name", node["name"].asString()))); + } else { + button.set_label(icon); + } button.show(); } } @@ -88,12 +96,13 @@ auto waybar::modules::sway::Workspaces::update() -> void void waybar::modules::sway::Workspaces::addWorkspace(Json::Value node) { - auto icon = getIcon(node["name"].asString()); - auto pair = buttons_.emplace(node["num"].asInt(), icon); + auto icon = getIcon(node["name"].asString(), node); + auto format = config_["format"] + ? fmt::format(config_["format"].asString(), fmt::arg("icon", icon), + fmt::arg("name", node["name"].asString())) + : icon; + auto pair = buttons_.emplace(node["num"].asInt(), format); auto &button = pair.first->second; - if (icon != node["name"].asString()) { - button.get_style_context()->add_class("icon"); - } box_.pack_start(button, false, false, 0); button.set_relief(Gtk::RELIEF_NONE); button.signal_clicked().connect([this, pair] { @@ -123,13 +132,19 @@ void waybar::modules::sway::Workspaces::addWorkspace(Json::Value node) button.show(); } -std::string waybar::modules::sway::Workspaces::getIcon(std::string name) +std::string waybar::modules::sway::Workspaces::getIcon(std::string name, + Json::Value node) { - if (config_["format-icons"][name]) { - return config_["format-icons"][name].asString(); - } - if (config_["format-icons"]["default"]) { - return config_["format-icons"]["default"].asString(); + std::vector keys = { + name, "urgent", "focused", "visible", "default"}; + for (auto const& key : keys) { + if (key == "focused" || key == "visible" || key == "urgent") { + if (config_["format-icons"][key] && node[key].asBool()) { + return config_["format-icons"][key].asString(); + } + } else if (config_["format-icons"][key]) { + return config_["format-icons"][key].asString(); + } } return name; }