diff --git a/src/modules/battery.cpp b/src/modules/battery.cpp index bb06781e..406d4077 100644 --- a/src/modules/battery.cpp +++ b/src/modules/battery.cpp @@ -107,6 +107,15 @@ void waybar::modules::Battery::refreshBatteries() { std::ifstream(node.path() / "type") >> type; if (!type.compare("Battery")) { + // 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; + if (g_ascii_strcasecmp(scope.data(), "device") == 0) { + continue; + } + } + check_map[node.path()] = true; auto search = batteries_.find(node.path()); if (search == batteries_.end()) { @@ -233,6 +242,10 @@ const std::tuple waybar::modules::Battery::g bool total_energy_full_design_exists = false; uint32_t total_capacity = 0; bool total_capacity_exists = false; + uint32_t time_to_empty_now = 0; + bool time_to_empty_now_exists = false; + uint32_t time_to_full_now = 0; + bool time_to_full_now_exists = false; std::string status = "Unknown"; for (auto const& item : batteries_) { @@ -260,6 +273,16 @@ const std::tuple waybar::modules::Battery::g std::ifstream(bat / "current_avg") >> current_now; } + if (fs::exists(bat / "time_to_empty_now")) { + time_to_empty_now_exists = true; + std::ifstream(bat / "time_to_empty_now") >> time_to_empty_now; + } + + if (fs::exists(bat / "time_to_full_now")) { + time_to_full_now_exists = true; + std::ifstream(bat / "time_to_full_now") >> time_to_full_now; + } + uint32_t voltage_now = 0; bool voltage_now_exists = false; if (fs::exists(bat / "voltage_now")) { @@ -481,8 +504,15 @@ const std::tuple waybar::modules::Battery::g } float time_remaining{0.0f}; - if (status == "Discharging" && total_power_exists && total_energy_exists) { + if (status == "Discharging" && time_to_empty_now_exists) { + if (time_to_empty_now != 0) time_remaining = (float)time_to_empty_now / 1000.0f; + } else if (status == "Discharging" && total_power_exists && total_energy_exists) { if (total_power != 0) time_remaining = (float)total_energy / total_power; + } else if (status == "Charging" && time_to_full_now_exists) { + if (time_to_full_now_exists && (time_to_full_now != 0)) time_remaining = -(float)time_to_full_now / 1000.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; } else if (status == "Charging" && total_energy_exists && total_energy_full_exists && total_power_exists) { if (total_power != 0) diff --git a/src/modules/clock.cpp b/src/modules/clock.cpp index 71b24c19..a40d4128 100644 --- a/src/modules/clock.cpp +++ b/src/modules/clock.cpp @@ -113,8 +113,12 @@ auto waybar::modules::Clock::update() -> void { if (config_["tooltip-format"].isString()) { std::string calendar_lines{""}; std::string timezoned_time_lines{""}; - if (is_calendar_in_tooltip_) calendar_lines = calendar_text(wtime); - if (is_timezoned_list_in_tooltip_) timezoned_time_lines = timezones_text(&now); + if (is_calendar_in_tooltip_) { + calendar_lines = calendar_text(wtime); + } + if (is_timezoned_list_in_tooltip_) { + timezoned_time_lines = timezones_text(&now); + } auto tooltip_format = config_["tooltip-format"].asString(); text = fmt::format(tooltip_format, wtime, fmt::arg(kCalendarPlaceholder.c_str(), calendar_lines), @@ -136,7 +140,7 @@ bool waybar::modules::Clock::handleScroll(GdkEventScroll* e) { auto dir = AModule::getScrollDir(e); // Shift calendar date - if (calendar_shift_init_.count() > 0) { + if (calendar_shift_init_.count() != 0) { if (dir == SCROLL_DIR::UP) calendar_shift_ += calendar_shift_init_; else @@ -168,72 +172,77 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str const auto daypoint = date::floor(wtime.ztime.get_local_time()); const auto ymd{date::year_month_day{daypoint}}; - if (calendar_cached_ymd_ == ymd) return calendar_cached_text_; + if (calendar_cached_ymd_ == ymd) { + return calendar_cached_text_; + } - const auto curr_day{(calendar_shift_init_.count() > 0 && calendar_shift_.count() != 0) + const auto curr_day{(calendar_shift_init_.count() != 0 && calendar_shift_.count() != 0) ? date::day{0} : ymd.day()}; const date::year_month ym{ymd.year(), ymd.month()}; - const auto week_format{config_["format-calendar-weekdays"].isString() - ? config_["format-calendar-weekdays"].asString() - : ""}; - const auto wn_format{config_["format-calendar-weeks"].isString() - ? config_["format-calendar-weeks"].asString() - : ""}; + const auto weeks_format{config_["format-calendar-weeks"].isString() + ? config_["format-calendar-weeks"].asString() + : ""}; std::stringstream os; - const auto first_dow = first_day_of_week(); - int ws{0}; // weeks-pos: side(1 - left, 2 - right) + const date::weekday first_week_day = first_day_of_week(); + + enum class WeeksPlacement { + LEFT, + RIGHT, + HIDDEN, + }; + WeeksPlacement weeks_pos = WeeksPlacement::HIDDEN; if (config_["calendar-weeks-pos"].isString()) { if (config_["calendar-weeks-pos"].asString() == "left") { - ws = 1; + weeks_pos = WeeksPlacement::LEFT; // Add paddings before the header os << std::string(4, ' '); } else if (config_["calendar-weeks-pos"].asString() == "right") { - ws = 2; + weeks_pos = WeeksPlacement::RIGHT; } } - weekdays_header(first_dow, os); + weekdays_header(first_week_day, os); // First week prefixed with spaces if needed. - auto wd = date::weekday(ym / 1); - auto empty_days = (wd - first_dow).count(); - date::sys_days lwd{static_cast(ym / 1) + date::days{7 - empty_days}}; + auto first_month_day = date::weekday(ym / 1); + int empty_days = (first_week_day - first_month_day).count() + 1; + date::sys_days last_week_day{static_cast(ym / 1) + date::days{7 - empty_days}}; - if (first_dow == date::Monday) { - lwd -= date::days{1}; + if (first_week_day == date::Monday) { + last_week_day -= date::days{1}; } /* Print weeknumber on the left for the first row*/ - if (ws == 1) { - os << fmt::format(wn_format, lwd); - os << ' '; - lwd += date::weeks{1}; + if (weeks_pos == WeeksPlacement::LEFT) { + os << fmt::format(weeks_format, date::format("%U", last_week_day)) << ' '; + last_week_day += date::weeks{1}; } if (empty_days > 0) { os << std::string(empty_days * 3 - 1, ' '); } - auto last_day = (ym / date::literals::last).day(); - for (auto d = date::day(1); d <= last_day; ++d, ++wd) { - if (wd != first_dow) { + const auto last_day = (ym / date::literals::last).day(); + auto weekday = first_month_day; + for (auto d = date::day(1); d <= last_day; ++d, ++weekday) { + if (weekday != first_week_day) { os << ' '; } else if (unsigned(d) != 1) { - if (ws == 2) { + last_week_day -= date::days{1}; + if (weeks_pos == WeeksPlacement::RIGHT) { os << ' '; - os << fmt::format(wn_format, lwd); - lwd += date::weeks{1}; + os << fmt::format(weeks_format, date::format("%U", last_week_day)); } - os << '\n'; + os << "\n"; - if (ws == 1) { - os << fmt::format(wn_format, lwd); + if (weeks_pos == WeeksPlacement::LEFT) { + os << fmt::format(weeks_format, date::format("%U", last_week_day)); os << ' '; - lwd += date::weeks{1}; } + last_week_day += date::weeks{1} + date::days{1}; } if (d == curr_day) { if (config_["today-format"].isString()) { @@ -244,15 +253,16 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str } } else if (config_["format-calendar"].isString()) { os << fmt::format(config_["format-calendar"].asString(), date::format("%e", d)); - } else + } else { os << date::format("%e", d); + } /*Print weeks on the right when the endings with spaces*/ - if (ws == 2 && d == last_day) { - empty_days = 6 - (wd.c_encoding() - first_dow.c_encoding()); - if (empty_days > 0) { - os << std::string(empty_days * 3 + 1, ' '); - os << fmt::format(wn_format, lwd); - } + if (weeks_pos == WeeksPlacement::RIGHT && d == last_day) { + last_week_day -= date::days{1}; + empty_days = 6 - (weekday - first_week_day).count(); + os << std::string(empty_days * 3 + 1, ' '); + os << fmt::format(weeks_format, date::format("%U", last_week_day)); + last_week_day += date::days{1}; } } @@ -262,12 +272,14 @@ auto waybar::modules::Clock::calendar_text(const waybar_time& wtime) -> std::str return result; } -auto waybar::modules::Clock::weekdays_header(const date::weekday& first_dow, std::ostream& os) +auto waybar::modules::Clock::weekdays_header(const date::weekday& first_week_day, std::ostream& os) -> void { std::stringstream res; - auto wd = first_dow; + auto wd = first_week_day; do { - if (wd != first_dow) res << ' '; + if (wd != first_week_day) { + res << ' '; + } Glib::ustring wd_ustring(date::format(locale_, "%a", wd)); auto clen = ustring_clen(wd_ustring); auto wd_len = wd_ustring.length(); @@ -278,7 +290,7 @@ auto waybar::modules::Clock::weekdays_header(const date::weekday& first_dow, std } const std::string pad(2 - clen, ' '); res << pad << wd_ustring; - } while (++wd != first_dow); + } while (++wd != first_week_day); res << "\n"; if (config_["format-calendar-weekdays"].isString()) { diff --git a/src/modules/hyprland/language.cpp b/src/modules/hyprland/language.cpp index ad0cdb81..13e30ec6 100644 --- a/src/modules/hyprland/language.cpp +++ b/src/modules/hyprland/language.cpp @@ -85,7 +85,6 @@ void Language::initLanguage() { try { auto searcher = INPUTDEVICES.substr(INPUTDEVICES.find(KEEBNAME) + KEEBNAME.length()); - searcher = searcher.substr(searcher.find("Keyboard at")); searcher = searcher.substr(searcher.find("keymap:") + 7); searcher = searcher.substr(0, searcher.find_first_of("\n\t")); diff --git a/src/modules/mpd/mpd.cpp b/src/modules/mpd/mpd.cpp index 99ba2bea..2c855d39 100644 --- a/src/modules/mpd/mpd.cpp +++ b/src/modules/mpd/mpd.cpp @@ -96,7 +96,13 @@ void waybar::modules::MPD::setLabel() { auto format = config_["format-disconnected"].isString() ? config_["format-disconnected"].asString() : "disconnected"; - label_.set_markup(format); + if (format.empty()) { + label_.set_markup(format); + label_.show(); + } else { + label_.hide(); + } + if (tooltipEnabled()) { std::string tooltip_format; @@ -107,9 +113,8 @@ void waybar::modules::MPD::setLabel() { 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_; Glib::ustring artist, album_artist, album, title; @@ -169,7 +174,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( + auto text = fmt::format( 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), @@ -177,7 +182,13 @@ 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), - fmt::arg("filename", filename))); + fmt::arg("filename", filename)); + if (text.empty()) { + label_.hide(); + } else { + label_.show(); + label_.set_markup(text); + } } catch (fmt::format_error const& e) { spdlog::warn("mpd: format error: {}", e.what()); } diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp index 4ba88de0..c7979976 100644 --- a/src/modules/pulseaudio.cpp +++ b/src/modules/pulseaudio.cpp @@ -295,10 +295,16 @@ auto waybar::modules::Pulseaudio::update() -> void { } } format_source = fmt::format(format_source, fmt::arg("volume", source_volume_)); - label_.set_markup(fmt::format( + auto text = 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())))); + fmt::arg("source_desc", source_desc_), fmt::arg("icon", getIcon(volume_, getPulseIcon()))); + if (text.empty()) { + label_.hide(); + } else { + label_.set_markup(text); + label_.show(); + } getState(volume_); if (tooltipEnabled()) { diff --git a/src/modules/sndio.cpp b/src/modules/sndio.cpp index 92a8d3da..7a358c18 100644 --- a/src/modules/sndio.cpp +++ b/src/modules/sndio.cpp @@ -110,7 +110,14 @@ auto Sndio::update() -> void { label_.get_style_context()->remove_class("muted"); } - label_.set_markup(fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_))); + auto text = fmt::format(format, fmt::arg("volume", vol), fmt::arg("raw_value", volume_)); + if (text.empty()) { + label_.hide(); + } else { + label_.set_markup(text); + label_.show(); + } + ALabel::update(); } diff --git a/src/modules/sni/tray.cpp b/src/modules/sni/tray.cpp index 87e5577f..09d53e7f 100644 --- a/src/modules/sni/tray.cpp +++ b/src/modules/sni/tray.cpp @@ -10,9 +10,6 @@ Tray::Tray(const std::string& id, const Bar& bar, const Json::Value& config) watcher_(SNI::Watcher::getInstance()), host_(nb_hosts_, config, bar, std::bind(&Tray::onAdd, this, std::placeholders::_1), std::bind(&Tray::onRemove, this, std::placeholders::_1)) { - spdlog::warn( - "For a functional tray you must have libappindicator-* installed and export " - "XDG_CURRENT_DESKTOP=Unity"); box_.set_name("tray"); event_box_.add(box_); if (!id.empty()) { diff --git a/src/modules/user.cpp b/src/modules/user.cpp index eab14106..2f7c6e9c 100644 --- a/src/modules/user.cpp +++ b/src/modules/user.cpp @@ -10,6 +10,7 @@ #include "gdkmm/cursor.h" #include "gdkmm/event.h" #include "gdkmm/types.h" +#include "glibmm/fileutils.h" #include "sigc++/functors/mem_fun.h" #include "sigc++/functors/ptr_fun.h" @@ -26,6 +27,7 @@ const static int LEFT_MOUSE_BUTTON_CODE = 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, true, true) { + AIconLabel::box_.set_spacing(0); if (AIconLabel::iconEnabled()) { this->init_avatar(AIconLabel::config_); } @@ -106,8 +108,12 @@ void User::init_default_user_avatar(int width, int height) { } void User::init_user_avatar(const std::string& path, int width, int height) { - Glib::RefPtr pixbuf_ = Gdk::Pixbuf::create_from_file(path, width, height); - AIconLabel::image_.set(pixbuf_); + if (Glib::file_test(path, Glib::FILE_TEST_EXISTS)) { + Glib::RefPtr pixbuf_ = Gdk::Pixbuf::create_from_file(path, width, height); + AIconLabel::image_.set(pixbuf_); + } else { + AIconLabel::box_.remove(AIconLabel::image_); + } } auto User::update() -> void { @@ -132,6 +138,6 @@ auto User::update() -> void { fmt::arg("work_S", fmt::format("{:%S}", workSystemTimeSeconds)), fmt::arg("user", systemUser)); ALabel::label_.set_markup(label); - ALabel::update(); + AIconLabel::update(); } }; // namespace waybar::modules diff --git a/src/modules/wireplumber.cpp b/src/modules/wireplumber.cpp index 0ab129e66..9a12a9b5 100644 --- a/src/modules/wireplumber.cpp +++ b/src/modules/wireplumber.cpp @@ -54,17 +54,25 @@ uint32_t waybar::modules::Wireplumber::getDefaultNodeId(waybar::modules::Wireplu } void waybar::modules::Wireplumber::updateNodeName(waybar::modules::Wireplumber* self) { - auto proxy = static_cast(wp_object_manager_lookup( - self->om_, WP_TYPE_GLOBAL_PROXY, WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, "object.id", "=u", - self->node_id_, NULL)); + auto proxy = static_cast( + wp_object_manager_lookup(self->om_, WP_TYPE_GLOBAL_PROXY, WP_CONSTRAINT_TYPE_G_PROPERTY, + "bound-id", "=u", self->node_id_, NULL)); if (!proxy) { throw std::runtime_error(fmt::format("Object '{}' not found\n", self->node_id_)); } - g_autoptr(WpProperties) properties = wp_pipewire_object_get_properties(proxy); + g_autoptr(WpProperties) properties = + WP_IS_PIPEWIRE_OBJECT(proxy) ? wp_pipewire_object_get_properties(WP_PIPEWIRE_OBJECT(proxy)) + : wp_properties_new_empty(); + g_autoptr(WpProperties) global_p = wp_global_proxy_get_global_properties(WP_GLOBAL_PROXY(proxy)); properties = wp_properties_ensure_unique_owner(properties); - self->node_name_ = wp_properties_get(properties, "node.nick"); + wp_properties_add(properties, global_p); + wp_properties_set(properties, "object.id", NULL); + auto nick = wp_properties_get(properties, "node.nick"); + auto description = wp_properties_get(properties, "node.description"); + + self->node_name_ = nick ? nick : description; } void waybar::modules::Wireplumber::updateVolume(waybar::modules::Wireplumber* self) { @@ -120,6 +128,7 @@ void waybar::modules::Wireplumber::activatePlugins() { void waybar::modules::Wireplumber::prepare() { wp_object_manager_add_interest(om_, WP_TYPE_NODE, NULL); + wp_object_manager_add_interest(om_, WP_TYPE_GLOBAL_PROXY, NULL); wp_object_manager_request_object_features(om_, WP_TYPE_GLOBAL_PROXY, WP_PIPEWIRE_OBJECT_FEATURES_MINIMAL); } @@ -156,8 +165,8 @@ auto waybar::modules::Wireplumber::update() -> void { label_.get_style_context()->remove_class("muted"); } - std::string markup = - fmt::format(format, fmt::arg("node_name", node_name_), fmt::arg("volume", volume_)); + std::string markup = fmt::format(format, fmt::arg("node_name", node_name_), + fmt::arg("volume", volume_), fmt::arg("icon", getIcon(volume_))); label_.set_markup(markup); getState(volume_); @@ -169,7 +178,8 @@ auto waybar::modules::Wireplumber::update() -> void { if (!tooltip_format.empty()) { label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("node_name", node_name_), - fmt::arg("volume", volume_))); + fmt::arg("volume", volume_), + fmt::arg("icon", getIcon(volume_)))); } else { label_.set_tooltip_text(node_name_); }