mirror of
https://github.com/rad4day/Waybar.git
synced 2023-12-21 10:22:59 +01:00
Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
bf5c00ff2a | |||
14ace24a26 | |||
2fa581c7ea | |||
6ff013e25b | |||
cf3cb4c61f | |||
00ada46dfc | |||
2db81a6107 | |||
3e76984ce7 | |||
48a58cd979 | |||
296b448d06 | |||
7a3febf6a7 | |||
bb4af295bc | |||
cf7663153d | |||
12a251c3a4 | |||
4accdd4524 | |||
032ad925af | |||
50bfe78aed | |||
afd291a566 | |||
316a9be656 | |||
cdb347aaca | |||
ed240ac105 | |||
232073ca17 | |||
5314b74dae | |||
e3879559a2 | |||
0ec8774a08 | |||
071b4928dc | |||
7c4d75d428 | |||
67593b8c0f | |||
cff39bc7cf | |||
f2edc8f965 | |||
7b11283b73 | |||
03e43fb31d | |||
913d0f7ad0 | |||
5feb478611 | |||
6bf64cd04d | |||
5e43b4f587 | |||
e8dd1e2d2c | |||
51be97f9aa | |||
a00f812cd1 | |||
863e0babd8 | |||
8ba3052dd1 | |||
1a76aa0c8c | |||
85f177a213 | |||
f743882baa | |||
9fa0eb7068 |
@ -17,4 +17,4 @@ script:
|
||||
- echo FROM alexays/waybar:${distro} > Dockerfile
|
||||
- echo ADD . /root >> Dockerfile
|
||||
- docker build -t waybar .
|
||||
- docker run waybar /bin/sh -c "cd /root && git clone --depth=1 https://github.com/swaywm/wlroots subprojects/wlroots && meson build && ninja -C build"
|
||||
- docker run waybar /bin/sh -c "cd /root && meson build && ninja -C build"
|
@ -38,13 +38,13 @@ class Bar {
|
||||
bool vertical = false;
|
||||
|
||||
private:
|
||||
static inline const std::string MIN_HEIGHT_MSG =
|
||||
static constexpr const char* MIN_HEIGHT_MSG =
|
||||
"Requested height: {} exceeds the minimum height: {} required by the modules";
|
||||
static inline const std::string MIN_WIDTH_MSG =
|
||||
static constexpr const char* MIN_WIDTH_MSG =
|
||||
"Requested width: {} exceeds the minimum width: {} required by the modules";
|
||||
static inline const std::string BAR_SIZE_MSG =
|
||||
static constexpr const char* BAR_SIZE_MSG =
|
||||
"Bar configured (width: {}, height: {}) for output: {}";
|
||||
static inline const std::string SIZE_DEFINED =
|
||||
static constexpr const char* SIZE_DEFINED =
|
||||
"{} size is defined in the config file so it will stay like that";
|
||||
static void layerSurfaceHandleConfigure(void *, struct zwlr_layer_surface_v1 *, uint32_t,
|
||||
uint32_t, uint32_t);
|
||||
|
@ -9,7 +9,8 @@
|
||||
#include <sys/inotify.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "ALabel.hpp"
|
||||
#include "util/sleeper_thread.hpp"
|
||||
|
||||
@ -32,8 +33,9 @@ class Battery : public ALabel {
|
||||
|
||||
void getBatteries();
|
||||
void worker();
|
||||
const std::string getAdapterStatus(uint8_t capacity, uint32_t current_now) const;
|
||||
const std::tuple<uint8_t, uint32_t, std::string> getInfos() const;
|
||||
const std::string getAdapterStatus(uint8_t capacity) const;
|
||||
const std::tuple<uint8_t, float, std::string> getInfos() const;
|
||||
const std::string formatTimeRemaining(float hoursRemaining);
|
||||
|
||||
util::SleeperThread thread_;
|
||||
util::SleeperThread thread_timer_;
|
||||
|
@ -3,9 +3,11 @@
|
||||
#include <fmt/format.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include "ALabel.hpp"
|
||||
#include "util/sleeper_thread.hpp"
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <csignal>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "ALabel.hpp"
|
||||
#include "util/command.hpp"
|
||||
#include "util/json.hpp"
|
||||
|
@ -30,7 +30,7 @@ class Network : public ALabel {
|
||||
void worker();
|
||||
void createInfoSocket();
|
||||
void createEventSocket();
|
||||
int getExternalInterface();
|
||||
int getExternalInterface(int skip_idx = -1);
|
||||
void getInterfaceAddress();
|
||||
int netlinkRequest(void*, uint32_t, uint32_t groups = 0);
|
||||
int netlinkResponse(void*, uint32_t, uint32_t groups = 0);
|
||||
@ -39,8 +39,9 @@ class Network : public ALabel {
|
||||
void parseFreq(struct nlattr**);
|
||||
bool associatedOrJoined(struct nlattr**);
|
||||
bool checkInterface(struct ifinfomsg *rtif, std::string name);
|
||||
int getPreferredIface();
|
||||
int getPreferredIface(int skip_idx = -1);
|
||||
auto getInfo() -> void;
|
||||
void clearIface();
|
||||
bool wildcardMatch(const std::string& pattern, const std::string& text);
|
||||
|
||||
waybar::util::SleeperThread thread_;
|
||||
|
@ -18,6 +18,7 @@ class Pulseaudio : public ALabel {
|
||||
static void subscribeCb(pa_context*, pa_subscription_event_type_t, uint32_t, void*);
|
||||
static void contextStateCb(pa_context*, void*);
|
||||
static void sinkInfoCb(pa_context*, const pa_sink_info*, int, void*);
|
||||
static void sourceInfoCb(pa_context*, const pa_source_info* i, int, void* data);
|
||||
static void serverInfoCb(pa_context*, const pa_server_info*, void*);
|
||||
static void volumeModifyCb(pa_context*, int, void*);
|
||||
bool handleVolume(GdkEventScroll* e);
|
||||
@ -27,14 +28,21 @@ class Pulseaudio : public ALabel {
|
||||
pa_threaded_mainloop* mainloop_;
|
||||
pa_mainloop_api* mainloop_api_;
|
||||
pa_context* context_;
|
||||
uint32_t sink_idx_{0};
|
||||
uint16_t volume_;
|
||||
pa_cvolume pa_volume_;
|
||||
bool muted_;
|
||||
std::string port_name_;
|
||||
std::string desc_;
|
||||
std::string monitor_;
|
||||
bool scrolling_;
|
||||
// SINK
|
||||
uint32_t sink_idx_{0};
|
||||
uint16_t volume_;
|
||||
pa_cvolume pa_volume_;
|
||||
bool muted_;
|
||||
std::string port_name_;
|
||||
std::string desc_;
|
||||
std::string monitor_;
|
||||
// SOURCE
|
||||
uint32_t source_idx_{0};
|
||||
uint16_t source_volume_;
|
||||
bool source_muted_;
|
||||
std::string source_port_name_;
|
||||
std::string source_desc_;
|
||||
};
|
||||
|
||||
} // namespace waybar::modules
|
||||
|
@ -8,7 +8,7 @@ namespace waybar::modules::SNI {
|
||||
|
||||
class Watcher {
|
||||
public:
|
||||
Watcher();
|
||||
Watcher(std::size_t id);
|
||||
~Watcher();
|
||||
|
||||
private:
|
||||
|
@ -35,6 +35,7 @@ class Workspaces : public IModule, public sigc::trackable {
|
||||
const Bar& bar_;
|
||||
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_;
|
||||
|
@ -1,6 +1,6 @@
|
||||
project(
|
||||
'waybar', 'cpp', 'c',
|
||||
version: '0.6.5',
|
||||
version: '0.6.6',
|
||||
license: 'MIT',
|
||||
default_options : [
|
||||
'cpp_std=c++17',
|
||||
@ -48,10 +48,10 @@ add_global_link_arguments(cpp_link_args, language : 'cpp')
|
||||
thread_dep = dependency('threads')
|
||||
libinput = dependency('libinput')
|
||||
fmt = dependency('fmt', version : ['>=5.3.0'], fallback : ['fmt', 'fmt_dep'])
|
||||
spdlog = dependency('spdlog', version : ['>=1.3.1'], fallback : ['spdlog', 'spdlog_dep'])
|
||||
wayland_client = dependency('wayland-client')
|
||||
wayland_cursor = dependency('wayland-cursor')
|
||||
wayland_protos = dependency('wayland-protocols')
|
||||
wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots'])
|
||||
gtkmm = dependency('gtkmm-3.0')
|
||||
dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk'))
|
||||
giounix = dependency('gio-unix-2.0', required: get_option('dbusmenu-gtk'))
|
||||
@ -125,10 +125,10 @@ executable(
|
||||
src_files,
|
||||
dependencies: [
|
||||
thread_dep,
|
||||
wlroots,
|
||||
client_protos,
|
||||
wayland_client,
|
||||
fmt,
|
||||
spdlog,
|
||||
sigcpp,
|
||||
jsoncpp,
|
||||
libinput,
|
||||
|
@ -96,6 +96,7 @@
|
||||
"format": "{capacity}% {icon}",
|
||||
"format-charging": "{capacity}% ",
|
||||
"format-plugged": "{capacity}% ",
|
||||
"format-alt": "{time} {icon}",
|
||||
// "format-good": "", // An empty format will hide the module
|
||||
// "format-full": "",
|
||||
"format-icons": ["", "", "", "", ""]
|
||||
@ -108,13 +109,16 @@
|
||||
"format-wifi": "{essid} ({signalStrength}%) ",
|
||||
"format-ethernet": "{ifname}: {ipaddr}/{cidr} ",
|
||||
"format-linked": "{ifname} (No IP) ",
|
||||
"format-disconnected": "Disconnected ⚠"
|
||||
"format-disconnected": "Disconnected ⚠",
|
||||
"format-alt": "{ifname}: {ipaddr}/{cidr}"
|
||||
},
|
||||
"pulseaudio": {
|
||||
// "scroll-step": 1, // %, can be a float
|
||||
"format": "{volume}% {icon}",
|
||||
"format-bluetooth": "{volume}% {icon}",
|
||||
"format-muted": "",
|
||||
"format": "{volume}% {icon} {format_source}",
|
||||
"format-bluetooth": "{volume}% {icon} {format_source}",
|
||||
"format-muted": " {format_source}",
|
||||
"format-source": "{volume}% ",
|
||||
"format-source-muted": "",
|
||||
"format-icons": {
|
||||
"headphones": "",
|
||||
"handsfree": "",
|
||||
|
20
src/bar.cpp
20
src/bar.cpp
@ -1,4 +1,5 @@
|
||||
#include "bar.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "client.hpp"
|
||||
#include "factory.hpp"
|
||||
|
||||
@ -114,7 +115,7 @@ void waybar::Bar::setMarginsAndZone(uint32_t height, uint32_t width) {
|
||||
.left = std::stoi(margins[3], nullptr, 10)};
|
||||
}
|
||||
} catch (...) {
|
||||
std::cerr << "Invalid margins: " + config["margin"].asString() << std::endl;
|
||||
spdlog::warn("Invalid margins: {}", config["margin"].asString());
|
||||
}
|
||||
} else if (config["margin"].isInt()) {
|
||||
auto gaps = config["margin"].asInt();
|
||||
@ -132,10 +133,10 @@ void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
|
||||
if (ev->height > static_cast<int>(height_)) {
|
||||
// Default minimal value
|
||||
if (height_ != 1) {
|
||||
std::cout << fmt::format(MIN_HEIGHT_MSG, height_, ev->height) << std::endl;
|
||||
spdlog::warn(MIN_HEIGHT_MSG, height_, ev->height);
|
||||
}
|
||||
if (config["height"].isUInt()) {
|
||||
std::cout << fmt::format(SIZE_DEFINED, "Height") << std::endl;
|
||||
spdlog::info(SIZE_DEFINED, "Height");
|
||||
} else {
|
||||
tmp_height = ev->height;
|
||||
}
|
||||
@ -143,10 +144,10 @@ void waybar::Bar::onConfigure(GdkEventConfigure* ev) {
|
||||
if (ev->width > static_cast<int>(width_)) {
|
||||
// Default minimal value
|
||||
if (width_ != 1) {
|
||||
std::cout << fmt::format(MIN_WIDTH_MSG, width_, ev->width) << std::endl;
|
||||
spdlog::warn(MIN_WIDTH_MSG, width_, ev->width);
|
||||
}
|
||||
if (config["width"].isUInt()) {
|
||||
std::cout << fmt::format(SIZE_DEFINED, "Width") << std::endl;
|
||||
spdlog::info(SIZE_DEFINED, "Width");
|
||||
} else {
|
||||
tmp_width = ev->width;
|
||||
}
|
||||
@ -227,11 +228,10 @@ void waybar::Bar::layerSurfaceHandleConfigure(void* data, struct zwlr_layer_surf
|
||||
o->window.resize(o->width_, o->height_);
|
||||
auto zone = o->vertical ? width + o->margins_.right : height + o->margins_.bottom;
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(o->layer_surface, zone);
|
||||
std::cout << fmt::format(BAR_SIZE_MSG,
|
||||
spdlog::info(BAR_SIZE_MSG,
|
||||
o->width_ == 1 ? "auto" : std::to_string(o->width_),
|
||||
o->height_ == 1 ? "auto" : std::to_string(o->height_),
|
||||
o->output->name)
|
||||
<< std::endl;
|
||||
o->output->name);
|
||||
wl_surface_commit(o->surface);
|
||||
}
|
||||
zwlr_layer_surface_v1_ack_configure(surface, serial);
|
||||
@ -277,12 +277,12 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos) {
|
||||
try {
|
||||
module->update();
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << name.asString() + ": " + e.what() << std::endl;
|
||||
spdlog::error("{}: {}", name.asString(), e.what());
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
spdlog::warn("module {}: {}", name.asString(), e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "client.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "util/clara.hpp"
|
||||
#include "util/json.hpp"
|
||||
|
||||
@ -55,7 +56,7 @@ void waybar::Client::handleGlobalRemove(void * data, struct wl_registry * /*re
|
||||
auto output_name = (*it)->output->name;
|
||||
(*it)->window.close();
|
||||
it = client->bars.erase(it);
|
||||
std::cout << "Bar removed from output: " + output_name << std::endl;
|
||||
spdlog::info("Bar removed from output: {}", output_name);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
@ -191,7 +192,7 @@ void waybar::Client::setupConfigs(const std::string &config, const std::string &
|
||||
if (css_file_.empty() || config_file_.empty()) {
|
||||
throw std::runtime_error("Missing required resources files");
|
||||
}
|
||||
std::cout << "Resources files: " + config_file_ + ", " + css_file_ << std::endl;
|
||||
spdlog::info("Resources files: {}, {}", config_file_, css_file_);
|
||||
}
|
||||
|
||||
auto waybar::Client::setupConfig() -> void {
|
||||
@ -242,14 +243,18 @@ int waybar::Client::main(int argc, char *argv[]) {
|
||||
std::string config;
|
||||
std::string style;
|
||||
std::string bar_id;
|
||||
std::string log_level;
|
||||
auto cli = clara::detail::Help(show_help) |
|
||||
clara::detail::Opt(show_version)["-v"]["--version"]("Show version") |
|
||||
clara::detail::Opt(config, "config")["-c"]["--config"]("Config path") |
|
||||
clara::detail::Opt(style, "style")["-s"]["--style"]("Style path") |
|
||||
clara::detail::Opt(
|
||||
log_level,
|
||||
"trace|debug|info|warning|error|critical|off")["-l"]["--log-level"]("Log level") |
|
||||
clara::detail::Opt(bar_id, "id")["-b"]["--bar"]("Bar id");
|
||||
auto res = cli.parse(clara::detail::Args(argc, argv));
|
||||
if (!res) {
|
||||
std::cerr << "Error in command line: " << res.errorMessage() << std::endl;
|
||||
spdlog::error("Error in command line: {}", res.errorMessage());
|
||||
return 1;
|
||||
}
|
||||
if (show_help) {
|
||||
@ -260,6 +265,9 @@ int waybar::Client::main(int argc, char *argv[]) {
|
||||
std::cout << "Waybar v" << VERSION << std::endl;
|
||||
return 0;
|
||||
}
|
||||
if (!log_level.empty()) {
|
||||
spdlog::set_level(spdlog::level::from_str(log_level));
|
||||
}
|
||||
setupConfigs(config, style);
|
||||
setupConfig();
|
||||
setupCss();
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <csignal>
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "client.hpp"
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
@ -23,10 +23,10 @@ int main(int argc, char* argv[]) {
|
||||
delete client;
|
||||
return ret;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
spdlog::error("{}", e.what());
|
||||
return 1;
|
||||
} catch (const Glib::Exception& e) {
|
||||
std::cerr << e.what().c_str() << std::endl;
|
||||
spdlog::error("{}", static_cast<std::string>(e.what()));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +213,9 @@ void waybar::modules::Backlight::upsert_device(ForwardIt first, ForwardIt last,
|
||||
const char *name = udev_device_get_sysname(dev);
|
||||
check_nn(name);
|
||||
|
||||
const char *actual = udev_device_get_sysattr_value(dev, "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);
|
||||
const int actual_int = std::stoi(actual);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "modules/battery.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "{capacity}%", 60) {
|
||||
@ -75,23 +76,34 @@ void waybar::modules::Battery::getBatteries() {
|
||||
}
|
||||
}
|
||||
|
||||
const std::tuple<uint8_t, uint32_t, std::string> waybar::modules::Battery::getInfos() const {
|
||||
const std::tuple<uint8_t, float, std::string> waybar::modules::Battery::getInfos() const {
|
||||
try {
|
||||
uint16_t total = 0;
|
||||
uint32_t total_current = 0;
|
||||
uint32_t total_power = 0; // μW
|
||||
uint32_t total_energy = 0; // μWh
|
||||
uint32_t total_energy_full = 0;
|
||||
std::string status = "Unknown";
|
||||
for (auto const& bat : batteries_) {
|
||||
uint16_t capacity;
|
||||
uint32_t current_now;
|
||||
uint32_t power_now;
|
||||
uint32_t energy_full;
|
||||
uint32_t energy_now;
|
||||
std::string _status;
|
||||
std::ifstream(bat / "capacity") >> capacity;
|
||||
std::ifstream(bat / "status") >> _status;
|
||||
std::ifstream(bat / "current_now") >> current_now;
|
||||
auto rate_path = fs::exists(bat / "current_now") ? "current_now" : "power_now";
|
||||
std::ifstream(bat / rate_path) >> power_now;
|
||||
auto now_path = fs::exists(bat / "charge_now") ? "charge_now" : "energy_now";
|
||||
std::ifstream(bat / now_path) >> energy_now;
|
||||
auto full_path = fs::exists(bat / "charge_full") ? "charge_full" : "energy_full";
|
||||
std::ifstream(bat / full_path) >> energy_full;
|
||||
if (_status != "Unknown") {
|
||||
status = _status;
|
||||
}
|
||||
total += capacity;
|
||||
total_current += current_now;
|
||||
total_power += power_now;
|
||||
total_energy += energy_now;
|
||||
total_energy_full += energy_full;
|
||||
}
|
||||
if (!adapter_.empty() && status == "Discharging") {
|
||||
bool online;
|
||||
@ -100,16 +112,21 @@ const std::tuple<uint8_t, uint32_t, std::string> waybar::modules::Battery::getIn
|
||||
status = "Plugged";
|
||||
}
|
||||
}
|
||||
float time_remaining = 0;
|
||||
if (status == "Discharging" && total_power != 0) {
|
||||
time_remaining = (float)total_energy / total_power;
|
||||
} else if (status == "Charging" && total_power != 0) {
|
||||
time_remaining = -(float)(total_energy_full - total_energy) / total_power;
|
||||
}
|
||||
uint16_t capacity = total / batteries_.size();
|
||||
return {capacity, total_current, status};
|
||||
return {capacity, time_remaining, status};
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
spdlog::error("Battery: {}", e.what());
|
||||
return {0, 0, "Unknown"};
|
||||
}
|
||||
}
|
||||
|
||||
const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity,
|
||||
uint32_t current_now) const {
|
||||
const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const {
|
||||
if (!adapter_.empty()) {
|
||||
bool online;
|
||||
std::ifstream(adapter_ / "online") >> online;
|
||||
@ -124,13 +141,27 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity,
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemaining) {
|
||||
hoursRemaining = std::fabs(hoursRemaining);
|
||||
uint16_t full_hours = static_cast<uint16_t>(hoursRemaining);
|
||||
uint16_t minutes = static_cast<uint16_t>(60 * (hoursRemaining - full_hours));
|
||||
return std::to_string(full_hours) + " h " + std::to_string(minutes) + " min";
|
||||
}
|
||||
|
||||
auto waybar::modules::Battery::update() -> void {
|
||||
auto [capacity, current_now, status] = getInfos();
|
||||
auto [capacity, time_remaining, status] = getInfos();
|
||||
if (status == "Unknown") {
|
||||
status = getAdapterStatus(capacity, current_now);
|
||||
status = getAdapterStatus(capacity);
|
||||
}
|
||||
if (tooltipEnabled()) {
|
||||
label_.set_tooltip_text(status);
|
||||
std::string tooltip_text;
|
||||
if (time_remaining != 0) {
|
||||
std::string time_to = std::string("Time to ") + ((time_remaining > 0) ? "empty" : "full");
|
||||
tooltip_text = time_to + ": " + formatTimeRemaining(time_remaining);
|
||||
} else {
|
||||
tooltip_text = status;
|
||||
}
|
||||
label_.set_tooltip_text(tooltip_text);
|
||||
}
|
||||
std::transform(status.begin(), status.end(), status.begin(), ::tolower);
|
||||
auto format = format_;
|
||||
@ -151,7 +182,9 @@ auto waybar::modules::Battery::update() -> void {
|
||||
event_box_.hide();
|
||||
} else {
|
||||
event_box_.show();
|
||||
label_.set_markup(fmt::format(
|
||||
format, fmt::arg("capacity", capacity), fmt::arg("icon", getIcon(capacity, state))));
|
||||
label_.set_markup(fmt::format(format,
|
||||
fmt::arg("capacity", capacity),
|
||||
fmt::arg("icon", getIcon(capacity, state)),
|
||||
fmt::arg("time", formatTimeRemaining(time_remaining))));
|
||||
}
|
||||
}
|
||||
|
@ -14,16 +14,13 @@ waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config)
|
||||
auto sub_m =
|
||||
std::chrono::duration_cast<std::chrono::seconds>(time_s.time_since_epoch()).count() %
|
||||
interval_.count();
|
||||
if (sub_m > 0) {
|
||||
thread_.sleep_until(timeout - std::chrono::seconds(sub_m - 1));
|
||||
} else {
|
||||
thread_.sleep_until(timeout - std::chrono::seconds(sub_m));
|
||||
}
|
||||
thread_.sleep_until(timeout - std::chrono::seconds(sub_m));
|
||||
};
|
||||
}
|
||||
|
||||
auto waybar::modules::Clock::update() -> void {
|
||||
auto localtime = fmt::localtime(std::time(nullptr));
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto localtime = fmt::localtime(std::chrono::system_clock::to_time_t(now));
|
||||
auto text = fmt::format(format_, localtime);
|
||||
label_.set_markup(text);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "modules/cpu.hpp"
|
||||
#include <numeric>
|
||||
|
||||
waybar::modules::Cpu::Cpu(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "{usage}%", 10) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
#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) {
|
||||
@ -58,7 +59,7 @@ void waybar::modules::Custom::continuousWorker() {
|
||||
if (exit_code != 0) {
|
||||
output_ = {exit_code, ""};
|
||||
dp.emit();
|
||||
std::cerr << name_ + " just stopped unexpectedly, is it endless?" << std::endl;
|
||||
spdlog::error("{} stopped unexpectedly, is it endless?", name_);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -16,9 +16,14 @@ auto waybar::modules::Memory::update() -> void {
|
||||
parseMeminfo();
|
||||
if (memtotal_ > 0 && memfree_ >= 0) {
|
||||
int used_ram_percentage = 100 * (memtotal_ - memfree_) / memtotal_;
|
||||
getState(used_ram_percentage);
|
||||
label_.set_markup(fmt::format(format_, used_ram_percentage));
|
||||
auto used_ram_gigabytes = (memtotal_ - memfree_) / std::pow(1024, 2);
|
||||
auto available_ram_gigabytes = memfree_ / std::pow(1024, 2);
|
||||
|
||||
getState(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)));
|
||||
if (tooltipEnabled()) {
|
||||
label_.set_tooltip_text(fmt::format("{:.{}f}Gb used", used_ram_gigabytes, 1));
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "modules/mpd.hpp"
|
||||
|
||||
#include <fmt/chrono.h>
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config)
|
||||
: ALabel(config, "{album} - {artist} - {title}", 5),
|
||||
@ -14,11 +14,11 @@ waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config)
|
||||
status_(nullptr, &mpd_status_free),
|
||||
song_(nullptr, &mpd_song_free) {
|
||||
if (!config_["port"].isNull() && !config_["port"].isUInt()) {
|
||||
std::cerr << module_name_ << ": `port` configuration should be an unsigned int" << std::endl;
|
||||
spdlog::warn("{}: `port` configuration should be an unsigned int", module_name_);
|
||||
}
|
||||
|
||||
if (!config_["timeout"].isNull() && !config_["timeout"].isUInt()) {
|
||||
std::cerr << module_name_ << ": `timeout` configuration should be an unsigned int" << std::endl;
|
||||
spdlog::warn("{}: `timeout` configuration should be an unsigned int", module_name_);
|
||||
}
|
||||
|
||||
label_.set_name("mpd");
|
||||
@ -28,7 +28,7 @@ waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config)
|
||||
|
||||
if (!config["server"].isNull()) {
|
||||
if (!config_["server"].isString()) {
|
||||
std::cerr << module_name_ << "`server` configuration should be a string" << std::endl;
|
||||
spdlog::warn("{}:`server` configuration should be a string", module_name_);
|
||||
}
|
||||
server_ = config["server"].asCString();
|
||||
}
|
||||
@ -51,7 +51,7 @@ auto waybar::modules::MPD::update() -> void {
|
||||
periodic_updater().detach();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << module_name_ + ": " + e.what() << std::endl;
|
||||
spdlog::error("{}: {}", module_name_, e.what());
|
||||
state_ = MPD_STATE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
@ -72,7 +72,7 @@ std::thread waybar::modules::MPD::event_listener() {
|
||||
dp.emit();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << module_name_ + ": " + e.what() << std::endl;
|
||||
spdlog::warn("{}: {}", module_name_, e.what());
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -206,12 +206,12 @@ std::string waybar::modules::MPD::getStateIcon() {
|
||||
}
|
||||
|
||||
if (connection_ == nullptr) {
|
||||
std::cerr << module_name_ << ": Trying to fetch state icon while disconnected" << std::endl;
|
||||
spdlog::warn("{}: Trying to fetch state icon while disconnected", module_name_);
|
||||
return "";
|
||||
}
|
||||
|
||||
if (stopped()) {
|
||||
std::cerr << module_name_ << ": Trying to fetch state icon while stopped" << std::endl;
|
||||
spdlog::warn("{}: Trying to fetch state icon while stopped", module_name_);
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -228,7 +228,7 @@ std::string waybar::modules::MPD::getOptionIcon(std::string optionName, bool act
|
||||
}
|
||||
|
||||
if (connection_ == nullptr) {
|
||||
std::cerr << module_name_ << ": Trying to fetch option icon while disconnected" << std::endl;
|
||||
spdlog::warn("{}: Trying to fetch option icon while disconnected", module_name_);
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ void waybar::modules::MPD::tryConnect() {
|
||||
unique_connection(mpd_connection_new(server_, port_, timeout_), &mpd_connection_free);
|
||||
|
||||
if (connection_ == nullptr || alternate_connection_ == nullptr) {
|
||||
std::cerr << module_name_ << ": Failed to connect to MPD" << std::endl;
|
||||
spdlog::error("{}: Failed to connect to MPD", module_name_);
|
||||
connection_.reset();
|
||||
alternate_connection_.reset();
|
||||
return;
|
||||
@ -259,9 +259,9 @@ void waybar::modules::MPD::tryConnect() {
|
||||
|
||||
try {
|
||||
checkErrors(connection_.get());
|
||||
std::cerr << module_name_ << ": Connected to MPD" << std::endl;
|
||||
spdlog::info("{}: Connected to MPD", module_name_);
|
||||
} catch (std::runtime_error& e) {
|
||||
std::cerr << module_name_ << ": Failed to connect to MPD: " << e.what() << std::endl;
|
||||
spdlog::error("{}: Failed to connect to MPD: {}", module_name_, e.what());
|
||||
connection_.reset();
|
||||
alternate_connection_.reset();
|
||||
}
|
||||
|
@ -1,74 +1,76 @@
|
||||
#include "modules/network.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char * NETSTAT_FILE = "/proc/net/netstat"; // std::ifstream does not take std::string_view as param
|
||||
constexpr std::string_view BANDWIDTH_CATEGORY = "IpExt";
|
||||
constexpr std::string_view BANDWIDTH_DOWN_TOTAL_KEY = "InOctets";
|
||||
constexpr std::string_view BANDWIDTH_UP_TOTAL_KEY = "OutOctets";
|
||||
constexpr const char *NETSTAT_FILE =
|
||||
"/proc/net/netstat"; // std::ifstream does not take std::string_view as param
|
||||
constexpr std::string_view BANDWIDTH_CATEGORY = "IpExt";
|
||||
constexpr std::string_view BANDWIDTH_DOWN_TOTAL_KEY = "InOctets";
|
||||
constexpr std::string_view BANDWIDTH_UP_TOTAL_KEY = "OutOctets";
|
||||
|
||||
std::ifstream netstat(NETSTAT_FILE);
|
||||
std::optional<unsigned long long> read_netstat(std::string_view category, std::string_view key) {
|
||||
if (!netstat) {
|
||||
std::cerr << "Failed to open netstat file " << NETSTAT_FILE << '\n' << std::flush;
|
||||
return {};
|
||||
}
|
||||
netstat.seekg(std::ios_base::beg);
|
||||
|
||||
|
||||
// finding corresponding line (category)
|
||||
// looks into the file for the first line starting by the 'category' string
|
||||
auto starts_with = [](const std::string& str, std::string_view start) {
|
||||
return start == std::string_view{str.data(), std::min(str.size(), start.size())};
|
||||
};
|
||||
|
||||
std::string read;
|
||||
while (std::getline(netstat, read) && !starts_with(read, category));
|
||||
if (!starts_with(read, category)) {
|
||||
std::cerr << "Category '" << category << "' not found in netstat file " << NETSTAT_FILE << '\n' << std::flush;
|
||||
return {};
|
||||
}
|
||||
|
||||
// finding corresponding column (key)
|
||||
// looks into the fetched line for the first word (space separated) equal to 'key'
|
||||
int index = 0;
|
||||
auto r_it = read.begin();
|
||||
auto k_it = key.begin();
|
||||
while (k_it != key.end() && r_it != read.end()) {
|
||||
if (*r_it != *k_it) {
|
||||
r_it = std::find(r_it, read.end(), ' ');
|
||||
if (r_it != read.end()) {
|
||||
++r_it;
|
||||
}
|
||||
k_it = key.begin();
|
||||
++index;
|
||||
} else {
|
||||
++r_it;
|
||||
++k_it;
|
||||
}
|
||||
}
|
||||
|
||||
if (r_it == read.end() && k_it != key.end()) {
|
||||
std::cerr << "Key '" << key << "' not found in category '" << category << "' of netstat file " << NETSTAT_FILE << '\n' << std::flush;
|
||||
return {};
|
||||
}
|
||||
|
||||
// finally accessing value
|
||||
// accesses the line right under the fetched one
|
||||
std::getline(netstat, read);
|
||||
assert(starts_with(read, category));
|
||||
std::istringstream iss(read);
|
||||
while (index--) {
|
||||
std::getline(iss, read, ' ');
|
||||
}
|
||||
unsigned long long value;
|
||||
iss >> value;
|
||||
return value;
|
||||
std::ifstream netstat(NETSTAT_FILE);
|
||||
std::optional<unsigned long long> read_netstat(std::string_view category, std::string_view key) {
|
||||
if (!netstat) {
|
||||
spdlog::warn("Failed to open netstat file {}", NETSTAT_FILE);
|
||||
return {};
|
||||
}
|
||||
netstat.seekg(std::ios_base::beg);
|
||||
|
||||
// finding corresponding line (category)
|
||||
// looks into the file for the first line starting by the 'category' string
|
||||
auto starts_with = [](const std::string &str, std::string_view start) {
|
||||
return start == std::string_view{str.data(), std::min(str.size(), start.size())};
|
||||
};
|
||||
|
||||
std::string read;
|
||||
while (std::getline(netstat, read) && !starts_with(read, category))
|
||||
;
|
||||
if (!starts_with(read, category)) {
|
||||
spdlog::warn("Category '{}' not found in netstat file {}", category, NETSTAT_FILE);
|
||||
return {};
|
||||
}
|
||||
|
||||
// finding corresponding column (key)
|
||||
// looks into the fetched line for the first word (space separated) equal to 'key'
|
||||
int index = 0;
|
||||
auto r_it = read.begin();
|
||||
auto k_it = key.begin();
|
||||
while (k_it != key.end() && r_it != read.end()) {
|
||||
if (*r_it != *k_it) {
|
||||
r_it = std::find(r_it, read.end(), ' ');
|
||||
if (r_it != read.end()) {
|
||||
++r_it;
|
||||
}
|
||||
k_it = key.begin();
|
||||
++index;
|
||||
} else {
|
||||
++r_it;
|
||||
++k_it;
|
||||
}
|
||||
}
|
||||
|
||||
if (r_it == read.end() && k_it != key.end()) {
|
||||
spdlog::warn(
|
||||
"Key '{}' not found in category '{}' of netstat file {}", key, category, NETSTAT_FILE);
|
||||
return {};
|
||||
}
|
||||
|
||||
// finally accessing value
|
||||
// accesses the line right under the fetched one
|
||||
std::getline(netstat, read);
|
||||
assert(starts_with(read, category));
|
||||
std::istringstream iss(read);
|
||||
while (index--) {
|
||||
std::getline(iss, read, ' ');
|
||||
}
|
||||
unsigned long long value;
|
||||
iss >> value;
|
||||
return value;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
waybar::modules::Network::Network(const std::string &id, const Json::Value &config)
|
||||
: ALabel(config, "{ifname}", 60),
|
||||
@ -272,39 +274,42 @@ auto waybar::modules::Network::update() -> void {
|
||||
format_ = default_format_;
|
||||
}
|
||||
getState(signal_strength_);
|
||||
|
||||
auto pow_format = [](unsigned long long value, const std::string& unit) {
|
||||
if (value > 2000ull * 1000ull * 1000ull) { // > 2G
|
||||
|
||||
auto pow_format = [](unsigned long long value, const std::string &unit) {
|
||||
if (value > 2000ull * 1000ull * 1000ull) { // > 2G
|
||||
auto go = value / (1000 * 1000 * 1000);
|
||||
return std::to_string(go) + "." + std::to_string((value - go * 1000 * 1000 * 1000) / (100 * 1000 * 1000)) + "G" + unit;
|
||||
return std::to_string(go) + "." +
|
||||
std::to_string((value - go * 1000 * 1000 * 1000) / (100 * 1000 * 1000)) + "G" + unit;
|
||||
|
||||
} else if (value > 2000ull * 1000ull) { // > 2M
|
||||
} else if (value > 2000ull * 1000ull) { // > 2M
|
||||
auto mo = value / (1000 * 1000);
|
||||
return std::to_string(mo) + "." + std::to_string((value - mo * 1000 * 1000) / (100 * 1000)) + "M" + unit;
|
||||
return std::to_string(mo) + "." + std::to_string((value - mo * 1000 * 1000) / (100 * 1000)) +
|
||||
"M" + unit;
|
||||
|
||||
} else if (value > 2000ull) { // > 2k
|
||||
} else if (value > 2000ull) { // > 2k
|
||||
auto ko = value / 1000;
|
||||
return std::to_string(ko) + "." + std::to_string((value - ko * 1000) / 100) + "k" + unit;
|
||||
|
||||
|
||||
} else {
|
||||
return std::to_string(value) + unit;
|
||||
}
|
||||
};
|
||||
|
||||
auto text = fmt::format(format_,
|
||||
fmt::arg("essid", essid_),
|
||||
fmt::arg("signaldBm", signal_strength_dbm_),
|
||||
fmt::arg("signalStrength", signal_strength_),
|
||||
fmt::arg("ifname", ifname_),
|
||||
fmt::arg("netmask", netmask_),
|
||||
fmt::arg("ipaddr", ipaddr_),
|
||||
fmt::arg("cidr", cidr_),
|
||||
fmt::arg("frequency", frequency_),
|
||||
fmt::arg("icon", getIcon(signal_strength_, connectiontype)),
|
||||
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")),
|
||||
fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / interval_.count(), "o/s")));
|
||||
auto text = fmt::format(
|
||||
format_,
|
||||
fmt::arg("essid", essid_),
|
||||
fmt::arg("signaldBm", signal_strength_dbm_),
|
||||
fmt::arg("signalStrength", signal_strength_),
|
||||
fmt::arg("ifname", ifname_),
|
||||
fmt::arg("netmask", netmask_),
|
||||
fmt::arg("ipaddr", ipaddr_),
|
||||
fmt::arg("cidr", cidr_),
|
||||
fmt::arg("frequency", frequency_),
|
||||
fmt::arg("icon", getIcon(signal_strength_, connectiontype)),
|
||||
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")),
|
||||
fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / interval_.count(), "o/s")));
|
||||
if (text != label_.get_label()) {
|
||||
label_.set_markup(text);
|
||||
}
|
||||
@ -313,20 +318,22 @@ auto waybar::modules::Network::update() -> void {
|
||||
tooltip_format = config_["tooltip-format"].asString();
|
||||
}
|
||||
if (!tooltip_format.empty()) {
|
||||
auto tooltip_text = fmt::format(tooltip_format,
|
||||
fmt::arg("essid", essid_),
|
||||
fmt::arg("signaldBm", signal_strength_dbm_),
|
||||
fmt::arg("signalStrength", signal_strength_),
|
||||
fmt::arg("ifname", ifname_),
|
||||
fmt::arg("netmask", netmask_),
|
||||
fmt::arg("ipaddr", ipaddr_),
|
||||
fmt::arg("cidr", cidr_),
|
||||
fmt::arg("frequency", frequency_),
|
||||
fmt::arg("icon", getIcon(signal_strength_, connectiontype)),
|
||||
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")),
|
||||
fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / interval_.count(), "o/s")));
|
||||
auto tooltip_text = fmt::format(
|
||||
tooltip_format,
|
||||
fmt::arg("essid", essid_),
|
||||
fmt::arg("signaldBm", signal_strength_dbm_),
|
||||
fmt::arg("signalStrength", signal_strength_),
|
||||
fmt::arg("ifname", ifname_),
|
||||
fmt::arg("netmask", netmask_),
|
||||
fmt::arg("ipaddr", ipaddr_),
|
||||
fmt::arg("cidr", cidr_),
|
||||
fmt::arg("frequency", frequency_),
|
||||
fmt::arg("icon", getIcon(signal_strength_, connectiontype)),
|
||||
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")),
|
||||
fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / interval_.count(), "o/s")));
|
||||
if (label_.get_tooltip_text() != text) {
|
||||
label_.set_tooltip_text(tooltip_text);
|
||||
}
|
||||
@ -337,7 +344,7 @@ auto waybar::modules::Network::update() -> void {
|
||||
}
|
||||
|
||||
// Based on https://gist.github.com/Yawning/c70d804d4b8ae78cc698
|
||||
int waybar::modules::Network::getExternalInterface() {
|
||||
int waybar::modules::Network::getExternalInterface(int skip_idx) {
|
||||
static const uint32_t route_buffer_size = 8192;
|
||||
struct nlmsghdr * hdr = nullptr;
|
||||
struct rtmsg * rt = nullptr;
|
||||
@ -447,7 +454,7 @@ int waybar::modules::Network::getExternalInterface() {
|
||||
/* If this is the default route, and we know the interface index,
|
||||
* we can stop parsing this message.
|
||||
*/
|
||||
if (has_gateway && !has_destination && temp_idx != -1) {
|
||||
if (has_gateway && !has_destination && temp_idx != -1 && temp_idx != skip_idx) {
|
||||
ifidx = temp_idx;
|
||||
break;
|
||||
}
|
||||
@ -540,7 +547,7 @@ bool waybar::modules::Network::checkInterface(struct ifinfomsg *rtif, std::strin
|
||||
return external_iface == rtif->ifi_index;
|
||||
}
|
||||
|
||||
int waybar::modules::Network::getPreferredIface() {
|
||||
int waybar::modules::Network::getPreferredIface(int skip_idx) {
|
||||
if (config_["interface"].isString()) {
|
||||
ifid_ = if_nametoindex(config_["interface"].asCString());
|
||||
if (ifid_ > 0) {
|
||||
@ -566,7 +573,7 @@ int waybar::modules::Network::getPreferredIface() {
|
||||
return ifid_;
|
||||
}
|
||||
}
|
||||
ifid_ = getExternalInterface();
|
||||
ifid_ = getExternalInterface(skip_idx);
|
||||
if (ifid_ > 0) {
|
||||
char ifname[IF_NAMESIZE];
|
||||
if_indextoname(ifid_, ifname);
|
||||
@ -576,6 +583,17 @@ int waybar::modules::Network::getPreferredIface() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void waybar::modules::Network::clearIface() {
|
||||
essid_.clear();
|
||||
ipaddr_.clear();
|
||||
netmask_.clear();
|
||||
cidr_ = 0;
|
||||
signal_strength_dbm_ = 0;
|
||||
signal_strength_ = 0;
|
||||
frequency_ = 0;
|
||||
linked_ = false;
|
||||
}
|
||||
|
||||
int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
||||
auto net = static_cast<waybar::modules::Network *>(data);
|
||||
auto nh = nlmsg_hdr(msg);
|
||||
@ -586,13 +604,18 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
||||
char ifname[IF_NAMESIZE];
|
||||
if_indextoname(rtif->ifi_index, ifname);
|
||||
// Auto detected network can also be assigned here
|
||||
if (net->ifid_ == -1 && net->checkInterface(rtif, ifname)) {
|
||||
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;
|
||||
}
|
||||
// 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();
|
||||
@ -617,15 +640,9 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) {
|
||||
net->ifid_ = rtif->ifi_index;
|
||||
net->dp.emit();
|
||||
} else if (rtif->ifi_index == net->ifid_) {
|
||||
net->linked_ = false;
|
||||
net->ifname_.clear();
|
||||
net->ifid_ = -1;
|
||||
net->essid_.clear();
|
||||
net->signal_strength_dbm_ = 0;
|
||||
net->signal_strength_ = 0;
|
||||
net->frequency_ = 0;
|
||||
net->clearIface();
|
||||
// Check for a new interface and get info
|
||||
auto new_iface = net->getPreferredIface();
|
||||
auto new_iface = net->getPreferredIface(rtif->ifi_index);
|
||||
if (new_iface != -1) {
|
||||
net->getInterfaceAddress();
|
||||
net->thread_timer_.wake_up();
|
||||
|
@ -1,15 +1,17 @@
|
||||
#include "modules/pulseaudio.hpp"
|
||||
#include <array>
|
||||
|
||||
waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value &config)
|
||||
: ALabel(config, "{volume}%"),
|
||||
mainloop_(nullptr),
|
||||
mainloop_api_(nullptr),
|
||||
context_(nullptr),
|
||||
scrolling_(false),
|
||||
sink_idx_(0),
|
||||
volume_(0),
|
||||
muted_(false),
|
||||
scrolling_(false) {
|
||||
source_idx_(0),
|
||||
source_volume_(0),
|
||||
source_muted_(false) {
|
||||
label_.set_name("pulseaudio");
|
||||
if (!id.empty()) {
|
||||
label_.get_style_context()->add_class(id);
|
||||
@ -58,7 +60,12 @@ void waybar::modules::Pulseaudio::contextStateCb(pa_context *c, void *data) {
|
||||
case PA_CONTEXT_READY:
|
||||
pa_context_get_server_info(c, serverInfoCb, data);
|
||||
pa_context_set_subscribe_callback(c, subscribeCb, data);
|
||||
pa_context_subscribe(c, PA_SUBSCRIPTION_MASK_SINK, nullptr, nullptr);
|
||||
pa_context_subscribe(
|
||||
c,
|
||||
static_cast<enum pa_subscription_mask>(static_cast<int>(PA_SUBSCRIPTION_MASK_SINK) |
|
||||
static_cast<int>(PA_SUBSCRIPTION_MASK_SOURCE)),
|
||||
nullptr,
|
||||
nullptr);
|
||||
break;
|
||||
case PA_CONTEXT_FAILED:
|
||||
pa->mainloop_api_->quit(pa->mainloop_api_, 1);
|
||||
@ -76,10 +83,10 @@ bool waybar::modules::Pulseaudio::handleVolume(GdkEventScroll *e) {
|
||||
if (scrolling_) {
|
||||
return false;
|
||||
}
|
||||
bool direction_up = false;
|
||||
double volume_tick = (double)PA_VOLUME_NORM / 100;
|
||||
bool direction_up = false;
|
||||
double volume_tick = (double)PA_VOLUME_NORM / 100;
|
||||
pa_volume_t change = volume_tick;
|
||||
pa_cvolume pa_volume = pa_volume_;
|
||||
pa_cvolume pa_volume = pa_volume_;
|
||||
scrolling_ = true;
|
||||
if (e->direction == GDK_SCROLL_UP) {
|
||||
direction_up = true;
|
||||
@ -108,7 +115,7 @@ bool waybar::modules::Pulseaudio::handleVolume(GdkEventScroll *e) {
|
||||
pa_cvolume_inc(&pa_volume, change);
|
||||
}
|
||||
} else {
|
||||
if (volume_ - 1 > 0) {
|
||||
if (volume_ - 1 >= 0) {
|
||||
pa_cvolume_dec(&pa_volume, change);
|
||||
}
|
||||
}
|
||||
@ -127,6 +134,8 @@ void waybar::modules::Pulseaudio::subscribeCb(pa_context * conte
|
||||
unsigned facility = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
|
||||
if (facility == PA_SUBSCRIPTION_EVENT_SINK) {
|
||||
pa_context_get_sink_info_by_index(context, idx, sinkInfoCb, data);
|
||||
} else if (facility == PA_SUBSCRIPTION_EVENT_SOURCE) {
|
||||
pa_context_get_source_info_by_index(context, idx, sourceInfoCb, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,6 +149,23 @@ void waybar::modules::Pulseaudio::volumeModifyCb(pa_context *c, int success, voi
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the requested source information is ready.
|
||||
*/
|
||||
void waybar::modules::Pulseaudio::sourceInfoCb(pa_context * /*context*/, const pa_source_info *i,
|
||||
int /*eol*/, void *data) {
|
||||
if (i != nullptr) {
|
||||
auto self = static_cast<waybar::modules::Pulseaudio *>(data);
|
||||
auto source_volume = static_cast<float>(pa_cvolume_avg(&(i->volume))) / float{PA_VOLUME_NORM};
|
||||
self->source_volume_ = std::round(source_volume * 100.0F);
|
||||
self->source_idx_ = i->index;
|
||||
self->source_muted_ = i->mute != 0;
|
||||
self->source_desc_ = i->description;
|
||||
self->source_port_name_ = i->active_port != nullptr ? i->active_port->name : "Unknown";
|
||||
self->dp.emit();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the requested sink information is ready.
|
||||
*/
|
||||
@ -166,6 +192,7 @@ void waybar::modules::Pulseaudio::sinkInfoCb(pa_context * /*context*/, const pa_
|
||||
void waybar::modules::Pulseaudio::serverInfoCb(pa_context *context, const pa_server_info *i,
|
||||
void *data) {
|
||||
pa_context_get_sink_info_by_name(context, i->default_sink_name, sinkInfoCb, data);
|
||||
pa_context_get_source_info_by_name(context, i->default_source_name, sourceInfoCb, data);
|
||||
}
|
||||
|
||||
static const std::array<std::string, 9> ports = {
|
||||
@ -206,8 +233,18 @@ auto waybar::modules::Pulseaudio::update() -> void {
|
||||
label_.get_style_context()->remove_class("bluetooth");
|
||||
}
|
||||
}
|
||||
label_.set_markup(fmt::format(
|
||||
format, fmt::arg("volume", volume_), fmt::arg("icon", getIcon(volume_, getPortIcon()))));
|
||||
// TODO: find a better way to split source/sink
|
||||
std::string format_source = "{volume}%";
|
||||
if (source_muted_ && config_["format-source-muted"].isString()) {
|
||||
format_source = config_["format-source-muted"].asString();
|
||||
} else if (!source_muted_ && config_["format-source"].isString()) {
|
||||
format_source = config_["format-source"].asString();
|
||||
}
|
||||
format_source = fmt::format(format_source, fmt::arg("volume", source_volume_));
|
||||
label_.set_markup(fmt::format(format,
|
||||
fmt::arg("volume", volume_),
|
||||
fmt::arg("format_source", format_source),
|
||||
fmt::arg("icon", getIcon(volume_, getPortIcon()))));
|
||||
getState(volume_);
|
||||
if (tooltipEnabled()) {
|
||||
label_.set_tooltip_text(desc_);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "modules/sni/host.hpp"
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <fmt/ostream.h>
|
||||
|
||||
namespace waybar::modules::SNI {
|
||||
|
||||
@ -63,14 +64,14 @@ void Host::proxyReady(GObject* src, GAsyncResult* res, gpointer data) {
|
||||
GError* error = nullptr;
|
||||
SnWatcher* watcher = sn_watcher_proxy_new_finish(res, &error);
|
||||
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
std::cerr << error->message << std::endl;
|
||||
spdlog::error("Host: {}", error->message);
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
auto host = static_cast<SNI::Host*>(data);
|
||||
host->watcher_ = watcher;
|
||||
if (error != nullptr) {
|
||||
std::cerr << error->message << std::endl;
|
||||
spdlog::error("Host: {}", error->message);
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
@ -82,13 +83,13 @@ void Host::registerHost(GObject* src, GAsyncResult* res, gpointer data) {
|
||||
GError* error = nullptr;
|
||||
sn_watcher_call_register_host_finish(SN_WATCHER(src), res, &error);
|
||||
if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
|
||||
std::cerr << error->message << std::endl;
|
||||
spdlog::error("Host: {}", error->message);
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
auto host = static_cast<SNI::Host*>(data);
|
||||
if (error != nullptr) {
|
||||
std::cerr << error->message << std::endl;
|
||||
spdlog::error("Host: {}", error->message);
|
||||
g_error_free(error);
|
||||
return;
|
||||
}
|
||||
@ -139,4 +140,4 @@ void Host::addRegisteredItem(std::string service) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace waybar::modules::SNI
|
||||
} // namespace waybar::modules::SNI
|
||||
|
@ -1,6 +1,32 @@
|
||||
#include "modules/sni/item.hpp"
|
||||
#include <glibmm/main.h>
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "modules/sni/item.hpp"
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Glib::ustring> : formatter<std::string> {
|
||||
template <typename FormatContext>
|
||||
auto format(const Glib::ustring& value, FormatContext& ctx) {
|
||||
return formatter<std::string>::format(value, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Glib::VariantBase> : formatter<std::string> {
|
||||
bool is_printable(const Glib::VariantBase& value) {
|
||||
auto type = value.get_type_string();
|
||||
/* Print only primitive (single character excluding 'v') and short complex types */
|
||||
return (type.length() == 1 && islower(type[0]) && type[0] != 'v') || value.get_size() <= 32;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const Glib::VariantBase& value, FormatContext& ctx) {
|
||||
if (is_printable(value)) {
|
||||
return formatter<std::string>::format(value.print(), ctx);
|
||||
} else {
|
||||
return formatter<std::string>::format(value.get_type_string(), ctx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace waybar::modules::SNI {
|
||||
|
||||
@ -47,23 +73,16 @@ void Item::proxyReady(Glib::RefPtr<Gio::AsyncResult>& result) {
|
||||
this->proxy_->signal_signal().connect(sigc::mem_fun(*this, &Item::onSignal));
|
||||
|
||||
if (this->id.empty() || this->category.empty() || this->status.empty()) {
|
||||
std::cerr << "Invalid Status Notifier Item: " + this->bus_name + "," + this->object_path
|
||||
<< std::endl;
|
||||
spdlog::error("Invalid Status Notifier Item: {}, {}", bus_name, object_path);
|
||||
return;
|
||||
}
|
||||
this->updateImage();
|
||||
// this->event_box.set_tooltip_text(this->title);
|
||||
|
||||
} catch (const Glib::Error& err) {
|
||||
g_error("Failed to create DBus Proxy for %s %s: %s",
|
||||
bus_name.c_str(),
|
||||
object_path.c_str(),
|
||||
err.what().c_str());
|
||||
spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path, err.what());
|
||||
} catch (const std::exception& err) {
|
||||
g_error("Failed to create DBus Proxy for %s %s: %s",
|
||||
bus_name.c_str(),
|
||||
object_path.c_str(),
|
||||
err.what());
|
||||
spdlog::error("Failed to create DBus Proxy for {} {}: {}", bus_name, object_path, err.what());
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,41 +92,57 @@ T get_variant(Glib::VariantBase& value) {
|
||||
}
|
||||
|
||||
void Item::setProperty(const Glib::ustring& name, Glib::VariantBase& value) {
|
||||
if (name == "Category") {
|
||||
category = get_variant<std::string>(value);
|
||||
} else if (name == "Id") {
|
||||
id = get_variant<std::string>(value);
|
||||
} else if (name == "Title") {
|
||||
title = get_variant<std::string>(value);
|
||||
} else if (name == "Status") {
|
||||
status = get_variant<std::string>(value);
|
||||
} else if (name == "WindowId") {
|
||||
window_id = get_variant<int32_t>(value);
|
||||
} else if (name == "IconName") {
|
||||
icon_name = get_variant<std::string>(value);
|
||||
} else if (name == "IconPixmap") {
|
||||
icon_pixmap = this->extractPixBuf(value.gobj());
|
||||
} else if (name == "OverlayIconName") {
|
||||
overlay_icon_name = get_variant<std::string>(value);
|
||||
} else if (name == "OverlayIconPixmap") {
|
||||
// TODO: overlay_icon_pixmap
|
||||
} else if (name == "AttentionIconName") {
|
||||
attention_icon_name = get_variant<std::string>(value);
|
||||
} else if (name == "AttentionIconPixmap") {
|
||||
// TODO: attention_icon_pixmap
|
||||
} else if (name == "AttentionMovieName") {
|
||||
attention_movie_name = get_variant<std::string>(value);
|
||||
} else if (name == "ToolTip") {
|
||||
// TODO: tooltip
|
||||
} else if (name == "IconThemePath") {
|
||||
icon_theme_path = get_variant<std::string>(value);
|
||||
if (!icon_theme_path.empty()) {
|
||||
icon_theme->set_search_path({icon_theme_path});
|
||||
try {
|
||||
spdlog::trace("Set tray item property: {}.{} = {}", id.empty() ? bus_name : id, name, value);
|
||||
|
||||
if (name == "Category") {
|
||||
category = get_variant<std::string>(value);
|
||||
} else if (name == "Id") {
|
||||
id = get_variant<std::string>(value);
|
||||
} else if (name == "Title") {
|
||||
title = get_variant<std::string>(value);
|
||||
} else if (name == "Status") {
|
||||
status = get_variant<std::string>(value);
|
||||
} else if (name == "WindowId") {
|
||||
window_id = get_variant<int32_t>(value);
|
||||
} else if (name == "IconName") {
|
||||
icon_name = get_variant<std::string>(value);
|
||||
} else if (name == "IconPixmap") {
|
||||
icon_pixmap = this->extractPixBuf(value.gobj());
|
||||
} else if (name == "OverlayIconName") {
|
||||
overlay_icon_name = get_variant<std::string>(value);
|
||||
} else if (name == "OverlayIconPixmap") {
|
||||
// TODO: overlay_icon_pixmap
|
||||
} else if (name == "AttentionIconName") {
|
||||
attention_icon_name = get_variant<std::string>(value);
|
||||
} else if (name == "AttentionIconPixmap") {
|
||||
// TODO: attention_icon_pixmap
|
||||
} else if (name == "AttentionMovieName") {
|
||||
attention_movie_name = get_variant<std::string>(value);
|
||||
} else if (name == "ToolTip") {
|
||||
// TODO: tooltip
|
||||
} else if (name == "IconThemePath") {
|
||||
icon_theme_path = get_variant<std::string>(value);
|
||||
if (!icon_theme_path.empty()) {
|
||||
icon_theme->set_search_path({icon_theme_path});
|
||||
}
|
||||
} else if (name == "Menu") {
|
||||
menu = get_variant<std::string>(value);
|
||||
} else if (name == "ItemIsMenu") {
|
||||
item_is_menu = get_variant<bool>(value);
|
||||
}
|
||||
} else if (name == "Menu") {
|
||||
menu = get_variant<std::string>(value);
|
||||
} else if (name == "ItemIsMenu") {
|
||||
item_is_menu = get_variant<bool>(value);
|
||||
} catch (const Glib::Error& err) {
|
||||
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
||||
id.empty() ? bus_name : id,
|
||||
name,
|
||||
value,
|
||||
err.what());
|
||||
} catch (const std::exception& err) {
|
||||
spdlog::warn("Failed to set tray item property: {}.{}, value = {}, err = {}",
|
||||
id.empty() ? bus_name : id,
|
||||
name,
|
||||
value,
|
||||
err.what());
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,7 +167,7 @@ void Item::processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& _result) {
|
||||
for (const auto& [name, value] : properties) {
|
||||
Glib::VariantBase old_value;
|
||||
proxy_->get_cached_property(old_value, name);
|
||||
if (!value.equal(old_value)) {
|
||||
if (!old_value || !value.equal(old_value)) {
|
||||
proxy_->set_cached_property(name, value);
|
||||
setProperty(name, const_cast<Glib::VariantBase&>(value));
|
||||
}
|
||||
@ -141,14 +176,15 @@ void Item::processUpdatedProperties(Glib::RefPtr<Gio::AsyncResult>& _result) {
|
||||
this->updateImage();
|
||||
// this->event_box.set_tooltip_text(this->title);
|
||||
} catch (const Glib::Error& err) {
|
||||
g_warning("Failed to update properties: %s", err.what().c_str());
|
||||
spdlog::warn("Failed to update properties: {}", err.what());
|
||||
} catch (const std::exception& err) {
|
||||
g_warning("Failed to update properties: %s", err.what());
|
||||
spdlog::warn("Failed to update properties: {}", err.what());
|
||||
}
|
||||
}
|
||||
|
||||
void Item::onSignal(const Glib::ustring& sender_name, const Glib::ustring& signal_name,
|
||||
const Glib::VariantContainerBase& arguments) {
|
||||
spdlog::trace("Tray item '{}' got signal {}", id, signal_name);
|
||||
if (!update_pending_ && signal_name.compare(0, 3, "New") == 0) {
|
||||
/* Debounce signals and schedule update of all properties.
|
||||
* Based on behavior of Plasma dataengine for StatusNotifierItem.
|
||||
@ -235,7 +271,7 @@ void Item::updateImage() {
|
||||
image.set(getIconByName(icon_name, icon_size));
|
||||
}
|
||||
} catch (Glib::Error& e) {
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
spdlog::error("Item '{}': {}", id, static_cast<std::string>(e.what()));
|
||||
}
|
||||
} else if (icon_pixmap) {
|
||||
// An icon extracted may be the wrong size for the tray
|
||||
@ -321,4 +357,4 @@ bool Item::handleClick(GdkEventButton* const& ev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace waybar::modules::SNI
|
||||
} // namespace waybar::modules::SNI
|
||||
|
@ -1,14 +1,18 @@
|
||||
#include "modules/sni/tray.hpp"
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace waybar::modules::SNI {
|
||||
|
||||
Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config)
|
||||
: config_(config),
|
||||
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0),
|
||||
watcher_(nb_hosts_),
|
||||
host_(nb_hosts_, config, std::bind(&Tray::onAdd, this, std::placeholders::_1),
|
||||
std::bind(&Tray::onRemove, this, std::placeholders::_1)) {
|
||||
box_.set_name("tray");
|
||||
spdlog::warn(
|
||||
"For a functionnal tray you must have libappindicator-* installed and export "
|
||||
"XDG_CURRENT_DESKTOP=Unity");
|
||||
if (!id.empty()) {
|
||||
box_.get_style_context()->add_class(id);
|
||||
}
|
||||
@ -39,4 +43,4 @@ auto Tray::update() -> void {
|
||||
|
||||
Tray::operator Gtk::Widget&() { return box_; }
|
||||
|
||||
}
|
||||
} // namespace waybar::modules::SNI
|
||||
|
@ -1,16 +1,16 @@
|
||||
#include "modules/sni/watcher.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
using namespace waybar::modules::SNI;
|
||||
|
||||
Watcher::Watcher()
|
||||
Watcher::Watcher(std::size_t id)
|
||||
: bus_name_id_(Gio::DBus::own_name(Gio::DBus::BusType::BUS_TYPE_SESSION,
|
||||
"org.kde.StatusNotifierWatcher",
|
||||
sigc::mem_fun(*this, &Watcher::busAcquired),
|
||||
Gio::DBus::SlotNameAcquired(), Gio::DBus::SlotNameLost(),
|
||||
Gio::DBus::BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
|
||||
Gio::DBus::BUS_NAME_OWNER_FLAGS_REPLACE)),
|
||||
watcher_id_(id),
|
||||
watcher_(sn_watcher_skeleton_new()) {}
|
||||
|
||||
Watcher::~Watcher() {
|
||||
@ -34,7 +34,7 @@ void Watcher::busAcquired(const Glib::RefPtr<Gio::DBus::Connection>& conn, Glib:
|
||||
if (error != nullptr) {
|
||||
// Don't print an error when a watcher is already present
|
||||
if (error->code != 2) {
|
||||
std::cerr << error->message << std::endl;
|
||||
spdlog::error("Watcher {}: {}", watcher_id_, error->message);
|
||||
}
|
||||
g_error_free(error);
|
||||
return;
|
||||
@ -193,4 +193,4 @@ void Watcher::updateRegisteredItems(SnWatcher* obj) {
|
||||
sn_watcher_set_registered_items(obj, items);
|
||||
g_variant_unref(variant);
|
||||
g_free(items);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "modules/sway/mode.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace waybar::modules::sway {
|
||||
|
||||
@ -18,13 +19,13 @@ void Mode::onEvent(const struct Ipc::ipc_response& res) {
|
||||
try {
|
||||
auto payload = parser_.parse(res.payload);
|
||||
if (payload["change"] != "default") {
|
||||
mode_ = payload["change"].asString();
|
||||
mode_ = Glib::Markup::escape_text(payload["change"].asString());
|
||||
} else {
|
||||
mode_.clear();
|
||||
}
|
||||
dp.emit();
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Mode: " << e.what() << std::endl;
|
||||
spdlog::error("Mode: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +34,7 @@ void Mode::worker() {
|
||||
try {
|
||||
ipc_.handleEvent();
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Mode: " << e.what() << std::endl;
|
||||
spdlog::error("Mode: {}", e.what());
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -50,4 +51,4 @@ auto Mode::update() -> void {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace waybar::modules::sway
|
||||
} // namespace waybar::modules::sway
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "modules/sway/window.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace waybar::modules::sway {
|
||||
|
||||
@ -55,7 +56,7 @@ void Window::onCmd(const struct Ipc::ipc_response& res) {
|
||||
dp.emit();
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Window: " << e.what() << std::endl;
|
||||
spdlog::error("Window: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +65,7 @@ void Window::worker() {
|
||||
try {
|
||||
ipc_.handleEvent();
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Window: " << e.what() << std::endl;
|
||||
spdlog::error("Window: {}", e.what());
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -102,7 +103,7 @@ void Window::getTree() {
|
||||
try {
|
||||
ipc_.sendCmd(IPC_GET_TREE);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
spdlog::error("Window: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "modules/sway/workspaces.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
namespace waybar::modules::sway {
|
||||
|
||||
@ -16,7 +17,7 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
|
||||
ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Workspaces::onCmd));
|
||||
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||
if (!config["disable-bar-scroll"].asBool()) {
|
||||
auto &window = const_cast<Bar&>(bar_).window;
|
||||
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));
|
||||
}
|
||||
@ -28,7 +29,7 @@ void Workspaces::onEvent(const struct Ipc::ipc_response &res) {
|
||||
try {
|
||||
ipc_.sendCmd(IPC_GET_WORKSPACES);
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Workspaces: " << e.what() << std::endl;
|
||||
spdlog::error("Workspaces: {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,10 +48,53 @@ void Workspaces::onCmd(const struct Ipc::ipc_response &res) {
|
||||
? workspace["output"].asString() == bar_.output->name
|
||||
: true;
|
||||
});
|
||||
|
||||
// adding persistant workspaces (as per the config file)
|
||||
if (config_["persistant_workspaces"].isObject()) {
|
||||
const Json::Value & p_workspaces = config_["persistant_workspaces"];
|
||||
const std::vector<std::string> p_workspaces_names = p_workspaces.getMemberNames();
|
||||
|
||||
for (const std::string &p_w_name : p_workspaces_names) {
|
||||
const Json::Value &p_w = p_workspaces[p_w_name];
|
||||
auto it =
|
||||
std::find_if(payload.begin(), payload.end(), [&p_w_name](const Json::Value &node) {
|
||||
return node["name"].asString() == p_w_name;
|
||||
});
|
||||
|
||||
if (it != payload.end()) {
|
||||
continue; // already displayed by some bar
|
||||
}
|
||||
|
||||
if (p_w.isArray() && !p_w.empty()) {
|
||||
// Adding to target outputs
|
||||
for (const Json::Value &output : p_w) {
|
||||
if (output.asString() == bar_.output->name) {
|
||||
Json::Value v;
|
||||
v["name"] = p_w_name;
|
||||
v["target_output"] = bar_.output->name;
|
||||
workspaces_.emplace_back(std::move(v));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Adding to all outputs
|
||||
Json::Value v;
|
||||
v["name"] = p_w_name;
|
||||
workspaces_.emplace_back(std::move(v));
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(workspaces_.begin(),
|
||||
workspaces_.end(),
|
||||
[](const Json::Value &lhs, const Json::Value &rhs) {
|
||||
return lhs["name"].asString() < rhs["name"].asString();
|
||||
});
|
||||
}
|
||||
|
||||
dp.emit();
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Workspaces: " << e.what() << std::endl;
|
||||
spdlog::error("Workspaces: {}", e.what());
|
||||
}
|
||||
} else {
|
||||
if (scrolling_) {
|
||||
@ -64,7 +108,7 @@ void Workspaces::worker() {
|
||||
try {
|
||||
ipc_.handleEvent();
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Workspaces: " << e.what() << std::endl;
|
||||
spdlog::error("Workspaces: {}", e.what());
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -135,11 +179,20 @@ Gtk::Button &Workspaces::addButton(const Json::Value &node) {
|
||||
auto &button = pair.first->second;
|
||||
box_.pack_start(button, false, false, 0);
|
||||
button.set_relief(Gtk::RELIEF_NONE);
|
||||
button.signal_clicked().connect([this, pair] {
|
||||
button.signal_clicked().connect([this, node] {
|
||||
try {
|
||||
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", pair.first->first));
|
||||
if (node["target_output"].isString()) {
|
||||
ipc_.sendCmd(
|
||||
IPC_COMMAND,
|
||||
fmt::format("workspace \"{}\"; move workspace to output \"{}\"; workspace \"{}\"",
|
||||
node["name"].asString(),
|
||||
node["target_output"].asString(),
|
||||
node["name"].asString()));
|
||||
} else {
|
||||
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", node["name"].asString()));
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << e.what() << std::endl;
|
||||
spdlog::error("Workspaces: {}", e.what());
|
||||
}
|
||||
});
|
||||
if (!config_["disable-scroll"].asBool()) {
|
||||
@ -208,7 +261,7 @@ bool Workspaces::handleScroll(GdkEventScroll *e) {
|
||||
try {
|
||||
ipc_.sendCmd(IPC_COMMAND, fmt::format("workspace \"{}\"", name));
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Workspaces: " << e.what() << std::endl;
|
||||
spdlog::error("Workspaces: {}", e.what());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
10
subprojects/spdlog.wrap
Normal file
10
subprojects/spdlog.wrap
Normal file
@ -0,0 +1,10 @@
|
||||
[wrap-file]
|
||||
directory = spdlog-1.3.1
|
||||
|
||||
source_url = https://github.com/gabime/spdlog/archive/v1.3.1.tar.gz
|
||||
source_filename = v1.3.1.tar.gz
|
||||
source_hash = 160845266e94db1d4922ef755637f6901266731c4cb3b30b45bf41efa0e6ab70
|
||||
|
||||
patch_url = https://wrapdb.mesonbuild.com/v1/projects/spdlog/1.3.1/1/get_zip
|
||||
patch_filename = spdlog-1.3.1-1-wrap.zip
|
||||
patch_hash = 715a0229781019b853d409cc0bf891ee4b9d3a17bec0cf87f4ad30b28bbecc87
|
Reference in New Issue
Block a user