Commit Graph
5279 Commits
Author SHA1 Message Date
Alexis Rouillard 6c3bd01bae Merge pull request #5251 from daher13/fix/format-backlight-module
fix: fix module backlight format using clang
2026-08-13 14:24:41 +02:00
Alexis Rouillard f95987d5c1 Merge pull request #5252 from daher13/feat/clang-makefile-archlinux
feat: clang format options added on makefile and docker image for arc…
2026-08-13 14:24:27 +02:00
Guilherme Daher ca46b9321f feat: clang format options added on makefile and docker image for archlinux 2026-08-13 08:56:48 -03:00
Guilherme Daher ab08e22494 fix: fix module backlight format using clang 2026-08-13 08:50:04 -03:00
Alexis Rouillard 1039ed8ee2 Merge pull request #5248 from daher13/fix/refresh-on-changeid
fix(hyprland/workspaces): handle workspace ID changes
2026-08-13 10:17:16 +02:00
Alexis Rouillard 9ca345e32c Merge pull request #5249 from shivankgarg98/fix/privacy-timeout-use-after-free
privacy: disconnect pending timeouts on destruction
2026-08-13 09:35:07 +02:00
Guilherme Daher e92f280a94 fix: formatted with clang 2026-08-12 17:06:44 -03:00
Shivank Garg 38cc11c3b0 privacy: disconnect pending timeouts on destruction
The privacy module registers timeout callbacks in the GLib main context.
The GeoClue callback uses sigc::mem_fun() with the Privacy object, but the
connection remains active when the module is destroyed during a bar reload.

If the timeout runs after destruction, it dereferences the freed Privacy
object and crashes Waybar:

  #0 waybar::modules::privacy::Privacy::locationTimeout(bool)
  #4 g_main_context_iteration()
  #5 g_application_run()

Disconnect the GeoClue and visibility timeout connections in the Privacy
destructor so no callback can run after the module is gone.

The unpatched binary crashed after four SIGUSR2 reloads at 1.5-second
intervals. The patched binary survived ten reloads.

Fixes: eeb7bc702e ("Added GeoClue2 privacy item")
Assisted-by: Claude Opus + Cursor
2026-08-13 01:07:14 +05:30
Guilherme Daher 5ef2da41be fix(hyprland/workspaces): handle workspace ID changes 2026-08-12 16:09:48 -03:00
Alexis Rouillard 084d87401d Merge pull request #5230 from toadjaune/patch-1
Replace lone tab character in style.css with spaces for consistency
2026-08-03 23:07:00 +02:00
Alexis Rouillard 5e713c5619 Merge pull request #5209 from gitmpr/backlight-default-min-brightness
config: add min-brightness to backlight example
2026-08-03 23:05:54 +02:00
Alexis Rouillard 7ceb61a64d Merge pull request #5210 from gitmpr/fix/backlight-min-brightness-step-clamp
fix(backlight): clamp scroll step to min-brightness
2026-08-03 23:05:40 +02:00
Arnaud Venturi e07ee87ab3 Replace lone tab character in style.css with spaces for consistency 2026-07-30 18:16:29 +02:00
Alexis Rouillard d44a27af10 Merge pull request #5219 from 10ne1/fix/sway-ipc-subscribe-race
fix(sway/ipc): don't mistake events for the subscribe reply
2026-07-30 10:11:18 +02:00
Alexis Rouillard d3fb8a621e Merge pull request #5216 from LukashonakV/enum-refactor
util/enum: make header-only and drop mandatory Hyprland dependency
2026-07-30 09:41:01 +02:00
Alexis Rouillard d7e0554b3c Merge pull request #5225 from JuustKiwi/fix-mpris-newlines
fix(mpris): sanitize metadata to prevent multiline UI expansion
2026-07-30 09:34:41 +02:00
Ibrahim Issa f9e2b1dea7 fix(mpris): sanitize metadata to prevent multiline UI expansion 2026-07-28 13:48:40 +02:00
Adrian RatiuandClaude Fable 5 6e0b50567e fix(sway/ipc): don't mistake events for the subscribe reply
Ipc::subscribe() assumes the next message on the event socket is the
reply to the IPC_SUBSCRIBE it just sent.

