Merge branch 'master' into issue-1681

This commit is contained in:
Alexis Rouillard
2025-06-22 08:41:15 +01:00
committed by GitHub
276 changed files with 15334 additions and 5163 deletions

View File

@ -2,16 +2,23 @@
#include <spdlog/spdlog.h>
#include "util/scope_guard.hpp"
waybar::modules::Custom::Custom(const std::string& name, const std::string& id,
const Json::Value& config)
const Json::Value& config, const std::string& output_name)
: ALabel(config, "custom-" + name, id, "{}"),
name_(name),
output_name_(output_name),
id_(id),
tooltip_format_enabled_{config_["tooltip-format"].isString()},
percentage_(0),
fp_(nullptr),
pid_(-1) {
dp.emit();
if (interval_.count() > 0) {
if (!config_["signal"].empty() && config_["interval"].empty() &&
config_["restart-interval"].empty()) {
waitingWorker();
} else if (interval_.count() > 0) {
delayWorker();
} else if (config_["exec"].isString()) {
continuousWorker();
@ -46,7 +53,7 @@ void waybar::modules::Custom::delayWorker() {
}
if (can_update) {
if (config_["exec"].isString()) {
output_ = util::command::exec(config_["exec"].asString());
output_ = util::command::exec(config_["exec"].asString(), output_name_);
}
dp.emit();
}
@ -57,12 +64,17 @@ void waybar::modules::Custom::delayWorker() {
void waybar::modules::Custom::continuousWorker() {
auto cmd = config_["exec"].asString();
pid_ = -1;
fp_ = util::command::open(cmd, pid_);
fp_ = util::command::open(cmd, pid_, output_name_);
if (!fp_) {
throw std::runtime_error("Unable to open " + cmd);
}
thread_ = [this, cmd] {
char* buff = nullptr;
waybar::util::ScopeGuard buff_deleter([&buff]() {
if (buff) {
free(buff);
}
});
size_t len = 0;
if (getline(&buff, &len, fp_) == -1) {
int exit_code = 1;
@ -78,7 +90,7 @@ void waybar::modules::Custom::continuousWorker() {
if (config_["restart-interval"].isUInt()) {
pid_ = -1;
thread_.sleep_for(std::chrono::seconds(config_["restart-interval"].asUInt()));
fp_ = util::command::open(cmd, pid_);
fp_ = util::command::open(cmd, pid_, output_name_);
if (!fp_) {
throw std::runtime_error("Unable to open " + cmd);
}
@ -96,7 +108,26 @@ void waybar::modules::Custom::continuousWorker() {
output_ = {0, output};
dp.emit();
}
free(buff);
};
}
void waybar::modules::Custom::waitingWorker() {
thread_ = [this] {
bool can_update = true;
if (config_["exec-if"].isString()) {
output_ = util::command::execNoRead(config_["exec-if"].asString());
if (output_.exit_code != 0) {
can_update = false;
dp.emit();
}
}
if (can_update) {
if (config_["exec"].isString()) {
output_ = util::command::exec(config_["exec"].asString(), output_name_);
}
dp.emit();
}
thread_.sleep();
};
}
@ -135,35 +166,53 @@ auto waybar::modules::Custom::update() -> void {
} else {
parseOutputRaw();
}
auto str = fmt::format(fmt::runtime(format_), text_, fmt::arg("alt", alt_),
fmt::arg("icon", getIcon(percentage_, alt_)),
fmt::arg("percentage", percentage_));
if (str.empty()) {
event_box_.hide();
} else {
label_.set_markup(str);
if (tooltipEnabled()) {
if (text_ == tooltip_) {
if (label_.get_tooltip_markup() != str) {
label_.set_tooltip_markup(str);
}
} else {
if (label_.get_tooltip_markup() != tooltip_) {
label_.set_tooltip_markup(tooltip_);
try {
auto str = fmt::format(fmt::runtime(format_), fmt::arg("text", text_), fmt::arg("alt", alt_),
fmt::arg("icon", getIcon(percentage_, alt_)),
fmt::arg("percentage", percentage_));
if ((config_["hide-empty-text"].asBool() && text_.empty()) || str.empty()) {
event_box_.hide();
} else {
label_.set_markup(str);
if (tooltipEnabled()) {
if (tooltip_format_enabled_) {
auto tooltip = config_["tooltip-format"].asString();
tooltip = fmt::format(
fmt::runtime(tooltip), fmt::arg("text", text_), fmt::arg("alt", alt_),
fmt::arg("icon", getIcon(percentage_, alt_)), fmt::arg("percentage", percentage_));
label_.set_tooltip_markup(tooltip);
} else if (text_ == tooltip_) {
if (label_.get_tooltip_markup() != str) {
label_.set_tooltip_markup(str);
}
} else {
if (label_.get_tooltip_markup() != tooltip_) {
label_.set_tooltip_markup(tooltip_);
}
}
}
auto style = label_.get_style_context();
auto classes = style->list_classes();
for (auto const& c : classes) {
if (c == id_) continue;
style->remove_class(c);
}
for (auto const& c : class_) {
style->add_class(c);
}
style->add_class("flat");
style->add_class("text-button");
style->add_class(MODULE_CLASS);
event_box_.show();
}
auto classes = label_.get_style_context()->list_classes();
for (auto const& c : classes) {
if (c == id_) continue;
label_.get_style_context()->remove_class(c);
}
for (auto const& c : class_) {
label_.get_style_context()->add_class(c);
}
label_.get_style_context()->add_class("flat");
label_.get_style_context()->add_class("text-button");
event_box_.show();
} catch (const fmt::format_error& e) {
if (std::strcmp(e.what(), "cannot switch from manual to automatic argument indexing") != 0)
throw;
throw fmt::format_error(
"mixing manual and automatic argument indexing is no longer supported; "
"try replacing \"{}\" with \"{text}\" in your format specifier");
}
}
// Call parent update
@ -175,18 +224,29 @@ void waybar::modules::Custom::parseOutputRaw() {
std::string line;
int i = 0;
while (getline(output, line)) {
Glib::ustring validated_line = line;
if (!validated_line.validate()) {
validated_line = validated_line.make_valid();
}
if (i == 0) {
if (config_["escape"].isBool() && config_["escape"].asBool()) {
text_ = Glib::Markup::escape_text(line);
text_ = Glib::Markup::escape_text(validated_line);
tooltip_ = Glib::Markup::escape_text(validated_line);
} else {
text_ = line;
text_ = validated_line;
tooltip_ = validated_line;
}
tooltip_ = line;
tooltip_ = validated_line;
class_.clear();
} else if (i == 1) {
tooltip_ = line;
if (config_["escape"].isBool() && config_["escape"].asBool()) {
tooltip_ = Glib::Markup::escape_text(validated_line);
} else {
tooltip_ = validated_line;
}
} else if (i == 2) {
class_.push_back(line);
class_.push_back(validated_line);
} else {
break;
}
@ -210,7 +270,11 @@ void waybar::modules::Custom::parseOutputJson() {
} else {
alt_ = parsed["alt"].asString();
}
tooltip_ = parsed["tooltip"].asString();
if (config_["escape"].isBool() && config_["escape"].asBool()) {
tooltip_ = Glib::Markup::escape_text(parsed["tooltip"].asString());
} else {
tooltip_ = parsed["tooltip"].asString();
}
if (parsed["class"].isString()) {
class_.push_back(parsed["class"].asString());
} else if (parsed["class"].isArray()) {