diff --git a/include/modules/memory.hpp b/include/modules/memory.hpp index 3b6342b3..c73ece23 100644 --- a/include/modules/memory.hpp +++ b/include/modules/memory.hpp @@ -19,9 +19,13 @@ class Memory : public ALabel { private: void parseMeminfo(); + static float calc_divisor(const std::string& divisor); + std::unordered_map meminfo_; util::SleeperThread thread_; + + std::string unit_; }; } // namespace waybar::modules diff --git a/include/modules/network.hpp b/include/modules/network.hpp index 4abe26bd..66fc6d04 100644 --- a/include/modules/network.hpp +++ b/include/modules/network.hpp @@ -70,6 +70,9 @@ class Network : public ALabel { unsigned long long bandwidth_down_total_{0}; unsigned long long bandwidth_up_total_{0}; + unsigned long long bandwidth_down_prev_{0}; + unsigned long long bandwidth_up_prev_{0}; + std::chrono::steady_clock::time_point bandwidth_last_sample_time_; std::string state_; std::string essid_; diff --git a/include/util/hex_checker.hpp b/include/util/hex_checker.hpp new file mode 100644 index 00000000..27a84d1f --- /dev/null +++ b/include/util/hex_checker.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +/** + * Result of transforming 8-bit hex codes to rgba(). + */ +struct TransformResult { + std::string css; + bool was_transformed; +}; + +/** + * Reads a CSS file, searches for 8-bit hex codes (#RRGGBBAA), + * and transforms them into GTK-compatible rgba() syntax. + */ +TransformResult transform_8bit_to_hex(const std::string& file_path); diff --git a/man/waybar-memory.5.scd b/man/waybar-memory.5.scd index 567c2c72..99f57299 100644 --- a/man/waybar-memory.5.scd +++ b/man/waybar-memory.5.scd @@ -102,23 +102,29 @@ Addressed by *memory* default: false ++ Enables this module to consume all left over space dynamically. +*unit*: ++ + typeof: string ++ + default: GiB ++ + Used to specify unit for total, swapTotal, used, swapUsed, avail, swapAvail, + and swapState. Accepts B, kB, kiB, MB, MiB, GB, GiB, TB, and TiB. + # FORMAT REPLACEMENTS *{percentage}*: Percentage of memory in use. *{swapPercentage}*: Percentage of swap in use. -*{total}*: Amount of total memory available in GiB. +*{total}*: Amount of total memory available. Defaults to GiB. -*{swapTotal}*: Amount of total swap available in GiB. +*{swapTotal}*: Amount of total swap available. Defaults to GiB. -*{used}*: Amount of used memory in GiB. +*{used}*: Amount of used memory. Defaults to GiB. -*{swapUsed}*: Amount of used swap in GiB. +*{swapUsed}*: Amount of used swap. Defaults to GiB. -*{avail}*: Amount of available memory in GiB. +*{avail}*: Amount of available memory. Defaults to GiB. -*{swapAvail}*: Amount of available swap in GiB. +*{swapAvail}*: Amount of available swap. Defaults to GiB. *{swapState}*: Signals if swap is activated or not diff --git a/meson.build b/meson.build index db9407eb..0c494eb2 100644 --- a/meson.build +++ b/meson.build @@ -185,7 +185,8 @@ src_files = files( 'src/util/gtk_icon.cpp', 'src/util/icon_loader.cpp', 'src/util/regex_collection.cpp', - 'src/util/css_reload_helper.cpp' + 'src/util/css_reload_helper.cpp', + 'src/util/transform_8bit_to_rgba.cpp' ) man_files = files( diff --git a/src/bar.cpp b/src/bar.cpp index 6a78707e..7ff73c4f 100644 --- a/src/bar.cpp +++ b/src/bar.cpp @@ -541,13 +541,15 @@ void waybar::Bar::getModules(const Factory& factory, const std::string& pos, auto vertical = (group != nullptr ? group->getBox().get_orientation() : box_.get_orientation()) == Gtk::ORIENTATION_VERTICAL; - auto group_config = config[ref]; + const Json::Value& group_config = config[ref]; if (group_config["modules"].isNull()) { spdlog::warn("Group definition '{}' has not been found, group will be hidden", ref); } - auto* group_module = new waybar::Group(id_name, class_name, group_config, vertical); - getModules(factory, ref, group_module); - module = group_module; + auto group_module = std::make_unique( + id_name, class_name, group_config, vertical); + + getModules(factory, ref, group_module.get()); + module = group_module.release(); } else { module = factory.makeModule(ref, pos); } diff --git a/src/client.cpp b/src/client.cpp index 1da3ffcb..d1489186 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -10,6 +10,7 @@ #include "idle-inhibit-unstable-v1-client-protocol.h" #include "util/clara.hpp" #include "util/format.hpp" +#include "util/hex_checker.hpp" waybar::Client* waybar::Client::inst() { static auto* c = new Client(); @@ -22,21 +23,18 @@ void waybar::Client::handleGlobal(void* data, struct wl_registry* registry, uint if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 && version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { - if (client->xdg_output_manager != nullptr) { zxdg_output_manager_v1_destroy(client->xdg_output_manager); client->xdg_output_manager = nullptr; } - client->xdg_output_manager = static_cast( - wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, - ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)); + client->xdg_output_manager = static_cast(wl_registry_bind( + registry, name, &zxdg_output_manager_v1_interface, ZXDG_OUTPUT_V1_NAME_SINCE_VERSION)); } else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) { - if (client->idle_inhibit_manager != nullptr) { zwp_idle_inhibit_manager_v1_destroy(client->idle_inhibit_manager); - client->idle_inhibit_manager = nullptr; + client->idle_inhibit_manager = nullptr; } client->idle_inhibit_manager = static_cast( @@ -209,11 +207,15 @@ auto waybar::Client::setupCss(const std::string& css_file) -> void { } css_provider_ = Gtk::CssProvider::create(); - if (!css_provider_->load_from_path(css_file)) { - css_provider_.reset(); - throw std::runtime_error("Can't open style file"); + auto [modified_css, was_transformed] = transform_8bit_to_hex(css_file); + if (was_transformed) { + css_provider_->load_from_data(modified_css); + } else { + if (!css_provider_->load_from_path(css_file)) { + css_provider_.reset(); + throw std::runtime_error("Can't open style file"); + } } - Gtk::StyleContext::add_provider_for_screen(screen, css_provider_, GTK_STYLE_PROVIDER_PRIORITY_USER); } diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index d39c4920..30be3857 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -126,7 +126,14 @@ void waybar::modules::Battery::refreshBatteries() { // Ignore non-system power supplies unless explicitly requested if (!bat_defined && fs::exists(node.path() / "scope")) { std::string scope; - std::ifstream(node.path() / "scope") >> scope; + try { + // for hotplug-in device, access it is always unstable because you may remove the + // device anytime so just allow failure happen and do nothing + std::ifstream(node.path() / "scope") >> scope; + } catch (const std::ifstream::failure& e) { + scope.clear(); + continue; + } if (g_ascii_strcasecmp(scope.data(), "device") == 0) { continue; } diff --git a/src/modules/dwl/tags.cpp b/src/modules/dwl/tags.cpp index 399c7d4b..243aaa92 100644 --- a/src/modules/dwl/tags.cpp +++ b/src/modules/dwl/tags.cpp @@ -70,17 +70,33 @@ static const zdwl_ipc_output_v2_listener output_status_listener_impl{ static void handle_global(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { - if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) { - static_cast(data)->status_manager_ = static_cast( - (zdwl_ipc_manager_v2*)wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1)); - } - if (std::strcmp(interface, wl_seat_interface.name) == 0) { - version = std::min(version, 1); - static_cast(data)->seat_ = - static_cast(wl_registry_bind(registry, name, &wl_seat_interface, version)); - } + +if (std::strcmp(interface, zdwl_ipc_manager_v2_interface.name) == 0) { + auto* self = static_cast(data); + + if (self->status_manager_) { + zdwl_ipc_manager_v2_destroy(self->status_manager_); + self->status_manager_ = nullptr; } + self->status_manager_ = static_cast( + wl_registry_bind(registry, name, &zdwl_ipc_manager_v2_interface, 1)); +} + +if (std::strcmp(interface, wl_seat_interface.name) == 0) { + auto* self = static_cast(data); + + if (self->seat_) { + wl_seat_destroy(self->seat_); + self->seat_ = nullptr; + } + + version = std::min(version, 1); + + self->seat_ = static_cast( + wl_registry_bind(registry, name, &wl_seat_interface, version)); +} +} static void handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) { /* Ignore event */ } diff --git a/src/modules/memory/common.cpp b/src/modules/memory/common.cpp index 3c486a33..731f0b08 100644 --- a/src/modules/memory/common.cpp +++ b/src/modules/memory/common.cpp @@ -6,6 +6,9 @@ waybar::modules::Memory::Memory(const std::string& id, const Json::Value& config dp.emit(); thread_.sleep_for(interval_); }; + if (config["unit"].isString()) { + unit_ = config["unit"].asString(); + } } auto waybar::modules::Memory::update() -> void { @@ -13,15 +16,15 @@ auto waybar::modules::Memory::update() -> void { unsigned long memtotal = meminfo_["MemTotal"]; unsigned long swaptotal = 0; - if (meminfo_.count("SwapTotal")) { + if (meminfo_.contains("SwapTotal")) { swaptotal = meminfo_["SwapTotal"]; } unsigned long memfree; unsigned long swapfree = 0; - if (meminfo_.count("SwapFree")) { + if (meminfo_.contains("SwapFree")) { swapfree = meminfo_["SwapFree"]; } - if (meminfo_.count("MemAvailable")) { + if (meminfo_.contains("MemAvailable")) { // New kernels (3.4+) have an accurate available memory field. memfree = meminfo_["MemAvailable"] + meminfo_["zfs_size"]; } else { @@ -31,18 +34,19 @@ 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); int used_ram_percentage = 100 * (memtotal - memfree) / memtotal; int used_swap_percentage = 0; - if (swaptotal) { + if ((bool) swaptotal) { 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 divisor = calc_divisor(unit_); + float total_ram = memtotal / divisor; + float total_swap = swaptotal / divisor; + float used_ram = (memtotal - memfree) / divisor; + float used_swap = (swaptotal - swapfree) / divisor; + float available_ram = memfree / divisor; + float available_swap = swapfree / divisor; auto format = format_; auto state = getState(used_ram_percentage); @@ -58,12 +62,12 @@ auto waybar::modules::Memory::update() -> void { label_.set_markup(fmt::format( fmt::runtime(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("total", total_ram), fmt::arg("swapTotal", total_swap), fmt::arg("percentage", used_ram_percentage), fmt::arg("swapState", swaptotal == 0 ? "Off" : "On"), - fmt::arg("swapPercentage", used_swap_percentage), fmt::arg("used", used_ram_gigabytes), - fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes), - fmt::arg("swapAvail", available_swap_gigabytes))); + fmt::arg("swapPercentage", used_swap_percentage), fmt::arg("used", used_ram), + fmt::arg("swapUsed", used_swap), fmt::arg("avail", available_ram), + fmt::arg("swapAvail", available_swap))); } if (tooltipEnabled()) { @@ -71,14 +75,14 @@ auto waybar::modules::Memory::update() -> void { auto tooltip_format = config_["tooltip-format"].asString(); label_.set_tooltip_markup(fmt::format( fmt::runtime(tooltip_format), used_ram_percentage, - fmt::arg("total", total_ram_gigabytes), fmt::arg("swapTotal", total_swap_gigabytes), + fmt::arg("total", total_ram), fmt::arg("swapTotal", total_swap), fmt::arg("percentage", used_ram_percentage), fmt::arg("swapState", swaptotal == 0 ? "Off" : "On"), - fmt::arg("swapPercentage", used_swap_percentage), fmt::arg("used", used_ram_gigabytes), - fmt::arg("swapUsed", used_swap_gigabytes), fmt::arg("avail", available_ram_gigabytes), - fmt::arg("swapAvail", available_swap_gigabytes))); + fmt::arg("swapPercentage", used_swap_percentage), fmt::arg("used", used_ram), + fmt::arg("swapUsed", used_swap), fmt::arg("avail", available_ram), + fmt::arg("swapAvail", available_swap))); } else { - label_.set_tooltip_markup(fmt::format("{:.{}f}GiB used", used_ram_gigabytes, 1)); + label_.set_tooltip_markup(fmt::format("{:.{}f}GiB used", used_ram, 1)); } } } else { @@ -87,3 +91,25 @@ auto waybar::modules::Memory::update() -> void { // Call parent update ALabel::update(); } + +float waybar::modules::Memory::calc_divisor(const std::string& divisor) { + if (divisor == "kB") { + return 1.0; + } else if (divisor == "kiB") { + return 1.024; + } else if (divisor == "MB") { + return 1.000 * 1000.0; + } else if (divisor == "MiB") { + return 1.024 * 1024.0; + } else if (divisor == "GB") { + return 1.000 * 1000.0 * 1000.0; + } else if (divisor == "GiB") { + return 1.024 * 1024.0 * 1024.0; + } else if (divisor == "TB") { + return 1.000 * 1000.0 * 1000.0 * 1000.0; + } else if (divisor == "TiB") { + return 1.024 * 1024.0 * 1024.0 * 1024.0; + } else { // default to GiB if it is anything that we don't recongnise + return 1.024 * 1024.0 * 1024.0; + } +} diff --git a/src/modules/network.cpp b/src/modules/network.cpp index a4f2bcc2..f43893c5 100644 --- a/src/modules/network.cpp +++ b/src/modules/network.cpp @@ -105,6 +105,7 @@ waybar::modules::Network::Network(const std::string& id, const Json::Value& conf bandwidth_down_total_ = 0; bandwidth_up_total_ = 0; } + bandwidth_last_sample_time_ = std::chrono::steady_clock::now(); if (!config_["interface"].isString()) { // "interface" isn't configured, then try to guess the external @@ -277,19 +278,41 @@ const std::string waybar::modules::Network::getNetworkState() const { auto waybar::modules::Network::update() -> void { std::lock_guard lock(mutex_); std::string tooltip_format; + auto now = std::chrono::steady_clock::now(); + auto elapsed_seconds = std::chrono::duration(now - bandwidth_last_sample_time_).count(); - auto bandwidth = readBandwidthUsage(); auto bandwidth_down = 0ull; auto bandwidth_up = 0ull; - if (bandwidth.has_value()) { - auto down_octets = (*bandwidth).first; - auto up_octets = (*bandwidth).second; - bandwidth_down = down_octets - bandwidth_down_total_; - bandwidth_down_total_ = down_octets; + // Only recalculate bandwidth when enough time has elapsed since the last + // sample. Event-driven dp.emit() calls (link/addr/route changes) can + // trigger update() between timer intervals, which would consume the byte + // delta prematurely and show near-zero bandwidth. + auto min_elapsed = std::chrono::duration(interval_).count() * 0.5; + if (elapsed_seconds >= min_elapsed) { + if (elapsed_seconds <= 0.0) { + elapsed_seconds = std::chrono::duration(interval_).count(); + } + bandwidth_last_sample_time_ = now; - bandwidth_up = up_octets - bandwidth_up_total_; - bandwidth_up_total_ = up_octets; + auto bandwidth = readBandwidthUsage(); + if (bandwidth.has_value()) { + auto down_octets = (*bandwidth).first; + auto up_octets = (*bandwidth).second; + + bandwidth_down = down_octets - bandwidth_down_total_; + bandwidth_down_total_ = down_octets; + + bandwidth_up = up_octets - bandwidth_up_total_; + bandwidth_up_total_ = up_octets; + + bandwidth_down_prev_ = bandwidth_down; + bandwidth_up_prev_ = bandwidth_up; + } + } else { + bandwidth_down = bandwidth_down_prev_; + bandwidth_up = bandwidth_up_prev_; + elapsed_seconds = std::chrono::duration(interval_).count(); } if (!alt_) { @@ -335,23 +358,18 @@ auto waybar::modules::Network::update() -> void { fmt::arg("ipaddr", final_ipaddr_), fmt::arg("gwaddr", gwaddr_), fmt::arg("cidr", cidr_), fmt::arg("cidr6", cidr6_), fmt::arg("frequency", fmt::format("{:.1f}", frequency_)), fmt::arg("icon", getIcon(signal_strength_, state_)), - fmt::arg("bandwidthDownBits", - pow_format(bandwidth_down * 8ull / (interval_.count() / 1000.0), "b/s")), - fmt::arg("bandwidthUpBits", - pow_format(bandwidth_up * 8ull / (interval_.count() / 1000.0), "b/s")), - fmt::arg( - "bandwidthTotalBits", - pow_format((bandwidth_up + bandwidth_down) * 8ull / (interval_.count() / 1000.0), "b/s")), - fmt::arg("bandwidthDownOctets", - pow_format(bandwidth_down / (interval_.count() / 1000.0), "o/s")), - fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / (interval_.count() / 1000.0), "o/s")), + fmt::arg("bandwidthDownBits", pow_format(bandwidth_down * 8ull / elapsed_seconds, "b/s")), + fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / elapsed_seconds, "b/s")), + fmt::arg("bandwidthTotalBits", + pow_format((bandwidth_up + bandwidth_down) * 8ull / elapsed_seconds, "b/s")), + fmt::arg("bandwidthDownOctets", pow_format(bandwidth_down / elapsed_seconds, "o/s")), + fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / elapsed_seconds, "o/s")), fmt::arg("bandwidthTotalOctets", - pow_format((bandwidth_up + bandwidth_down) / (interval_.count() / 1000.0), "o/s")), - fmt::arg("bandwidthDownBytes", - pow_format(bandwidth_down / (interval_.count() / 1000.0), "B/s")), - fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / (interval_.count() / 1000.0), "B/s")), + pow_format((bandwidth_up + bandwidth_down) / elapsed_seconds, "o/s")), + fmt::arg("bandwidthDownBytes", pow_format(bandwidth_down / elapsed_seconds, "B/s")), + fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / elapsed_seconds, "B/s")), fmt::arg("bandwidthTotalBytes", - pow_format((bandwidth_up + bandwidth_down) / (interval_.count() / 1000.0), "B/s"))); + pow_format((bandwidth_up + bandwidth_down) / elapsed_seconds, "B/s"))); if (text.compare(label_.get_label()) != 0) { label_.set_markup(text); if (text.empty()) { @@ -373,27 +391,18 @@ auto waybar::modules::Network::update() -> void { fmt::arg("ipaddr", final_ipaddr_), fmt::arg("gwaddr", gwaddr_), fmt::arg("cidr", cidr_), fmt::arg("cidr6", cidr6_), fmt::arg("frequency", fmt::format("{:.1f}", frequency_)), fmt::arg("icon", getIcon(signal_strength_, state_)), - fmt::arg("bandwidthDownBits", - pow_format(bandwidth_down * 8ull / (interval_.count() / 1000.0), "b/s")), - fmt::arg("bandwidthUpBits", - pow_format(bandwidth_up * 8ull / (interval_.count() / 1000.0), "b/s")), + fmt::arg("bandwidthDownBits", pow_format(bandwidth_down * 8ull / elapsed_seconds, "b/s")), + fmt::arg("bandwidthUpBits", pow_format(bandwidth_up * 8ull / elapsed_seconds, "b/s")), fmt::arg("bandwidthTotalBits", - pow_format((bandwidth_up + bandwidth_down) * 8ull / (interval_.count() / 1000.0), - "b/s")), - fmt::arg("bandwidthDownOctets", - pow_format(bandwidth_down / (interval_.count() / 1000.0), "o/s")), - fmt::arg("bandwidthUpOctets", - pow_format(bandwidth_up / (interval_.count() / 1000.0), "o/s")), - fmt::arg( - "bandwidthTotalOctets", - pow_format((bandwidth_up + bandwidth_down) / (interval_.count() / 1000.0), "o/s")), - fmt::arg("bandwidthDownBytes", - pow_format(bandwidth_down / (interval_.count() / 1000.0), "B/s")), - fmt::arg("bandwidthUpBytes", - pow_format(bandwidth_up / (interval_.count() / 1000.0), "B/s")), - fmt::arg( - "bandwidthTotalBytes", - pow_format((bandwidth_up + bandwidth_down) / (interval_.count() / 1000.0), "B/s"))); + pow_format((bandwidth_up + bandwidth_down) * 8ull / elapsed_seconds, "b/s")), + fmt::arg("bandwidthDownOctets", pow_format(bandwidth_down / elapsed_seconds, "o/s")), + fmt::arg("bandwidthUpOctets", pow_format(bandwidth_up / elapsed_seconds, "o/s")), + fmt::arg("bandwidthTotalOctets", + pow_format((bandwidth_up + bandwidth_down) / elapsed_seconds, "o/s")), + fmt::arg("bandwidthDownBytes", pow_format(bandwidth_down / elapsed_seconds, "B/s")), + fmt::arg("bandwidthUpBytes", pow_format(bandwidth_up / elapsed_seconds, "B/s")), + fmt::arg("bandwidthTotalBytes", + pow_format((bandwidth_up + bandwidth_down) / elapsed_seconds, "B/s"))); if (label_.get_tooltip_text() != tooltip_text) { label_.set_tooltip_markup(tooltip_text); } @@ -684,12 +693,15 @@ int waybar::modules::Network::handleEvents(struct nl_msg* msg, void* data) { changed_cidr); } } else { - net->ipaddr_.clear(); - net->ipaddr6_.clear(); - net->cidr_ = 0; - net->cidr6_ = 0; - net->netmask_.clear(); - net->netmask6_.clear(); + if (ifa->ifa_family == AF_INET) { + net->ipaddr_.clear(); + net->cidr_ = 0; + net->netmask_.clear(); + } else if (ifa->ifa_family == AF_INET6) { + net->ipaddr6_.clear(); + net->cidr6_ = 0; + net->netmask6_.clear(); + } spdlog::debug("network: {} addr deleted {}/{}", net->ifname_, inet_ntop(ifa->ifa_family, RTA_DATA(ifa_rta), ipaddr, sizeof(ipaddr)), ifa->ifa_prefixlen); @@ -744,16 +756,20 @@ int waybar::modules::Network::handleEvents(struct nl_msg* msg, void* data) { /* The destination address. * Should be either missing, or maybe all 0s. Accept both. */ - const uint32_t nr_zeroes = (family == AF_INET) ? 4 : 16; - unsigned char c = 0; - size_t dstlen = RTA_PAYLOAD(attr); - if (dstlen != nr_zeroes) { - break; + auto* dest = (const unsigned char*)RTA_DATA(attr); + size_t dest_size = RTA_PAYLOAD(attr); + for (size_t i = 0; i < dest_size; ++i) { + if (dest[i] != 0) { + has_destination = true; + break; + } } - for (uint32_t i = 0; i < dstlen; i += 1) { - c |= *((unsigned char*)RTA_DATA(attr) + i); + + if (rtm->rtm_dst_len != 0) { + // We have found a destination like 0.0.0.0/24, this is not a + // default gateway route. + has_destination = true; } - has_destination = (c == 0); break; } case RTA_OIF: diff --git a/src/modules/niri/workspaces.cpp b/src/modules/niri/workspaces.cpp index 3e8a432e..97d15215 100644 --- a/src/modules/niri/workspaces.cpp +++ b/src/modules/niri/workspaces.cpp @@ -114,6 +114,11 @@ void Workspaces::doUpdate() { button.show(); else button.hide(); + } else if (config_["hide-empty"].asBool()) { + if (ws["active_window_id"].isNull() && !ws["is_focused"].asBool()) + button.hide(); + else + button.show(); } else { button.show(); } diff --git a/src/modules/sni/host.cpp b/src/modules/sni/host.cpp index 18eac643..567fbf9f 100644 --- a/src/modules/sni/host.cpp +++ b/src/modules/sni/host.cpp @@ -178,9 +178,11 @@ void Host::addRegisteredItem(const std::string& service) { return bus_name == item->bus_name && object_path == item->object_path; }); if (it == items_.end()) { - items_.emplace_back(new Item( - bus_name, object_path, config_, bar_, [this](Item& item) { itemReady(item); }, - [this](Item& item) { itemInvalidated(item); }, on_update_)); + items_.emplace_back(std::make_unique( + bus_name, object_path, config_, bar_, + [this](Item& item) { itemReady(item); }, + [this](Item& item) { itemInvalidated(item); }, + on_update_)); } } diff --git a/src/modules/wlr/taskbar.cpp b/src/modules/wlr/taskbar.cpp index 2aef0ae3..bde90910 100644 --- a/src/modules/wlr/taskbar.cpp +++ b/src/modules/wlr/taskbar.cpp @@ -198,7 +198,7 @@ void Task::handle_title(const char* title) { title_ = title; hide_if_ignored(); - if (!with_icon_ && !with_name_ || app_info_) { + if ((!with_icon_ && !with_name_) || app_info_) { return; } diff --git a/src/util/transform_8bit_to_rgba.cpp b/src/util/transform_8bit_to_rgba.cpp new file mode 100644 index 00000000..dc87a88e --- /dev/null +++ b/src/util/transform_8bit_to_rgba.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include +namespace fs = std::filesystem; + +struct TransformResult { + std::string css; + bool was_transformed; +}; + +TransformResult transform_8bit_to_hex(const std::string& file_path) { + std::ifstream f(file_path, std::ios::in | std::ios::binary); + const auto size = fs::file_size(file_path); + std::string result(size, '\0'); + if (!f.is_open() || !f.good()) { + throw std::runtime_error("Cannot open file: " + file_path); + } + + if (size == 0) { + return {.css = result, .was_transformed = false}; + } + + f.read(result.data(), size); + + static std::regex pattern( + R"(\#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2}))"); + std::string final_output; + + auto it = std::sregex_iterator(result.begin(), result.end(), pattern); + auto eof = std::sregex_iterator(); + + if (it == eof) { + return {.css = result, .was_transformed = false}; + } + + std::smatch match; + while (it != eof) { + match = *it; + + final_output += match.prefix().str(); + + int r = stoi(match[1].str(), nullptr, 16); + int g = stoi(match[2].str(), nullptr, 16); + int b = stoi(match[3].str(), nullptr, 16); + double a = (stoi(match[4].str(), nullptr, 16) / 255.0); + + std::stringstream ss; + ss << "rgba(" << r << "," << g << "," << b << "," << std::fixed << std::setprecision(2) << a + << ")"; + final_output += ss.str(); + + ++it; + } + + final_output += match.suffix().str(); + + return {.css = final_output, .was_transformed = true}; +}