fix(hyprland): detect dispatch protocol via configProvider - #5231
fix(hyprland): detect dispatch protocol via configProvider#5231CristianMz21 wants to merge 3 commits into
Conversation
94fbe40 to
f3fc651
Compare
|
Now running in production on a real machine, not just in tests. Backported onto the 0.14.0 packaging and installed system-wide (Fedora 43, Hyprland 0.56.1, Lua config). Clicking a workspace button switches, and the detection resolves through the new path on the first dispatch: No Still the same caveat as above: the legacy branch is covered by the unit tests but I have no pre-0.54 instance to confirm it against. |
Waybar decided between the legacy and the Lua dispatch protocol from the
Hyprland version alone, assuming >= 0.54 always means Lua. Hyprland does
not work that way: it only loads the Lua config manager when the config
file name ends in ".lua", so an instance running a traditional
hyprland.conf still speaks the legacy protocol no matter its version.
Those users got Lua-formatted dispatches, Hyprland answered "Invalid
dispatcher", and clicking a workspace button did nothing.
Hyprland already reports which manager it loaded, in the "systeminfo"
reply:
configProvider: lua
Read that instead. The field landed together with the Lua config manager
in 0.55, so its absence means the instance predates Lua support entirely
and necessarily speaks the legacy protocol, which makes the field
sufficient on its own and lets the version heuristic go away.
Dropping that heuristic also fixes 0.54, which it misread: Lua config
support only arrived in 0.55, so ">= 0.54" claimed Lua on a release that
has no Lua config manager at all.
The query is read-only, so detection keeps none of the side effects that
motivated replacing the earlier dispatch-based probe.
The parsing lives in a pure parseConfigProvider() helper so it can be
covered without a live compositor. Tests exercise both managers, a
realistic full systeminfo reply, the absent field, formatting variations
(tab and multi-space separators, CRLF, no trailing newline, empty value),
and the socket failure path.
Fixes Alexays#5198
f3fc651 to
bfd0cfe
Compare
|
One more data point, since #5198 raised the question of what happens when Hyprland drops legacy config support (hyprwm/Hyprland#15539, merged 2026-07-22): the field this PR relies on survives that removal. On Hyprland // src/helpers/SystemInfo.cpp
configProvider: {}
// ...
Config::typeToString(Config::mgr()->type())// src/config/ConfigManager.cpp
const char* Config::typeToString(eConfigManagerType t) {
switch (t) {
case CONFIG_LUA: return "lua";
default: return "error";
}
}So the three cases this PR handles stay correct across that transition:
Worth contrasting with the version heuristic this replaces: it would have kept drifting, since "new enough" stops implying anything about the parser once the config file name is no longer the deciding factor. Also note |
Address review feedback from Bart97: - Collapse parseConfigProvider + luaProtocolFromSystemInfo into a single isLuaConfigProvider, whose name states the boolean it answers. Two functions instead of three; the pure helper stays separate from the socket call only because CI has no compositor, so the parsing paths (absent field, legacy value, formatting) are only coverable through it. - Drop the optional<bool>: since the version fallback was removed, an absent field and a non-lua value both mean legacy, so the tri-state answered nothing the caller could act on. - Handle the end-of-reply case with an explicit npos branch instead of relying on substr clamping. - Reuse trim() from util/string.hpp instead of a hand-rolled rtrim loop; it also covers the leading separator whitespace and trailing CR.
4a97df6 to
92742e4
Compare
|
Changes look fine to me now, for some reason github doesn't let me mark my comments as resolved. |
The fixtures used "configProvider: legacy", a value Hyprland never emits.
Config::typeToString returns "hyprlang" for the legacy manager:
case CONFIG_LUA: return "lua";
case CONFIG_LEGACY: return "hyprlang";
Runtime behaviour was unaffected, since the check is trim(value) == "lua"
and every other value already falls through to legacy. But the test that
covers the case this PR exists to fix - a >= 0.55 instance started with a
traditional hyprland.conf - asserted on a string that cannot occur, so
nothing exercised the real legacy reply.
Verified against ConfigManager.cpp at v0.55.0, v0.56.0 and v0.56.1.
|
Thanks @Bart97 — resolved all six threads. You could not do it yourself because resolving requires either write access or PR authorship, and you have neither here; as the author I can, so that is on me rather than a GitHub glitch. One correction went in on top, found while re-verifying the branch rather than reported by anyone: the fixtures asserted on case CONFIG_LUA: return "lua";
case CONFIG_LEGACY: return "hyprlang";Runtime behaviour was unaffected — the check is Two things that need someone with write access:
No further pushes planned from my side, so the next approval should be the last one needed. |
Fixes #5198.
Problem
IPC::isLuaProtocol()decides between the legacy and the Lua dispatch protocol from the Hyprland version alone:That is not the rule Hyprland uses. It only loads the Lua config manager when the config file name ends in
.lua; an instance started with a traditionalhyprland.confkeeps the legacy parser regardless of its version.So on Hyprland >= 0.54 with a
.conf, Waybar sends Lua-formatted dispatches, Hyprland answersInvalid dispatcher, and clicking a workspace button does nothing.Fix
Hyprland already reports which config manager it loaded, in the
systeminforeply:This reads that field first and falls back to the existing version heuristic when it is absent, which is the case on versions predating the Lua config manager. The query is read-only, so detection stays free of the side effects that motivated replacing the earlier
dispatch workspace __waybar_probe__approach.Behaviour by case:
configProviderluaThe parsing sits in a pure
parseConfigProvider()helper, separate from the socket call, so it is covered by unit tests without needing a live compositor.Tests
Added to
test/hyprland/backend.cpp:parseConfigProvider reads the config manager Hyprland loaded— a realistic fullsysteminforeply, barelua, barelegacy,legacysubstituted into the full reply (the exact hyprland/workspaces: Workspace switching buttons are unclickable on version >= 0.55 with traditional config format #5198 case), and an unrecognised value that must not be treated as Lua.parseConfigProvider tolerates formatting variations— tab separator, multiple spaces, CRLF line ending, value on the last line with no trailing newline, and an empty value.parseConfigProvider returns nullopt when the field is absent— an older reply and an empty reply, both of which must fall through to version detection rather than assume legacy.luaProtocolFromSystemInfo returns nullopt when Hyprland is not running—getSocket1Replythrows; detection has to degrade to the version fallback instead of propagating and breaking the click.Result on this branch:
Also verified end to end on Hyprland 0.56.1 with a Lua config:
systeminfoover the IPC socket reportsconfigProvider: lua, and the resulting/dispatch hl.dsp.focus({ workspace = "3" })returnsokand switches workspace.Caveat worth stating plainly: I could not exercise the legacy branch against a live pre-0.54 instance, only the parsing that selects it. Confirmation from someone running a traditional
hyprland.confwould be welcome.🤖 Generated with Claude Code