Enable Yambar to show Hyprland workspaces.
Once installed use the Yambar config further down in the README. You'll need
to adjust the script
path depending on your installation method.
Assuming you have Rust installed, run:
$ cargo install yambar-hyprland-wses
Use ~/.cargo/bin/yambar-hyprland-wses
as your script path
There is a community maintained package available in the AUR which can be installed manually or with any AUR helper.
Assuming you have paru, run:
$ paru -S yambar-hyprland-wses
Assuming you have yay, run:
$ yay -S yambar-hyprland-wses
Or if you would like to install the package without an AUR helper use:
$ git clone https://aur.archlinux.org/yambar-hyprland-wses.git
$ cd yambar-hyprland-wses
$ makepkg -si
Use /usr/bin/yambar-hyprland-wses
as your script path.
There is a community maintained Nix package on nixpgs but I could not find documentation on how to configure it, so you are on your own a little bit here. Pull requests with documentation on this are welcome :)
Yambar doesn't currently have a mechanism for displaying Hyprland workspaces. There is at least one polling script out there that does it, but because it is polling, it feels sluggish and is less efficient than it could be.
This tool uses the Hyprland IPC interface via the [hyprland crate] to query and display the workspace list, and then listen for changes whenever they happen. It does so in a way that is compatible with the Yambar script module so that a Yambar configuration can visualize an always-up-to-date Hyprland workspace list.
The script, when run, outputs the following (using Yambar's script module output format):
workspace_N|string|The Hyprland name of the workspace
workspace_N_windows|int|The number of windows on the workspace
workspace_N_index_on_monitor|int|The index of the workspace on its monitor
workspace_N_monitor|string|The name of the monitor the workspace is on
workspace_N_active|bool|Whether the workspace is active on _a_ monitor
workspace_N_focused|bool|Whether the workspace is active _and_ its monitor has focus
workspace_count|int|The total number of workspaces
In Hyprland, empty workspaces don't exist, and so you'll only see workspaces that have anything on them appear in your bar. To make this a little less jarring, this tool will also fill in empty workspaces up to the the last populated workspace. If you want all the workspaces to always be listed, you'll want to tweak the suggested Yambar config slightly (see comments inline below).
Because Yambar's support for plugins is very simple, and its "particles" are fairly limited, the Yambar configuration is quite verbose and repetitive (see below). For some reason it also seems to render the particles before the script module has issued its first tags, so you get a bunch of warnings initially upon launching yambar that then go away.
I don't currently have a multi-monitor setup, so I haven't tested how well this works there. It's probably broken. The tool tries to list out workspaces from left to right based on what monitor they're on, and it tries to highlight workspaces that are active on non-focused monitors, but I don't know if any of those bits currently work. Please let me know!
I haven't set up on-click
handlers for the configuration
below. Feel free to do so. You'll probably want to invoke
hyprctl dispatch workspace N
with maybe some special handling on multi-monitor setups? If you make something good, please do report back!
You must change the path of the script depending on your installation method. See installation notes above for more information.
- script:
path: ~/.cargo/bin/yambar-hyprland-wses
anchors:
ws_focused: &ws_focused fba922ff
ws_active: &ws_active ffaa00ff
ws_empty: &ws_empty 555555ff
ws_other: &ws_other bbbbbbff
# you can use `{workspace_N}` here to use the workspace name
# assigned by Hyprland instead of hard-coding one here. That
# name is, as far as I can tell, always just the index of the
# workspace though, so not all that valuable.
ws_1: &ws_1 "I"
ws_2: &ws_2 "II"
ws_3: &ws_3 "III"
ws_4: &ws_4 "IV"
ws_5: &ws_5 "V"
ws_6: &ws_6 "VI"
ws_7: &ws_7 "VII"
ws_8: &ws_8 "VIII"
ws_9: &ws_9 "IX"
content:
list:
spacing: 6
items:
- map:
default:
string: { text: *ws_1, foreground: *ws_other }
conditions:
workspace_count < 2:
# if you replace all of these empty: entries with
#
# string: { text: *ws_N, foreground: *ws_empty }
#
# instead, then you'll always see the full
# workspace list. however, you'll be unable to use
# `{workspace_N}` as the workspace names in the
# anchors list above.
empty: {}
workspace_1_focused:
string: { text: *ws_1, foreground: *ws_focused }
workspace_1_active:
string: { text: *ws_1, foreground: *ws_active }
workspace_1_windows == 0:
string: { text: *ws_1, foreground: *ws_empty }
# All of the maps below are identical to the one above,
# except with N++.
- map:
default:
string: { text: *ws_2, foreground: *ws_other }
conditions:
workspace_count < 3:
empty: {}
workspace_2_focused:
string: { text: *ws_2, foreground: *ws_focused }
workspace_2_active:
string: { text: *ws_2, foreground: *ws_active }
workspace_2_windows == 0:
string: { text: *ws_2, foreground: *ws_empty }
- map:
default:
string: { text: *ws_3, foreground: *ws_other }
conditions:
workspace_count < 4:
empty: {}
workspace_3_focused:
string: { text: *ws_3, foreground: *ws_focused }
workspace_3_active:
string: { text: *ws_3, foreground: *ws_active }
workspace_3_windows == 0:
string: { text: *ws_3, foreground: *ws_empty }
- map:
default:
string: { text: *ws_4, foreground: *ws_other }
conditions:
workspace_count < 5:
empty: {}
workspace_4_focused:
string: { text: *ws_4, foreground: *ws_focused }
workspace_4_active:
string: { text: *ws_4, foreground: *ws_active }
workspace_4_windows == 0:
string: { text: *ws_4, foreground: *ws_empty }
- map:
default:
string: { text: *ws_5, foreground: *ws_other }
conditions:
workspace_count < 6:
empty: {}
workspace_5_focused:
string: { text: *ws_5, foreground: *ws_focused }
workspace_5_active:
string: { text: *ws_5, foreground: *ws_active }
workspace_5_windows == 0:
string: { text: *ws_5, foreground: *ws_empty }
- map:
default:
string: { text: *ws_6, foreground: *ws_other }
conditions:
workspace_count < 7:
empty: {}
workspace_6_focused:
string: { text: *ws_6, foreground: *ws_focused }
workspace_6_active:
string: { text: *ws_6, foreground: *ws_active }
workspace_6_windows == 0:
string: { text: *ws_6, foreground: *ws_empty }
- map:
default:
string: { text: *ws_7, foreground: *ws_other }
conditions:
workspace_count < 8:
empty: {}
workspace_7_focused:
string: { text: *ws_7, foreground: *ws_focused }
workspace_7_active:
string: { text: *ws_7, foreground: *ws_active }
workspace_7_windows == 0:
string: { text: *ws_7, foreground: *ws_empty }
- map:
default:
string: { text: *ws_8, foreground: *ws_other }
conditions:
workspace_count < 9:
empty: {}
workspace_8_focused:
string: { text: *ws_8, foreground: *ws_focused }
workspace_8_active:
string: { text: *ws_8, foreground: *ws_active }
workspace_8_windows == 0:
string: { text: *ws_8, foreground: *ws_empty }
- map:
default:
string: { text: *ws_9, foreground: *ws_other }
conditions:
workspace_count < 10:
empty: {}
workspace_9_focused:
string: { text: *ws_9, foreground: *ws_focused }
workspace_9_active:
string: { text: *ws_9, foreground: *ws_active }
workspace_9_windows == 0:
string: { text: *ws_9, foreground: *ws_empty }
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.