Compare commits

...

49 Commits
0.6.6 ... 0.6.9

Author SHA1 Message Date
7f74de977c chore: 0.6.9 2019-06-14 10:27:41 +02:00
028b184f7b fix(workspaces): persistant class with empty outputs 2019-06-12 09:50:33 +02:00
564fdcb369 fix(custom): exit status 2019-06-11 22:09:47 +02:00
3c9b533997 fix(window): avoid hexpand 2019-06-11 17:57:17 +02:00
ec75be0bc3 fix(Tray): click behaviour 2019-06-11 17:53:16 +02:00
c2e9ed6091 feat(workspaces): add class to persistant workspaces 2019-06-11 14:08:48 +02:00
a37b4687ff Revert "refactor(window): we don't need to subscribe workspace events"
This reverts commit 648eecdd83.
2019-06-11 14:06:31 +02:00
ee29a35aa5 Update README.md 2019-06-11 13:55:35 +02:00
0be8e200ce adds the wl output name as a css class (#373)
adds the wl output name as a css class
2019-06-10 12:15:05 +02:00
46e5dd93d4 adds the wl output name as a css class
now you can have a custom styling for each bar
2019-06-08 11:04:34 -07:00
2ee4a51546 chore: 0.6.8 2019-06-08 18:33:17 +02:00
91996a85c1 Merge pull request #372 from rianadon/patch-1
Increase specificity of media stylings
2019-06-08 18:28:42 +02:00
460d25ac45 Increase specificity of media stylings
Because of CSS specificity rules, the `#custom-media` style will always override the `custom-spotify` and `custom-vlc` styles, so the background of the media element is always green rather than sometimes orange when VLC is running. I added `#custom-media` in front of each of the class selectors to increase their specificity so they take precedence.
2019-06-07 22:18:06 -07:00
648eecdd83 refactor(window): we don't need to subscribe workspace events 2019-06-07 15:08:33 +02:00
f04ff38567 Merge pull request #370 from toke/bugfix/upstream-369
Prevent zombie apocalypse by ignoring SIGCHLD
2019-06-06 12:07:03 +02:00
d20a586734 Prevent zombie apocalypse by ignoring SIGCHLD
Fixes Issue #369
2019-06-05 14:35:25 +02:00
1962caf144 refactor(window): gtk stuff in update method 2019-06-04 17:34:00 +02:00
9dbf057f58 fix(custom): hide on empty format 2019-06-03 09:50:35 +02:00
918146c16b style: prefer background-color property 2019-05-31 17:20:14 +02:00
0b01b35c76 refactor(pulseaudio): only watch changes 2019-05-31 16:21:01 +02:00
f3fb955d75 chore: 0.6.7 2019-05-31 12:15:01 +02:00
fcf2d18a01 refactor: destroy threads first 2019-05-29 17:53:22 +02:00
b05d4cd413 fix(network): retry around all getExternalInterface 2019-05-29 16:17:40 +02:00
9b89fc6470 refactor: disable bar scroll by default 2019-05-28 16:11:33 +02:00
c06725aa69 fix(network): better disconnect handler 2019-05-28 11:21:59 +02:00
5ae5821929 refactor(network): re-add MAX_RETRY in order to detect external interface 2019-05-28 11:08:48 +02:00
74e40432e5 fix(network): linked state 2019-05-28 09:58:48 +02:00
6e69af8967 refactor(custon): avoid useless logic 2019-05-27 00:08:16 +02:00
be2fa743eb refactor(custon): hide on empty text 2019-05-27 00:05:29 +02:00
5fdb122829 Create FUNDING.yml 2019-05-26 23:55:46 +02:00
6e73c6db61 refactor(network): remove last_ext_iface_ 2019-05-26 23:16:09 +02:00
253366baf4 refactor(network): remove useless assignment 2019-05-26 22:40:29 +02:00
ecec02c8be refactor(network): better events handler 2019-05-26 22:36:26 +02:00
070619fa34 revert: restore idle fix 2019-05-26 20:09:05 +02:00
d4ace4b4d8 fix(network): subscribe only wanted family 2019-05-26 20:06:27 +02:00
5fd92b3c28 fix(network): don't check IFF_UP 2019-05-26 19:53:10 +02:00
c0a39f34cd refactor(network): don't clear ipaddr 2019-05-25 18:02:36 +02:00
2a9fa1a4b9 refactor(bar): onRealize, onMap 2019-05-25 17:50:45 +02:00
07147878a9 refactor(network): code cleaning 2019-05-24 09:49:56 +02:00
ffadd5c1a7 refactor: avoid useless class vars 2019-05-24 09:49:09 +02:00
2b34f3a30f refactor: parse args before app creation 2019-05-23 10:13:49 +02:00
85d60f95c4 refactor(network): const methods 2019-05-22 22:20:50 +02:00
755d38d4d6 fix(custom): bad alloc 2019-05-22 19:46:56 +02:00
b673279a43 style: remove non wanted comment 2019-05-22 12:22:56 +02:00
9e1200ae32 refactor: also pass id to custom modules 2019-05-22 12:20:13 +02:00
e999cca7a6 style: don't specify included namespaces 2019-05-22 12:15:59 +02:00
d24d85bebf refactor: move label name and id to label contructor 2019-05-22 12:06:24 +02:00
97bd637f5d refactor(clock): avoid usless time_point_cast 2019-05-22 11:51:33 +02:00
23d4a811db refactor(clock): avoid usless duration_cast 2019-05-22 11:48:02 +02:00
40 changed files with 502 additions and 492 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
custom: https://paypal.me/ARouillard

View File

@ -2,7 +2,8 @@
> Highly customizable Wayland bar for Sway and Wlroots based compositors.<br>
> Available in Arch [community](https://www.archlinux.org/packages/community/x86_64/waybar/) or
[AUR](https://aur.archlinux.org/packages/waybar-git/) and [openSUSE](https://build.opensuse.org/package/show/X11:Wayland/waybar)
[AUR](https://aur.archlinux.org/packages/waybar-git/) and [openSUSE](https://build.opensuse.org/package/show/X11:Wayland/waybar)<br>
> *Waybar [examples](https://github.com/Alexays/Waybar/wiki/Examples)*
**Current features**
- Sway (Workspaces, Binding mode, Focused window name)
@ -42,6 +43,7 @@ $ waybar
gtkmm3
jsoncpp
libinput
libsigc++
fmt
wayland

View File

@ -10,7 +10,8 @@ namespace waybar {
class ALabel : public IModule {
public:
ALabel(const Json::Value &, const std::string &format, uint16_t interval = 0);
ALabel(const Json::Value &, const std::string &, const std::string &, const std::string &format,
uint16_t interval = 0);
virtual ~ALabel();
virtual auto update() -> void;
virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0);

View File

@ -52,6 +52,8 @@ class Bar {
void destroyOutput();
void onConfigure(GdkEventConfigure *ev);
void onRealize();
void onMap(GdkEventAny *ev);
void setMarginsAndZone(uint32_t height, uint32_t width);
auto setupWidgets() -> void;
void getModules(const Factory &, const std::string &);
@ -66,6 +68,7 @@ class Bar {
} margins_;
uint32_t width_ = 0;
uint32_t height_ = 1;
uint8_t anchor_;
Gtk::Box left_;
Gtk::Box center_;
Gtk::Box right_;

View File

@ -26,13 +26,14 @@ class Client {
private:
Client() = default;
void setupConfigs(const std::string &config, const std::string &style);
std::tuple<const std::string, const std::string> getConfigs(const std::string &config,
const std::string &style) const;
void bindInterfaces();
const std::string getValidPath(const std::vector<std::string> &paths);
const std::string getValidPath(const std::vector<std::string> &paths) const;
void handleOutput(std::unique_ptr<struct waybar_output> &output);
bool isValidOutput(const Json::Value &config, std::unique_ptr<struct waybar_output> &output);
auto setupConfig() -> void;
auto setupCss() -> void;
auto setupConfig(const std::string &config_file) -> void;
auto setupCss(const std::string &css_file) -> void;
std::unique_ptr<struct waybar_output> &getOutput(uint32_t wl_name);
std::vector<Json::Value> getOutputConfigs(std::unique_ptr<struct waybar_output> &output);
@ -46,8 +47,6 @@ class Client {
static void handleDescription(void *, struct zxdg_output_v1 *, const char *);
Json::Value config_;
std::string css_file_;
std::string config_file_;
Glib::RefPtr<Gtk::StyleContext> style_context_;
Glib::RefPtr<Gtk::CssProvider> css_provider_;
std::vector<std::unique_ptr<struct waybar_output>> outputs_;

View File

@ -47,7 +47,6 @@ class Backlight : public ALabel {
template <class ForwardIt, class Inserter>
static void enumerate_devices(ForwardIt first, ForwardIt last, Inserter inserter, udev *udev);
const std::string name_;
const std::string preferred_device_;
static constexpr int EPOLL_MAX_EVENTS = 16;
@ -57,6 +56,6 @@ class Backlight : public ALabel {
std::mutex udev_thread_mutex_;
std::vector<BacklightDev> devices_;
// thread must destruct before shared data
waybar::util::SleeperThread udev_thread_;
util::SleeperThread udev_thread_;
};
} // namespace waybar::modules

View File

@ -37,13 +37,14 @@ class Battery : public ALabel {
const std::tuple<uint8_t, float, std::string> getInfos() const;
const std::string formatTimeRemaining(float hoursRemaining);
util::SleeperThread thread_;
util::SleeperThread thread_timer_;
std::vector<fs::path> batteries_;
fs::path adapter_;
int fd_;
std::vector<int> wds_;
std::string old_status_;
util::SleeperThread thread_;
util::SleeperThread thread_timer_;
};
} // namespace waybar::modules

View File

@ -14,7 +14,7 @@ class Clock : public ALabel {
auto update() -> void;
private:
waybar::util::SleeperThread thread_;
util::SleeperThread thread_;
};
} // namespace waybar::modules

View File

@ -2,12 +2,12 @@
#include <fmt/format.h>
#include <sys/sysinfo.h>
#include <fstream>
#include <cstdint>
#include <fstream>
#include <numeric>
#include <vector>
#include <string>
#include <utility>
#include <vector>
#include "ALabel.hpp"
#include "util/sleeper_thread.hpp"
@ -26,7 +26,8 @@ class Cpu : public ALabel {
std::vector<std::tuple<size_t, size_t>> parseCpuinfo();
std::vector<std::tuple<size_t, size_t>> prev_times_;
waybar::util::SleeperThread thread_;
util::SleeperThread thread_;
};
} // namespace waybar::modules

View File

@ -12,7 +12,7 @@ namespace waybar::modules {
class Custom : public ALabel {
public:
Custom(const std::string&, const Json::Value&);
Custom(const std::string&, const std::string&, const Json::Value&);
~Custom();
auto update() -> void;
void refresh(int /*signal*/);
@ -31,11 +31,12 @@ class Custom : public ALabel {
std::string tooltip_;
std::vector<std::string> class_;
int percentage_;
waybar::util::SleeperThread thread_;
waybar::util::command::res output_;
waybar::util::JsonParser parser_;
FILE* fp_;
int pid_;
util::command::res output_;
util::JsonParser parser_;
util::SleeperThread thread_;
};
} // namespace waybar::modules

View File

@ -15,10 +15,12 @@ class Memory : public ALabel {
private:
static inline const std::string data_dir_ = "/proc/meminfo";
void parseMeminfo();
unsigned long memtotal_;
unsigned long memfree_;
void parseMeminfo();
waybar::util::SleeperThread thread_;
util::SleeperThread thread_;
};
} // namespace waybar::modules

View File

@ -30,24 +30,23 @@ class Network : public ALabel {
void worker();
void createInfoSocket();
void createEventSocket();
int getExternalInterface(int skip_idx = -1);
int getExternalInterface(int skip_idx = -1) const;
void getInterfaceAddress();
int netlinkRequest(void*, uint32_t, uint32_t groups = 0);
int netlinkResponse(void*, uint32_t, uint32_t groups = 0);
int netlinkRequest(void*, uint32_t, uint32_t groups = 0) const;
int netlinkResponse(void*, uint32_t, uint32_t groups = 0) const;
void parseEssid(struct nlattr**);
void parseSignal(struct nlattr**);
void parseFreq(struct nlattr**);
bool associatedOrJoined(struct nlattr**);
bool checkInterface(struct ifinfomsg* rtif, std::string name);
int getPreferredIface(int skip_idx = -1);
int getPreferredIface(int skip_idx = -1) const;
auto getInfo() -> void;
void checkNewInterface(struct ifinfomsg* rtif);
const std::string getNetworkState() const;
void clearIface();
bool wildcardMatch(const std::string& pattern, const std::string& text);
bool wildcardMatch(const std::string& pattern, const std::string& text) const;
waybar::util::SleeperThread thread_;
waybar::util::SleeperThread thread_timer_;
int ifid_;
int last_ext_iface_;
sa_family_t family_;
struct sockaddr_nl nladdr_ = {0};
struct nl_sock* sock_ = nullptr;
@ -60,15 +59,18 @@ class Network : public ALabel {
unsigned long long bandwidth_down_total_;
unsigned long long bandwidth_up_total_;
std::string state_;
std::string essid_;
std::string ifname_;
std::string ipaddr_;
std::string netmask_;
int cidr_;
bool linked_;
int32_t signal_strength_dbm_;
uint8_t signal_strength_;
uint32_t frequency_;
util::SleeperThread thread_;
util::SleeperThread thread_timer_;
};
} // namespace waybar::modules

View File

@ -5,8 +5,8 @@
#include "bar.hpp"
#include "client.hpp"
#include "modules/sway/ipc/client.hpp"
#include "util/sleeper_thread.hpp"
#include "util/json.hpp"
#include "util/sleeper_thread.hpp"
namespace waybar::modules::sway {
@ -20,10 +20,11 @@ class Mode : public ALabel, public sigc::trackable {
void onEvent(const struct Ipc::ipc_response&);
void worker();
waybar::util::SleeperThread thread_;
Ipc ipc_;
std::string mode_;
util::JsonParser parser_;
util::SleeperThread thread_;
Ipc ipc_;
};
} // namespace waybar::modules::sway

View File

@ -25,13 +25,16 @@ class Window : public ALabel, public sigc::trackable {
void getTree();
const Bar& bar_;
waybar::util::SleeperThread thread_;
Ipc ipc_;
std::mutex mutex_;
std::string window_;
int windowId_;
std::string app_id_;
std::string old_app_id_;
std::size_t app_nb_;
util::JsonParser parser_;
util::SleeperThread thread_;
Ipc ipc_;
};
} // namespace waybar::modules::sway

View File

@ -36,13 +36,14 @@ class Workspaces : public IModule, public sigc::trackable {
const Json::Value& config_;
std::vector<Json::Value> workspaces_;
std::vector<std::string> workspaces_order_;
waybar::util::SleeperThread thread_;
std::mutex mutex_;
Gtk::Box box_;
Ipc ipc_;
util::JsonParser parser_;
bool scrolling_;
std::unordered_map<std::string, Gtk::Button> buttons_;
util::SleeperThread thread_;
Ipc ipc_;
};
} // namespace waybar::modules::sway

View File

@ -18,7 +18,7 @@ class Temperature : public ALabel {
bool isCritical(uint16_t);
std::string file_path_;
waybar::util::SleeperThread thread_;
util::SleeperThread thread_;
};
} // namespace waybar::modules

View File

@ -33,7 +33,7 @@ inline int close(FILE* fp, pid_t pid) {
fclose(fp);
while (waitpid(pid, &stat, 0) == -1) {
if (errno != EINTR) {
stat = -1;
stat = 0;
break;
}
}
@ -90,6 +90,8 @@ inline int32_t forkExec(std::string cmd) {
setpgid(pid, pid);
execl("/bin/sh", "sh", "-c", cmd.c_str(), (char*)0);
exit(0);
} else {
signal(SIGCHLD,SIG_IGN);
}
return pid;

View File

@ -14,7 +14,10 @@ class SleeperThread {
SleeperThread(std::function<void()> func)
: thread_{[this, func] {
while (do_run_) func();
while (do_run_) {
signal_ = false;
func();
}
}} {}
SleeperThread& operator=(std::function<void()> func) {
@ -42,7 +45,10 @@ class SleeperThread {
}
auto wake_up() {
{
std::lock_guard<std::mutex> lck(mutex_);
signal_ = true;
}
condvar_.notify_all();
}

View File

@ -1,6 +1,6 @@
project(
'waybar', 'cpp', 'c',
version: '0.6.6',
version: '0.6.9',
license: 'MIT',
default_options : [
'cpp_std=c++17',

View File

@ -39,7 +39,7 @@ def on_metadata(player, metadata, manager):
track_info = '{artist} - {title}'.format(artist=player.get_artist(),
title=player.get_title())
if player.props.status != 'Playing':
if player.props.status != 'Playing' and track_info:
track_info = '' + track_info
write_output(track_info, player)

View File

@ -7,10 +7,10 @@
}
window#waybar {
background: rgba(43, 48, 59, 0.5);
background-color: rgba(43, 48, 59, 0.5);
border-bottom: 3px solid rgba(100, 114, 125, 0.5);
color: #ffffff;
transition-property: background, background-color;
transition-property: background-color;
transition-duration: .5s;
}
@ -20,10 +20,10 @@ window#waybar.hidden {
/*
window#waybar.empty {
background: transparent;
background-color: transparent;
}
window#waybar.solo {
background: #FFFFFF;
background-color: #FFFFFF;
}
*/
@ -39,13 +39,13 @@ window#waybar.chromium {
/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */
#workspaces button {
padding: 0 5px;
background: transparent;
background-color: transparent;
color: #ffffff;
border-bottom: 3px solid transparent;
}
#workspaces button.focused {
background: #64727D;
background-color: #64727D;
border-bottom: 3px solid #ffffff;
}
@ -54,7 +54,7 @@ window#waybar.chromium {
}
#mode {
background: #64727D;
background-color: #64727D;
border-bottom: 3px solid #ffffff;
}
@ -86,7 +86,7 @@ window#waybar.chromium {
}
#battery.critical:not(.charging) {
background: #f53c3c;
background-color: #f53c3c;
color: #ffffff;
animation-name: blink;
animation-duration: 0.5s;
@ -100,56 +100,56 @@ label:focus {
}
#cpu {
background: #2ecc71;
background-color: #2ecc71;
color: #000000;
}
#memory {
background: #9b59b6;
background-color: #9b59b6;
}
#backlight {
background: #90b1b1;
background-color: #90b1b1;
}
#network {
background: #2980b9;
background-color: #2980b9;
}
#network.disconnected {
background: #f53c3c;
background-color: #f53c3c;
}
#pulseaudio {
background: #f1c40f;
background-color: #f1c40f;
color: #000000;
}
#pulseaudio.muted {
background: #90b1b1;
background-color: #90b1b1;
color: #2a5c45;
}
#custom-media {
background: #66cc99;
background-color: #66cc99;
color: #2a5c45;
min-width: 100px;
}
.custom-spotify {
background: #66cc99;
#custom-media.custom-spotify {
background-color: #66cc99;
}
.custom-vlc {
background: #ffa000;
#custom-media.custom-vlc {
background-color: #ffa000;
}
#temperature {
background: #f0932b;
background-color: #f0932b;
}
#temperature.critical {
background: #eb4d4b;
background-color: #eb4d4b;
}
#tray {
@ -166,18 +166,18 @@ label:focus {
}
#mpd {
background: #66cc99;
background-color: #66cc99;
color: #2a5c45;
}
#mpd.disconnected {
background: #f53c3c;
background-color: #f53c3c;
}
#mpd.stopped {
background: #90b1b1;
background-color: #90b1b1;
}
#mpd.paused {
background: #51a37a;
background-color: #51a37a;
}

