Skip to main content

Hyprland

Hyprland implements wlr-layer-shell-v1 natively, so awob works out of the box. Two integration patterns:

Pattern A: systemd user unit + auto-discovery

Recommended. The daemon starts when your graphical session starts; the bundled listeners auto-spawn; volume / brightness keys "just work" because awob-listener-pipewire and awob-listener-backlight see the underlying state changes directly.

# 1. Install awob and the listeners you want.
just install

# 2. Drop in the systemd user unit.
mkdir -p ~/.config/systemd/user
cp contrib/systemd/awob.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now awob.service

That's it. No keybinds to write. The PipeWire listener drives volume, the battery listener drives battery state, the backlight listener drives brightness.

If you're using uwsm (Universal Wayland Session Manager), the unit's WantedBy=graphical-session.target plays nice with it without any extra config.

If you're not using uwsm and your systemd user instance doesn't reach graphical-session.target automatically, the simplest fallback is to add awob-daemon to Hyprland's startup directly:

# ~/.config/hypr/hyprland.conf
exec-once = awob-daemon

Pick one or the other — running both means two daemons fighting for the IPC socket.

Pattern B: keybind-driven via awob send

If you'd rather not run listeners — or need finer-grained control over what shows up on screen — drive awob send from your keybinds. Add to ~/.config/hypr/hyprland.conf:

# Volume up / down via PulseAudio (works whether your audio backend
# is PipeWire or PulseAudio, thanks to pactl). Pipe through awob.
bind = , XF86AudioRaiseVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ +5% && \
awob send --preempt --icon audio-volume-high volume \
"$(pactl get-sink-volume @DEFAULT_SINK@ | grep -oP '\d+%' | head -1 | tr -d %)" 100

bind = , XF86AudioLowerVolume, exec, pactl set-sink-volume @DEFAULT_SINK@ -5% && \
awob send --preempt --icon audio-volume-low volume \
"$(pactl get-sink-volume @DEFAULT_SINK@ | grep -oP '\d+%' | head -1 | tr -d %)" 100

bind = , XF86AudioMute, exec, pactl set-sink-mute @DEFAULT_SINK@ toggle && \
awob send --preempt --icon audio-volume-muted --style critical mute 1 1

# Mic mute.
bind = , XF86AudioMicMute, exec, pactl set-source-mute @DEFAULT_SOURCE@ toggle && \
awob send --preempt --icon microphone-disabled --style critical mic 1 1

# Brightness up / down via brightnessctl.
bind = , XF86MonBrightnessUp, exec, brightnessctl set 5%+ && \
awob send --preempt --icon display-brightness brightness \
"$(brightnessctl -m | cut -d, -f4 | tr -d %)" 100

bind = , XF86MonBrightnessDown, exec, brightnessctl set 5%- && \
awob send --preempt --icon display-brightness brightness \
"$(brightnessctl -m | cut -d, -f4 | tr -d %)" 100

These rely on pactl and brightnessctl being installed (commonly already are on a Hyprland system).

Surface position

awob's stock themes anchor to the bottom of the focused output. Hyprland honours that natively. To anchor differently — top, side, specific monitor — edit your theme's surface { anchor … } block. See Themes → Surface.

If you have multiple outputs and want the OSD on a specific one, that requires either an explicit anchor on the surface or a future multi-output mode in the daemon — not implemented yet, see FUTURES.md.

Troubleshooting

SymptomLikely cause
OSD never appearsDaemon not running. systemctl --user status awob.service.
OSD shows but Hyprland flickersConflict with another layer-shell tool. Most commonly an old wob daemon — pkill wob.
Listener errors in journalThe relevant upstream isn't running (PipeWire), or your user lacks access to the underlying device (sysfs backlight / /sys/class/power_supply/* on some hardware).