When a module subscribes more than once (sway/workspaces subscribes to
"workspace" and then to "window"), an event from the first subscription
can arrive before the reply to the second one. The payload check fails
and the thrown exception permanently disables the module for that bar.

This is easy to hit when bars are (re)created on output hotplug, since
sway emits a burst of workspace events at exactly that moment while
moving workspaces to the new output:

[warning] module sway/workspaces: Disabling module "sway/workspaces",
Unable to subscribe ipc event

Fix it by skipping over event messages (type high bit set) until the
subscribe reply is found, re-emitting them on signal_event so none are
lost.

Fixes: #5218
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Adrian Ratiu <adrian.ratiu@collabora.com>
2026-07-24 19:22:32 +03:00
Viktar Lukashonak 2d87bd5ba9 Drop mandatory hyprland dependency 2026-07-23 11:58:35 +03:00
Alexis Rouillard 30610d3b68 Merge pull request #5212 from bjnobre/fix/dynamic-tooltip-updates
fix(tooltips): keep dynamic tooltips from resetting hover delay
2026-07-21 21:13:14 +02:00
Alexis Rouillard 7fae3d7d43 Merge pull request #5213 from LukashonakV/cavaBump
cava bump
2026-07-21 15:08:37 +02:00
Viktar Lukashonak 5bd3cd4805 cavaBump 2026-07-21 15:17:55 +03:00
Bene-Jázem B. Nobre d32e7fa86f fix(tooltips): keep dynamic tooltips from resetting hover delay
Cache ALabel tooltip markup and provide it through query-tooltip instead of repeatedly setting GtkWidget's tooltip-markup property. This prevents frequently updating modules from restarting GTK's display-wide tooltip timer.

Keep the active tooltip updated directly so dynamic tooltip contents continue refreshing while the pointer remains stationary.
2026-07-20 11:20:39 -04:00
Alexis Rouillard 456f78ecb1 Merge pull request #5208 from Mrpaoo/ref/rm-dpemit
refactor: rm direct dp.emit() call in constructor.
2026-07-19 19:15:51 +02:00
gitmpr 7409ff6976 backlight: clamp scroll step to min-brightness
When min-brightness is set, a scroll step that would cross it was not
clamped — only scrolling while already at or below min was blocked.
With scroll-step: 5 and min-brightness: 1, scrolling from 5% would
pass the guard (5 > 1) and set brightness to 0%.

Fix by computing the post-step value before applying it: if it would
fall below min-brightness, set exactly to min-brightness instead.
2026-07-18 20:41:40 +02:00
gitmpr 937aca0b72 config: add min-brightness to backlight example config 2026-07-18 18:38:50 +02:00
yubo 5b8c98729f refactor: rm direct dp.emit() call in constructor. 2026-07-18 21:14:08 +08:00
Alexis Rouillard 7f732f0553 Merge pull request #5201 from grishatop1/master
use nmcli implementation for calculating WiFi signal strength
2026-07-16 22:24:23 +02:00
grisha e60ffa4a9c clang format 2026-07-15 22:52:46 +02:00
grisha 73fdafb5d3 use nmcli implementation for calculating signal strength 2026-07-15 16:15:09 +02:00
Alexis Rouillard d4a4417210 Merge pull request #5199 from LukashonakV/cavaImpr_2
refactor(cava): fix thread-safety, resource leaks, and style violations
2026-07-15 15:23:43 +02:00
Viktar Lukashonak 50f636236a man(waybar-cava): refresh and polish documentation
Synchronize the cava module man page with the current implementation:

- Fix scdoc table syntax (correct header/body cell prefixes)
- Add missing Waybar-side options: format-icons, vertex_shader, fragment_shader
- Remove options not consumed by the module (data_format, raw_target)
- Clarify option scope: raw-only, GLSL-only, and cava-config-only settings
- Update descriptions to match backend behavior:
  - ascii_range is derived from format-icons length
  - bar_height is ignored by Waybar
  - bar_delimiter is used for raw output
