Compare commits

..

11 Commits
0.0.6 ... 0.0.7

Author SHA1 Message Date
55e1905284 fix(Sway): compile without sway 2018-09-10 11:25:53 +02:00
0abaaf2f7f style: fix 2018-09-10 11:16:57 +02:00
f78ef0d491 fix(Meson): optional sway 2018-09-10 11:00:53 +02:00
de5df09fcd fix(Custom): loop script block main loop 2018-09-05 19:20:19 +02:00
7020af7653 feat(Workspaces): urgent, visible, focused icons 2018-09-05 00:16:56 +02:00
28c65c64e6 chore: add default build type 2018-08-30 11:30:20 +02:00
4f75d5e33b fix: config 2018-08-30 00:04:43 +02:00
aa05304139 feat(Pulseadio): config icons 2018-08-29 23:54:23 +02:00
6dd9b5ccc4 feat(Pulseadio): port icons 2018-08-29 23:50:41 +02:00
d0933ab50f fix(thread): check before detach 2018-08-29 21:07:58 +02:00
9a1b8bb831 fix(Custom): only set id when getting an output 2018-08-28 11:10:36 +02:00
21 changed files with 134 additions and 58 deletions

View File

@ -10,7 +10,7 @@ class ALabel : public IModule {
ALabel(const Json::Value&, const std::string format); ALabel(const Json::Value&, const std::string format);
virtual ~ALabel() = default; virtual ~ALabel() = default;
virtual auto update() -> void; virtual auto update() -> void;
virtual std::string getIcon(uint16_t percentage); virtual std::string getIcon(uint16_t, const std::string& alt = "");
virtual operator Gtk::Widget &(); virtual operator Gtk::Widget &();
protected: protected:
Gtk::EventBox event_box_; Gtk::EventBox event_box_;

View File

@ -19,6 +19,8 @@
namespace waybar { namespace waybar {
class Bar;
class Factory { class Factory {
public: public:
Factory(Bar& bar, const Json::Value& config); Factory(Bar& bar, const Json::Value& config);

View File

@ -17,6 +17,7 @@ class Custom : public ALabel {
const std::string name_; const std::string name_;
waybar::util::SleeperThread thread_; waybar::util::SleeperThread thread_;
waybar::util::command::res output_;
}; };
} }

View File

@ -17,8 +17,8 @@ class Network : public ALabel {
~Network(); ~Network();
auto update() -> void; auto update() -> void;
private: private:
static uint64_t netlinkRequest(int, void*, uint32_t, uint32_t groups = 0); static int netlinkRequest(int, void*, uint32_t, uint32_t groups = 0);
static uint64_t netlinkResponse(int, void*, uint32_t, uint32_t groups = 0); static int netlinkResponse(int, void*, uint32_t, uint32_t groups = 0);
static int scanCb(struct nl_msg*, void*); static int scanCb(struct nl_msg*, void*);
void disconnected(); void disconnected();
@ -33,7 +33,7 @@ class Network : public ALabel {
int ifid_; int ifid_;
sa_family_t family_; sa_family_t family_;
int sock_fd_; int sock_fd_;
struct sockaddr_nl nladdr_ = {0}; struct sockaddr_nl nladdr_ = {};
struct nl_sock* sk_ = nullptr; struct nl_sock* sk_ = nullptr;
int nl80211_id_; int nl80211_id_;

View File

@ -19,12 +19,15 @@ class Pulseaudio : public ALabel {
static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*); static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*);
static void serverInfoCb(pa_context*, const pa_server_info*, void*); static void serverInfoCb(pa_context*, const pa_server_info*, void*);
const std::string getPortIcon() const;
pa_threaded_mainloop* mainloop_; pa_threaded_mainloop* mainloop_;
pa_mainloop_api* mainloop_api_; pa_mainloop_api* mainloop_api_;
pa_context* context_; pa_context* context_;
uint32_t sink_idx_{0}; uint32_t sink_idx_{0};
uint16_t volume_; uint16_t volume_;
bool muted_; bool muted_;
std::string port_name_;
std::string desc_; std::string desc_;
}; };

View File

@ -18,7 +18,7 @@ class Workspaces : public IModule {
private: private:
void worker(); void worker();
void addWorkspace(Json::Value); void addWorkspace(Json::Value);
std::string getIcon(std::string); std::string getIcon(std::string, Json::Value);
bool handleScroll(GdkEventScroll*); bool handleScroll(GdkEventScroll*);
int getPrevWorkspace(); int getPrevWorkspace();
int getNextWorkspace(); int getNextWorkspace();

View File

@ -74,8 +74,10 @@ struct SleeperThread {
{ {
do_run_ = false; do_run_ = false;
condvar_.notify_all(); condvar_.notify_all();
if (thread_.joinable()) {
thread_.detach(); thread_.detach();
} }
}
private: private:
std::thread thread_; std::thread thread_;

View File

@ -4,12 +4,12 @@
namespace waybar::util::command { namespace waybar::util::command {
struct cmd_res { struct res {
int exit_code; int exit_code;
std::string out; std::string out;
}; };
inline struct cmd_res exec(const std::string cmd) inline struct res exec(const std::string cmd)
{ {
FILE* fp(popen(cmd.c_str(), "r")); FILE* fp(popen(cmd.c_str(), "r"));
if (!fp) { if (!fp) {

View File

@ -2,7 +2,10 @@ project(
'waybar', 'cpp', 'c', 'waybar', 'cpp', 'c',
version: '0.0.5', version: '0.0.5',
license: 'MIT', license: 'MIT',
default_options : ['cpp_std=c++17'], default_options : [
'cpp_std=c++17',
'buildtype=release'
],
) )
cpp_args = [] cpp_args = []
@ -48,7 +51,7 @@ src_files = files(
'src/client.cpp' 'src/client.cpp'
) )
if find_program('sway').found() if find_program('sway', required : false).found()
add_project_arguments('-DHAVE_SWAY', language: 'cpp') add_project_arguments('-DHAVE_SWAY', language: 'cpp')
src_files += [ src_files += [
'src/modules/sway/ipc/client.cpp', 'src/modules/sway/ipc/client.cpp',

View File

@ -8,7 +8,7 @@
"modules-center": ["sway/window"], "modules-center": ["sway/window"],
"modules-right": ["pulseaudio", "network", "cpu", "memory", "battery", "clock"], "modules-right": ["pulseaudio", "network", "cpu", "memory", "battery", "clock"],
// Modules configuration // Modules configuration
"sway/workspaces": { // "sway/workspaces": {
// "disable-scroll": true, // "disable-scroll": true,
// "all-outputs": true, // "all-outputs": true,
// "format-icons": { // "format-icons": {
@ -16,9 +16,12 @@
// "2": "", // "2": "",
// "3": "", // "3": "",
// "4": "", // "4": "",
// "5": "" // "5": "",
// "urgent": "",
// "focused": "",
// "default": ""
// } // }
}, // },
"sway/window": { "sway/window": {
"max-length": 50 "max-length": 50
}, },
@ -43,8 +46,17 @@
}, },
"pulseaudio": { "pulseaudio": {
"format": "{volume}% {icon}", "format": "{volume}% {icon}",
"format-bluetooth": "{volume}% {icon}",
"format-muted": "", "format-muted": "",
"format-icons": ["", ""] "format-icons": {
"headphones": "",
"handsfree": "",
"headset": "",
"phone": "",
"portable": "",
"car": "",
"default": ["", ""]
}
}, },
"custom/spotify": { "custom/spotify": {
"format": " {}", "format": " {}",

View File

@ -24,7 +24,7 @@ auto waybar::ALabel::update() -> void
// Nothing here // Nothing here
} }
bool waybar::ALabel::handleToggle(GdkEventButton* const& ev) bool waybar::ALabel::handleToggle(GdkEventButton* const& /*ev*/)
{ {
alt = !alt; alt = !alt;
if (alt) { if (alt) {
@ -36,14 +36,25 @@ bool waybar::ALabel::handleToggle(GdkEventButton* const& ev)
return true; return true;
} }
std::string waybar::ALabel::getIcon(uint16_t percentage) std::string waybar::ALabel::getIcon(uint16_t percentage, const std::string& alt)
{ {
if (!config_["format-icons"] || !config_["format-icons"].isArray()) { auto format_icons = config_["format-icons"];
return ""; if (format_icons.isObject()) {
if (!alt.empty() && format_icons[alt]) {
format_icons = format_icons[alt];
} else {
format_icons = format_icons["default"];
} }
auto size = config_["format-icons"].size(); }
if (format_icons.isArray()) {
auto size = format_icons.size();
auto idx = std::clamp(percentage / (100 / size), 0U, size - 1); auto idx = std::clamp(percentage / (100 / size), 0U, size - 1);
return config_["format-icons"][idx].asString(); format_icons = format_icons[idx];
}
if (format_icons.isString()) {
return format_icons.asString();
}
return "";
} }
waybar::ALabel::operator Gtk::Widget &() { waybar::ALabel::operator Gtk::Widget &() {

View File

@ -1,10 +1,16 @@
#include "client.hpp" #include "client.hpp"
waybar::Client::Client(int argc, char* argv[]) waybar::Client::Client(int argc, char* argv[])
: gtk_app(Gtk::Application::create(argc, argv, "org.alexays.waybar")), : gtk_app(Gtk::Application::create(argc, argv, "fr.arouillard.waybar")),
gdk_display(Gdk::Display::get_default()), gdk_display(Gdk::Display::get_default())
wl_display(gdk_wayland_display_get_wl_display(gdk_display->gobj()))
{ {
if (!gdk_display) {
throw std::runtime_error("Can't find display");
}
if (!GDK_IS_WAYLAND_DISPLAY(gdk_display->gobj())) {
throw std::runtime_error("Bar need to run under Wayland");
}
wl_display = gdk_wayland_display_get_wl_display(gdk_display->gobj());
auto getFirstValidPath = [] (std::vector<std::string> possiblePaths) { auto getFirstValidPath = [] (std::vector<std::string> possiblePaths) {
wordexp_t p; wordexp_t p;

View File

@ -14,10 +14,10 @@ waybar::IModule* waybar::Factory::makeModule(const std::string &name) const
if (name == "sway/workspaces") { if (name == "sway/workspaces") {
return new waybar::modules::sway::Workspaces(bar_, config_[name]); return new waybar::modules::sway::Workspaces(bar_, config_[name]);
} }
#endif
if (name == "sway/window") { if (name == "sway/window") {
return new waybar::modules::sway::Window(bar_, config_[name]); return new waybar::modules::sway::Window(bar_, config_[name]);
} }
#endif
if (name == "memory") { if (name == "memory") {
return new waybar::modules::Memory(config_[name]); return new waybar::modules::Memory(config_[name]);
} }

View File

@ -13,7 +13,7 @@ int main(int argc, char* argv[])
try { try {
waybar::Client c(argc, argv); waybar::Client c(argc, argv);
waybar::client = &c; waybar::client = &c;
std::signal(SIGUSR1, [] (int signal) { std::signal(SIGUSR1, [] (int /*signal*/) {
for (auto& bar : waybar::client->bars) { for (auto& bar : waybar::client->bars) {
(*bar).toggle(); (*bar).toggle();
} }

View File

@ -13,7 +13,7 @@ waybar::modules::Cpu::Cpu(const Json::Value& config)
auto waybar::modules::Cpu::update() -> void auto waybar::modules::Cpu::update() -> void
{ {
struct sysinfo info = {0}; struct sysinfo info = {};
if (sysinfo(&info) == 0) { if (sysinfo(&info) == 0) {
float f_load = 1.f / (1u << SI_LOAD_SHIFT); float f_load = 1.f / (1u << SI_LOAD_SHIFT);
uint16_t load = info.loads[0] * f_load * 100 / get_nprocs(); uint16_t load = info.loads[0] * f_load * 100 / get_nprocs();

View File

@ -7,7 +7,6 @@ waybar::modules::Custom::Custom(const std::string name,
if (!config_["exec"]) { if (!config_["exec"]) {
throw std::runtime_error(name_ + " has no exec path."); throw std::runtime_error(name_ + " has no exec path.");
} }
label_.set_name("custom-" + name_);
worker(); worker();
} }
@ -21,9 +20,11 @@ void waybar::modules::Custom::worker()
if (res.exit_code != 0) { if (res.exit_code != 0) {
can_update = false; can_update = false;
label_.hide(); label_.hide();
label_.set_name("");
} }
} }
if (can_update) { if (can_update) {
output_ = waybar::util::command::exec(config_["exec"].asString());
dp.emit(); dp.emit();
} }
thread_.sleep_for(chrono::seconds(interval)); thread_.sleep_for(chrono::seconds(interval));
@ -32,13 +33,13 @@ void waybar::modules::Custom::worker()
auto waybar::modules::Custom::update() -> void auto waybar::modules::Custom::update() -> void
{ {
auto res = waybar::util::command::exec(config_["exec"].asString());
// Hide label if output is empty // Hide label if output is empty
if (res.out.empty() || res.exit_code != 0) { if (output_.out.empty() || output_.exit_code != 0) {
label_.hide(); label_.hide();
label_.set_name("");
} else { } else {
auto str = fmt::format(format_, res.out); label_.set_name("custom-" + name_);
auto str = fmt::format(format_, output_.out);
label_.set_text(str); label_.set_text(str);
label_.set_tooltip_text(str); label_.set_tooltip_text(str);
label_.show(); label_.show();

View File

@ -13,7 +13,7 @@ waybar::modules::Memory::Memory(const Json::Value& config)
auto waybar::modules::Memory::update() -> void auto waybar::modules::Memory::update() -> void
{ {
struct sysinfo info = {0}; struct sysinfo info = {};
if (sysinfo(&info) == 0) { if (sysinfo(&info) == 0) {
auto total = info.totalram * info.mem_unit; auto total = info.totalram * info.mem_unit;
auto freeram = info.freeram * info.mem_unit; auto freeram = info.freeram * info.mem_unit;

View File

@ -165,7 +165,7 @@ int waybar::modules::Network::getExternalInterface()
* consume responses till NLMSG_DONE/NLMSG_ERROR is encountered). * consume responses till NLMSG_DONE/NLMSG_ERROR is encountered).
*/ */
do { do {
uint64_t len = netlinkResponse(sock_fd_, resp, route_buffer_size); auto len = netlinkResponse(sock_fd_, resp, route_buffer_size);
if (len < 0) { if (len < 0) {
goto out; goto out;
} }
@ -228,7 +228,7 @@ int waybar::modules::Network::getExternalInterface()
break; break;
} }
for (uint32_t i = 0; i < dstlen; i += 1) { for (uint32_t i = 0; i < dstlen; i += 1) {
c |= *(unsigned char *)(RTA_DATA(attr) + i); c |= *((unsigned char *)RTA_DATA(attr) + i);
} }
has_destination = (c == 0); has_destination = (c == 0);
break; break;
@ -255,10 +255,10 @@ out:
return ifidx; return ifidx;
} }
uint64_t waybar::modules::Network::netlinkRequest(int fd, void *req, int waybar::modules::Network::netlinkRequest(int fd, void *req,
uint32_t reqlen, uint32_t groups) uint32_t reqlen, uint32_t groups)
{ {
struct sockaddr_nl sa = {0}; struct sockaddr_nl sa = {};
sa.nl_family = AF_NETLINK; sa.nl_family = AF_NETLINK;
sa.nl_groups = groups; sa.nl_groups = groups;
struct iovec iov = { req, reqlen }; struct iovec iov = { req, reqlen };
@ -266,11 +266,11 @@ uint64_t waybar::modules::Network::netlinkRequest(int fd, void *req,
return sendmsg(fd, &msg, 0); return sendmsg(fd, &msg, 0);
} }
uint64_t waybar::modules::Network::netlinkResponse(int fd, void *resp, int waybar::modules::Network::netlinkResponse(int fd, void *resp,
uint32_t resplen, uint32_t groups) uint32_t resplen, uint32_t groups)
{ {
uint64_t ret; int ret;
struct sockaddr_nl sa = {0}; struct sockaddr_nl sa = {};
sa.nl_family = AF_NETLINK; sa.nl_family = AF_NETLINK;
sa.nl_groups = groups; sa.nl_groups = groups;
struct iovec iov = { resp, resplen }; struct iovec iov = { resp, resplen };

View File

@ -89,6 +89,7 @@ void waybar::modules::Pulseaudio::sinkInfoCb(pa_context* /*context*/,
pa->volume_ = volume * 100.0f; pa->volume_ = volume * 100.0f;
pa->muted_ = i->mute != 0; pa->muted_ = i->mute != 0;
pa->desc_ = i->description; pa->desc_ = i->description;
pa->port_name_ = i->active_port->name;
pa->dp.emit(); pa->dp.emit();
} }
} }
@ -104,6 +105,27 @@ void waybar::modules::Pulseaudio::serverInfoCb(pa_context *context,
sinkInfoCb, data); sinkInfoCb, data);
} }
const std::string waybar::modules::Pulseaudio::getPortIcon() const
{
std::vector<std::string> ports = {
"headphones",
"speaker",
"hdmi",
"headset",
"handsfree",
"portable",
"car",
"hifi",
"phone",
};
for (auto port : ports) {
if (port_name_.find(port) != std::string::npos) {
return port;
}
}
return "";
}
auto waybar::modules::Pulseaudio::update() -> void auto waybar::modules::Pulseaudio::update() -> void
{ {
auto format = format_; auto format = format_;
@ -111,11 +133,16 @@ auto waybar::modules::Pulseaudio::update() -> void
format = format =
config_["format-muted"] ? config_["format-muted"].asString() : format; config_["format-muted"] ? config_["format-muted"].asString() : format;
label_.get_style_context()->add_class("muted"); label_.get_style_context()->add_class("muted");
} else if (port_name_.find("a2dp_sink") != std::string::npos) {
format = config_["format-bluetooth"]
? config_["format-bluetooth"].asString() : format;
label_.get_style_context()->add_class("bluetooth");
} else { } else {
label_.get_style_context()->remove_class("muted"); label_.get_style_context()->remove_class("muted");
label_.get_style_context()->add_class("bluetooth");
} }
label_.set_label(fmt::format(format, label_.set_label(fmt::format(format,
fmt::arg("volume", volume_), fmt::arg("volume", volume_),
fmt::arg("icon", getIcon(volume_)))); fmt::arg("icon", getIcon(volume_, getPortIcon()))));
label_.set_tooltip_text(desc_); label_.set_tooltip_text(desc_);
} }

View File

@ -48,7 +48,7 @@ int waybar::modules::sway::Ipc::open(const std::string& socketPath) const
addr.sun_path[sizeof(addr.sun_path) - 1] = 0; addr.sun_path[sizeof(addr.sun_path) - 1] = 0;
int l = sizeof(struct sockaddr_un); int l = sizeof(struct sockaddr_un);
if (::connect(fd, reinterpret_cast<struct sockaddr *>(&addr), l) == -1) { if (::connect(fd, reinterpret_cast<struct sockaddr *>(&addr), l) == -1) {
throw std::runtime_error("Unable to connect to " + socketPath); throw std::runtime_error("Unable to connect to Sway");
} }
return fd; return fd;
} }

View File

@ -78,6 +78,8 @@ auto waybar::modules::sway::Workspaces::update() -> void
if (needReorder) { if (needReorder) {
box_.reorder_child(button, node["num"].asInt()); box_.reorder_child(button, node["num"].asInt());
} }
auto icon = getIcon(node["name"].asString(), node);
button.set_label(icon);
button.show(); button.show();
} }
} }
@ -88,7 +90,7 @@ auto waybar::modules::sway::Workspaces::update() -> void
void waybar::modules::sway::Workspaces::addWorkspace(Json::Value node) void waybar::modules::sway::Workspaces::addWorkspace(Json::Value node)
{ {
auto icon = getIcon(node["name"].asString()); auto icon = getIcon(node["name"].asString(), node);
auto pair = buttons_.emplace(node["num"].asInt(), icon); auto pair = buttons_.emplace(node["num"].asInt(), icon);
auto &button = pair.first->second; auto &button = pair.first->second;
if (icon != node["name"].asString()) { if (icon != node["name"].asString()) {
@ -123,13 +125,19 @@ void waybar::modules::sway::Workspaces::addWorkspace(Json::Value node)
button.show(); button.show();
} }
std::string waybar::modules::sway::Workspaces::getIcon(std::string name) std::string waybar::modules::sway::Workspaces::getIcon(std::string name,
Json::Value node)
{ {
if (config_["format-icons"][name]) { std::vector<std::string> keys = {
return config_["format-icons"][name].asString(); name, "urgent", "focused", "visible", "default"};
for (auto const& key : keys) {
if (key == "focused" || key == "visible" || key == "urgent") {
if (config_["format-icons"][key] && node[key].asBool()) {
return config_["format-icons"][key].asString();
}
} else if (config_["format-icons"][key]) {
return config_["format-icons"][key].asString();
} }
if (config_["format-icons"]["default"]) {
return config_["format-icons"]["default"].asString();
} }
return name; return name;
} }