fix(hyprland): detect Lua protocol without side-effecting dispatch

isLuaProtocol() probed the protocol by sending a real
"dispatch workspace __waybar_probe__". On Hyprland < 0.54 "workspace"
is a valid dispatcher, so the probe actually switched the user to a junk
workspace named __waybar_probe__ on the first workspace click/scroll.

Detect the protocol with the read-only "version" IPC query instead:
parse the numeric "version" field (falling back to the always-present
"tag" field) and treat Hyprland >= 0.54 as Lua. This has no side
effects. On any parse/query failure we log and fall back to the legacy
protocol, preserving prior behavior for older versions.
This commit is contained in:
Alex
2026-07-05 10:13:24 +02:00
parent 30dcd7a7ca
commit 74cf45d530
+34 -5
View File
@@ -297,11 +297,40 @@ bool IPC::isLuaProtocol() {
return *s_luaProtocolDetected_;
}
// Probe: send a harmless old-style dispatch and check the error.
// In Lua-based Hyprland (>= 0.54) the error contains "hl.dispatch".
// In older versions it returns "ok" or a different error.
auto reply = getSocket1Reply("dispatch workspace __waybar_probe__");
bool luaProto = reply.find("hl.dispatch") != std::string::npos;
// Detect the Lua-based dispatch protocol (Hyprland >= 0.54) via the read-only
// "version" query. This MUST have no side effects: an earlier probe issued a real
// "dispatch workspace __waybar_probe__", which on Hyprland < 0.54 actually switched
// the user to a junk workspace named __waybar_probe__ on the first click/scroll.
bool luaProto = false;
try {
util::JsonParser parser;
const Json::Value ver = parser.parse(getSocket1Reply("j/version"));
// Prefer the numeric "version" field ("0.54.0"); fall back to the "tag" field
// ("v0.54.0" or "v0.54.0-16-gdeadbee"), which is present on all releases.
std::string versionStr = ver["version"].asString();
if (versionStr.empty()) {
versionStr = ver["tag"].asString();
}
const size_t firstDigit = versionStr.find_first_of("0123456789");
if (firstDigit != std::string::npos) {
// std::stoi parses the leading integer and stops at the first non-digit, so it
// tolerates the trailing ".patch-commits-ghash" suffix on the tag.
const int major = std::stoi(versionStr.substr(firstDigit));
int minor = 0;
const size_t dot = versionStr.find('.', firstDigit);
if (dot != std::string::npos && dot + 1 < versionStr.size()) {
minor = std::stoi(versionStr.substr(dot + 1));
}
luaProto = major > 0 || (major == 0 && minor >= 54);
} else {
spdlog::warn("Hyprland IPC: could not parse version '{}', assuming legacy protocol",
versionStr);
}
} catch (const std::exception& e) {
spdlog::warn("Hyprland IPC: version detection failed ({}), assuming legacy protocol", e.what());
}
if (luaProto) {
spdlog::info("Hyprland IPC: detected Lua-based dispatch protocol (Hyprland >= 0.54)");