- Polish grammar, tighten structure, and fix example filenames
- Refresh STYLE and FRONTENDS sections to match the actual source
2026-07-15 15:46:37 +03:00
Viktar Lukashonak 52a5f74cd2 docs: merge coding conventions into CONTRIBUTING.md
Consolidate the standalone `CONVENTION.md` into `CONTRIBUTING.md` so that
all contributor guidelines live in a single, discoverable file.

Added sections:
- Language, build system, and formatting rules (Google style, clang-format)
- Naming conventions (PascalCase types, snake_case_ members, lowerCamelCase methods)
- Include ordering and header self-sufficiency requirements
- Class/module design patterns (AModule hierarchy, SafeSignal threading)
- JSON configuration and string handling guidelines
- GTK/Glib and OpenGL patterns
- Platform portability and RAII conventions
- Thread-safety rules (GTK single-threaded, background thread marshalling)
- Unsafe patterns to avoid (C-style casts, unbounded buffer copies)
- Singleton lifetime guidance (store config by value, no dangling refs)docs: merge coding conventions into CONTRIBUTING.md
2026-07-14 09:29:06 +03:00
Viktar Lukashonak 5c979152de refactor(cava): fix thread-safety, resource leaks, and style violations
Comprehensive refactor of the cava module backend and frontends.

Style & naming
- Rename Cava -> CavaRaw; snake_case methods -> lowerCamelCase
- Replace NULL with nullptr; replace C-style casts with static_cast
- Add explicit standard-library includes (<memory>, <string>, <chrono>)
- Fix missing trailing underscores on member variables

Architecture
- Remove Gtk::GLArea multiple inheritance in CavaGLSL (composition)
- Return std::unique_ptr from factory; add doAction() to GLSL variant
- Encapsulate thread timing arithmetic in AdaptiveDelay struct

Thread safety & correctness
- Replace raw sigc::signal with SafeSignal for cross-thread marshalling
- Fix data race between loadConfig() and out_thread_ (recursive_mutex)
- Fix audio_raw shallow-copy use-after-free via deep-copy AudioRaw payload
- Make loadConfig() exception-safe with CavaConfigGuard RAII
- Fix blocking read_thread_ race on shutdown (condition_variable + timeout join)
- Fix isSilent() data race (acquire pthread mutex)
- Eliminate doUpdate() recursion (iteration instead)
- Guard audio_raw_clean() against uninitialized state
- Fix format-icons underflow and cava_config buffer overflow
- Store config by value to prevent dangling references on reload
- Cache frontend config and refresh on runtime changes
- Fix signed-char icon lookup bug on x86
- Prevent Json::Value mutation bloat via const-ref lookups
- Broaden exception catches in worker threads (std::exception)

Resource management & GL robustness
- Fix OpenGL resource leaks (persist VBO/IBO/VAO; explicit destructor cleanup)
- Fix shader error handling crashes (valid infoLog allocation)
- Cache uniform locations instead of querying per frame
- Fix gradient color uninitialized stack memory (zero-init + clamped count)
- Fix shader time uniform integer division bug (float arithmetic)
- Add explicit VAO bind in onRender()
- Handle runtime surface config changes independently of shader changes
- Clamp negative gradient_count before GL upload

Follow-up
- Singleton API split (inst() + configure()) intentionally deferred to a
  dedicated PR because it changes the public constructor contract.
