diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index c593e59b..435b01b4 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -5,8 +5,11 @@ #include #if defined(__linux__) #include +#include "util/udev_deleter.hpp" #endif +#include + #include #include #include @@ -37,11 +40,12 @@ class Battery : public ALabel { void setBarClass(std::string&); void processEvents(std::string& state, std::string& status, uint8_t capacity); - int global_watch; std::map batteries_; + std::unique_ptr udev_; + std::array poll_fds_; + std::unique_ptr mon_; fs::path adapter_; int battery_watch_fd_; - int global_watch_fd_; std::mutex battery_list_mutex_; std::string old_status_; std::string last_event_; diff --git a/include/util/udev_deleter.hpp b/include/util/udev_deleter.hpp new file mode 100644 index 00000000..b2f1e538 --- /dev/null +++ b/include/util/udev_deleter.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace waybar::util { +struct UdevDeleter { + void operator()(udev *ptr) const { udev_unref(ptr); } +}; + +struct UdevDeviceDeleter { + void operator()(udev_device *ptr) const { udev_device_unref(ptr); } +}; + +struct UdevEnumerateDeleter { + void operator()(udev_enumerate *ptr) const { udev_enumerate_unref(ptr); } +}; + +struct UdevMonitorDeleter { + void operator()(udev_monitor *ptr) const { udev_monitor_unref(ptr); } +}; +} // namespace waybar::util \ No newline at end of file diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 138432d0..d4594e2a 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -8,6 +8,9 @@ #include #endif #include +#include +#include +#include waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const Json::Value& config) : ALabel(config, "battery", id, "{capacity}%", 60), last_event_(""), bar_(bar) { @@ -16,17 +19,18 @@ waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const J if (battery_watch_fd_ == -1) { throw std::runtime_error("Unable to listen batteries."); } - - global_watch_fd_ = inotify_init1(IN_CLOEXEC); - if (global_watch_fd_ == -1) { - throw std::runtime_error("Unable to listen batteries."); + udev_ = std::unique_ptr(udev_new()); + if (udev_ == nullptr) { + throw std::runtime_error("udev_new failed"); } - - // Watch the directory for any added or removed batteries - global_watch = inotify_add_watch(global_watch_fd_, data_dir_.c_str(), IN_CREATE | IN_DELETE); - if (global_watch < 0) { - throw std::runtime_error("Could not watch for battery plug/unplug"); + mon_ = std::unique_ptr(udev_monitor_new_from_netlink(udev_.get(), "kernel")); + if (mon_ == nullptr) { + throw std::runtime_error("udev monitor new failed"); } + if (udev_monitor_filter_add_match_subsystem_devtype(mon_.get(), "power_supply", nullptr) < 0) { + throw std::runtime_error("udev failed to add monitor filter"); + } + udev_monitor_enable_receiving(mon_.get()); #endif spdlog::debug("battery: worker interval is {}", interval_.count()); worker(); @@ -36,11 +40,6 @@ waybar::modules::Battery::~Battery() { #if defined(__linux__) std::lock_guard guard(battery_list_mutex_); - if (global_watch >= 0) { - inotify_rm_watch(global_watch_fd_, global_watch); - } - close(global_watch_fd_); - for (auto it = batteries_.cbegin(), next_it = it; it != batteries_.cend(); it = next_it) { ++next_it; auto watch_id = (*it).second; @@ -77,12 +76,18 @@ void waybar::modules::Battery::worker() { dp.emit(); }; thread_battery_update_ = [this] { - struct inotify_event event = {0}; - int nbytes = read(global_watch_fd_, &event, sizeof(event)); - if (nbytes != sizeof(event) || event.mask & IN_IGNORED) { + poll_fds_[0].revents = 0; + poll_fds_[0].events = POLLIN; + poll_fds_[0].fd = udev_monitor_get_fd(mon_.get()); + int ret = poll(poll_fds_.data(), poll_fds_.size(), -1); + if (ret < 0) { thread_.stop(); return; } + if ((poll_fds_[0].revents & POLLIN) != 0) { + signalfd_siginfo signal_info; + read(poll_fds_[0].fd, &signal_info, sizeof(signal_info)); + } refreshBatteries(); dp.emit(); }; @@ -679,6 +684,7 @@ auto waybar::modules::Battery::update() -> void { status = getAdapterStatus(capacity); } auto status_pretty = status; + puts(status.c_str()); // Transform to lowercase and replace space with dash std::ranges::transform(status.begin(), status.end(), status.begin(), [](char ch) { return ch == ' ' ? '-' : std::tolower(ch); }); diff --git a/src/util/backlight_backend.cpp b/src/util/backlight_backend.cpp index cc513cce..204009ab 100644 --- a/src/util/backlight_backend.cpp +++ b/src/util/backlight_backend.cpp @@ -1,4 +1,5 @@ #include "util/backlight_backend.hpp" +#include "util/udev_deleter.hpp" #include #include @@ -29,22 +30,6 @@ class FileDescriptor { int fd_; }; -struct UdevDeleter { - void operator()(udev *ptr) { udev_unref(ptr); } -}; - -struct UdevDeviceDeleter { - void operator()(udev_device *ptr) { udev_device_unref(ptr); } -}; - -struct UdevEnumerateDeleter { - void operator()(udev_enumerate *ptr) { udev_enumerate_unref(ptr); } -}; - -struct UdevMonitorDeleter { - void operator()(udev_monitor *ptr) { udev_monitor_unref(ptr); } -}; - void check_eq(int rc, int expected, const char *message = "eq, rc was: ") { if (rc != expected) { throw std::runtime_error(fmt::format(fmt::runtime(message), rc));