From 729564cc27a753aacb1bc553c89ca6857fbc4c5c Mon Sep 17 00:00:00 2001 From: Mann mit Hut Date: Wed, 21 Dec 2022 17:44:11 +0100 Subject: [PATCH] Introduced separate load module The module provides the three system load averages. This is an improvement compared what you can do with the cpu module: cpu only provides the one minute sample and the state of the cpu module is derived from the cpu usage which messes up the formating of the load average. Also, at least on modern Linux systems, the load of a system takes much more than the cpu utilization into account and it should therefore live in a separate module. --- include/factory.hpp | 1 + include/modules/load.hpp | 29 +++++++++++++++++++ meson.build | 1 + src/factory.cpp | 3 ++ src/modules/load.cpp | 61 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+) create mode 100644 include/modules/load.hpp create mode 100644 src/modules/load.cpp diff --git a/include/factory.hpp b/include/factory.hpp index 90d0ac1d..217f4122 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -38,6 +38,7 @@ #endif #if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD) #include "modules/cpu.hpp" +#include "modules/load.hpp" #endif #include "modules/idle_inhibitor.hpp" #if defined(HAVE_MEMORY_LINUX) || defined(HAVE_MEMORY_BSD) diff --git a/include/modules/load.hpp b/include/modules/load.hpp new file mode 100644 index 00000000..39df4131 --- /dev/null +++ b/include/modules/load.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include +#include +#include +#include +#include +#include + +#include "AButton.hpp" +#include "util/sleeper_thread.hpp" + +namespace waybar::modules { + +class Load : public AButton { + public: + Load(const std::string&, const Json::Value&); + ~Load() = default; + auto update() -> void; + + private: + std::tuple getLoad(); + + util::SleeperThread thread_; +}; + +} // namespace waybar::modules diff --git a/meson.build b/meson.build index 9ccd83d8..fc6aa738 100644 --- a/meson.build +++ b/meson.build @@ -164,6 +164,7 @@ src_files = files( 'src/modules/disk.cpp', 'src/modules/idle_inhibitor.cpp', 'src/modules/image.cpp', + 'src/modules/load.cpp', 'src/modules/temperature.cpp', 'src/modules/user.cpp', 'src/main.cpp', diff --git a/src/factory.cpp b/src/factory.cpp index 1d7a00b5..965c57d5 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -99,6 +99,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { if (ref == "cpu") { return new waybar::modules::Cpu(id, config_[name]); } + if (ref == "load") { + return new waybar::modules::Load(id, config_[name]); + } #endif if (ref == "clock") { return new waybar::modules::Clock(id, config_[name]); diff --git a/src/modules/load.cpp b/src/modules/load.cpp new file mode 100644 index 00000000..98bc1302 --- /dev/null +++ b/src/modules/load.cpp @@ -0,0 +1,61 @@ +#include "modules/load.hpp" + +// In the 80000 version of fmt library authors decided to optimize imports +// and moved declarations required for fmt::dynamic_format_arg_store in new +// header fmt/args.h +#if (FMT_VERSION >= 80000) +#include +#else +#include +#endif + +waybar::modules::Load::Load(const std::string& id, const Json::Value& config) + : AButton(config, "load", id, "{load1}", 10) { + thread_ = [this] { + dp.emit(); + thread_.sleep_for(interval_); + }; +} + +auto waybar::modules::Load::update() -> void { + // TODO: as creating dynamic fmt::arg arrays is buggy we have to calc both + auto [load1, load5, load15] = getLoad(); + if (tooltipEnabled()) { + auto tooltip = fmt::format("Load 1: {}\nLoad 5: {}\nLoad 15: {}", load1, load5, load15); + button_.set_tooltip_text(tooltip); + } + auto format = format_; + auto state = getState(load1); + if (!state.empty() && config_["format-" + state].isString()) { + format = config_["format-" + state].asString(); + } + + if (format.empty()) { + event_box_.hide(); + } else { + event_box_.show(); + auto icons = std::vector{state}; + fmt::dynamic_format_arg_store store; + store.push_back(fmt::arg("load1", load1)); + store.push_back(fmt::arg("load5", load5)); + store.push_back(fmt::arg("load15", load15)); + store.push_back(fmt::arg("icon1", getIcon(load1, icons))); + store.push_back(fmt::arg("icon5", getIcon(load5, icons))); + store.push_back(fmt::arg("icon15", getIcon(load15, icons))); + label_->set_markup(fmt::vformat(format, store)); + } + + // Call parent update + AButton::update(); +} + +std::tuple waybar::modules::Load::getLoad() { + double load[3]; + if (getloadavg(load, 3) != -1) { + double load1 = std::ceil(load[0] * 100.0) / 100.0; + double load5 = std::ceil(load[1] * 100.0) / 100.0; + double load15 = std::ceil(load[2] * 100.0) / 100.0; + return {load1, load5, load15}; + } + throw std::runtime_error("Can't get Cpu load"); +}