set_current_layout() mutated label_'s GTK style context (remove_class/
add_class) while being called from the sway IPC worker thread via
onEvent(). Off-main-thread GTK widget mutation caused a SIGSEGV.
Record only the target layout in set_current_layout() and apply the
matching CSS class in update(), which the dispatcher runs on the GTK
main thread. A new applied_class_ member tracks the currently applied
class so update() can swap it. The shared layout_/applied_class_ state
is guarded by the existing mutex_.
Fixes#3702.
The Portal constructor synchronously auto-starts org.freedesktop.portal.Desktop
via a Gio::DBus::Proxy. If that service fails or crashes on start it throws a
Glib::Error, which was previously uncaught and terminated Waybar. Wrap the
construction in a try/catch, log a warning and leave portal as nullptr on
failure, and null-guard every dereference so a missing portal simply disables
light/dark appearance detection instead of crashing.
Fixes#3140, #3601.
Building a zoned_time/zoned_seconds from a local_time throws
ambiguous_local_time during the DST fall-back hour and nonexistent_local_time
across the spring-forward gap. update() runs this every minute with the
tooltip enabled by default and has no try/catch, so Waybar aborts every
minute during a DST transition. Pass choose::earliest at each construction to
resolve deterministically instead of throwing.
Fixes#2615; resolves the recurring DST-crash duplicates #5006, #5018, #5063,
#5096, #3024.
- parseOutputJson() passed script text/alt/tooltip straight to Pango/GTK; an
invalid-UTF-8 byte aborted the bar in g_utf8_collate. Validate/make_valid
like parseOutputRaw already does. Fixes#2829.
- restart-interval:0 was floored to 1ms, respawning the script ~1000x/s and
starving the main loop; a non-positive restart-interval now stops instead.
Part of #4842.
std::max(1L, interval*1000) turned a user's explicit "interval": 0 into a
1ms periodic refresh, i.e. a ~1000x/s busy loop that starves the GTK main
loop and leaks memory (mpris RSS growth, missing tooltips, frozen updates).
An explicit 0 now stays the 'no periodic refresh' sentinel. Fixes#4987,
#4842; helps #4864, #4917, #4998, #5145.
The format-<short_description>[-<variant>] override branches only passed a
positional arg, so a format using {short}/{long}/{variant} threw 'argument
not found', which disabled the whole module. Now supply the same named args
as the fallback/tooltip branches. Fixes#5120.
refresh() called config_["signal"].asInt() unconditionally on every RT
signal; a non-integer "signal" value throws Json::LogicError and aborts
Waybar. Matches the guard already present in custom/image/idle_inhibitor.
Fixes#3514.
generate.py now keeps _Sidebar.md in sync: any Module:-* page from the
mapping that is not yet linked is inserted alphabetically into the
Modules list. Existing entries (custom labels, nested sub-entries,
hand-written non-module links) are left untouched, so adding a module no
longer requires editing the sidebar by hand.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add tooling that makes the scdoc man pages the single source of truth and
regenerates the wiki module pages from them:
- .github/wiki/mapping.json: man-page -> wiki-page mapping (aggregation-aware)
- .github/wiki/generate.py: scdoc -> pandoc -> gfm, strips man-only sections,
concatenates aggregated pages, appends optional extras/<Page>.md
- .github/wiki/extras/: hand-kept appendices (screenshots) with no man equivalent
- .github/workflows/wiki.yml: on push to man/** (or the tooling), regenerate
and push the wiki; other wiki pages are left untouched
Covers all 65 man pages -> 45 wiki pages (5 new: GPS, Inhibitor, Mango, Menu,
WWAN). Non-module and hand-written wiki pages are never modified.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Port information that previously lived only in the GitHub wiki into the
authoritative scdoc man pages, so the man pages become the single source
of truth for module documentation.
33 man pages enriched (options, format replacements, actions, style
selectors, troubleshooting and implementation notes). Additions were
verified against the source; stale/incorrect wiki entries were
deliberately not ported. All pages still compile with scdoc.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A full man<->code consistency audit surfaced options, format placeholders
and CSS classes that were implemented but undocumented, documented but not
implemented (some causing fmt crashes when copied from examples), and
defaults that disagreed with the code. This aligns the docs with the code
and fixes a few genuine code gaps.
Docs:
- Add the missing waybar-user(5) man page (and register it in meson.build)
- Document previously-undocumented options/placeholders/CSS across many
modules (custom image-path/image-name/icon-size, graph_type/width/
datapoints; battery smooth-power; wireplumber format-source/only-physical;
mpris {position}/prefer-album-artist; network {signalStrengthApp}/compact
bandwidth; pulseaudio {source_volume}/{source_desc}; upower {temperature}/
{model}/{native-path}; wwan {power_state}/{imei}; tray ignore-list; and
many CSS state classes: .sink-muted, .source-muted, .workspace-hover, etc.)
- Correct documented defaults to match the code (hyprland format {name},
gamemode {count}, cpu-graph interval 5, cava input_delay 4, niri taskbar
icon-size 16, disk/gps/wayfire formats, menu-actions object type, ...)
- Remove placeholders/options that do not apply (custom-graph {icon}/format/
format-icons/rotate) and fix crashing examples (wwan {mode}, gps
format-no-fix); note cava background/foreground/continuous_rendering are
cava-config-file options
Code:
- bluetooth: accept the documented `controller` key as a synonym of
`controller-alias` (the option was silently ignored)
- mango/workspaces: supply the documented `{name}` fmt arg (was missing ->
fmt::format threw)
- privacy: read `tooltip` as a bool (was guarded on isString(), so the
documented `tooltip: false` was silently ignored)
All man pages validated with scdoc 1.11.4. Not compiled locally (no gtkmm);
C++ build relies on CI.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
On Debian sid, `dependency('systemd')` needs systemd.pc, which is shipped by
the `systemd-dev` package, not `libsystemd-dev`. Add it so the forced
-Dsystemd=enabled configure step succeeds.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The linux matrix ran every distro with features in `auto` mode, so any
module whose dependency was missing from the image was silently skipped
and never compiled. Three modules (privacy/pipewire, gps, wwan) were built
by no CI job at all, and several others only on one or two distros.
Add a dedicated `build-full` job (Debian image) that installs the missing
dependencies inline and force-enables every optional feature, turning a
broken include or a missing dep into a hard build error instead of a silent
skip. Drop `debian` from the auto matrix since `build-full` uses the same
image and builds a strict superset.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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>
Adds an ethernet link speed ({linkSpeed}) read from
/sys/class/net/<iface>/speed, plus a skip-decimal option on pow_format
to drop a trailing .0. Rebased onto master's store-based network
formatting; existing compact bandwidth args updated for the new
pow_format signature.
Adds a per-workspace app-icon taskbar (Workspace class) to the
niri/workspaces module. Rebased onto master: integrated with the
existing window-rewrite feature so the {windows} and {total} format
replacements continue to work alongside the new taskbar.
Rebased onto current master and fixed the privacy module build:
- privacy_item.hpp no longer includes privacy.hpp (it does not use the
Privacy class); this broke the circular include that left PrivacyItem
undeclared when privacy.hpp was reached first from privacy_item.cpp.
- privacy_item.cpp now includes gtkmm/label.h explicitly, since Gtk::Label
was previously only pulled in transitively via privacy.hpp.
Adds format-window-separator, window-rewrite and window-rewrite-default
options plus the {windows} format replacement to the niri/workspaces
module (rebased onto master; coexists with ignore-workspaces).
The ModemManager libmm-glib library installs its pkg-config file as
mm-glib.pc (not libmm-glib.pc), so dependency('libmm-glib') never
resolved and the nix-flake-check build failed with the wwan module
enabled.
- update(): only hide the module when hide-disconnected is set AND the
modem is not in the CONNECTED state, instead of hiding it unconditionally
(the module was invisible by default).
- free the gchar* returned by mm_modem_dup_physdev/
mm_modem_dup_equipment_identifier/mm_sim_dup_operator_name.
- meson.build: drop duplicate libgps dependency, install the wwan man page.
- man: document hide-disconnected (replacing the unimplemented
hide-failed/hide-disabled/hide-not-registered options).
- remove stray empty subprojects/.wraplock.