2026-07-13 19:50:09 +03:00
Alexis Rouillard cf19c836d3 Merge pull request #5197 from VlkrS/openbsd
fix(idle_inhibitor.cpp): Fix build for systems without SIGRTMIN/SIGRTMAX
2026-07-12 09:30:12 +02:00
Volker Schlecht 795047ba8b idle_inhibitor.cpp: Fix build for systems without SIGRTMIN/SIGRTMAX
See https://github.com/Alexays/Waybar/pull/4992 for reference
2026-07-11 23:36:59 +02:00
Alexis Rouillard 98b2a563f3 Merge pull request #5187 from pajlada/fix/add-waybar-load-manpage
docs(man): add load
2026-07-06 17:22:02 +02:00
Rasmus Karlsson b5abbdc696 docs(man): add load 2026-07-06 16:56:17 +02:00
Alex 624623215d ci(smoke): keep the compositor alive between hardware cases
hardware.sh called smoke::stop between umockdev cases, but smoke::stop runs
`swaymsg exit` and tears down the shared compositor -- so only the first case
(backlight) had a display and the rest failed with "cannot open display".
Kill only waybar between cases; leave compositor teardown to the EXIT trap.
2026-07-06 02:08:06 +02:00
Alex eee2ab92fe style(bluetooth): clang-format the enumerate args 2026-07-05 23:12:38 +02:00
Alexis Rouillard b3e9545899 Merge pull request #5184 from Alexays/fix/smoke-state-hang
ci(smoke): fix state tier hang from bare wait on a lingering daemon
2026-07-05 23:12:19 +02:00
AlexandClaude Opus 4.8 4222d5a213 ci(smoke): fix state tier hang from bare wait on a lingering daemon
The state tier started actually running mpd in 74f0d33, which exposed a
deadlock in teardown: state.sh launches `mpd --no-daemon &` and never kills
it during the tier, and its cleanup() called smoke::stop *before* killing mpd.
smoke::stop ended in a bare `wait`, which reaps *every* background job of the
shell -- including the still-running mpd -- so it blocked until GitHub's 6h
job timeout. continue-on-error doesn't help: it catches failures, not hangs.

- lib.sh: smoke::stop now waits only on the PIDs it owns (waybar, compositor),
  so an unrelated daemon left running by a tier can't deadlock teardown.
- state.sh: cleanup() tears down mpd/pulseaudio before smoke::stop.
- smoke.yml: add timeout-minutes: 20 so a future hang fails fast instead of
  burning the default 6h runner budget.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 23:10:07 +02:00
Alex 6294ed2520 fix(hyprland/language): apply the CSS class on the main thread
onEvent() runs on the Hyprland IPC listener thread and mutated the label's
style context (add/remove class) directly, racing the GTK main thread's
drawing and corrupting the heap (double free / corrupted double-linked list).
Follow the Submap pattern: onEvent only stores the layout under the mutex and
emits the dispatcher; update() swaps the CSS class on the main thread, tracking
the previously applied class.

Fixes #4665
2026-07-05 23:06:37 +02:00
Alex 6c1a0fa185 fix(bluetooth): accept module-level placeholders in enumerate formats
tooltip-format-enumerate-connected[-battery] only received the device_* args,
so {status}, {num_connections} and {controller_*} threw fmt "argument not
found". Pass those args to the enumerate fmt::format as well.

Fixes #4384
2026-07-05 23:06:37 +02:00
Alex 6d5d5f0768 fix(cava): throw instead of exit() on a bad config
loadConfig() called exit(EXIT_FAILURE) when the cava config failed to load or
no input source was available, killing the whole bar. Throw std::runtime_error
instead: the factory/bar catch it at construction and disable only the cava
module. The read_thread_ also calls loadConfig() at runtime, so contain the
throw there too, logging instead of terminating.

Fixes #4456
2026-07-05 23:06:37 +02:00
Alex 699589b66a fix(river/tags): parse hide-vacant once, not in the wl callbacks
config_["hide-vacant"].asBool() was called from the river status listeners.
When the option is given as a string ("true") jsoncpp's asBool() throws
"Value is not convertible to bool", and that exception unwinding through
libwayland's C dispatch aborts the process. Parse it once in the constructor
into a bool member (accepting the string form) and read the cached value.

