fix: backward-compat + bug fixes and man-page build fix for 0.16.0

Post-0.15.0 review of the 0.15.0..HEAD range surfaced regressions and
bugs. This restores backward compatibility for existing configs/CSS,
fixes confirmed defects, and repairs the scdoc man-page build break on
master. Pango-markup tooltips are intentional and were kept.

Backward-compat restorations:
- AModule: honor legacy numeric Gdk::CursorType cursor values (int overload)
- memory: correct GiB divisor (was ~2.3% low); round bare {} placeholders
- wireplumber: scale max-volume into the linear domain so the cap works again
- idle_inhibitor: gate right/middle-click deactivate & scroll on dynamic-timeouts;
  accept both dynamic-timeout(s); widen timeout to double (no fractional truncation)
- custom: keep #custom-<name>.<class> CSS selectors working (classes on box_)
- image: don't wordexp-split a single path; fall back to the literal path
- niri/window: restore hide-when-empty (new show-empty opt-in); escape tooltip
- wlr/taskbar: plain-text tooltip when markup is disabled

Bug fixes:
- tray: fix use-after-free in onAdd; guard the watcher retry timeout
- hyprland: clamp max-windows iterator (OOB); drop duplicate language tooltip block
- niri/window: supply {col}/{max_col} args in the empty branch (fmt::format_error)
- mpris: escape {dynamic}/{player} tooltip; fix dangling player; albumArtist source
- mango: fix use-after-free race (dispatch under callback_mutex_)
- mpd: contain throwing checkErrors in noexcept idle paths (no std::terminate/UAF)
- keyboard_state: always render every lock label, with guarded defaults
- bluetooth: bound GATT ReadValue timeout, opt-in + services-resolved gating,
  preserve authoritative Battery1 percentage
- wireplumber: fix WpDevice reference leak / NULL handling
- battery, clock, dwl, wayfire, graph, custom_graph, transform, river: assorted
  crash/logic fixes

Man page / build:
- niri-workspaces: fix scdoc "indented by an amount greater than 1"
  (workspace-taskbar sub-options were mis-indented; breaks man-page build)
- document new show-empty (niri/window); correct network {txBitrate}/{rxBitrate}

Not compiled locally (no gtkmm on this host); C++ build relies on CI.
Man pages validated with scdoc 1.11.4.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alex
2026-07-04 02:14:13 +02:00
co-authored by Claude Opus 4.8
parent 482cfab64e
commit f72f84e011
35 changed files with 377 additions and 192 deletions
+27 -3
View File
@@ -223,6 +223,17 @@ auto waybar::modules::Custom::update() -> void {
for (auto const& c : class_) {
style->add_class(c);
}
// Mirror the dynamic script classes onto box_, which now carries the
// #custom-<name> widget name (see AIconLabel), so #custom-<name>.<class>
// CSS selectors keep resolving as they did in 0.15.0.
auto box_style = box_.get_style_context();
for (auto const& c : box_style->list_classes()) {
if (c == id_ || c == MODULE_CLASS) continue;
box_style->remove_class(c);
}
for (auto const& c : class_) {
box_style->add_class(c);
}
style->add_class("flat");
style->add_class("text-button");
style->add_class(MODULE_CLASS);
@@ -230,14 +241,20 @@ auto waybar::modules::Custom::update() -> void {
image_style->add_class("image-button");
event_box_.show();
if (!image_path_.empty()) {
auto pixbuf = Gdk::Pixbuf::create_from_file(image_path_, app_icon_size_, app_icon_size_);
image_.set(pixbuf);
try {
auto pixbuf =
Gdk::Pixbuf::create_from_file(image_path_, app_icon_size_, app_icon_size_);
image_.set(pixbuf);
} catch (const Glib::Error& e) {
spdlog::warn("custom {}: failed to load image-path '{}': {}", name_, image_path_,
std::string(e.what()));
image_.clear();
}
} else if (!image_name_.empty()) {
image_.set_from_icon_name(image_name_, Gtk::ICON_SIZE_INVALID);
image_.set_pixel_size(app_icon_size_);
}
image_.set_visible(!image_name_.empty() || !image_path_.empty());
label_.set_visible(!str.empty());
}
} catch (const fmt::format_error& e) {
@@ -251,6 +268,13 @@ auto waybar::modules::Custom::update() -> void {
}
// Call parent update
AIconLabel::update();
// Show a configured image-path/image-name image after the base update() so
// AIconLabel::update()'s icon gate cannot re-hide it. Leave the embedded-icon
// and "icon" cases to the base class (they have no image-path/image-name).
if (!image_name_.empty() || !image_path_.empty()) {
image_.set_visible(true);
}
}
void waybar::modules::Custom::parseOutputRaw() {