Currently, modules polling hardware nodes continuously wake up kernel drivers even when the monitor is asleep (e.g., DPMS off), flooding dmesg.
- Adds 'disable-on-sleep' config flag
- Hooks GTK window map/unmap signals to track DPMS state
- Propagates suspend/resume calls to AModule worker threads
Fixes a bug where removing a hot-plugged device mid-loop causes a filesystem error that turns into a fatal runtime error that crashes waybar entirely, changed to warning instead of runtime error.
### Problem
Waybar segfaults on startup when `niri/workspaces` is the only configured
module (default options). Right after the first `WorkspacesChanged` event:
Thread 1 "waybar" received signal SIGSEGV
#0 gtk_label_set_markup ()
#1 waybar::modules::niri::Workspaces::doUpdate () at src/modules/niri/workspaces.cpp:106
### Root cause
[doUpdate()](cci:1://file:///home/lj/Downloads/Waybar/src/modules/niri/window.cpp:27:0-90:1) set the label markup via:
static_cast<Gtk::Label*>(button.get_children()[0])->set_markup(name);
The button's child *is* a valid `GtkLabel`, but gtkmm's `get_children()`
returns it wrapped as a generic `Gtk::Widget` (confirmed: `dynamic_cast`
to `Gtk::Label*` yields `nullptr`). The unchecked `static_cast` then
performs an invalid downcast, producing a corrupt pointer whose `gobj()`
is garbage (`0x1`), so `gtk_label_set_markup()` dereferences it and crashes.
This is reliably triggered when no other module has instantiated a
`Gtk::Label` yet (so the `Gtk::Label` wrapper isn't registered), which is
exactly the case for a `niri/workspaces`-only bar. The same idiom exists in
`sway/workspaces` and `wayfire/workspaces`; it's masked there because typical
configs include other label-using modules.
### Testing
- Reproduced the crash on 0.15.0 / current `master` with a minimal
`"modules-left": ["niri/workspaces"]` config under niri.
- After the fix: no crash; three workspace buttons render with correct
names/labels (`niri-workspace-1/2/3`).
Fix an issue in the MPD module where text failed to render
when raw tags containing markup characters were truncated
mid-sequence after sanitization,
resulting in fragmented XML entities (such as `&` cut into `&am`).
Resolve this by shifting the order of operations to
truncate the raw strings *before* running `sanitize_string`.
To keep `setLabel` decoupled and clean,
we introduce helper methods (`getArtistStr`, `getAlbumArtistStr`,
`getAlbumStr`, `getTitleStr`) inside the `MPD` class,
matching the architectural style of MPRIS.
Additionally:
- Introduce support for the customizable `ellipsis` config option
(defaulting to `…`).
- Switch the truncation logic of the MPD module to be
visual-width-aware using the newly extracted
`waybar::util::utf8_truncate`.
- Decouple the tooltip text from the main label's truncated text.
The tooltip now displays un-truncated, complete metadata
(properly escaped), providing a significantly better user
experience.
Fix an issue where the mpris module's tooltip failed to render
when track metadata contained unescaped XML/HTML markup characters.
This occurred because
the mpris module formatted raw strings into the tooltip template
before passing the final string directly to `set_tooltip_markup()`,
triggering GTK/Pango parsing warnings and rendering failures.
Resolve this by wrapping tooltip metadata fields
in `Glib::Markup::escape_text` before formatting,
ensuring Pango-compliant strings are always delivered to the GTK
tooltip markup.
Move the UTF-8 visual-width measurement and truncation helper functions
from the mpris module to a common utility
(include/util/utf8_string.hpp and src/util/utf8_string.cpp).
This decouples string truncation and width measurement
from the mpris module, allowing other modules (like mpd) to reuse.
The helper function `utf8_truncate` (formerly `truncate` in mpris)
and `utf8_width` is exported under the `waybar::util` namespace,
while the low-level `measure_and_truncate` (formerly `utf8_truncate`)
is encapsulated in an anonymous namespace in src/util/utf8_string.cpp
to avoid unnecessary API exposure.
No functional changes were made to the mpris module's behavior.
The handleScroll method unconditionally dispatched workspace cycling commands
and never checked for custom on-scroll-up/on-scroll-down config values.
Register the scroll handler when custom scroll commands are configured (even
without enable-bar-scroll), and delegate to AModule::handleScroll so user
commands are executed, matching the pattern used by other modules.