1 #include "modules/memory.hpp"
2 
Memory(const std::string & id,const Json::Value & config)3 waybar::modules::Memory::Memory(const std::string& id, const Json::Value& config)
4     : ALabel(config, "memory", id, "{}%", 30) {
5   thread_ = [this] {
6     dp.emit();
7     thread_.sleep_for(interval_);
8   };
9 }
10 
update()11 auto waybar::modules::Memory::update() -> void {
12   parseMeminfo();
13 
14   unsigned long memtotal = meminfo_["MemTotal"];
15   unsigned long swaptotal = 0;
16   if (meminfo_.count("SwapTotal")) {
17     swaptotal = meminfo_["SwapTotal"];
18   }
19   unsigned long memfree;
20   unsigned long swapfree = 0;
21   if (meminfo_.count("SwapFree")) {
22     swapfree = meminfo_["SwapFree"];
23   }
24   if (meminfo_.count("MemAvailable")) {
25     // New kernels (3.4+) have an accurate available memory field.
26     memfree = meminfo_["MemAvailable"] + meminfo_["zfs_size"];
27   } else {
28     // Old kernel; give a best-effort approximation of available memory.
29     memfree = meminfo_["MemFree"] + meminfo_["Buffers"] + meminfo_["Cached"] +
30               meminfo_["SReclaimable"] - meminfo_["Shmem"] + meminfo_["zfs_size"];
31   }
32 
33   if (memtotal > 0 && memfree >= 0) {
34     auto total_ram_gigabytes = memtotal / std::pow(1024, 2);
35     auto total_swap_gigabytes = swaptotal / std::pow(1024, 2);
36     int  used_ram_percentage = 100 * (memtotal - memfree) / memtotal;
37     int  used_swap_percentage = 0;
38     if (swaptotal && swapfree) {
39       used_swap_percentage = 100 * (swaptotal - swapfree) / swaptotal;
40     }
41     auto used_ram_gigabytes = (memtotal - memfree) / std::pow(1024, 2);
42     auto used_swap_gigabytes = (swaptotal - swapfree) / std::pow(1024, 2);
43     auto available_ram_gigabytes = memfree / std::pow(1024, 2);
44     auto available_swap_gigabytes = swapfree / std::pow(1024, 2);
45 
46     auto format = format_;
47     auto state = getState(used_ram_percentage);
48     if (!state.empty() && config_["format-" + state].isString()) {
49       format = config_["format-" + state].asString();
50     }
51 
52     if (format.empty()) {
53       event_box_.hide();
54     } else {
55       event_box_.show();
56       auto icons = std::vector<std::string>{state};
57       label_.set_markup(fmt::format(format,
58                                     used_ram_percentage,
59                                     fmt::arg("icon", getIcon(used_ram_percentage, icons)),
60                                     fmt::arg("total", total_ram_gigabytes),
61                                     fmt::arg("swapTotal", total_swap_gigabytes),
62                                     fmt::arg("percentage", used_ram_percentage),
63                                     fmt::arg("swapPercentage", used_swap_percentage),
64                                     fmt::arg("used", used_ram_gigabytes),
65                                     fmt::arg("swapUsed", used_swap_gigabytes),
66                                     fmt::arg("avail", available_ram_gigabytes),
67                                     fmt::arg("swapAvail", available_swap_gigabytes)));
68     }
69 
70     if (tooltipEnabled()) {
71       if (config_["tooltip-format"].isString()) {
72         auto tooltip_format = config_["tooltip-format"].asString();
73         label_.set_tooltip_text(fmt::format(tooltip_format,
74                                             used_ram_percentage,
75                                             fmt::arg("total", total_ram_gigabytes),
76                                             fmt::arg("swapTotal", total_swap_gigabytes),
77                                             fmt::arg("percentage", used_ram_percentage),
78                                             fmt::arg("swapPercentage", used_swap_percentage),
79                                             fmt::arg("used", used_ram_gigabytes),
80                                             fmt::arg("swapUsed", used_swap_gigabytes),
81                                             fmt::arg("avail", available_ram_gigabytes),
82                                             fmt::arg("swapAvail", available_swap_gigabytes)));
83       } else {
84         label_.set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1));
85       }
86     }
87   } else {
88     event_box_.hide();
89   }
90   // Call parent update
91   ALabel::update();
92 }
93