diff --git a/include/bar.hpp b/include/bar.hpp index e4b2179b..5f09f6c4 100644 --- a/include/bar.hpp +++ b/include/bar.hpp @@ -4,17 +4,18 @@ #include #include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h" +#include "IModule.hpp" namespace waybar { class Client; +class Factory; class Bar { public: - Bar(Client&, std::unique_ptr&&); + Bar(Client&, std::unique_ptr&&, uint32_t wl_name); Bar(const Bar&) = delete; - auto setWidth(uint32_t) -> void; auto toggle() -> void; Client& client; @@ -22,7 +23,8 @@ class Bar { struct wl_surface *surface; struct zwlr_layer_surface_v1 *layer_surface; std::unique_ptr output; - std::string outputName; + std::string output_name; + uint32_t wl_name; bool visible = true; private: static void handleLogicalPosition(void *, struct zxdg_output_v1 *, int32_t, @@ -41,6 +43,7 @@ class Bar { auto setupConfig() -> void; auto setupWidgets() -> void; auto setupCss() -> void; + void getModules(Factory factory, const std::string& pos); uint32_t width_ = 0; uint32_t height_ = 30; @@ -48,6 +51,9 @@ class Bar { Glib::RefPtr style_context_; Glib::RefPtr css_provider_; struct zxdg_output_v1 *xdg_output_; + std::vector> modules_left_; + std::vector> modules_center_; + std::vector> modules_right_; }; } diff --git a/include/client.hpp b/include/client.hpp index 8db4c687..d4374dcd 100644 --- a/include/client.hpp +++ b/include/client.hpp @@ -19,7 +19,7 @@ class Client { Client(int argc, char *argv[]); int main(int argc, char *argv[]); - Gtk::Main gtk_main; + Glib::RefPtr gtk_app; std::string css_file; std::string config_file; Glib::RefPtr gdk_display; diff --git a/include/factory.hpp b/include/factory.hpp index 07f83d3d..de129266 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -16,7 +16,7 @@ namespace waybar { class Factory { public: Factory(Bar &bar, Json::Value config); - IModule *makeModule(const std::string &name); + IModule* makeModule(const std::string &name); private: Bar &_bar; Json::Value _config; diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index e5662a3d..22a02a86 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -16,6 +16,7 @@ namespace fs = std::filesystem; class Battery : public ALabel { public: Battery(Json::Value); + ~Battery(); auto update() -> void; private: std::string getIcon(uint16_t percentage); @@ -24,6 +25,7 @@ class Battery : public ALabel { util::SleeperThread thread_; std::vector batteries_; + int fd_; }; } diff --git a/include/modules/network.hpp b/include/modules/network.hpp index cbed9298..cd5eb89a 100644 --- a/include/modules/network.hpp +++ b/include/modules/network.hpp @@ -14,6 +14,7 @@ namespace waybar::modules { class Network : public ALabel { public: Network(Json::Value); + ~Network(); auto update() -> void; private: static uint64_t netlinkRequest(int, void*, uint32_t, uint32_t groups = 0); diff --git a/include/modules/pulseaudio.hpp b/include/modules/pulseaudio.hpp index 65d4e0d5..17a1907b 100644 --- a/include/modules/pulseaudio.hpp +++ b/include/modules/pulseaudio.hpp @@ -10,6 +10,7 @@ namespace waybar::modules { class Pulseaudio : public ALabel { public: Pulseaudio(Json::Value); + ~Pulseaudio(); auto update() -> void; private: static void subscribeCb(pa_context*, pa_subscription_event_type_t, diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp index 3a89825d..73200e1b 100644 --- a/include/modules/sway/window.hpp +++ b/include/modules/sway/window.hpp @@ -12,6 +12,7 @@ namespace waybar::modules::sway { class Window : public ALabel { public: Window(waybar::Bar&, Json::Value); + ~Window(); auto update() -> void; private: std::string getFocusedNode(Json::Value nodes); diff --git a/include/modules/sway/workspaces.hpp b/include/modules/sway/workspaces.hpp index 1fe33585..3f56c581 100644 --- a/include/modules/sway/workspaces.hpp +++ b/include/modules/sway/workspaces.hpp @@ -12,6 +12,7 @@ namespace waybar::modules::sway { class Workspaces : public IModule { public: Workspaces(waybar::Bar&, Json::Value); + ~Workspaces(); auto update() -> void; operator Gtk::Widget &(); private: diff --git a/include/util/chrono.hpp b/include/util/chrono.hpp index 09ac5b27..a361d64c 100644 --- a/include/util/chrono.hpp +++ b/include/util/chrono.hpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace waybar::chrono { @@ -14,18 +15,6 @@ using clock = std::chrono::system_clock; using duration = clock::duration; using time_point = std::chrono::time_point; -inline struct timespec to_timespec(time_point t) noexcept -{ - long secs = duration_cast(t.time_since_epoch()).count(); - long nsc = duration_cast(t.time_since_epoch() % seconds(1)).count(); - return {secs, nsc}; -} - -inline time_point to_time_point(struct timespec t) noexcept -{ - return time_point(duration_cast(seconds(t.tv_sec) + nanoseconds(t.tv_nsec))); -} - } namespace waybar::util { @@ -34,59 +23,71 @@ struct SleeperThread { SleeperThread() = default; SleeperThread(std::function func) - : thread{[this, func] { - do { + : thread_{[this, func] { + while(true) { + { + std::lock_guard lock(mutex_); + if (!do_run_) { + break; + } + } func(); - } while (do_run); + } }} - { - defined = true; - } + {} SleeperThread& operator=(std::function func) { - thread = std::thread([this, func] { - do { + thread_ = std::thread([this, func] { + while(true) { + { + std::lock_guard lock(mutex_); + if (!do_run_) { + break; + } + } func(); - } while (do_run); + } }); - defined = true; return *this; } auto sleep_for(chrono::duration dur) { - auto lock = std::unique_lock(mutex); - return condvar.wait_for(lock, dur); + auto lock = std::unique_lock(mutex_); + return condvar_.wait_for(lock, dur); } auto sleep_until(chrono::time_point time) { - auto lock = std::unique_lock(mutex); - return condvar.wait_until(lock, time); + auto lock = std::unique_lock(mutex_); + return condvar_.wait_until(lock, time); } auto wake_up() { - condvar.notify_all(); + condvar_.notify_all(); } ~SleeperThread() { - do_run = false; - if (defined) { - condvar.notify_all(); - thread.join(); + do_run_ = false; + condvar_.notify_all(); + auto native_handle = thread_.native_handle(); + pthread_cancel(native_handle); + if (thread_.joinable()) { + thread_.join(); } } + sigc::signal sig_update; + private: - std::thread thread; - std::condition_variable condvar; - std::mutex mutex; - bool defined = false; - bool do_run = true; + std::thread thread_; + std::condition_variable condvar_; + std::mutex mutex_; + bool do_run_ = true; }; } diff --git a/include/util/json.hpp b/include/util/json.hpp index 6c2db959..2930644d 100644 --- a/include/util/json.hpp +++ b/include/util/json.hpp @@ -14,6 +14,9 @@ struct JsonParser { { 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); if (!res) @@ -24,6 +27,7 @@ struct JsonParser { ~JsonParser() { delete _reader; + _reader = nullptr; } private: diff --git a/meson.build b/meson.build index 136b48d9..950c6b1b 100644 --- a/meson.build +++ b/meson.build @@ -6,7 +6,7 @@ project( ) cpp_args = [] -cpp_link_args = [] +cpp_link_args = ['-g'] if false # libc++ cpp_args += ['-stdlib=libc++'] diff --git a/src/bar.cpp b/src/bar.cpp index a9ff0bc7..03f1bbd1 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -3,9 +3,10 @@ #include "factory.hpp" #include "util/json.hpp" -waybar::Bar::Bar(Client &client, std::unique_ptr &&p_output) +waybar::Bar::Bar(Client &client, + std::unique_ptr &&p_output, uint32_t p_wl_name) : client(client), window{Gtk::WindowType::WINDOW_TOPLEVEL}, - output(std::move(p_output)) + output(std::move(p_output)), wl_name(std::move(p_wl_name)) { static const struct zxdg_output_v1_listener xdgOutputListener = { .logical_position = handleLogicalPosition, @@ -22,29 +23,39 @@ waybar::Bar::Bar(Client &client, std::unique_ptr &&p_output) setupConfig(); setupCss(); setupWidgets(); - if (config_["height"]) { - height_ = config_["height"].asUInt(); - } + Gtk::Widget& wrap(window); gtk_widget_realize(wrap.gobj()); GdkWindow *gdk_window = gtk_widget_get_window(wrap.gobj()); gdk_wayland_window_set_use_custom_surface(gdk_window); surface = gdk_wayland_window_get_wl_surface(gdk_window); + std::size_t layer_top = config_["layer"] == "top" ? ZWLR_LAYER_SHELL_V1_LAYER_TOP : ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM; layer_surface = zwlr_layer_shell_v1_get_layer_surface( client.layer_shell, surface, *output, layer_top, "waybar"); - std::size_t position_bottom = config_["position"] == "bottom" - ? ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM : ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; - zwlr_layer_surface_v1_set_anchor(layer_surface, position_bottom - | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT); - zwlr_layer_surface_v1_set_size(layer_surface, width_, height_); + static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { .configure = layerSurfaceHandleConfigure, .closed = layerSurfaceHandleClosed, }; zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, this); + + std::size_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT + | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + if (config_["position"] == "bottom") { + anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM; + } else { + anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP; + } + + auto height = config_["height"] ? config_["height"].asUInt() : height_; + auto width = config_["width"] ? config_["width"].asUInt() : width_; + zwlr_layer_surface_v1_set_anchor(layer_surface, anchor); + zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, height); + zwlr_layer_surface_v1_set_size(layer_surface, width, height); + wl_surface_commit(surface); } @@ -71,7 +82,7 @@ void waybar::Bar::handleName(void* data, struct zxdg_output_v1* /*xdg_output*/, const char* name) { auto o = static_cast(data); - o->outputName = name; + o->output_name = name; } void waybar::Bar::handleDescription(void* /*data*/, @@ -86,13 +97,17 @@ void waybar::Bar::layerSurfaceHandleConfigure(void* data, { auto o = static_cast(data); o->window.show_all(); - o->setWidth(o->config_["width"] ? o->config_["width"].asUInt() : width); zwlr_layer_surface_v1_ack_configure(surface, serial); - if (o->height_ != height) { - height = o->height_; - std::cout << fmt::format("New Height: {}", height) << std::endl; - zwlr_layer_surface_v1_set_size(surface, o->width_, height); - zwlr_layer_surface_v1_set_exclusive_zone(surface, o->visible ? height : 0); + if (width != o->width_ || height != o->height_) { + o->width_ = width; + o->height_ = height; + std::cout << fmt::format( + "Bar configured (width: {}, height: {}) for output: {}", + o->width_, o->height_, o->output_name) << std::endl; + o->window.set_size_request(o->width_, o->height_); + o->window.resize(o->width_, o->height_); + zwlr_layer_surface_v1_set_exclusive_zone(surface, o->height_); + zwlr_layer_surface_v1_set_size(surface, o->width_, o->height_); wl_surface_commit(o->surface); } } @@ -101,24 +116,13 @@ void waybar::Bar::layerSurfaceHandleClosed(void* data, struct zwlr_layer_surface_v1* /*surface*/) { auto o = static_cast(data); + std::cout << "Bar removed from output: " + o->output_name << std::endl; zwlr_layer_surface_v1_destroy(o->layer_surface); - o->layer_surface = nullptr; - wl_surface_destroy(o->surface); - o->surface = nullptr; - o->window.close(); -} - -auto waybar::Bar::setWidth(uint32_t width) -> void -{ - if (width == width_) { - return; - } - std::cout << fmt::format("Bar width configured: {}", width) << std::endl; - width_ = width; - window.set_size_request(width); - window.resize(width, height_); - zwlr_layer_surface_v1_set_size(layer_surface, width, height_ + 1); - wl_surface_commit(surface); + wl_output_destroy(*o->output); + zxdg_output_v1_destroy(o->xdg_output_); + o->modules_left_.clear(); + o->modules_center_.clear(); + o->modules_right_.clear(); } auto waybar::Bar::toggle() -> void @@ -154,6 +158,27 @@ auto waybar::Bar::setupCss() -> void } } +void waybar::Bar::getModules(Factory factory, const std::string& pos) +{ + if (config_[pos]) { + for (const auto &name : config_[pos]) { + try { + if (pos == "modules-left") { + modules_left_.emplace_back(factory.makeModule(name.asString())); + } + if (pos == "modules-center") { + modules_center_.emplace_back(factory.makeModule(name.asString())); + } + if (pos == "modules-right") { + modules_right_.emplace_back(factory.makeModule(name.asString())); + } + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + } + } + } +} + auto waybar::Bar::setupWidgets() -> void { auto &left = *Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 0)); @@ -167,30 +192,17 @@ auto waybar::Bar::setupWidgets() -> void box.pack_end(right, true, true); Factory factory(*this, config_); - - if (config_["modules-left"]) { - for (const auto &name : config_["modules-left"]) { - auto module = factory.makeModule(name.asString()); - if (module != nullptr) { - left.pack_start(*module, false, true, 0); - } - } + getModules(factory, "modules-left"); + getModules(factory, "modules-center"); + getModules(factory, "modules-right"); + for (auto& module : modules_left_) { + left.pack_start(*module, false, true, 0); } - if (config_["modules-center"]) { - for (const auto &name : config_["modules-center"]) { - auto module = factory.makeModule(name.asString()); - if (module != nullptr) { - center.pack_start(*module, true, false, 0); - } - } + for (auto& module : modules_center_) { + center.pack_start(*module, true, true, 0); } - if (config_["modules-right"]) { - std::reverse(config_["modules-right"].begin(), config_["modules-right"].end()); - for (const auto &name : config_["modules-right"]) { - auto module = factory.makeModule(name.asString()); - if (module != nullptr) { - right.pack_end(*module, false, false, 0); - } - } + std::reverse(modules_right_.begin(), modules_right_.end()); + for (auto& module : modules_right_) { + right.pack_end(*module, false, false, 0); } } diff --git a/src/client.cpp b/src/client.cpp index 022e3195..611c7868 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1,7 +1,8 @@ #include "client.hpp" waybar::Client::Client(int argc, char* argv[]) - : gtk_main(argc, argv), gdk_display(Gdk::Display::get_default()), + : gtk_app(Gtk::Application::create(argc, argv, "org.alexays.waybar")), + gdk_display(Gdk::Display::get_default()), wl_display(gdk_wayland_display_get_wl_display(gdk_display->gobj())) { auto getFirstValidPath = [] (std::vector possiblePaths) { @@ -48,7 +49,7 @@ void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, *output = static_cast(wl_registry_bind(registry, name, &wl_output_interface, version)); if (o->xdg_output_manager != nullptr) { - o->bars.emplace_back(std::make_unique(*o, std::move(output))); + o->bars.emplace_back(std::make_unique(*o, std::move(output), name)); } } else if (strcmp(interface, wl_seat_interface.name) == 0) { o->seat = static_cast(wl_registry_bind(registry, name, @@ -61,10 +62,16 @@ void waybar::Client::handleGlobal(void *data, struct wl_registry *registry, } } -void waybar::Client::handleGlobalRemove(void* /*data*/, - struct wl_registry* /*registry*/, uint32_t /*name*/) +void waybar::Client::handleGlobalRemove(void* data, + struct wl_registry* /*registry*/, uint32_t name) { - // TODO(someone) + auto o = static_cast(data); + for (auto it = o->bars.begin(); it != o->bars.end(); ++it) { + if ((**it).wl_name == name) { + o->bars.erase(it); + break; + } + } } void waybar::Client::bindInterfaces() @@ -81,7 +88,8 @@ void waybar::Client::bindInterfaces() int waybar::Client::main(int /*argc*/, char* /*argv*/[]) { bindInterfaces(); - Gtk::Main::run(); + gtk_app->hold(); + gtk_app->run(); bars.clear(); zxdg_output_manager_v1_destroy(xdg_output_manager); zwlr_layer_shell_v1_destroy(layer_shell); diff --git a/src/factory.cpp b/src/factory.cpp index 840a1871..98b1fd2b 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -4,7 +4,7 @@ waybar::Factory::Factory(Bar &bar, Json::Value config) : _bar(bar), _config(std::move(config)) {} -waybar::IModule *waybar::Factory::makeModule(const std::string &name) +waybar::IModule* waybar::Factory::makeModule(const std::string &name) { try { if (name == "battery") { @@ -34,13 +34,12 @@ waybar::IModule *waybar::Factory::makeModule(const std::string &name) if (name.compare(0, 7, "custom/") == 0 && name.size() > 7) { return new waybar::modules::Custom(name.substr(7), _config[name]); } - std::cerr << "Unknown module: " + name << std::endl; } catch (const std::exception& e) { auto err = fmt::format("Disabling module \"{}\", {}", name, e.what()); - std::cerr << err << std::endl; + throw std::runtime_error(err); } catch (...) { auto err = fmt::format("Disabling module \"{}\", Unknown reason", name); - std::cerr << err << std::endl; + throw std::runtime_error(err); } - return nullptr; + throw std::runtime_error("Unknown module: " + name); } diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 7e3280ae..ea9d02d2 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -16,26 +16,32 @@ waybar::modules::Battery::Battery(Json::Value config) if (batteries_.empty()) { throw std::runtime_error("No batteries."); } - auto fd = inotify_init1(IN_CLOEXEC); - if (fd == -1) { + fd_ = inotify_init1(IN_CLOEXEC); + if (fd_ == -1) { throw std::runtime_error("Unable to listen batteries."); } for (auto &bat : batteries_) { - inotify_add_watch(fd, (bat / "uevent").c_str(), IN_ACCESS); + inotify_add_watch(fd_, (bat / "uevent").c_str(), IN_ACCESS); } - // Trigger first value - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Battery::update)); + // Trigger first values + update(); label_.set_name("battery"); - thread_ = [this, fd] { + thread_.sig_update.connect(sigc::mem_fun(*this, &Battery::update)); + thread_ = [this] { struct inotify_event event = {0}; - int nbytes = read(fd, &event, sizeof(event)); + int nbytes = read(fd_, &event, sizeof(event)); if (nbytes != sizeof(event)) { return; } - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Battery::update)); + thread_.sig_update.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 47900ada..190df873 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -5,9 +5,10 @@ waybar::modules::Clock::Clock(Json::Value 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(); - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Clock::update)); + thread_.sig_update.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 5aea971f..6ff37364 100644 --- a/src/modules/cpu.cpp +++ b/src/modules/cpu.cpp @@ -5,8 +5,9 @@ waybar::modules::Cpu::Cpu(Json::Value 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] { - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Cpu::update)); + thread_.sig_update.emit(); thread_.sleep_for(chrono::seconds(interval)); }; } diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index d298c54d..a1061f54 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -16,10 +16,11 @@ waybar::modules::Custom::Custom(std::string name, Json::Value config) } } if (can_update) { - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Custom::update)); + thread_.sig_update.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 f44f6cd3..39d23700 100644 --- a/src/modules/memory.cpp +++ b/src/modules/memory.cpp @@ -5,8 +5,9 @@ waybar::modules::Memory::Memory(Json::Value 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] { - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Memory::update)); + thread_.sig_update.emit(); thread_.sleep_for(chrono::seconds(interval)); }; } diff --git a/src/modules/network.cpp b/src/modules/network.cpp index 56565ec1..28effcaf 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -29,8 +29,10 @@ waybar::modules::Network::Network(Json::Value config) } } label_.set_name("network"); + // Trigger first values getInfo(); - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Network::update)); + update(); + thread_.sig_update.connect(sigc::mem_fun(*this, &Network::update)); thread_ = [this] { char buf[4096]; uint64_t len = netlinkResponse(sock_fd_, buf, sizeof(buf), @@ -67,11 +69,16 @@ waybar::modules::Network::Network(Json::Value config) } if (need_update) { getInfo(); - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Network::update)); + thread_.sig_update.emit(); } }; } +waybar::modules::Network::~Network() +{ + close(sock_fd_); +} + auto waybar::modules::Network::update() -> void { auto format = config_["format"] ? config_["format"].asString() : "{ifname}"; diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 00837698..a8571209 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -28,6 +28,13 @@ waybar::modules::Pulseaudio::Pulseaudio(Json::Value config) pa_threaded_mainloop_unlock(mainloop_); } +waybar::modules::Pulseaudio::~Pulseaudio() +{ + mainloop_api_->quit(mainloop_api_, 0); + pa_threaded_mainloop_stop(mainloop_); + pa_threaded_mainloop_free(mainloop_); +} + void waybar::modules::Pulseaudio::contextStateCb(pa_context *c, void *data) { auto pa = static_cast(data); diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index d13aea93..aba6e24b 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -10,6 +10,7 @@ waybar::modules::sway::Window::Window(Bar &bar, Json::Value config) ipc_eventfd_ = ipcOpenSocket(socketPath); ipcSingleCommand(ipc_eventfd_, IPC_SUBSCRIBE, "[ \"window\" ]"); getFocusedWindow(); + thread_.sig_update.connect(sigc::mem_fun(*this, &Window::update)); thread_ = [this] { try { auto res = ipcRecvResponse(ipc_eventfd_); @@ -17,7 +18,7 @@ waybar::modules::sway::Window::Window(Bar &bar, Json::Value config) if ((parsed["change"] == "focus" || parsed["change"] == "title") && parsed["container"]["focused"].asBool()) { window_ = parsed["container"]["name"].asString(); - Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Window::update)); + thread_.sig_update.emit(); } } catch (const std::exception& e) { std::cerr << e.what() << std::endl; @@ -25,6 +26,12 @@ 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_); diff --git a/src/modules/sway/workspaces.cpp b/src/modules/sway/workspaces.cpp index 701e5cb1..69563bdd 100644 --- a/src/modules/sway/workspaces.cpp +++ b/src/modules/sway/workspaces.cpp @@ -9,30 +9,35 @@ waybar::modules::sway::Workspaces::Workspaces(Bar &bar, Json::Value config) ipcfd_ = ipcOpenSocket(socketPath); ipc_eventfd_ = ipcOpenSocket(socketPath); ipcSingleCommand(ipc_eventfd_, IPC_SUBSCRIBE, "[ \"workspace\" ]"); + thread_.sig_update.connect(sigc::mem_fun(*this, &Workspaces::update)); thread_ = [this] { try { // Wait for the name of the output - if (!config_["all-outputs"].asBool() && bar_.outputName.empty()) { - while (bar_.outputName.empty()) { + if (!config_["all-outputs"].asBool() && bar_.output_name.empty()) { + while (bar_.output_name.empty()) { thread_.sleep_for(chrono::milliseconds(150)); } } else if (!workspaces_.empty()) { ipcRecvResponse(ipc_eventfd_); } - std::lock_guard lock(mutex_); - auto res = ipcSingleCommand(ipcfd_, IPC_GET_WORKSPACES, ""); - workspaces_ = parser_.parse(res.payload); - Glib::signal_idle() - .connect_once(sigc::mem_fun(*this, &Workspaces::update)); + thread_.sig_update.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_); + auto res = ipcSingleCommand(ipcfd_, IPC_GET_WORKSPACES, ""); + workspaces_ = parser_.parse(res.payload); bool needReorder = false; for (auto it = buttons_.begin(); it != buttons_.end();) { auto ws = std::find_if(workspaces_.begin(), workspaces_.end(), @@ -46,7 +51,7 @@ auto waybar::modules::sway::Workspaces::update() -> void } for (auto node : workspaces_) { if (!config_["all-outputs"].asBool() - && bar_.outputName != node["output"].asString()) { + && bar_.output_name != node["output"].asString()) { continue; } auto it = buttons_.find(node["num"].asInt());