View File

@ -2,7 +2,8 @@
#include <fmt/format.h>
#include <util/command.hpp>
waybar::ALabel::ALabel(const Json::Value& config, const std::string& format, uint16_t interval)
waybar::ALabel::ALabel(const Json::Value& config, const std::string& name, const std::string& id,
const std::string& format, uint16_t interval)
: config_(config),
format_(config_["format"].isString() ? config_["format"].asString() : format),
interval_(config_["interval"] == "once"
@ -10,6 +11,10 @@ waybar::ALabel::ALabel(const Json::Value& config, const std::string& format, uin
: std::chrono::seconds(
config_["interval"].isUInt() ? config_["interval"].asUInt() : interval)),
default_format_(format_) {
label_.set_name(name);
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
event_box_.add(label_);
if (config_["max-length"].isUInt()) {
label_.set_max_width_chars(config_["max-length"].asUInt());
@ -64,8 +69,7 @@ bool waybar::ALabel::handleToggle(GdkEventButton* const& e) {
format = config_["on-click-forward"].asString();
}
if (!format.empty()) {
pid_.push_back(
waybar::util::command::forkExec(fmt::format(format, fmt::arg("arg", click_param))));
pid_.push_back(util::command::forkExec(fmt::format(format, fmt::arg("arg", click_param))));
}
if (config_["format-alt-click"].isUInt() && e->button == config_["format-alt-click"].asUInt()) {
alt_ = !alt_;
@ -101,9 +105,9 @@ bool waybar::ALabel::handleScroll(GdkEventScroll* e) {
}
}
if (direction_up && config_["on-scroll-up"].isString()) {
pid_.push_back(waybar::util::command::forkExec(config_["on-scroll-up"].asString()));
pid_.push_back(util::command::forkExec(config_["on-scroll-up"].asString()));
} else if (config_["on-scroll-down"].isString()) {
pid_.push_back(waybar::util::command::forkExec(config_["on-scroll-down"].asString()));
pid_.push_back(util::command::forkExec(config_["on-scroll-down"].asString()));
}
dp.emit();
return true;

View File

@ -9,6 +9,7 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
window{Gtk::WindowType::WINDOW_TOPLEVEL},
surface(nullptr),
layer_surface(nullptr),
anchor_(ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP),
left_(Gtk::ORIENTATION_HORIZONTAL, 0),
center_(Gtk::ORIENTATION_HORIZONTAL, 0),
right_(Gtk::ORIENTATION_HORIZONTAL, 0),
@ -16,46 +17,33 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
window.set_title("waybar");
window.set_name("waybar");
window.set_decorated(false);
window.get_style_context()->add_class(output->name);
if (config["position"] == "right" || config["position"] == "left") {
height_ = 0;
width_ = 1;
}
height_ = config["height"].isUInt() ? config["height"].asUInt() : height_;
width_ = config["width"].isUInt() ? config["width"].asUInt() : width_;
auto gtk_window = window.gobj();
auto gtk_widget = GTK_WIDGET(gtk_window);
gtk_widget_realize(gtk_widget);
auto gdk_window = window.get_window()->gobj();
gdk_wayland_window_set_use_custom_surface(gdk_window);
surface = gdk_wayland_window_get_wl_surface(gdk_window);
window.signal_realize().connect_notify(sigc::mem_fun(*this, &Bar::onRealize));
window.signal_map_event().connect_notify(sigc::mem_fun(*this, &Bar::onMap));
window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure));
window.set_size_request(width_, height_);
std::size_t layer =
config["layer"] == "top" ? ZWLR_LAYER_SHELL_V1_LAYER_TOP : ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
auto client = waybar::Client::inst();
layer_surface = zwlr_layer_shell_v1_get_layer_surface(
client->layer_shell, surface, output->output, layer, "waybar");
static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
.configure = layerSurfaceHandleConfigure,
.closed = layerSurfaceHandleClosed,
};
zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, this);
auto height = config["height"].isUInt() ? config["height"].asUInt() : height_;
auto width = config["width"].isUInt() ? config["width"].asUInt() : width_;
std::size_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
if (config["position"] == "bottom") {
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
anchor_ = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
} else if (config["position"] == "left") {
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
anchor_ = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
} else if (config["position"] == "right") {
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
anchor_ = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
}
if (anchor == ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM || anchor == ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
} else if (anchor == ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT ||
anchor == ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
if (anchor_ == ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM ||
anchor_ == ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP) {
anchor_ |= ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
} else if (anchor_ == ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT ||
anchor_ == ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT) {
anchor_ |= ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
left_ = Gtk::Box(Gtk::ORIENTATION_VERTICAL, 0);
center_ = Gtk::Box(Gtk::ORIENTATION_VERTICAL, 0);
right_ = Gtk::Box(Gtk::ORIENTATION_VERTICAL, 0);
@ -63,17 +51,71 @@ waybar::Bar::Bar(struct waybar_output* w_output, const Json::Value& w_config)
vertical = true;
}
zwlr_layer_surface_v1_set_anchor(layer_surface, anchor);
zwlr_layer_surface_v1_set_size(layer_surface, width, height);
setMarginsAndZone(height, width);
setupWidgets();
if (window.get_realized()) {
onRealize();
}
window.show_all();
}
void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
auto tmp_height = height_;
auto tmp_width = width_;
if (ev->height > static_cast<int>(height_)) {
// Default minimal value
if (height_ != 1) {
spdlog::warn(MIN_HEIGHT_MSG, height_, ev->height);
}
if (config["height"].isUInt()) {
spdlog::info(SIZE_DEFINED, "Height");
} else {
tmp_height = ev->height;
}
}
if (ev->width > static_cast<int>(width_)) {
// Default minimal value
if (width_ != 1) {
spdlog::warn(MIN_WIDTH_MSG, width_, ev->width);
}
if (config["width"].isUInt()) {
spdlog::info(SIZE_DEFINED, "Width");
} else {
tmp_width = ev->width;
}
}
if (tmp_width != width_ || tmp_height != height_) {
zwlr_layer_surface_v1_set_size(layer_surface, tmp_width, tmp_height);
}
}
void waybar::Bar::onRealize() {
auto gdk_window = window.get_window()->gobj();
gdk_wayland_window_set_use_custom_surface(gdk_window);
}
void waybar::Bar::onMap(GdkEventAny* ev) {
auto gdk_window = window.get_window()->gobj();
surface = gdk_wayland_window_get_wl_surface(gdk_window);
auto client = waybar::Client::inst();
auto layer =
config["layer"] == "top" ? ZWLR_LAYER_SHELL_V1_LAYER_TOP : ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
layer_surface = zwlr_layer_shell_v1_get_layer_surface(
client->layer_shell, surface, output->output, layer, "waybar");
zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface, false);
zwlr_layer_surface_v1_set_anchor(layer_surface, anchor_);
zwlr_layer_surface_v1_set_size(layer_surface, width_, height_);
setMarginsAndZone(height_, width_);
static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
.configure = layerSurfaceHandleConfigure,
.closed = layerSurfaceHandleClosed,
};
zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, this);
wl_surface_commit(surface);
wl_display_roundtrip(client->wl_display);
setupWidgets();
window.set_size_request(width_, height_);
window.signal_configure_event().connect_notify(sigc::mem_fun(*this, &Bar::onConfigure));
}
void waybar::Bar::setMarginsAndZone(uint32_t height, uint32_t width) {
@ -127,36 +169,6 @@ void waybar::Bar::setMarginsAndZone(uint32_t height, uint32_t width) {
zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, zone);
}
void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
auto tmp_height = height_;
auto tmp_width = width_;
if (ev->height > static_cast<int>(height_)) {
// Default minimal value
if (height_ != 1) {
spdlog::warn(MIN_HEIGHT_MSG, height_, ev->height);
}
if (config["height"].isUInt()) {
spdlog::info(SIZE_DEFINED, "Height");
} else {
tmp_height = ev->height;
}
}
if (ev->width > static_cast<int>(width_)) {
// Default minimal value
if (width_ != 1) {
spdlog::warn(MIN_WIDTH_MSG, width_, ev->width);
}
if (config["width"].isUInt()) {
spdlog::info(SIZE_DEFINED, "Width");
} else {
tmp_width = ev->width;
}
}
if (tmp_width != width_ || tmp_height != height_) {
zwlr_layer_surface_v1_set_size(layer_surface, tmp_width, tmp_height);
}
}
// Converting string to button code rn as to avoid doing it later
void waybar::Bar::setupAltFormatKeyForModule(const std::string& module_name) {
if (config.isMember(module_name)) {
@ -239,7 +251,10 @@ void waybar::Bar::layerSurfaceHandleConfigure(void* data, struct zwlr_layer_surf
void waybar::Bar::layerSurfaceHandleClosed(void* data, struct zwlr_layer_surface_v1* /*surface*/) {
auto o = static_cast<waybar::Bar*>(data);
if (o->layer_surface) {
zwlr_layer_surface_v1_destroy(o->layer_surface);
o->layer_surface = nullptr;
}
o->modules_left_.clear();
o->modules_center_.clear();
o->modules_right_.clear();
@ -313,5 +328,4 @@ auto waybar::Bar::setupWidgets() -> void {
for (auto const& module : modules_right_) {
right_.pack_end(*module, false, false, 0);
}
window.show_all();
}

View File

@ -1,7 +1,7 @@
#include "client.hpp"
#include <spdlog/spdlog.h>
#include <fstream>
#include <iostream>
#include <spdlog/spdlog.h>
#include "util/clara.hpp"
#include "util/json.hpp"
@ -10,7 +10,7 @@ waybar::Client *waybar::Client::inst() {
return c;
}
const std::string waybar::Client::getValidPath(const std::vector<std::string> &paths) {
const std::string waybar::Client::getValidPath(const std::vector<std::string> &paths) const {
wordexp_t p;
for (const std::string &path : paths) {
@ -172,8 +172,9 @@ void waybar::Client::handleDescription(void * /*data*/, struct zxdg_output_v1 *
// Nothing here
}
void waybar::Client::setupConfigs(const std::string &config, const std::string &style) {
config_file_ = config.empty() ? getValidPath({
std::tuple<const std::string, const std::string> waybar::Client::getConfigs(
const std::string &config, const std::string &style) const {
auto config_file = config.empty() ? getValidPath({
"$XDG_CONFIG_HOME/waybar/config",
"$HOME/.config/waybar/config",
"$HOME/waybar/config",
@ -181,7 +182,7 @@ void waybar::Client::setupConfigs(const std::string &config, const std::string &
"./resources/config",
})
: config;
css_file_ = style.empty() ? getValidPath({
auto css_file = style.empty() ? getValidPath({
"$XDG_CONFIG_HOME/waybar/style.css",
"$HOME/.config/waybar/style.css",
"$HOME/waybar/style.css",
@ -189,14 +190,15 @@ void waybar::Client::setupConfigs(const std::string &config, const std::string &
"./resources/style.css",
})
: style;
if (css_file_.empty() || config_file_.empty()) {
if (css_file.empty() || config_file.empty()) {
throw std::runtime_error("Missing required resources files");
}
spdlog::info("Resources files: {}, {}", config_file_, css_file_);
spdlog::info("Resources files: {}, {}", config_file, css_file);
return {config_file, css_file};
}
auto waybar::Client::setupConfig() -> void {
std::ifstream file(config_file_);
auto waybar::Client::setupConfig(const std::string &config_file) -> void {
std::ifstream file(config_file);
if (!file.is_open()) {
throw std::runtime_error("Can't open config file");
}
@ -205,12 +207,12 @@ auto waybar::Client::setupConfig() -> void {
config_ = parser.parse(str);
}
auto waybar::Client::setupCss() -> void {
auto waybar::Client::setupCss(const std::string &css_file) -> void {
css_provider_ = Gtk::CssProvider::create();
style_context_ = Gtk::StyleContext::create();
// Load our css file, wherever that may be hiding
if (!css_provider_->load_from_path(css_file_)) {
if (!css_provider_->load_from_path(css_file)) {
throw std::runtime_error("Can't open style file");
}
}
@ -229,15 +231,6 @@ void waybar::Client::bindInterfaces() {
}
int waybar::Client::main(int argc, char *argv[]) {
gtk_app = Gtk::Application::create(argc, argv, "fr.arouillard.waybar");
gdk_display = Gdk::Display::get_default();
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());
bool show_help = false;
bool show_version = false;
std::string config;
@ -268,9 +261,18 @@ int waybar::Client::main(int argc, char *argv[]) {
if (!log_level.empty()) {
spdlog::set_level(spdlog::level::from_str(log_level));
}
setupConfigs(config, style);
setupConfig();
setupCss();
gtk_app = Gtk::Application::create(argc, argv, "fr.arouillard.waybar");
gdk_display = Gdk::Display::get_default();
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 [config_file, css_file] = getConfigs(config, style);
setupConfig(config_file);
setupCss(css_file);
bindInterfaces();
gtk_app->hold();
gtk_app->run();

View File

@ -64,7 +64,7 @@ waybar::IModule* waybar::Factory::makeModule(const std::string& name) const {
return new waybar::modules::Temperature(id, config_[name]);
}
if (ref.compare(0, 7, "custom/") == 0 && ref.size() > 7) {
return new waybar::modules::Custom(ref.substr(7), config_[name]);
return new waybar::modules::Custom(ref.substr(7), id, config_[name]);
}
} catch (const std::exception& e) {
auto err = fmt::format("Disabling module \"{}\", {}", name, e.what());

View File

@ -88,12 +88,9 @@ int waybar::modules::Backlight::BacklightDev::get_max() const { return max_; }
void waybar::modules::Backlight::BacklightDev::set_max(int max) { max_ = max; }
waybar::modules::Backlight::Backlight(const std::string &name, const Json::Value &config)
: ALabel(config, "{percent}%", 2),
name_(name),
waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &config)
: ALabel(config, "backlight", id, "{percent}%", 2),
preferred_device_(config["device"].isString() ? config["device"].asString() : "") {
label_.set_name("backlight");
// Get initial state
{
std::unique_ptr<udev, UdevDeleter> udev_check{udev_new()};
@ -213,7 +210,8 @@ void waybar::modules::Backlight::upsert_device(ForwardIt first, ForwardIt last,
const char *name = udev_device_get_sysname(dev);
check_nn(name);
const char *actual_brightness_attr = strcmp(name, "amdgpu_bl0") == 0 ? "brightness" : "actual_brightness";
const char *actual_brightness_attr =
strcmp(name, "amdgpu_bl0") == 0 ? "brightness" : "actual_brightness";
const char *actual = udev_device_get_sysattr_value(dev, actual_brightness_attr);
check_nn(actual);

View File

@ -2,11 +2,7 @@
#include <spdlog/spdlog.h>
waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config)
: ALabel(config, "{capacity}%", 60) {
label_.set_name("battery");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
: ALabel(config, "battery", id, "{capacity}%", 60) {
getBatteries();
fd_ = inotify_init1(IN_CLOEXEC);
if (fd_ == -1) {

View File

@ -1,20 +1,13 @@
#include "modules/clock.hpp"
waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
: ALabel(config, "{:%H:%M}", 60) {
label_.set_name("clock");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
: ALabel(config, "clock", id, "{:%H:%M}", 60) {
thread_ = [this] {
dp.emit();
auto now = std::chrono::system_clock::now();
auto timeout = std::chrono::floor<std::chrono::seconds>(now + interval_);
auto time_s = std::chrono::time_point_cast<std::chrono::seconds>(timeout);
auto sub_m =
std::chrono::duration_cast<std::chrono::seconds>(time_s.time_since_epoch()).count() %
interval_.count();
thread_.sleep_until(timeout - std::chrono::seconds(sub_m));
auto diff = std::chrono::seconds(timeout.time_since_epoch().count() % interval_.count());
thread_.sleep_until(timeout - diff);
};
}

View File

@ -2,11 +2,7 @@
#include <numeric>
waybar::modules::Cpu::Cpu(const std::string& id, const Json::Value& config)
: ALabel(config, "{usage}%", 10) {
label_.set_name("cpu");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
: ALabel(config, "cpu", id, "{usage}%", 10) {
thread_ = [this] {
dp.emit();
thread_.sleep_for(interval_);

View File

@ -1,9 +1,9 @@
#include "modules/custom.hpp"
#include <spdlog/spdlog.h>
waybar::modules::Custom::Custom(const std::string& name, const Json::Value& config)
: ALabel(config, "{}"), name_(name), fp_(nullptr), pid_(-1) {
label_.set_name("custom-" + name_);
waybar::modules::Custom::Custom(const std::string& name, const std::string& id,
const Json::Value& config)
: ALabel(config, "custom-" + name, id, "{}"), name_(name), fp_(nullptr), pid_(-1) {
if (config_["exec"].isString()) {
if (interval_.count() > 0) {
delayWorker();
@ -25,14 +25,14 @@ void waybar::modules::Custom::delayWorker() {
thread_ = [this] {
bool can_update = true;
if (config_["exec-if"].isString()) {
auto res = waybar::util::command::exec(config_["exec-if"].asString());
auto res = util::command::exec(config_["exec-if"].asString());
if (res.exit_code != 0) {
can_update = false;
event_box_.hide();
}
}
if (can_update) {
output_ = waybar::util::command::exec(config_["exec"].asString());
output_ = util::command::exec(config_["exec"].asString());
dp.emit();
}
thread_.sleep_for(interval_);
@ -74,7 +74,7 @@ void waybar::modules::Custom::continuousWorker() {
};
}
void waybar::modules::Custom::refresh(int sig /*signal*/) {
void waybar::modules::Custom::refresh(int sig) {
if (sig == SIGRTMIN + config_["signal"].asInt()) {
thread_.wake_up();
}
@ -102,12 +102,14 @@ auto waybar::modules::Custom::update() -> void {
} else {
parseOutputRaw();
}
auto str = fmt::format(format_,
text_,
fmt::arg("alt", alt_),
fmt::arg("icon", getIcon(percentage_, alt_)),
fmt::arg("percentage", percentage_));
if (str.empty()) {
event_box_.hide();
} else {
label_.set_markup(str);
if (tooltipEnabled()) {
if (text_ == tooltip_) {
@ -123,10 +125,10 @@ auto waybar::modules::Custom::update() -> void {
for (auto const& c : class_) {
label_.get_style_context()->add_class(c);
}
event_box_.show();
}
}
}
void waybar::modules::Custom::parseOutputRaw() {
std::istringstream output(output_.out);

View File

@ -3,15 +3,11 @@
waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& bar,
const Json::Value& config)
: ALabel(config, "{status}"),
: ALabel(config, "idle_inhibitor", id, "{status}"),
bar_(bar),
status_("deactivated"),
idle_inhibitor_(nullptr),
pid_(-1) {
label_.set_name("idle_inhibitor");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
event_box_.add_events(Gdk::BUTTON_PRESS_MASK);
event_box_.signal_button_press_event().connect(
sigc::mem_fun(*this, &IdleInhibitor::handleToggle));

View File

@ -1,11 +1,7 @@
#include "modules/memory.hpp"
waybar::modules::Memory::Memory(const std::string& id, const Json::Value& config)
: ALabel(config, "{}%", 30) {
label_.set_name("memory");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
: ALabel(config, "memory", id, "{}%", 30) {
thread_ = [this] {
dp.emit();
thread_.sleep_for(interval_);
@ -20,7 +16,8 @@ auto waybar::modules::Memory::update() -> void {
auto available_ram_gigabytes = memfree_ / std::pow(1024, 2);
getState(used_ram_percentage);
label_.set_markup(fmt::format(format_, used_ram_percentage,
label_.set_markup(fmt::format(format_,
used_ram_percentage,
fmt::arg("percentage", used_ram_percentage),
fmt::arg("used", used_ram_gigabytes),
fmt::arg("avail", available_ram_gigabytes)));

View File

@ -4,7 +4,7 @@
#include <spdlog/spdlog.h>
waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config)
: ALabel(config, "{album} - {artist} - {title}", 5),
: ALabel(config, "mpd", id, "{album} - {artist} - {title}", 5),
module_name_(id.empty() ? "mpd" : "mpd#" + id),
server_(nullptr),
port_(config_["port"].isUInt() ? config["port"].asUInt() : 0),
@ -21,11 +21,6 @@ waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config)
spdlog::warn("{}: `timeout` configuration should be an unsigned int", module_name_);
}
label_.set_name("mpd");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
if (!config["server"].isNull()) {
if (!config_["server"].isString()) {
spdlog::warn("{}:`server` configuration should be a string", module_name_);

View File

@ -73,9 +73,8 @@ std::optional<unsigned long long> read_netstat(std::string_view category, std::s
} // namespace
waybar::modules::Network::Network(const std::string &id, const Json::Value &config)
: ALabel(config, "{ifname}", 60),
: ALabel(config, "network", id, "{ifname}", 60),
ifid_(-1),
last_ext_iface_(-1),
family_(config["family"] == "ipv6" ? AF_INET6 : AF_INET),
efd_(-1),
ev_fd_(-1),
@ -83,11 +82,6 @@ waybar::modules::Network::Network(const std::string &id, const Json::Value &conf
signal_strength_dbm_(0),
signal_strength_(0),
frequency_(0) {
label_.set_name("network");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
auto down_octets = read_netstat(BANDWIDTH_CATEGORY, BANDWIDTH_DOWN_TOTAL_KEY);
auto up_octets = read_netstat(BANDWIDTH_CATEGORY, BANDWIDTH_UP_TOTAL_KEY);
if (down_octets) {
@ -102,10 +96,11 @@ waybar::modules::Network::Network(const std::string &id, const Json::Value &conf
bandwidth_up_total_ = 0;
}
createInfoSocket();
createEventSocket();
createInfoSocket();
auto default_iface = getPreferredIface();
if (default_iface != -1) {
ifid_ = default_iface;
char ifname[IF_NAMESIZE];
if_indextoname(default_iface, ifname);
ifname_ = ifname;
@ -126,8 +121,11 @@ waybar::modules::Network::~Network() {
}
if (ev_sock_ != nullptr) {
nl_socket_drop_membership(ev_sock_, RTNLGRP_LINK);
if (family_ == AF_INET) {
nl_socket_drop_membership(ev_sock_, RTNLGRP_IPV4_IFADDR);
} else {
nl_socket_drop_membership(ev_sock_, RTNLGRP_IPV6_IFADDR);
}
nl_close(ev_sock_);
nl_socket_free(ev_sock_);
}
@ -137,17 +135,21 @@ waybar::modules::Network::~Network() {
}
}
void waybar::modules::Network::createInfoSocket() {
void waybar::modules::Network::createEventSocket() {
ev_sock_ = nl_socket_alloc();
nl_socket_disable_seq_check(ev_sock_);
nl_socket_modify_cb(ev_sock_, NL_CB_VALID, NL_CB_CUSTOM, handleEvents, this);
nl_join_groups(ev_sock_, RTMGRP_LINK);
auto groups = RTMGRP_LINK | (family_ == AF_INET ? RTMGRP_IPV4_IFADDR : RTMGRP_IPV6_IFADDR);
nl_join_groups(ev_sock_, groups); // Deprecated
if (nl_connect(ev_sock_, NETLINK_ROUTE) != 0) {
throw std::runtime_error("Can't connect network socket");
}
nl_socket_add_membership(ev_sock_, RTNLGRP_LINK);
if (family_ == AF_INET) {
nl_socket_add_membership(ev_sock_, RTNLGRP_IPV4_IFADDR);
} else {
nl_socket_add_membership(ev_sock_, RTNLGRP_IPV6_IFADDR);
}
efd_ = epoll_create1(EPOLL_CLOEXEC);
if (efd_ < 0) {
throw std::runtime_error("Can't create epoll");
@ -174,7 +176,7 @@ void waybar::modules::Network::createInfoSocket() {
}
}
void waybar::modules::Network::createEventSocket() {
void waybar::modules::Network::createInfoSocket() {
sock_ = nl_socket_alloc();
if (genl_connect(sock_) != 0) {
throw std::runtime_error("Can't connect to netlink socket");
@ -204,9 +206,7 @@ void waybar::modules::Network::worker() {
int ec = epoll_wait(efd_, events.data(), EPOLL_MAX, -1);
if (ec > 0) {
for (auto i = 0; i < ec; i++) {
if (events[i].data.fd == nl_socket_get_fd(ev_sock_)) {
nl_recvmsgs_default(ev_sock_);
} else {
if (events[i].data.fd != nl_socket_get_fd(ev_sock_) || nl_recvmsgs_default(ev_sock_) < 0) {
thread_.stop();
break;
}
@ -215,10 +215,16 @@ void waybar::modules::Network::worker() {
};
}
const std::string waybar::modules::Network::getNetworkState() const {
if (ifid_ == -1) return "disconnected";
if (ipaddr_.empty()) return "linked";
if (essid_.empty()) return "ethernet";
return "wifi";
}
auto waybar::modules::Network::update() -> void {
std::string connectiontype;
std::string tooltip_format;
std::lock_guard<std::mutex> lock(mutex_);
std::string tooltip_format;
auto down_octets = read_netstat(BANDWIDTH_CATEGORY, BANDWIDTH_DOWN_TOTAL_KEY);
auto up_octets = read_netstat(BANDWIDTH_CATEGORY, BANDWIDTH_UP_TOTAL_KEY);
@ -233,45 +239,22 @@ auto waybar::modules::Network::update() -> void {
bandwidth_up = *up_octets - bandwidth_up_total_;
bandwidth_up_total_ = *up_octets;
}
if (ifid_ <= 0 || !linked_) {
if (config_["format-disconnected"].isString()) {
default_format_ = config_["format-disconnected"].asString();
}
if (config_["tooltip-format-disconnected"].isString()) {
tooltip_format = config_["tooltip-format-disconnected"].asString();
}
label_.get_style_context()->add_class("disconnected");
connectiontype = "disconnected";
} else {
if (essid_.empty()) {
if (config_["format-ethernet"].isString()) {
default_format_ = config_["format-ethernet"].asString();
}
if (config_["tooltip-format-ethernet"].isString()) {
tooltip_format = config_["tooltip-format-ethernet"].asString();
}
connectiontype = "ethernet";
} else if (ipaddr_.empty()) {
if (config_["format-linked"].isString()) {
default_format_ = config_["format-linked"].asString();
}
if (config_["tooltip-format-linked"].isString()) {
tooltip_format = config_["tooltip-format-linked"].asString();
}
connectiontype = "linked";
} else {
if (config_["format-wifi"].isString()) {
default_format_ = config_["format-wifi"].asString();
}
if (config_["tooltip-format-wifi"].isString()) {
tooltip_format = config_["tooltip-format-wifi"].asString();
}
connectiontype = "wifi";
}
label_.get_style_context()->remove_class("disconnected");
}
if (!alt_) {
auto state = getNetworkState();
if (!state_.empty() && label_.get_style_context()->has_class(state_)) {
label_.get_style_context()->remove_class(state_);
}
if (config_["format-" + state].isString()) {
default_format_ = config_["format-" + state].asString();
}
if (config_["tooltip-format-" + state].isString()) {
tooltip_format = config_["tooltip-format-" + state].asString();
}
if (!label_.get_style_context()->has_class(state)) {
label_.get_style_context()->add_class(state);
}
format_ = default_format_;
state_ = state;
}
getState(signal_strength_);
@ -305,7 +288,7 @@ auto waybar::modules::Network::update() -> void {
fmt::arg("ipaddr", ipaddr_),
fmt::arg("cidr", cidr_),
fmt::arg("frequency", frequency_),
fmt::arg("icon", getIcon(signal_strength_, connectiontype)),
fmt::arg("icon", getIcon(signal_strength_, state_)),
fmt::arg("bandwidthDownBits", pow_format(bandwidth_down * 8ull / interval_.count(), "b/s")),
fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / interval_.count(), "b/s")),
fmt::arg("bandwidthDownOctets", pow_format(bandwidth_down / interval_.count(), "o/s")),
@ -328,7 +311,7 @@ auto waybar::modules::Network::update() -> void {
fmt::arg("ipaddr", ipaddr_),
fmt::arg("cidr", cidr_),
fmt::arg("frequency", frequency_),
fmt::arg("icon", getIcon(signal_strength_, connectiontype)),
fmt::arg("icon", getIcon(signal_strength_, state_)),
fmt::arg("bandwidthDownBits",
pow_format(bandwidth_down * 8ull / interval_.count(), "b/s")),
fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / interval_.count(), "b/s")),
@ -344,7 +327,7 @@ auto waybar::modules::Network::update() -> void {
}
// Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
int waybar::modules::Network::getExternalInterface(int skip_idx) {
int waybar::modules::Network::getExternalInterface(int skip_idx) const {
static const uint32_t route_buffer_size = 8192;
struct nlmsghdr * hdr = nullptr;
struct rtmsg * rt = nullptr;
@ -462,22 +445,19 @@ int waybar::modules::Network::getExternalInterface(int skip_idx) {
} while (true);
out:
last_ext_iface_ = ifidx;
return ifidx;
}
void waybar::modules::Network::getInterfaceAddress() {
unsigned int cidrRaw;
struct ifaddrs *ifaddr, *ifa;
ipaddr_.clear();
netmask_.clear();
cidr_ = 0;
int success = getifaddrs(&ifaddr);
if (success != 0) {
return;
}
ifa = ifaddr;
while (ifa != nullptr && ipaddr_.empty() && netmask_.empty()) {
while (ifa != nullptr) {
if (ifa->ifa_addr != nullptr && ifa->ifa_addr->sa_family == family_ &&
ifa->ifa_name == ifname_) {
char ipaddr[INET6_ADDRSTRLEN];
@ -489,20 +469,20 @@ void waybar::modules::Network::getInterfaceAddress() {
auto net_addr = reinterpret_cast<struct sockaddr_in *>(ifa->ifa_netmask);
netmask_ = inet_ntop(family_, &net_addr->sin_addr, netmask, INET6_ADDRSTRLEN);
cidrRaw = net_addr->sin_addr.s_addr;
linked_ = ifa->ifa_flags & IFF_RUNNING;
unsigned int cidr = 0;
while (cidrRaw) {
cidr += cidrRaw & 1;
cidrRaw >>= 1;
}
cidr_ = cidr;
break;
}
ifa = ifa->ifa_next;
}
freeifaddrs(ifaddr);
}
int waybar::modules::Network::netlinkRequest(void *req, uint32_t reqlen, uint32_t groups) {
int waybar::modules::Network::netlinkRequest(void *req, uint32_t reqlen, uint32_t groups) const {
struct sockaddr_nl sa = {};
sa.nl_family = AF_NETLINK;
sa.nl_groups = groups;
@ -516,7 +496,7 @@ int waybar::modules::Network::netlinkRequest(void *req, uint32_t reqlen, uint32_
return sendmsg(nl_socket_get_fd(ev_sock_), &msg, 0);
}
int waybar::modules::Network::netlinkResponse(void *resp, uint32_t resplen, uint32_t groups) {
int waybar::modules::Network::netlinkResponse(void *resp, uint32_t resplen, uint32_t groups) const {
struct sockaddr_nl sa = {};
sa.nl_family = AF_NETLINK;
sa.nl_groups = groups;
@ -539,20 +519,23 @@ bool waybar::modules::Network::checkInterface(struct ifinfomsg *rtif, std::strin
return config_["interface"].asString() == name ||
wildcardMatch(config_["interface"].asString(), name);
}
// getExternalInterface may need some delay to detect external interface
for (uint8_t tries = 0; tries < MAX_RETRY; tries += 1) {
auto external_iface = getExternalInterface();
if (external_iface == -1) {
// Try with lastest working external iface
return last_ext_iface_ == rtif->ifi_index;
}
if (external_iface > 0) {
return external_iface == rtif->ifi_index;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
return false;
}
int waybar::modules::Network::getPreferredIface(int skip_idx) {
int waybar::modules::Network::getPreferredIface(int skip_idx) const {
int ifid = -1;
if (config_["interface"].isString()) {
ifid_ = if_nametoindex(config_["interface"].asCString());
if (ifid_ > 0) {
ifname_ = config_["interface"].asString();
return ifid_;
ifid = if_nametoindex(config_["interface"].asCString());
if (ifid > 0) {
return ifid;
} else {
// Try with wildcard
struct ifaddrs *ifaddr, *ifa;
@ -561,24 +544,26 @@ int waybar::modules::Network::getPreferredIface(int skip_idx) {
return -1;
}
ifa = ifaddr;
ifid_ = -1;
ifid = -1;
while (ifa != nullptr) {
if (wildcardMatch(config_["interface"].asString(), ifa->ifa_name)) {
ifid_ = if_nametoindex(ifa->ifa_name);
if (ifa->ifa_addr->sa_family == family_ &&
wildcardMatch(config_["interface"].asString(), ifa->ifa_name)) {
ifid = if_nametoindex(ifa->ifa_name);
break;
}
ifa = ifa->ifa_next;
}
freeifaddrs(ifaddr);
return ifid_;
return ifid;
}
}
ifid_ = getExternalInterface(skip_idx);
if (ifid_ > 0) {
char ifname[IF_NAMESIZE];
if_indextoname(ifid_, ifname);
ifname_ = ifname;
return ifid_;
// getExternalInterface may need some delay to detect external interface
for (uint8_t tries = 0; tries < MAX_RETRY; tries += 1) {
ifid = getExternalInterface(skip_idx);
if (ifid > 0) {
return ifid;
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
}
return -1;
}
@ -591,64 +576,80 @@ void waybar::modules::Network::clearIface() {
signal_strength_dbm_ = 0;
signal_strength_ = 0;
frequency_ = 0;
linked_ = false;
}
void waybar::modules::Network::checkNewInterface(struct ifinfomsg *rtif) {
auto new_iface = getPreferredIface(rtif->ifi_index);
if (new_iface != -1) {
ifid_ = new_iface;
char ifname[IF_NAMESIZE];
if_indextoname(new_iface, ifname);
ifname_ = ifname;
getInterfaceAddress();
thread_timer_.wake_up();
} else {
ifid_ = -1;
dp.emit();
}
}
int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
auto net = static_cast<waybar::modules::Network *>(data);
auto nh = nlmsg_hdr(msg);
std::lock_guard<std::mutex> lock(net->mutex_);
if (nh->nlmsg_type == RTM_NEWADDR) {
auto rtif = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
char ifname[IF_NAMESIZE];
if_indextoname(rtif->ifi_index, ifname);
// Auto detected network can also be assigned here
if ((net->ifid_ == -1 || rtif->ifi_index != net->ifid_) && net->checkInterface(rtif, ifname)) {
// If iface is different, clear data
if (rtif->ifi_index != net->ifid_) {
net->clearIface();
}
net->linked_ = true;
net->ifname_ = ifname;
net->ifid_ = rtif->ifi_index;
}
auto nh = nlmsg_hdr(msg);
auto ifi = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
if (nh->nlmsg_type == RTM_DELADDR) {
// Check for valid interface
if (rtif->ifi_index == net->ifid_) {
net->linked_ = true;
// Get Iface and WIFI info
net->getInterfaceAddress();
net->thread_timer_.wake_up();
}
} else if (nh->nlmsg_type == RTM_DELADDR) {
auto rtif = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
// Check for valid interface
if (rtif->ifi_index == net->ifid_) {
if (ifi->ifi_index == net->ifid_) {
net->ipaddr_.clear();
net->netmask_.clear();
net->cidr_ = 0;
net->dp.emit();
}
} else if (nh->nlmsg_type < RTM_NEWADDR) {
auto rtif = static_cast<struct ifinfomsg *>(NLMSG_DATA(nh));
char ifname[IF_NAMESIZE];
if_indextoname(rtif->ifi_index, ifname);
// Check for valid interface
if (rtif->ifi_flags & IFF_RUNNING && net->checkInterface(rtif, ifname)) {
net->linked_ = true;
net->ifname_ = ifname;
net->ifid_ = rtif->ifi_index;
net->dp.emit();
} else if (rtif->ifi_index == net->ifid_) {
if (!(ifi->ifi_flags & IFF_RUNNING)) {
net->clearIface();
// Check for a new interface and get info
auto new_iface = net->getPreferredIface(rtif->ifi_index);
if (new_iface != -1) {
net->getInterfaceAddress();
net->thread_timer_.wake_up();
net->checkNewInterface(ifi);
} else {
net->dp.emit();
}
return NL_OK;
}
} else if (nh->nlmsg_type == RTM_NEWLINK || nh->nlmsg_type == RTM_DELLINK) {
char ifname[IF_NAMESIZE];
if_indextoname(ifi->ifi_index, ifname);
// Check for valid interface
if (ifi->ifi_index != net->ifid_ && net->checkInterface(ifi, ifname)) {
net->ifname_ = ifname;
net->ifid_ = ifi->ifi_index;
// Get Iface and WIFI info
net->getInterfaceAddress();
net->thread_timer_.wake_up();
return NL_OK;
} else if (ifi->ifi_index == net->ifid_ &&
(!(ifi->ifi_flags & IFF_RUNNING) || !(ifi->ifi_flags & IFF_UP) ||
!net->checkInterface(ifi, ifname))) {
net->clearIface();
// Check for a new interface and get info
net->checkNewInterface(ifi);
return NL_OK;
}
} else {
char ifname[IF_NAMESIZE];
if_indextoname(ifi->ifi_index, ifname);
// Auto detected network can also be assigned here
if (ifi->ifi_index != net->ifid_ && net->checkInterface(ifi, ifname)) {
// If iface is different, clear data
if (ifi->ifi_index != net->ifid_) {
net->clearIface();
}
net->ifname_ = ifname;
net->ifid_ = ifi->ifi_index;
}
// Check for valid interface
if (ifi->ifi_index == net->ifid_) {
// Get Iface and WIFI info
net->getInterfaceAddress();
net->thread_timer_.wake_up();
return NL_OK;
}
}
return NL_SKIP;
@ -686,11 +687,10 @@ int waybar::modules::Network::handleScan(struct nl_msg *msg, void *data) {
net->parseEssid(bss);
net->parseSignal(bss);
net->parseFreq(bss);
return NL_SKIP;
return NL_OK;
}
void waybar::modules::Network::parseEssid(struct nlattr **bss) {
essid_.clear();
if (bss[NL80211_BSS_INFORMATION_ELEMENTS] != nullptr) {
auto ies = static_cast<char *>(nla_data(bss[NL80211_BSS_INFORMATION_ELEMENTS]));
auto ies_len = nla_len(bss[NL80211_BSS_INFORMATION_ELEMENTS]);
@ -763,7 +763,8 @@ auto waybar::modules::Network::getInfo() -> void {
}
// https://gist.github.com/rressi/92af77630faf055934c723ce93ae2495
bool waybar::modules::Network::wildcardMatch(const std::string &pattern, const std::string &text) {
bool waybar::modules::Network::wildcardMatch(const std::string &pattern,
const std::string &text) const {
auto P = int(pattern.size());
auto T = int(text.size());

View File

@ -1,7 +1,7 @@
#include "modules/pulseaudio.hpp"
waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value &config)
: ALabel(config, "{volume}%"),
: ALabel(config, "pulseaudio", id, "{volume}%"),
mainloop_(nullptr),
mainloop_api_(nullptr),
context_(nullptr),
@ -12,10 +12,6 @@ waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value
source_idx_(0),
source_volume_(0),
source_muted_(false) {
label_.set_name("pulseaudio");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
mainloop_ = pa_threaded_mainloop_new();
if (mainloop_ == nullptr) {
throw std::runtime_error("pa_mainloop_new() failed.");
@ -132,6 +128,10 @@ void waybar::modules::Pulseaudio::subscribeCb(pa_context * conte
pa_subscription_event_type_t type, uint32_t idx,
void *data) {
unsigned facility = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
unsigned operation = type & PA_SUBSCRIPTION_EVENT_TYPE_MASK;
if (operation != PA_SUBSCRIPTION_EVENT_CHANGE) {
return;
}
if (facility == PA_SUBSCRIPTION_EVENT_SINK) {
pa_context_get_sink_info_by_index(context, idx, sinkInfoCb, data);
} else if (facility == PA_SUBSCRIPTION_EVENT_SOURCE) {

View File

@ -1,6 +1,6 @@
#include "modules/sni/item.hpp"
#include <glibmm/main.h>
#include <spdlog/spdlog.h>
#include "modules/sni/item.hpp"
template <>
struct fmt::formatter<Glib::ustring> : formatter<std::string> {
@ -334,7 +334,7 @@ void Item::makeMenu(GdkEventButton* const& ev) {
bool Item::handleClick(GdkEventButton* const& ev) {
auto parameters = Glib::VariantContainerBase::create_tuple(
{Glib::Variant<int>::create(ev->x), Glib::Variant<int>::create(ev->y)});
if ((ev->button == 1 && item_is_menu) || ev->button == 3) {
if ((ev->button == 1 && (item_is_menu || !menu.empty())) || ev->button == 3) {
makeMenu(ev);
if (gtk_menu != nullptr) {
#if GTK_CHECK_VERSION(3, 22, 0)

View File

@ -3,11 +3,7 @@
namespace waybar::modules::sway {
Mode::Mode(const std::string& id, const Json::Value& config) : ALabel(config, "{}") {
label_.set_name("mode");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
Mode::Mode(const std::string& id, const Json::Value& config) : ALabel(config, "mode", id, "{}") {
ipc_.subscribe(R"(["mode"])");
ipc_.signal_event.connect(sigc::mem_fun(*this, &Mode::onEvent));
// Launch worker

View File

@ -4,13 +4,8 @@
namespace waybar::modules::sway {
Window::Window(const std::string& id, const Bar& bar, const Json::Value& config)
: ALabel(config, "{}"), bar_(bar), windowId_(-1) {
label_.set_name("window");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
: ALabel(config, "window", id, "{}"), bar_(bar), windowId_(-1) {
if (label_.get_max_width_chars() == -1) {
label_.set_hexpand(true);
label_.set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END);
}
ipc_.subscribe(R"(["window","workspace"])");
@ -28,33 +23,8 @@ void Window::onCmd(const struct Ipc::ipc_response& res) {
try {
std::lock_guard<std::mutex> lock(mutex_);
auto payload = parser_.parse(res.payload);
auto [nb, id, name, app_id] = getFocusedNode(payload);
if (!app_id_.empty()) {
bar_.window.get_style_context()->remove_class(app_id_);
}
if (nb == 0) {
bar_.window.get_style_context()->remove_class("solo");
if (!bar_.window.get_style_context()->has_class("empty")) {
bar_.window.get_style_context()->add_class("empty");
}
} else if (nb == 1) {
bar_.window.get_style_context()->remove_class("empty");
if (!bar_.window.get_style_context()->has_class("solo")) {
bar_.window.get_style_context()->add_class("solo");
}
if (!app_id.empty() && !bar_.window.get_style_context()->has_class(app_id)) {
bar_.window.get_style_context()->add_class(app_id);
}
} else {
bar_.window.get_style_context()->remove_class("solo");
bar_.window.get_style_context()->remove_class("empty");
}
app_id_ = app_id;
if (windowId_ != id || window_ != name) {
windowId_ = id;
window_ = name;
std::tie(app_nb_, windowId_, window_, app_id_) = getFocusedNode(payload);
dp.emit();
}
} catch (const std::exception& e) {
spdlog::error("Window: {}", e.what());
}
@ -71,6 +41,27 @@ void Window::worker() {
}
auto Window::update() -> void {
if (!old_app_id_.empty()) {
bar_.window.get_style_context()->remove_class(old_app_id_);
}
if (app_nb_ == 0) {
bar_.window.get_style_context()->remove_class("solo");
if (!bar_.window.get_style_context()->has_class("empty")) {
bar_.window.get_style_context()->add_class("empty");
}
} else if (app_nb_ == 1) {
bar_.window.get_style_context()->remove_class("empty");
if (!bar_.window.get_style_context()->has_class("solo")) {
bar_.window.get_style_context()->add_class("solo");
}
if (!app_id_.empty() && !bar_.window.get_style_context()->has_class(app_id_)) {
bar_.window.get_style_context()->add_class(app_id_);
old_app_id_ = app_id_;
}
} else {
bar_.window.get_style_context()->remove_class("solo");
bar_.window.get_style_context()->remove_class("empty");
}
label_.set_markup(fmt::format(format_, window_));
if (tooltipEnabled()) {
label_.set_tooltip_text(window_);

View File

@ -16,7 +16,7 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
ipc_.signal_event.connect(sigc::mem_fun(*this, &Workspaces::onEvent));
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd));
ipc_.sendCmd(IPC_GET_WORKSPACES);
if (!config["disable-bar-scroll"].asBool()) {
if (config["enable-bar-scroll"].asBool()) {
auto &window = const_cast<Bar &>(bar_).window;
window.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
window.signal_scroll_event().connect(sigc::mem_fun(*this, &Workspaces::handleScroll));
@ -80,6 +80,7 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
// Adding to all outputs
Json::Value v;
v["name"] = p_w_name;
v["target_output"] = "";
workspaces_.emplace_back(std::move(v));
}
}
@ -154,6 +155,11 @@ auto Workspaces::update() -> void {
} else {
button.get_style_context()->remove_class("urgent");
}
if ((*it)["target_output"].isString()) {
button.get_style_context()->add_class("persistant");
} else {
button.get_style_context()->remove_class("persistant");
}
if (needReorder) {
box_.reorder_child(button, it - workspaces_.begin());
}

View File

@ -1,7 +1,7 @@
#include "modules/temperature.hpp"
waybar::modules::Temperature::Temperature(const std::string& id, const Json::Value& config)
: ALabel(config, "{temperatureC}°C", 10) {
: ALabel(config, "temperature", id, "{temperatureC}°C", 10) {
if (config_["hwmon-path"].isString()) {
file_path_ = config_["hwmon-path"].asString();
} else {
@ -12,10 +12,6 @@ waybar::modules::Temperature::Temperature(const std::string& id, const Json::Val
if (!temp.is_open()) {
throw std::runtime_error("Can't open " + file_path_);
}
label_.set_name("temperature");
if (!id.empty()) {
label_.get_style_context()->add_class(id);
}
thread_ = [this] {
dp.emit();
thread_.sleep_for(interval_);