diff --git a/include/modules/cpu.hpp b/include/modules/cpu.hpp index 18543464..71d2c51b 100644 --- a/include/modules/cpu.hpp +++ b/include/modules/cpu.hpp @@ -1,7 +1,9 @@ #pragma once #include -#include +#include +#include +#include #include "util/chrono.hpp" #include "ALabel.hpp" @@ -12,6 +14,9 @@ class Cpu : public ALabel { Cpu(const Json::Value&); auto update() -> void; private: + static inline const std::string data_dir_ = "/proc/stat"; + std::vector< std::tuple > parseCpuinfo(); + std::vector< std::tuple > prevTimes_; waybar::util::SleeperThread thread_; }; diff --git a/src/modules/cpu.cpp b/src/modules/cpu.cpp index 5bb836ea..1bdd0fe3 100644 --- a/src/modules/cpu.cpp +++ b/src/modules/cpu.cpp @@ -13,10 +13,52 @@ waybar::modules::Cpu::Cpu(const Json::Value& config) auto waybar::modules::Cpu::update() -> void { - struct sysinfo info = {}; - if (sysinfo(&info) == 0) { - float f_load = 1.f / (1u << SI_LOAD_SHIFT); - uint16_t load = info.loads[0] * f_load * 100 / get_nprocs(); - label_.set_text(fmt::format(format_, load)); + if (prevTimes_.size() < 1) { + prevTimes_ = parseCpuinfo(); + std::this_thread::sleep_for(chrono::milliseconds(100)); } + std::vector< std::tuple > currTimes = parseCpuinfo(); + std::string tooltip; + for (size_t i = 0; i < currTimes.size(); ++i) { + auto [currIdle, currTotal] = currTimes[i]; + auto [prevIdle, prevTotal] = prevTimes_[i]; + const float deltaIdle = currIdle - prevIdle; + const float deltaTotal = currTotal - prevTotal; + uint16_t load = 100 * (1 - deltaIdle / deltaTotal); + if (i == 0) { + label_.set_text(fmt::format(format_, load)); + tooltip = fmt::format("Total: {}%", load); + } else { + tooltip = tooltip + fmt::format("\nCore{}: {}%", i - 1, load); + } + } + label_.set_tooltip_text(tooltip); + prevTimes_ = currTimes; +} + +std::vector< std::tuple > waybar::modules::Cpu::parseCpuinfo() +{ + std::ifstream info(data_dir_); + if (!info.is_open()) { + throw std::runtime_error("Can't open " + data_dir_); + } + std::vector< std::tuple > cpuinfo; + std::string line; + while (getline(info, line)) { + if (line.substr(0,3).compare("cpu") != 0) { + break; + } + std::stringstream sline(line.substr(5)); + std::vector times; + for (size_t time; sline >> time; times.push_back(time)); + + size_t idle_time = 0; + size_t total_time = 0; + if (times.size() >= 4) { + idle_time = times[3]; + total_time = std::accumulate(times.begin(), times.end(), 0); + } + cpuinfo.push_back( {idle_time, total_time} ); + } + return cpuinfo; }