Fixes #4078
2026-07-05 23:06:37 +02:00
AlexandClaude Opus 4.8 a7b3a2c0db ci(smoke): fix state tier hang from bare wait on a lingering daemon
The state tier started actually running mpd in 74f0d33, which exposed a
deadlock in teardown: state.sh launches `mpd --no-daemon &` and never kills
it during the tier, and its cleanup() called smoke::stop *before* killing mpd.
smoke::stop ended in a bare `wait`, which reaps *every* background job of the
shell -- including the still-running mpd -- so it blocked until GitHub's 6h
job timeout. continue-on-error doesn't help: it catches failures, not hangs.

- lib.sh: smoke::stop now waits only on the PIDs it owns (waybar, compositor),
  so an unrelated daemon left running by a tier can't deadlock teardown.
- state.sh: cleanup() tears down mpd/pulseaudio before smoke::stop.
- smoke.yml: add timeout-minutes: 20 so a future hang fails fast instead of
  burning the default 6h runner budget.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 23:00:33 +02:00
Alex 74f0d3393a ci(smoke): fix the mpd / hardware / leak tiers so they actually run
The first run went green but the best-effort tiers silently didn't exercise
anything:

- state.sh: the mpd `audio_output { ... }` block was on one line, which mpd
  rejects ("Unknown tokens after '{'"), so mpd never started and the mpd
  sub-tier (the #5183 empty-queue repro) skipped. Split the block across lines.
  Also move teardown into a cleanup() with `|| true` so a dead-pid kill under
  `set -e` no longer makes the step exit 1.
- hardware.sh: umockdev-run's LD_PRELOAD lands ahead of the linked-in ASan
  runtime, so ASan aborted before main() ("ASan runtime does not come first")
  and waybar never started -- the backlight/slider (#5179) path wasn't tested.
  Set verify_asan_link_order=0 so the instrumented binary runs under the preload.
- leakcheck.sh: abort_on_error=1 turned LSan's exit report into a core dump;
  force abort_on_error=0 for this report-only tier.
- lib.sh: assert_clean now also flags "ASan runtime does not come first" so a
  future preload/link-order regression fails loudly instead of passing.
2026-07-05 22:39:35 +02:00
Alex 9a10949938 ci(smoke): cover teardown, state transitions and fake hardware
The smoke test only exercised steady-state rendering and killed waybar with
SIGTERM, so whole crash classes were invisible: exit-time use-after-free
(#5182), module state transitions (#5183) and hardware-backed modules (#5179).
Add tiers that hit those paths under ASan (+ _GLIBCXX_ASSERTIONS):

- lib.sh: assert_clean_exit (SIGINT teardown -> checks segfault/abort + ASan
  report emitted during destruction), output hotplug helpers, signal/reload,
  WAYBAR_WRAP hook, opt-in leak detection.
- lifecycle.sh (gating): clean exit, runtime output hotplug (Bar/module
  destroy), toggle/reload churn, fast-interval teardown race (#5182 class).
- fuzz.sh (gating): pathological custom-backend output (empty, nonzero exit,
  invalid JSON, huge, non-UTF8, empty format).
- coverage.sh (gating): every Factory module must be classified for smoke
  coverage; a new unlisted module fails the job (#5179 slipped through).
- modules.sh: also render the whole matrix inside a group; SIGINT teardown per
  module instead of SIGTERM.
- state.sh (best-effort): real mpd driven through an empty queue (#5183) +
  stop/clear; pulseaudio + slider on a null sink.
- hardware.sh (best-effort): backlight, backlight/slider (#5179) and battery
  via umockdev.
- leakcheck.sh (report-only): clean-exit run under LSan.
2026-07-05 22:21:46 +02:00
Alex 445e2aec1f fix(bar): avoid use-after-free segfault on exit
Members are destroyed in reverse declaration order, so modules_all_ (and
the modules it owns) are gone before the GtkWindow. Tearing down a mapped
window emits `unmap`, whose handler runs toggleSuspend() over the already
freed modules. Disconnect the map/unmap handlers in ~Bar first.

Fixes #5182
2026-07-05 22:03:28 +02:00