feat: Add support for battery related events

This commit is contained in:
markx86
2025-06-20 12:31:56 +02:00
parent 4730fc4d77
commit 08da7b5282
3 changed files with 33 additions and 4 deletions

View File

@ -35,6 +35,7 @@ class Battery : public ALabel {
std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos(); std::tuple<uint8_t, float, std::string, float, uint16_t, float> getInfos();
const std::string formatTimeRemaining(float hoursRemaining); const std::string formatTimeRemaining(float hoursRemaining);
void setBarClass(std::string&); void setBarClass(std::string&);
void processEvents(std::string& state, std::string& status, uint8_t capacity);
int global_watch; int global_watch;
std::map<fs::path, int> batteries_; std::map<fs::path, int> batteries_;
@ -43,6 +44,7 @@ class Battery : public ALabel {
int global_watch_fd_; int global_watch_fd_;
std::mutex battery_list_mutex_; std::mutex battery_list_mutex_;
std::string old_status_; std::string old_status_;
std::string last_event_;
bool warnFirstTime_{true}; bool warnFirstTime_{true};
const Bar& bar_; const Bar& bar_;

View File

@ -200,7 +200,7 @@ std::string ALabel::getState(uint8_t value, bool lesser) {
} }
} }
// Sort states // Sort states
std::sort(states.begin(), states.end(), [&lesser](auto& a, auto& b) { std::ranges::sort(states.begin(), states.end(), [&lesser](auto& a, auto& b) {
return lesser ? a.second < b.second : a.second > b.second; return lesser ? a.second < b.second : a.second > b.second;
}); });
std::string valid_state; std::string valid_state;

View File

@ -1,14 +1,15 @@
#include "modules/battery.hpp" #include "modules/battery.hpp"
#include "util/command.hpp"
#include <algorithm> #include <algorithm>
#include <cctype>
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
#include <sys/sysctl.h> #include <sys/sysctl.h>
#endif #endif
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <iostream>
waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const Json::Value& config) waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const Json::Value& config)
: ALabel(config, "battery", id, "{capacity}%", 60), bar_(bar) { : ALabel(config, "battery", id, "{capacity}%", 60), last_event_(""), bar_(bar) {
#if defined(__linux__) #if defined(__linux__)
battery_watch_fd_ = inotify_init1(IN_CLOEXEC); battery_watch_fd_ = inotify_init1(IN_CLOEXEC);
if (battery_watch_fd_ == -1) { if (battery_watch_fd_ == -1) {
@ -26,6 +27,7 @@ waybar::modules::Battery::Battery(const std::string& id, const Bar& bar, const J
throw std::runtime_error("Could not watch for battery plug/unplug"); throw std::runtime_error("Could not watch for battery plug/unplug");
} }
#endif #endif
spdlog::debug("battery: worker interval is {}", interval_.count());
worker(); worker();
} }
@ -677,10 +679,11 @@ auto waybar::modules::Battery::update() -> void {
} }
auto status_pretty = status; auto status_pretty = status;
// Transform to lowercase and replace space with dash // Transform to lowercase and replace space with dash
std::transform(status.begin(), status.end(), status.begin(), std::ranges::transform(status.begin(), status.end(), status.begin(),
[](char ch) { return ch == ' ' ? '-' : std::tolower(ch); }); [](char ch) { return ch == ' ' ? '-' : std::tolower(ch); });
auto format = format_; auto format = format_;
auto state = getState(capacity, true); auto state = getState(capacity, true);
processEvents(state, status, capacity);
setBarClass(state); setBarClass(state);
auto time_remaining_formatted = formatTimeRemaining(time_remaining); auto time_remaining_formatted = formatTimeRemaining(time_remaining);
if (tooltipEnabled()) { if (tooltipEnabled()) {
@ -767,3 +770,27 @@ void waybar::modules::Battery::setBarClass(std::string& state) {
bar_.window.get_style_context()->add_class(new_class); bar_.window.get_style_context()->add_class(new_class);
} }
} }
void waybar::modules::Battery::processEvents(std::string& state, std::string& status, uint8_t capacity) {
// There are no events specified, skip
auto events = config_["events"];
if (!events.isObject() || events.empty()) {
return;
}
std::string event_name = fmt::format(
"on-{}-{}",
status == "discharging" ? status : "charging",
state.empty() ? std::to_string(capacity) : state
);
if (last_event_ != event_name) {
spdlog::debug("battery: triggering event {}", event_name);
if (events[event_name].isString()) {
std::string exec = events[event_name].asString();
// Execute the command if it is not empty
if (!exec.empty()) {
util::command::exec(exec, "");
}
}
last_event_ = event_name;
}
}