wlr/workspace: port to ext-workspace-v1 for labwc support
This PR allows to use wlr/workspaces with labwc >= 0.8.3. This is more or less a follow up to https://github.com/Alexays/Waybar/pull/3481 and based on https://github.com/labwc/labwc/pull/2365
Additional to labwc, this PR also enables workspaces for niri with https://github.com/YaLTeR/niri/pull/1800
~The heavy lifting is done in this PR, it works with labwc, but it doesn't take protocol differences between the two version into account. The last commit is a hack because workspace creation is too late and doesn't get the initial state (same reason why not the name, but the workspace id appears).~ This is now a complete reimplementation and has seen testing from multiple configurations and compositors, see discussions below.
wayland-protocols dependency needs to be >=1.39 for this module to be built.
The big outstanding question is the module name and location. The new upstream workspaces protocol is no longer Wlroots specific, so wlr/workspaces is probably not the best choice.
Obligatory screenshot:
Closes https://github.com/Alexays/Waybar/issues/3967
Note that for CI to fully succeed, https://github.com/Alexays/Waybar/pull/4094 has to land first.
I reworked the code to move the workspace creation to the manager to be in line with the protocol. As a result the initial state hack is gone and state/name are properly picked up from labwc. I haven't tested with a multi monitor setup, but the current version works nicely for me i.c.w. labwc. That said, I have a hard time figuring out how features like persistent-workspaces or all-ouputs are supposed to work (both functionality and code-wise). Both are very likely broken with this PR. I'm also not sure if those features still makes sense with the protocol update. May be those features should be dropped? Or may be it makes more sense to start fresh, eventually as a new module? ~Leaving this for now for some feedback about the general direction.~
May be those features should be dropped? Or may be it makes more sense to start fresh, eventually as a new module?
The last commit re-implements the module from scratch. I'm quite happy with the result. All config options should still work with the exception of "persistent-workspaces". I did not took this over because of above mentioned reasons.
From my perspective this is ready for testing and of course still ready for general feedback on the direction and how this should fit in.
TODO:
- [x] Do not bump the required wayland-protocol version, but build the workspaces module conditionally based on the detected version
- [x] Tweak documentation
- [x] Squash commits
- [x] Testing (limited, from developers perspective)
I'm happy with how this PR turned out and all things that needs to be done in my opinion are done. Ready for review!
The main question still remains though: should this be a new module (since the protocol is no longer wlr specific) or, what this PR is, an in-place port.
Any info on whether this will be merged?
I compiled waybar with the workspace patch and it works great with labwc, at least for my simple usecase of a desktop with a single monitor and a laptop, both with virtual desktops.
Thanks for firing up CI. The meson magic should be good now, also linting for the files this PR touches. Let's if CI agrees ;)
If you want, I can also add a few separate commits for fixing the formatting in other modules so that CI will become completely green.
Edit: Missed a few & and * aligns, hopefully now good.
very nice!! its builds on gentoo against 0.12.0 but one tiny issue and its to do with the unicode symbols for workspaces
entry in the config:
running wayland:
it using the "default" icon throughout
very nice!! its builds on gentoo against 0.12.0 but one tiny issue and its to do with the unicode symbols for workspaces
You need to use the names of the workspaces in the configuration section, not the id. With a default labwc setup this looks like this:
"format-icons": {
"Workspace 1": "",
"Workspace 2": "",
"Workspace 3": "",
"Workspace 4": "",
"Workspace 5": "",
"active": "",
"default": ""
},
I've changed the documentation section in this PR accordingly, so thanks for pointing this out.
that works! thankyou!!
First - thx for this @jp7677! - tested out this patch set today and see 2 noticeable issues atm
- When using multiple outputs/monitors (extend, not clone), no matter if
sort-by-idis set (with all other sort options = false) andall-outputs = true, thesort-by-idappears to only take effect on a single output while the other(s) retainsort-by-name - When changing output configurations (e.g. kanshi, wlr-randr) and what appeared to be resume from swayidle while waybar is using
wlr/workspaces, waybar will segfault (few backtraces below)
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x000000000055c1da in sigc::internal::signal_emit0<void, sigc::nil>::emit (impl=0x3100000000) at /usr/include/sigc++-2.0/sigc++/signal.h:786
786 if (!impl || impl->slots_.empty()) return;
[Current thread is 1 (Thread 0x7fd2a957f980 (LWP 19200))]
(gdb) bt
#0 0x000000000055c1da in sigc::internal::signal_emit0<void, sigc::nil>::emit (impl=0x3100000000) at /usr/include/sigc++-2.0/sigc++/signal.h:786
#1 0x00007fd2ab7d1bd9 in Glib::DispatchNotifier::pipe_io_handler(Glib::IOCondition) () at /usr/lib64/libglibmm-2.4.so.1
#2 0x00007fd2ab7d3fec in Glib::IOSource::dispatch(sigc::slot_base*) () at /usr/lib64/libglibmm-2.4.so.1
#3 0x00007fd2ab7d3ba7 in Glib::Source::dispatch_vfunc(_GSource*, int (*)(void*), void*) () at /usr/lib64/libglibmm-2.4.so.1
#4 0x00007fd2ab60e7c5 in ??? () at /usr/lib64/libglib-2.0.so.0
#5 0x00007fd2ab6107b7 in ??? () at /usr/lib64/libglib-2.0.so.0
#6 0x00007fd2ab610ebc in g_main_context_iteration () at /usr/lib64/libglib-2.0.so.0
#7 0x00007fd2ab8ed78d in g_application_run () at /usr/lib64/libgio-2.0.so.0
#8 0x000000000047eeb2 in waybar::Client::main (this=this@entry=0x15b52a10, argc=<optimized out>, argc@entry=1, argv=<optimized out>, argv@entry=0x7ffdbc85eb38) at /usr/include/glibmm-2.4/glibmm/refptr.h:259
#9 0x0000000000472464 in main (argc=1, argv=0x7ffdbc85eb38) at ../src/main.cpp:107
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007fb04fa8ea05 in Glib::DispatchNotifier::send_notification(Glib::Dispatcher*) () from /usr/lib64/libglibmm-2.4.so.1
[Current thread is 1 (Thread 0x7fb04c56e980 (LWP 19959))]
(gdb) bt
#0 0x00007fb04fa8ea05 in Glib::DispatchNotifier::send_notification(Glib::Dispatcher*) () at /usr/lib64/libglibmm-2.4.so.1
#1 0x00000000004ff689 in waybar::modules::wlr::WorkspaceManager::handle_done (this=<optimized out>) at ../src/modules/wlr/workspace_manager.cpp:120
#2 0x0000000000505bc2 in waybar::modules::wlr::workspace_manager_handle_done (data=<optimized out>, _=<optimized out>) at ../src/modules/wlr/workspace_manager_binding.cpp:45
#3 0x00007fb04e1260ca in ??? () at /usr/lib64/libffi.so.8
#4 0x00007fb04e125600 in ??? () at /usr/lib64/libffi.so.8
#5 0x00007fb04e125cbd in ffi_call () at /usr/lib64/libffi.so.8
#6 0x00007fb04fc61851 in ??? () at /usr/lib64/libwayland-client.so.0
#7 0x00007fb04fc5dbbf in ??? () at /usr/lib64/libwayland-client.so.0
#8 0x00007fb04fc5eddb in wl_display_dispatch_queue_pending () at /usr/lib64/libwayland-client.so.0
#9 0x00007fb04e9676c4 in ??? () at /usr/lib64/libgdk-3.so.0
#10 0x00007fb04e92f050 in gdk_display_get_event () at /usr/lib64/libgdk-3.so.0
#11 0x00007fb04e9673e2 in ??? () at /usr/lib64/libgdk-3.so.0
#12 0x00007fb04e5917c5 in ??? () at /usr/lib64/libglib-2.0.so.0
#13 0x00007fb04e5937b7 in ??? () at /usr/lib64/libglib-2.0.so.0
#14 0x00007fb04e593ebc in g_main_context_iteration () at /usr/lib64/libglib-2.0.so.0
#15 0x00007fb04e7df78d in g_application_run () at /usr/lib64/libgio-2.0.so.0
#16 0x000000000047eeb2 in waybar::Client::main (this=this@entry=0x105bda10, argc=<optimized out>, argc@entry=1, argv=<optimized out>, argv@entry=0x7ffdc9b0f8c8) at /usr/include/glibmm-2.4/glibmm/refptr.h:259
#17 0x0000000000472464 in main (argc=1, argv=0x7ffdc9b0f8c8) at ../src/main.cpp:107
When changing output configurations (e.g. kanshi, wlr-randr) and what appeared to be resume from swayidle while waybar is using
wlr/workspaces, waybar will segfault (few backtraces below)
Thanks a lot for raising this. Seems that I had a small misunderstanding how the Waybar WorkspaceManager is supposed to work. I could reproduce this with unplugging/plugging a second monitor. I've reworked deconstruction and it should be good now. Could you please retest and report back?
When using multiple outputs/monitors (extend, not clone), no matter if
sort-by-idis set (with all other sort options = false) andall-outputs = true, thesort-by-idappears to only take effect on a single output while the other(s) retainsort-by-name
Am I assuming correctly that you are using labwc? Could you please share the desktop part of your labwc desktop configuration and the wlr/workspaces part of your waybar config? The sorting works fine here, lets see if I can reproduce with your configuration.
Note though that all-outputs doesn't matter for labwc since workspaces in labwc are global and not per output, so each output already gets all workspace assigned to. Also note that labwc doesn't send IDs for workspaces, only names, as a fallback an internal Waybar counter is used. So setting workspace names in the labwc configuration and using sort-by-name is the clearest approach. That said, I've also reworked the ID/name fallback in Waybar, those should be identical now for each output (since the counter is no longer global but per WorkspaceManager). Please let me know if that improves what you are seeing.
PS: You can show both name and ID with e.g. "format": "{name} ({id})", may be that helps to identify whats going on.
I've reworked deconstruction and it should be good now. Could you please retest and report back?
Much better now - so far so good testing a few hotplug situations w/ multiple monitors
Am I assuming correctly that you are using labwc?
Yes, sorry - testing performed against commit https://github.com/labwc/labwc/commit/cb58156904ec3e3401c8600b784485c36b978716
Could you please share the desktop part of your labwc desktop configuration
<desktops>
<popupTime>300</popupTime>
<number>12</number>
<names>
<name>1</name>
<name>2</name>
<name>3</name>
<name>4</name>
<name>5</name>
<name>6</name>
<name>7</name>
<name>8</name>
<name>9</name>
<name>10</name>
<name>11</name>
<name>12</name>
</names>
</desktops>
As you can see above, the workspace "names" are integers but the prior ordering issue I was encountering was string sorting on one output (e.g. 1, 10, 11, 12, 2, 3, 4, ....)
Now, I observe both outputs with the same ordering. Commenting out all "sort" options gives the desired behavior but flipping any of below to true will result in the described above behavior
"wlr/workspaces": {
"format": " {name} ",
"on-click": "activate",
"format-icons": {
"active": "🔳",
"default": "⬜",
"urgent": "🟥"
}
//"all-outputs": true,
//"sort-by-coordinates": false,
//"sort-by-name": false,
//"sort-by-id": true
},
Much better now - so far so good testing a few hotplug situations w/ multiple monitors
Nice!
Now, I observe both outputs with the same ordering. Commenting out all "sort" options gives the desired behavior but flipping any of below to
truewill result in the described above behavior
Ah right, the workspace ID and name are both strings, thus string sorting and not number sorting is applied. Only when no sorting is set, it falls back to sort by an internal ID which is an integer (https://github.com/jp7677/Waybar/blob/ext-workspaces/src/modules/wlr/workspace_manager.cpp#L158 ).
What is wise? I can stick to the old implementation and change sort-by-id to actually do sort-by-name-numerically which would work nicely since labwc doesn't send ID's. That said, since the protocol defines ID and name, having sort-by-id to not do sort by ID can also be confusing.
PS: I guess this works for you?
Patch
diff --git a/src/modules/wlr/workspace_manager.cpp b/src/modules/wlr/workspace_manager.cpp
index 9c88f210..b339f7e6 100644
--- a/src/modules/wlr/workspace_manager.cpp
+++ b/src/modules/wlr/workspace_manager.cpp
@@ -158,7 +158,10 @@ void WorkspaceManager::update() {
if (sort_by_id_ || sort_by_name_ || sort_by_coordinates_) {
std::sort(workspaces_.begin(), workspaces_.end(), [&](const auto &w1, const auto &w2) {
if (sort_by_id_) {
- return w1->workspace_id() < w2->workspace_id();
+ // the idea is that phonetic compare can be applied
+ // just to numbers with same number of digits
+ return w1->name().size() < w2->name().size() ||
+ (w1->name().size() == w2->name().size() && w1->name() < w2->name());
}
if (sort_by_name_) {
return w1->name() < w2->name();
PPS: I've pushed a commit (now squashed) that detects if numeric sorting should be applied for both name and workspace ID. In your case all sort settings except coordinates should yield numeric sorting.
PPS: I've pushed a commit (can be squashed later) that detects if numeric sorting should be applied for both name and workspace ID. In your case all sort settings except coordinates should yield numeric sorting.
Thx - latest commits LGTM (note: "sort-by-coordinates": true w/ all others set to false still appears to preserve numeric sorting of workspace names)
PPS: I've pushed a commit (can be squashed later) that detects if numeric sorting should be applied for both name and workspace ID. In your case all sort settings except coordinates should yield numeric sorting.
Thx - latest commits LGTM (note:
"sort-by-coordinates": truew/ all others set to false still appears to preserve numeric sorting of workspace names)
Nice. I did a last optimization, sort only when needed, but this shouldn't change anything. W.r.t. coordinates, labwc doesn't send coordinates, so in that case ordering falls back again to internal ID, which is order by creation which matches numeric sorting in your case.
@Alexays Any chance that you could fire up CI again? Thanks!
@Alexays Gentle ping.
Hi, I'm implementing ext-workspace in niri: https://github.com/YaLTeR/niri/pull/1800
I tested this PR, seems to work well, except for one problem: the bar only shows workspaces for one of the outputs (either my first or my second output), even with "all-outputs": true. It behaves as if it's not aware of workspaces on other outputs.
Suggested config:
"wlr/workspaces": {
"sort-by-name": false,
"sort-by-coordinates": true,
"on-click": "activate"
},
Wayland debug log with two outputs:
└─ WAYLAND_DEBUG=1 ~/source/cpp/Waybar/build/waybar 2>| grep -E '(workspace|wl_output)'
[3780157.365] {Default Queue} wl_registry#2.global(29, "ext_workspace_manager_v1", 1)
[3780157.403] {Default Queue} wl_registry#2.global(43, "wl_output", 4)
[3780157.405] {Default Queue} -> wl_registry#2.bind(43, "wl_output", 2, new id [unknown]#19)
[3780157.437] {Default Queue} -> zxdg_output_manager_v1#8.get_xdg_output(new id zxdg_output_v1#20, wl_output#19)
[3780157.443] {Default Queue} wl_registry#2.global(44, "wl_output", 4)
[3780157.445] {Default Queue} -> wl_registry#2.bind(44, "wl_output", 2, new id [unknown]#22)
[3780157.452] {Default Queue} -> zxdg_output_manager_v1#8.get_xdg_output(new id zxdg_output_v1#23, wl_output#22)
[3780165.700] {Default Queue} wl_output#19.geometry(0, 0, 700, 390, 0, "Acer Technologies", "XV320QU LV", 0)
[3780165.706] {Default Queue} wl_output#19.mode(3, 2560, 1440, 170071)
[3780165.709] {Default Queue} wl_output#19.scale(1)
[3780165.711] {Default Queue} wl_output#19.done()
[3780165.726] {Default Queue} wl_output#19.done()
[3780165.731] {Default Queue} wl_output#22.geometry(2560, 0, 600, 340, 0, "Dell Inc.", "Dell S2716DG", 0)
[3780165.735] {Default Queue} wl_output#22.mode(3, 2560, 1440, 143998)
[3780165.738] {Default Queue} wl_output#22.scale(1)
[3780165.739] {Default Queue} wl_output#22.done()
[3780165.749] {Default Queue} wl_output#22.done()
[2025-06-14 17:21:35.524] [info] Using configuration file /var/home/yalter/.config/waybar/config.jsonc
[2025-06-14 17:21:35.526] [info] Using CSS file /var/home/yalter/.config/waybar/style.css
[3780184.732] {Default Queue} wl_registry#34.global(29, "ext_workspace_manager_v1", 1)
[3780184.755] {Default Queue} wl_registry#34.global(43, "wl_output", 4)
[3780184.756] {Default Queue} wl_registry#34.global(44, "wl_output", 4)
[3780185.066] {Default Queue} wl_registry#35.global(29, "ext_workspace_manager_v1", 1)
[3780185.093] {Default Queue} wl_registry#35.global(43, "wl_output", 4)
[3780185.096] {Default Queue} wl_registry#35.global(44, "wl_output", 4)
[3780185.108] {Default Queue} -> zxdg_output_manager_v1#36.get_xdg_output(new id zxdg_output_v1#38, wl_output#19)
[3780185.114] {Default Queue} -> zxdg_output_manager_v1#36.get_xdg_output(new id zxdg_output_v1#41, wl_output#22)
[2025-06-14 17:21:35.530] [info] Niri IPC starting
[3780187.176] {Default Queue} wl_output#19.done()
[3780187.467] {Default Queue} wl_output#22.done()
[3780188.830] {Default Queue} wl_registry#42.global(29, "ext_workspace_manager_v1", 1)
[3780188.832] {Default Queue} -> wl_registry#42.bind(29, "ext_workspace_manager_v1", 1, new id [unknown]#41)
[3780188.856] {Default Queue} wl_registry#42.global(43, "wl_output", 4)
[3780188.858] {Default Queue} wl_registry#42.global(44, "wl_output", 4)
[3780188.916] {Default Queue} wl_registry#44.global(29, "ext_workspace_manager_v1", 1)
[3780188.918] {Default Queue} -> wl_registry#44.bind(29, "ext_workspace_manager_v1", 1, new id [unknown]#43)
[3780188.942] {Default Queue} wl_registry#44.global(43, "wl_output", 4)
[3780188.943] {Default Queue} wl_registry#44.global(44, "wl_output", 4)
[2025-06-14 17:21:35.534] [warning] No batteries.
[3780204.622] {Default Queue} -> zwlr_layer_shell_v1#40.get_layer_surface(new id zwlr_layer_surface_v1#38, wl_surface#45, wl_output#22, 2, "waybar")
[3780206.412] {Default Queue} ext_workspace_manager_v1#41.workspace(new id ext_workspace_handle_v1#4278190080)
[3780206.561] {Default Queue} ext_workspace_handle_v1#4278190080.name("2")
[3780206.566] {Default Queue} ext_workspace_handle_v1#4278190080.coordinates(array[8])
[3780206.569] {Default Queue} ext_workspace_handle_v1#4278190080.state(0)
[3780206.571] {Default Queue} ext_workspace_handle_v1#4278190080.capabilities(9)
[3780206.573] {Default Queue} ext_workspace_manager_v1#41.workspace(new id ext_workspace_handle_v1#4278190081)
[3780206.600] {Default Queue} ext_workspace_handle_v1#4278190081.name("1")
[3780206.604] {Default Queue} ext_workspace_handle_v1#4278190081.coordinates(array[8])
[3780206.605] {Default Queue} ext_workspace_handle_v1#4278190081.state(0)
[3780206.607] {Default Queue} ext_workspace_handle_v1#4278190081.capabilities(9)
[3780206.609] {Default Queue} ext_workspace_manager_v1#41.workspace(new id ext_workspace_handle_v1#4278190082)
[3780206.632] {Default Queue} ext_workspace_handle_v1#4278190082.id("browser")
[3780206.635] {Default Queue} ext_workspace_handle_v1#4278190082.name("browser")
[3780206.637] {Default Queue} ext_workspace_handle_v1#4278190082.coordinates(array[8])
[3780206.638] {Default Queue} ext_workspace_handle_v1#4278190082.state(1)
[3780206.640] {Default Queue} ext_workspace_handle_v1#4278190082.capabilities(9)
[3780206.642] {Default Queue} ext_workspace_manager_v1#41.workspace(new id ext_workspace_handle_v1#4278190083)
[3780206.663] {Default Queue} ext_workspace_handle_v1#4278190083.id("discord")
[3780206.666] {Default Queue} ext_workspace_handle_v1#4278190083.name("discord")
[3780206.668] {Default Queue} ext_workspace_handle_v1#4278190083.coordinates(array[8])
[3780206.670] {Default Queue} ext_workspace_handle_v1#4278190083.state(1)
[3780206.672] {Default Queue} ext_workspace_handle_v1#4278190083.capabilities(9)
[3780206.673] {Default Queue} ext_workspace_manager_v1#41.workspace(new id ext_workspace_handle_v1#4278190084)
[3780206.704] {Default Queue} ext_workspace_handle_v1#4278190084.id("chat")
[3780206.707] {Default Queue} ext_workspace_handle_v1#4278190084.name("chat")
[3780206.709] {Default Queue} ext_workspace_handle_v1#4278190084.coordinates(array[8])
[3780206.710] {Default Queue} ext_workspace_handle_v1#4278190084.state(0)
[3780206.712] {Default Queue} ext_workspace_handle_v1#4278190084.capabilities(9)
[3780206.714] {Default Queue} ext_workspace_manager_v1#41.workspace_group(new id ext_workspace_group_handle_v1#4278190085)
[3780206.716] {Default Queue} ext_workspace_group_handle_v1#4278190085.capabilities(0)
[3780206.718] {Default Queue} ext_workspace_group_handle_v1#4278190085.output_enter(wl_output#19)
[3780206.720] {Default Queue} ext_workspace_group_handle_v1#4278190085.workspace_enter(ext_workspace_handle_v1#4278190081)
[3780206.721] {Default Queue} ext_workspace_group_handle_v1#4278190085.workspace_enter(ext_workspace_handle_v1#4278190082)
[3780206.723] {Default Queue} ext_workspace_manager_v1#41.workspace_group(new id ext_workspace_group_handle_v1#4278190086)
[3780206.725] {Default Queue} ext_workspace_group_handle_v1#4278190086.capabilities(0)
[3780206.727] {Default Queue} ext_workspace_group_handle_v1#4278190086.output_enter(wl_output#22)
[3780206.729] {Default Queue} ext_workspace_group_handle_v1#4278190086.workspace_enter(ext_workspace_handle_v1#4278190080)
[3780206.730] {Default Queue} ext_workspace_group_handle_v1#4278190086.workspace_enter(ext_workspace_handle_v1#4278190083)
[3780206.732] {Default Queue} ext_workspace_group_handle_v1#4278190086.workspace_enter(ext_workspace_handle_v1#4278190084)
[3780206.734] {Default Queue} ext_workspace_manager_v1#41.done()
[3780206.737] {Default Queue} ext_workspace_manager_v1#43.workspace(new id ext_workspace_handle_v1#4278190087)
[3780206.760] {Default Queue} ext_workspace_handle_v1#4278190087.name("2")
[3780206.762] {Default Queue} ext_workspace_handle_v1#4278190087.coordinates(array[8])
[3780206.764] {Default Queue} ext_workspace_handle_v1#4278190087.state(0)
[3780206.766] {Default Queue} ext_workspace_handle_v1#4278190087.capabilities(9)
[3780206.768] {Default Queue} ext_workspace_manager_v1#43.workspace(new id ext_workspace_handle_v1#4278190088)
[3780206.788] {Default Queue} ext_workspace_handle_v1#4278190088.name("1")
[3780206.792] {Default Queue} ext_workspace_handle_v1#4278190088.coordinates(array[8])
[3780206.794] {Default Queue} ext_workspace_handle_v1#4278190088.state(0)
[3780206.796] {Default Queue} ext_workspace_handle_v1#4278190088.capabilities(9)
[3780206.798] {Default Queue} ext_workspace_manager_v1#43.workspace(new id ext_workspace_handle_v1#4278190089)
[3780206.818] {Default Queue} ext_workspace_handle_v1#4278190089.id("browser")
[3780206.820] {Default Queue} ext_workspace_handle_v1#4278190089.name("browser")
[3780206.822] {Default Queue} ext_workspace_handle_v1#4278190089.coordinates(array[8])
[3780206.824] {Default Queue} ext_workspace_handle_v1#4278190089.state(1)
[3780206.825] {Default Queue} ext_workspace_handle_v1#4278190089.capabilities(9)
[3780206.827] {Default Queue} ext_workspace_manager_v1#43.workspace(new id ext_workspace_handle_v1#4278190090)
[3780206.855] {Default Queue} ext_workspace_handle_v1#4278190090.id("discord")
[3780206.857] {Default Queue} ext_workspace_handle_v1#4278190090.name("discord")
[3780206.859] {Default Queue} ext_workspace_handle_v1#4278190090.coordinates(array[8])
[3780206.861] {Default Queue} ext_workspace_handle_v1#4278190090.state(1)
[3780206.862] {Default Queue} ext_workspace_handle_v1#4278190090.capabilities(9)
[3780206.864] {Default Queue} ext_workspace_manager_v1#43.workspace(new id ext_workspace_handle_v1#4278190091)
[3780206.883] {Default Queue} ext_workspace_handle_v1#4278190091.id("chat")
[3780206.886] {Default Queue} ext_workspace_handle_v1#4278190091.name("chat")
[3780206.888] {Default Queue} ext_workspace_handle_v1#4278190091.coordinates(array[8])
[3780206.890] {Default Queue} ext_workspace_handle_v1#4278190091.state(0)
[3780206.892] {Default Queue} ext_workspace_handle_v1#4278190091.capabilities(9)
[3780206.893] {Default Queue} ext_workspace_manager_v1#43.workspace_group(new id ext_workspace_group_handle_v1#4278190092)
[3780206.895] {Default Queue} ext_workspace_group_handle_v1#4278190092.capabilities(0)
[3780206.897] {Default Queue} ext_workspace_group_handle_v1#4278190092.output_enter(wl_output#19)
[3780206.899] {Default Queue} ext_workspace_group_handle_v1#4278190092.workspace_enter(ext_workspace_handle_v1#4278190088)
[3780206.900] {Default Queue} ext_workspace_group_handle_v1#4278190092.workspace_enter(ext_workspace_handle_v1#4278190089)
[3780206.902] {Default Queue} ext_workspace_manager_v1#43.workspace_group(new id ext_workspace_group_handle_v1#4278190093)
[3780206.904] {Default Queue} ext_workspace_group_handle_v1#4278190093.capabilities(0)
[3780206.906] {Default Queue} ext_workspace_group_handle_v1#4278190093.output_enter(wl_output#22)
[3780206.908] {Default Queue} ext_workspace_group_handle_v1#4278190093.workspace_enter(ext_workspace_handle_v1#4278190087)
[3780206.909] {Default Queue} ext_workspace_group_handle_v1#4278190093.workspace_enter(ext_workspace_handle_v1#4278190090)
[3780206.911] {Default Queue} ext_workspace_group_handle_v1#4278190093.workspace_enter(ext_workspace_handle_v1#4278190091)
[3780206.913] {Default Queue} ext_workspace_manager_v1#43.done()
[3780206.915] {Default Queue} wl_surface#45.enter(wl_output#22)
[2025-06-14 17:21:35.552] [warning] No batteries.
[3780209.391] {Default Queue} -> zwlr_layer_shell_v1#40.get_layer_surface(new id zwlr_layer_surface_v1#47, wl_surface#46, wl_output#19, 2, "waybar")
[3780210.152] {Default Queue} wl_surface#46.enter(wl_output#19)
[2025-06-14 17:21:35.774] [info] Bar configured (width: 50, height: 1440) for output: DP-2
[2025-06-14 17:21:35.774] [error] Item '': No icon name or pixmap given.
[2025-06-14 17:21:35.786] [error] Item '': No icon name or pixmap given.
[2025-06-14 17:21:35.788] [info] Bar configured (width: 35, height: 1440) for output: DP-1
Just a small nitpick: using wlr/workspaces feels wrong, its the official wayland protocol for workspaces rather than a wlroots one.
Just a small nitpick: using
wlr/workspacesfeels wrong, its the official wayland protocol for workspaces rather than a wlroots one.
Yes, I agree on that. I had hoped to get a hint from the maintainers here for a better location/name, but so far no feedback :( I'm hesitant to decide for myself how this PR fits best into this project.
Hi, I'm implementing ext-workspace in niri: YaLTeR/niri#1800
I tested this PR, seems to work well, except for one problem: the bar only shows workspaces for one of the outputs (either my first or my second output), even with
"all-outputs": true. It behaves as if it's not aware of workspaces on other outputs.
Thanks for the report. Could you describe more detailed how your setup looks like and what you are seeing? From the logs I'm seeing the following (may be with DP-1/2 reversed):
Output DP-2
- Workspace group
- Workspace "1"
- Workspace "browser"
Output DP-1
- Workspace group
- Workspace "2
- Workspace "discord"
- Workspace "chat"
Waybar is configured for both outputs (so internally two waybar workspace manager are created and both should know the full topology, whereas each waybar workspace manager is bound to exactly one output).
With "all-outputs" set to "false" (which is the default), do you see the correct workspaces on each output? With "all-outputs" set to "true", does anything changes or is the result on both outputs exactly the same?
With all-outputs false, I see workspaces only on one of the bars (for that output). Across compositor restarts I've seen it use either.
With all-outputs true, I see the same set of workspaces (for that one output) on both.
~Could you please post the waybar logs prefixed with [wlr/workspaces] when running waybar with debug logging (waybar -l debug)?~
I think I see what's going on, clearly my fault ;) Will get to work...
@YaLTeR Could you please try again with the last (forced) pushed commit?
Seems to work well!
@jp7677
When marking the workspace as hidden, is it allowed to completely hide the workspace button on waybar?
like this:
button.set_visible(false);
Currently, only a hidden attribute has been added to it.This doesn't make him hide completely.
Perhaps an option could be added to support hiding, which is very friendly for compositor like river and dwl that are based on fixed tag lengths. You can also see that waybar has relevant pr requests to achieve the hiding of some buttons about these compositor.
@DreamMaoMao thanks for the suggestion. This is probably easy to achieve but I would prefer to do this after this PR has landed, or at least when there is a path forward for getting this merged.
Btw I also think that renaming the module to ext/workspace would make sense. Especially since wlr/workspace hasn't been enabled by default yet I think?
Btw I also think that renaming the module to
ext/workspacewould make sense. Especially sincewlr/workspacehasn't been enabled by default yet I think?
Yes I agree. As stated above, I’m looking for a hint from the maintainers here how to handle this (naming, file locations, etc) in the best interest of the project.
I'd just s/wlr/ext/g and call it a day.