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.
- Add "muted" class for styling the muted state.
- Add "zero-on-mute" boolean option to control slider position
when muted.
- Add "unmute-on-volume-change" boolean option to control whether
to automatically unmute when the volume changes.
When switching between workspaces rapidly (especially empty ones),
Hyprland sends createworkspace and destroyworkspace events slightly
out of order. This causes workspace buttons to render in wrong
positions for a split second before snapping to their correct spots.
Add a 7ms debounce timer that batches workspace events before
calling dp.emit(), preventing the visual glitch.
Fixes#4376
Tray::update() already had logic to hide the module when all child items were passive, but it was only re-run on item add/remove — never on a status change. When the last visible item transitioned to Passive, the item hid itself but the now-empty module remained visible.
Connect Tray to each item's Gtk::EventBox signal_show/signal_hide so update() runs on every visibility transition, and simplify update() to check child->get_visible() directly instead of inspecting the `passive` CSS class. The Tray-level `show-passive-items` read becomes redundant since Item already honours it when deciding its own visibility; remove it along with the now-unused Tray::show_passive_ member.
Fixes: #3721
Move buildLuaDispatch and isLuaProtocol from private to
protected/public so IPCTestHelper can access them.
Add 7 tests covering all buildLuaDispatch branches, dispatch
error path, and isLuaProtocol cache behavior.
Adds the following:
- bandwidthDownByesCompact
- bandwidthUpByesCompact
Differences from normal version:
- drop the "/s" suffix
- drop the deciaml part if less than 1MB/s
Hyprland 0.54 replaced the text-based dispatch socket protocol with a
Lua-based one. Commands like "dispatch workspace 1" are now interpreted
as invalid Lua (return hl.dispatch(workspace 1)), breaking workspace
clicks and scroll navigation.
Add IPC::dispatch() that probes the running Hyprland on first call and
routes commands through the new hl.dsp Lua API when the Lua protocol is
detected, falling back to the old text format otherwise.
Enable per-workspace styling by adding the workspace name as a
CSS class to each workspace button. The name is sanitized to a
valid CSS identifier: lowercased, non-alphanumeric characters
collapsed to hyphens, digit-leading names prefixed with "ws-".
Examples: "IDE" → .ide, "special:telegram" → .telegram, "1" → .ws-1
Allows users to style individual workspaces:
#workspaces button.telegram { color: #54a0e0; }
In order to obtain the RX and TX bitrates from the kernel netlink we need to open a second info socket to get the station data. The values are formatted like "1.9Gb/s" and then exposed as `rx_bitrate` and `tx_bitrate`.
This code is closely following the `iw` implementation.
When netlink events (link/addr/route changes) fire between timer
intervals, dp.emit() triggers update() which consumes the byte delta
and resets bandwidth_down_total_. A subsequent timer update sees
near-zero delta, displaying very small bandwidth.
Cache the last computed bandwidth values and skip recalculation
when update() is called within half the interval. Event-driven
updates reuse the cached values instead.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This allows users to use #RRGGBBAA format in their style.css.
The client now detects 8-bit hex codes, transforms them into
GTK-compatible rgba() syntax, and loads the modified data
into the CSS provider.
- Added utility to detect 8-bit hex patterns.
- Added transformation logic to convert hex alpha to decimal.
- Intercepted CSS loading in Client::setupCss to handle the conversion.
The iso8601 flag previously controlled both the calendar grid layout
and the week number format as a coupled boolean. This adds a new
weeks-numbering option (iso/monday/sunday) that explicitly overrides
just the week number calculation method, independent of iso8601 and
locale settings. Existing behaviour is fully preserved when the option
is not set.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These Nerdfonts codepoints were removed in [3.0.0](https://www.nerdfonts.com/releases#v3.0.0):
> **Breaking 2: Material Design Icons Codepoints**
>
> The old Material Design Icon codepoints are finally dropped. Due to an historic mistake we placed them in between some asiatic glyphs, breaking that script. Since v2.3.0 the (updated and expanded) Material Design Icons have new codepoints in the 5 digit region.
>
> - Dropped codepoints `F500`… and class names `nf-mdi-*`
> - New codepoints `F0001`… and class names `nf-md-*`
> - The whole discussions are here: https://github.com/ryanoasis/nerd-fonts/issues/365
> - A translation table is available here: https://github.com/ryanoasis/nerd-fonts/issues/1059#issuecomment-1404891287
> - There are tools out there that probably can update your configuration.
For the majority of the removed symbols, it was as easy as finding the
replacement with the exact same name. For example, `f76b` (`nf-mdi-format_header_2`)
became `f026c` (`nf-md-format_header_2`).
There was one symbol that was completely removed (it was removed from
Material Design): `f5fc` (`nf-mdi-camcorder_box`). I have substituted it
with `f03d` (`nf-fa-video_camera`) which is not Material Design, but the
closest icon I could find.
Here's some example output from [nerdfix](https://github.com/loichyan/nerdfix)
```
╭─(ignormies)(~/g/fork-waybar) removed-nerdfonts-codepoints
╰──▪ nix-shell -p nerdfix --run "nerdfix check resources/config.jsonc"
INFO Check input from 'resources/config.jsonc'
☞ Found obsolete icon U+F76B
╭─[resources/config.jsonc:131:27]
130 │ "format": "{temperatureC}°C {icon}",
131 │ "format-icons": ["", "", ""]
· ┬
· ╰── Icon 'mdi-format_header_2' is marked as obsolete
132 │ },
╰────
help: You could replace it with:
1. U+F026C md-format_header_2
2. U+F026B md-format_header_1
3. U+F026D md-format_header_3
4. U+F026E md-format_header_4
☞ Found obsolete icon U+F769
╭─[resources/config.jsonc:131:41]
130 │ "format": "{temperatureC}°C {icon}",
131 │ "format-icons": ["", "", ""]
· ┬
· ╰── Icon 'mdi-format_float_right' is marked as obsolete
132 │ },
╰────
help: You could replace it with:
1. U+F026A md-format_float_right
2. U+F0268 md-format_float_left
3. U+F0269 md-format_float_none
4. U+F0263 md-format_align_right
☞ Found obsolete icon U+F5E7
╭─[resources/config.jsonc:146:41]
145 │ "format-full": "{capacity}% {icon}",
146 │ "format-charging": "{capacity}% ",
· ┬
· ╰── Icon 'mdi-cached' is marked as obsolete
147 │ "format-plugged": "{capacity}% ",
╰────
help: You could replace it with:
1. U+F00E8 md-cached
☞ Found obsolete icon U+F796
╭─[resources/config.jsonc:170:45]
169 │ "format-wifi": "{essid} ({signalStrength}%) ",
170 │ "format-ethernet": "{ipaddr}/{cidr} ",
· ┬
· ╰── Icon 'mdi-gamepad_variant' is marked as obsolete
171 │ "tooltip-format": "{ifname} via {gwaddr} ",
╰────
help: You could replace it with:
1. U+F0297 md-gamepad_variant
2. U+F0EB7 md-gamepad_variant_outline
3. U+F0462 md-road_variant
4. U+F025C md-food_variant
☞ Found obsolete icon U+F796
╭─[resources/config.jsonc:171:50]
170 │ "format-ethernet": "{ipaddr}/{cidr} ",
171 │ "tooltip-format": "{ifname} via {gwaddr} ",
· ┬
· ╰── Icon 'mdi-gamepad_variant' is marked as obsolete
172 │ "format-linked": "{ifname} (No IP) ",
╰────
help: You could replace it with:
1. U+F0297 md-gamepad_variant
2. U+F0EB7 md-gamepad_variant_outline
3. U+F0462 md-road_variant
4. U+F025C md-food_variant
☞ Found obsolete icon U+F796
╭─[resources/config.jsonc:172:44]
171 │ "tooltip-format": "{ifname} via {gwaddr} ",
172 │ "format-linked": "{ifname} (No IP) ",
· ┬
· ╰── Icon 'mdi-gamepad_variant' is marked as obsolete
173 │ "format-disconnected": "Disconnected ⚠",
╰────
help: You could replace it with:
1. U+F0297 md-gamepad_variant
2. U+F0EB7 md-gamepad_variant_outline
3. U+F0462 md-road_variant
4. U+F025C md-food_variant
☞ Found obsolete icon U+F6A9
╭─[resources/config.jsonc:180:36]
179 │ "format-bluetooth": "{volume}% {icon} {format_source}",
180 │ "format-bluetooth-muted": " {icon} {format_source}",
· ┬
· ╰── Icon 'mdi-cup' is marked as obsolete
181 │ "format-muted": " {format_source}",
╰────
help: You could replace it with:
1. U+F01AA md-cup
☞ Found obsolete icon U+F6A9
╭─[resources/config.jsonc:181:26]
180 │ "format-bluetooth-muted": " {icon} {format_source}",
181 │ "format-muted": " {format_source}",
· ┬
· ╰── Icon 'mdi-cup' is marked as obsolete
182 │ "format-source": "{volume}% ",
╰────
help: You could replace it with:
1. U+F01AA md-cup
☞ Found obsolete icon U+F590
╭─[resources/config.jsonc:186:28]
185 │ "headphone": "",
186 │ "hands-free": "",
· ┬
· ╰── Icon 'mdi-battery_unknown' is marked as obsolete
187 │ "headset": "",
╰────
help: You could replace it with:
1. U+F0091 md-battery_unknown
2. U+F094A md-battery_unknown_bluetooth
3. U+F17DE md-battery_arrow_down
4. U+F0750 md-microsoft_xbox_controller_battery_unknown
☞ Found obsolete icon U+F590
╭─[resources/config.jsonc:187:25]
186 │ "hands-free": "",
187 │ "headset": "",
· ┬
· ╰── Icon 'mdi-battery_unknown' is marked as obsolete
188 │ "phone": "",
╰────
help: You could replace it with:
1. U+F0091 md-battery_unknown
2. U+F094A md-battery_unknown_bluetooth
3. U+F17DE md-battery_arrow_down
4. U+F0750 md-microsoft_xbox_controller_battery_unknown
```
Load attention and overlay pixmaps from item properties, watch the
corresponding update signals, and prefer attention artwork while an item is in
NeedsAttention state.
When an item only exports an attention movie asset, fall back to loading that
asset as a static pixbuf so the tray still shows the alert state.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
Only add tray widgets after the SNI proxy has finished initializing and the
item has a valid id/category pair.
This also removes invalid items through the host teardown path, refreshes the
tray when item status changes, and avoids calling DBus methods through a null
proxy during early clicks or scroll events.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>
Hyprland workspace reloads could stack duplicate scroll-event connections,
causing a single wheel gesture to switch multiple workspaces after repeated
config reloads. The persistent-workspaces monitor-array form also created the
monitor name instead of the configured workspace name.
Disconnect and replace the scroll handler on reinit, fix the persistent
workspace name selection, normalize urgent-window address matching, and reject
malformed workspace payloads before they corrupt the local state machine.
Signed-off-by: Austin Horstman <khaneliman12@gmail.com>