Merge pull request #4208 from markx86/feat/battery-events
battery: Add support for battery level related events
This commit is contained in:
@ -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_;
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||||||
*menu-file*: ++
|
*menu-file*: ++
|
||||||
typeof: string ++
|
typeof: string ++
|
||||||
Location of the menu descriptor file. There need to be an element of type
|
Location of the menu descriptor file. There need to be an element of type
|
||||||
GtkMenu with id *menu*
|
GtkMenu with id *menu*.
|
||||||
|
|
||||||
*menu-actions*: ++
|
*menu-actions*: ++
|
||||||
typeof: array ++
|
typeof: array ++
|
||||||
@ -127,6 +127,10 @@ The *battery* module displays the current capacity and state (eg. charging) of y
|
|||||||
default: false ++
|
default: false ++
|
||||||
Enables this module to consume all left over space dynamically.
|
Enables this module to consume all left over space dynamically.
|
||||||
|
|
||||||
|
*events*: ++
|
||||||
|
typeof: object ++
|
||||||
|
Specifies commands to be executed on specific battery states. See *EVENTS* section below.
|
||||||
|
|
||||||
# FORMAT REPLACEMENTS
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
*{capacity}*: Capacity in percentage
|
*{capacity}*: Capacity in percentage
|
||||||
@ -166,6 +170,19 @@ The *battery* module allows one to define custom formats based on up to two fact
|
|||||||
- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal to or below the configured *<value>*.
|
- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the *<name>* of the state. Each class gets activated when the current capacity is equal to or below the configured *<value>*.
|
||||||
- Also each state can have its own *format*. Those can be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*.
|
- Also each state can have its own *format*. Those can be configured via *format-<name>*. Or if you want to differentiate a bit more even as *format-<status>-<state>*. For more information see *custom-formats*.
|
||||||
|
|
||||||
|
# EVENTS
|
||||||
|
|
||||||
|
Every entry in the *events* object consists of a *<event-name>* (typeof: *string*) and a *<command>* (typeof: *string*). ++
|
||||||
|
*<event-name>* can be in one of the following formats:
|
||||||
|
|
||||||
|
- *on-<status>-<state>*
|
||||||
|
- *on-<status>-<capacity>*
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
- *<status>* is either *charging* or *discharging*,
|
||||||
|
- *<state>* is the name of one of the states specified in the *states* object,
|
||||||
|
- *<capacity>* is a battery level value (between *0-100*).
|
||||||
|
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
@ -178,6 +195,11 @@ The *battery* module allows one to define custom formats based on up to two fact
|
|||||||
"warning": 30,
|
"warning": 30,
|
||||||
"critical": 15
|
"critical": 15
|
||||||
},
|
},
|
||||||
|
"events": {
|
||||||
|
"on-discharging-warning": "notify-send -u normal 'Low Battery'",
|
||||||
|
"on-discharging-critical": "notify-send -u critical 'Very Low Battery'",
|
||||||
|
"on-charging-100": "notify-send -u normal 'Battery Full!'"
|
||||||
|
},
|
||||||
"format": "{capacity}% {icon}",
|
"format": "{capacity}% {icon}",
|
||||||
"format-icons": ["", "", "", "", ""],
|
"format-icons": ["", "", "", "", ""],
|
||||||
"max-length": 25
|
"max-length": 25
|
||||||
|
@ -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;
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
#include "modules/battery.hpp"
|
#include "modules/battery.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
#include "util/command.hpp"
|
||||||
#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 +28,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 +680,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()) {
|
||||||
@ -770,3 +774,25 @@ 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user