fix(hyprland): order workspaces by id - #3875
Merged
ItsLemmy merged 2 commits intoAug 15, 2026
Merged
Conversation
Named workspaces get negative ids from Hyprland, and the bar's comparator treated a negative id as "named": it pushed those workspaces behind every numbered one and sorted them alphabetically. Hyprland orders workspaces by ascending id, so with `workspace = name:0` / `name:Grave` rules the bar read 8, 0, Grave while `workspace m+1` walked Grave, 0, 8, and `m~1` landed on the last pill in the bar instead of the first. Sort by id and drop the special case. Labels in id mode now fall back to the workspace name instead of its position in the bar, since a named workspace has no numeric id to show; a negative id is an allocation artifact that changes between restarts, so it is not worth rendering.
TheBinaryLoop
force-pushed
the
fix/hyprland-workspace-order
branch
from
August 11, 2026 15:19
cb1ac0c to
c50c18e
Compare
Collaborator
|
THanks |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
HyprlandWorkspaceBackend::workspaceOrderLess()now sorts purely by workspace id. It used to read a negative id as "this workspace is named", push those workspaces behind every numbered one, and sort them alphabetically among themselves. Hyprland orders workspaces by ascending id, negatives included, so the bar disagreed with the compositor about what the next workspace is.The workspaces widget in
label_source = "id"mode also falls back to the workspace name when a workspace has no numeric id, instead of falling through to its position in the bar.Motivation
Reported in #3871: with persistent named workspaces, the bar order does not match the order Hyprland uses for relative dispatches.
With the reporter's rules:
Hyprland assigned
Grave = -1338and0 = -1337. Repeatedly dispatchingworkspace m+1visits Grave, 0, 8, andm~1("first workspace on the monitor") selects Grave. The bar showed 8, 0, Grave, so a next/previous keybind appeared to jump around the bar andm~1highlighted the rightmost pill.The label fallback matters for the same setup:
Graverendered as3in id mode, a number that was neither its id nor its name, and that changed as soon as the ordering changed. Rendering the negative id instead would be worse than useless, since the allocation is not stable across restarts: the same two rules produced -1339/-1338 for the reporter and -1337/-1338 here.The fallback only fires when there is no numeric identity at all, so no workspace that previously showed a number shows something else now. Backends that set
index(niri, kwin, dwl, mango, triad) never reach it. Named sway and ext-workspace workspaces get the same improvement as Hyprland.Type of Change
Related Issue
Closes #3871
Testing
just test debug— 80/80, including the newtests/hyprland_workspace_backend_test.cpp. It drives the backend against a stub hyprctl request socket serving the workspace set above plus a special workspace, and asserts ascending-id order fromall()andforOutput().got: 8(8), 0(-1337), Grave(-1338)and passes with the new one.just format— no changes (clang-format 22.1.8).-warnings-as-errors=*over both modified files — clean.workspace m+1highlights them left to right;m~1selects the leftmost. Labels come out asGrave 0 8in id mode andG 0 8in name mode withmax_label_chars = 1.Manual Coverage
Hyprland coverage was a nested instance with a single output, not a full session. The unchecked boxes are untested: no layout, geometry, or scaling code is touched, so pill order and label text should be independent of bar position, density, and scale. Multi-monitor is worth a look from someone with the hardware, since
forOutput()is one of the two call sites that changed.Screenshots / Videos
Bar contents in the nested instance, active workspace in brackets:
I have PNGs of all three and can attach them on request.
Checklist
CONTRIBUTING.md.just formatwith clang-format v22+ installed, or this PR has no code changes.assets/translations/en.json, or this PR adds no new user-facing strings.Additional Notes
I left the documentation box unchecked deliberately. No config key, IPC name, or identifier changes, but observable behavior does change for anyone running named workspaces, and I do not know whether the docs describe workspace ordering or what id mode shows for a named workspace. Point me at the right page and I will send a note.
Two limitations worth knowing:
Order among named workspaces follows Hyprland's id allocation, not the order the rules are declared in. Above,
name:0is declared first butGravesorts first. That is inherent in matching the compositor's own traversal.max_label_charsis only exposed forlabel_source = "name", so a long workspace name is not truncated in id mode. Widening that setting's visibility to both modes is a settings-schema change I kept out of this PR. Happy to add it if you want it.