The MPD state machine drives all connection attempts from Glib::signal_timeout
callbacks, which run on the GTK main loop. tryConnect() called
mpd_connection_new() with the user-facing timeout_ (up to 30s by default), so an
unreachable server blocked the whole bar for the full connect timeout.
Bound the connect attempt to a short fixed timeout (2000 ms) so a dead server
fails fast, then restore the configured timeout_ for subsequent command reads so
slow-but-alive servers are unaffected.
Fixes#1186.
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>
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.
- Replaced pass-by-value std::string parameters with const std::string&
or std::string_view to prevent SSO overallocations.
- Refactored static mapping functions in UPower to return
std::string_view instead of constructing std::string literals, enabling
perfect cache locality.
- Optimized string concatenation in hot loops (network IPs, inhibitor
lists, sway window marks) by using std::string::append() and
pre-reserving capacity instead of overloaded operator+ which produces
temporary heap instances.
These optimizations reduce high-frequency memory churn and overall heap
fragmentation within the main rendering loops.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
There were two main issues with fmtlib and C++20 mode:
- `fmt::format` defaults to compile-time argument checking and requires
using `fmt::runtime(format_string)` to bypass that.
- `std::format` implementation introduces conflicting declarations and
we have to specify the namespace for all `format`/`format_to` calls.
gtk requires some chars (<>&"') to be encoded for them to render
properly. `sanitize_str` sanitizes raw strings that have such chars and
returns a properly encoded string
Mouse-over tooltips set on the label only appear once the mouse hovers
over exactly the label. Other apps (e.g. firefox) show the tooltip once
the pointer hovers the button. Not solely its label. With this commit we
get the same behaviour.
Fixes issue where the class parameters in style.css would have no
effect.
The CSS now references the GtkButton instead of the GtkLabel. Removing
all style-classes from the custom module GtkButton however removes
any properties set via style.css. Thus, the default classes 'flat' and
'text-button' are added on every update of these modules.
The AButton class is designed as full a substitute to ALabel. The
GtkButton attribute 'button_' is initialized with a label. This
label can the be referenced by the subsequent inheritors of AButton
instead of the GtkLabel attribute 'label_' of ALabel.
For convenience a GtkLabel* 'label_' attribute is added to AButton.
If the button cannot be clicked it is disabled, effectively acting
like its label predecessor.
GtkButton seems to catch one-click mouse events regardless of the
flags set on it. Therefore, 'signal_pressed' is connected to a
function creating a fake GdkEventButton* and calling 'handleToggle'
(for details on this possible bug in GTK see:
https://stackoverflow.com/questions/45334911 )
In accordance with other GtkButtons (i.e. the sway/workspace ones)
set_relief(Gtk::RELIEF_NONE) is called on the 'button_' instance.
If the primary output does not support changing volume MPD will report
-1. Ensure that negative volume levels will be represented as 0 instead.
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
Allow the user to show the current volume from MPD status via the
`format` and/or `tooltip-format` configuration options.
The values are provided by libmpdclient and are integers, generally
between 0-100 (without %). Values above 100 are also possible, as mpd
output plugins like `pulse` support volumes above 100%.
Signed-off-by: Sefa Eyeoglu <contact@scrumplex.net>
There was one uninitialized value warning and two mismatched-sign
compare warnings. They both appear valid, the first occurring when MPD's
"format-stopped" contains {songPosition} or {queueLength} and the second
occurring when the clock's "timezones" array is more than 2 billion
items long (not likely, I admit). Fix both issues.
- Add elapsedTime and totalTime to tooltip format arguments
- Catch format exceptions and print error
- Copy mpd connection error message before it gets freed
- Update display after connection to mpd was lost
- Add MPD module option `password`, and document it.
- Add logic to send the password, directly after connecting to
MPD.
Fixes: #576
Signed-off-by: Joseph Benden <joe@benden.us>
Fix MPD connection issues by converting/rewriting module into a
state-machine driven system. It is fully single-threaded and uses
events for transitioning between states. It supports all features
and functionality of the previous MPD module.
Signed-off-by: Joseph Benden <joe@benden.us>
Fix MPD connection issues by converting/rewriting module into a
state-machine driven system. It is fully single-threaded and uses
events for transitioning between states. It supports all features
and functionality of the previous MPD module.
Signed-off-by: Joseph Benden <joe@benden.us>