From e14005a6aad5f910f98ada73cd7b893133a80840 Mon Sep 17 00:00:00 2001 From: Faye Duxovni Date: Thu, 21 Jul 2022 16:37:43 -0400 Subject: [PATCH 01/91] Fix binary pow formatting for values between 1000 and 1024 --- include/util/format.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/util/format.hpp b/include/util/format.hpp index e9904210..a9295425 100644 --- a/include/util/format.hpp +++ b/include/util/format.hpp @@ -56,7 +56,9 @@ struct formatter { fraction /= base; } - auto max_width = 4 // coeff in {:.3g} format + auto number_width = 5 // coeff in {:.1f} format + + s.binary_; // potential 4th digit before the decimal point + auto max_width = number_width + 1 // prefix from units array + s.binary_ // for the 'i' in GiB. + s.unit_.length(); @@ -69,15 +71,16 @@ struct formatter { case '<': return format_to(ctx.out(), "{:<{}}", fmt::format("{}", s), max_width); case '=': - format = "{coefficient:<4.3g}{padding}{prefix}{unit}"; + format = "{coefficient:<{number_width}.1f}{padding}{prefix}{unit}"; break; case 0: default: - format = "{coefficient:.3g}{prefix}{unit}"; + format = "{coefficient:.1f}{prefix}{unit}"; break; } return format_to( ctx.out(), format, fmt::arg("coefficient", fraction), + fmt::arg("number_width", number_width), fmt::arg("prefix", std::string() + units[pow] + ((s.binary_ && pow) ? "i" : "")), fmt::arg("unit", s.unit_), fmt::arg("padding", pow ? "" From 061f4550f49a89330fab4157828d8638e4865097 Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Mon, 22 Aug 2022 20:36:21 +0800 Subject: [PATCH 02/91] feat(keyboard): improve keyboard response time Use libinput event for keyboard state updates. The state will update when CAPS_LOCK, NUM_LOCK or SCROLL_LOCK has been released, `interval` will have no effect after this change. --- include/modules/keyboard_state.hpp | 7 ++ meson.build | 5 +- meson_options.txt | 1 + src/modules/keyboard_state.cpp | 128 +++++++++++++++++++++-------- 4 files changed, 104 insertions(+), 37 deletions(-) diff --git a/include/modules/keyboard_state.hpp b/include/modules/keyboard_state.hpp index 05fbec13..07569e4f 100644 --- a/include/modules/keyboard_state.hpp +++ b/include/modules/keyboard_state.hpp @@ -3,12 +3,15 @@ #include #include +#include + #include "AModule.hpp" #include "bar.hpp" #include "util/sleeper_thread.hpp" extern "C" { #include +#include } namespace waybar::modules { @@ -20,6 +23,8 @@ class KeyboardState : public AModule { auto update() -> void; private: + auto findKeyboards() -> void; + Gtk::Box box_; Gtk::Label numlock_label_; Gtk::Label capslock_label_; @@ -34,6 +39,8 @@ class KeyboardState : public AModule { int fd_; libevdev* dev_; + struct libinput* libinput_; + std::unordered_map libinput_devices_; util::SleeperThread thread_; }; diff --git a/meson.build b/meson.build index 3c320068..4035fda7 100644 --- a/meson.build +++ b/meson.build @@ -90,6 +90,7 @@ giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabl jsoncpp = dependency('jsoncpp') sigcpp = dependency('sigc++-2.0') libepoll = dependency('epoll-shim', required: false) +libinput = dependency('libinput', required: get_option('libinput')) libnl = dependency('libnl-3.0', required: get_option('libnl')) libnlgen = dependency('libnl-genl-3.0', required: get_option('libnl')) upower_glib = dependency('upower-glib', required: get_option('upower_glib')) @@ -243,8 +244,9 @@ if libudev.found() and (is_linux or libepoll.found()) src_files += 'src/modules/backlight.cpp' endif -if libevdev.found() and (is_linux or libepoll.found()) +if libevdev.found() and (is_linux or libepoll.found()) and libinput.found() add_project_arguments('-DHAVE_LIBEVDEV', language: 'cpp') + add_project_arguments('-DHAVE_LIBINPUT', language: 'cpp') src_files += 'src/modules/keyboard_state.cpp' endif @@ -304,6 +306,7 @@ executable( gtkmm, dbusmenu_gtk, giounix, + libinput, libnl, libnlgen, upower_glib, diff --git a/meson_options.txt b/meson_options.txt index d2e98476..82ae0d3e 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,4 +1,5 @@ option('libcxx', type : 'boolean', value : false, description : 'Build with Clang\'s libc++ instead of libstdc++ on Linux.') +option('libinput', type: 'feature', value: 'auto', description: 'Enable libinput support for libinput related features') option('libnl', type: 'feature', value: 'auto', description: 'Enable libnl support for network related features') option('libudev', type: 'feature', value: 'auto', description: 'Enable libudev support for udev related features') option('libevdev', type: 'feature', value: 'auto', description: 'Enable libevdev support for evdev related features') diff --git a/src/modules/keyboard_state.cpp b/src/modules/keyboard_state.cpp index 38faacd6..e936057a 100644 --- a/src/modules/keyboard_state.cpp +++ b/src/modules/keyboard_state.cpp @@ -8,8 +8,12 @@ extern "C" { #include +#include +#include +#include #include #include +#include } class errno_error : public std::runtime_error { @@ -73,6 +77,51 @@ auto supportsLockStates(const libevdev* dev) -> bool { libevdev_has_event_code(dev, EV_LED, LED_SCROLLL); } +auto waybar::modules::KeyboardState::findKeyboards() -> void { + if (config_["device-path"].isString()) { + std::string dev_path = config_["device-path"].asString(); + libinput_devices_[dev_path] = nullptr; + fd_ = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY); + dev_ = openDevice(fd_); + } else { + DIR* dev_dir = opendir("/dev/input/by-path"); + if (dev_dir == nullptr) { + throw errno_error(errno, "Failed to open /dev/input"); + } + dirent* ep; + while ((ep = readdir(dev_dir))) { + if (ep->d_type == DT_DIR) continue; + std::string dev_path = std::string("/dev/input/by-path/") + ep->d_name; + int fd = openFile(dev_path.c_str(), O_NONBLOCK | O_CLOEXEC | O_RDONLY); + try { + auto dev = openDevice(fd); + if (supportsLockStates(dev)) { + spdlog::info("Found device {} at '{}'", libevdev_get_name(dev), dev_path); + if (libinput_devices_.empty()) { + fd_ = fd; + dev_ = dev; + } else { + libevdev_free(dev); + closeFile(fd); + } + libinput_devices_[dev_path] = libinput_path_add_device(libinput_, dev_path.c_str()); + } else { + libevdev_free(dev); + closeFile(fd); + } + } catch (const errno_error& e) { + // ENOTTY just means the device isn't an evdev device, skip it + if (e.code != ENOTTY) { + spdlog::warn(e.what()); + } + } + } + if (dev_ == nullptr) { + throw errno_error(errno, "Failed to find keyboard device"); + } + } +} + waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar, const Json::Value& config) : AModule(config, "keyboard-state", id, false, !config["disable-scroll"].asBool()), @@ -100,7 +149,14 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& ? config_["format-icons"]["unlocked"].asString() : "unlocked"), fd_(0), - dev_(nullptr) { + dev_(nullptr), + libinput_(nullptr), + libinput_devices_({}) { + struct libinput_interface interface = { + [](const char* path, int flags, void* user_data) { return open(path, flags); }, + [](int fd, void* user_data) { close(fd); }}; + libinput_ = libinput_path_create_context(&interface, NULL); + box_.set_name("keyboard-state"); if (config_["numlock"].asBool()) { numlock_label_.get_style_context()->add_class("numlock"); @@ -119,44 +175,39 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& } event_box_.add(box_); - if (config_["device-path"].isString()) { - std::string dev_path = config_["device-path"].asString(); - fd_ = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY); - dev_ = openDevice(fd_); - } else { - DIR* dev_dir = opendir("/dev/input"); - if (dev_dir == nullptr) { - throw errno_error(errno, "Failed to open /dev/input"); - } - dirent* ep; - while ((ep = readdir(dev_dir))) { - if (ep->d_type != DT_CHR) continue; - std::string dev_path = std::string("/dev/input/") + ep->d_name; - int fd = openFile(dev_path.c_str(), O_NONBLOCK | O_CLOEXEC | O_RDONLY); - try { - auto dev = openDevice(fd); - if (supportsLockStates(dev)) { - spdlog::info("Found device {} at '{}'", libevdev_get_name(dev), dev_path); - fd_ = fd; - dev_ = dev; - break; - } - } catch (const errno_error& e) { - // ENOTTY just means the device isn't an evdev device, skip it - if (e.code != ENOTTY) { - spdlog::warn(e.what()); - } - } - closeFile(fd); - } - if (dev_ == nullptr) { - throw errno_error(errno, "Failed to find keyboard device"); - } - } + findKeyboards(); thread_ = [this] { dp.emit(); - thread_.sleep_for(interval_); + while (1) { + struct pollfd fd = {libinput_get_fd(libinput_), POLLIN, 0}; + poll(&fd, 1, -1); + libinput_dispatch(libinput_); + struct libinput_event* event; + while ((event = libinput_get_event(libinput_))) { + auto type = libinput_event_get_type(event); + if (type == LIBINPUT_EVENT_KEYBOARD_KEY) { + auto keyboard_event = libinput_event_get_keyboard_event(event); + auto state = libinput_event_keyboard_get_key_state(keyboard_event); + if (state == LIBINPUT_KEY_STATE_RELEASED) { + uint32_t key = libinput_event_keyboard_get_key(keyboard_event); + switch (key) { + case KEY_CAPSLOCK: + case KEY_NUMLOCK: + case KEY_SCROLLLOCK: + dp.emit(); + break; + default: + break; + } + } + } else if (type == LIBINPUT_EVENT_DEVICE_REMOVED) { + // TODO: Handle device removal. + // Clear libinput_devices_ and re-find keyboards. + } + libinput_event_destroy(event); + } + } }; } @@ -167,9 +218,14 @@ waybar::modules::KeyboardState::~KeyboardState() { } catch (const std::runtime_error& e) { spdlog::warn(e.what()); } + for (const auto& [_, dev_ptr] : libinput_devices_) { + libinput_path_remove_device(dev_ptr); + } } auto waybar::modules::KeyboardState::update() -> void { + sleep(0); // wait for keyboard status change + int err = LIBEVDEV_READ_STATUS_SUCCESS; while (err == LIBEVDEV_READ_STATUS_SUCCESS) { input_event ev; From dcd75b3b4018a7dbf3484addbf99e0fe26615da4 Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Tue, 23 Aug 2022 23:18:40 +0800 Subject: [PATCH 03/91] feat(keybaord): enable hotplug support Use inotify listening devices path changes to implement hotplug support. The new hotplug thread is also an event loop, so the interval value has no effect. The evdev is now open on demand. Fix libinput_interface object life-time. --- include/modules/keyboard_state.hpp | 7 +- src/modules/keyboard_state.cpp | 178 +++++++++++++++++------------ 2 files changed, 108 insertions(+), 77 deletions(-) diff --git a/include/modules/keyboard_state.hpp b/include/modules/keyboard_state.hpp index 07569e4f..ce9faba0 100644 --- a/include/modules/keyboard_state.hpp +++ b/include/modules/keyboard_state.hpp @@ -23,7 +23,7 @@ class KeyboardState : public AModule { auto update() -> void; private: - auto findKeyboards() -> void; + auto tryAddDevice(const std::string&) -> void; Gtk::Box box_; Gtk::Label numlock_label_; @@ -36,13 +36,12 @@ class KeyboardState : public AModule { const std::chrono::seconds interval_; std::string icon_locked_; std::string icon_unlocked_; + std::string devices_path_; - int fd_; - libevdev* dev_; struct libinput* libinput_; std::unordered_map libinput_devices_; - util::SleeperThread thread_; + util::SleeperThread libinput_thread_, hotplug_thread_; }; } // namespace waybar::modules diff --git a/src/modules/keyboard_state.cpp b/src/modules/keyboard_state.cpp index e936057a..40e8d930 100644 --- a/src/modules/keyboard_state.cpp +++ b/src/modules/keyboard_state.cpp @@ -11,6 +11,7 @@ extern "C" { #include #include #include +#include #include #include #include @@ -77,51 +78,6 @@ auto supportsLockStates(const libevdev* dev) -> bool { libevdev_has_event_code(dev, EV_LED, LED_SCROLLL); } -auto waybar::modules::KeyboardState::findKeyboards() -> void { - if (config_["device-path"].isString()) { - std::string dev_path = config_["device-path"].asString(); - libinput_devices_[dev_path] = nullptr; - fd_ = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY); - dev_ = openDevice(fd_); - } else { - DIR* dev_dir = opendir("/dev/input/by-path"); - if (dev_dir == nullptr) { - throw errno_error(errno, "Failed to open /dev/input"); - } - dirent* ep; - while ((ep = readdir(dev_dir))) { - if (ep->d_type == DT_DIR) continue; - std::string dev_path = std::string("/dev/input/by-path/") + ep->d_name; - int fd = openFile(dev_path.c_str(), O_NONBLOCK | O_CLOEXEC | O_RDONLY); - try { - auto dev = openDevice(fd); - if (supportsLockStates(dev)) { - spdlog::info("Found device {} at '{}'", libevdev_get_name(dev), dev_path); - if (libinput_devices_.empty()) { - fd_ = fd; - dev_ = dev; - } else { - libevdev_free(dev); - closeFile(fd); - } - libinput_devices_[dev_path] = libinput_path_add_device(libinput_, dev_path.c_str()); - } else { - libevdev_free(dev); - closeFile(fd); - } - } catch (const errno_error& e) { - // ENOTTY just means the device isn't an evdev device, skip it - if (e.code != ENOTTY) { - spdlog::warn(e.what()); - } - } - } - if (dev_ == nullptr) { - throw errno_error(errno, "Failed to find keyboard device"); - } - } -} - waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& bar, const Json::Value& config) : AModule(config, "keyboard-state", id, false, !config["disable-scroll"].asBool()), @@ -148,11 +104,10 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& icon_unlocked_(config_["format-icons"]["unlocked"].isString() ? config_["format-icons"]["unlocked"].asString() : "unlocked"), - fd_(0), - dev_(nullptr), + devices_path_("/dev/input/"), libinput_(nullptr), libinput_devices_({}) { - struct libinput_interface interface = { + static struct libinput_interface interface = { [](const char* path, int flags, void* user_data) { return open(path, flags); }, [](int fd, void* user_data) { close(fd); }}; libinput_ = libinput_path_create_context(&interface, NULL); @@ -175,9 +130,26 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& } event_box_.add(box_); - findKeyboards(); + if (config_["device-path"].isString()) { + std::string dev_path = config_["device-path"].asString(); + tryAddDevice(dev_path); + } else { + DIR* dev_dir = opendir(devices_path_.c_str()); + if (dev_dir == nullptr) { + throw errno_error(errno, "Failed to open " + devices_path_); + } + dirent* ep; + while ((ep = readdir(dev_dir))) { + if (ep->d_type == DT_DIR) continue; + std::string dev_path = devices_path_ + ep->d_name; + tryAddDevice(dev_path); + } + } + if (libinput_devices_.empty()) { + throw errno_error(errno, "Failed to find keyboard device"); + } - thread_ = [this] { + libinput_thread_ = [this] { dp.emit(); while (1) { struct pollfd fd = {libinput_get_fd(libinput_), POLLIN, 0}; @@ -201,46 +173,84 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& break; } } - } else if (type == LIBINPUT_EVENT_DEVICE_REMOVED) { - // TODO: Handle device removal. - // Clear libinput_devices_ and re-find keyboards. } libinput_event_destroy(event); } } }; + + hotplug_thread_ = [this] { + int fd; + fd = inotify_init(); + if (fd < 0) { + spdlog::error("Failed to initialize inotify: {}", strerror(errno)); + return; + } + inotify_add_watch(fd, devices_path_.c_str(), IN_CREATE | IN_DELETE); + while (1) { + int BUF_LEN = 1024 * (sizeof(struct inotify_event) + 16); + char buf[BUF_LEN]; + int length = read(fd, buf, 1024); + if (length < 0) { + spdlog::error("Failed to read inotify: {}", strerror(errno)); + return; + } + for (int i = 0; i < length;) { + struct inotify_event* event = (struct inotify_event*)&buf[i]; + std::string dev_path = devices_path_ + event->name; + if (event->mask & IN_CREATE) { + // Wait for device setup + int timeout = 10; + while (timeout--) { + try { + int fd = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY); + closeFile(fd); + break; + } catch (const errno_error& e) { + if (e.code == EACCES) { + sleep(1); + } + } + } + tryAddDevice(dev_path); + } else if (event->mask & IN_DELETE) { + auto it = libinput_devices_.find(dev_path); + if (it != libinput_devices_.end()) { + spdlog::info("Keyboard {} has been removed.", dev_path); + libinput_devices_.erase(it); + } + } + i += sizeof(struct inotify_event) + event->len; + } + } + }; } waybar::modules::KeyboardState::~KeyboardState() { - libevdev_free(dev_); - try { - closeFile(fd_); - } catch (const std::runtime_error& e) { - spdlog::warn(e.what()); - } for (const auto& [_, dev_ptr] : libinput_devices_) { libinput_path_remove_device(dev_ptr); } } auto waybar::modules::KeyboardState::update() -> void { - sleep(0); // wait for keyboard status change + sleep(0); // Wait for keyboard status change + int numl = 0, capsl = 0, scrolll = 0; - int err = LIBEVDEV_READ_STATUS_SUCCESS; - while (err == LIBEVDEV_READ_STATUS_SUCCESS) { - input_event ev; - err = libevdev_next_event(dev_, LIBEVDEV_READ_FLAG_NORMAL, &ev); - while (err == LIBEVDEV_READ_STATUS_SYNC) { - err = libevdev_next_event(dev_, LIBEVDEV_READ_FLAG_SYNC, &ev); + try { + std::string dev_path = libinput_devices_.begin()->first; + int fd = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY); + auto dev = openDevice(fd); + numl = libevdev_get_event_value(dev, EV_LED, LED_NUML); + capsl = libevdev_get_event_value(dev, EV_LED, LED_CAPSL); + scrolll = libevdev_get_event_value(dev, EV_LED, LED_SCROLLL); + libevdev_free(dev); + closeFile(fd); + } catch (const errno_error& e) { + // ENOTTY just means the device isn't an evdev device, skip it + if (e.code != ENOTTY) { + spdlog::warn(e.what()); } } - if (-err != EAGAIN) { - throw errno_error(-err, "Failed to sync evdev device"); - } - - int numl = libevdev_get_event_value(dev_, EV_LED, LED_NUML); - int capsl = libevdev_get_event_value(dev_, EV_LED, LED_CAPSL); - int scrolll = libevdev_get_event_value(dev_, EV_LED, LED_SCROLLL); struct { bool state; @@ -267,3 +277,25 @@ auto waybar::modules::KeyboardState::update() -> void { AModule::update(); } + +auto waybar::modules ::KeyboardState::tryAddDevice(const std::string& dev_path) -> void { + try { + int fd = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY); + auto dev = openDevice(fd); + if (supportsLockStates(dev)) { + spdlog::info("Found device {} at '{}'", libevdev_get_name(dev), dev_path); + if (libinput_devices_.find(dev_path) == libinput_devices_.end()) { + auto device = libinput_path_add_device(libinput_, dev_path.c_str()); + libinput_device_ref(device); + libinput_devices_[dev_path] = device; + } + } + libevdev_free(dev); + closeFile(fd); + } catch (const errno_error& e) { + // ENOTTY just means the device isn't an evdev device, skip it + if (e.code != ENOTTY) { + spdlog::warn(e.what()); + } + } +} From 58a399b9afc961053b6c93501e6c29aa63ca45de Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Wed, 24 Aug 2022 02:22:40 +0800 Subject: [PATCH 04/91] chore(ci, meson): add inotify dependency for BSD --- .github/workflows/freebsd.yml | 3 ++- meson.build | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index cc1c4b4e..a6da7ef7 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -21,7 +21,8 @@ jobs: pkg install -y git # subprojects/date pkg install -y catch evdev-proto gtk-layer-shell gtkmm30 jsoncpp \ libdbusmenu libevdev libfmt libmpdclient libudev-devd meson \ - pkgconf pulseaudio scdoc sndio spdlog wayland-protocols upower + pkgconf pulseaudio scdoc sndio spdlog wayland-protocols upower \ + libinotify run: | meson build -Dman-pages=enabled ninja -C build diff --git a/meson.build b/meson.build index 4035fda7..0a9ef280 100644 --- a/meson.build +++ b/meson.build @@ -89,6 +89,7 @@ dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gt giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabled() or get_option('logind').enabled() or get_option('upower_glib').enabled())) jsoncpp = dependency('jsoncpp') sigcpp = dependency('sigc++-2.0') +libinotify = dependency('libinotify', required: false) libepoll = dependency('epoll-shim', required: false) libinput = dependency('libinput', required: get_option('libinput')) libnl = dependency('libnl-3.0', required: get_option('libnl')) @@ -244,7 +245,7 @@ if libudev.found() and (is_linux or libepoll.found()) src_files += 'src/modules/backlight.cpp' endif -if libevdev.found() and (is_linux or libepoll.found()) and libinput.found() +if libevdev.found() and (is_linux or libepoll.found()) and libinput.found() and (is_linux or libinotify.found()) add_project_arguments('-DHAVE_LIBEVDEV', language: 'cpp') add_project_arguments('-DHAVE_LIBINPUT', language: 'cpp') src_files += 'src/modules/keyboard_state.cpp' @@ -312,6 +313,7 @@ executable( upower_glib, libpulse, libudev, + libinotify, libepoll, libmpdclient, libevdev, From 5944989a8aab120ea695193b63c5affb8691c868 Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Wed, 24 Aug 2022 02:41:12 +0800 Subject: [PATCH 05/91] doc(keyboard): add deprecated warning --- man/waybar-keyboard-state.5.scd | 1 + src/modules/keyboard_state.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/man/waybar-keyboard-state.5.scd b/man/waybar-keyboard-state.5.scd index 905a321f..fef46709 100644 --- a/man/waybar-keyboard-state.5.scd +++ b/man/waybar-keyboard-state.5.scd @@ -13,6 +13,7 @@ You must be a member of the input group to use this module. # CONFIGURATION *interval*: ++ + Deprecated, this module use event loop now, the interval has no effect. typeof: integer ++ default: 1 ++ The interval, in seconds, to poll the keyboard state. diff --git a/src/modules/keyboard_state.cpp b/src/modules/keyboard_state.cpp index 40e8d930..f3e846dd 100644 --- a/src/modules/keyboard_state.cpp +++ b/src/modules/keyboard_state.cpp @@ -110,6 +110,10 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& static struct libinput_interface interface = { [](const char* path, int flags, void* user_data) { return open(path, flags); }, [](int fd, void* user_data) { close(fd); }}; + if (config_["interval"].isUInt()) { + spdlog::warn("keyboard-state: interval is deprecated"); + } + libinput_ = libinput_path_create_context(&interface, NULL); box_.set_name("keyboard-state"); From 8b03e38594261bf623f306606b278ca3c1c5a804 Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Wed, 24 Aug 2022 14:08:34 +0800 Subject: [PATCH 06/91] fix(keyboard): correct device-path config behavior --- src/modules/keyboard_state.cpp | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/modules/keyboard_state.cpp b/src/modules/keyboard_state.cpp index f3e846dd..b2750b68 100644 --- a/src/modules/keyboard_state.cpp +++ b/src/modules/keyboard_state.cpp @@ -137,18 +137,22 @@ waybar::modules::KeyboardState::KeyboardState(const std::string& id, const Bar& if (config_["device-path"].isString()) { std::string dev_path = config_["device-path"].asString(); tryAddDevice(dev_path); - } else { - DIR* dev_dir = opendir(devices_path_.c_str()); - if (dev_dir == nullptr) { - throw errno_error(errno, "Failed to open " + devices_path_); - } - dirent* ep; - while ((ep = readdir(dev_dir))) { - if (ep->d_type == DT_DIR) continue; - std::string dev_path = devices_path_ + ep->d_name; - tryAddDevice(dev_path); + if (libinput_devices_.empty()) { + spdlog::error("keyboard-state: Cannot find device {}", dev_path); } } + + DIR* dev_dir = opendir(devices_path_.c_str()); + if (dev_dir == nullptr) { + throw errno_error(errno, "Failed to open " + devices_path_); + } + dirent* ep; + while ((ep = readdir(dev_dir))) { + if (ep->d_type == DT_DIR) continue; + std::string dev_path = devices_path_ + ep->d_name; + tryAddDevice(dev_path); + } + if (libinput_devices_.empty()) { throw errno_error(errno, "Failed to find keyboard device"); } @@ -241,7 +245,13 @@ auto waybar::modules::KeyboardState::update() -> void { int numl = 0, capsl = 0, scrolll = 0; try { - std::string dev_path = libinput_devices_.begin()->first; + std::string dev_path; + if (config_["device-path"].isString() && + libinput_devices_.find(config_["device-path"].asString()) != libinput_devices_.end()) { + dev_path = config_["device-path"].asString(); + } else { + dev_path = libinput_devices_.begin()->first; + } int fd = openFile(dev_path, O_NONBLOCK | O_CLOEXEC | O_RDONLY); auto dev = openDevice(fd); numl = libevdev_get_event_value(dev, EV_LED, LED_NUML); From e3342467fcdb7fc6c38610dacbd2e272d565900b Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Mon, 29 Aug 2022 04:55:48 +0800 Subject: [PATCH 07/91] feat(sway/scratchpad): add basic counter --- include/factory.hpp | 1 + include/modules/sway/scratchpad.hpp | 34 +++++++++++++++++++ meson.build | 3 +- src/factory.cpp | 3 ++ src/modules/sway/scratchpad.cpp | 52 +++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 include/modules/sway/scratchpad.hpp create mode 100644 src/modules/sway/scratchpad.cpp diff --git a/include/factory.hpp b/include/factory.hpp index 47ef530b..0bd4a909 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -9,6 +9,7 @@ #ifdef HAVE_SWAY #include "modules/sway/language.hpp" #include "modules/sway/mode.hpp" +#include "modules/sway/scratchpad.hpp" #include "modules/sway/window.hpp" #include "modules/sway/workspaces.hpp" #endif diff --git a/include/modules/sway/scratchpad.hpp b/include/modules/sway/scratchpad.hpp new file mode 100644 index 00000000..9464a6ed --- /dev/null +++ b/include/modules/sway/scratchpad.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include +#include + +#include "ALabel.hpp" +#include "bar.hpp" +#include "client.hpp" +#include "modules/sway/ipc/client.hpp" +#include "util/json.hpp" + +namespace waybar::modules::sway { +// class Scratchpad : public AModule, public sigc::trackable { +class Scratchpad : public ALabel { + public: + Scratchpad(const std::string&, const waybar::Bar&, const Json::Value&); + ~Scratchpad() = default; + auto update() -> void; + + private: + auto getTree() -> void; + auto onCmd(const struct Ipc::ipc_response&) -> void; + auto onEvent(const struct Ipc::ipc_response&) -> void; + // bool handleScroll(GdkEventScroll*); + Gtk::Box box_; + const Bar& bar_; + std::mutex mutex_; + int count_; + Ipc ipc_; + util::JsonParser parser_; +}; +} // namespace waybar::modules::sway \ No newline at end of file diff --git a/meson.build b/meson.build index 3c320068..d1442ec5 100644 --- a/meson.build +++ b/meson.build @@ -184,7 +184,8 @@ src_files += [ 'src/modules/sway/mode.cpp', 'src/modules/sway/language.cpp', 'src/modules/sway/window.cpp', - 'src/modules/sway/workspaces.cpp' + 'src/modules/sway/workspaces.cpp', + 'src/modules/sway/scratchpad.cpp' ] if true diff --git a/src/factory.cpp b/src/factory.cpp index 6df69d5c..4a72d403 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -35,6 +35,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { if (ref == "sway/language") { return new waybar::modules::sway::Language(id, config_[name]); } + if (ref == "sway/scratchpad") { + return new waybar::modules::sway::Scratchpad(id, bar_, config_[name]); + } #endif #ifdef HAVE_WLR if (ref == "wlr/taskbar") { diff --git a/src/modules/sway/scratchpad.cpp b/src/modules/sway/scratchpad.cpp new file mode 100644 index 00000000..a7fd7baf --- /dev/null +++ b/src/modules/sway/scratchpad.cpp @@ -0,0 +1,52 @@ +#include "modules/sway/scratchpad.hpp" + +#include + +#include + +namespace waybar::modules::sway { +Scratchpad::Scratchpad(const std::string& id, const waybar::Bar& bar, const Json::Value& config) + : ALabel(config, "scratchpad", id, "{count}"), + box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0), + bar_(bar), + count_(0) { + ipc_.subscribe(R"(["window"])"); + ipc_.signal_event.connect(sigc::mem_fun(*this, &Scratchpad::onEvent)); + ipc_.signal_cmd.connect(sigc::mem_fun(*this, &Scratchpad::onCmd)); + + getTree(); + + ipc_.setWorker([this] { + try { + ipc_.handleEvent(); + } catch (const std::exception& e) { + spdlog::error("Scratchpad: {}", e.what()); + } + }); +} +auto Scratchpad::update() -> void { + label_.set_markup(fmt::format(format_, fmt::arg("count", count_))); + AModule::update(); +} + +auto Scratchpad::getTree() -> void { + try { + ipc_.sendCmd(IPC_GET_TREE); + } catch (const std::exception& e) { + spdlog::error("Scratchpad: {}", e.what()); + } +} + +auto Scratchpad::onCmd(const struct Ipc::ipc_response& res) -> void { + try { + std::lock_guard lock(mutex_); + auto tree = parser_.parse(res.payload); + count_ = tree["nodes"][0]["nodes"][0]["floating_nodes"].size(); + dp.emit(); + } catch (const std::exception& e) { + spdlog::error("Scratchpad: {}", e.what()); + } +} + +auto Scratchpad::onEvent(const struct Ipc::ipc_response& res) -> void { getTree(); } +} // namespace waybar::modules::sway \ No newline at end of file From d2ff116c928c0e6927a88035decef3117a56d938 Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Wed, 31 Aug 2022 01:54:19 +0800 Subject: [PATCH 08/91] feat(sway/scratchpad): add some configs Add some configs for displaying. Remove draft codes. --- include/modules/sway/scratchpad.hpp | 13 ++++----- resources/config | 9 ++++++- resources/style.css | 9 +++++++ src/factory.cpp | 2 +- src/modules/sway/scratchpad.cpp | 42 ++++++++++++++++++++++++----- 5 files changed, 61 insertions(+), 14 deletions(-) diff --git a/include/modules/sway/scratchpad.hpp b/include/modules/sway/scratchpad.hpp index 9464a6ed..e68e7726 100644 --- a/include/modules/sway/scratchpad.hpp +++ b/include/modules/sway/scratchpad.hpp @@ -12,10 +12,9 @@ #include "util/json.hpp" namespace waybar::modules::sway { -// class Scratchpad : public AModule, public sigc::trackable { class Scratchpad : public ALabel { public: - Scratchpad(const std::string&, const waybar::Bar&, const Json::Value&); + Scratchpad(const std::string&, const Json::Value&); ~Scratchpad() = default; auto update() -> void; @@ -23,11 +22,13 @@ class Scratchpad : public ALabel { auto getTree() -> void; auto onCmd(const struct Ipc::ipc_response&) -> void; auto onEvent(const struct Ipc::ipc_response&) -> void; - // bool handleScroll(GdkEventScroll*); - Gtk::Box box_; - const Bar& bar_; - std::mutex mutex_; + + std::string tooltip_format_; + bool show_empty_; + bool tooltip_enabled_; + std::string tooltip_text_; int count_; + std::mutex mutex_; Ipc ipc_; util::JsonParser parser_; }; diff --git a/resources/config b/resources/config index 6a753acf..ad76e937 100644 --- a/resources/config +++ b/resources/config @@ -5,7 +5,7 @@ // "width": 1280, // Waybar width "spacing": 4, // Gaps between modules (4px) // Choose the order of the modules - "modules-left": ["sway/workspaces", "sway/mode", "custom/media"], + "modules-left": ["sway/workspaces", "sway/mode", "sway/scratchpad", "custom/media"], "modules-center": ["sway/window"], "modules-right": ["mpd", "idle_inhibitor", "pulseaudio", "network", "cpu", "memory", "temperature", "backlight", "keyboard-state", "sway/language", "battery", "battery#bat2", "clock", "tray"], // Modules configuration @@ -36,6 +36,13 @@ "sway/mode": { "format": "{}" }, + "sway/scratchpad": { + "format": "{icon} {count}", + "show-empty": false, + "format-icons": ["", ""], + "tooltip": true, + "tooltip-format": "{app}: {title}" + }, "mpd": { "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ", "format-disconnected": "Disconnected ", diff --git a/resources/style.css b/resources/style.css index 563ee0dd..d22cd252 100644 --- a/resources/style.css +++ b/resources/style.css @@ -78,6 +78,7 @@ window#waybar.chromium { #tray, #mode, #idle_inhibitor, +#scratchpad, #mpd { padding: 0 10px; color: #ffffff; @@ -252,3 +253,11 @@ label:focus { #keyboard-state > label.locked { background: rgba(0, 0, 0, 0.2); } + +#scratchpad { + background: rgba(0, 0, 0, 0.2); +} + +#scratchpad.empty { + background-color: transparent; +} diff --git a/src/factory.cpp b/src/factory.cpp index 4a72d403..f29b0f58 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -36,7 +36,7 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { return new waybar::modules::sway::Language(id, config_[name]); } if (ref == "sway/scratchpad") { - return new waybar::modules::sway::Scratchpad(id, bar_, config_[name]); + return new waybar::modules::sway::Scratchpad(id, config_[name]); } #endif #ifdef HAVE_WLR diff --git a/src/modules/sway/scratchpad.cpp b/src/modules/sway/scratchpad.cpp index a7fd7baf..59e30530 100644 --- a/src/modules/sway/scratchpad.cpp +++ b/src/modules/sway/scratchpad.cpp @@ -5,10 +5,14 @@ #include namespace waybar::modules::sway { -Scratchpad::Scratchpad(const std::string& id, const waybar::Bar& bar, const Json::Value& config) - : ALabel(config, "scratchpad", id, "{count}"), - box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0), - bar_(bar), +Scratchpad::Scratchpad(const std::string& id, const Json::Value& config) + : ALabel(config, "scratchpad", id, + config["format"].isString() ? config["format"].asString() : "{icon} {count}"), + tooltip_format_(config_["tooltip-format"].isString() ? config_["tooltip-format"].asString() + : "{app}: {title}"), + show_empty_(config_["show-empty"].isBool() ? config_["show-empty"].asBool() : false), + tooltip_enabled_(config_["tooltip"].isBool() ? config_["tooltip"].asBool() : true), + tooltip_text_(""), count_(0) { ipc_.subscribe(R"(["window"])"); ipc_.signal_event.connect(sigc::mem_fun(*this, &Scratchpad::onEvent)); @@ -25,8 +29,23 @@ Scratchpad::Scratchpad(const std::string& id, const waybar::Bar& bar, const Json }); } auto Scratchpad::update() -> void { - label_.set_markup(fmt::format(format_, fmt::arg("count", count_))); - AModule::update(); + if (count_ || show_empty_) { + event_box_.show(); + label_.set_markup( + fmt::format(format_, fmt::arg("icon", getIcon(count_, "", config_["format-icons"].size())), + fmt::arg("count", count_))); + if (tooltip_enabled_) { + label_.set_tooltip_markup(tooltip_text_); + } + } else { + event_box_.hide(); + } + if (count_) { + label_.get_style_context()->remove_class("empty"); + } else { + label_.get_style_context()->add_class("empty"); + } + ALabel::update(); } auto Scratchpad::getTree() -> void { @@ -42,6 +61,17 @@ auto Scratchpad::onCmd(const struct Ipc::ipc_response& res) -> void { std::lock_guard lock(mutex_); auto tree = parser_.parse(res.payload); count_ = tree["nodes"][0]["nodes"][0]["floating_nodes"].size(); + if (tooltip_enabled_) { + tooltip_text_.clear(); + for (const auto& window : tree["nodes"][0]["nodes"][0]["floating_nodes"]) { + tooltip_text_.append(fmt::format(tooltip_format_ + '\n', + fmt::arg("app", window["app_id"].asString()), + fmt::arg("title", window["name"].asString()))); + } + if (!tooltip_text_.empty()) { + tooltip_text_.pop_back(); + } + } dp.emit(); } catch (const std::exception& e) { spdlog::error("Scratchpad: {}", e.what()); From bc201fd0eb72000daf90b385a25f02e2d89231f1 Mon Sep 17 00:00:00 2001 From: asas1asas200 Date: Wed, 31 Aug 2022 02:27:30 +0800 Subject: [PATCH 09/91] doc(sway/scratchpad): add man page --- man/waybar-sway-scratchpad.5.scd | 64 ++++++++++++++++++++++++++++++++ man/waybar.5.scd.in | 1 + meson.build | 1 + 3 files changed, 66 insertions(+) create mode 100644 man/waybar-sway-scratchpad.5.scd diff --git a/man/waybar-sway-scratchpad.5.scd b/man/waybar-sway-scratchpad.5.scd new file mode 100644 index 00000000..11fc32c0 --- /dev/null +++ b/man/waybar-sway-scratchpad.5.scd @@ -0,0 +1,64 @@ +waybar-sway-scratchpad(5) + +# NAME + +waybar - sway scratchpad module + +# DESCRIPTION + +The *scratchpad* module displays the scratchpad status in Sway + +# CONFIGURATION + +Addressed by *sway/scratchpad* + +*format*: ++ + typeof: string ++ + default: {icon} {count} ++ + The format, how information should be displayed. + +*show-empty*: ++ + typeof: bool ++ + default: false ++ + Option to show module when scratchpad is empty. + +*format-icons*: ++ + typeof: array/object ++ + Based on the current scratchpad window counts, the corresponding icon gets selected. + +*tooltip*: ++ + typeof: bool ++ + default: true ++ + Option to disable tooltip on hover. + +*tooltip-format*: ++ + typeof: string ++ + default: {app}: {title} ++ + The format, how information in the tooltip should be displayed. + +# FORMAT REPLACEMENTS + +*{icon}*: Icon, as defined in *format-icons*. + +*{count}*: Number of windows in the scratchpad. + +*{app}*: Name of the application in the scratchpad. + +*{title}*: Title of the application in the scratchpad. + +# EXAMPLES + +``` +"sway/scratchpad": { + "format": "{icon} {count}", + "show-empty": false, + "format-icons": ["", ""], + "tooltip": true, + "tooltip-format": "{app}: {title}" +} +``` + +# STYLE + +- *#scratchpad* +- *#scratchpad.empty* diff --git a/man/waybar.5.scd.in b/man/waybar.5.scd.in index fafc2b36..54340f21 100644 --- a/man/waybar.5.scd.in +++ b/man/waybar.5.scd.in @@ -273,6 +273,7 @@ A module group is defined by specifying a module named "group/some-group-name". - *waybar-river-window(5)* - *waybar-states(5)* - *waybar-sway-mode(5)* +- *waybar-sway-scratchpad(5)* - *waybar-sway-window(5)* - *waybar-sway-workspaces(5)* - *waybar-wlr-taskbar(5)* diff --git a/meson.build b/meson.build index d1442ec5..9fdabb2c 100644 --- a/meson.build +++ b/meson.build @@ -365,6 +365,7 @@ if scdoc.found() 'waybar-river-window.5.scd', 'waybar-sway-language.5.scd', 'waybar-sway-mode.5.scd', + 'waybar-sway-scratchpad.5.scd', 'waybar-sway-window.5.scd', 'waybar-sway-workspaces.5.scd', 'waybar-temperature.5.scd', From 120c68e014af7f379749e826bcd39e0e88d8eb3c Mon Sep 17 00:00:00 2001 From: Tom Charnock Date: Fri, 2 Sep 2022 11:42:46 +0200 Subject: [PATCH 10/91] Updated logic in battery module --- src/modules/battery.cpp | 263 ++++++++++++++++++++++++++++------------ 1 file changed, 184 insertions(+), 79 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 60194f0f..b47aee98 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -157,122 +157,227 @@ const std::tuple waybar::modules::Battery::g try { uint32_t total_power = 0; // μW + bool total_power_exists = false; uint32_t total_energy = 0; // μWh + bool total_energy_exists = false; uint32_t total_energy_full = 0; + bool total_energy_full_exists = false; uint32_t total_energy_full_design = 0; + bool total_energy_full_design_exists = false; uint32_t total_capacity{0}; + bool total_capacity_exists = false; + std::string status = "Unknown"; for (auto const& item : batteries_) { auto bat = item.first; - uint32_t power_now; - uint32_t energy_full; - uint32_t energy_now; - uint32_t energy_full_design; - uint32_t capacity{0}; std::string _status; std::getline(std::ifstream(bat / "status"), _status); // Some battery will report current and charge in μA/μAh. // Scale these by the voltage to get μW/μWh. - if (fs::exists(bat / "current_now") || fs::exists(bat / "current_avg")) { - uint32_t voltage_now; - uint32_t current_now; - uint32_t charge_now; - uint32_t charge_full; - uint32_t charge_full_design; - // Some batteries have only *_avg, not *_now - if (fs::exists(bat / "voltage_now")) - std::ifstream(bat / "voltage_now") >> voltage_now; - else - std::ifstream(bat / "voltage_avg") >> voltage_now; - if (fs::exists(bat / "current_now")) - std::ifstream(bat / "current_now") >> current_now; - else - std::ifstream(bat / "current_avg") >> current_now; - std::ifstream(bat / "charge_full") >> charge_full; - std::ifstream(bat / "charge_full_design") >> charge_full_design; - if (fs::exists(bat / "charge_now")) - std::ifstream(bat / "charge_now") >> charge_now; - else { - // charge_now is missing on some systems, estimate using capacity. - uint32_t capacity; - std::ifstream(bat / "capacity") >> capacity; - charge_now = (capacity * charge_full) / 100; - } - power_now = ((uint64_t)current_now * (uint64_t)voltage_now) / 1000000; - energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000; - energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000; - energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000; - } // Gamepads such as PS Dualshock provide the only capacity - else if (fs::exists(bat / "energy_now") && fs::exists(bat / "energy_full")) { - std::ifstream(bat / "power_now") >> power_now; - std::ifstream(bat / "energy_now") >> energy_now; - std::ifstream(bat / "energy_full") >> energy_full; - std::ifstream(bat / "energy_full_design") >> energy_full_design; - } else { + + uint32_t capacity; + bool capacity_exists; + if (fs::exists(bat / "capacity")) { + capacity_exists = true; std::ifstream(bat / "capacity") >> capacity; + } else { + capacity_exists = false; + capacity = 0; + } + + uint32_t current_now; + bool current_now_exists; + if (fs::exists(bat / "current_now")) { + current_now_exists = true; + std::ifstream(bat / "current_now") >> current_now; + } else if (fs::exists(bat / "current_avg")) { + current_now_exists = true; + std::ifstream(bat / "current_avg") >> current_now; + } else { + current_now_exists = false; + current_now = 0; + } + + uint32_t voltage_now; + bool voltage_now_exists; + if (fs::exists(bat / "voltage_now")) { + voltage_now_exists = true; + std::ifstream(bat / "voltage_now") >> voltage_now; + } else if (fs::exists(bat / "voltage_avg")) { + voltage_now_exists = true; + std::ifstream(bat / "voltage_avg") >> voltage_now; + } else { + voltage_now_exists = false; + voltage_now = 0; + } + + uint32_t charge_full; + bool charge_full_exists; + if (fs::exists(bat / "charge_full")) { + charge_full_exists = true; + std::ifstream(bat / "charge_full") >> charge_full; + } else { + charge_full_exists = false; + charge_full = 0; + } + + uint32_t charge_full_design; + bool charge_full_design_exists; + if (fs::exists(bat / "charge_full_design")) { + charge_full_design_exists = true; + std::ifstream(bat / "charge_full_design") >> charge_full_design; + } else { + charge_full_design_exists = false; + charge_full_design = 0; + } + + uint32_t charge_now; + bool charge_now_exists; + if (fs::exists(bat / "charge_now")) { + charge_now_exists = true; + std::ifstream(bat / "charge_now") >> charge_now; + } else if (capacity_exists && charge_full_exists) { + // charge_now is missing on some systems, estimate using capacity and charge_full. + charge_now_exists = true; // this could be debatably set to false (same for all properties below) + charge_now = (capacity * charge_full) / 100; + } else { + charge_now_exists = false; + charge_now = 0; + } + + uint32_t power_now; + bool power_now_exists; + if (fs::exists(bat / "power_now")) { + power_now_exists = true; + std::ifstream(bat / "power_now") >> power_now; + } else if (current_now_exists && voltage_now_exists) { + power_now_exists = true; + power_now = ((uint64_t)current_now * (uint64_t)voltage_now) / 1000000; + } else { + power_now_exists = false; power_now = 0; + } + + uint32_t energy_now; + bool energy_now_exists; + if (fs::exists(bat / "energy_now")) { + energy_now_exists = true; + std::ifstream(bat / "energy_now") >> energy_now; + } else if (charge_now_exists && voltage_now_exists) { + energy_now_exists = true; + energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000; + } else { + energy_now_exists = false; energy_now = 0; + } + + uint32_t energy_full; + bool energy_full_exists; + if (fs::exists(bat / "energy_full")) { + energy_full_exists = true; + std::ifstream(bat / "energy_full") >> energy_full; + } else if (charge_full_exists && voltage_now_exists) { + energy_full_exists = true; + energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000; + } else { + energy_full_exists = false; energy_full = 0; + } + + uint32_t energy_full_design; + bool energy_full_design_exists; + if (fs::exists(bat / "energy_full_design")) { + energy_full_design_exists = true; + std::ifstream(bat / "energy_full_design") >> energy_full_design; + } else if (charge_full_design_exists && voltage_now_exists) { + energy_full_design_exists = true; + energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000; + } else { + energy_full_design_exists = false; energy_full_design = 0; } // Show the "smallest" status among all batteries - if (status_gt(status, _status)) { + if (status_gt(status, _status)) status = _status; + + if (power_now_exists) { + total_power_exists = true; + total_power += power_now; + } + if (energy_now_exists) { + total_energy_exists = true; + total_energy += energy_now; + } + if (energy_full_exists) { + total_energy_full_exists = true; + total_energy_full += energy_full; + } + if (energy_full_design_exists) { + total_energy_full_design_exists = true; + total_energy_full_design += energy_full_design; + } + if (capacity_exists) { + total_capacity_exists = true; + total_capacity += capacity; } - total_power += power_now; - total_energy += energy_now; - total_energy_full += energy_full; - total_energy_full_design += energy_full_design; - total_capacity += capacity; } + if (!adapter_.empty() && status == "Discharging") { bool online; - std::ifstream(adapter_ / "online") >> online; - if (online) { + if (fs::exists(adapter_ / "online")) + std::ifstream(adapter_ / "online") >> online; + else + online = false; + if (online) 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; - if (time_remaining > 0.0f) { - // If we've turned positive it means the battery is past 100% and so - // just report that as no time remaining + + float time_remaining{0.0f}; + if (status == "Discharging" && total_power_exists && total_energy_exists) { + if (total_power != 0) + time_remaining = (float)total_energy / total_power; + } else if (status == "Charging" && total_energy_exists && total_energy_full_exists && total_power_exists) { + if (total_power != 0) + time_remaining = -(float)(total_energy_full - total_energy) / total_power; + // If we've turned positive it means the battery is past 100% and so just report that as no time remaining + if (time_remaining > 0.0f) time_remaining = 0.0f; + } + + float calculated_capacity{0.0f}; + if (total_capacity_exists) { + if (total_capacity > 0.0f) + calculated_capacity = (float)total_capacity; + else if (total_energy_full_exists && total_energy_exists) { + if (total_energy_full > 0.0f) + calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full); } } - float capacity{0.0f}; - if (total_energy_full > 0.0f) { - capacity = ((float)total_energy * 100.0f / (float)total_energy_full); - } else { - capacity = (float)total_capacity; - } + // Handle design-capacity - if (config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) { - capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design); + if ((config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) && total_energy_exists && total_energy_full_design_exists) { + if (total_energy_full_design > 0.0f) + calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design); } + // Handle full-at if (config_["full-at"].isUInt()) { auto full_at = config_["full-at"].asUInt(); - if (full_at < 100) { - capacity = 100.f * capacity / full_at; - } + if (full_at < 100) + calculated_capacity = 100.f * calculated_capacity / full_at; } - if (capacity > 100.f) { - // This can happen when the battery is calibrating and goes above 100% - // Handle it gracefully by clamping at 100% - capacity = 100.f; - } - uint8_t cap = round(capacity); - if (cap == 100 && status == "Charging") { - // If we've reached 100% just mark as full as some batteries can stay - // stuck reporting they're still charging but not yet done + + // Handle it gracefully by clamping at 100% + // This can happen when the battery is calibrating and goes above 100% + if (calculated_capacity > 100.f) + calculated_capacity = 100.f; + + uint8_t cap = round(calculated_capacity); + // If we've reached 100% just mark as full as some batteries can stay stuck reporting they're still charging but not yet done + if (cap == 100 && status == "Charging") status = "Full"; - } return {cap, time_remaining, status, total_power / 1e6}; } catch (const std::exception& e) { From 0d948536135b74393d7b09d367ad00be7d8a4c3c Mon Sep 17 00:00:00 2001 From: Tom Charnock Date: Fri, 2 Sep 2022 15:37:23 +0200 Subject: [PATCH 11/91] Added alternative variable calculations --- src/modules/battery.cpp | 63 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index b47aee98..7cbc7b54 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -246,6 +246,13 @@ const std::tuple waybar::modules::Battery::g charge_now = 0; } + if (!capacity_exists && charge_now_exists && charge_full_exists) { + if (charge_full != 0) { + capacity_exists = true; + capacity = charge_now * 100 / charge_full; + } + } + uint32_t power_now; bool power_now_exists; if (fs::exists(bat / "power_now")) { @@ -259,6 +266,20 @@ const std::tuple waybar::modules::Battery::g power_now = 0; } + if (!current_now_exists && power_now_exists && voltage_now_exists) { + if (voltage_now != 0){ + current_now_exists = true; + current_now = (uint64_t)power_now * 1000000 / (uint64_t)voltage_now; + } + } + + if (!voltage_now_exists && power_now_exists && current_now_exists) { + if (current_now != 0) { + voltage_now_exists = true; + voltage_now = (uint64_t)power_now * 1000000 / (uint64_t)current_now; + } + } + uint32_t energy_now; bool energy_now_exists; if (fs::exists(bat / "energy_now")) { @@ -272,6 +293,20 @@ const std::tuple waybar::modules::Battery::g energy_now = 0; } + if (!charge_now_exists && energy_now_exists && voltage_now_exists) { + if (voltage_now != 0){ + charge_now_exists = true; + charge_now = (uint64_t)energy_now * 1000000 / (uint64_t)voltage_now; + } + } + + if (!voltage_now_exists && energy_now_exists && charge_now_exists) { + if (charge_now != 0) { + voltage_now_exists = true; + voltage_now = (uint64_t)energy_now * 1000000 / (uint64_t)charge_now; + } + } + uint32_t energy_full; bool energy_full_exists; if (fs::exists(bat / "energy_full")) { @@ -285,6 +320,20 @@ const std::tuple waybar::modules::Battery::g energy_full = 0; } + if (!charge_full_exists && energy_full_exists && voltage_now_exists) { + if (voltage_now != 0){ + charge_full_exists = true; + charge_full = (uint64_t)energy_full * 1000000 / (uint64_t)voltage_now; + } + } + + if (!voltage_now_exists && energy_full_exists && charge_full_exists) { + if (charge_full != 0) { + voltage_now_exists = true; + voltage_now = (uint64_t)energy_full * 1000000 / (uint64_t)charge_full; + } + } + uint32_t energy_full_design; bool energy_full_design_exists; if (fs::exists(bat / "energy_full_design")) { @@ -298,6 +347,20 @@ const std::tuple waybar::modules::Battery::g energy_full_design = 0; } + if (!charge_full_design_exists && energy_full_design_exists && voltage_now_exists) { + if (voltage_now != 0){ + charge_full_design_exists = true; + charge_full_design = (uint64_t)energy_full_design * 1000000 / (uint64_t)voltage_now; + } + } + + if (!voltage_now_exists && energy_full_design_exists && charge_full_design_exists) { + if (charge_full_design != 0) { + voltage_now_exists = true; + voltage_now = (uint64_t)energy_full_design * 1000000 / (uint64_t)charge_full_design; + } + } + // Show the "smallest" status among all batteries if (status_gt(status, _status)) status = _status; From af2a3f8bda521853548d1e4774fd6df9fba8a498 Mon Sep 17 00:00:00 2001 From: Tom Charnock Date: Sat, 3 Sep 2022 16:06:13 +0200 Subject: [PATCH 12/91] Added alternative calculations for time remaining --- src/modules/battery.cpp | 315 +++++++++++++++++++++++----------------- 1 file changed, 178 insertions(+), 137 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 7cbc7b54..1cff9f9f 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -164,7 +164,7 @@ const std::tuple waybar::modules::Battery::g bool total_energy_full_exists = false; uint32_t total_energy_full_design = 0; bool total_energy_full_design_exists = false; - uint32_t total_capacity{0}; + uint32_t total_capacity = 0; bool total_capacity_exists = false; std::string status = "Unknown"; @@ -176,191 +176,232 @@ const std::tuple waybar::modules::Battery::g // Some battery will report current and charge in μA/μAh. // Scale these by the voltage to get μW/μWh. - uint32_t capacity; - bool capacity_exists; + // uint32_t capacity (bool pass) { + // uint32_t c = 0; + // if (fs::exists(bat / "capacity")) + // c = std::ifstream(bat / "capacity"); + // else if (pass) + // c = charge_now(pass) / charge_full(pass); + // return c; + // } + + // uint32_t current_now (bool pass) { + // uint32_t c = 0; + // if (fs::exists(bat / "current_now")) + // std::ifstream(bat / "current_now") >> c; + // else if (fs::exists(bat / "current_avg")) + // std::ifstream(bat / "current_avg") >> c; + // else + // c = power_now(pass) / voltage_now(pass); + // return c; + // } + + // uint32_t voltage_now () { + // uint32_t v = 0; + // if (fs::exists(bat / "voltage_now")) + // std::ifstream(bat / "voltage_now") >> v; + // else if (fs::exists(bat / "voltage_avg")) + // std::ifstream(bat / "voltage_avg") >> v; + // else + + // } + + uint32_t capacity = 0; + bool capacity_exists = false; if (fs::exists(bat / "capacity")) { - capacity_exists = true; - std::ifstream(bat / "capacity") >> capacity; - } else { - capacity_exists = false; - capacity = 0; + capacity_exists = true; + std::ifstream(bat / "capacity") >> capacity; } - uint32_t current_now; - bool current_now_exists; + uint32_t current_now = 0; + bool current_now_exists = false; if (fs::exists(bat / "current_now")) { - current_now_exists = true; - std::ifstream(bat / "current_now") >> current_now; + current_now_exists = true; + std::ifstream(bat / "current_now") >> current_now; } else if (fs::exists(bat / "current_avg")) { - current_now_exists = true; - std::ifstream(bat / "current_avg") >> current_now; - } else { - current_now_exists = false; - current_now = 0; + current_now_exists = true; + std::ifstream(bat / "current_avg") >> current_now; } - uint32_t voltage_now; - bool voltage_now_exists; + uint32_t voltage_now = 0; + bool voltage_now_exists = false; if (fs::exists(bat / "voltage_now")) { - voltage_now_exists = true; - std::ifstream(bat / "voltage_now") >> voltage_now; + voltage_now_exists = true; + std::ifstream(bat / "voltage_now") >> voltage_now; } else if (fs::exists(bat / "voltage_avg")) { - voltage_now_exists = true; - std::ifstream(bat / "voltage_avg") >> voltage_now; - } else { - voltage_now_exists = false; - voltage_now = 0; + voltage_now_exists = true; + std::ifstream(bat / "voltage_avg") >> voltage_now; } - uint32_t charge_full; - bool charge_full_exists; + uint32_t charge_full = 0; + bool charge_full_exists = false; if (fs::exists(bat / "charge_full")) { charge_full_exists = true; std::ifstream(bat / "charge_full") >> charge_full; - } else { - charge_full_exists = false; - charge_full = 0; } - uint32_t charge_full_design; - bool charge_full_design_exists; + uint32_t charge_full_design = 0; + bool charge_full_design_exists = false; if (fs::exists(bat / "charge_full_design")) { charge_full_design_exists = true; std::ifstream(bat / "charge_full_design") >> charge_full_design; - } else { - charge_full_design_exists = false; - charge_full_design = 0; } - uint32_t charge_now; - bool charge_now_exists; + uint32_t charge_now = 0; + bool charge_now_exists = false; if (fs::exists(bat / "charge_now")) { charge_now_exists = true; std::ifstream(bat / "charge_now") >> charge_now; - } else if (capacity_exists && charge_full_exists) { - // charge_now is missing on some systems, estimate using capacity and charge_full. - charge_now_exists = true; // this could be debatably set to false (same for all properties below) - charge_now = (capacity * charge_full) / 100; - } else { - charge_now_exists = false; - charge_now = 0; } - if (!capacity_exists && charge_now_exists && charge_full_exists) { - if (charge_full != 0) { - capacity_exists = true; - capacity = charge_now * 100 / charge_full; - } - } - - uint32_t power_now; - bool power_now_exists; + uint32_t power_now = 0; + bool power_now_exists = false; if (fs::exists(bat / "power_now")) { power_now_exists = true; std::ifstream(bat / "power_now") >> power_now; - } else if (current_now_exists && voltage_now_exists) { - power_now_exists = true; - power_now = ((uint64_t)current_now * (uint64_t)voltage_now) / 1000000; - } else { - power_now_exists = false; - power_now = 0; - } + } - if (!current_now_exists && power_now_exists && voltage_now_exists) { - if (voltage_now != 0){ - current_now_exists = true; - current_now = (uint64_t)power_now * 1000000 / (uint64_t)voltage_now; - } - } - - if (!voltage_now_exists && power_now_exists && current_now_exists) { - if (current_now != 0) { - voltage_now_exists = true; - voltage_now = (uint64_t)power_now * 1000000 / (uint64_t)current_now; - } - } - - uint32_t energy_now; - bool energy_now_exists; + uint32_t energy_now = 0; + bool energy_now_exists = false; if (fs::exists(bat / "energy_now")) { energy_now_exists = true; std::ifstream(bat / "energy_now") >> energy_now; - } else if (charge_now_exists && voltage_now_exists) { - energy_now_exists = true; - energy_now = ((uint64_t)charge_now * (uint64_t)voltage_now) / 1000000; - } else { - energy_now_exists = false; - energy_now = 0; } - if (!charge_now_exists && energy_now_exists && voltage_now_exists) { - if (voltage_now != 0){ - charge_now_exists = true; - charge_now = (uint64_t)energy_now * 1000000 / (uint64_t)voltage_now; - } - } - - if (!voltage_now_exists && energy_now_exists && charge_now_exists) { - if (charge_now != 0) { - voltage_now_exists = true; - voltage_now = (uint64_t)energy_now * 1000000 / (uint64_t)charge_now; - } - } - - uint32_t energy_full; - bool energy_full_exists; + uint32_t energy_full = 0; + bool energy_full_exists = false; if (fs::exists(bat / "energy_full")) { energy_full_exists = true; std::ifstream(bat / "energy_full") >> energy_full; - } else if (charge_full_exists && voltage_now_exists) { - energy_full_exists = true; - energy_full = ((uint64_t)charge_full * (uint64_t)voltage_now) / 1000000; - } else { - energy_full_exists = false; - energy_full = 0; } - if (!charge_full_exists && energy_full_exists && voltage_now_exists) { - if (voltage_now != 0){ - charge_full_exists = true; - charge_full = (uint64_t)energy_full * 1000000 / (uint64_t)voltage_now; - } - } - - if (!voltage_now_exists && energy_full_exists && charge_full_exists) { - if (charge_full != 0) { - voltage_now_exists = true; - voltage_now = (uint64_t)energy_full * 1000000 / (uint64_t)charge_full; - } - } - - uint32_t energy_full_design; - bool energy_full_design_exists; + uint32_t energy_full_design = 0; + bool energy_full_design_exists = false; if (fs::exists(bat / "energy_full_design")) { energy_full_design_exists = true; std::ifstream(bat / "energy_full_design") >> energy_full_design; - } else if (charge_full_design_exists && voltage_now_exists) { - energy_full_design_exists = true; - energy_full_design = ((uint64_t)charge_full_design * (uint64_t)voltage_now) / 1000000; - } else { - energy_full_design_exists = false; - energy_full_design = 0; } - if (!charge_full_design_exists && energy_full_design_exists && voltage_now_exists) { - if (voltage_now != 0){ - charge_full_design_exists = true; - charge_full_design = (uint64_t)energy_full_design * 1000000 / (uint64_t)voltage_now; - } - } - - if (!voltage_now_exists && energy_full_design_exists && charge_full_design_exists) { - if (charge_full_design != 0) { + if (!voltage_now_exists) { + if (power_now_exists && current_now_exists && current_now != 0) { voltage_now_exists = true; - voltage_now = (uint64_t)energy_full_design * 1000000 / (uint64_t)charge_full_design; + voltage_now = 1000000 * power_now / current_now; + } else if (energy_full_design_exists && charge_full_design_exists && charge_full_design != 0) { + voltage_now_exists = true; + voltage_now = 1000000 * energy_full_design / charge_full_design; + } else if (energy_now_exists) { + if (charge_now_exists && charge_now != 0) { + voltage_now_exists = true; + voltage_now = 1000000 * energy_now / charge_now; + } else if (capacity_exists && charge_full_exists) { + charge_now_exists = true; + charge_now = charge_full * capacity / 100; + if (charge_full != 0 && capacity != 0) { + voltage_now_exists = true; + voltage_now = 1000000 * energy_now * 100 / charge_full / capacity; + } + } + } else if (energy_full_exists) { + if (charge_full_exists && charge_full != 0) { + voltage_now_exists = true; + voltage_now = 1000000 * energy_full / charge_full; + } else if (charge_now_exists && capacity_exists) { + if (capacity != 0) { + charge_full_exists = true; + charge_full = 100 * charge_now / capacity; + } + if (charge_now != 0) { + voltage_now_exists = true; + voltage_now = 10000 * energy_full * capacity / charge_now; + } + } } } + if (!capacity_exists) { + if (charge_now_exists && charge_full_exists && charge_full != 0) { + capacity_exists = true; + capacity = 100 * charge_now / charge_full; + } else if (energy_now_exists && energy_full_exists && energy_full != 0) { + capacity_exists = true; + capacity = 100 * energy_now / energy_full; + } else if (charge_now_exists && energy_full_exists && voltage_now_exists) { + if (!charge_full_exists && voltage_now != 0) { + charge_full_exists = true; + charge_full = 1000000 * energy_full / voltage_now; + } + if (energy_full != 0) { + capacity_exists = true; + capacity = charge_now * voltage_now / 10000 / energy_full; + } + } else if (charge_full_exists && energy_now_exists && voltage_now_exists) { + if (!charge_now_exists && voltage_now != 0) { + charge_now_exists = true; + charge_now = 1000000 * energy_now / voltage_now; + } + if (voltage_now != 0 && charge_full != 0) { + capacity_exists = true; + capacity = 100 * 1000000 * energy_now / voltage_now / charge_full; + } + } + } + + if (!energy_now_exists && voltage_now_exists) { + if (charge_now_exists) { + energy_now_exists = true; + energy_now = charge_now * voltage_now / 1000000; + } else if (capacity_exists && charge_full_exists) { + charge_now_exists = true; + charge_now = capacity * charge_full / 100; + energy_now_exists = true; + energy_now = voltage_now * capacity * charge_full / 1000000 / 100; + } else if (capacity_exists && energy_full) { + if (voltage_now != 0) { + charge_full_exists = true; + charge_full = 1000000 * energy_full / voltage_now; + charge_now_exists = true; + charge_now = capacity * 10000 * energy_full / voltage_now; + } + energy_now_exists = true; + energy_now = capacity * energy_full / 100; + } + } + + if (!energy_full_exists && voltage_now_exists) { + if (charge_full_exists) { + energy_full_exists = true; + energy_full = charge_full * voltage_now / 1000000; + } else if (charge_now_exists && capacity_exists && capacity != 0) { + charge_full_exists = true; + charge_full = 100 * charge_now / capacity; + energy_full_exists = true; + energy_full = charge_now * voltage_now / capacity / 10000; + } else if (capacity_exists && energy_now) { + if (voltage_now != 0) { + charge_now_exists = true; + charge_now = 1000000 * energy_now / voltage_now; + } + if (capacity != 0) { + energy_full_exists = true; + energy_full = 100 * energy_now / capacity; + if (voltage_now != 0) { + charge_full_exists = true; + charge_full = 100 * 1000000 * energy_now / voltage_now / capacity; + } + } + } + } + + if (!power_now_exists && voltage_now_exists && charge_now_exists) { + power_now_exists = true; + power_now = voltage_now * current_now / 1000000; + } + + if (!energy_full_design_exists && voltage_now_exists && charge_full_design_exists) { + energy_full_design_exists = true; + energy_full_design = voltage_now * charge_full_design / 1000000; + } + // Show the "smallest" status among all batteries if (status_gt(status, _status)) status = _status; From 5647146ac0920df6ffc0f9e189bdc687b50d9ad9 Mon Sep 17 00:00:00 2001 From: Tom Charnock Date: Sat, 3 Sep 2022 17:52:11 +0200 Subject: [PATCH 13/91] Added Discharging clause and corrected typo --- src/modules/battery.cpp | 47 ++++++++--------------------------------- 1 file changed, 9 insertions(+), 38 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 1cff9f9f..35d41ed6 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -108,7 +108,7 @@ void waybar::modules::Battery::refreshBatteries() { } auto adap_defined = config_["adapter"].isString(); if (((adap_defined && dir_name == config_["adapter"].asString()) || !adap_defined) && - fs::exists(node.path() / "online")) { + (fs::exists(node.path() / "online") || fs::exists(node.path() / "status"))) { adapter_ = node.path(); } } @@ -176,36 +176,6 @@ const std::tuple waybar::modules::Battery::g // Some battery will report current and charge in μA/μAh. // Scale these by the voltage to get μW/μWh. - // uint32_t capacity (bool pass) { - // uint32_t c = 0; - // if (fs::exists(bat / "capacity")) - // c = std::ifstream(bat / "capacity"); - // else if (pass) - // c = charge_now(pass) / charge_full(pass); - // return c; - // } - - // uint32_t current_now (bool pass) { - // uint32_t c = 0; - // if (fs::exists(bat / "current_now")) - // std::ifstream(bat / "current_now") >> c; - // else if (fs::exists(bat / "current_avg")) - // std::ifstream(bat / "current_avg") >> c; - // else - // c = power_now(pass) / voltage_now(pass); - // return c; - // } - - // uint32_t voltage_now () { - // uint32_t v = 0; - // if (fs::exists(bat / "voltage_now")) - // std::ifstream(bat / "voltage_now") >> v; - // else if (fs::exists(bat / "voltage_avg")) - // std::ifstream(bat / "voltage_avg") >> v; - // else - - // } - uint32_t capacity = 0; bool capacity_exists = false; if (fs::exists(bat / "capacity")) { @@ -392,7 +362,7 @@ const std::tuple waybar::modules::Battery::g } } - if (!power_now_exists && voltage_now_exists && charge_now_exists) { + if (!power_now_exists && voltage_now_exists && current_now_exists) { power_now_exists = true; power_now = voltage_now * current_now / 1000000; } @@ -430,11 +400,10 @@ const std::tuple waybar::modules::Battery::g if (!adapter_.empty() && status == "Discharging") { bool online; - if (fs::exists(adapter_ / "online")) - std::ifstream(adapter_ / "online") >> online; - else - online = false; - if (online) + std::string current_status; + std::ifstream(adapter_ / "online") >> online; + std::getline(std::ifstream(adapter_ / "status"), current_status); + if (online && current_status != "Discharging") status = "Plugged"; } @@ -493,11 +462,13 @@ const std::tuple waybar::modules::Battery::g const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { if (!adapter_.empty()) { bool online; + std::string status; std::ifstream(adapter_ / "online") >> online; + std::getline(std::ifstream(adapter_ / "status"), status); if (capacity == 100) { return "Full"; } - if (online) { + if (online && status != "Discharging") { return "Plugged"; } return "Discharging"; From 912d7f85880be72628ccad07df329c729043246a Mon Sep 17 00:00:00 2001 From: Tom Charnock Date: Sat, 3 Sep 2022 18:08:26 +0200 Subject: [PATCH 14/91] Making calculations uint64_t --- src/modules/battery.cpp | 56 ++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 35d41ed6..d46c0512 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -255,34 +255,34 @@ const std::tuple waybar::modules::Battery::g if (!voltage_now_exists) { if (power_now_exists && current_now_exists && current_now != 0) { voltage_now_exists = true; - voltage_now = 1000000 * power_now / current_now; + voltage_now = 1000000 * (uint64_t)power_now / (uint64_t)current_now; } else if (energy_full_design_exists && charge_full_design_exists && charge_full_design != 0) { voltage_now_exists = true; - voltage_now = 1000000 * energy_full_design / charge_full_design; + voltage_now = 1000000 * (uint64_t)energy_full_design / (uint64_t)charge_full_design; } else if (energy_now_exists) { if (charge_now_exists && charge_now != 0) { voltage_now_exists = true; - voltage_now = 1000000 * energy_now / charge_now; + voltage_now = 1000000 * (uint64_t)energy_now / (uint64_t)charge_now; } else if (capacity_exists && charge_full_exists) { charge_now_exists = true; - charge_now = charge_full * capacity / 100; + charge_now = (uint64_t)charge_full * (uint64_t)capacity / 100; if (charge_full != 0 && capacity != 0) { voltage_now_exists = true; - voltage_now = 1000000 * energy_now * 100 / charge_full / capacity; + voltage_now = 1000000 * (uint64_t)energy_now * 100 / (uint64_t)charge_full / (uint64_t)capacity; } } } else if (energy_full_exists) { if (charge_full_exists && charge_full != 0) { voltage_now_exists = true; - voltage_now = 1000000 * energy_full / charge_full; + voltage_now = 1000000 * (uint64_t)energy_full / (uint64_t)charge_full; } else if (charge_now_exists && capacity_exists) { if (capacity != 0) { charge_full_exists = true; - charge_full = 100 * charge_now / capacity; + charge_full = 100 * (uint64_t)charge_now / (uint64_t)capacity; } if (charge_now != 0) { voltage_now_exists = true; - voltage_now = 10000 * energy_full * capacity / charge_now; + voltage_now = 10000 * (uint64_t)energy_full * (uint64_t)capacity / (uint64_t)charge_now; } } } @@ -291,27 +291,27 @@ const std::tuple waybar::modules::Battery::g if (!capacity_exists) { if (charge_now_exists && charge_full_exists && charge_full != 0) { capacity_exists = true; - capacity = 100 * charge_now / charge_full; + capacity = 100 * (uint64_t)charge_now / (uint64_t)charge_full; } else if (energy_now_exists && energy_full_exists && energy_full != 0) { capacity_exists = true; - capacity = 100 * energy_now / energy_full; + capacity = 100 * (uint64_t)energy_now / (uint64_t)energy_full; } else if (charge_now_exists && energy_full_exists && voltage_now_exists) { if (!charge_full_exists && voltage_now != 0) { charge_full_exists = true; - charge_full = 1000000 * energy_full / voltage_now; + charge_full = 1000000 * (uint64_t)energy_full / (uint64_t)voltage_now; } if (energy_full != 0) { capacity_exists = true; - capacity = charge_now * voltage_now / 10000 / energy_full; + capacity = (uint64_t)charge_now * (uint64_t)voltage_now / 10000 / (uint64_t)energy_full; } } else if (charge_full_exists && energy_now_exists && voltage_now_exists) { if (!charge_now_exists && voltage_now != 0) { charge_now_exists = true; - charge_now = 1000000 * energy_now / voltage_now; + charge_now = 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now; } if (voltage_now != 0 && charge_full != 0) { capacity_exists = true; - capacity = 100 * 1000000 * energy_now / voltage_now / charge_full; + capacity = 100 * 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now / (uint64_t)charge_full; } } } @@ -319,44 +319,44 @@ const std::tuple waybar::modules::Battery::g if (!energy_now_exists && voltage_now_exists) { if (charge_now_exists) { energy_now_exists = true; - energy_now = charge_now * voltage_now / 1000000; + energy_now = (uint64_t)charge_now * (uint64_t)voltage_now / 1000000; } else if (capacity_exists && charge_full_exists) { charge_now_exists = true; - charge_now = capacity * charge_full / 100; + charge_now = (uint64_t)capacity * (uint64_t)charge_full / 100; energy_now_exists = true; - energy_now = voltage_now * capacity * charge_full / 1000000 / 100; + energy_now = (uint64_t)voltage_now * (uint64_t)capacity * (uint64_t)charge_full / 1000000 / 100; } else if (capacity_exists && energy_full) { if (voltage_now != 0) { charge_full_exists = true; - charge_full = 1000000 * energy_full / voltage_now; + charge_full = 1000000 * (uint64_t)energy_full / (uint64_t)voltage_now; charge_now_exists = true; - charge_now = capacity * 10000 * energy_full / voltage_now; + charge_now = (uint64_t)capacity * 10000 * (uint64_t)energy_full / (uint64_t)voltage_now; } energy_now_exists = true; - energy_now = capacity * energy_full / 100; + energy_now = (uint64_t)capacity * (uint64_t)energy_full / 100; } } if (!energy_full_exists && voltage_now_exists) { if (charge_full_exists) { energy_full_exists = true; - energy_full = charge_full * voltage_now / 1000000; + energy_full = (uint64_t)charge_full * (uint64_t)voltage_now / 1000000; } else if (charge_now_exists && capacity_exists && capacity != 0) { charge_full_exists = true; - charge_full = 100 * charge_now / capacity; + charge_full = 100 * (uint64_t)charge_now / (uint64_t)capacity; energy_full_exists = true; - energy_full = charge_now * voltage_now / capacity / 10000; + energy_full = (uint64_t)charge_now * (uint64_t)voltage_now / (uint64_t)capacity / 10000; } else if (capacity_exists && energy_now) { if (voltage_now != 0) { charge_now_exists = true; - charge_now = 1000000 * energy_now / voltage_now; + charge_now = 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now; } if (capacity != 0) { energy_full_exists = true; - energy_full = 100 * energy_now / capacity; + energy_full = 100 * (uint64_t)energy_now / (uint64_t)capacity; if (voltage_now != 0) { charge_full_exists = true; - charge_full = 100 * 1000000 * energy_now / voltage_now / capacity; + charge_full = 100 * 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now / (uint64_t)capacity; } } } @@ -364,12 +364,12 @@ const std::tuple waybar::modules::Battery::g if (!power_now_exists && voltage_now_exists && current_now_exists) { power_now_exists = true; - power_now = voltage_now * current_now / 1000000; + power_now = (uint64_t)voltage_now * (uint64_t)current_now / 1000000; } if (!energy_full_design_exists && voltage_now_exists && charge_full_design_exists) { energy_full_design_exists = true; - energy_full_design = voltage_now * charge_full_design / 1000000; + energy_full_design = (uint64_t)voltage_now * (uint64_t)charge_full_design / 1000000; } // Show the "smallest" status among all batteries From faf8954712f8276c3196c5eda2622e4ad554fb2c Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Wed, 27 Jul 2022 01:12:34 +0100 Subject: [PATCH 15/91] Add config option to ignore Pulseaudio Sinks Fixes #1347 --- src/modules/pulseaudio.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 24b858d3..43af2b19 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -170,6 +170,15 @@ void waybar::modules::Pulseaudio::sinkInfoCb(pa_context * /*context*/, const pa_ if (i == nullptr) return; auto pa = static_cast(data); + + if (pa->config_["ignored-sinks"].isArray()) { + for (const auto& ignored_sink : pa->config_["ignored-sinks"]) { + if (ignored_sink.asString() == i->description) { + return; + } + } + } + if (pa->current_sink_name_ == i->name) { if (i->state != PA_SINK_RUNNING) { pa->current_sink_running_ = false; From 6558a156b33d310e9796bc6dc159c200e243890c Mon Sep 17 00:00:00 2001 From: Isaac Woods Date: Fri, 9 Sep 2022 00:52:49 +0100 Subject: [PATCH 16/91] Add man entry for the `ignored-sinks` option --- man/waybar-pulseaudio.5.scd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/man/waybar-pulseaudio.5.scd b/man/waybar-pulseaudio.5.scd index 07a0de80..e3f9045f 100644 --- a/man/waybar-pulseaudio.5.scd +++ b/man/waybar-pulseaudio.5.scd @@ -101,6 +101,10 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu default: 100 ++ The maximum volume that can be set, in percentage. +*ignored-sinks*: ++ + typeof: array ++ + Sinks in this list will not be shown as the active sink by Waybar. Entries should be the sink's description field. + # FORMAT REPLACEMENTS *{desc}*: Pulseaudio port's description, for bluetooth it'll be the device name. From 9e03bb61c799fbc6a47598929319d05adf408904 Mon Sep 17 00:00:00 2001 From: Spyros Seimenis Date: Fri, 16 Sep 2022 01:19:44 +0300 Subject: [PATCH 17/91] Escape text in custom module --- src/modules/custom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index 6fc01675..1be0e3e0 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -125,7 +125,7 @@ auto waybar::modules::Custom::update() -> void { } else { parseOutputRaw(); } - auto str = fmt::format(format_, text_, fmt::arg("alt", alt_), + auto str = fmt::format(format_, Glib::Markup::escape_text(text_).raw(), fmt::arg("alt", alt_), fmt::arg("icon", getIcon(percentage_, alt_)), fmt::arg("percentage", percentage_)); if (str.empty()) { From 97588330274256b0ba16e98d7c83f549418ea66b Mon Sep 17 00:00:00 2001 From: Dordovel Date: Fri, 30 Sep 2022 14:33:23 +0300 Subject: [PATCH 18/91] added user module --- include/factory.hpp | 1 + include/modules/user.hpp | 34 ++++++++++++ meson.build | 1 + src/factory.cpp | 3 ++ src/modules/user.cpp | 114 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 153 insertions(+) create mode 100644 include/modules/user.hpp create mode 100644 src/modules/user.cpp diff --git a/include/factory.hpp b/include/factory.hpp index 06cd4d90..48df6257 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -72,6 +72,7 @@ #include "modules/jack.hpp" #endif #include "bar.hpp" +#include "modules/user.hpp" #include "modules/custom.hpp" #include "modules/temperature.hpp" diff --git a/include/modules/user.hpp b/include/modules/user.hpp new file mode 100644 index 00000000..41e7884e --- /dev/null +++ b/include/modules/user.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include + +#include "AIconLabel.hpp" +#include "util/sleeper_thread.hpp" + +namespace waybar::modules { +class User : public AIconLabel { + public: + User(const std::string&, const Json::Value&); + ~User() = default; + auto update() -> void; + + private: + util::SleeperThread thread_; + + Glib::RefPtr pixbuf_; + + static constexpr inline int defaultUserImageWidth_ = 20; + static constexpr inline int defaultUserImageHeight_ = 20; + + long uptime_as_seconds(); + std::string get_user_login(); + std::string get_user_home_dir(); + std::string get_default_user_avatar_path(); + void init_default_user_avatar(int width, int height); + void init_user_avatar(const std::string& path, int width, int height); + void init_avatar(const Json::Value& config); + void init_update_worker(); +}; +} // namespace waybar::modules diff --git a/meson.build b/meson.build index 420606aa..ff16cea9 100644 --- a/meson.build +++ b/meson.build @@ -149,6 +149,7 @@ src_files = files( 'src/modules/disk.cpp', 'src/modules/idle_inhibitor.cpp', 'src/modules/temperature.cpp', + 'src/modules/user.cpp', 'src/main.cpp', 'src/bar.cpp', 'src/client.cpp', diff --git a/src/factory.cpp b/src/factory.cpp index 13b7803f..858291ff 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -81,6 +81,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { if (ref == "clock") { return new waybar::modules::Clock(id, config_[name]); } + if (ref == "user") { + return new waybar::modules::User(id, config_[name]); + } if (ref == "disk") { return new waybar::modules::Disk(id, config_[name]); } diff --git a/src/modules/user.cpp b/src/modules/user.cpp new file mode 100644 index 00000000..88da0a45 --- /dev/null +++ b/src/modules/user.cpp @@ -0,0 +1,114 @@ +#include "modules/user.hpp" + +#include +#include +#include + +#include +#include +#include + +#if HAVE_CPU_LINUX +#include +#endif + +#if HAVE_CPU_BSD +#include +#endif + +namespace waybar::modules { +User::User(const std::string& id, const Json::Value& config) + : AIconLabel(config, "user", id, "{user} {work_H}:{work_M}", 60, false, false, true) { + if (AIconLabel::iconEnabled()) { + this->init_avatar(AIconLabel::config_); + } + this->init_update_worker(); +} + +long User::uptime_as_seconds() { + long uptime = 0; + +#if HAVE_CPU_LINUX + struct sysinfo s_info; + if (0 == sysinfo(&s_info)) { + uptime = s_info.uptime; + } +#endif + +#if HAVE_CPU_BSD + struct timespec s_info; + if (0 == clock_gettime(CLOCK_UPTIME_PRECISE, &s_info)) { + uptime = s_info.tv_sec; + } +#endif + + return uptime; +} + +std::string User::get_user_login() { return Glib::get_user_name(); } + +std::string User::get_user_home_dir() { return Glib::get_home_dir(); } + +void User::init_update_worker() { + this->thread_ = [this] { + ALabel::dp.emit(); + auto now = std::chrono::system_clock::now(); + auto diff = now.time_since_epoch() % ALabel::interval_; + this->thread_.sleep_for(ALabel::interval_ - diff); + }; +} + +void User::init_avatar(const Json::Value& config) { + int height = + config["height"].isUInt() ? config["height"].asUInt() : this->defaultUserImageHeight_; + int width = config["width"].isUInt() ? config["width"].asUInt() : this->defaultUserImageWidth_; + + if (config["avatar"].isString()) { + std::string userAvatar = config["avatar"].asString(); + if (!userAvatar.empty()) { + this->init_user_avatar(userAvatar, width, height); + return; + } + } + + this->init_default_user_avatar(width, width); +} + +std::string User::get_default_user_avatar_path() { + return this->get_user_home_dir() + "/" + ".face"; +} + +void User::init_default_user_avatar(int width, int height) { + this->init_user_avatar(this->get_default_user_avatar_path(), width, height); +} + +void User::init_user_avatar(const std::string& path, int width, int height) { + this->pixbuf_ = Gdk::Pixbuf::create_from_file(path, width, height); + AIconLabel::image_.set(this->pixbuf_); +} + +auto User::update() -> void { + std::string systemUser = this->get_user_login(); + std::transform(systemUser.cbegin(), systemUser.cend(), systemUser.begin(), + [](unsigned char c) { return std::toupper(c); }); + + long uptimeSeconds = this->uptime_as_seconds(); + auto workSystemTimeSeconds = std::chrono::seconds(uptimeSeconds); + auto currentSystemTime = std::chrono::system_clock::now(); + auto startSystemTime = currentSystemTime - workSystemTimeSeconds; + long workSystemDays = uptimeSeconds / 86400; + + auto label = fmt::format(ALabel::format_, fmt::arg("up_H", fmt::format("{:%H}", startSystemTime)), + fmt::arg("up_M", fmt::format("{:%M}", startSystemTime)), + fmt::arg("up_d", fmt::format("{:%d}", startSystemTime)), + fmt::arg("up_m", fmt::format("{:%m}", startSystemTime)), + fmt::arg("up_Y", fmt::format("{:%Y}", startSystemTime)), + fmt::arg("work_d", workSystemDays), + fmt::arg("work_H", fmt::format("{:%H}", workSystemTimeSeconds)), + fmt::arg("work_M", fmt::format("{:%M}", workSystemTimeSeconds)), + fmt::arg("work_S", fmt::format("{:%S}", workSystemTimeSeconds)), + fmt::arg("user", systemUser)); + ALabel::label_.set_markup(label); + ALabel::update(); +} +}; // namespace waybar::modules From c500c7d9a1da03abfc90b7f56d372cfbd774726f Mon Sep 17 00:00:00 2001 From: Matthew Fry Date: Fri, 30 Sep 2022 15:25:12 -0600 Subject: [PATCH 19/91] Fixed pulseaudio max-volume configuration. Fixed issue where volume stepping would cause the max volume to go above the max and never reach 0. --- src/modules/pulseaudio.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 24b858d3..ccfeb7ef 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -91,19 +91,33 @@ bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) { pa_volume_t change = volume_tick; pa_cvolume pa_volume = pa_volume_; int max_volume = 100; + double step = 1; // isDouble returns true for integers as well, just in case if (config_["scroll-step"].isDouble()) { - change = round(config_["scroll-step"].asDouble() * volume_tick); + step = config_["scroll-step"].asDouble(); } if (config_["max-volume"].isInt()) { - max_volume = std::min(0, config_["max-volume"].asInt()); + max_volume = std::min(config_["max-volume"].asInt(), static_cast(PA_VOLUME_UI_MAX)); } + if (dir == SCROLL_DIR::UP) { - if (volume_ + 1 <= max_volume) { + if (volume_ < max_volume) { + if (volume_ + step > max_volume) { + change = round((max_volume - volume_) * volume_tick); + } + else { + change = round(step * volume_tick); + } pa_cvolume_inc(&pa_volume, change); } } else if (dir == SCROLL_DIR::DOWN) { - if (volume_ - 1 >= 0) { + if (volume_ > 0) { + if (volume_ - step < 0) { + change = round(volume_ * volume_tick); + } + else { + change = round(step * volume_tick); + } pa_cvolume_dec(&pa_volume, change); } } From c3e91cd228bc7625985ff25c33bffc5c9dbcdc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 07:29:16 +0200 Subject: [PATCH 20/91] [FreeBSD] Use thermal-zone The zone was hardcoded in #1702. This commit allows to use the "thermal-zone" variable. Follow up #1702 --- src/modules/temperature.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/modules/temperature.cpp b/src/modules/temperature.cpp index eea1198e..80584dad 100644 --- a/src/modules/temperature.cpp +++ b/src/modules/temperature.cpp @@ -81,8 +81,11 @@ float waybar::modules::Temperature::getTemperature() { int temp; size_t size = sizeof temp; - if (sysctlbyname("hw.acpi.thermal.tz0.temperature", &temp, &size, NULL, 0) != 0) { - throw std::runtime_error("sysctl hw.acpi.thermal.tz0.temperature or dev.cpu.0.temperature failed"); + auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0; + auto sysctl_thermal = fmt::format("hw.acpi.thermal.tz{}.temperature", zone); + + if (sysctlbyname(sysctl_thermal.c_str(), &temp, &size, NULL, 0) != 0) { + throw std::runtime_error(fmt::format("sysctl {} failed",sysctl_thermal)); } auto temperature_c = ((float)temp-2732)/10; return temperature_c; From 089823658664f2ec15f9a6dd31a851ad879dcf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 07:37:05 +0200 Subject: [PATCH 21/91] remove useless include --- src/modules/temperature.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/temperature.cpp b/src/modules/temperature.cpp index 80584dad..de41753e 100644 --- a/src/modules/temperature.cpp +++ b/src/modules/temperature.cpp @@ -4,7 +4,6 @@ #if defined(__FreeBSD__) // clang-format off -#include #include // clang-format on #endif From 1ca660460a44dd4d781a214daa29e6ba7c95247c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 08:03:54 +0200 Subject: [PATCH 22/91] apply clang-format --- src/modules/temperature.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/modules/temperature.cpp b/src/modules/temperature.cpp index de41753e..3178c12b 100644 --- a/src/modules/temperature.cpp +++ b/src/modules/temperature.cpp @@ -10,7 +10,6 @@ waybar::modules::Temperature::Temperature(const std::string& id, const Json::Value& config) : ALabel(config, "temperature", id, "{temperatureC}°C", 10) { - #if defined(__FreeBSD__) // try to read sysctl? #else @@ -84,12 +83,12 @@ float waybar::modules::Temperature::getTemperature() { auto sysctl_thermal = fmt::format("hw.acpi.thermal.tz{}.temperature", zone); if (sysctlbyname(sysctl_thermal.c_str(), &temp, &size, NULL, 0) != 0) { - throw std::runtime_error(fmt::format("sysctl {} failed",sysctl_thermal)); + throw std::runtime_error(fmt::format("sysctl {} failed", sysctl_thermal)); } - auto temperature_c = ((float)temp-2732)/10; + auto temperature_c = ((float)temp - 2732) / 10; return temperature_c; -#else // Linux +#else // Linux std::ifstream temp(file_path_); if (!temp.is_open()) { throw std::runtime_error("Can't open " + file_path_); From ddf3e112401b0da2d34d8113bab48881e3ec5662 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 11:28:32 +0200 Subject: [PATCH 23/91] remove clang-format lines --- src/modules/temperature.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/temperature.cpp b/src/modules/temperature.cpp index 3178c12b..243cbcc9 100644 --- a/src/modules/temperature.cpp +++ b/src/modules/temperature.cpp @@ -3,9 +3,7 @@ #include #if defined(__FreeBSD__) -// clang-format off #include -// clang-format on #endif waybar::modules::Temperature::Temperature(const std::string& id, const Json::Value& config) From b8322c4b4b023d8e6fbe8b6bf4100d6c60a06e42 Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Thu, 27 May 2021 15:40:54 +0200 Subject: [PATCH 24/91] button: Add AButton class The AButton class is designed as full a substitute to ALabel. The GtkButton attribute 'button_' is initialized with a label. This label can the be referenced by the subsequent inheritors of AButton instead of the GtkLabel attribute 'label_' of ALabel. For convenience a GtkLabel* 'label_' attribute is added to AButton. If the button cannot be clicked it is disabled, effectively acting like its label predecessor. GtkButton seems to catch one-click mouse events regardless of the flags set on it. Therefore, 'signal_pressed' is connected to a function creating a fake GdkEventButton* and calling 'handleToggle' (for details on this possible bug in GTK see: https://stackoverflow.com/questions/45334911 ) In accordance with other GtkButtons (i.e. the sway/workspace ones) set_relief(Gtk::RELIEF_NONE) is called on the 'button_' instance. --- include/AButton.hpp | 34 ++++++ include/factory.hpp | 2 +- include/modules/backlight.hpp | 4 +- include/modules/battery.hpp | 4 +- include/modules/bluetooth.hpp | 4 +- include/modules/clock.hpp | 4 +- include/modules/cpu.hpp | 4 +- include/modules/custom.hpp | 4 +- include/modules/disk.hpp | 4 +- include/modules/hyprland/backend.hpp | 22 ++-- include/modules/hyprland/language.hpp | 10 +- include/modules/hyprland/window.hpp | 6 +- include/modules/idle_inhibitor.hpp | 4 +- include/modules/inhibitor.hpp | 4 +- include/modules/jack.hpp | 32 +++--- include/modules/memory.hpp | 4 +- include/modules/mpd/mpd.hpp | 4 +- include/modules/mpd/state.hpp | 2 +- include/modules/network.hpp | 4 +- include/modules/pulseaudio.hpp | 4 +- include/modules/simpleclock.hpp | 4 +- include/modules/sndio.hpp | 4 +- include/modules/sway/language.hpp | 4 +- include/modules/sway/mode.hpp | 4 +- include/modules/temperature.hpp | 4 +- meson.build | 1 + src/AButton.cpp | 154 ++++++++++++++++++++++++++ src/modules/backlight.cpp | 10 +- src/modules/battery.cpp | 23 ++-- src/modules/bluetooth.cpp | 16 +-- src/modules/clock.cpp | 8 +- src/modules/cpu/common.cpp | 8 +- src/modules/custom.cpp | 24 ++-- src/modules/disk.cpp | 8 +- src/modules/hyprland/language.cpp | 16 +-- src/modules/idle_inhibitor.cpp | 18 +-- src/modules/inhibitor.cpp | 16 +-- src/modules/memory/common.cpp | 10 +- src/modules/mpd/mpd.cpp | 38 +++---- src/modules/network.cpp | 28 ++--- src/modules/pulseaudio.cpp | 26 ++--- src/modules/simpleclock.cpp | 10 +- src/modules/sndio.cpp | 10 +- src/modules/sway/language.cpp | 14 +-- src/modules/sway/mode.cpp | 8 +- src/modules/temperature.cpp | 30 ++--- 46 files changed, 423 insertions(+), 233 deletions(-) create mode 100644 include/AButton.hpp create mode 100644 src/AButton.cpp diff --git a/include/AButton.hpp b/include/AButton.hpp new file mode 100644 index 00000000..4628f1ea --- /dev/null +++ b/include/AButton.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#include + +#include "AModule.hpp" + +namespace waybar { + +class AButton : public AModule { + public: + AButton(const Json::Value &, const std::string &, const std::string &, const std::string &format, + uint16_t interval = 0, bool ellipsize = false, bool enable_click = false, + bool enable_scroll = false); + virtual ~AButton() = default; + virtual auto update() -> void; + virtual std::string getIcon(uint16_t, const std::string &alt = "", uint16_t max = 0); + virtual std::string getIcon(uint16_t, const std::vector &alts, uint16_t max = 0); + + protected: + Gtk::Button button_ = Gtk::Button(name_); + Gtk::Label *label_ = (Gtk::Label *)button_.get_child(); + std::string format_; + const std::chrono::seconds interval_; + bool alt_ = false; + std::string default_format_; + + virtual bool handleToggle(GdkEventButton *const &e); + virtual std::string getState(uint8_t value, bool lesser = false); +}; + +} // namespace waybar diff --git a/include/factory.hpp b/include/factory.hpp index 06cd4d90..a853841c 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -23,8 +23,8 @@ #endif #ifdef HAVE_HYPRLAND #include "modules/hyprland/backend.hpp" -#include "modules/hyprland/window.hpp" #include "modules/hyprland/language.hpp" +#include "modules/hyprland/window.hpp" #endif #if defined(__linux__) && !defined(NO_FILESYSTEM) #include "modules/battery.hpp" diff --git a/include/modules/backlight.hpp b/include/modules/backlight.hpp index b7499b8f..4f60d6ec 100644 --- a/include/modules/backlight.hpp +++ b/include/modules/backlight.hpp @@ -5,7 +5,7 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/json.hpp" #include "util/sleeper_thread.hpp" @@ -14,7 +14,7 @@ struct udev_device; namespace waybar::modules { -class Backlight : public ALabel { +class Backlight : public AButton { class BacklightDev { public: BacklightDev() = default; diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index 99950ae3..5f25fd59 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -13,7 +13,7 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { @@ -24,7 +24,7 @@ namespace fs = std::experimental::filesystem; namespace fs = std::filesystem; #endif -class Battery : public ALabel { +class Battery : public AButton { public: Battery(const std::string&, const Json::Value&); ~Battery(); diff --git a/include/modules/bluetooth.hpp b/include/modules/bluetooth.hpp index bd9737b1..6aac0747 100644 --- a/include/modules/bluetooth.hpp +++ b/include/modules/bluetooth.hpp @@ -1,6 +1,6 @@ #pragma once -#include "ALabel.hpp" +#include "AButton.hpp" #ifdef WANT_RFKILL #include "util/rfkill.hpp" #endif @@ -12,7 +12,7 @@ namespace waybar::modules { -class Bluetooth : public ALabel { +class Bluetooth : public AButton { struct ControllerInfo { std::string path; std::string address; diff --git a/include/modules/clock.hpp b/include/modules/clock.hpp index 08ab05e0..b3e49888 100644 --- a/include/modules/clock.hpp +++ b/include/modules/clock.hpp @@ -2,7 +2,7 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/sleeper_thread.hpp" namespace waybar { @@ -14,7 +14,7 @@ namespace modules { const std::string kCalendarPlaceholder = "calendar"; const std::string KTimezonedTimeListPlaceholder = "timezoned_time_list"; -class Clock : public ALabel { +class Clock : public AButton { public: Clock(const std::string&, const Json::Value&); ~Clock() = default; diff --git a/include/modules/cpu.hpp b/include/modules/cpu.hpp index 539f926c..4ad5771f 100644 --- a/include/modules/cpu.hpp +++ b/include/modules/cpu.hpp @@ -9,12 +9,12 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { -class Cpu : public ALabel { +class Cpu : public AButton { public: Cpu(const std::string&, const Json::Value&); ~Cpu() = default; diff --git a/include/modules/custom.hpp b/include/modules/custom.hpp index 711d07e2..e4a81bb4 100644 --- a/include/modules/custom.hpp +++ b/include/modules/custom.hpp @@ -5,14 +5,14 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/command.hpp" #include "util/json.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { -class Custom : public ALabel { +class Custom : public AButton { public: Custom(const std::string&, const std::string&, const Json::Value&); ~Custom(); diff --git a/include/modules/disk.hpp b/include/modules/disk.hpp index ec386b21..761314e2 100644 --- a/include/modules/disk.hpp +++ b/include/modules/disk.hpp @@ -5,13 +5,13 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/format.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { -class Disk : public ALabel { +class Disk : public AButton { public: Disk(const std::string&, const Json::Value&); ~Disk() = default; diff --git a/include/modules/hyprland/backend.hpp b/include/modules/hyprland/backend.hpp index b9d1c99e..51cbd8f1 100644 --- a/include/modules/hyprland/backend.hpp +++ b/include/modules/hyprland/backend.hpp @@ -1,30 +1,28 @@ #pragma once -#include -#include -#include #include #include +#include +#include +#include #include namespace waybar::modules::hyprland { class IPC { -public: + public: IPC() { startIPC(); } void registerForIPC(const std::string&, std::function); std::string getSocket1Reply(const std::string& rq); -private: + private: + void startIPC(); + void parseIPC(const std::string&); - void startIPC(); - void parseIPC(const std::string&); - - std::mutex callbackMutex; - std::deque>> callbacks; + std::mutex callbackMutex; + std::deque>> callbacks; }; inline std::unique_ptr gIPC; inline bool modulesReady = false; -}; - +}; // namespace waybar::modules::hyprland diff --git a/include/modules/hyprland/language.hpp b/include/modules/hyprland/language.hpp index 9e7193e2..bdf24ec3 100644 --- a/include/modules/hyprland/language.hpp +++ b/include/modules/hyprland/language.hpp @@ -1,20 +1,20 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "bar.hpp" #include "modules/hyprland/backend.hpp" #include "util/json.hpp" namespace waybar::modules::hyprland { -class Language : public waybar::ALabel { -public: +class Language : public waybar::AButton { + public: Language(const std::string&, const waybar::Bar&, const Json::Value&); ~Language() = default; auto update() -> void; -private: + private: void onEvent(const std::string&); void initLanguage(); @@ -26,4 +26,4 @@ private: std::string layoutName_; }; -} \ No newline at end of file +} // namespace waybar::modules::hyprland diff --git a/include/modules/hyprland/window.hpp b/include/modules/hyprland/window.hpp index e8446551..ac61156e 100644 --- a/include/modules/hyprland/window.hpp +++ b/include/modules/hyprland/window.hpp @@ -10,13 +10,13 @@ namespace waybar::modules::hyprland { class Window : public waybar::ALabel { -public: + public: Window(const std::string&, const waybar::Bar&, const Json::Value&); ~Window() = default; auto update() -> void; -private: + private: void onEvent(const std::string&); std::mutex mutex_; @@ -25,4 +25,4 @@ private: std::string lastView; }; -} \ No newline at end of file +} // namespace waybar::modules::hyprland \ No newline at end of file diff --git a/include/modules/idle_inhibitor.hpp b/include/modules/idle_inhibitor.hpp index ac0bcf02..f2ff6c1d 100644 --- a/include/modules/idle_inhibitor.hpp +++ b/include/modules/idle_inhibitor.hpp @@ -2,13 +2,13 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "bar.hpp" #include "client.hpp" namespace waybar::modules { -class IdleInhibitor : public ALabel { +class IdleInhibitor : public AButton { sigc::connection timeout_; public: diff --git a/include/modules/inhibitor.hpp b/include/modules/inhibitor.hpp index a5f300d6..9a012035 100644 --- a/include/modules/inhibitor.hpp +++ b/include/modules/inhibitor.hpp @@ -4,12 +4,12 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "bar.hpp" namespace waybar::modules { -class Inhibitor : public ALabel { +class Inhibitor : public AButton { public: Inhibitor(const std::string&, const waybar::Bar&, const Json::Value&); ~Inhibitor() override; diff --git a/include/modules/jack.hpp b/include/modules/jack.hpp index a3555be6..fbab0623 100644 --- a/include/modules/jack.hpp +++ b/include/modules/jack.hpp @@ -1,9 +1,11 @@ #pragma once #include -#include #include #include + +#include + #include "ALabel.hpp" #include "util/sleeper_thread.hpp" @@ -11,26 +13,26 @@ namespace waybar::modules { class JACK : public ALabel { public: - JACK(const std::string&, const Json::Value&); + JACK(const std::string &, const Json::Value &); ~JACK() = default; auto update() -> void; - int bufSize(jack_nframes_t size); - int sampleRate(jack_nframes_t rate); - int xrun(); - void shutdown(); + int bufSize(jack_nframes_t size); + int sampleRate(jack_nframes_t rate); + int xrun(); + void shutdown(); private: - std::string JACKState(); + std::string JACKState(); - jack_client_t* client_; - jack_nframes_t bufsize_; - jack_nframes_t samplerate_; - unsigned int xruns_; - float load_; - bool running_; - std::mutex mutex_; - std::string state_; + jack_client_t *client_; + jack_nframes_t bufsize_; + jack_nframes_t samplerate_; + unsigned int xruns_; + float load_; + bool running_; + std::mutex mutex_; + std::string state_; util::SleeperThread thread_; }; diff --git a/include/modules/memory.hpp b/include/modules/memory.hpp index e23ed841..a5887e3d 100644 --- a/include/modules/memory.hpp +++ b/include/modules/memory.hpp @@ -5,12 +5,12 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { -class Memory : public ALabel { +class Memory : public AButton { public: Memory(const std::string&, const Json::Value&); ~Memory() = default; diff --git a/include/modules/mpd/mpd.hpp b/include/modules/mpd/mpd.hpp index ae3f9152..b85906d1 100644 --- a/include/modules/mpd/mpd.hpp +++ b/include/modules/mpd/mpd.hpp @@ -7,12 +7,12 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "modules/mpd/state.hpp" namespace waybar::modules { -class MPD : public ALabel { +class MPD : public AButton { friend class detail::Context; // State machine diff --git a/include/modules/mpd/state.hpp b/include/modules/mpd/state.hpp index 1276e3c3..28ca6410 100644 --- a/include/modules/mpd/state.hpp +++ b/include/modules/mpd/state.hpp @@ -7,7 +7,7 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" namespace waybar::modules { class MPD; diff --git a/include/modules/network.hpp b/include/modules/network.hpp index 8ec6b6df..9f13da59 100644 --- a/include/modules/network.hpp +++ b/include/modules/network.hpp @@ -10,7 +10,7 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/sleeper_thread.hpp" #ifdef WANT_RFKILL #include "util/rfkill.hpp" @@ -18,7 +18,7 @@ namespace waybar::modules { -class Network : public ALabel { +class Network : public AButton { public: Network(const std::string&, const Json::Value&); ~Network(); diff --git a/include/modules/pulseaudio.hpp b/include/modules/pulseaudio.hpp index a8e4890a..f222f9e7 100644 --- a/include/modules/pulseaudio.hpp +++ b/include/modules/pulseaudio.hpp @@ -7,11 +7,11 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" namespace waybar::modules { -class Pulseaudio : public ALabel { +class Pulseaudio : public AButton { public: Pulseaudio(const std::string&, const Json::Value&); ~Pulseaudio(); diff --git a/include/modules/simpleclock.hpp b/include/modules/simpleclock.hpp index 5cbee4c6..2945d86e 100644 --- a/include/modules/simpleclock.hpp +++ b/include/modules/simpleclock.hpp @@ -2,12 +2,12 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { -class Clock : public ALabel { +class Clock : public AButton { public: Clock(const std::string&, const Json::Value&); ~Clock() = default; diff --git a/include/modules/sndio.hpp b/include/modules/sndio.hpp index eb9b218e..6d7350cf 100644 --- a/include/modules/sndio.hpp +++ b/include/modules/sndio.hpp @@ -4,12 +4,12 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { -class Sndio : public ALabel { +class Sndio : public AButton { public: Sndio(const std::string &, const Json::Value &); ~Sndio(); diff --git a/include/modules/sway/language.hpp b/include/modules/sway/language.hpp index f7602765..8673067b 100644 --- a/include/modules/sway/language.hpp +++ b/include/modules/sway/language.hpp @@ -6,7 +6,7 @@ #include #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "bar.hpp" #include "client.hpp" #include "modules/sway/ipc/client.hpp" @@ -14,7 +14,7 @@ namespace waybar::modules::sway { -class Language : public ALabel, public sigc::trackable { +class Language : public AButton, public sigc::trackable { public: Language(const std::string& id, const Json::Value& config); ~Language() = default; diff --git a/include/modules/sway/mode.hpp b/include/modules/sway/mode.hpp index 5543c4eb..041f68ac 100644 --- a/include/modules/sway/mode.hpp +++ b/include/modules/sway/mode.hpp @@ -2,7 +2,7 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "bar.hpp" #include "client.hpp" #include "modules/sway/ipc/client.hpp" @@ -10,7 +10,7 @@ namespace waybar::modules::sway { -class Mode : public ALabel, public sigc::trackable { +class Mode : public AButton, public sigc::trackable { public: Mode(const std::string&, const Json::Value&); ~Mode() = default; diff --git a/include/modules/temperature.hpp b/include/modules/temperature.hpp index 04caafc5..47898015 100644 --- a/include/modules/temperature.hpp +++ b/include/modules/temperature.hpp @@ -4,12 +4,12 @@ #include -#include "ALabel.hpp" +#include "AButton.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { -class Temperature : public ALabel { +class Temperature : public AButton { public: Temperature(const std::string&, const Json::Value&); ~Temperature() = default; diff --git a/meson.build b/meson.build index 420606aa..a69ce60b 100644 --- a/meson.build +++ b/meson.build @@ -143,6 +143,7 @@ endif src_files = files( 'src/factory.cpp', 'src/AModule.cpp', + 'src/AButton.cpp', 'src/ALabel.cpp', 'src/AIconLabel.cpp', 'src/modules/custom.cpp', diff --git a/src/AButton.cpp b/src/AButton.cpp new file mode 100644 index 00000000..3b9ad2d4 --- /dev/null +++ b/src/AButton.cpp @@ -0,0 +1,154 @@ +#include "AButton.hpp" + +#include + +#include + +namespace waybar { + +AButton::AButton(const Json::Value& config, const std::string& name, const std::string& id, + const std::string& format, uint16_t interval, bool ellipsize, bool enable_click, + bool enable_scroll) + : AModule(config, name, id, config["format-alt"].isString() || enable_click, enable_scroll), + format_(config_["format"].isString() ? config_["format"].asString() : format), + interval_(config_["interval"] == "once" + ? std::chrono::seconds(100000000) + : std::chrono::seconds( + config_["interval"].isUInt() ? config_["interval"].asUInt() : interval)), + default_format_(format_) { + button_.set_name(name); + button_.set_relief(Gtk::RELIEF_NONE); + if (!id.empty()) { + button_.get_style_context()->add_class(id); + } + event_box_.add(button_); + if (config_["max-length"].isUInt()) { + label_->set_max_width_chars(config_["max-length"].asInt()); + label_->set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END); + label_->set_single_line_mode(true); + } else if (ellipsize && label_->get_max_width_chars() == -1) { + label_->set_ellipsize(Pango::EllipsizeMode::ELLIPSIZE_END); + label_->set_single_line_mode(true); + } + + if (config_["min-length"].isUInt()) { + label_->set_width_chars(config_["min-length"].asUInt()); + } + + uint rotate = 0; + + if (config_["rotate"].isUInt()) { + rotate = config["rotate"].asUInt(); + label_->set_angle(rotate); + } + + if (config_["align"].isDouble()) { + auto align = config_["align"].asFloat(); + if (rotate == 90 || rotate == 270) { + label_->set_yalign(align); + } else { + label_->set_xalign(align); + } + } + + if (!(config_["on-click"].isString() || config_["on-click-middle"].isString() || + config_["on-click-backward"].isString() || config_["on-click-forward"].isString() || + config_["on-click-right"].isString() || config_["format-alt"].isString() || enable_click)) { + button_.set_sensitive(false); + } else { + button_.signal_pressed().connect([this] { + GdkEventButton* e = (GdkEventButton*)gdk_event_new(GDK_BUTTON_PRESS); + e->button = 1; + handleToggle(e); + }); + } +} + +auto AButton::update() -> void { AModule::update(); } + +std::string AButton::getIcon(uint16_t percentage, const std::string& alt, uint16_t max) { + auto format_icons = config_["format-icons"]; + if (format_icons.isObject()) { + if (!alt.empty() && (format_icons[alt].isString() || format_icons[alt].isArray())) { + format_icons = format_icons[alt]; + } else { + format_icons = format_icons["default"]; + } + } + if (format_icons.isArray()) { + auto size = format_icons.size(); + auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1); + format_icons = format_icons[idx]; + } + if (format_icons.isString()) { + return format_icons.asString(); + } + return ""; +} + +std::string AButton::getIcon(uint16_t percentage, const std::vector& alts, + uint16_t max) { + auto format_icons = config_["format-icons"]; + if (format_icons.isObject()) { + std::string _alt = "default"; + for (const auto& alt : alts) { + if (!alt.empty() && (format_icons[alt].isString() || format_icons[alt].isArray())) { + _alt = alt; + break; + } + } + format_icons = format_icons[_alt]; + } + if (format_icons.isArray()) { + auto size = format_icons.size(); + auto idx = std::clamp(percentage / ((max == 0 ? 100 : max) / size), 0U, size - 1); + format_icons = format_icons[idx]; + } + if (format_icons.isString()) { + return format_icons.asString(); + } + return ""; +} + +bool waybar::AButton::handleToggle(GdkEventButton* const& e) { + if (config_["format-alt-click"].isUInt() && e->button == config_["format-alt-click"].asUInt()) { + alt_ = !alt_; + if (alt_ && config_["format-alt"].isString()) { + format_ = config_["format-alt"].asString(); + } else { + format_ = default_format_; + } + } + return AModule::handleToggle(e); +} + +std::string AButton::getState(uint8_t value, bool lesser) { + if (!config_["states"].isObject()) { + return ""; + } + // Get current state + std::vector> states; + if (config_["states"].isObject()) { + for (auto it = config_["states"].begin(); it != config_["states"].end(); ++it) { + if (it->isUInt() && it.key().isString()) { + states.emplace_back(it.key().asString(), it->asUInt()); + } + } + } + // Sort states + std::sort(states.begin(), states.end(), [&lesser](auto& a, auto& b) { + return lesser ? a.second < b.second : a.second > b.second; + }); + std::string valid_state; + for (auto const& state : states) { + if ((lesser ? value <= state.second : value >= state.second) && valid_state.empty()) { + label_->get_style_context()->add_class(state.first); + valid_state = state.first; + } else { + label_->get_style_context()->remove_class(state.first); + } + } + return valid_state; +} + +} // namespace waybar diff --git a/src/modules/backlight.cpp b/src/modules/backlight.cpp index 4b34824f..12ae0488 100644 --- a/src/modules/backlight.cpp +++ b/src/modules/backlight.cpp @@ -87,7 +87,7 @@ 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 &id, const Json::Value &config) - : ALabel(config, "backlight", id, "{percent}%", 2), + : AButton(config, "backlight", id, "{percent}%", 2), preferred_device_(config["device"].isString() ? config["device"].asString() : "") { // Get initial state { @@ -174,19 +174,19 @@ auto waybar::modules::Backlight::update() -> void { const uint8_t percent = best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max()); - label_.set_markup(fmt::format(format_, fmt::arg("percent", std::to_string(percent)), - fmt::arg("icon", getIcon(percent)))); + label_->set_markup(fmt::format(format_, fmt::arg("percent", std::to_string(percent)), + fmt::arg("icon", getIcon(percent)))); getState(percent); } else { if (!previous_best_.has_value()) { return; } - label_.set_markup(""); + label_->set_markup(""); } previous_best_ = best == nullptr ? std::nullopt : std::optional{*best}; previous_format_ = format_; // Call parent update - ALabel::update(); + AButton::update(); } template diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index bd8583c5..1a371726 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -3,7 +3,7 @@ #include waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config) - : ALabel(config, "battery", id, "{capacity}%", 60) { + : AButton(config, "battery", id, "{capacity}%", 60) { battery_watch_fd_ = inotify_init1(IN_CLOEXEC); if (battery_watch_fd_ == -1) { throw std::runtime_error("Unable to listen batteries."); @@ -309,7 +309,8 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai format = config_["format-time"].asString(); } std::string zero_pad_minutes = fmt::format("{:02d}", minutes); - return fmt::format(format, fmt::arg("H", full_hours), fmt::arg("M", minutes), fmt::arg("m", zero_pad_minutes)); + return fmt::format(format, fmt::arg("H", full_hours), fmt::arg("M", minutes), + fmt::arg("m", zero_pad_minutes)); } auto waybar::modules::Battery::update() -> void { @@ -346,14 +347,14 @@ auto waybar::modules::Battery::update() -> void { } else if (config_["tooltip-format"].isString()) { tooltip_format = config_["tooltip-format"].asString(); } - label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default), - fmt::arg("capacity", capacity), - fmt::arg("time", time_remaining_formatted))); + label_->set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default), + fmt::arg("capacity", capacity), + fmt::arg("time", time_remaining_formatted))); } if (!old_status_.empty()) { - label_.get_style_context()->remove_class(old_status_); + label_->get_style_context()->remove_class(old_status_); } - label_.get_style_context()->add_class(status); + label_->get_style_context()->add_class(status); old_status_ = status; if (!state.empty() && config_["format-" + status + "-" + state].isString()) { format = config_["format-" + status + "-" + state].asString(); @@ -367,10 +368,10 @@ auto waybar::modules::Battery::update() -> void { } else { event_box_.show(); auto icons = std::vector{status + "-" + state, status, state}; - label_.set_markup(fmt::format(format, fmt::arg("capacity", capacity), fmt::arg("power", power), - fmt::arg("icon", getIcon(capacity, icons)), - fmt::arg("time", time_remaining_formatted))); + label_->set_markup(fmt::format(format, fmt::arg("capacity", capacity), fmt::arg("power", power), + fmt::arg("icon", getIcon(capacity, icons)), + fmt::arg("time", time_remaining_formatted))); } // Call parent update - ALabel::update(); + AButton::update(); } diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index 7a640f09..242774e1 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -80,7 +80,7 @@ auto getUcharProperty(GDBusProxy* proxy, const char* property_name) -> unsigned } // namespace waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& config) - : ALabel(config, "bluetooth", id, " {status}", 10), + : AButton(config, "bluetooth", id, " {status}", 10), #ifdef WANT_RFKILL rfkill_{RFKILL_TYPE_BLUETOOTH}, #endif @@ -189,10 +189,10 @@ auto waybar::modules::Bluetooth::update() -> void { format_.empty() ? event_box_.hide() : event_box_.show(); auto update_style_context = [this](const std::string& style_class, bool in_next_state) { - if (in_next_state && !label_.get_style_context()->has_class(style_class)) { - label_.get_style_context()->add_class(style_class); - } else if (!in_next_state && label_.get_style_context()->has_class(style_class)) { - label_.get_style_context()->remove_class(style_class); + if (in_next_state && !label_->get_style_context()->has_class(style_class)) { + label_->get_style_context()->add_class(style_class); + } else if (!in_next_state && label_->get_style_context()->has_class(style_class)) { + label_->get_style_context()->remove_class(style_class); } }; update_style_context("discoverable", cur_controller_.discoverable); @@ -204,7 +204,7 @@ auto waybar::modules::Bluetooth::update() -> void { update_style_context(state, true); state_ = state; - label_.set_markup(fmt::format( + label_->set_markup(fmt::format( format_, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()), fmt::arg("controller_address", cur_controller_.address), fmt::arg("controller_address_type", cur_controller_.address_type), @@ -245,7 +245,7 @@ auto waybar::modules::Bluetooth::update() -> void { device_enumerate_.erase(0, 1); } } - label_.set_tooltip_text(fmt::format( + label_->set_tooltip_text(fmt::format( tooltip_format, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()), fmt::arg("controller_address", cur_controller_.address), @@ -259,7 +259,7 @@ auto waybar::modules::Bluetooth::update() -> void { } // Call parent update - ALabel::update(); + AButton::update(); } // NOTE: only for when the org.bluez.Battery1 interface is added/removed after/before a device is diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 71b24c19..07625d5d 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -18,7 +18,7 @@ using waybar::waybar_time; waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) - : ALabel(config, "clock", id, "{:%H:%M}", 60, false, false, true), + : AButton(config, "clock", id, "{:%H:%M}", 60, false, false, true), current_time_zone_idx_(0), is_calendar_in_tooltip_(false), is_timezoned_list_in_tooltip_(false) { @@ -107,7 +107,7 @@ auto waybar::modules::Clock::update() -> void { } else { text = fmt::format(format_, wtime); } - label_.set_markup(text); + label_->set_markup(text); if (tooltipEnabled()) { if (config_["tooltip-format"].isString()) { @@ -119,12 +119,12 @@ auto waybar::modules::Clock::update() -> void { text = fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines), fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines)); - label_.set_tooltip_markup(text); + label_->set_tooltip_markup(text); } } // Call parent update - ALabel::update(); + AButton::update(); } bool waybar::modules::Clock::handleScroll(GdkEventScroll* e) { diff --git a/src/modules/cpu/common.cpp b/src/modules/cpu/common.cpp index cdbbc3d4..888d3117 100644 --- a/src/modules/cpu/common.cpp +++ b/src/modules/cpu/common.cpp @@ -10,7 +10,7 @@ #endif waybar::modules::Cpu::Cpu(const std::string& id, const Json::Value& config) - : ALabel(config, "cpu", id, "{usage}%", 10) { + : AButton(config, "cpu", id, "{usage}%", 10) { thread_ = [this] { dp.emit(); thread_.sleep_for(interval_); @@ -23,7 +23,7 @@ auto waybar::modules::Cpu::update() -> void { auto [cpu_usage, tooltip] = getCpuUsage(); auto [max_frequency, min_frequency, avg_frequency] = getCpuFrequency(); if (tooltipEnabled()) { - label_.set_tooltip_text(tooltip); + label_->set_tooltip_text(tooltip); } auto format = format_; auto total_usage = cpu_usage.empty() ? 0 : cpu_usage[0]; @@ -52,11 +52,11 @@ auto waybar::modules::Cpu::update() -> void { auto icon_format = fmt::format("icon{}", core_i); store.push_back(fmt::arg(icon_format.c_str(), getIcon(cpu_usage[i], icons))); } - label_.set_markup(fmt::vformat(format, store)); + label_->set_markup(fmt::vformat(format, store)); } // Call parent update - ALabel::update(); + AButton::update(); } double waybar::modules::Cpu::getCpuLoad() { diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index 6fc01675..17950ddd 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -4,7 +4,7 @@ waybar::modules::Custom::Custom(const std::string& name, const std::string& id, const Json::Value& config) - : ALabel(config, "custom-" + name, id, "{}"), + : AButton(config, "custom-" + name, id, "{}"), name_(name), id_(id), percentage_(0), @@ -103,13 +103,13 @@ void waybar::modules::Custom::handleEvent() { } bool waybar::modules::Custom::handleScroll(GdkEventScroll* e) { - auto ret = ALabel::handleScroll(e); + auto ret = AButton::handleScroll(e); handleEvent(); return ret; } bool waybar::modules::Custom::handleToggle(GdkEventButton* const& e) { - auto ret = ALabel::handleToggle(e); + auto ret = AButton::handleToggle(e); handleEvent(); return ret; } @@ -131,31 +131,31 @@ auto waybar::modules::Custom::update() -> void { if (str.empty()) { event_box_.hide(); } else { - label_.set_markup(str); + label_->set_markup(str); if (tooltipEnabled()) { if (text_ == tooltip_) { - if (label_.get_tooltip_markup() != str) { - label_.set_tooltip_markup(str); + if (label_->get_tooltip_markup() != str) { + label_->set_tooltip_markup(str); } } else { - if (label_.get_tooltip_markup() != tooltip_) { - label_.set_tooltip_markup(tooltip_); + if (label_->get_tooltip_markup() != tooltip_) { + label_->set_tooltip_markup(tooltip_); } } } - auto classes = label_.get_style_context()->list_classes(); + auto classes = label_->get_style_context()->list_classes(); for (auto const& c : classes) { if (c == id_) continue; - label_.get_style_context()->remove_class(c); + label_->get_style_context()->remove_class(c); } for (auto const& c : class_) { - label_.get_style_context()->add_class(c); + label_->get_style_context()->add_class(c); } event_box_.show(); } } // Call parent update - ALabel::update(); + AButton::update(); } void waybar::modules::Custom::parseOutputRaw() { diff --git a/src/modules/disk.cpp b/src/modules/disk.cpp index 5578dc2f..1767cfd3 100644 --- a/src/modules/disk.cpp +++ b/src/modules/disk.cpp @@ -3,7 +3,7 @@ using namespace waybar::util; waybar::modules::Disk::Disk(const std::string& id, const Json::Value& config) - : ALabel(config, "disk", id, "{}%", 30), path_("/") { + : AButton(config, "disk", id, "{}%", 30), path_("/") { thread_ = [this] { dp.emit(); thread_.sleep_for(interval_); @@ -58,7 +58,7 @@ auto waybar::modules::Disk::update() -> void { event_box_.hide(); } else { event_box_.show(); - label_.set_markup( + label_->set_markup( fmt::format(format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), @@ -70,12 +70,12 @@ auto waybar::modules::Disk::update() -> void { if (config_["tooltip-format"].isString()) { tooltip_format = config_["tooltip-format"].asString(); } - label_.set_tooltip_text( + label_->set_tooltip_text( fmt::format(tooltip_format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), fmt::arg("total", total), fmt::arg("path", path_))); } // Call parent update - ALabel::update(); + AButton::update(); } diff --git a/src/modules/hyprland/language.cpp b/src/modules/hyprland/language.cpp index 5463508b..afd31e1c 100644 --- a/src/modules/hyprland/language.cpp +++ b/src/modules/hyprland/language.cpp @@ -9,7 +9,7 @@ namespace waybar::modules::hyprland { Language::Language(const std::string& id, const Bar& bar, const Json::Value& config) - : ALabel(config, "language", id, "{}", 0, true), bar_(bar) { + : AButton(config, "language", id, "{}", 0, true), bar_(bar) { modulesReady = true; if (!gIPC.get()) { @@ -19,8 +19,8 @@ Language::Language(const std::string& id, const Bar& bar, const Json::Value& con // get the active layout when open initLanguage(); - label_.hide(); - ALabel::update(); + button_.hide(); + AButton::update(); // register for hyprland ipc gIPC->registerForIPC("activelayout", [&](const std::string& ev) { this->onEvent(ev); }); @@ -30,13 +30,13 @@ auto Language::update() -> void { std::lock_guard lg(mutex_); if (!format_.empty()) { - label_.show(); - label_.set_markup(layoutName_); + button_.show(); + label_->set_markup(layoutName_); } else { - label_.hide(); + button_.hide(); } - ALabel::update(); + AButton::update(); } void Language::onEvent(const std::string& ev) { @@ -128,4 +128,4 @@ std::string Language::getShortFrom(const std::string& fullName) { return ""; } -} // namespace waybar::modules::hyprland \ No newline at end of file +} // namespace waybar::modules::hyprland diff --git a/src/modules/idle_inhibitor.cpp b/src/modules/idle_inhibitor.cpp index 3302abb6..fd5611fe 100644 --- a/src/modules/idle_inhibitor.cpp +++ b/src/modules/idle_inhibitor.cpp @@ -8,7 +8,7 @@ bool waybar::modules::IdleInhibitor::status = false; waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& bar, const Json::Value& config) - : ALabel(config, "idle_inhibitor", id, "{status}"), + : AButton(config, "idle_inhibitor", id, "{status}", 0, false, true), bar_(bar), idle_inhibitor_(nullptr), pid_(-1) { @@ -44,13 +44,13 @@ waybar::modules::IdleInhibitor::~IdleInhibitor() { auto waybar::modules::IdleInhibitor::update() -> void { // Check status if (status) { - label_.get_style_context()->remove_class("deactivated"); + label_->get_style_context()->remove_class("deactivated"); if (idle_inhibitor_ == nullptr) { idle_inhibitor_ = zwp_idle_inhibit_manager_v1_create_inhibitor( waybar::Client::inst()->idle_inhibit_manager, bar_.surface); } } else { - label_.get_style_context()->remove_class("activated"); + label_->get_style_context()->remove_class("activated"); if (idle_inhibitor_ != nullptr) { zwp_idle_inhibitor_v1_destroy(idle_inhibitor_); idle_inhibitor_ = nullptr; @@ -58,11 +58,11 @@ auto waybar::modules::IdleInhibitor::update() -> void { } std::string status_text = status ? "activated" : "deactivated"; - label_.set_markup(fmt::format(format_, fmt::arg("status", status_text), - fmt::arg("icon", getIcon(0, status_text)))); - label_.get_style_context()->add_class(status_text); + label_->set_markup(fmt::format(format_, fmt::arg("status", status_text), + fmt::arg("icon", getIcon(0, status_text)))); + label_->get_style_context()->add_class(status_text); if (tooltipEnabled()) { - label_.set_tooltip_markup( + label_->set_tooltip_markup( status ? fmt::format(config_["tooltip-format-activated"].isString() ? config_["tooltip-format-activated"].asString() : "{status}", @@ -75,7 +75,7 @@ auto waybar::modules::IdleInhibitor::update() -> void { fmt::arg("icon", getIcon(0, status_text)))); } // Call parent update - ALabel::update(); + AButton::update(); } bool waybar::modules::IdleInhibitor::handleToggle(GdkEventButton* const& e) { @@ -115,6 +115,6 @@ bool waybar::modules::IdleInhibitor::handleToggle(GdkEventButton* const& e) { } } - ALabel::handleToggle(e); + AButton::handleToggle(e); return true; } diff --git a/src/modules/inhibitor.cpp b/src/modules/inhibitor.cpp index e4340b14..2ab013db 100644 --- a/src/modules/inhibitor.cpp +++ b/src/modules/inhibitor.cpp @@ -98,7 +98,7 @@ auto getInhibitors(const Json::Value& config) -> std::string { namespace waybar::modules { Inhibitor::Inhibitor(const std::string& id, const Bar& bar, const Json::Value& config) - : ALabel(config, "inhibitor", id, "{status}", true), + : AButton(config, "inhibitor", id, "{status}", true), dbus_(::dbus()), inhibitors_(::getInhibitors(config)) { event_box_.add_events(Gdk::BUTTON_PRESS_MASK); @@ -117,16 +117,16 @@ auto Inhibitor::activated() -> bool { return handle_ != -1; } auto Inhibitor::update() -> void { std::string status_text = activated() ? "activated" : "deactivated"; - label_.get_style_context()->remove_class(activated() ? "deactivated" : "activated"); - label_.set_markup(fmt::format(format_, fmt::arg("status", status_text), - fmt::arg("icon", getIcon(0, status_text)))); - label_.get_style_context()->add_class(status_text); + label_->get_style_context()->remove_class(activated() ? "deactivated" : "activated"); + label_->set_markup(fmt::format(format_, fmt::arg("status", status_text), + fmt::arg("icon", getIcon(0, status_text)))); + label_->get_style_context()->add_class(status_text); if (tooltipEnabled()) { - label_.set_tooltip_text(status_text); + label_->set_tooltip_text(status_text); } - return ALabel::update(); + return AButton::update(); } auto Inhibitor::handleToggle(GdkEventButton* const& e) -> bool { @@ -142,7 +142,7 @@ auto Inhibitor::handleToggle(GdkEventButton* const& e) -> bool { } } - return ALabel::handleToggle(e); + return AButton::handleToggle(e); } } // namespace waybar::modules diff --git a/src/modules/memory/common.cpp b/src/modules/memory/common.cpp index 6bf84e86..b9244451 100644 --- a/src/modules/memory/common.cpp +++ b/src/modules/memory/common.cpp @@ -1,7 +1,7 @@ #include "modules/memory.hpp" waybar::modules::Memory::Memory(const std::string& id, const Json::Value& config) - : ALabel(config, "memory", id, "{}%", 30) { + : AButton(config, "memory", id, "{}%", 30) { thread_ = [this] { dp.emit(); thread_.sleep_for(interval_); @@ -54,7 +54,7 @@ auto waybar::modules::Memory::update() -> void { } else { event_box_.show(); auto icons = std::vector{state}; - label_.set_markup(fmt::format( + label_->set_markup(fmt::format( format, used_ram_percentage, fmt::arg("icon", getIcon(used_ram_percentage, icons)), fmt::arg("total", total_ram_gigabytes), fmt::arg("swapTotal", total_swap_gigabytes), fmt::arg("percentage", used_ram_percentage), @@ -66,7 +66,7 @@ auto waybar::modules::Memory::update() -> void { if (tooltipEnabled()) { if (config_["tooltip-format"].isString()) { auto tooltip_format = config_["tooltip-format"].asString(); - label_.set_tooltip_text(fmt::format( + label_->set_tooltip_text(fmt::format( tooltip_format, used_ram_percentage, fmt::arg("total", total_ram_gigabytes), fmt::arg("swapTotal", total_swap_gigabytes), fmt::arg("percentage", used_ram_percentage), @@ -74,12 +74,12 @@ auto waybar::modules::Memory::update() -> void { fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes), fmt::arg("swapAvail", available_swap_gigabytes))); } else { - label_.set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1)); + label_->set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1)); } } } else { event_box_.hide(); } // Call parent update - ALabel::update(); + AButton::update(); } diff --git a/src/modules/mpd/mpd.cpp b/src/modules/mpd/mpd.cpp index 0f58343d..a79f203a 100644 --- a/src/modules/mpd/mpd.cpp +++ b/src/modules/mpd/mpd.cpp @@ -12,7 +12,7 @@ namespace waybar::modules { #endif waybar::modules::MPD::MPD(const std::string& id, const Json::Value& config) - : ALabel(config, "mpd", id, "{album} - {artist} - {title}", 5), + : AButton(config, "mpd", id, "{album} - {artist} - {title}", 5, false, true), module_name_(id.empty() ? "mpd" : "mpd#" + id), server_(nullptr), port_(config_["port"].isUInt() ? config["port"].asUInt() : 0), @@ -44,7 +44,7 @@ auto waybar::modules::MPD::update() -> void { context_.update(); // Call parent update - ALabel::update(); + AButton::update(); } void waybar::modules::MPD::queryMPD() { @@ -85,15 +85,15 @@ std::string waybar::modules::MPD::getFilename() const { void waybar::modules::MPD::setLabel() { if (connection_ == nullptr) { - label_.get_style_context()->add_class("disconnected"); - label_.get_style_context()->remove_class("stopped"); - label_.get_style_context()->remove_class("playing"); - label_.get_style_context()->remove_class("paused"); + label_->get_style_context()->add_class("disconnected"); + label_->get_style_context()->remove_class("stopped"); + label_->get_style_context()->remove_class("playing"); + label_->get_style_context()->remove_class("paused"); auto format = config_["format-disconnected"].isString() ? config_["format-disconnected"].asString() : "disconnected"; - label_.set_markup(format); + label_->set_markup(format); if (tooltipEnabled()) { std::string tooltip_format; @@ -101,11 +101,11 @@ void waybar::modules::MPD::setLabel() { ? config_["tooltip-format-disconnected"].asString() : "MPD (disconnected)"; // Nothing to format - label_.set_tooltip_text(tooltip_format); + label_->set_tooltip_text(tooltip_format); } return; } else { - label_.get_style_context()->remove_class("disconnected"); + label_->get_style_context()->remove_class("disconnected"); } auto format = format_; @@ -118,19 +118,19 @@ void waybar::modules::MPD::setLabel() { if (stopped()) { format = config_["format-stopped"].isString() ? config_["format-stopped"].asString() : "stopped"; - label_.get_style_context()->add_class("stopped"); - label_.get_style_context()->remove_class("playing"); - label_.get_style_context()->remove_class("paused"); + label_->get_style_context()->add_class("stopped"); + label_->get_style_context()->remove_class("playing"); + label_->get_style_context()->remove_class("paused"); } else { - label_.get_style_context()->remove_class("stopped"); + label_->get_style_context()->remove_class("stopped"); if (playing()) { - label_.get_style_context()->add_class("playing"); - label_.get_style_context()->remove_class("paused"); + label_->get_style_context()->add_class("playing"); + label_->get_style_context()->remove_class("paused"); } else if (paused()) { format = config_["format-paused"].isString() ? config_["format-paused"].asString() : config_["format"].asString(); - label_.get_style_context()->add_class("paused"); - label_.get_style_context()->remove_class("playing"); + label_->get_style_context()->add_class("paused"); + label_->get_style_context()->remove_class("playing"); } stateIcon = getStateIcon(); @@ -166,7 +166,7 @@ void waybar::modules::MPD::setLabel() { if (config_["title-len"].isInt()) title = title.substr(0, config_["title-len"].asInt()); try { - label_.set_markup(fmt::format( + label_->set_markup(fmt::format( format, fmt::arg("artist", Glib::Markup::escape_text(artist).raw()), fmt::arg("albumArtist", Glib::Markup::escape_text(album_artist).raw()), fmt::arg("album", Glib::Markup::escape_text(album).raw()), @@ -195,7 +195,7 @@ void waybar::modules::MPD::setLabel() { fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon), fmt::arg("consumeIcon", consumeIcon), fmt::arg("randomIcon", randomIcon), fmt::arg("repeatIcon", repeatIcon), fmt::arg("singleIcon", singleIcon)); - label_.set_tooltip_text(tooltip_text); + label_->set_tooltip_text(tooltip_text); } catch (fmt::format_error const& e) { spdlog::warn("mpd: format error (tooltip): {}", e.what()); } diff --git a/src/modules/network.cpp b/src/modules/network.cpp index 3fe4a8b0..c5200266 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -78,7 +78,7 @@ waybar::modules::Network::readBandwidthUsage() { } waybar::modules::Network::Network(const std::string &id, const Json::Value &config) - : ALabel(config, "network", id, DEFAULT_FORMAT, 60), + : AButton(config, "network", id, DEFAULT_FORMAT, 60), ifid_(-1), family_(config["family"] == "ipv6" ? AF_INET6 : AF_INET), efd_(-1), @@ -95,11 +95,11 @@ waybar::modules::Network::Network(const std::string &id, const Json::Value &conf #endif frequency_(0.0) { - // Start with some "text" in the module's label_, update() will then + // Start with some "text" in the module's label_-> update() will then // update it. Since the text should be different, update() will be able // to show or hide the event_box_. This is to work around the case where // the module start with no text, but the the event_box_ is shown. - label_.set_markup(""); + label_->set_markup(""); auto bandwidth = readBandwidthUsage(); if (bandwidth.has_value()) { @@ -309,8 +309,8 @@ auto waybar::modules::Network::update() -> void { if (!alt_) { auto state = getNetworkState(); - if (!state_.empty() && label_.get_style_context()->has_class(state_)) { - label_.get_style_context()->remove_class(state_); + 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(); @@ -322,8 +322,8 @@ auto waybar::modules::Network::update() -> void { 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); + if (!label_->get_style_context()->has_class(state)) { + label_->get_style_context()->add_class(state); } format_ = default_format_; state_ = state; @@ -349,8 +349,8 @@ auto waybar::modules::Network::update() -> void { fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / interval_.count(), "B/s")), fmt::arg("bandwidthTotalBytes", pow_format((bandwidth_up + bandwidth_down) / interval_.count(), "B/s"))); - if (text.compare(label_.get_label()) != 0) { - label_.set_markup(text); + if (text.compare(label_->get_label()) != 0) { + label_->set_markup(text); if (text.empty()) { event_box_.hide(); } else { @@ -382,16 +382,16 @@ auto waybar::modules::Network::update() -> void { fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / interval_.count(), "B/s")), fmt::arg("bandwidthTotalBytes", pow_format((bandwidth_up + bandwidth_down) / interval_.count(), "B/s"))); - if (label_.get_tooltip_text() != tooltip_text) { - label_.set_tooltip_markup(tooltip_text); + if (label_->get_tooltip_text() != tooltip_text) { + label_->set_tooltip_markup(tooltip_text); } - } else if (label_.get_tooltip_text() != text) { - label_.set_tooltip_markup(text); + } else if (label_->get_tooltip_text() != text) { + label_->set_tooltip_markup(text); } } // Call parent update - ALabel::update(); + AButton::update(); } bool waybar::modules::Network::checkInterface(std::string name) { diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 24b858d3..11aaced7 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -1,7 +1,7 @@ #include "modules/pulseaudio.hpp" waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value &config) - : ALabel(config, "pulseaudio", id, "{volume}%"), + : AButton(config, "pulseaudio", id, "{volume}%"), mainloop_(nullptr), mainloop_api_(nullptr), context_(nullptr), @@ -240,9 +240,9 @@ auto waybar::modules::Pulseaudio::update() -> void { if (monitor_.find("a2dp_sink") != std::string::npos || // PulseAudio monitor_.find("a2dp-sink") != std::string::npos) { // PipeWire format_name = format_name + "-bluetooth"; - label_.get_style_context()->add_class("bluetooth"); + label_->get_style_context()->add_class("bluetooth"); } else { - label_.get_style_context()->remove_class("bluetooth"); + label_->get_style_context()->remove_class("bluetooth"); } if (muted_) { // Check muted bluetooth format exist, otherwise fallback to default muted format @@ -250,29 +250,29 @@ auto waybar::modules::Pulseaudio::update() -> void { format_name = "format"; } format_name = format_name + "-muted"; - label_.get_style_context()->add_class("muted"); - label_.get_style_context()->add_class("sink-muted"); + label_->get_style_context()->add_class("muted"); + label_->get_style_context()->add_class("sink-muted"); } else { - label_.get_style_context()->remove_class("muted"); - label_.get_style_context()->remove_class("sink-muted"); + label_->get_style_context()->remove_class("muted"); + label_->get_style_context()->remove_class("sink-muted"); } format = config_[format_name].isString() ? config_[format_name].asString() : format; } // TODO: find a better way to split source/sink std::string format_source = "{volume}%"; if (source_muted_) { - label_.get_style_context()->add_class("source-muted"); + label_->get_style_context()->add_class("source-muted"); if (config_["format-source-muted"].isString()) { format_source = config_["format-source-muted"].asString(); } } else { - label_.get_style_context()->remove_class("source-muted"); + label_->get_style_context()->remove_class("source-muted"); if (config_["format-source-muted"].isString()) { format_source = config_["format-source"].asString(); } } format_source = fmt::format(format_source, fmt::arg("volume", source_volume_)); - label_.set_markup(fmt::format( + label_->set_markup(fmt::format( format, fmt::arg("desc", desc_), fmt::arg("volume", volume_), fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_), fmt::arg("source_desc", source_desc_), fmt::arg("icon", getIcon(volume_, getPulseIcon())))); @@ -283,16 +283,16 @@ auto waybar::modules::Pulseaudio::update() -> void { tooltip_format = config_["tooltip-format"].asString(); } if (!tooltip_format.empty()) { - label_.set_tooltip_text(fmt::format( + label_->set_tooltip_text(fmt::format( tooltip_format, fmt::arg("desc", desc_), fmt::arg("volume", volume_), fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_), fmt::arg("source_desc", source_desc_), fmt::arg("icon", getIcon(volume_, getPulseIcon())))); } else { - label_.set_tooltip_text(desc_); + label_->set_tooltip_text(desc_); } } // Call parent update - ALabel::update(); + AButton::update(); } diff --git a/src/modules/simpleclock.cpp b/src/modules/simpleclock.cpp index 27c7ac77..9cf5a2da 100644 --- a/src/modules/simpleclock.cpp +++ b/src/modules/simpleclock.cpp @@ -3,7 +3,7 @@ #include waybar::modules::Clock::Clock(const std::string& id, const Json::Value& config) - : ALabel(config, "clock", id, "{:%H:%M}", 60) { + : AButton(config, "clock", id, "{:%H:%M}", 60) { thread_ = [this] { dp.emit(); auto now = std::chrono::system_clock::now(); @@ -19,17 +19,17 @@ auto waybar::modules::Clock::update() -> void { 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); + label_->set_markup(text); if (tooltipEnabled()) { if (config_["tooltip-format"].isString()) { auto tooltip_format = config_["tooltip-format"].asString(); auto tooltip_text = fmt::format(tooltip_format, localtime); - label_.set_tooltip_text(tooltip_text); + label_->set_tooltip_text(tooltip_text); } else { - label_.set_tooltip_text(text); + label_->set_tooltip_text(text); } } // Call parent update - ALabel::update(); + AButton::update(); } diff --git a/src/modules/sndio.cpp b/src/modules/sndio.cpp index 63e9eac3..57b435e6 100644 --- a/src/modules/sndio.cpp +++ b/src/modules/sndio.cpp @@ -41,7 +41,7 @@ auto Sndio::connect_to_sndio() -> void { } Sndio::Sndio(const std::string &id, const Json::Value &config) - : ALabel(config, "sndio", id, "{volume}%", 1), + : AButton(config, "sndio", id, "{volume}%", 1, false, true), hdl_(nullptr), pfds_(0), addr_(0), @@ -105,14 +105,14 @@ auto Sndio::update() -> void { unsigned int vol = 100. * static_cast(volume_) / static_cast(maxval_); if (volume_ == 0) { - label_.get_style_context()->add_class("muted"); + label_->get_style_context()->add_class("muted"); } else { - label_.get_style_context()->remove_class("muted"); + label_->get_style_context()->remove_class("muted"); } - label_.set_markup(fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_))); + label_->set_markup(fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_))); - ALabel::update(); + AButton::update(); } auto Sndio::set_desc(struct sioctl_desc *d, unsigned int val) -> void { diff --git a/src/modules/sway/language.cpp b/src/modules/sway/language.cpp index d3730a11..eb414381 100644 --- a/src/modules/sway/language.cpp +++ b/src/modules/sway/language.cpp @@ -18,7 +18,7 @@ const std::string Language::XKB_LAYOUT_NAMES_KEY = "xkb_layout_names"; const std::string Language::XKB_ACTIVE_LAYOUT_NAME_KEY = "xkb_active_layout_name"; Language::Language(const std::string& id, const Json::Value& config) - : ALabel(config, "language", id, "{}", 0, true) { + : AButton(config, "language", id, "{}", 0, true) { is_variant_displayed = format_.find("{variant}") != std::string::npos; if (format_.find("{}") != std::string::npos || format_.find("{short}") != std::string::npos) { displayed_short_flag |= static_cast(DispayedShortFlag::ShortName); @@ -99,7 +99,7 @@ auto Language::update() -> void { format_, fmt::arg("short", layout_.short_name), fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name), fmt::arg("variant", layout_.variant), fmt::arg("flag", layout_.country_flag()))); - label_.set_markup(display_layout); + label_->set_markup(display_layout); if (tooltipEnabled()) { if (tooltip_format_ != "") { auto tooltip_display_layout = trim( @@ -107,22 +107,22 @@ auto Language::update() -> void { fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name), fmt::arg("variant", layout_.variant), fmt::arg("flag", layout_.country_flag()))); - label_.set_tooltip_markup(tooltip_display_layout); + label_->set_tooltip_markup(tooltip_display_layout); } else { - label_.set_tooltip_markup(display_layout); + label_->set_tooltip_markup(display_layout); } } event_box_.show(); // Call parent update - ALabel::update(); + AButton::update(); } auto Language::set_current_layout(std::string current_layout) -> void { - label_.get_style_context()->remove_class(layout_.short_name); + label_->get_style_context()->remove_class(layout_.short_name); layout_ = layouts_map_[current_layout]; - label_.get_style_context()->add_class(layout_.short_name); + label_->get_style_context()->add_class(layout_.short_name); } auto Language::init_layouts_map(const std::vector& used_layouts) -> void { diff --git a/src/modules/sway/mode.cpp b/src/modules/sway/mode.cpp index 7eaa523a..9f4c6b14 100644 --- a/src/modules/sway/mode.cpp +++ b/src/modules/sway/mode.cpp @@ -5,7 +5,7 @@ namespace waybar::modules::sway { Mode::Mode(const std::string& id, const Json::Value& config) - : ALabel(config, "mode", id, "{}", 0, true) { + : AButton(config, "mode", id, "{}", 0, true) { ipc_.subscribe(R"(["mode"])"); ipc_.signal_event.connect(sigc::mem_fun(*this, &Mode::onEvent)); // Launch worker @@ -42,14 +42,14 @@ auto Mode::update() -> void { if (mode_.empty()) { event_box_.hide(); } else { - label_.set_markup(fmt::format(format_, mode_)); + label_->set_markup(fmt::format(format_, mode_)); if (tooltipEnabled()) { - label_.set_tooltip_text(mode_); + label_->set_tooltip_text(mode_); } event_box_.show(); } // Call parent update - ALabel::update(); + AButton::update(); } } // namespace waybar::modules::sway diff --git a/src/modules/temperature.cpp b/src/modules/temperature.cpp index eea1198e..b6ee7fad 100644 --- a/src/modules/temperature.cpp +++ b/src/modules/temperature.cpp @@ -10,8 +10,7 @@ #endif waybar::modules::Temperature::Temperature(const std::string& id, const Json::Value& config) - : ALabel(config, "temperature", id, "{temperatureC}°C", 10) { - + : AButton(config, "temperature", id, "{temperatureC}°C", 10) { #if defined(__FreeBSD__) // try to read sysctl? #else @@ -46,9 +45,9 @@ auto waybar::modules::Temperature::update() -> void { auto format = format_; if (critical) { format = config_["format-critical"].isString() ? config_["format-critical"].asString() : format; - label_.get_style_context()->add_class("critical"); + label_->get_style_context()->add_class("critical"); } else { - label_.get_style_context()->remove_class("critical"); + label_->get_style_context()->remove_class("critical"); } if (format.empty()) { @@ -59,21 +58,21 @@ auto waybar::modules::Temperature::update() -> void { } auto max_temp = config_["critical-threshold"].isInt() ? config_["critical-threshold"].asInt() : 0; - label_.set_markup(fmt::format(format, fmt::arg("temperatureC", temperature_c), - fmt::arg("temperatureF", temperature_f), - fmt::arg("temperatureK", temperature_k), - fmt::arg("icon", getIcon(temperature_c, "", max_temp)))); + label_->set_markup(fmt::format(format, fmt::arg("temperatureC", temperature_c), + fmt::arg("temperatureF", temperature_f), + fmt::arg("temperatureK", temperature_k), + fmt::arg("icon", getIcon(temperature_c, "", max_temp)))); if (tooltipEnabled()) { std::string tooltip_format = "{temperatureC}°C"; if (config_["tooltip-format"].isString()) { tooltip_format = config_["tooltip-format"].asString(); } - label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("temperatureC", temperature_c), - fmt::arg("temperatureF", temperature_f), - fmt::arg("temperatureK", temperature_k))); + label_->set_tooltip_text(fmt::format(tooltip_format, fmt::arg("temperatureC", temperature_c), + fmt::arg("temperatureF", temperature_f), + fmt::arg("temperatureK", temperature_k))); } // Call parent update - ALabel::update(); + AButton::update(); } float waybar::modules::Temperature::getTemperature() { @@ -82,12 +81,13 @@ float waybar::modules::Temperature::getTemperature() { size_t size = sizeof temp; if (sysctlbyname("hw.acpi.thermal.tz0.temperature", &temp, &size, NULL, 0) != 0) { - throw std::runtime_error("sysctl hw.acpi.thermal.tz0.temperature or dev.cpu.0.temperature failed"); + throw std::runtime_error( + "sysctl hw.acpi.thermal.tz0.temperature or dev.cpu.0.temperature failed"); } - auto temperature_c = ((float)temp-2732)/10; + auto temperature_c = ((float)temp - 2732) / 10; return temperature_c; -#else // Linux +#else // Linux std::ifstream temp(file_path_); if (!temp.is_open()) { throw std::runtime_error("Can't open " + file_path_); From 0012bcbd74a4ae6857103ce52ee4c286762c7681 Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Sat, 29 May 2021 15:40:55 +0200 Subject: [PATCH 25/91] resources: Set button hover effects globally Since now modules as well as workspaces are buttons, the fix for the 'strange hover effects' has to be applied on a global level. In return there is a nice hover effect also on the modules. --- resources/style.css | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/resources/style.css b/resources/style.css index 563ee0dd..bfee80de 100644 --- a/resources/style.css +++ b/resources/style.css @@ -34,6 +34,12 @@ window#waybar.chromium { border: none; } +/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ +button:hover { + background: inherit; + box-shadow: inset 0 -3px #ffffff; +} + #workspaces button { padding: 0 5px; background-color: transparent; @@ -45,10 +51,8 @@ window#waybar.chromium { border-radius: 0; } -/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ #workspaces button:hover { background: rgba(0, 0, 0, 0.2); - box-shadow: inset 0 -3px #ffffff; } #workspaces button.focused { From 8fa5d9b838111519719ab742acece293bcde68a7 Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Sat, 29 May 2021 19:40:50 +0200 Subject: [PATCH 26/91] modules: Set style-context on button Fixes issue where the class parameters in style.css would have no effect. The CSS now references the GtkButton instead of the GtkLabel. Removing all style-classes from the custom module GtkButton however removes any properties set via style.css. Thus, the default classes 'flat' and 'text-button' are added on every update of these modules. --- src/AButton.cpp | 4 ++-- src/modules/battery.cpp | 4 ++-- src/modules/bluetooth.cpp | 8 ++++---- src/modules/custom.cpp | 8 +++++--- src/modules/idle_inhibitor.cpp | 6 +++--- src/modules/inhibitor.cpp | 4 ++-- src/modules/mpd/mpd.cpp | 26 +++++++++++++------------- src/modules/network.cpp | 8 ++++---- src/modules/pulseaudio.cpp | 16 ++++++++-------- src/modules/sndio.cpp | 4 ++-- src/modules/sway/language.cpp | 4 ++-- src/modules/temperature.cpp | 4 ++-- 12 files changed, 49 insertions(+), 47 deletions(-) diff --git a/src/AButton.cpp b/src/AButton.cpp index 3b9ad2d4..1ef1804b 100644 --- a/src/AButton.cpp +++ b/src/AButton.cpp @@ -142,10 +142,10 @@ std::string AButton::getState(uint8_t value, bool lesser) { std::string valid_state; for (auto const& state : states) { if ((lesser ? value <= state.second : value >= state.second) && valid_state.empty()) { - label_->get_style_context()->add_class(state.first); + button_.get_style_context()->add_class(state.first); valid_state = state.first; } else { - label_->get_style_context()->remove_class(state.first); + button_.get_style_context()->remove_class(state.first); } } return valid_state; diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 1a371726..6d849465 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -352,9 +352,9 @@ auto waybar::modules::Battery::update() -> void { fmt::arg("time", time_remaining_formatted))); } if (!old_status_.empty()) { - label_->get_style_context()->remove_class(old_status_); + button_.get_style_context()->remove_class(old_status_); } - label_->get_style_context()->add_class(status); + button_.get_style_context()->add_class(status); old_status_ = status; if (!state.empty() && config_["format-" + status + "-" + state].isString()) { format = config_["format-" + status + "-" + state].asString(); diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index 242774e1..d483ac35 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -189,10 +189,10 @@ auto waybar::modules::Bluetooth::update() -> void { format_.empty() ? event_box_.hide() : event_box_.show(); auto update_style_context = [this](const std::string& style_class, bool in_next_state) { - if (in_next_state && !label_->get_style_context()->has_class(style_class)) { - label_->get_style_context()->add_class(style_class); - } else if (!in_next_state && label_->get_style_context()->has_class(style_class)) { - label_->get_style_context()->remove_class(style_class); + if (in_next_state && !button_.get_style_context()->has_class(style_class)) { + button_.get_style_context()->add_class(style_class); + } else if (!in_next_state && button_.get_style_context()->has_class(style_class)) { + button_.get_style_context()->remove_class(style_class); } }; update_style_context("discoverable", cur_controller_.discoverable); diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index 17950ddd..930379bb 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -143,14 +143,16 @@ auto waybar::modules::Custom::update() -> void { } } } - auto classes = label_->get_style_context()->list_classes(); + auto classes = button_.get_style_context()->list_classes(); for (auto const& c : classes) { if (c == id_) continue; - label_->get_style_context()->remove_class(c); + button_.get_style_context()->remove_class(c); } for (auto const& c : class_) { - label_->get_style_context()->add_class(c); + button_.get_style_context()->add_class(c); } + button_.get_style_context()->add_class("flat"); + button_.get_style_context()->add_class("text-button"); event_box_.show(); } } diff --git a/src/modules/idle_inhibitor.cpp b/src/modules/idle_inhibitor.cpp index fd5611fe..dc373a92 100644 --- a/src/modules/idle_inhibitor.cpp +++ b/src/modules/idle_inhibitor.cpp @@ -44,13 +44,13 @@ waybar::modules::IdleInhibitor::~IdleInhibitor() { auto waybar::modules::IdleInhibitor::update() -> void { // Check status if (status) { - label_->get_style_context()->remove_class("deactivated"); + button_.get_style_context()->remove_class("deactivated"); if (idle_inhibitor_ == nullptr) { idle_inhibitor_ = zwp_idle_inhibit_manager_v1_create_inhibitor( waybar::Client::inst()->idle_inhibit_manager, bar_.surface); } } else { - label_->get_style_context()->remove_class("activated"); + button_.get_style_context()->remove_class("activated"); if (idle_inhibitor_ != nullptr) { zwp_idle_inhibitor_v1_destroy(idle_inhibitor_); idle_inhibitor_ = nullptr; @@ -60,7 +60,7 @@ auto waybar::modules::IdleInhibitor::update() -> void { std::string status_text = status ? "activated" : "deactivated"; label_->set_markup(fmt::format(format_, fmt::arg("status", status_text), fmt::arg("icon", getIcon(0, status_text)))); - label_->get_style_context()->add_class(status_text); + button_.get_style_context()->add_class(status_text); if (tooltipEnabled()) { label_->set_tooltip_markup( status ? fmt::format(config_["tooltip-format-activated"].isString() diff --git a/src/modules/inhibitor.cpp b/src/modules/inhibitor.cpp index 2ab013db..fc854566 100644 --- a/src/modules/inhibitor.cpp +++ b/src/modules/inhibitor.cpp @@ -117,10 +117,10 @@ auto Inhibitor::activated() -> bool { return handle_ != -1; } auto Inhibitor::update() -> void { std::string status_text = activated() ? "activated" : "deactivated"; - label_->get_style_context()->remove_class(activated() ? "deactivated" : "activated"); + button_.get_style_context()->remove_class(activated() ? "deactivated" : "activated"); label_->set_markup(fmt::format(format_, fmt::arg("status", status_text), fmt::arg("icon", getIcon(0, status_text)))); - label_->get_style_context()->add_class(status_text); + button_.get_style_context()->add_class(status_text); if (tooltipEnabled()) { label_->set_tooltip_text(status_text); diff --git a/src/modules/mpd/mpd.cpp b/src/modules/mpd/mpd.cpp index a79f203a..ec6ccb3a 100644 --- a/src/modules/mpd/mpd.cpp +++ b/src/modules/mpd/mpd.cpp @@ -85,10 +85,10 @@ std::string waybar::modules::MPD::getFilename() const { void waybar::modules::MPD::setLabel() { if (connection_ == nullptr) { - label_->get_style_context()->add_class("disconnected"); - label_->get_style_context()->remove_class("stopped"); - label_->get_style_context()->remove_class("playing"); - label_->get_style_context()->remove_class("paused"); + button_.get_style_context()->add_class("disconnected"); + button_.get_style_context()->remove_class("stopped"); + button_.get_style_context()->remove_class("playing"); + button_.get_style_context()->remove_class("paused"); auto format = config_["format-disconnected"].isString() ? config_["format-disconnected"].asString() @@ -105,7 +105,7 @@ void waybar::modules::MPD::setLabel() { } return; } else { - label_->get_style_context()->remove_class("disconnected"); + button_.get_style_context()->remove_class("disconnected"); } auto format = format_; @@ -118,19 +118,19 @@ void waybar::modules::MPD::setLabel() { if (stopped()) { format = config_["format-stopped"].isString() ? config_["format-stopped"].asString() : "stopped"; - label_->get_style_context()->add_class("stopped"); - label_->get_style_context()->remove_class("playing"); - label_->get_style_context()->remove_class("paused"); + button_.get_style_context()->add_class("stopped"); + button_.get_style_context()->remove_class("playing"); + button_.get_style_context()->remove_class("paused"); } else { - label_->get_style_context()->remove_class("stopped"); + button_.get_style_context()->remove_class("stopped"); if (playing()) { - label_->get_style_context()->add_class("playing"); - label_->get_style_context()->remove_class("paused"); + button_.get_style_context()->add_class("playing"); + button_.get_style_context()->remove_class("paused"); } else if (paused()) { format = config_["format-paused"].isString() ? config_["format-paused"].asString() : config_["format"].asString(); - label_->get_style_context()->add_class("paused"); - label_->get_style_context()->remove_class("playing"); + button_.get_style_context()->add_class("paused"); + button_.get_style_context()->remove_class("playing"); } stateIcon = getStateIcon(); diff --git a/src/modules/network.cpp b/src/modules/network.cpp index c5200266..e2467f22 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -309,8 +309,8 @@ auto waybar::modules::Network::update() -> void { if (!alt_) { auto state = getNetworkState(); - if (!state_.empty() && label_->get_style_context()->has_class(state_)) { - label_->get_style_context()->remove_class(state_); + if (!state_.empty() && button_.get_style_context()->has_class(state_)) { + button_.get_style_context()->remove_class(state_); } if (config_["format-" + state].isString()) { default_format_ = config_["format-" + state].asString(); @@ -322,8 +322,8 @@ auto waybar::modules::Network::update() -> void { 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); + if (!button_.get_style_context()->has_class(state)) { + button_.get_style_context()->add_class(state); } format_ = default_format_; state_ = state; diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 11aaced7..f0b7b7d0 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -240,9 +240,9 @@ auto waybar::modules::Pulseaudio::update() -> void { if (monitor_.find("a2dp_sink") != std::string::npos || // PulseAudio monitor_.find("a2dp-sink") != std::string::npos) { // PipeWire format_name = format_name + "-bluetooth"; - label_->get_style_context()->add_class("bluetooth"); + button_.get_style_context()->add_class("bluetooth"); } else { - label_->get_style_context()->remove_class("bluetooth"); + button_.get_style_context()->remove_class("bluetooth"); } if (muted_) { // Check muted bluetooth format exist, otherwise fallback to default muted format @@ -250,23 +250,23 @@ auto waybar::modules::Pulseaudio::update() -> void { format_name = "format"; } format_name = format_name + "-muted"; - label_->get_style_context()->add_class("muted"); - label_->get_style_context()->add_class("sink-muted"); + button_.get_style_context()->add_class("muted"); + button_.get_style_context()->add_class("sink-muted"); } else { - label_->get_style_context()->remove_class("muted"); - label_->get_style_context()->remove_class("sink-muted"); + button_.get_style_context()->remove_class("muted"); + button_.get_style_context()->remove_class("sink-muted"); } format = config_[format_name].isString() ? config_[format_name].asString() : format; } // TODO: find a better way to split source/sink std::string format_source = "{volume}%"; if (source_muted_) { - label_->get_style_context()->add_class("source-muted"); + button_.get_style_context()->add_class("source-muted"); if (config_["format-source-muted"].isString()) { format_source = config_["format-source-muted"].asString(); } } else { - label_->get_style_context()->remove_class("source-muted"); + button_.get_style_context()->remove_class("source-muted"); if (config_["format-source-muted"].isString()) { format_source = config_["format-source"].asString(); } diff --git a/src/modules/sndio.cpp b/src/modules/sndio.cpp index 57b435e6..dfab0d2a 100644 --- a/src/modules/sndio.cpp +++ b/src/modules/sndio.cpp @@ -105,9 +105,9 @@ auto Sndio::update() -> void { unsigned int vol = 100. * static_cast(volume_) / static_cast(maxval_); if (volume_ == 0) { - label_->get_style_context()->add_class("muted"); + button_.get_style_context()->add_class("muted"); } else { - label_->get_style_context()->remove_class("muted"); + button_.get_style_context()->remove_class("muted"); } label_->set_markup(fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_))); diff --git a/src/modules/sway/language.cpp b/src/modules/sway/language.cpp index eb414381..f9d81a2a 100644 --- a/src/modules/sway/language.cpp +++ b/src/modules/sway/language.cpp @@ -120,9 +120,9 @@ auto Language::update() -> void { } auto Language::set_current_layout(std::string current_layout) -> void { - label_->get_style_context()->remove_class(layout_.short_name); + button_.get_style_context()->remove_class(layout_.short_name); layout_ = layouts_map_[current_layout]; - label_->get_style_context()->add_class(layout_.short_name); + button_.get_style_context()->add_class(layout_.short_name); } auto Language::init_layouts_map(const std::vector& used_layouts) -> void { diff --git a/src/modules/temperature.cpp b/src/modules/temperature.cpp index b6ee7fad..c8e0bf08 100644 --- a/src/modules/temperature.cpp +++ b/src/modules/temperature.cpp @@ -45,9 +45,9 @@ auto waybar::modules::Temperature::update() -> void { auto format = format_; if (critical) { format = config_["format-critical"].isString() ? config_["format-critical"].asString() : format; - label_->get_style_context()->add_class("critical"); + button_.get_style_context()->add_class("critical"); } else { - label_->get_style_context()->remove_class("critical"); + button_.get_style_context()->remove_class("critical"); } if (format.empty()) { From 2b735f44bc80ab0f8a16406da1d58dc1be59218d Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Wed, 23 Jun 2021 10:43:28 +0200 Subject: [PATCH 27/91] modules: Set tooltip on button Mouse-over tooltips set on the label only appear once the mouse hovers over exactly the label. Other apps (e.g. firefox) show the tooltip once the pointer hovers the button. Not solely its label. With this commit we get the same behaviour. --- src/modules/battery.cpp | 2 +- src/modules/bluetooth.cpp | 2 +- src/modules/clock.cpp | 2 +- src/modules/cpu/common.cpp | 2 +- src/modules/custom.cpp | 8 ++++---- src/modules/disk.cpp | 2 +- src/modules/idle_inhibitor.cpp | 2 +- src/modules/inhibitor.cpp | 2 +- src/modules/memory/common.cpp | 4 ++-- src/modules/mpd/mpd.cpp | 4 ++-- src/modules/network.cpp | 8 ++++---- src/modules/pulseaudio.cpp | 4 ++-- src/modules/simpleclock.cpp | 4 ++-- src/modules/sway/language.cpp | 4 ++-- src/modules/sway/mode.cpp | 2 +- src/modules/temperature.cpp | 2 +- 16 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 6d849465..be30e14c 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -347,7 +347,7 @@ auto waybar::modules::Battery::update() -> void { } else if (config_["tooltip-format"].isString()) { tooltip_format = config_["tooltip-format"].asString(); } - label_->set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default), + button_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default), fmt::arg("capacity", capacity), fmt::arg("time", time_remaining_formatted))); } diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index d483ac35..6ceab785 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -245,7 +245,7 @@ auto waybar::modules::Bluetooth::update() -> void { device_enumerate_.erase(0, 1); } } - label_->set_tooltip_text(fmt::format( + button_.set_tooltip_text(fmt::format( tooltip_format, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()), fmt::arg("controller_address", cur_controller_.address), diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 07625d5d..80c02a45 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -119,7 +119,7 @@ auto waybar::modules::Clock::update() -> void { text = fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines), fmt::arg(KTimezonedTimeListPlaceholder.c_str(), timezoned_time_lines)); - label_->set_tooltip_markup(text); + button_.set_tooltip_markup(text); } } diff --git a/src/modules/cpu/common.cpp b/src/modules/cpu/common.cpp index 888d3117..8201ed09 100644 --- a/src/modules/cpu/common.cpp +++ b/src/modules/cpu/common.cpp @@ -23,7 +23,7 @@ auto waybar::modules::Cpu::update() -> void { auto [cpu_usage, tooltip] = getCpuUsage(); auto [max_frequency, min_frequency, avg_frequency] = getCpuFrequency(); if (tooltipEnabled()) { - label_->set_tooltip_text(tooltip); + button_.set_tooltip_text(tooltip); } auto format = format_; auto total_usage = cpu_usage.empty() ? 0 : cpu_usage[0]; diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index 930379bb..397298b2 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -134,12 +134,12 @@ auto waybar::modules::Custom::update() -> void { label_->set_markup(str); if (tooltipEnabled()) { if (text_ == tooltip_) { - if (label_->get_tooltip_markup() != str) { - label_->set_tooltip_markup(str); + if (button_.get_tooltip_markup() != str) { + button_.set_tooltip_markup(str); } } else { - if (label_->get_tooltip_markup() != tooltip_) { - label_->set_tooltip_markup(tooltip_); + if (button_.get_tooltip_markup() != tooltip_) { + button_.set_tooltip_markup(tooltip_); } } } diff --git a/src/modules/disk.cpp b/src/modules/disk.cpp index 1767cfd3..626378ca 100644 --- a/src/modules/disk.cpp +++ b/src/modules/disk.cpp @@ -70,7 +70,7 @@ auto waybar::modules::Disk::update() -> void { if (config_["tooltip-format"].isString()) { tooltip_format = config_["tooltip-format"].asString(); } - label_->set_tooltip_text( + button_.set_tooltip_text( fmt::format(tooltip_format, stats.f_bavail * 100 / stats.f_blocks, fmt::arg("free", free), fmt::arg("percentage_free", stats.f_bavail * 100 / stats.f_blocks), fmt::arg("used", used), fmt::arg("percentage_used", percentage_used), diff --git a/src/modules/idle_inhibitor.cpp b/src/modules/idle_inhibitor.cpp index dc373a92..c75c53c0 100644 --- a/src/modules/idle_inhibitor.cpp +++ b/src/modules/idle_inhibitor.cpp @@ -62,7 +62,7 @@ auto waybar::modules::IdleInhibitor::update() -> void { fmt::arg("icon", getIcon(0, status_text)))); button_.get_style_context()->add_class(status_text); if (tooltipEnabled()) { - label_->set_tooltip_markup( + button_.set_tooltip_markup( status ? fmt::format(config_["tooltip-format-activated"].isString() ? config_["tooltip-format-activated"].asString() : "{status}", diff --git a/src/modules/inhibitor.cpp b/src/modules/inhibitor.cpp index fc854566..73af5037 100644 --- a/src/modules/inhibitor.cpp +++ b/src/modules/inhibitor.cpp @@ -123,7 +123,7 @@ auto Inhibitor::update() -> void { button_.get_style_context()->add_class(status_text); if (tooltipEnabled()) { - label_->set_tooltip_text(status_text); + button_.set_tooltip_text(status_text); } return AButton::update(); diff --git a/src/modules/memory/common.cpp b/src/modules/memory/common.cpp index b9244451..596659be 100644 --- a/src/modules/memory/common.cpp +++ b/src/modules/memory/common.cpp @@ -66,7 +66,7 @@ auto waybar::modules::Memory::update() -> void { if (tooltipEnabled()) { if (config_["tooltip-format"].isString()) { auto tooltip_format = config_["tooltip-format"].asString(); - label_->set_tooltip_text(fmt::format( + button_.set_tooltip_text(fmt::format( tooltip_format, used_ram_percentage, fmt::arg("total", total_ram_gigabytes), fmt::arg("swapTotal", total_swap_gigabytes), fmt::arg("percentage", used_ram_percentage), @@ -74,7 +74,7 @@ auto waybar::modules::Memory::update() -> void { fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes), fmt::arg("swapAvail", available_swap_gigabytes))); } else { - label_->set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1)); + button_.set_tooltip_text(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1)); } } } else { diff --git a/src/modules/mpd/mpd.cpp b/src/modules/mpd/mpd.cpp index ec6ccb3a..d223c661 100644 --- a/src/modules/mpd/mpd.cpp +++ b/src/modules/mpd/mpd.cpp @@ -101,7 +101,7 @@ void waybar::modules::MPD::setLabel() { ? config_["tooltip-format-disconnected"].asString() : "MPD (disconnected)"; // Nothing to format - label_->set_tooltip_text(tooltip_format); + button_.set_tooltip_text(tooltip_format); } return; } else { @@ -195,7 +195,7 @@ void waybar::modules::MPD::setLabel() { fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon), fmt::arg("consumeIcon", consumeIcon), fmt::arg("randomIcon", randomIcon), fmt::arg("repeatIcon", repeatIcon), fmt::arg("singleIcon", singleIcon)); - label_->set_tooltip_text(tooltip_text); + button_.set_tooltip_text(tooltip_text); } catch (fmt::format_error const& e) { spdlog::warn("mpd: format error (tooltip): {}", e.what()); } diff --git a/src/modules/network.cpp b/src/modules/network.cpp index e2467f22..953d4078 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -382,11 +382,11 @@ auto waybar::modules::Network::update() -> void { fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / interval_.count(), "B/s")), fmt::arg("bandwidthTotalBytes", pow_format((bandwidth_up + bandwidth_down) / interval_.count(), "B/s"))); - if (label_->get_tooltip_text() != tooltip_text) { - label_->set_tooltip_markup(tooltip_text); + if (button_.get_tooltip_text() != tooltip_text) { + button_.set_tooltip_markup(tooltip_text); } - } else if (label_->get_tooltip_text() != text) { - label_->set_tooltip_markup(text); + } else if (button_.get_tooltip_text() != text) { + button_.set_tooltip_markup(text); } } diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index f0b7b7d0..f71d37d1 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -283,13 +283,13 @@ auto waybar::modules::Pulseaudio::update() -> void { tooltip_format = config_["tooltip-format"].asString(); } if (!tooltip_format.empty()) { - label_->set_tooltip_text(fmt::format( + button_.set_tooltip_text(fmt::format( tooltip_format, fmt::arg("desc", desc_), fmt::arg("volume", volume_), fmt::arg("format_source", format_source), fmt::arg("source_volume", source_volume_), fmt::arg("source_desc", source_desc_), fmt::arg("icon", getIcon(volume_, getPulseIcon())))); } else { - label_->set_tooltip_text(desc_); + button_.set_tooltip_text(desc_); } } diff --git a/src/modules/simpleclock.cpp b/src/modules/simpleclock.cpp index 9cf5a2da..f6fc17fb 100644 --- a/src/modules/simpleclock.cpp +++ b/src/modules/simpleclock.cpp @@ -25,9 +25,9 @@ auto waybar::modules::Clock::update() -> void { if (config_["tooltip-format"].isString()) { auto tooltip_format = config_["tooltip-format"].asString(); auto tooltip_text = fmt::format(tooltip_format, localtime); - label_->set_tooltip_text(tooltip_text); + button_.set_tooltip_text(tooltip_text); } else { - label_->set_tooltip_text(text); + button_.set_tooltip_text(text); } } // Call parent update diff --git a/src/modules/sway/language.cpp b/src/modules/sway/language.cpp index f9d81a2a..8a6af618 100644 --- a/src/modules/sway/language.cpp +++ b/src/modules/sway/language.cpp @@ -107,9 +107,9 @@ auto Language::update() -> void { fmt::arg("shortDescription", layout_.short_description), fmt::arg("long", layout_.full_name), fmt::arg("variant", layout_.variant), fmt::arg("flag", layout_.country_flag()))); - label_->set_tooltip_markup(tooltip_display_layout); + button_.set_tooltip_markup(tooltip_display_layout); } else { - label_->set_tooltip_markup(display_layout); + button_.set_tooltip_markup(display_layout); } } diff --git a/src/modules/sway/mode.cpp b/src/modules/sway/mode.cpp index 9f4c6b14..b6c9fc2b 100644 --- a/src/modules/sway/mode.cpp +++ b/src/modules/sway/mode.cpp @@ -44,7 +44,7 @@ auto Mode::update() -> void { } else { label_->set_markup(fmt::format(format_, mode_)); if (tooltipEnabled()) { - label_->set_tooltip_text(mode_); + button_.set_tooltip_text(mode_); } event_box_.show(); } diff --git a/src/modules/temperature.cpp b/src/modules/temperature.cpp index c8e0bf08..e8881097 100644 --- a/src/modules/temperature.cpp +++ b/src/modules/temperature.cpp @@ -67,7 +67,7 @@ auto waybar::modules::Temperature::update() -> void { if (config_["tooltip-format"].isString()) { tooltip_format = config_["tooltip-format"].asString(); } - label_->set_tooltip_text(fmt::format(tooltip_format, fmt::arg("temperatureC", temperature_c), + button_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("temperatureC", temperature_c), fmt::arg("temperatureF", temperature_f), fmt::arg("temperatureK", temperature_k))); } From 015409acaf25aa70bc1c76ad73b8e997740e5b53 Mon Sep 17 00:00:00 2001 From: herlev <> Date: Thu, 13 Oct 2022 23:41:56 +0200 Subject: [PATCH 28/91] Allow hyprland/window to show active window on a per monitor basis --- include/modules/hyprland/window.hpp | 3 +++ src/modules/hyprland/window.cpp | 36 ++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/include/modules/hyprland/window.hpp b/include/modules/hyprland/window.hpp index e8446551..3eb90774 100644 --- a/include/modules/hyprland/window.hpp +++ b/include/modules/hyprland/window.hpp @@ -17,8 +17,11 @@ public: auto update() -> void; private: + uint getActiveWorkspaceID(std::string); + std::string getLastWindowTitle(uint); void onEvent(const std::string&); + bool separate_outputs; std::mutex mutex_; const Bar& bar_; util::JsonParser parser_; diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index c2923335..461cb6c3 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -1,14 +1,18 @@ #include "modules/hyprland/window.hpp" #include +#include #include "modules/hyprland/backend.hpp" +#include "util/command.hpp" +#include "util/json.hpp" namespace waybar::modules::hyprland { Window::Window(const std::string& id, const Bar& bar, const Json::Value& config) : ALabel(config, "window", id, "{}", 0, true), bar_(bar) { modulesReady = true; + separate_outputs = config["separate-outputs"].as(); if (!gIPC.get()) { gIPC = std::make_unique(); @@ -35,9 +39,39 @@ auto Window::update() -> void { ALabel::update(); } +uint Window::getActiveWorkspaceID(std::string monitorName) { + auto cmd = waybar::util::command::exec("hyprctl monitors -j"); + assert(cmd.exit_code == 0); + Json::Value json = parser_.parse(cmd.out); + assert(json.isArray()); + auto monitor = std::find_if(json.begin(), json.end(), [&](Json::Value monitor){ + return monitor["name"] == monitorName; + }); + assert(monitor != std::end(json)); + return (*monitor)["activeWorkspace"]["id"].as(); +} + +std::string Window::getLastWindowTitle(uint workspaceID) { + auto cmd = waybar::util::command::exec("hyprctl workspaces -j"); + assert(cmd.exit_code == 0); + Json::Value json = parser_.parse(cmd.out); + assert(json.isArray()); + auto workspace = std::find_if(json.begin(), json.end(), [&](Json::Value workspace){ + return workspace["id"].as() == workspaceID; + }); + assert(workspace != std::end(json)); + return (*workspace)["lastwindowtitle"].as(); +} + void Window::onEvent(const std::string& ev) { std::lock_guard lg(mutex_); - auto windowName = ev.substr(ev.find_first_of(',') + 1).substr(0, 256); + + std::string windowName; + if (separate_outputs) { + windowName = getLastWindowTitle(getActiveWorkspaceID(this->bar_.output->name)); + } else { + windowName = ev.substr(ev.find_first_of(',') + 1).substr(0, 256); + } auto replaceAll = [](std::string str, const std::string& from, const std::string& to) -> std::string { From cf9d98a0be6b4eb4dc1f14071e99c0afc1dcef9e Mon Sep 17 00:00:00 2001 From: herlev <> Date: Thu, 13 Oct 2022 23:49:41 +0200 Subject: [PATCH 29/91] remove dependency --- src/modules/hyprland/window.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index 461cb6c3..7446ce85 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -1,7 +1,6 @@ #include "modules/hyprland/window.hpp" #include -#include #include "modules/hyprland/backend.hpp" #include "util/command.hpp" From cca5227210e70ef389fa103c7c28077ce5dad34c Mon Sep 17 00:00:00 2001 From: Ian Manske Date: Thu, 13 Oct 2022 21:47:57 -0400 Subject: [PATCH 30/91] Add config value for inhibitor default state. --- include/modules/idle_inhibitor.hpp | 1 + man/waybar-idle-inhibitor.5.scd | 5 +++ src/modules/idle_inhibitor.cpp | 63 ++++++++++++++++++------------ 3 files changed, 43 insertions(+), 26 deletions(-) diff --git a/include/modules/idle_inhibitor.hpp b/include/modules/idle_inhibitor.hpp index ac0bcf02..8378e58d 100644 --- a/include/modules/idle_inhibitor.hpp +++ b/include/modules/idle_inhibitor.hpp @@ -20,6 +20,7 @@ class IdleInhibitor : public ALabel { private: bool handleToggle(GdkEventButton* const& e); + void toggleStatus(); const Bar& bar_; struct zwp_idle_inhibitor_v1* idle_inhibitor_; diff --git a/man/waybar-idle-inhibitor.5.scd b/man/waybar-idle-inhibitor.5.scd index b341a494..f85456d8 100644 --- a/man/waybar-idle-inhibitor.5.scd +++ b/man/waybar-idle-inhibitor.5.scd @@ -63,6 +63,11 @@ screensaving, also known as "presentation mode". typeof: double ++ Threshold to be used when scrolling. +*start-activated*: ++ + typeof: bool ++ + default: *false* ++ + Whether the inhibit should be activated when starting waybar. + *timeout*: ++ typeof: double ++ The number of minutes the inhibit should last. diff --git a/src/modules/idle_inhibitor.cpp b/src/modules/idle_inhibitor.cpp index 3302abb6..1133ebda 100644 --- a/src/modules/idle_inhibitor.cpp +++ b/src/modules/idle_inhibitor.cpp @@ -16,6 +16,13 @@ waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& throw std::runtime_error("idle-inhibit not available"); } + if (waybar::modules::IdleInhibitor::modules.empty() + && config_["start-activated"].isBool() + && config_["start-activated"].asBool() != status + ) { + toggleStatus(); + } + event_box_.add_events(Gdk::BUTTON_PRESS_MASK); event_box_.signal_button_press_event().connect( sigc::mem_fun(*this, &IdleInhibitor::handleToggle)); @@ -78,34 +85,38 @@ auto waybar::modules::IdleInhibitor::update() -> void { ALabel::update(); } +void waybar::modules::IdleInhibitor::toggleStatus() { + status = !status; + + if (timeout_.connected()) { + /* cancel any already active timeout handler */ + timeout_.disconnect(); + } + + if (status && config_["timeout"].isNumeric()) { + auto timeoutMins = config_["timeout"].asDouble(); + int timeoutSecs = timeoutMins * 60; + + timeout_ = Glib::signal_timeout().connect_seconds( + []() { + /* intentionally not tied to a module instance lifetime + * as the output with `this` can be disconnected + */ + spdlog::info("deactivating idle_inhibitor by timeout"); + status = false; + for (auto const& module : waybar::modules::IdleInhibitor::modules) { + module->update(); + } + /* disconnect */ + return false; + }, + timeoutSecs); + } +} + bool waybar::modules::IdleInhibitor::handleToggle(GdkEventButton* const& e) { if (e->button == 1) { - status = !status; - - if (timeout_.connected()) { - /* cancel any already active timeout handler */ - timeout_.disconnect(); - } - - if (status && config_["timeout"].isNumeric()) { - auto timeoutMins = config_["timeout"].asDouble(); - int timeoutSecs = timeoutMins * 60; - - timeout_ = Glib::signal_timeout().connect_seconds( - []() { - /* intentionally not tied to a module instance lifetime - * as the output with `this` can be disconnected - */ - spdlog::info("deactivating idle_inhibitor by timeout"); - status = false; - for (auto const& module : waybar::modules::IdleInhibitor::modules) { - module->update(); - } - /* disconnect */ - return false; - }, - timeoutSecs); - } + toggleStatus(); // Make all other idle inhibitor modules update for (auto const& module : waybar::modules::IdleInhibitor::modules) { From 9a0013cb10ce449e429e6d0986abd0b154db21ac Mon Sep 17 00:00:00 2001 From: herlev <> Date: Sat, 15 Oct 2022 01:44:58 +0200 Subject: [PATCH 31/91] Add option to wlr/workspaces to sort workspaces by number --- include/modules/wlr/workspace_manager.hpp | 1 + src/modules/wlr/workspace_manager.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/include/modules/wlr/workspace_manager.hpp b/include/modules/wlr/workspace_manager.hpp index e65594af..963d610f 100644 --- a/include/modules/wlr/workspace_manager.hpp +++ b/include/modules/wlr/workspace_manager.hpp @@ -152,6 +152,7 @@ class WorkspaceManager : public AModule { bool sort_by_name_ = true; bool sort_by_coordinates_ = true; + bool sort_by_number_ = false; bool all_outputs_ = false; bool active_only_ = false; bool creation_delayed_ = false; diff --git a/src/modules/wlr/workspace_manager.cpp b/src/modules/wlr/workspace_manager.cpp index cc3c8151..da83cb79 100644 --- a/src/modules/wlr/workspace_manager.cpp +++ b/src/modules/wlr/workspace_manager.cpp @@ -32,6 +32,11 @@ WorkspaceManager::WorkspaceManager(const std::string &id, const waybar::Bar &bar sort_by_coordinates_ = config_sort_by_coordinates.asBool(); } + auto config_sort_by_number = config_["sort-by-number"]; + if (config_sort_by_number.isBool()) { + sort_by_number_ = config_sort_by_number.asBool(); + } + auto config_all_outputs = config_["all-outputs"]; if (config_all_outputs.isBool()) { all_outputs_ = config_all_outputs.asBool(); @@ -61,6 +66,12 @@ auto WorkspaceManager::workspace_comparator() const auto is_name_less = lhs->get_name() < rhs->get_name(); auto is_name_eq = lhs->get_name() == rhs->get_name(); auto is_coords_less = lhs->get_coords() < rhs->get_coords(); + auto is_number_less = std::stoi(lhs->get_name()) < std::stoi(rhs->get_name()); + + if (sort_by_number_) { + return is_number_less; + } + if (sort_by_name_) { if (sort_by_coordinates_) { return is_name_eq ? is_coords_less : is_name_less; From 35254ee834ad29a08572887e7b745f5b4c22f2f1 Mon Sep 17 00:00:00 2001 From: lilydjwg Date: Sun, 16 Oct 2022 15:24:17 +0800 Subject: [PATCH 32/91] pulseaudio: disconnect on destruction --- src/modules/pulseaudio.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 24b858d3..9dc5db48 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -36,6 +36,7 @@ waybar::modules::Pulseaudio::Pulseaudio(const std::string &id, const Json::Value } waybar::modules::Pulseaudio::~Pulseaudio() { + pa_context_disconnect(context_); mainloop_api_->quit(mainloop_api_, 0); pa_threaded_mainloop_stop(mainloop_); pa_threaded_mainloop_free(mainloop_); From 1db3c55b488fbc4f2936fd6e4656b70aa53c42f5 Mon Sep 17 00:00:00 2001 From: llyyr Date: Sun, 16 Oct 2022 19:21:43 +0530 Subject: [PATCH 33/91] Fix build with catch2>=3.0.0 --- test/SafeSignal.cpp | 2 +- test/config.cpp | 2 +- test/main.cpp | 19 ++++++++++--------- test/waybar_time.cpp | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/test/SafeSignal.cpp b/test/SafeSignal.cpp index 6a1e17a5..7ff6f2ae 100644 --- a/test/SafeSignal.cpp +++ b/test/SafeSignal.cpp @@ -2,7 +2,7 @@ #include -#include +#include #include #include diff --git a/test/config.cpp b/test/config.cpp index 29b0502a..cdc96b0c 100644 --- a/test/config.cpp +++ b/test/config.cpp @@ -1,6 +1,6 @@ #include "config.hpp" -#include +#include TEST_CASE("Load simple config", "[config]") { waybar::Config conf; diff --git a/test/main.cpp b/test/main.cpp index 5eb060d9..7970c262 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -3,8 +3,8 @@ #include #include -#include -#include +#include +#include #include int main(int argc, char* argv[]) { @@ -13,13 +13,14 @@ int main(int argc, char* argv[]) { session.applyCommandLine(argc, argv); const auto logger = spdlog::default_logger(); - const auto& reporter_name = session.config().getReporterName(); - if (reporter_name == "tap") { - spdlog::set_pattern("# [%l] %v"); - } else if (reporter_name == "compact") { - logger->sinks().clear(); - } else { - logger->sinks().assign({std::make_shared()}); + for (const auto& spec : session.config().getReporterSpecs()) { + if (spec.name() == "tap") { + spdlog::set_pattern("# [%l] %v"); + } else if (spec.name() == "compact") { + logger->sinks().clear(); + } else { + logger->sinks().assign({std::make_shared()}); + } } return session.run(); diff --git a/test/waybar_time.cpp b/test/waybar_time.cpp index 5fc3312d..79469d41 100644 --- a/test/waybar_time.cpp +++ b/test/waybar_time.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include From f86dff60e6082b0dfedd8814de0a862bd0184b97 Mon Sep 17 00:00:00 2001 From: Mika Braunschweig Date: Sun, 9 Oct 2022 19:13:54 +0200 Subject: [PATCH 34/91] utils: add sanitize_str to encode '&' etc. gtk requires some chars (<>&"') to be encoded for them to render properly. `sanitize_str` sanitizes raw strings that have such chars and returns a properly encoded string --- include/util/sanitize_str.hpp | 6 ++++++ meson.build | 3 ++- src/modules/hyprland/language.cpp | 14 +++----------- src/modules/hyprland/window.cpp | 14 +++----------- src/modules/mpd/mpd.cpp | 15 +++++++++------ src/util/sanitize_str.cpp | 24 ++++++++++++++++++++++++ 6 files changed, 47 insertions(+), 29 deletions(-) create mode 100644 include/util/sanitize_str.hpp create mode 100644 src/util/sanitize_str.cpp diff --git a/include/util/sanitize_str.hpp b/include/util/sanitize_str.hpp new file mode 100644 index 00000000..bb45c353 --- /dev/null +++ b/include/util/sanitize_str.hpp @@ -0,0 +1,6 @@ +#pragma once +#include + +namespace waybar::util { +std::string sanitize_string(std::string str); +} // namespace waybar::util diff --git a/meson.build b/meson.build index 420606aa..ccea0502 100644 --- a/meson.build +++ b/meson.build @@ -154,7 +154,8 @@ src_files = files( 'src/client.cpp', 'src/config.cpp', 'src/group.cpp', - 'src/util/ustring_clen.cpp' + 'src/util/ustring_clen.cpp', + 'src/util/sanitize_str.cpp' ) if is_linux diff --git a/src/modules/hyprland/language.cpp b/src/modules/hyprland/language.cpp index 5463508b..e82bd7e9 100644 --- a/src/modules/hyprland/language.cpp +++ b/src/modules/hyprland/language.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include "modules/hyprland/backend.hpp" namespace waybar::modules::hyprland { @@ -48,16 +50,6 @@ void Language::onEvent(const std::string& ev) { if (config_.isMember("keyboard-name") && keebName != config_["keyboard-name"].asString()) return; // ignore - auto replaceAll = [](std::string str, const std::string& from, - const std::string& to) -> std::string { - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != std::string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); - } - return str; - }; - const auto BRIEFNAME = getShortFrom(layoutName); if (config_.isMember("format-" + BRIEFNAME)) { @@ -67,7 +59,7 @@ void Language::onEvent(const std::string& ev) { layoutName = fmt::format(format_, layoutName); } - layoutName = replaceAll(layoutName, "&", "&"); + layoutName = waybar::util::sanitize_string(layoutName); if (layoutName == layoutName_) return; diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index c2923335..c20b31d3 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -2,6 +2,8 @@ #include +#include + #include "modules/hyprland/backend.hpp" namespace waybar::modules::hyprland { @@ -39,17 +41,7 @@ void Window::onEvent(const std::string& ev) { std::lock_guard lg(mutex_); auto windowName = ev.substr(ev.find_first_of(',') + 1).substr(0, 256); - auto replaceAll = [](std::string str, const std::string& from, - const std::string& to) -> std::string { - size_t start_pos = 0; - while ((start_pos = str.find(from, start_pos)) != std::string::npos) { - str.replace(start_pos, from.length(), to); - start_pos += to.length(); - } - return str; - }; - - windowName = replaceAll(windowName, "&", "&"); + windowName = waybar::util::sanitize_string(windowName); if (windowName == lastView) return; diff --git a/src/modules/mpd/mpd.cpp b/src/modules/mpd/mpd.cpp index 0f58343d..053b9edb 100644 --- a/src/modules/mpd/mpd.cpp +++ b/src/modules/mpd/mpd.cpp @@ -4,6 +4,9 @@ #include #include +#include +using namespace waybar::util; + #include "modules/mpd/state.hpp" #if defined(MPD_NOINLINE) namespace waybar::modules { @@ -135,12 +138,12 @@ void waybar::modules::MPD::setLabel() { stateIcon = getStateIcon(); - artist = getTag(MPD_TAG_ARTIST); - album_artist = getTag(MPD_TAG_ALBUM_ARTIST); - album = getTag(MPD_TAG_ALBUM); - title = getTag(MPD_TAG_TITLE); - date = getTag(MPD_TAG_DATE); - filename = getFilename(); + artist = sanitize_string(getTag(MPD_TAG_ARTIST)); + album_artist = sanitize_string(getTag(MPD_TAG_ALBUM_ARTIST)); + album = sanitize_string(getTag(MPD_TAG_ALBUM)); + title = sanitize_string(getTag(MPD_TAG_TITLE)); + date = sanitize_string(getTag(MPD_TAG_DATE)); + filename = sanitize_string(getFilename()); song_pos = mpd_status_get_song_pos(status_.get()) + 1; volume = mpd_status_get_volume(status_.get()); if (volume < 0) { diff --git a/src/util/sanitize_str.cpp b/src/util/sanitize_str.cpp new file mode 100644 index 00000000..72c72f84 --- /dev/null +++ b/src/util/sanitize_str.cpp @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +namespace waybar::util { +// replaces ``<>&"'`` with their encoded counterparts +std::string sanitize_string(std::string str) { + // note: it's important that '&' is replaced first; therefor we *can't* use std::map + const std::pair replacement_table[] = { + {'&', "&"}, {'<', "<"}, {'>', ">"}, {'"', """}, {'\'', "'"}}; + size_t startpoint; + for (size_t i = 0; i < (sizeof(replacement_table) / sizeof(replacement_table[0])); ++i) { + startpoint = 0; + std::pair pair = replacement_table[i]; + while ((startpoint = str.find(pair.first, startpoint)) != std::string::npos) { + str.replace(startpoint, 1, pair.second); + startpoint += pair.second.length(); + } + } + + return str; +} +} // namespace waybar::util From 8551c4bbe34850ad14637238a5bfd4f086ab350b Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 17 Oct 2022 09:19:00 +0200 Subject: [PATCH 35/91] fix: lint --- ext4fuse.rb | 57 +++++++++++++++++++++++ include/util/format.hpp | 9 ++-- src/modules/battery.cpp | 85 ++++++++++++++++++---------------- src/modules/idle_inhibitor.cpp | 6 +-- src/modules/pulseaudio.cpp | 8 ++-- 5 files changed, 110 insertions(+), 55 deletions(-) create mode 100644 ext4fuse.rb diff --git a/ext4fuse.rb b/ext4fuse.rb new file mode 100644 index 00000000..bc86f5fb --- /dev/null +++ b/ext4fuse.rb @@ -0,0 +1,57 @@ +class MacFuseRequirement < Requirement + fatal true + + satisfy(build_env: false) { self.class.binary_mac_fuse_installed? } + + def self.binary_mac_fuse_installed? + File.exist?("/usr/local/include/fuse/fuse.h") && + !File.symlink?("/usr/local/include/fuse") + end + + env do + ENV.append_path "PKG_CONFIG_PATH", HOMEBREW_LIBRARY/"Homebrew/os/mac/pkgconfig/fuse" + ENV.append_path "PKG_CONFIG_PATH", "/usr/local/lib/pkgconfig" + + unless HOMEBREW_PREFIX.to_s == "/usr/local" + ENV.append_path "HOMEBREW_LIBRARY_PATHS", "/usr/local/lib" + ENV.append_path "HOMEBREW_INCLUDE_PATHS", "/usr/local/include/fuse" + end + end + + def message + "macFUSE is required. Please run `brew install --cask macfuse` first." + end +end + +class Ext4fuse < Formula + desc "Read-only implementation of ext4 for FUSE" + homepage "https://github.com/gerard/ext4fuse" + url "https://github.com/gerard/ext4fuse/archive/v0.1.3.tar.gz" + sha256 "550f1e152c4de7d4ea517ee1c708f57bfebb0856281c508511419db45aa3ca9f" + license "GPL-2.0" + head "https://github.com/gerard/ext4fuse.git" + + bottle do + sha256 cellar: :any, catalina: "446dde5e84b058966ead0cde5e38e9411f465732527f6decfa1c0dcdbd4abbef" + sha256 cellar: :any, mojave: "88c4918bf5218f99295e539fe4499152edb3b60b6659e44ddd68b22359f512ae" + sha256 cellar: :any, high_sierra: "fc69c8993afd0ffc16a73c9c036ca8f83c77ac2a19b3237f76f9ccee8b30bbc9" + sha256 cellar: :any, sierra: "fe8bbe7cd5362f00ff06ef750926bf349d60563c20b0ecf212778631c8912ba2" + sha256 cellar: :any, el_capitan: "291047c821b7b205d85be853fb005510c6ab01bd4c2a2193c192299b6f049d35" + sha256 cellar: :any, yosemite: "b11f564b7e7c08af0b0a3e9854973d39809bf2d8a56014f4882772b2f7307ac1" + end + + depends_on "pkg-config" => :build + + on_macos do + depends_on MacFuseRequirement => :build + end + + on_linux do + depends_on "libfuse" + end + + def install + system "make" + bin.install "ext4fuse" + end +end diff --git a/include/util/format.hpp b/include/util/format.hpp index a9295425..fac0377d 100644 --- a/include/util/format.hpp +++ b/include/util/format.hpp @@ -56,11 +56,10 @@ struct formatter { fraction /= base; } - auto number_width = 5 // coeff in {:.1f} format - + s.binary_; // potential 4th digit before the decimal point - auto max_width = number_width - + 1 // prefix from units array - + s.binary_ // for the 'i' in GiB. + auto number_width = 5 // coeff in {:.1f} format + + s.binary_; // potential 4th digit before the decimal point + auto max_width = number_width + 1 // prefix from units array + + s.binary_ // for the 'i' in GiB. + s.unit_.length(); const char* format; diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 7b763cdd..e25ad9e5 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -156,7 +156,7 @@ const std::tuple waybar::modules::Battery::g std::lock_guard guard(battery_list_mutex_); try { - uint32_t total_power = 0; // μW + uint32_t total_power = 0; // μW bool total_power_exists = false; uint32_t total_energy = 0; // μWh bool total_energy_exists = false; @@ -179,28 +179,28 @@ const std::tuple waybar::modules::Battery::g uint32_t capacity = 0; bool capacity_exists = false; if (fs::exists(bat / "capacity")) { - capacity_exists = true; - std::ifstream(bat / "capacity") >> capacity; + capacity_exists = true; + std::ifstream(bat / "capacity") >> capacity; } uint32_t current_now = 0; bool current_now_exists = false; if (fs::exists(bat / "current_now")) { - current_now_exists = true; - std::ifstream(bat / "current_now") >> current_now; + current_now_exists = true; + std::ifstream(bat / "current_now") >> current_now; } else if (fs::exists(bat / "current_avg")) { - current_now_exists = true; - std::ifstream(bat / "current_avg") >> current_now; + current_now_exists = true; + std::ifstream(bat / "current_avg") >> current_now; } uint32_t voltage_now = 0; bool voltage_now_exists = false; if (fs::exists(bat / "voltage_now")) { - voltage_now_exists = true; - std::ifstream(bat / "voltage_now") >> voltage_now; + voltage_now_exists = true; + std::ifstream(bat / "voltage_now") >> voltage_now; } else if (fs::exists(bat / "voltage_avg")) { - voltage_now_exists = true; - std::ifstream(bat / "voltage_avg") >> voltage_now; + voltage_now_exists = true; + std::ifstream(bat / "voltage_avg") >> voltage_now; } uint32_t charge_full = 0; @@ -229,14 +229,14 @@ const std::tuple waybar::modules::Battery::g if (fs::exists(bat / "power_now")) { power_now_exists = true; std::ifstream(bat / "power_now") >> power_now; - } + } uint32_t energy_now = 0; bool energy_now_exists = false; if (fs::exists(bat / "energy_now")) { energy_now_exists = true; std::ifstream(bat / "energy_now") >> energy_now; - } + } uint32_t energy_full = 0; bool energy_full_exists = false; @@ -256,7 +256,8 @@ const std::tuple waybar::modules::Battery::g if (power_now_exists && current_now_exists && current_now != 0) { voltage_now_exists = true; voltage_now = 1000000 * (uint64_t)power_now / (uint64_t)current_now; - } else if (energy_full_design_exists && charge_full_design_exists && charge_full_design != 0) { + } else if (energy_full_design_exists && charge_full_design_exists && + charge_full_design != 0) { voltage_now_exists = true; voltage_now = 1000000 * (uint64_t)energy_full_design / (uint64_t)charge_full_design; } else if (energy_now_exists) { @@ -268,9 +269,10 @@ const std::tuple waybar::modules::Battery::g charge_now = (uint64_t)charge_full * (uint64_t)capacity / 100; if (charge_full != 0 && capacity != 0) { voltage_now_exists = true; - voltage_now = 1000000 * (uint64_t)energy_now * 100 / (uint64_t)charge_full / (uint64_t)capacity; + voltage_now = + 1000000 * (uint64_t)energy_now * 100 / (uint64_t)charge_full / (uint64_t)capacity; } - } + } } else if (energy_full_exists) { if (charge_full_exists && charge_full != 0) { voltage_now_exists = true; @@ -282,7 +284,8 @@ const std::tuple waybar::modules::Battery::g } if (charge_now != 0) { voltage_now_exists = true; - voltage_now = 10000 * (uint64_t)energy_full * (uint64_t)capacity / (uint64_t)charge_now; + voltage_now = + 10000 * (uint64_t)energy_full * (uint64_t)capacity / (uint64_t)charge_now; } } } @@ -311,7 +314,8 @@ const std::tuple waybar::modules::Battery::g } if (voltage_now != 0 && charge_full != 0) { capacity_exists = true; - capacity = 100 * 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now / (uint64_t)charge_full; + capacity = 100 * 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now / + (uint64_t)charge_full; } } } @@ -324,7 +328,8 @@ const std::tuple waybar::modules::Battery::g charge_now_exists = true; charge_now = (uint64_t)capacity * (uint64_t)charge_full / 100; energy_now_exists = true; - energy_now = (uint64_t)voltage_now * (uint64_t)capacity * (uint64_t)charge_full / 1000000 / 100; + energy_now = + (uint64_t)voltage_now * (uint64_t)capacity * (uint64_t)charge_full / 1000000 / 100; } else if (capacity_exists && energy_full) { if (voltage_now != 0) { charge_full_exists = true; @@ -334,7 +339,7 @@ const std::tuple waybar::modules::Battery::g } energy_now_exists = true; energy_now = (uint64_t)capacity * (uint64_t)energy_full / 100; - } + } } if (!energy_full_exists && voltage_now_exists) { @@ -356,7 +361,8 @@ const std::tuple waybar::modules::Battery::g energy_full = 100 * (uint64_t)energy_now / (uint64_t)capacity; if (voltage_now != 0) { charge_full_exists = true; - charge_full = 100 * 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now / (uint64_t)capacity; + charge_full = + 100 * 1000000 * (uint64_t)energy_now / (uint64_t)voltage_now / (uint64_t)capacity; } } } @@ -373,8 +379,7 @@ const std::tuple waybar::modules::Battery::g } // Show the "smallest" status among all batteries - if (status_gt(status, _status)) - status = _status; + if (status_gt(status, _status)) status = _status; if (power_now_exists) { total_power_exists = true; @@ -403,20 +408,19 @@ const std::tuple waybar::modules::Battery::g std::string current_status; std::ifstream(adapter_ / "online") >> online; std::getline(std::ifstream(adapter_ / "status"), current_status); - if (online && current_status != "Discharging") - status = "Plugged"; + if (online && current_status != "Discharging") status = "Plugged"; } float time_remaining{0.0f}; if (status == "Discharging" && total_power_exists && total_energy_exists) { - if (total_power != 0) - time_remaining = (float)total_energy / total_power; - } else if (status == "Charging" && total_energy_exists && total_energy_full_exists && total_power_exists) { + if (total_power != 0) time_remaining = (float)total_energy / total_power; + } else if (status == "Charging" && total_energy_exists && total_energy_full_exists && + total_power_exists) { if (total_power != 0) time_remaining = -(float)(total_energy_full - total_energy) / total_power; - // If we've turned positive it means the battery is past 100% and so just report that as no time remaining - if (time_remaining > 0.0f) - time_remaining = 0.0f; + // If we've turned positive it means the battery is past 100% and so just report that as no + // time remaining + if (time_remaining > 0.0f) time_remaining = 0.0f; } float calculated_capacity{0.0f}; @@ -428,9 +432,10 @@ const std::tuple waybar::modules::Battery::g calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full); } } - + // Handle design-capacity - if ((config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) && total_energy_exists && total_energy_full_design_exists) { + if ((config_["design-capacity"].isBool() ? config_["design-capacity"].asBool() : false) && + total_energy_exists && total_energy_full_design_exists) { if (total_energy_full_design > 0.0f) calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full_design); } @@ -438,19 +443,17 @@ const std::tuple waybar::modules::Battery::g // Handle full-at if (config_["full-at"].isUInt()) { auto full_at = config_["full-at"].asUInt(); - if (full_at < 100) - calculated_capacity = 100.f * calculated_capacity / full_at; + if (full_at < 100) calculated_capacity = 100.f * calculated_capacity / full_at; } // Handle it gracefully by clamping at 100% // This can happen when the battery is calibrating and goes above 100% - if (calculated_capacity > 100.f) - calculated_capacity = 100.f; - + if (calculated_capacity > 100.f) calculated_capacity = 100.f; + uint8_t cap = round(calculated_capacity); - // If we've reached 100% just mark as full as some batteries can stay stuck reporting they're still charging but not yet done - if (cap == 100 && status == "Charging") - status = "Full"; + // If we've reached 100% just mark as full as some batteries can stay stuck reporting they're + // still charging but not yet done + if (cap == 100 && status == "Charging") status = "Full"; return {cap, time_remaining, status, total_power / 1e6}; } catch (const std::exception& e) { diff --git a/src/modules/idle_inhibitor.cpp b/src/modules/idle_inhibitor.cpp index be16d5dc..0c82a08e 100644 --- a/src/modules/idle_inhibitor.cpp +++ b/src/modules/idle_inhibitor.cpp @@ -16,10 +16,8 @@ waybar::modules::IdleInhibitor::IdleInhibitor(const std::string& id, const Bar& throw std::runtime_error("idle-inhibit not available"); } - if (waybar::modules::IdleInhibitor::modules.empty() - && config_["start-activated"].isBool() - && config_["start-activated"].asBool() != status - ) { + if (waybar::modules::IdleInhibitor::modules.empty() && config_["start-activated"].isBool() && + config_["start-activated"].asBool() != status) { toggleStatus(); } diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 20a4648f..a396a9d5 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -104,8 +104,7 @@ bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) { if (volume_ < max_volume) { if (volume_ + step > max_volume) { change = round((max_volume - volume_) * volume_tick); - } - else { + } else { change = round(step * volume_tick); } pa_cvolume_inc(&pa_volume, change); @@ -114,8 +113,7 @@ bool waybar::modules::Pulseaudio::handleScroll(GdkEventScroll *e) { if (volume_ > 0) { if (volume_ - step < 0) { change = round(volume_ * volume_tick); - } - else { + } else { change = round(step * volume_tick); } pa_cvolume_dec(&pa_volume, change); @@ -186,7 +184,7 @@ void waybar::modules::Pulseaudio::sinkInfoCb(pa_context * /*context*/, const pa_ auto pa = static_cast(data); if (pa->config_["ignored-sinks"].isArray()) { - for (const auto& ignored_sink : pa->config_["ignored-sinks"]) { + for (const auto &ignored_sink : pa->config_["ignored-sinks"]) { if (ignored_sink.asString() == i->description) { return; } From 33c3ab35a8d445e1898c0959731e83954dc67ea5 Mon Sep 17 00:00:00 2001 From: herlev <> Date: Mon, 17 Oct 2022 10:13:37 +0200 Subject: [PATCH 36/91] Fix linter error (formatting) --- src/modules/hyprland/window.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index 1a9866e6..cd1584d3 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -45,9 +45,8 @@ uint Window::getActiveWorkspaceID(std::string monitorName) { assert(cmd.exit_code == 0); Json::Value json = parser_.parse(cmd.out); assert(json.isArray()); - auto monitor = std::find_if(json.begin(), json.end(), [&](Json::Value monitor){ - return monitor["name"] == monitorName; - }); + auto monitor = std::find_if(json.begin(), json.end(), + [&](Json::Value monitor) { return monitor["name"] == monitorName; }); assert(monitor != std::end(json)); return (*monitor)["activeWorkspace"]["id"].as(); } @@ -57,7 +56,7 @@ std::string Window::getLastWindowTitle(uint workspaceID) { assert(cmd.exit_code == 0); Json::Value json = parser_.parse(cmd.out); assert(json.isArray()); - auto workspace = std::find_if(json.begin(), json.end(), [&](Json::Value workspace){ + auto workspace = std::find_if(json.begin(), json.end(), [&](Json::Value workspace) { return workspace["id"].as() == workspaceID; }); assert(workspace != std::end(json)); From 6e73c58e60285f0c7d85d35bf6ea2ab7f0ff4741 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 18 Oct 2022 09:01:45 +0200 Subject: [PATCH 37/91] fix: lint --- include/factory.hpp | 2 +- src/modules/hyprland/window.cpp | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/include/factory.hpp b/include/factory.hpp index 0f770b97..55031b83 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -73,9 +73,9 @@ #include "modules/jack.hpp" #endif #include "bar.hpp" -#include "modules/user.hpp" #include "modules/custom.hpp" #include "modules/temperature.hpp" +#include "modules/user.hpp" namespace waybar { diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index 1a9866e6..cd1584d3 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -45,9 +45,8 @@ uint Window::getActiveWorkspaceID(std::string monitorName) { assert(cmd.exit_code == 0); Json::Value json = parser_.parse(cmd.out); assert(json.isArray()); - auto monitor = std::find_if(json.begin(), json.end(), [&](Json::Value monitor){ - return monitor["name"] == monitorName; - }); + auto monitor = std::find_if(json.begin(), json.end(), + [&](Json::Value monitor) { return monitor["name"] == monitorName; }); assert(monitor != std::end(json)); return (*monitor)["activeWorkspace"]["id"].as(); } @@ -57,7 +56,7 @@ std::string Window::getLastWindowTitle(uint workspaceID) { assert(cmd.exit_code == 0); Json::Value json = parser_.parse(cmd.out); assert(json.isArray()); - auto workspace = std::find_if(json.begin(), json.end(), [&](Json::Value workspace){ + auto workspace = std::find_if(json.begin(), json.end(), [&](Json::Value workspace) { return workspace["id"].as() == workspaceID; }); assert(workspace != std::end(json)); From 93807b0b3e74ec229872a17afc54761735d75204 Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Tue, 18 Oct 2022 11:21:44 +0200 Subject: [PATCH 38/91] resources: Remove border effect on hover Moves the ``border = none;`` attribute from workspace buttons to the global scope. The hover effects on all buttons are now consistent in the default stylesheet. --- resources/style.css | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/resources/style.css b/resources/style.css index 2a8c3199..40d870af 100644 --- a/resources/style.css +++ b/resources/style.css @@ -34,6 +34,14 @@ window#waybar.chromium { border: none; } +button { + /* Use box-shadow instead of border so the text isn't offset */ + box-shadow: inset 0 -3px transparent; + /* Avoid rounded borders under each button name */ + border: none; + border-radius: 0; +} + /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ button:hover { background: inherit; @@ -44,11 +52,6 @@ button:hover { padding: 0 5px; background-color: transparent; color: #ffffff; - /* Use box-shadow instead of border so the text isn't offset */ - box-shadow: inset 0 -3px transparent; - /* Avoid rounded borders under each workspace name */ - border: none; - border-radius: 0; } #workspaces button:hover { From 3d63080346dbd401d1b72bd6b02e27393c82c4e2 Mon Sep 17 00:00:00 2001 From: herlev <> Date: Tue, 18 Oct 2022 12:25:22 +0200 Subject: [PATCH 39/91] Document sort-by-number option in man page --- man/waybar-wlr-workspaces.5.scd | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/man/waybar-wlr-workspaces.5.scd b/man/waybar-wlr-workspaces.5.scd index 5d7b2acd..169112fc 100644 --- a/man/waybar-wlr-workspaces.5.scd +++ b/man/waybar-wlr-workspaces.5.scd @@ -33,6 +33,11 @@ Addressed by *wlr/workspaces* Note that if both *sort-by-name* and *sort-by-coordinates* are true sort by name will be first. If both are false - sort by id will be performed. +*sort-by-number*: ++ + typeof: bool ++ + default: false ++ + If set to true, workspace names will be sorted numerically. Takes presedence over any other sort-by option. + *all-outputs*: ++ typeof: bool ++ default: false ++ @@ -75,7 +80,8 @@ Additional to workspace name matching, the following *format-icons* can be set. "5": "", "focused": "", "default": "" - } + }, + "sort-by-number": true } ``` From 97ae2ff343e44a2fb9898312deed81c3499e3f05 Mon Sep 17 00:00:00 2001 From: herlev <> Date: Tue, 18 Oct 2022 13:18:43 +0200 Subject: [PATCH 40/91] Add rewrite option to hyprland/window --- include/modules/hyprland/window.hpp | 1 + src/modules/hyprland/window.cpp | 29 ++++++++++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/modules/hyprland/window.hpp b/include/modules/hyprland/window.hpp index 1423aece..2c2ed972 100644 --- a/include/modules/hyprland/window.hpp +++ b/include/modules/hyprland/window.hpp @@ -19,6 +19,7 @@ class Window : public waybar::ALabel { private: uint getActiveWorkspaceID(std::string); std::string getLastWindowTitle(uint); + std::string rewriteTitle(const std::string&); void onEvent(const std::string&); bool separate_outputs; diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index cd1584d3..20e438d1 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -2,6 +2,7 @@ #include +#include #include #include "modules/hyprland/backend.hpp" @@ -32,7 +33,7 @@ auto Window::update() -> void { if (!format_.empty()) { label_.show(); - label_.set_markup(fmt::format(format_, lastView)); + label_.set_markup(fmt::format(format_, rewriteTitle(lastView))); } else { label_.hide(); } @@ -84,4 +85,30 @@ void Window::onEvent(const std::string& ev) { dp.emit(); } +std::string Window::rewriteTitle(const std::string& title) { + const auto& rules = config_["rewrite"]; + if (!rules.isObject()) { + return title; + } + + std::string res = title; + + for (auto it = rules.begin(); it != rules.end(); ++it) { + if (it.key().isString() && it->isString()) { + try { + // malformated regexes will cause an exception. + // in this case, log error and try the next rule. + const std::regex rule{it.key().asString()}; + if (std::regex_match(title, rule)) { + res = std::regex_replace(res, rule, it->asString()); + } + } catch (const std::regex_error& e) { + spdlog::error("Invalid rule {}: {}", it.key().asString(), e.what()); + } + } + } + + return res; +} + } // namespace waybar::modules::hyprland \ No newline at end of file From 59e7f1974c0b3eec4d1f1ba371daae040cac362d Mon Sep 17 00:00:00 2001 From: herlev <> Date: Tue, 18 Oct 2022 13:21:20 +0200 Subject: [PATCH 41/91] Document hyprland/window rewrite option --- man/waybar-hyprland-window.5.scd | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/man/waybar-hyprland-window.5.scd b/man/waybar-hyprland-window.5.scd index 4be137d0..0135d7c9 100644 --- a/man/waybar-hyprland-window.5.scd +++ b/man/waybar-hyprland-window.5.scd @@ -17,12 +17,31 @@ Addressed by *hyprland/window* default: {} ++ The format, how information should be displayed. On {} the current window title is displayed. +*rewrite*: ++ + typeof: object ++ + Rules to rewrite window title. See *rewrite rules*. + +# REWRITE RULES + +*rewrite* is an object where keys are regular expressions and values are +rewrite rules if the expression matches. Rules may contain references to +captures of the expression. + +Regular expression and replacement follow ECMA-script rules. + +If no expression matches, the title is left unchanged. + +Invalid expressions (e.g., mismatched parentheses) are skipped. # EXAMPLES ``` "hyprland/window": { - "format": "{}" + "format": "{}", + "rewrite": { + "(.*) - Mozilla Firefox": "🌎 $1", + "(.*) - zsh": "> [$1]" + } } ``` From 90f206f92aee2ccd18e9b2549e4bcc2228c5004e Mon Sep 17 00:00:00 2001 From: ItsDrike Date: Tue, 18 Oct 2022 18:36:00 +0200 Subject: [PATCH 42/91] Fix crash on quickly switching workspaces The hyprland/window widget had an assertion ensuring that the output from hyprctl matched the currently selected workspace id. However this assertion fails if workspaces are switched too quickly, causing the selected workspace to differ in id from the one in hyprctl, failing this assertion which then crashes the entire program. This fix simply changes this assertion into an if statement, and if a mismatch is found, empty string is returned as the window name. --- src/modules/hyprland/window.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index cd1584d3..8d02cf33 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -59,7 +59,10 @@ std::string Window::getLastWindowTitle(uint workspaceID) { auto workspace = std::find_if(json.begin(), json.end(), [&](Json::Value workspace) { return workspace["id"].as() == workspaceID; }); - assert(workspace != std::end(json)); + + if (workspace != std::end(json)) { + return ""; + } return (*workspace)["lastwindowtitle"].as(); } From 830c5cd5d09ed3639040b0034f3c031498bc78a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Fri, 30 Sep 2022 21:59:27 +0200 Subject: [PATCH 43/91] FreeBSD: Add support to battery This commit aims to propose a FreeBSD to gain battery support using sysctl on hw.acpi.battery.* --- include/factory.hpp | 2 +- meson.build | 5 +++ src/factory.cpp | 2 +- src/modules/battery.cpp | 79 +++++++++++++++++++++++++++++++++++++++-- 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/include/factory.hpp b/include/factory.hpp index 55031b83..ca707a3c 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -27,7 +27,7 @@ #include "modules/hyprland/language.hpp" #include "modules/hyprland/window.hpp" #endif -#if defined(__linux__) && !defined(NO_FILESYSTEM) +#if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM)) #include "modules/battery.hpp" #endif #if defined(HAVE_CPU_LINUX) || defined(HAVE_CPU_BSD) diff --git a/meson.build b/meson.build index aab5a492..e537bcca 100644 --- a/meson.build +++ b/meson.build @@ -179,6 +179,11 @@ elif is_dragonfly or is_freebsd or is_netbsd or is_openbsd 'src/modules/memory/bsd.cpp', 'src/modules/memory/common.cpp', ) + if is_freebsd + src_files += files( + 'src/modules/battery.cpp', + ) + endif endif add_project_arguments('-DHAVE_SWAY', language: 'cpp') diff --git a/src/factory.cpp b/src/factory.cpp index 9b9dde89..d00a7d47 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -7,7 +7,7 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { auto hash_pos = name.find('#'); auto ref = name.substr(0, hash_pos); auto id = hash_pos != std::string::npos ? name.substr(hash_pos + 1) : ""; -#if defined(__linux__) && !defined(NO_FILESYSTEM) +#if defined(__FreeBSD__) || (defined(__linux__) && !defined(NO_FILESYSTEM)) if (ref == "battery") { return new waybar::modules::Battery(id, config_[name]); } diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index e25ad9e5..1fbdcb58 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -1,9 +1,16 @@ #include "modules/battery.hpp" - +#if defined(__FreeBSD__) +// clang-format off +#include +#include +// clang-format on +#endif #include +#include waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config) : AButton(config, "battery", id, "{capacity}%", 60) { +#if defined(__Linux__) battery_watch_fd_ = inotify_init1(IN_CLOEXEC); if (battery_watch_fd_ == -1) { throw std::runtime_error("Unable to listen batteries."); @@ -19,11 +26,12 @@ waybar::modules::Battery::Battery(const std::string& id, const Json::Value& conf if (global_watch < 0) { throw std::runtime_error("Could not watch for battery plug/unplug"); } - +#endif worker(); } waybar::modules::Battery::~Battery() { +#if (__Linux__) std::lock_guard guard(battery_list_mutex_); if (global_watch >= 0) { @@ -39,9 +47,16 @@ waybar::modules::Battery::~Battery() { batteries_.erase(it); } close(battery_watch_fd_); +#endif } void waybar::modules::Battery::worker() { +#if defined(__FreeBSD__) + thread_timer_ = [this] { + dp.emit(); + thread_timer_.sleep_for(interval_); + }; +#else thread_timer_ = [this] { // Make sure we eventually update the list of batteries even if we miss an // inotify event for some reason @@ -68,9 +83,11 @@ void waybar::modules::Battery::worker() { refreshBatteries(); dp.emit(); }; +#endif } void waybar::modules::Battery::refreshBatteries() { +#if (__Linux__) std::lock_guard guard(battery_list_mutex_); // Mark existing list of batteries as not necessarily found std::map check_map; @@ -135,6 +152,7 @@ void waybar::modules::Battery::refreshBatteries() { batteries_.erase(check.first); } } +#endif } // Unknown > Full > Not charging > Discharging > Charging @@ -158,6 +176,49 @@ const std::tuple waybar::modules::Battery::g try { uint32_t total_power = 0; // μW bool total_power_exists = false; +#if defined(__FreeBSD__) + int capacity; + size_t size_capacity = sizeof capacity; + if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.life failed"); + } + int time; + size_t size_time = sizeof time; + if (sysctlbyname("hw.acpi.battery.time", &time, &size_time, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.time failed"); + } + int rate; + size_t size_rate = sizeof rate; + if (sysctlbyname("hw.acpi.battery.rate", &rate, &size_rate, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.rate failed"); + } + + auto status = getAdapterStatus(capacity); + // Handle full-at + if (config_["full-at"].isUInt()) { + auto full_at = config_["full-at"].asUInt(); + if (full_at < 100) { + capacity = 100.f * capacity / full_at; + } + } + if (capacity > 100.f) { + // This can happen when the battery is calibrating and goes above 100% + // Handle it gracefully by clamping at 100% + capacity = 100.f; + } + uint8_t cap = round(capacity); + if (cap == 100 && status=="Plugged") { + // If we've reached 100% just mark as full as some batteries can stay + // stuck reporting they're still charging but not yet done + status = "Full"; + } + + //spdlog::info("{} {} {} {}", capacity,time,status,rate); + return {capacity, time, status, rate}; + +#else + uint32_t total_power = 0; // μW +>>>>>>> 246e377 (FreeBSD: Add support to battery) uint32_t total_energy = 0; // μWh bool total_energy_exists = false; uint32_t total_energy_full = 0; @@ -456,6 +517,7 @@ const std::tuple waybar::modules::Battery::g if (cap == 100 && status == "Charging") status = "Full"; return {cap, time_remaining, status, total_power / 1e6}; +#endif } catch (const std::exception& e) { spdlog::error("Battery: {}", e.what()); return {0, 0, "Unknown", 0}; @@ -463,11 +525,20 @@ const std::tuple waybar::modules::Battery::g } const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { +#if defined(__Linux__) if (!adapter_.empty()) { bool online; std::string status; std::ifstream(adapter_ / "online") >> online; std::getline(std::ifstream(adapter_ / "status"), status); +#else + int state; + size_t size_state = sizeof state; + if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.state failed"); + } + bool online = state == 2; +#endif if (capacity == 100) { return "Full"; } @@ -475,7 +546,9 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c return "Plugged"; } return "Discharging"; +#if defined(__Linux__) } +#endif return "Unknown"; } @@ -497,10 +570,12 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai } auto waybar::modules::Battery::update() -> void { +#if __Linux__ if (batteries_.empty()) { event_box_.hide(); return; } +#endif auto [capacity, time_remaining, status, power] = getInfos(); if (status == "Unknown") { status = getAdapterStatus(capacity); From 45e44e03bd768dcad23309ee4b7d213f6db7332b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 06:12:42 +0200 Subject: [PATCH 44/91] Apply jbeich suggestion for if defined(__linux__) --- include/modules/battery.hpp | 2 ++ src/modules/battery.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index 5f25fd59..42cf1647 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -6,7 +6,9 @@ #include #endif #include +#if #defined(__linux__) #include +#endif #include #include diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 1fbdcb58..13a49208 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -31,7 +31,7 @@ waybar::modules::Battery::Battery(const std::string& id, const Json::Value& conf } waybar::modules::Battery::~Battery() { -#if (__Linux__) +#if defined(__linux__) std::lock_guard guard(battery_list_mutex_); if (global_watch >= 0) { @@ -87,7 +87,7 @@ void waybar::modules::Battery::worker() { } void waybar::modules::Battery::refreshBatteries() { -#if (__Linux__) +#if defined(__linux__) std::lock_guard guard(battery_list_mutex_); // Mark existing list of batteries as not necessarily found std::map check_map; @@ -525,7 +525,7 @@ const std::tuple waybar::modules::Battery::g } const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { -#if defined(__Linux__) +#if defined(__linux__) if (!adapter_.empty()) { bool online; std::string status; @@ -546,7 +546,7 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c return "Plugged"; } return "Discharging"; -#if defined(__Linux__) +#if defined(__linux__) } #endif return "Unknown"; @@ -570,7 +570,7 @@ const std::string waybar::modules::Battery::formatTimeRemaining(float hoursRemai } auto waybar::modules::Battery::update() -> void { -#if __Linux__ +#if defined(__linux__) if (batteries_.empty()) { event_box_.hide(); return; From 9d5f0e45c051de9b424c89bfb32f43ac7392ab85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 06:14:37 +0200 Subject: [PATCH 45/91] Add test if there is battery --- include/modules/battery.hpp | 2 +- src/modules/battery.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/include/modules/battery.hpp b/include/modules/battery.hpp index 42cf1647..614b36ab 100644 --- a/include/modules/battery.hpp +++ b/include/modules/battery.hpp @@ -6,7 +6,7 @@ #include #endif #include -#if #defined(__linux__) +#if defined(__linux__) #include #endif diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 13a49208..a4657409 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -177,6 +177,17 @@ const std::tuple waybar::modules::Battery::g uint32_t total_power = 0; // μW bool total_power_exists = false; #if defined(__FreeBSD__) + /* Allocate state of battery units reported via ACPI. */ + int battery_units = 0; + size_t battery_units_size = sizeof battery_units; + if( sysctlbyname("hw.acpi.battery.units", &battery_units, &battery_units_size, NULL, 0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.units failed"); + } + + if(battery_units < 0) { + throw std::runtime_error("No battery units"); + } + int capacity; size_t size_capacity = sizeof capacity; if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL,0) != 0) { From 1421163df304db67f220b5ce893099785587fbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 06:26:24 +0200 Subject: [PATCH 46/91] remove useless include --- src/modules/battery.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index a4657409..5f4734c1 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -1,7 +1,6 @@ #include "modules/battery.hpp" #if defined(__FreeBSD__) // clang-format off -#include #include // clang-format on #endif From 0ada5ac8b06e1962f9368758b0d114a1ce52a22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 06:39:29 +0200 Subject: [PATCH 47/91] Battery::getAdapterStatus: better code format --- src/modules/battery.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 5f4734c1..143cc1b0 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -535,7 +535,15 @@ const std::tuple waybar::modules::Battery::g } const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) const { -#if defined(__linux__) +#if defined(__FreeBSD__) + int state; + size_t size_state = sizeof state; + if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { + throw std::runtime_error("sysctl hw.acpi.battery.state failed"); + } + bool online = state == 2; + { +#else if (!adapter_.empty()) { bool online; std::string status; @@ -556,9 +564,7 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c return "Plugged"; } return "Discharging"; -#if defined(__linux__) } -#endif return "Unknown"; } From a58988ea9dd71eae6ae1b80933e376a9f41fa545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 07:39:35 +0200 Subject: [PATCH 48/91] Battery: replace #else by #elif defined(__linux__) Cannot use #else here when inotify_init1() is hidden behind #if defined(__Linux__). Co-authored-by: Jan Beich --- src/modules/battery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 143cc1b0..ecf9891d 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -226,7 +226,7 @@ const std::tuple waybar::modules::Battery::g //spdlog::info("{} {} {} {}", capacity,time,status,rate); return {capacity, time, status, rate}; -#else +#elif defined(__linux__) uint32_t total_power = 0; // μW >>>>>>> 246e377 (FreeBSD: Add support to battery) uint32_t total_energy = 0; // μWh From d4d35e2f89818dd949f3399986ef178a7bcef9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 07:41:19 +0200 Subject: [PATCH 49/91] apply clang-format --- src/modules/battery.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index ecf9891d..7b1b3f76 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -179,27 +179,27 @@ const std::tuple waybar::modules::Battery::g /* Allocate state of battery units reported via ACPI. */ int battery_units = 0; size_t battery_units_size = sizeof battery_units; - if( sysctlbyname("hw.acpi.battery.units", &battery_units, &battery_units_size, NULL, 0) != 0) { + if (sysctlbyname("hw.acpi.battery.units", &battery_units, &battery_units_size, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.units failed"); } - if(battery_units < 0) { + if (battery_units < 0) { throw std::runtime_error("No battery units"); } int capacity; size_t size_capacity = sizeof capacity; - if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL,0) != 0) { + if (sysctlbyname("hw.acpi.battery.life", &capacity, &size_capacity, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.life failed"); } int time; size_t size_time = sizeof time; - if (sysctlbyname("hw.acpi.battery.time", &time, &size_time, NULL,0) != 0) { + if (sysctlbyname("hw.acpi.battery.time", &time, &size_time, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.time failed"); } int rate; size_t size_rate = sizeof rate; - if (sysctlbyname("hw.acpi.battery.rate", &rate, &size_rate, NULL,0) != 0) { + if (sysctlbyname("hw.acpi.battery.rate", &rate, &size_rate, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.rate failed"); } @@ -217,13 +217,13 @@ const std::tuple waybar::modules::Battery::g capacity = 100.f; } uint8_t cap = round(capacity); - if (cap == 100 && status=="Plugged") { + if (cap == 100 && status == "Plugged") { // If we've reached 100% just mark as full as some batteries can stay // stuck reporting they're still charging but not yet done status = "Full"; } - //spdlog::info("{} {} {} {}", capacity,time,status,rate); + // spdlog::info("{} {} {} {}", capacity,time,status,rate); return {capacity, time, status, rate}; #elif defined(__linux__) @@ -538,7 +538,7 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c #if defined(__FreeBSD__) int state; size_t size_state = sizeof state; - if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { + if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL, 0) != 0) { throw std::runtime_error("sysctl hw.acpi.battery.state failed"); } bool online = state == 2; From 6156a62294de768e9e74a382807f7106cb316c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 08:01:59 +0200 Subject: [PATCH 50/91] fix time_remaining. FreeBSD sysctl returns minutes and not hours --- src/modules/battery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 7b1b3f76..acdfd438 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -224,7 +224,7 @@ const std::tuple waybar::modules::Battery::g } // spdlog::info("{} {} {} {}", capacity,time,status,rate); - return {capacity, time, status, rate}; + return {capacity, time / 60.0, status, rate}; #elif defined(__linux__) uint32_t total_power = 0; // μW From 72a2ada82c959329a6a8a68509218de736e3e164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 4 Oct 2022 11:38:21 +0200 Subject: [PATCH 51/91] remove clang-format lines --- src/modules/battery.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index acdfd438..fd78c881 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -1,8 +1,6 @@ #include "modules/battery.hpp" #if defined(__FreeBSD__) -// clang-format off #include -// clang-format on #endif #include From 692b90c995ba9b779d7f31deb3c013a27cea7914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Bartoletti?= Date: Tue, 18 Oct 2022 20:44:55 +0200 Subject: [PATCH 52/91] fix build --- src/modules/battery.cpp | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index fd78c881..88774940 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -171,8 +171,6 @@ const std::tuple waybar::modules::Battery::g std::lock_guard guard(battery_list_mutex_); try { - uint32_t total_power = 0; // μW - bool total_power_exists = false; #if defined(__FreeBSD__) /* Allocate state of battery units reported via ACPI. */ int battery_units = 0; @@ -225,8 +223,8 @@ const std::tuple waybar::modules::Battery::g return {capacity, time / 60.0, status, rate}; #elif defined(__linux__) - uint32_t total_power = 0; // μW ->>>>>>> 246e377 (FreeBSD: Add support to battery) + uint32_t total_power = 0; // μW + bool total_power_exists = false; uint32_t total_energy = 0; // μWh bool total_energy_exists = false; uint32_t total_energy_full = 0; @@ -540,6 +538,7 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c throw std::runtime_error("sysctl hw.acpi.battery.state failed"); } bool online = state == 2; + std::string status{"Unknown"}; // TODO: add status in FreeBSD { #else if (!adapter_.empty()) { @@ -547,13 +546,6 @@ const std::string waybar::modules::Battery::getAdapterStatus(uint8_t capacity) c std::string status; std::ifstream(adapter_ / "online") >> online; std::getline(std::ifstream(adapter_ / "status"), status); -#else - int state; - size_t size_state = sizeof state; - if (sysctlbyname("hw.acpi.battery.state", &state, &size_state, NULL,0) != 0) { - throw std::runtime_error("sysctl hw.acpi.battery.state failed"); - } - bool online = state == 2; #endif if (capacity == 100) { return "Full"; From 662a250705236b1c9748cbaccf12347b2a8f8274 Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Wed, 19 Oct 2022 13:15:21 +0200 Subject: [PATCH 53/91] Fix battery indicator crash on linux A pre-processor flag was misspelled and is now corrected. --- src/modules/battery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 88774940..fd1be357 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -7,7 +7,7 @@ #include waybar::modules::Battery::Battery(const std::string& id, const Json::Value& config) : AButton(config, "battery", id, "{capacity}%", 60) { -#if defined(__Linux__) +#if defined(__linux__) battery_watch_fd_ = inotify_init1(IN_CLOEXEC); if (battery_watch_fd_ == -1) { throw std::runtime_error("Unable to listen batteries."); From 54e04b5a30228e1c7c95c714bcf0fe178684b96d Mon Sep 17 00:00:00 2001 From: herlev <> Date: Wed, 19 Oct 2022 13:25:08 +0200 Subject: [PATCH 54/91] Refactor rewriteTitle --- include/modules/hyprland/window.hpp | 1 - include/modules/sway/window.hpp | 1 - include/util/rewrite_title.hpp | 8 ++++++++ meson.build | 3 ++- src/modules/hyprland/window.cpp | 32 +++-------------------------- src/modules/sway/window.cpp | 29 ++------------------------ src/util/rewrite_title.cpp | 32 +++++++++++++++++++++++++++++ 7 files changed, 47 insertions(+), 59 deletions(-) create mode 100644 include/util/rewrite_title.hpp create mode 100644 src/util/rewrite_title.cpp diff --git a/include/modules/hyprland/window.hpp b/include/modules/hyprland/window.hpp index 2c2ed972..1423aece 100644 --- a/include/modules/hyprland/window.hpp +++ b/include/modules/hyprland/window.hpp @@ -19,7 +19,6 @@ class Window : public waybar::ALabel { private: uint getActiveWorkspaceID(std::string); std::string getLastWindowTitle(uint); - std::string rewriteTitle(const std::string&); void onEvent(const std::string&); bool separate_outputs; diff --git a/include/modules/sway/window.hpp b/include/modules/sway/window.hpp index c99ba7f7..c13d5cee 100644 --- a/include/modules/sway/window.hpp +++ b/include/modules/sway/window.hpp @@ -24,7 +24,6 @@ class Window : public AIconLabel, public sigc::trackable { std::tuple getFocusedNode( const Json::Value& nodes, std::string& output); void getTree(); - std::string rewriteTitle(const std::string& title); void updateAppIconName(); void updateAppIcon(); diff --git a/include/util/rewrite_title.hpp b/include/util/rewrite_title.hpp new file mode 100644 index 00000000..c477339e --- /dev/null +++ b/include/util/rewrite_title.hpp @@ -0,0 +1,8 @@ +#pragma once +#include + +#include + +namespace waybar::util { +std::string rewriteTitle(const std::string&, const Json::Value&); +} diff --git a/meson.build b/meson.build index e537bcca..e72d99f4 100644 --- a/meson.build +++ b/meson.build @@ -157,7 +157,8 @@ src_files = files( 'src/config.cpp', 'src/group.cpp', 'src/util/ustring_clen.cpp', - 'src/util/sanitize_str.cpp' + 'src/util/sanitize_str.cpp', + 'src/util/rewrite_title.cpp' ) if is_linux diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index 0d22fe03..e49561df 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -8,6 +8,7 @@ #include "modules/hyprland/backend.hpp" #include "util/command.hpp" #include "util/json.hpp" +#include "util/rewrite_title.hpp" namespace waybar::modules::hyprland { @@ -33,7 +34,7 @@ auto Window::update() -> void { if (!format_.empty()) { label_.show(); - label_.set_markup(fmt::format(format_, rewriteTitle(lastView))); + label_.set_markup(fmt::format(format_, waybar::util::rewriteTitle(lastView, config_["rewrite"]))); } else { label_.hide(); } @@ -61,7 +62,7 @@ std::string Window::getLastWindowTitle(uint workspaceID) { return workspace["id"].as() == workspaceID; }); - if (workspace != std::end(json)) { + if (workspace == std::end(json)) { return ""; } return (*workspace)["lastwindowtitle"].as(); @@ -87,31 +88,4 @@ void Window::onEvent(const std::string& ev) { dp.emit(); } - -std::string Window::rewriteTitle(const std::string& title) { - const auto& rules = config_["rewrite"]; - if (!rules.isObject()) { - return title; - } - - std::string res = title; - - for (auto it = rules.begin(); it != rules.end(); ++it) { - if (it.key().isString() && it->isString()) { - try { - // malformated regexes will cause an exception. - // in this case, log error and try the next rule. - const std::regex rule{it.key().asString()}; - if (std::regex_match(title, rule)) { - res = std::regex_replace(res, rule, it->asString()); - } - } catch (const std::regex_error& e) { - spdlog::error("Invalid rule {}: {}", it.key().asString(), e.what()); - } - } - } - - return res; -} - } // namespace waybar::modules::hyprland \ No newline at end of file diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index 3d63743f..499c08c0 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -1,4 +1,5 @@ #include "modules/sway/window.hpp" +#include "util/rewrite_title.hpp" #include #include @@ -175,7 +176,7 @@ auto Window::update() -> void { bar_.window.get_style_context()->remove_class("solo"); bar_.window.get_style_context()->remove_class("empty"); } - label_.set_markup(fmt::format(format_, fmt::arg("title", rewriteTitle(window_)), + label_.set_markup(fmt::format(format_, fmt::arg("title", waybar::util::rewriteTitle(window_, config_["rewrite"])), fmt::arg("app_id", app_id_), fmt::arg("shell", shell_))); if (tooltipEnabled()) { label_.set_tooltip_text(window_); @@ -262,30 +263,4 @@ void Window::getTree() { } } -std::string Window::rewriteTitle(const std::string& title) { - const auto& rules = config_["rewrite"]; - if (!rules.isObject()) { - return title; - } - - std::string res = title; - - for (auto it = rules.begin(); it != rules.end(); ++it) { - if (it.key().isString() && it->isString()) { - try { - // malformated regexes will cause an exception. - // in this case, log error and try the next rule. - const std::regex rule{it.key().asString()}; - if (std::regex_match(title, rule)) { - res = std::regex_replace(res, rule, it->asString()); - } - } catch (const std::regex_error& e) { - spdlog::error("Invalid rule {}: {}", it.key().asString(), e.what()); - } - } - } - - return res; -} - } // namespace waybar::modules::sway diff --git a/src/util/rewrite_title.cpp b/src/util/rewrite_title.cpp new file mode 100644 index 00000000..fae59bb1 --- /dev/null +++ b/src/util/rewrite_title.cpp @@ -0,0 +1,32 @@ +#include "util/rewrite_title.hpp" + +#include + +#include + +namespace waybar::util { +std::string rewriteTitle(const std::string& title, const Json::Value& rules) { + if (!rules.isObject()) { + return title; + } + + std::string res = title; + + for (auto it = rules.begin(); it != rules.end(); ++it) { + if (it.key().isString() && it->isString()) { + try { + // malformated regexes will cause an exception. + // in this case, log error and try the next rule. + const std::regex rule{it.key().asString()}; + if (std::regex_match(title, rule)) { + res = std::regex_replace(res, rule, it->asString()); + } + } catch (const std::regex_error& e) { + spdlog::error("Invalid rule {}: {}", it.key().asString(), e.what()); + } + } + } + + return res; +} +} // namespace waybar::util From e660a3634d3599a3703555bde47ecb9875eb4570 Mon Sep 17 00:00:00 2001 From: herlev <> Date: Wed, 19 Oct 2022 13:29:05 +0200 Subject: [PATCH 55/91] Fix linter --- src/modules/sway/window.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/modules/sway/window.cpp b/src/modules/sway/window.cpp index 499c08c0..5da7d3d4 100644 --- a/src/modules/sway/window.cpp +++ b/src/modules/sway/window.cpp @@ -1,5 +1,4 @@ #include "modules/sway/window.hpp" -#include "util/rewrite_title.hpp" #include #include @@ -13,6 +12,8 @@ #include #include +#include "util/rewrite_title.hpp" + namespace waybar::modules::sway { Window::Window(const std::string& id, const Bar& bar, const Json::Value& config) @@ -176,8 +177,9 @@ auto Window::update() -> void { bar_.window.get_style_context()->remove_class("solo"); bar_.window.get_style_context()->remove_class("empty"); } - label_.set_markup(fmt::format(format_, fmt::arg("title", waybar::util::rewriteTitle(window_, config_["rewrite"])), - fmt::arg("app_id", app_id_), fmt::arg("shell", shell_))); + label_.set_markup(fmt::format( + format_, fmt::arg("title", waybar::util::rewriteTitle(window_, config_["rewrite"])), + fmt::arg("app_id", app_id_), fmt::arg("shell", shell_))); if (tooltipEnabled()) { label_.set_tooltip_text(window_); } From e1045381fed839105662b27f07cb8b43d2b0e836 Mon Sep 17 00:00:00 2001 From: herlev <> Date: Wed, 19 Oct 2022 13:30:28 +0200 Subject: [PATCH 56/91] Fix linter --- src/modules/hyprland/window.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index e49561df..d942cf68 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -34,7 +34,8 @@ auto Window::update() -> void { if (!format_.empty()) { label_.show(); - label_.set_markup(fmt::format(format_, waybar::util::rewriteTitle(lastView, config_["rewrite"]))); + label_.set_markup( + fmt::format(format_, waybar::util::rewriteTitle(lastView, config_["rewrite"]))); } else { label_.hide(); } From c18c6b080a0e09b8930a5ac5e8a166c3c688041f Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Wed, 19 Oct 2022 13:47:04 +0200 Subject: [PATCH 57/91] Set default minimal width of buttons to zero Even if all margins, padding and borders of buttons are removed the label inside the buttons may still be padded if they are too short. Setting the minimal width of buttons to zero fixes this issue. --- resources/style.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/style.css b/resources/style.css index 40d870af..ae6e496d 100644 --- a/resources/style.css +++ b/resources/style.css @@ -40,6 +40,8 @@ button { /* Avoid rounded borders under each button name */ border: none; border-radius: 0; + /* https://github.com/Alexays/Waybar/issues/1731 */ + min-width: 0; } /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ From 1f591e36f1e6212e5b4748495b3c45354cae46c1 Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Thu, 20 Oct 2022 10:27:41 +0200 Subject: [PATCH 58/91] button: Hardcode min-width property set to zero Buttons come with an intrinsic min-width but lack a method to alter this property. Setting the requested size to zero has also no effect on it. The only way found to work is to hard code the CSS into the button. --- include/AButton.hpp | 1 + src/AButton.cpp | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/include/AButton.hpp b/include/AButton.hpp index 4628f1ea..ce29a09f 100644 --- a/include/AButton.hpp +++ b/include/AButton.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include diff --git a/src/AButton.cpp b/src/AButton.cpp index 1ef1804b..2952b0d8 100644 --- a/src/AButton.cpp +++ b/src/AButton.cpp @@ -18,6 +18,12 @@ AButton::AButton(const Json::Value& config, const std::string& name, const std:: default_format_(format_) { button_.set_name(name); button_.set_relief(Gtk::RELIEF_NONE); + + /* https://github.com/Alexays/Waybar/issues/1731 */ + auto css = Gtk::CssProvider::create(); + css->load_from_data("button { min-width: 0; }"); + button_.get_style_context()->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_USER); + if (!id.empty()) { button_.get_style_context()->add_class(id); } From 05dbfe261af282f511f12388c730425e69fe26fa Mon Sep 17 00:00:00 2001 From: Simon Plakolb Date: Thu, 20 Oct 2022 10:34:20 +0200 Subject: [PATCH 59/91] style: Revert set default minimal width of buttons to zero #1737 --- resources/style.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/resources/style.css b/resources/style.css index ae6e496d..40d870af 100644 --- a/resources/style.css +++ b/resources/style.css @@ -40,8 +40,6 @@ button { /* Avoid rounded borders under each button name */ border: none; border-radius: 0; - /* https://github.com/Alexays/Waybar/issues/1731 */ - min-width: 0; } /* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ From 411c6f4b4b65b5ddaaa4f1ba6a9a80f0382cacb8 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 20 Oct 2022 10:56:47 +0200 Subject: [PATCH 60/91] chore: update catch --- meson.build | 1 + subprojects/catch2.wrap | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index 05a32f43..3c443a2e 100644 --- a/meson.build +++ b/meson.build @@ -428,6 +428,7 @@ endif catch2 = dependency( 'catch2', + version: '>=3.0.0' fallback: ['catch2', 'catch2_dep'], required: get_option('tests'), ) diff --git a/subprojects/catch2.wrap b/subprojects/catch2.wrap index c82b310f..ea61b942 100644 --- a/subprojects/catch2.wrap +++ b/subprojects/catch2.wrap @@ -1,12 +1,13 @@ [wrap-file] -directory = Catch2-2.13.7 -source_url = https://github.com/catchorg/Catch2/archive/v2.13.7.zip -source_filename = Catch2-2.13.7.zip -source_hash = 3f3ccd90ad3a8fbb1beeb15e6db440ccdcbebe378dfd125d07a1f9a587a927e9 -patch_filename = catch2_2.13.7-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/catch2_2.13.7-1/get_patch -patch_hash = 2f7369645d747e5bd866317ac1dd4c3d04dc97d3aad4fc6b864bdf75d3b57158 +directory = Catch2-3.1.0 +source_url = https://github.com/catchorg/Catch2/archive/v3.1.0.tar.gz +source_filename = Catch2-3.1.0.tar.gz +source_hash = c252b2d9537e18046d8b82535069d2567f77043f8e644acf9a9fffc22ea6e6f7 +patch_filename = catch2_3.1.0-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/catch2_3.1.0-1/get_patch +patch_hash = 4ebf4277aed574a9912a79f4817a310d837798e099bbafa6097be23a7f5e3ae4 +wrapdb_version = 3.1.0-1 [provide] catch2 = catch2_dep - +catch2-with-main = catch2_with_main_dep From f330e5147293a2d57c9267982238d2b25dcedf45 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 20 Oct 2022 10:57:27 +0200 Subject: [PATCH 61/91] fix: typo --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 3c443a2e..8758c083 100644 --- a/meson.build +++ b/meson.build @@ -428,7 +428,7 @@ endif catch2 = dependency( 'catch2', - version: '>=3.0.0' + version: '>=3.0.0', fallback: ['catch2', 'catch2_dep'], required: get_option('tests'), ) From 527017bacafaee4dd4a07e89c80903858b8a1689 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 20 Oct 2022 11:05:19 +0200 Subject: [PATCH 62/91] chore: update date wrap --- subprojects/date.wrap | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/subprojects/date.wrap b/subprojects/date.wrap index 4d4067c9..d18c3ebf 100644 --- a/subprojects/date.wrap +++ b/subprojects/date.wrap @@ -1,9 +1,14 @@ [wrap-file] -source_url=https://github.com/HowardHinnant/date/archive/v3.0.0.tar.gz -source_filename=date-3.0.0.tar.gz -source_hash=87bba2eaf0ebc7ec539e5e62fc317cb80671a337c1fb1b84cb9e4d42c6dbebe3 -directory=date-3.0.0 +source_url = https://github.com/HowardHinnant/date/archive/v3.0.1.tar.gz +source_filename = date-3.0.1.tar.gz +source_hash = 7a390f200f0ccd207e8cff6757e04817c1a0aec3e327b006b7eb451c57ee3538 +directory = date-3.0.1 +patch_filename = hinnant-date_3.0.1-2_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/hinnant-date_3.0.1-2/get_patch +patch_hash = 11b715b792609117a63310eeefc2939cc2ca26ecd4e996108335e504db58a41d +wrapdb_version = 3.0.1-2 + +[provide] +tz = tz_dep +date = date_dep -patch_url = https://github.com/mesonbuild/hinnant-date/releases/download/3.0.0-1/hinnant-date.zip -patch_filename = hinnant-date-3.0.0-1-wrap.zip -patch_hash = 6ccaf70732d8bdbd1b6d5fdf3e1b935c23bf269bda12fdfd0e561276f63432fe From 1ceaff27c243dd254b08ff750f91a187574259ec Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Thu, 20 Oct 2022 12:38:52 +0200 Subject: [PATCH 63/91] Fixed gamemode module segfaulting when disconnecting monitor --- src/modules/gamemode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/gamemode.cpp b/src/modules/gamemode.cpp index c7accd58..7129297d 100644 --- a/src/modules/gamemode.cpp +++ b/src/modules/gamemode.cpp @@ -109,7 +109,7 @@ Gamemode::Gamemode(const std::string& id, const Json::Value& config) } Gamemode::~Gamemode() { - if (gamemode_proxy) gamemode_proxy->unreference(); + if (gamemode_proxy) gamemode_proxy.reset(); if (gamemodeWatcher_id > 0) { Gio::DBus::unwatch_name(gamemodeWatcher_id); gamemodeWatcher_id = 0; From 64849f52c97509295d2a84ba57259048caf28e9a Mon Sep 17 00:00:00 2001 From: Quantenzitrone Date: Sat, 22 Oct 2022 02:31:14 +0200 Subject: [PATCH 64/91] fixed memory module not rounding numbers --- src/modules/memory/common.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/memory/common.cpp b/src/modules/memory/common.cpp index 596659be..f8f469cf 100644 --- a/src/modules/memory/common.cpp +++ b/src/modules/memory/common.cpp @@ -31,17 +31,17 @@ auto waybar::modules::Memory::update() -> void { } if (memtotal > 0 && memfree >= 0) { - auto total_ram_gigabytes = memtotal / std::pow(1024, 2); - auto total_swap_gigabytes = swaptotal / std::pow(1024, 2); + float total_ram_gigabytes = 0.01*round(memtotal / 10485.76); // 100*10485.76 = 2^20 = 1024^2 = GiB/KiB + float total_swap_gigabytes = 0.01*round(swaptotal / 10485.76); int used_ram_percentage = 100 * (memtotal - memfree) / memtotal; int used_swap_percentage = 0; if (swaptotal && swapfree) { used_swap_percentage = 100 * (swaptotal - swapfree) / swaptotal; } - auto used_ram_gigabytes = (memtotal - memfree) / std::pow(1024, 2); - auto used_swap_gigabytes = (swaptotal - swapfree) / std::pow(1024, 2); - auto available_ram_gigabytes = memfree / std::pow(1024, 2); - auto available_swap_gigabytes = swapfree / std::pow(1024, 2); + float used_ram_gigabytes = 0.01*round((memtotal - memfree) / 10485.76); + float used_swap_gigabytes = 0.01*round((swaptotal - swapfree) / 10485.76); + float available_ram_gigabytes = 0.01*round(memfree / 10485.76); + float available_swap_gigabytes = 0.01*round(swapfree / 10485.76); auto format = format_; auto state = getState(used_ram_percentage); From ff61e7bf4e780b79e756f34e1192df5649396c1f Mon Sep 17 00:00:00 2001 From: bi4k8 Date: Tue, 25 Oct 2022 19:39:23 +0000 Subject: [PATCH 65/91] taskbar: implement drag-and-drop task reordering --- include/modules/wlr/taskbar.hpp | 9 ++++ src/modules/wlr/taskbar.cpp | 80 ++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/include/modules/wlr/taskbar.hpp b/include/modules/wlr/taskbar.hpp index 74b0109d..da1c93be 100644 --- a/include/modules/wlr/taskbar.hpp +++ b/include/modules/wlr/taskbar.hpp @@ -74,6 +74,10 @@ class Task { std::string app_id_; uint32_t state_ = 0; + int32_t drag_start_x; + int32_t drag_start_y; + int32_t drag_start_button = -1; + private: std::string repr() const; std::string state_string(bool = false) const; @@ -105,6 +109,11 @@ class Task { /* Callbacks for Gtk events */ bool handle_clicked(GdkEventButton *); + bool handle_button_release(GdkEventButton *); + bool handle_motion_notify(GdkEventMotion *); + void handle_drag_data_get(const Glib::RefPtr& context, Gtk::SelectionData& selection_data, guint info, guint time); + void handle_drag_data_received(const Glib::RefPtr& context, int x, int y, Gtk::SelectionData selection_data, guint info, guint time); + public: bool operator==(const Task &) const; diff --git a/src/modules/wlr/taskbar.cpp b/src/modules/wlr/taskbar.cpp index 156624d5..80290bd5 100644 --- a/src/modules/wlr/taskbar.cpp +++ b/src/modules/wlr/taskbar.cpp @@ -251,6 +251,10 @@ static const struct zwlr_foreign_toplevel_handle_v1_listener toplevel_handle_imp .parent = tl_handle_parent, }; +static const std::vector target_entries = { + Gtk::TargetEntry("WAYBAR_TOPLEVEL", Gtk::TARGET_SAME_APP, 0) +}; + Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar, struct zwlr_foreign_toplevel_handle_v1 *tl_handle, struct wl_seat *seat) : bar_{bar}, @@ -309,9 +313,19 @@ Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar, /* Handle click events if configured */ if (config_["on-click"].isString() || config_["on-click-middle"].isString() || config_["on-click-right"].isString()) { - button_.add_events(Gdk::BUTTON_PRESS_MASK); - button_.signal_button_press_event().connect(sigc::mem_fun(*this, &Task::handle_clicked), false); } + + button_.add_events(Gdk::BUTTON_PRESS_MASK); + button_.signal_button_press_event().connect(sigc::mem_fun(*this, &Task::handle_clicked), false); + button_.signal_button_release_event().connect(sigc::mem_fun(*this, &Task::handle_button_release), false); + + button_.signal_motion_notify_event().connect(sigc::mem_fun(*this, &Task::handle_motion_notify), false); + + button_.drag_source_set(target_entries, Gdk::BUTTON1_MASK, Gdk::ACTION_MOVE); + button_.drag_dest_set(target_entries, Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_MOVE); + + button_.signal_drag_data_get().connect(sigc::mem_fun(*this, &Task::handle_drag_data_get), false); + button_.signal_drag_data_received().connect(sigc::mem_fun(*this, &Task::handle_drag_data_received), false); } Task::~Task() { @@ -495,6 +509,14 @@ void Task::handle_closed() { } bool Task::handle_clicked(GdkEventButton *bt) { + /* filter out additional events for double/triple clicks */ + if (bt->type == GDK_BUTTON_PRESS) { + /* save where the button press ocurred in case it becomes a drag */ + drag_start_button = bt->button; + drag_start_x = bt->x; + drag_start_y = bt->y; + } + std::string action; if (config_["on-click"].isString() && bt->button == 1) action = config_["on-click"].asString(); @@ -528,6 +550,60 @@ bool Task::handle_clicked(GdkEventButton *bt) { return true; } +bool Task::handle_button_release(GdkEventButton *bt) { + drag_start_button = -1; + return false; +} + +bool Task::handle_motion_notify(GdkEventMotion *mn) { + if (drag_start_button == -1) + return false; + + if ( button_.drag_check_threshold(drag_start_x, drag_start_y, mn->x, mn->y)) { + /* start drag in addition to other assigned action */ + auto target_list = Gtk::TargetList::create(target_entries); + auto refptr = Glib::RefPtr(target_list); + auto drag_context = button_.drag_begin(refptr, Gdk::DragAction::ACTION_MOVE, drag_start_button, (GdkEvent*)mn); + } + + return false; +} + +void Task::handle_drag_data_get(const Glib::RefPtr& context, Gtk::SelectionData& selection_data, guint info, guint time) +{ + spdlog::debug("drag_data_get"); + void* button_addr = (void*)&this->button_; + + selection_data.set( + "WAYBAR_TOPLEVEL", + 32, + (const guchar *)&button_addr, + sizeof (gpointer)); +} + +void Task::handle_drag_data_received(const Glib::RefPtr& context, int x, int y, Gtk::SelectionData selection_data, guint info, guint time) +{ + spdlog::debug("drag_data_received"); + gpointer handle = *(gpointer*)selection_data.get_data(); + auto dragged_button = (Gtk::Button*)handle; + + if(dragged_button == &this->button_) + return; + + auto parent_of_dragged = dragged_button->get_parent(); + auto parent_of_dest = this->button_.get_parent(); + + if(parent_of_dragged != parent_of_dest) + return; + + auto box = (Gtk::Box*)parent_of_dragged; + + auto position_prop = box->child_property_position(this->button_); + auto position = position_prop.get_value(); + + box->reorder_child(*dragged_button, position); +} + bool Task::operator==(const Task &o) const { return o.id_ == id_; } bool Task::operator!=(const Task &o) const { return o.id_ != id_; } From 2d7e21ed7d3ec7557cfa35e91319d2d422fc6bd9 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 26 Oct 2022 17:26:15 +0200 Subject: [PATCH 66/91] fix: lint --- include/modules/wlr/taskbar.hpp | 7 ++--- src/modules/memory/common.cpp | 13 ++++----- src/modules/wlr/taskbar.cpp | 48 +++++++++++++++------------------ 3 files changed, 33 insertions(+), 35 deletions(-) diff --git a/include/modules/wlr/taskbar.hpp b/include/modules/wlr/taskbar.hpp index da1c93be..7a1f17a6 100644 --- a/include/modules/wlr/taskbar.hpp +++ b/include/modules/wlr/taskbar.hpp @@ -111,9 +111,10 @@ class Task { bool handle_clicked(GdkEventButton *); bool handle_button_release(GdkEventButton *); bool handle_motion_notify(GdkEventMotion *); - void handle_drag_data_get(const Glib::RefPtr& context, Gtk::SelectionData& selection_data, guint info, guint time); - void handle_drag_data_received(const Glib::RefPtr& context, int x, int y, Gtk::SelectionData selection_data, guint info, guint time); - + void handle_drag_data_get(const Glib::RefPtr &context, + Gtk::SelectionData &selection_data, guint info, guint time); + void handle_drag_data_received(const Glib::RefPtr &context, int x, int y, + Gtk::SelectionData selection_data, guint info, guint time); public: bool operator==(const Task &) const; diff --git a/src/modules/memory/common.cpp b/src/modules/memory/common.cpp index f8f469cf..8f190d2d 100644 --- a/src/modules/memory/common.cpp +++ b/src/modules/memory/common.cpp @@ -31,17 +31,18 @@ auto waybar::modules::Memory::update() -> void { } if (memtotal > 0 && memfree >= 0) { - float total_ram_gigabytes = 0.01*round(memtotal / 10485.76); // 100*10485.76 = 2^20 = 1024^2 = GiB/KiB - float total_swap_gigabytes = 0.01*round(swaptotal / 10485.76); + float total_ram_gigabytes = + 0.01 * round(memtotal / 10485.76); // 100*10485.76 = 2^20 = 1024^2 = GiB/KiB + float total_swap_gigabytes = 0.01 * round(swaptotal / 10485.76); int used_ram_percentage = 100 * (memtotal - memfree) / memtotal; int used_swap_percentage = 0; if (swaptotal && swapfree) { used_swap_percentage = 100 * (swaptotal - swapfree) / swaptotal; } - float used_ram_gigabytes = 0.01*round((memtotal - memfree) / 10485.76); - float used_swap_gigabytes = 0.01*round((swaptotal - swapfree) / 10485.76); - float available_ram_gigabytes = 0.01*round(memfree / 10485.76); - float available_swap_gigabytes = 0.01*round(swapfree / 10485.76); + float used_ram_gigabytes = 0.01 * round((memtotal - memfree) / 10485.76); + float used_swap_gigabytes = 0.01 * round((swaptotal - swapfree) / 10485.76); + float available_ram_gigabytes = 0.01 * round(memfree / 10485.76); + float available_swap_gigabytes = 0.01 * round(swapfree / 10485.76); auto format = format_; auto state = getState(used_ram_percentage); diff --git a/src/modules/wlr/taskbar.cpp b/src/modules/wlr/taskbar.cpp index 80290bd5..97d84bd0 100644 --- a/src/modules/wlr/taskbar.cpp +++ b/src/modules/wlr/taskbar.cpp @@ -252,8 +252,7 @@ static const struct zwlr_foreign_toplevel_handle_v1_listener toplevel_handle_imp }; static const std::vector target_entries = { - Gtk::TargetEntry("WAYBAR_TOPLEVEL", Gtk::TARGET_SAME_APP, 0) -}; + Gtk::TargetEntry("WAYBAR_TOPLEVEL", Gtk::TARGET_SAME_APP, 0)}; Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar, struct zwlr_foreign_toplevel_handle_v1 *tl_handle, struct wl_seat *seat) @@ -317,15 +316,18 @@ Task::Task(const waybar::Bar &bar, const Json::Value &config, Taskbar *tbar, button_.add_events(Gdk::BUTTON_PRESS_MASK); button_.signal_button_press_event().connect(sigc::mem_fun(*this, &Task::handle_clicked), false); - button_.signal_button_release_event().connect(sigc::mem_fun(*this, &Task::handle_button_release), false); + button_.signal_button_release_event().connect(sigc::mem_fun(*this, &Task::handle_button_release), + false); - button_.signal_motion_notify_event().connect(sigc::mem_fun(*this, &Task::handle_motion_notify), false); + button_.signal_motion_notify_event().connect(sigc::mem_fun(*this, &Task::handle_motion_notify), + false); button_.drag_source_set(target_entries, Gdk::BUTTON1_MASK, Gdk::ACTION_MOVE); button_.drag_dest_set(target_entries, Gtk::DEST_DEFAULT_ALL, Gdk::ACTION_MOVE); button_.signal_drag_data_get().connect(sigc::mem_fun(*this, &Task::handle_drag_data_get), false); - button_.signal_drag_data_received().connect(sigc::mem_fun(*this, &Task::handle_drag_data_received), false); + button_.signal_drag_data_received().connect( + sigc::mem_fun(*this, &Task::handle_drag_data_received), false); } Task::~Task() { @@ -556,47 +558,41 @@ bool Task::handle_button_release(GdkEventButton *bt) { } bool Task::handle_motion_notify(GdkEventMotion *mn) { - if (drag_start_button == -1) - return false; + if (drag_start_button == -1) return false; - if ( button_.drag_check_threshold(drag_start_x, drag_start_y, mn->x, mn->y)) { + if (button_.drag_check_threshold(drag_start_x, drag_start_y, mn->x, mn->y)) { /* start drag in addition to other assigned action */ auto target_list = Gtk::TargetList::create(target_entries); auto refptr = Glib::RefPtr(target_list); - auto drag_context = button_.drag_begin(refptr, Gdk::DragAction::ACTION_MOVE, drag_start_button, (GdkEvent*)mn); + auto drag_context = + button_.drag_begin(refptr, Gdk::DragAction::ACTION_MOVE, drag_start_button, (GdkEvent *)mn); } return false; } -void Task::handle_drag_data_get(const Glib::RefPtr& context, Gtk::SelectionData& selection_data, guint info, guint time) -{ +void Task::handle_drag_data_get(const Glib::RefPtr &context, + Gtk::SelectionData &selection_data, guint info, guint time) { spdlog::debug("drag_data_get"); - void* button_addr = (void*)&this->button_; + void *button_addr = (void *)&this->button_; - selection_data.set( - "WAYBAR_TOPLEVEL", - 32, - (const guchar *)&button_addr, - sizeof (gpointer)); + selection_data.set("WAYBAR_TOPLEVEL", 32, (const guchar *)&button_addr, sizeof(gpointer)); } -void Task::handle_drag_data_received(const Glib::RefPtr& context, int x, int y, Gtk::SelectionData selection_data, guint info, guint time) -{ +void Task::handle_drag_data_received(const Glib::RefPtr &context, int x, int y, + Gtk::SelectionData selection_data, guint info, guint time) { spdlog::debug("drag_data_received"); - gpointer handle = *(gpointer*)selection_data.get_data(); - auto dragged_button = (Gtk::Button*)handle; + gpointer handle = *(gpointer *)selection_data.get_data(); + auto dragged_button = (Gtk::Button *)handle; - if(dragged_button == &this->button_) - return; + if (dragged_button == &this->button_) return; auto parent_of_dragged = dragged_button->get_parent(); auto parent_of_dest = this->button_.get_parent(); - if(parent_of_dragged != parent_of_dest) - return; + if (parent_of_dragged != parent_of_dest) return; - auto box = (Gtk::Box*)parent_of_dragged; + auto box = (Gtk::Box *)parent_of_dragged; auto position_prop = box->child_property_position(this->button_); auto position = position_prop.get_value(); From be28ee3d7ec34d86265280f9fd82d5e984aeeb3c Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 27 Oct 2022 09:00:31 +0200 Subject: [PATCH 67/91] fix(#1707): hide module when no controller found --- src/modules/bluetooth.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index 6ceab785..3a24b0dc 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -101,6 +101,7 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& } else { spdlog::error("findCurController() failed: no bluetooth controller found"); } + event_box_.hide() return; } findConnectedDevices(cur_controller_.path, connected_devices_); From 2fec1d490782e5eb41de9d0be98f709fa6b2922c Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 27 Oct 2022 09:14:07 +0200 Subject: [PATCH 68/91] fix: typo --- src/modules/bluetooth.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index 3a24b0dc..a1233361 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -101,7 +101,7 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& } else { spdlog::error("findCurController() failed: no bluetooth controller found"); } - event_box_.hide() + event_box_.hide(); return; } findConnectedDevices(cur_controller_.path, connected_devices_); From c374c412d34101506c5901e38b1c3fe5d0791d53 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 27 Oct 2022 10:00:38 +0200 Subject: [PATCH 69/91] chore: remove unwanted file --- ext4fuse.rb | 57 ----------------------------------------------------- 1 file changed, 57 deletions(-) delete mode 100644 ext4fuse.rb diff --git a/ext4fuse.rb b/ext4fuse.rb deleted file mode 100644 index bc86f5fb..00000000 --- a/ext4fuse.rb +++ /dev/null @@ -1,57 +0,0 @@ -class MacFuseRequirement < Requirement - fatal true - - satisfy(build_env: false) { self.class.binary_mac_fuse_installed? } - - def self.binary_mac_fuse_installed? - File.exist?("/usr/local/include/fuse/fuse.h") && - !File.symlink?("/usr/local/include/fuse") - end - - env do - ENV.append_path "PKG_CONFIG_PATH", HOMEBREW_LIBRARY/"Homebrew/os/mac/pkgconfig/fuse" - ENV.append_path "PKG_CONFIG_PATH", "/usr/local/lib/pkgconfig" - - unless HOMEBREW_PREFIX.to_s == "/usr/local" - ENV.append_path "HOMEBREW_LIBRARY_PATHS", "/usr/local/lib" - ENV.append_path "HOMEBREW_INCLUDE_PATHS", "/usr/local/include/fuse" - end - end - - def message - "macFUSE is required. Please run `brew install --cask macfuse` first." - end -end - -class Ext4fuse < Formula - desc "Read-only implementation of ext4 for FUSE" - homepage "https://github.com/gerard/ext4fuse" - url "https://github.com/gerard/ext4fuse/archive/v0.1.3.tar.gz" - sha256 "550f1e152c4de7d4ea517ee1c708f57bfebb0856281c508511419db45aa3ca9f" - license "GPL-2.0" - head "https://github.com/gerard/ext4fuse.git" - - bottle do - sha256 cellar: :any, catalina: "446dde5e84b058966ead0cde5e38e9411f465732527f6decfa1c0dcdbd4abbef" - sha256 cellar: :any, mojave: "88c4918bf5218f99295e539fe4499152edb3b60b6659e44ddd68b22359f512ae" - sha256 cellar: :any, high_sierra: "fc69c8993afd0ffc16a73c9c036ca8f83c77ac2a19b3237f76f9ccee8b30bbc9" - sha256 cellar: :any, sierra: "fe8bbe7cd5362f00ff06ef750926bf349d60563c20b0ecf212778631c8912ba2" - sha256 cellar: :any, el_capitan: "291047c821b7b205d85be853fb005510c6ab01bd4c2a2193c192299b6f049d35" - sha256 cellar: :any, yosemite: "b11f564b7e7c08af0b0a3e9854973d39809bf2d8a56014f4882772b2f7307ac1" - end - - depends_on "pkg-config" => :build - - on_macos do - depends_on MacFuseRequirement => :build - end - - on_linux do - depends_on "libfuse" - end - - def install - system "make" - bin.install "ext4fuse" - end -end From a10266ceee8875643abeec0c6c556a62f43750ee Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 28 Oct 2022 14:35:18 +0200 Subject: [PATCH 70/91] fix: add power to tooltip format --- src/modules/battery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index fd1be357..fdd81b59 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -612,7 +612,7 @@ auto waybar::modules::Battery::update() -> void { tooltip_format = config_["tooltip-format"].asString(); } button_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("timeTo", tooltip_text_default), - fmt::arg("capacity", capacity), + fmt::arg("power", power), fmt::arg("capacity", capacity), fmt::arg("time", time_remaining_formatted))); } if (!old_status_.empty()) { From a4d27ea8067a1767dfe1cdc526f5170d515fe226 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 28 Oct 2022 14:44:04 +0200 Subject: [PATCH 71/91] fix: checking router id in handleEvent function --- src/modules/network.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/network.cpp b/src/modules/network.cpp index 953d4078..5f7534d3 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -646,7 +646,11 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) { if (has_gateway && !has_destination && temp_idx != -1) { // Check if this is the first default route we see, or if this new // route have a higher priority. - if (!is_del_event && ((net->ifid_ == -1) || (priority < net->route_priority))) { + /** Module doesn`t update state, because RTA_GATEWAY call before enable new router and set higher priority. + Disable router -> RTA_GATEWAY -> up new router -> set higher priority + added checking route id + **/ + if (!is_del_event && ((net->ifid_ == -1) || (priority < net->route_priority) || (net->ifid_ != temp_idx))) { // Clear if's state for the case were there is a higher priority // route on a different interface. net->clearIface(); From ebdf575d45c0e4f8c6f6ce484fbbf5375ed8dbba Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 28 Oct 2022 14:44:48 +0200 Subject: [PATCH 72/91] fix: lint --- src/modules/network.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/modules/network.cpp b/src/modules/network.cpp index 5f7534d3..c787d5bd 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -646,11 +646,12 @@ int waybar::modules::Network::handleEvents(struct nl_msg *msg, void *data) { if (has_gateway && !has_destination && temp_idx != -1) { // Check if this is the first default route we see, or if this new // route have a higher priority. - /** Module doesn`t update state, because RTA_GATEWAY call before enable new router and set higher priority. - Disable router -> RTA_GATEWAY -> up new router -> set higher priority - added checking route id + /** Module doesn`t update state, because RTA_GATEWAY call before enable new router and set + higher priority. Disable router -> RTA_GATEWAY -> up new router -> set higher priority added + checking route id **/ - if (!is_del_event && ((net->ifid_ == -1) || (priority < net->route_priority) || (net->ifid_ != temp_idx))) { + if (!is_del_event && + ((net->ifid_ == -1) || (priority < net->route_priority) || (net->ifid_ != temp_idx))) { // Clear if's state for the case were there is a higher priority // route on a different interface. net->clearIface(); From df36ac3408457a61320eed2e6720aa7026e4cb9b Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 2 Nov 2022 05:59:50 +0100 Subject: [PATCH 73/91] Revert "Escape text in custom module" --- src/modules/custom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/custom.cpp b/src/modules/custom.cpp index 1a64d2a3..397298b2 100644 --- a/src/modules/custom.cpp +++ b/src/modules/custom.cpp @@ -125,7 +125,7 @@ auto waybar::modules::Custom::update() -> void { } else { parseOutputRaw(); } - auto str = fmt::format(format_, Glib::Markup::escape_text(text_).raw(), fmt::arg("alt", alt_), + auto str = fmt::format(format_, text_, fmt::arg("alt", alt_), fmt::arg("icon", getIcon(percentage_, alt_)), fmt::arg("percentage", percentage_)); if (str.empty()) { From fd417c0805d5600fe7f18b8d4d584c9e56ca2e26 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 3 Nov 2022 09:43:05 +0100 Subject: [PATCH 74/91] chore: 0.9.15 --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 8758c083..071c400c 100644 --- a/meson.build +++ b/meson.build @@ -1,6 +1,6 @@ project( 'waybar', 'cpp', 'c', - version: '0.9.13', + version: '0.9.15', license: 'MIT', meson_version: '>= 0.49.0', default_options : [ From 73495df377ff898c7a983344fe1da89787f4ea96 Mon Sep 17 00:00:00 2001 From: Jan Palus Date: Thu, 3 Nov 2022 10:59:03 +0100 Subject: [PATCH 75/91] build: require jsoncpp >= 1.9.2 with #1719 Waybar started using Json::Value.as() available since jsoncpp 1.9.2. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 071c400c..6e5e19b8 100644 --- a/meson.build +++ b/meson.build @@ -87,7 +87,7 @@ wayland_protos = dependency('wayland-protocols') gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0']) dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk')) giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabled() or get_option('logind').enabled() or get_option('upower_glib').enabled())) -jsoncpp = dependency('jsoncpp') +jsoncpp = dependency('jsoncpp', version : ['>=1.9.2']) sigcpp = dependency('sigc++-2.0') libinotify = dependency('libinotify', required: false) libepoll = dependency('epoll-shim', required: false) From 3cf027fc567c343f5523b7b08476a467d5248b37 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 3 Nov 2022 14:04:29 +0100 Subject: [PATCH 76/91] fix: button default style --- src/AButton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AButton.cpp b/src/AButton.cpp index 2952b0d8..103cf6c4 100644 --- a/src/AButton.cpp +++ b/src/AButton.cpp @@ -21,7 +21,7 @@ AButton::AButton(const Json::Value& config, const std::string& name, const std:: /* https://github.com/Alexays/Waybar/issues/1731 */ auto css = Gtk::CssProvider::create(); - css->load_from_data("button { min-width: 0; }"); + css->load_from_data("button { all: unset; min-width: 0; }"); button_.get_style_context()->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_USER); if (!id.empty()) { From eb705533b55e07664a0b47b6814ad8f980766d1f Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 3 Nov 2022 14:08:22 +0100 Subject: [PATCH 77/91] feat: jsoncpp wrap --- meson.build | 2 +- subprojects/jsoncpp.wrap | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 subprojects/jsoncpp.wrap diff --git a/meson.build b/meson.build index 6e5e19b8..355a3c06 100644 --- a/meson.build +++ b/meson.build @@ -87,7 +87,7 @@ wayland_protos = dependency('wayland-protocols') gtkmm = dependency('gtkmm-3.0', version : ['>=3.22.0']) dbusmenu_gtk = dependency('dbusmenu-gtk3-0.4', required: get_option('dbusmenu-gtk')) giounix = dependency('gio-unix-2.0', required: (get_option('dbusmenu-gtk').enabled() or get_option('logind').enabled() or get_option('upower_glib').enabled())) -jsoncpp = dependency('jsoncpp', version : ['>=1.9.2']) +jsoncpp = dependency('jsoncpp', version : ['>=1.9.2'], fallback : ['jsoncpp', 'jsoncpp_dep']) sigcpp = dependency('sigc++-2.0') libinotify = dependency('libinotify', required: false) libepoll = dependency('epoll-shim', required: false) diff --git a/subprojects/jsoncpp.wrap b/subprojects/jsoncpp.wrap new file mode 100644 index 00000000..ee3eb2e1 --- /dev/null +++ b/subprojects/jsoncpp.wrap @@ -0,0 +1,9 @@ +[wrap-file] +directory = jsoncpp-1.9.5 +source_url = https://github.com/open-source-parsers/jsoncpp/archive/1.9.5.tar.gz +source_filename = jsoncpp-1.9.5.tar.gz +source_hash = f409856e5920c18d0c2fb85276e24ee607d2a09b5e7d5f0a371368903c275da2 + +[provide] +jsoncpp = jsoncpp_dep + From d48eebd4d3d92d7a8f39cf28574dd8543c105b8a Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 3 Nov 2022 14:10:18 +0100 Subject: [PATCH 78/91] fix: use GTK_STYLE_PROVIDER_PRIORITY_APPLICATION --- src/AButton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AButton.cpp b/src/AButton.cpp index 103cf6c4..021ad972 100644 --- a/src/AButton.cpp +++ b/src/AButton.cpp @@ -22,7 +22,7 @@ AButton::AButton(const Json::Value& config, const std::string& name, const std:: /* https://github.com/Alexays/Waybar/issues/1731 */ auto css = Gtk::CssProvider::create(); css->load_from_data("button { all: unset; min-width: 0; }"); - button_.get_style_context()->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_USER); + button_.get_style_context()->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); if (!id.empty()) { button_.get_style_context()->add_class(id); From 92cc01f40149292d315456f7e5bbdad6dc099caf Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 3 Nov 2022 15:53:45 +0100 Subject: [PATCH 79/91] fix: label default style --- src/AButton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AButton.cpp b/src/AButton.cpp index 021ad972..78d5d422 100644 --- a/src/AButton.cpp +++ b/src/AButton.cpp @@ -21,7 +21,7 @@ AButton::AButton(const Json::Value& config, const std::string& name, const std:: /* https://github.com/Alexays/Waybar/issues/1731 */ auto css = Gtk::CssProvider::create(); - css->load_from_data("button { all: unset; min-width: 0; }"); + css->load_from_data("button { all: unset; min-width: 0; } label { all: unset; }"); button_.get_style_context()->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); if (!id.empty()) { From 3030850b225863d2433590a796aa043d382df810 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 4 Nov 2022 08:39:59 +0100 Subject: [PATCH 80/91] refactor: inherit disabled button --- src/AButton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AButton.cpp b/src/AButton.cpp index 78d5d422..caf34d95 100644 --- a/src/AButton.cpp +++ b/src/AButton.cpp @@ -21,7 +21,7 @@ AButton::AButton(const Json::Value& config, const std::string& name, const std:: /* https://github.com/Alexays/Waybar/issues/1731 */ auto css = Gtk::CssProvider::create(); - css->load_from_data("button { all: unset; min-width: 0; } label { all: unset; }"); + css->load_from_data("button { all: unset; min-width: 0; } label:disabled,button:disabled { all: inherit; } label { all: unset; }"); button_.get_style_context()->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); if (!id.empty()) { From 0e53c37d6bd58ded1e2551af21ff9e23b51edf98 Mon Sep 17 00:00:00 2001 From: Birger Schacht Date: Fri, 4 Nov 2022 15:03:10 +0100 Subject: [PATCH 81/91] Fix typos in manual pages --- man/waybar-bluetooth.5.scd | 2 +- man/waybar-gamemode.5.scd | 2 +- man/waybar-inhibitor.5.scd | 2 +- man/waybar-upower.5.scd | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/man/waybar-bluetooth.5.scd b/man/waybar-bluetooth.5.scd index fd01dd97..6a5e71a7 100644 --- a/man/waybar-bluetooth.5.scd +++ b/man/waybar-bluetooth.5.scd @@ -137,7 +137,7 @@ Addressed by *bluetooth* *{device_alias}*: Alias of the displayed device. -*{device_enumerate}*: Show a list of all connected devices, each on a seperate line. Define the format of each device with the *tooltip-format-enumerate-connected* ++ +*{device_enumerate}*: Show a list of all connected devices, each on a separate line. Define the format of each device with the *tooltip-format-enumerate-connected* ++ and/or *tooltip-format-enumerate-connected-battery* config options. Can only be used in the tooltip related format options. # EXPERIMENTAL BATTERY PERCENTAGE FEATURE diff --git a/man/waybar-gamemode.5.scd b/man/waybar-gamemode.5.scd index f7847bd9..257c9c91 100644 --- a/man/waybar-gamemode.5.scd +++ b/man/waybar-gamemode.5.scd @@ -23,7 +23,7 @@ Feral Gamemode optimizations. *tooltip*: ++ typeof: bool ++ - defualt: true ++ + default: true ++ Option to disable tooltip on hover. *tooltip-format*: ++ diff --git a/man/waybar-inhibitor.5.scd b/man/waybar-inhibitor.5.scd index 0838f4d6..10d41bd5 100644 --- a/man/waybar-inhibitor.5.scd +++ b/man/waybar-inhibitor.5.scd @@ -6,7 +6,7 @@ waybar - inhibitor module # DESCRIPTION -The *inhibitor* module allows to take an inhibitor lock that logind provides. +The *inhibitor* module allows one to take an inhibitor lock that logind provides. See *systemd-inhibit*(1) for more information. # CONFIGURATION diff --git a/man/waybar-upower.5.scd b/man/waybar-upower.5.scd index 99c015a5..dae974dd 100644 --- a/man/waybar-upower.5.scd +++ b/man/waybar-upower.5.scd @@ -33,7 +33,7 @@ compatible devices in the tooltip. *tooltip*: ++ typeof: bool ++ - defualt: true ++ + default: true ++ Option to disable tooltip on hover. *tooltip-spacing*: ++ From 6477e539d0da791c7248f7d2a06bc8a8aafd023e Mon Sep 17 00:00:00 2001 From: Eric L Date: Fri, 4 Nov 2022 19:38:05 +0000 Subject: [PATCH 82/91] Battery: Plugged status has higher priority --- src/modules/battery.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index fdd81b59..55760540 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -470,7 +470,9 @@ const std::tuple waybar::modules::Battery::g } } - if (!adapter_.empty() && status == "Discharging") { + // Give `Plugged` higher priority over `Not charging`. + // So in a setting where TLP is used, `Plugged` is shown when the threshold is reached + if (!adapter_.empty() && (status == "Discharging" || status == "Not charging")) { bool online; std::string current_status; std::ifstream(adapter_ / "online") >> online; From cf5877073a979d7997ad72b9b3c8a4423f4f6f14 Mon Sep 17 00:00:00 2001 From: Sefa Eyeoglu Date: Sat, 5 Nov 2022 20:20:28 +0100 Subject: [PATCH 83/91] fix: don't escape mpd label twice Signed-off-by: Sefa Eyeoglu --- src/modules/mpd/mpd.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/modules/mpd/mpd.cpp b/src/modules/mpd/mpd.cpp index 7566284f..04d7a46d 100644 --- a/src/modules/mpd/mpd.cpp +++ b/src/modules/mpd/mpd.cpp @@ -170,16 +170,14 @@ void waybar::modules::MPD::setLabel() { try { label_->set_markup(fmt::format( - format, fmt::arg("artist", Glib::Markup::escape_text(artist).raw()), - fmt::arg("albumArtist", Glib::Markup::escape_text(album_artist).raw()), - fmt::arg("album", Glib::Markup::escape_text(album).raw()), - fmt::arg("title", Glib::Markup::escape_text(title).raw()), - fmt::arg("date", Glib::Markup::escape_text(date).raw()), fmt::arg("volume", volume), - fmt::arg("elapsedTime", elapsedTime), fmt::arg("totalTime", totalTime), - fmt::arg("songPosition", song_pos), fmt::arg("queueLength", queue_length), - fmt::arg("stateIcon", stateIcon), fmt::arg("consumeIcon", consumeIcon), - fmt::arg("randomIcon", randomIcon), fmt::arg("repeatIcon", repeatIcon), - fmt::arg("singleIcon", singleIcon), fmt::arg("filename", filename))); + format, fmt::arg("artist", artist.raw()), fmt::arg("albumArtist", album_artist.raw()), + fmt::arg("album", album.raw()), fmt::arg("title", title.raw()), fmt::arg("date", date), + fmt::arg("volume", volume), fmt::arg("elapsedTime", elapsedTime), + fmt::arg("totalTime", totalTime), fmt::arg("songPosition", song_pos), + fmt::arg("queueLength", queue_length), fmt::arg("stateIcon", stateIcon), + fmt::arg("consumeIcon", consumeIcon), fmt::arg("randomIcon", randomIcon), + fmt::arg("repeatIcon", repeatIcon), fmt::arg("singleIcon", singleIcon), + fmt::arg("filename", filename))); } catch (fmt::format_error const& e) { spdlog::warn("mpd: format error: {}", e.what()); } From 51e6fc62507dc95d3844693adf9ffac4dedfe214 Mon Sep 17 00:00:00 2001 From: Kelsey Judson Date: Mon, 7 Nov 2022 20:30:01 +1300 Subject: [PATCH 84/91] Fix states documentation --- man/waybar-backlight.5.scd | 4 ++-- man/waybar-battery.5.scd | 2 +- man/waybar-cpu.5.scd | 2 +- man/waybar-disk.5.scd | 2 +- man/waybar-memory.5.scd | 2 +- man/waybar-pulseaudio.5.scd | 4 ++-- man/waybar-states.5.scd | 11 +++++------ 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/man/waybar-backlight.5.scd b/man/waybar-backlight.5.scd index d14e4f24..9c8ba791 100644 --- a/man/waybar-backlight.5.scd +++ b/man/waybar-backlight.5.scd @@ -37,8 +37,8 @@ The *backlight* module displays the current backlight level. Positive value to rotate the text label. *states*: ++ - typeof: array ++ - A number of backlight states which get activated on certain brightness levels. + typeof: object ++ + A number of backlight states which get activated on certain brightness levels. See *waybar-states(5)*. *on-click*: ++ typeof: string ++ diff --git a/man/waybar-battery.5.scd b/man/waybar-battery.5.scd index 1ddd4d6d..fabde59a 100644 --- a/man/waybar-battery.5.scd +++ b/man/waybar-battery.5.scd @@ -33,7 +33,7 @@ The *battery* module displays the current capacity and state (eg. charging) of y The interval in which the information gets polled. *states*: ++ - typeof: array ++ + typeof: object ++ A number of battery states which get activated on certain capacity levels. See *waybar-states(5)*. *format*: ++ diff --git a/man/waybar-cpu.5.scd b/man/waybar-cpu.5.scd index 2e0d6c71..e3545536 100644 --- a/man/waybar-cpu.5.scd +++ b/man/waybar-cpu.5.scd @@ -42,7 +42,7 @@ The *cpu* module displays the current cpu utilization. Positive value to rotate the text label. *states*: ++ - typeof: array ++ + typeof: object ++ A number of cpu usage states which get activated on certain usage levels. See *waybar-states(5)*. *on-click*: ++ diff --git a/man/waybar-disk.5.scd b/man/waybar-disk.5.scd index 58797141..586c9dbd 100644 --- a/man/waybar-disk.5.scd +++ b/man/waybar-disk.5.scd @@ -32,7 +32,7 @@ Addressed by *disk* Positive value to rotate the text label. *states*: ++ - typeof: array ++ + typeof: object ++ A number of disk utilization states which get activated on certain percentage thresholds (percentage_used). See *waybar-states(5)*. *max-length*: ++ diff --git a/man/waybar-memory.5.scd b/man/waybar-memory.5.scd index d960ffd2..34e342f3 100644 --- a/man/waybar-memory.5.scd +++ b/man/waybar-memory.5.scd @@ -32,7 +32,7 @@ Addressed by *memory* Positive value to rotate the text label. *states*: ++ - typeof: array ++ + typeof: object ++ A number of memory utilization states which get activated on certain percentage thresholds. See *waybar-states(5)*. *max-length*: ++ diff --git a/man/waybar-pulseaudio.5.scd b/man/waybar-pulseaudio.5.scd index e3f9045f..b941c22c 100644 --- a/man/waybar-pulseaudio.5.scd +++ b/man/waybar-pulseaudio.5.scd @@ -43,8 +43,8 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu Positive value to rotate the text label. *states*: ++ - typeof: array ++ - A number of volume states which get activated on certain volume levels. See *waybar-states(5)* + typeof: object ++ + A number of volume states which get activated on certain volume levels. See *waybar-states(5)*. *max-length*: ++ typeof: integer ++ diff --git a/man/waybar-states.5.scd b/man/waybar-states.5.scd index ae2df1b9..c1b78391 100644 --- a/man/waybar-states.5.scd +++ b/man/waybar-states.5.scd @@ -7,14 +7,13 @@ apply a class when the value matches the declared state value. # STATES -- Every entry (*state*) consists of a ** (typeof: *string*) and a ** (typeof: *integer*). +Every entry (*state*) consists of a ** (typeof: *string*) and a ** (typeof: *integer*). - - The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the ** of the state. - Each class gets activated when the current capacity is equal or below the configured **. +- The state can be addressed as a CSS class in the *style.css*. The name of the CSS class is the ** of the state. + Each class gets activated when the current value is equal to or less than the configured ** for the *battery* module, or equal to or greater than the configured ** for all other modules. - - Also each state can have its own *format*. - Those can be configured via *format-*. - Or if you want to differentiate a bit more even as *format--*. +- Also, each state can have its own *format*. + Those can be configured via *format-*, or if you want to differentiate a bit more, as *format--*. # EXAMPLE From 253222d31cea3a49baf8fb60ad928308d6b9f19e Mon Sep 17 00:00:00 2001 From: Kelsey Judson Date: Mon, 7 Nov 2022 21:06:16 +1300 Subject: [PATCH 85/91] Make backlight module respect format- config --- src/modules/backlight.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/modules/backlight.cpp b/src/modules/backlight.cpp index 12ae0488..276fbd4c 100644 --- a/src/modules/backlight.cpp +++ b/src/modules/backlight.cpp @@ -174,9 +174,20 @@ auto waybar::modules::Backlight::update() -> void { const uint8_t percent = best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max()); - label_->set_markup(fmt::format(format_, fmt::arg("percent", std::to_string(percent)), - fmt::arg("icon", getIcon(percent)))); - getState(percent); + + auto format = format_; + auto state = getState(percent); + if (!state.empty() && config_["format-" + state].isString()) { + format = config_["format-" + state].asString(); + } + + if (format.empty()) { + event_box_.hide(); + } else { + event_box_.show(); + label_->set_markup(fmt::format(format, fmt::arg("percent", std::to_string(percent)), + fmt::arg("icon", getIcon(percent)))); + } } else { if (!previous_best_.has_value()) { return; From d2b22c6ec5921d3f24e1a9969f16fe7a1b4499e9 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 7 Nov 2022 09:23:47 +0100 Subject: [PATCH 86/91] fix: lint --- src/AButton.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/AButton.cpp b/src/AButton.cpp index caf34d95..3457bcfa 100644 --- a/src/AButton.cpp +++ b/src/AButton.cpp @@ -21,7 +21,9 @@ AButton::AButton(const Json::Value& config, const std::string& name, const std:: /* https://github.com/Alexays/Waybar/issues/1731 */ auto css = Gtk::CssProvider::create(); - css->load_from_data("button { all: unset; min-width: 0; } label:disabled,button:disabled { all: inherit; } label { all: unset; }"); + css->load_from_data( + "button { all: unset; min-width: 0; } label:disabled,button:disabled { all: inherit; } label " + "{ all: unset; }"); button_.get_style_context()->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); if (!id.empty()) { From d02e23c7591e4b30160aa24fe58ca827dc544f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Baltaz=C3=A1r=20Radics?= Date: Tue, 18 Oct 2022 23:43:15 +0200 Subject: [PATCH 87/91] feat(backlight): hide if the display is powered off --- include/modules/backlight.hpp | 5 ++++- src/modules/backlight.cpp | 35 +++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/include/modules/backlight.hpp b/include/modules/backlight.hpp index 4f60d6ec..90567716 100644 --- a/include/modules/backlight.hpp +++ b/include/modules/backlight.hpp @@ -18,12 +18,14 @@ class Backlight : public AButton { class BacklightDev { public: BacklightDev() = default; - BacklightDev(std::string name, int actual, int max); + BacklightDev(std::string name, int actual, int max, bool powered); std::string_view name() const; int get_actual() const; void set_actual(int actual); int get_max() const; void set_max(int max); + bool get_powered() const; + void set_powered(bool powered); friend inline bool operator==(const BacklightDev &lhs, const BacklightDev &rhs) { return lhs.name_ == rhs.name_ && lhs.actual_ == rhs.actual_ && lhs.max_ == rhs.max_; } @@ -32,6 +34,7 @@ class Backlight : public AButton { std::string name_; int actual_ = 1; int max_ = 1; + bool powered_ = true; }; public: diff --git a/src/modules/backlight.cpp b/src/modules/backlight.cpp index 276fbd4c..216ef232 100644 --- a/src/modules/backlight.cpp +++ b/src/modules/backlight.cpp @@ -73,8 +73,8 @@ void check_nn(const void *ptr, const char *message = "ptr was null") { } } // namespace -waybar::modules::Backlight::BacklightDev::BacklightDev(std::string name, int actual, int max) - : name_(std::move(name)), actual_(actual), max_(max) {} +waybar::modules::Backlight::BacklightDev::BacklightDev(std::string name, int actual, int max, bool powered) + : name_(std::move(name)), actual_(actual), max_(max), powered_(powered) {} std::string_view waybar::modules::Backlight::BacklightDev::name() const { return name_; } @@ -86,6 +86,10 @@ int waybar::modules::Backlight::BacklightDev::get_max() const { return max_; } void waybar::modules::Backlight::BacklightDev::set_max(int max) { max_ = max; } +bool waybar::modules::Backlight::BacklightDev::get_powered() const { return powered_; } + +void waybar::modules::Backlight::BacklightDev::set_powered(bool powered) { powered_ = powered; } + waybar::modules::Backlight::Backlight(const std::string &id, const Json::Value &config) : AButton(config, "backlight", id, "{percent}%", 2), preferred_device_(config["device"].isString() ? config["device"].asString() : "") { @@ -172,21 +176,15 @@ auto waybar::modules::Backlight::update() -> void { return; } - const uint8_t percent = - best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max()); - - auto format = format_; - auto state = getState(percent); - if (!state.empty() && config_["format-" + state].isString()) { - format = config_["format-" + state].asString(); - } - - if (format.empty()) { - event_box_.hide(); - } else { + if (best->get_powered()) { event_box_.show(); - label_->set_markup(fmt::format(format, fmt::arg("percent", std::to_string(percent)), + const uint8_t percent = + best->get_max() == 0 ? 100 : round(best->get_actual() * 100.0f / best->get_max()); + label_->set_markup(fmt::format(format_, fmt::arg("percent", std::to_string(percent)), fmt::arg("icon", getIcon(percent)))); + getState(percent); + } else { + event_box_.hide(); } } else { if (!previous_best_.has_value()) { @@ -226,6 +224,7 @@ void waybar::modules::Backlight::upsert_device(ForwardIt first, ForwardIt last, const char *actual = udev_device_get_sysattr_value(dev, actual_brightness_attr); const char *max = udev_device_get_sysattr_value(dev, "max_brightness"); + const char *power = udev_device_get_sysattr_value(dev, "bl_power"); auto found = std::find_if(first, last, [name](const auto &device) { return device.name() == name; }); @@ -236,10 +235,14 @@ void waybar::modules::Backlight::upsert_device(ForwardIt first, ForwardIt last, if (max != nullptr) { found->set_max(std::stoi(max)); } + if (power != nullptr) { + found->set_powered(std::stoi(power) == 0); + } } else { const int actual_int = actual == nullptr ? 0 : std::stoi(actual); const int max_int = max == nullptr ? 0 : std::stoi(max); - *inserter = BacklightDev{name, actual_int, max_int}; + const bool power_bool = power == nullptr ? true : std::stoi(power) == 0; + *inserter = BacklightDev{name, actual_int, max_int, power_bool}; ++inserter; } } From 8f4f67f69f86cda49c2034d846480c4f14391456 Mon Sep 17 00:00:00 2001 From: Jef Steelant Date: Wed, 9 Nov 2022 09:34:19 +0100 Subject: [PATCH 88/91] Do not crash when a monitor is removed --- include/modules/hyprland/backend.hpp | 14 ++++++++++--- include/modules/hyprland/language.hpp | 5 +++-- include/modules/hyprland/window.hpp | 7 ++++--- src/modules/hyprland/backend.cpp | 30 +++++++++++++++++++++++---- src/modules/hyprland/language.cpp | 8 ++++++- src/modules/hyprland/window.cpp | 14 ++++++++++--- 6 files changed, 62 insertions(+), 16 deletions(-) diff --git a/include/modules/hyprland/backend.hpp b/include/modules/hyprland/backend.hpp index 51cbd8f1..9401bf5a 100644 --- a/include/modules/hyprland/backend.hpp +++ b/include/modules/hyprland/backend.hpp @@ -1,5 +1,5 @@ #pragma once -#include +#include #include #include #include @@ -7,11 +7,19 @@ #include namespace waybar::modules::hyprland { + +class EventHandler { +public: + virtual void onEvent(const std::string& ev) = 0; + virtual ~EventHandler() = default; +}; + class IPC { public: IPC() { startIPC(); } - void registerForIPC(const std::string&, std::function); + void registerForIPC(const std::string&, EventHandler*); + void unregisterForIPC(EventHandler*); std::string getSocket1Reply(const std::string& rq); @@ -20,7 +28,7 @@ class IPC { void parseIPC(const std::string&); std::mutex callbackMutex; - std::deque>> callbacks; + std::list> callbacks; }; inline std::unique_ptr gIPC; diff --git a/include/modules/hyprland/language.hpp b/include/modules/hyprland/language.hpp index bdf24ec3..04fe3825 100644 --- a/include/modules/hyprland/language.hpp +++ b/include/modules/hyprland/language.hpp @@ -7,10 +7,11 @@ namespace waybar::modules::hyprland { -class Language : public waybar::AButton { +class Language : public waybar::AButton, +public EventHandler { public: Language(const std::string&, const waybar::Bar&, const Json::Value&); - ~Language() = default; + ~Language(); auto update() -> void; diff --git a/include/modules/hyprland/window.hpp b/include/modules/hyprland/window.hpp index 1423aece..4b697cf3 100644 --- a/include/modules/hyprland/window.hpp +++ b/include/modules/hyprland/window.hpp @@ -9,10 +9,11 @@ namespace waybar::modules::hyprland { -class Window : public waybar::ALabel { +class Window : public waybar::ALabel, + public EventHandler { public: Window(const std::string&, const waybar::Bar&, const Json::Value&); - ~Window() = default; + ~Window(); auto update() -> void; @@ -28,4 +29,4 @@ class Window : public waybar::ALabel { std::string lastView; }; -} // namespace waybar::modules::hyprland \ No newline at end of file +} // namespace waybar::modules::hyprland diff --git a/src/modules/hyprland/backend.cpp b/src/modules/hyprland/backend.cpp index ae73a252..7b9e5737 100644 --- a/src/modules/hyprland/backend.cpp +++ b/src/modules/hyprland/backend.cpp @@ -95,15 +95,37 @@ void IPC::parseIPC(const std::string& ev) { for (auto& [eventname, handler] : callbacks) { if (eventname == request) { - handler(ev); + handler->onEvent(ev); } } } -void IPC::registerForIPC(const std::string& ev, std::function fn) { +void IPC::registerForIPC(const std::string& ev, EventHandler* ev_handler) { + if (!ev_handler) { + return; + } callbackMutex.lock(); - callbacks.emplace_back(std::make_pair(ev, fn)); + callbacks.emplace_back(std::make_pair(ev, ev_handler)); + + callbackMutex.unlock(); +} + +void IPC::unregisterForIPC(EventHandler* ev_handler) { + if (!ev_handler) { + return; + } + + callbackMutex.lock(); + + for(auto it = callbacks.begin(); it != callbacks.end(); ) { + auto it_current = it; + it++; + auto& [eventname, handler] = *it_current; + if (handler == ev_handler) { + callbacks.erase(it_current); + } + } callbackMutex.unlock(); } @@ -168,4 +190,4 @@ std::string IPC::getSocket1Reply(const std::string& rq) { return std::string(buffer); } -} // namespace waybar::modules::hyprland \ No newline at end of file +} // namespace waybar::modules::hyprland diff --git a/src/modules/hyprland/language.cpp b/src/modules/hyprland/language.cpp index 65833436..b6d7c0fa 100644 --- a/src/modules/hyprland/language.cpp +++ b/src/modules/hyprland/language.cpp @@ -25,7 +25,13 @@ Language::Language(const std::string& id, const Bar& bar, const Json::Value& con AButton::update(); // register for hyprland ipc - gIPC->registerForIPC("activelayout", [&](const std::string& ev) { this->onEvent(ev); }); + gIPC->registerForIPC("activelayout", this); +} + +Language::~Language() { + gIPC->unregisterForIPC(this); + // wait for possible event handler to finish + std::lock_guard lg(mutex_); } auto Language::update() -> void { diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index d942cf68..3ab2b01d 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -25,7 +25,13 @@ Window::Window(const std::string& id, const Bar& bar, const Json::Value& config) ALabel::update(); // register for hyprland ipc - gIPC->registerForIPC("activewindow", [&](const std::string& ev) { this->onEvent(ev); }); + gIPC->registerForIPC("activewindow", this); +} + +Window::~Window() { + gIPC->unregisterForIPC(this); + // wait for possible event handler to finish + std::lock_guard lg(mutex_); } auto Window::update() -> void { @@ -50,7 +56,9 @@ uint Window::getActiveWorkspaceID(std::string monitorName) { assert(json.isArray()); auto monitor = std::find_if(json.begin(), json.end(), [&](Json::Value monitor) { return monitor["name"] == monitorName; }); - assert(monitor != std::end(json)); + if(monitor == std::end(json)) { + return 0; + } return (*monitor)["activeWorkspace"]["id"].as(); } @@ -89,4 +97,4 @@ void Window::onEvent(const std::string& ev) { dp.emit(); } -} // namespace waybar::modules::hyprland \ No newline at end of file +} // namespace waybar::modules::hyprland From 9f0a14c22baffd9a5ab30d458d2a1fb19fd88449 Mon Sep 17 00:00:00 2001 From: Jef Steelant Date: Thu, 10 Nov 2022 09:19:49 +0100 Subject: [PATCH 89/91] make linter happy --- src/modules/backlight.cpp | 3 ++- src/modules/hyprland/backend.cpp | 4 ++-- src/modules/hyprland/window.cpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/modules/backlight.cpp b/src/modules/backlight.cpp index 216ef232..a3c612ca 100644 --- a/src/modules/backlight.cpp +++ b/src/modules/backlight.cpp @@ -73,7 +73,8 @@ void check_nn(const void *ptr, const char *message = "ptr was null") { } } // namespace -waybar::modules::Backlight::BacklightDev::BacklightDev(std::string name, int actual, int max, bool powered) +waybar::modules::Backlight::BacklightDev::BacklightDev(std::string name, int actual, int max, + bool powered) : name_(std::move(name)), actual_(actual), max_(max), powered_(powered) {} std::string_view waybar::modules::Backlight::BacklightDev::name() const { return name_; } diff --git a/src/modules/hyprland/backend.cpp b/src/modules/hyprland/backend.cpp index 7b9e5737..76c071c0 100644 --- a/src/modules/hyprland/backend.cpp +++ b/src/modules/hyprland/backend.cpp @@ -112,13 +112,13 @@ void IPC::registerForIPC(const std::string& ev, EventHandler* ev_handler) { } void IPC::unregisterForIPC(EventHandler* ev_handler) { - if (!ev_handler) { + if (!ev_handler) { return; } callbackMutex.lock(); - for(auto it = callbacks.begin(); it != callbacks.end(); ) { + for (auto it = callbacks.begin(); it != callbacks.end();) { auto it_current = it; it++; auto& [eventname, handler] = *it_current; diff --git a/src/modules/hyprland/window.cpp b/src/modules/hyprland/window.cpp index 3ab2b01d..c3bebe49 100644 --- a/src/modules/hyprland/window.cpp +++ b/src/modules/hyprland/window.cpp @@ -56,7 +56,7 @@ uint Window::getActiveWorkspaceID(std::string monitorName) { assert(json.isArray()); auto monitor = std::find_if(json.begin(), json.end(), [&](Json::Value monitor) { return monitor["name"] == monitorName; }); - if(monitor == std::end(json)) { + if (monitor == std::end(json)) { return 0; } return (*monitor)["activeWorkspace"]["id"].as(); From 454ba610f45cc53347fe71f7cbe50137d51e4b51 Mon Sep 17 00:00:00 2001 From: Dordovel Date: Fri, 11 Nov 2022 15:15:12 +0300 Subject: [PATCH 90/91] clicking on the user label opens the default file manager --- include/modules/user.hpp | 8 +++++--- src/modules/user.cpp | 24 ++++++++++++++++++++---- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/include/modules/user.hpp b/include/modules/user.hpp index 41e7884e..38b09c41 100644 --- a/include/modules/user.hpp +++ b/include/modules/user.hpp @@ -22,10 +22,12 @@ class User : public AIconLabel { static constexpr inline int defaultUserImageWidth_ = 20; static constexpr inline int defaultUserImageHeight_ = 20; + bool signal_label(GdkEventButton* button) const; + long uptime_as_seconds(); - std::string get_user_login(); - std::string get_user_home_dir(); - std::string get_default_user_avatar_path(); + std::string get_user_login() const; + std::string get_user_home_dir() const; + std::string get_default_user_avatar_path() const; void init_default_user_avatar(int width, int height); void init_user_avatar(const std::string& path, int width, int height); void init_avatar(const Json::Value& config); diff --git a/src/modules/user.cpp b/src/modules/user.cpp index 88da0a45..7e3223c9 100644 --- a/src/modules/user.cpp +++ b/src/modules/user.cpp @@ -6,7 +6,11 @@ #include #include -#include + +#include "gdkmm/event.h" +#include "gdkmm/types.h" +#include "sigc++/functors/mem_fun.h" +#include "sigc++/functors/ptr_fun.h" #if HAVE_CPU_LINUX #include @@ -16,6 +20,8 @@ #include #endif +#define LEFT_MOUSE_BUTTON 1 + namespace waybar::modules { User::User(const std::string& id, const Json::Value& config) : AIconLabel(config, "user", id, "{user} {work_H}:{work_M}", 60, false, false, true) { @@ -23,6 +29,16 @@ User::User(const std::string& id, const Json::Value& config) this->init_avatar(AIconLabel::config_); } this->init_update_worker(); + AModule::event_box_.signal_button_press_event().connect(sigc::mem_fun(this, &User::signal_label)); +} + +bool User::signal_label(GdkEventButton* button) const { + if (button->type != GDK_BUTTON_PRESS) return true; + + if (button->button == LEFT_MOUSE_BUTTON) { + Gio::AppInfo::launch_default_for_uri("file:///" + this->get_user_home_dir()); + } + return false; } long User::uptime_as_seconds() { @@ -45,9 +61,9 @@ long User::uptime_as_seconds() { return uptime; } -std::string User::get_user_login() { return Glib::get_user_name(); } +std::string User::get_user_login() const { return Glib::get_user_name(); } -std::string User::get_user_home_dir() { return Glib::get_home_dir(); } +std::string User::get_user_home_dir() const { return Glib::get_home_dir(); } void User::init_update_worker() { this->thread_ = [this] { @@ -74,7 +90,7 @@ void User::init_avatar(const Json::Value& config) { this->init_default_user_avatar(width, width); } -std::string User::get_default_user_avatar_path() { +std::string User::get_default_user_avatar_path() const { return this->get_user_home_dir() + "/" + ".face"; } From c0b3e9ee35709c8475e0e13b45be153106765371 Mon Sep 17 00:00:00 2001 From: Frederic Grabowski Date: Sat, 12 Nov 2022 22:39:53 +0100 Subject: [PATCH 91/91] normalize capacity by number of batteries --- src/modules/battery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index 55760540..0ddd8246 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -495,7 +495,7 @@ const std::tuple waybar::modules::Battery::g float calculated_capacity{0.0f}; if (total_capacity_exists) { if (total_capacity > 0.0f) - calculated_capacity = (float)total_capacity; + calculated_capacity = (float)total_capacity / batteries_.size(); else if (total_energy_full_exists && total_energy_exists) { if (total_energy_full > 0.0f) calculated_capacity = ((float)total_energy * 100.0f / (float)total_energy_full);