Battery event (#18)
parent
01894f18cd
commit
a423f7032d
|
@ -15,7 +15,7 @@ namespace waybar {
|
||||||
class Factory {
|
class Factory {
|
||||||
public:
|
public:
|
||||||
Factory(Bar &bar, Json::Value config);
|
Factory(Bar &bar, Json::Value config);
|
||||||
IModule &makeModule(std::string name);
|
IModule *makeModule(std::string name);
|
||||||
private:
|
private:
|
||||||
Bar &_bar;
|
Bar &_bar;
|
||||||
Json::Value _config;
|
Json::Value _config;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
|
#include <sys/inotify.h>
|
||||||
#include "util/chrono.hpp"
|
#include "util/chrono.hpp"
|
||||||
#include "IModule.hpp"
|
#include "IModule.hpp"
|
||||||
|
|
||||||
|
@ -18,7 +19,7 @@ namespace waybar::modules {
|
||||||
auto update() -> void;
|
auto update() -> void;
|
||||||
operator Gtk::Widget&();
|
operator Gtk::Widget&();
|
||||||
private:
|
private:
|
||||||
std::string _getIcon(uint32_t percentage);
|
std::string _getIcon(uint16_t percentage);
|
||||||
static inline const fs::path _data_dir = "/sys/class/power_supply/";
|
static inline const fs::path _data_dir = "/sys/class/power_supply/";
|
||||||
std::vector<fs::path> _batteries;
|
std::vector<fs::path> _batteries;
|
||||||
util::SleeperThread _thread;
|
util::SleeperThread _thread;
|
||||||
|
|
|
@ -39,7 +39,9 @@ namespace waybar::util {
|
||||||
func();
|
func();
|
||||||
} while (do_run);
|
} while (do_run);
|
||||||
}}
|
}}
|
||||||
{}
|
{
|
||||||
|
defined = true;
|
||||||
|
}
|
||||||
|
|
||||||
SleeperThread& operator=(std::function<void()> func)
|
SleeperThread& operator=(std::function<void()> func)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +50,7 @@ namespace waybar::util {
|
||||||
func();
|
func();
|
||||||
} while (do_run);
|
} while (do_run);
|
||||||
});
|
});
|
||||||
|
defined = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,14 +75,17 @@ namespace waybar::util {
|
||||||
~SleeperThread()
|
~SleeperThread()
|
||||||
{
|
{
|
||||||
do_run = false;
|
do_run = false;
|
||||||
condvar.notify_all();
|
if (defined) {
|
||||||
thread.join();
|
condvar.notify_all();
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::thread thread;
|
std::thread thread;
|
||||||
std::condition_variable condvar;
|
std::condition_variable condvar;
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
|
bool defined = false;
|
||||||
bool do_run = true;
|
bool do_run = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
15
src/bar.cpp
15
src/bar.cpp
|
@ -170,21 +170,24 @@ auto waybar::Bar::_setupWidgets() -> void
|
||||||
|
|
||||||
if (_config["modules-left"]) {
|
if (_config["modules-left"]) {
|
||||||
for (auto name : _config["modules-left"]) {
|
for (auto name : _config["modules-left"]) {
|
||||||
auto &module = factory.makeModule(name.asString());
|
auto module = factory.makeModule(name.asString());
|
||||||
left.pack_start(module, false, true, 0);
|
if (module)
|
||||||
|
left.pack_start(*module, false, true, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_config["modules-center"]) {
|
if (_config["modules-center"]) {
|
||||||
for (auto name : _config["modules-center"]) {
|
for (auto name : _config["modules-center"]) {
|
||||||
auto &module = factory.makeModule(name.asString());
|
auto module = factory.makeModule(name.asString());
|
||||||
center.pack_start(module, true, false, 10);
|
if (module)
|
||||||
|
center.pack_start(*module, true, false, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_config["modules-right"]) {
|
if (_config["modules-right"]) {
|
||||||
std::reverse(_config["modules-right"].begin(), _config["modules-right"].end());
|
std::reverse(_config["modules-right"].begin(), _config["modules-right"].end());
|
||||||
for (auto name : _config["modules-right"]) {
|
for (auto name : _config["modules-right"]) {
|
||||||
auto &module = factory.makeModule(name.asString());
|
auto module = factory.makeModule(name.asString());
|
||||||
right.pack_end(module, false, false, 0);
|
if (module)
|
||||||
|
right.pack_end(*module, false, false, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,23 +4,32 @@ waybar::Factory::Factory(Bar &bar, Json::Value config)
|
||||||
: _bar(bar), _config(config)
|
: _bar(bar), _config(config)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
waybar::IModule &waybar::Factory::makeModule(std::string name)
|
waybar::IModule *waybar::Factory::makeModule(std::string name)
|
||||||
{
|
{
|
||||||
if (name == "battery")
|
try {
|
||||||
return *new waybar::modules::Battery(_config[name]);
|
if (name == "battery")
|
||||||
if (name == "workspaces")
|
return new waybar::modules::Battery(_config[name]);
|
||||||
return *new waybar::modules::Workspaces(_bar);
|
if (name == "workspaces")
|
||||||
if (name == "memory")
|
return new waybar::modules::Workspaces(_bar);
|
||||||
return *new waybar::modules::Memory(_config[name]);
|
if (name == "memory")
|
||||||
if (name == "cpu")
|
return new waybar::modules::Memory(_config[name]);
|
||||||
return *new waybar::modules::Cpu(_config[name]);
|
if (name == "cpu")
|
||||||
if (name == "clock")
|
return new waybar::modules::Cpu(_config[name]);
|
||||||
return *new waybar::modules::Clock(_config[name]);
|
if (name == "clock")
|
||||||
if (name == "network")
|
return new waybar::modules::Clock(_config[name]);
|
||||||
return *new waybar::modules::Network(_config[name]);
|
if (name == "network")
|
||||||
if (name == "pulseaudio")
|
return new waybar::modules::Network(_config[name]);
|
||||||
return *new waybar::modules::Pulseaudio(_config[name]);
|
if (name == "pulseaudio")
|
||||||
if (!name.compare(0, 7, "custom/") && name.size() > 7)
|
return new waybar::modules::Pulseaudio(_config[name]);
|
||||||
return *new waybar::modules::Custom(name.substr(7), _config[name]);
|
if (!name.compare(0, 7, "custom/") && name.size() > 7)
|
||||||
throw std::runtime_error("Unknown module: " + name);
|
return new waybar::modules::Custom(name.substr(7), _config[name]);
|
||||||
|
std::cerr << "Unknown module: " + name << std::endl;
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
auto err = fmt::format("Disabling module \"{}\", {}", name, e.what());
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
} catch (...) {
|
||||||
|
auto err = fmt::format("Disabling module \"{}\", Unknown reason", name);
|
||||||
|
std::cerr << err << std::endl;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,62 +5,66 @@ waybar::modules::Battery::Battery(Json::Value config)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
for (auto &node : fs::directory_iterator(_data_dir)) {
|
for (auto &node : fs::directory_iterator(_data_dir)) {
|
||||||
if (fs::is_directory(node) && fs::exists(node / "capacity")
|
if (fs::is_directory(node) && fs::exists(node / "capacity"))
|
||||||
&& fs::exists(node / "status")) {
|
|
||||||
_batteries.push_back(node);
|
_batteries.push_back(node);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (fs::filesystem_error &e) {
|
} catch (fs::filesystem_error &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
throw std::runtime_error(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_batteries.size()) {
|
if (!_batteries.size())
|
||||||
std::cerr << "No batteries." << std::endl;
|
throw std::runtime_error("No batteries.");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
auto fd = inotify_init();
|
||||||
|
if (fd == -1)
|
||||||
|
throw std::runtime_error("Unable to listen batteries.");
|
||||||
|
for (auto &bat : _batteries)
|
||||||
|
inotify_add_watch(fd, (bat / "uevent").c_str(), IN_ACCESS);
|
||||||
|
// Trigger first value
|
||||||
|
update();
|
||||||
_label.get_style_context()->add_class("battery");
|
_label.get_style_context()->add_class("battery");
|
||||||
int interval = _config["interval"] ? _config["inveral"].asInt() : 1;
|
_thread = [this, fd] {
|
||||||
_thread = [this, interval] {
|
struct inotify_event event;
|
||||||
|
int nbytes = read(fd, &event, sizeof(event));
|
||||||
|
if (nbytes != sizeof(event))
|
||||||
|
return;
|
||||||
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Battery::update));
|
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Battery::update));
|
||||||
_thread.sleep_for(chrono::seconds(interval));
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto waybar::modules::Battery::update() -> void
|
auto waybar::modules::Battery::update() -> void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
int total = 0;
|
uint16_t total = 0;
|
||||||
bool charging = false;
|
bool charging = false;
|
||||||
|
std::string status;
|
||||||
for (auto &bat : _batteries) {
|
for (auto &bat : _batteries) {
|
||||||
int capacity;
|
uint16_t capacity;
|
||||||
std::string status;
|
|
||||||
std::ifstream(bat / "capacity") >> capacity;
|
std::ifstream(bat / "capacity") >> capacity;
|
||||||
total += capacity;
|
|
||||||
std::ifstream(bat / "status") >> status;
|
std::ifstream(bat / "status") >> status;
|
||||||
if (status == "Charging") {
|
if (status == "Charging")
|
||||||
charging = true;
|
charging = true;
|
||||||
}
|
total += capacity;
|
||||||
}
|
}
|
||||||
|
uint16_t capacity = total / _batteries.size();
|
||||||
auto format = _config["format"] ? _config["format"].asString() : "{}%";
|
auto format = _config["format"] ? _config["format"].asString() : "{}%";
|
||||||
auto value = total / _batteries.size();
|
_label.set_text(fmt::format(format, fmt::arg("value", capacity),
|
||||||
_label.set_text(fmt::format(format, fmt::arg("value", value),
|
fmt::arg("icon", _getIcon(capacity))));
|
||||||
fmt::arg("icon", _getIcon(value))));
|
_label.set_tooltip_text(status);
|
||||||
_label.set_tooltip_text(charging ? "Charging" : "Discharging");
|
|
||||||
if (charging)
|
if (charging)
|
||||||
_label.get_style_context()->add_class("charging");
|
_label.get_style_context()->add_class("charging");
|
||||||
else
|
else
|
||||||
_label.get_style_context()->remove_class("charging");
|
_label.get_style_context()->remove_class("charging");
|
||||||
if (value < 16 && !charging)
|
if (capacity < 16 && !charging)
|
||||||
_label.get_style_context()->add_class("warning");
|
_label.get_style_context()->add_class("warning");
|
||||||
else
|
else
|
||||||
_label.get_style_context()->remove_class("warning");
|
_label.get_style_context()->remove_class("warning");
|
||||||
} catch (std::exception &e) {
|
} catch (const std::exception& e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string waybar::modules::Battery::_getIcon(uint32_t percentage)
|
std::string waybar::modules::Battery::_getIcon(uint16_t percentage)
|
||||||
{
|
{
|
||||||
if (!_config["format-icons"] || !_config["format-icons"].isArray()) return "";
|
if (!_config["format-icons"] || !_config["format-icons"].isArray()) return "";
|
||||||
auto step = 100 / _config["format-icons"].size();
|
auto step = 100 / _config["format-icons"].size();
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
waybar::modules::Custom::Custom(std::string name, Json::Value config)
|
waybar::modules::Custom::Custom(std::string name, Json::Value config)
|
||||||
: _name(name), _config(config)
|
: _name(name), _config(config)
|
||||||
{
|
{
|
||||||
if (!_config["exec"]) {
|
if (!_config["exec"])
|
||||||
std::cerr << name + " has no exec path." << std::endl;
|
throw std::runtime_error(name + " has no exec path.");
|
||||||
return;
|
|
||||||
}
|
|
||||||
int interval = _config["interval"] ? _config["inveral"].asInt() : 30;
|
int interval = _config["interval"] ? _config["inveral"].asInt() : 30;
|
||||||
_thread = [this, interval] {
|
_thread = [this, interval] {
|
||||||
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Custom::update));
|
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Custom::update));
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#include "modules/network.hpp"
|
#include "modules/network.hpp"
|
||||||
|
|
||||||
waybar::modules::Network::Network(Json::Value config)
|
waybar::modules::Network::Network(Json::Value config)
|
||||||
: _config(config), _ifid(if_nametoindex(config["interface"].asString().c_str()))
|
: _config(config), _ifid(if_nametoindex(config["interface"].asCString()))
|
||||||
{
|
{
|
||||||
|
if (_ifid == 0)
|
||||||
|
throw std::runtime_error("Can't found network interface");
|
||||||
_label.get_style_context()->add_class("network");
|
_label.get_style_context()->add_class("network");
|
||||||
int interval = _config["interval"] ? _config["inveral"].asInt() : 30;
|
int interval = _config["interval"] ? _config["inveral"].asInt() : 30;
|
||||||
_thread = [this, interval] {
|
_thread = [this, interval] {
|
||||||
|
@ -103,8 +105,6 @@ bool waybar::modules::Network::_associatedOrJoined(struct nlattr** bss)
|
||||||
|
|
||||||
auto waybar::modules::Network::_getInfo() -> void
|
auto waybar::modules::Network::_getInfo() -> void
|
||||||
{
|
{
|
||||||
if (_ifid == 0)
|
|
||||||
return;
|
|
||||||
struct nl_sock *sk = nl_socket_alloc();
|
struct nl_sock *sk = nl_socket_alloc();
|
||||||
if (genl_connect(sk) != 0) {
|
if (genl_connect(sk) != 0) {
|
||||||
nl_socket_free(sk);
|
nl_socket_free(sk);
|
||||||
|
|
|
@ -5,17 +5,12 @@ waybar::modules::Workspaces::Workspaces(Bar &bar)
|
||||||
: _bar(bar)
|
: _bar(bar)
|
||||||
{
|
{
|
||||||
_box.get_style_context()->add_class("workspaces");
|
_box.get_style_context()->add_class("workspaces");
|
||||||
try {
|
std::string socketPath = get_socketpath();
|
||||||
std::string socketPath = get_socketpath();
|
_ipcSocketfd = ipc_open_socket(socketPath);
|
||||||
_ipcSocketfd = ipc_open_socket(socketPath);
|
_ipcEventSocketfd = ipc_open_socket(socketPath);
|
||||||
_ipcEventSocketfd = ipc_open_socket(socketPath);
|
const char *subscribe = "[ \"workspace\", \"mode\" ]";
|
||||||
const char *subscribe = "[ \"workspace\", \"mode\" ]";
|
uint32_t len = strlen(subscribe);
|
||||||
uint32_t len = strlen(subscribe);
|
ipc_single_command(_ipcEventSocketfd, IPC_SUBSCRIBE, subscribe, &len);
|
||||||
ipc_single_command(_ipcEventSocketfd, IPC_SUBSCRIBE, subscribe, &len);
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::cerr << e.what() << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_thread = [this] {
|
_thread = [this] {
|
||||||
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Workspaces::update));
|
Glib::signal_idle().connect_once(sigc::mem_fun(*this, &Workspaces::update));
|
||||||
_thread.sleep_for(chrono::milliseconds(250));
|
_thread.sleep_for(chrono::milliseconds(250));
|
||||||
|
|
Loading…
Reference in New Issue