Package: waybar Version: 0.15.0-1 Severity: normal Tags: patch X-Debbugs-Cc: [email protected]
Dear Maintainer, Hyprland 0.55 has been released with lua support[1], and will soon be uploaded into Debian after the hyprutils migration[2][3] is complete. When hyprland 0.55 starts up with a lua config file, it stops responding to old-style `hyprctl dispatch` commands on its IPC socket, which waybar's `hyprland/workspaces` module relies on for workspace switching, so clicking on a workspace to switch to it will no longer work. This has been fixed upstream in PR #5013[4], specifically in commit e17c0d9f0a73acc370df60ec8c532b1ed2385c73. I've backported the commit onto version 0.15.0-1 and attached it here. I've also test-built a waybar package locally and can confirm that it fixes the issue with hyprland 0.55.1 running in lua mode. [1] https://hypr.land/news/26_lua/ [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1136342 [3] https://release.debian.org/transitions/html/auto-hyprutils.html [4] https://github.com/Alexays/Waybar/pull/5013 -- System Information: Debian Release: forky/sid APT prefers questing-updates APT policy: (500, 'questing-updates'), (500, 'questing-security'), (500, 'questing'), (100, 'questing-backports') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 6.17.0-23-generic (SMP w/14 CPU threads; PREEMPT) Kernel taint flags: TAINT_CPU_OUT_OF_SPEC, TAINT_OOT_MODULE, TAINT_UNSIGNED_MODULE Locale: LANG=en_SG.UTF-8, LC_CTYPE=en_SG.UTF-8 (charmap=UTF-8), LANGUAGE=en_SG:en Shell: /bin/sh linked to /usr/bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages waybar depends on: ii init-system-helpers 1.68 ii libatkmm-1.6-1v5 2.28.4-1build4 ii libc6 2.42-0ubuntu3.1 ii libcairomm-1.0-1v5 1.14.5-2build1 ii libdbusmenu-gtk3-4 18.10.20180917~bzr492+repack1-4 ii libevdev2 1.13.4+dfsg-1 ii libfmt10 10.1.1+ds1-4 ii libgcc-s1 15.2.0-4ubuntu4 ii libglib2.0-0t64 2.86.0-2ubuntu0.3 ii libglibmm-2.4-1t64 2.66.8-1 ii libgps30t64 3.25-5ubuntu1.25.10.1 ii libgtk-3-0t64 3.24.50-1ubuntu2 ii libgtk-layer-shell0 0.9.2-2 ii libgtkmm-3.0-1t64 3.24.10-1 ii libinput10 1.28.1-1ubuntu0.3 ii libjack-jackd2-0 [libjack-0.125] 1.9.22~dfsg-5 ii libjsoncpp26 1.9.6-3 ii libmpdclient2t64 2.22-1.1build1 ii libnl-3-200 3.7.0-2build1 ii libnl-genl-3-200 3.7.0-2build1 ii libpipewire-0.3-0t64 1.4.7-3ubuntu2 ii libplayerctl2 2.4.1-3 ii libpulse0 1:17.0+dfsg1-2ubuntu3 ii libsigc++-2.0-0v5 2.12.1-4 ii libsndio7.0 1.10.0-0.2 ii libspdlog1.15 [libspdlog1.15-fmt10] 1:1.15.3+ds-1 ii libstdc++6 15.2.0-4ubuntu4 ii libudev1 257.9-0ubuntu2.4 ii libupower-glib3 1.90.9-5 ii libwayland-client0 1.24.0-1build1 ii libwireplumber-0.5-0 0.5.10-3ubuntu1 ii libxkbregistry0 1.12.3-1 waybar recommends no packages. Versions of packages waybar suggests: ii fonts-font-awesome 5.0.10+really4.7.0~dfsg-4.1 pn gir1.2-playerctl-2.0 <none> ii libayatana-appindicator3-1 [libappindicator3-1 0.5.94-1 ] ii python3 3.13.7-1 pn sway <none> -- no debconf information
From: Higor Prado <[email protected]> Date: Wed, 29 Apr 2026 15:53:09 -0300 X-Dgit-Generated: 0.15.0-1 b007f6d817595d2aecb46cddbc2f6223d51ac1bb Subject: [PATCH] fix(hyprland/workspaces): adapt dispatch commands for Lua IPC protocol Hyprland 0.54 replaced the text-based dispatch socket protocol with a Lua-based one. Commands like "dispatch workspace 1" are now interpreted as invalid Lua (return hl.dispatch(workspace 1)), breaking workspace clicks and scroll navigation. Add IPC::dispatch() that probes the running Hyprland on first call and routes commands through the new hl.dsp Lua API when the Lua protocol is detected, falling back to the old text format otherwise. Origin: https://github.com/Alexays/Waybar/commit/e17c0d9f0a73acc370df60ec8c532b1ed2385c73 Bug: https://github.com/Alexays/Waybar/pull/5013 Applied-Upstream: https://github.com/Alexays/Waybar/commit/e17c0d9f0a73acc370df60ec8c532b1ed2385c73 --- diff --git a/include/modules/hyprland/backend.hpp b/include/modules/hyprland/backend.hpp index 2e0ef65..84e056f 100644 --- a/include/modules/hyprland/backend.hpp +++ b/include/modules/hyprland/backend.hpp @@ -3,6 +3,7 @@ #include <filesystem> #include <list> #include <mutex> +#include <optional> #include <string> #include <thread> #include <utility> @@ -34,6 +35,10 @@ class IPC { Json::Value getSocket1JsonReply(const std::string& rq); static std::filesystem::path getSocketFolder(const char* instanceSig); + /// Dispatch a Hyprland command. Automatically uses the correct protocol + /// (legacy text or Lua-based) depending on the running Hyprland version. + static std::string dispatch(const std::string& dispatcher, const std::string& arg); + protected: static std::filesystem::path socketFolder_; @@ -41,6 +46,15 @@ class IPC { void socketListener(); void parseIPC(const std::string&); + /// Detect whether the running Hyprland uses the Lua-based IPC protocol. + /// Returns true for Hyprland >= 0.54 (Lua config), false for older versions. + static bool isLuaProtocol(); + + /// Build a Lua-format dispatch command string. + static std::string buildLuaDispatch(const std::string& dispatcher, const std::string& arg); + + static std::optional<bool> s_luaProtocolDetected_; // cached detection result + std::thread ipcThread_; std::mutex callbackMutex_; util::JsonParser parser_; diff --git a/src/modules/hyprland/backend.cpp b/src/modules/hyprland/backend.cpp index 7060d30..1f772ec 100644 --- a/src/modules/hyprland/backend.cpp +++ b/src/modules/hyprland/backend.cpp @@ -10,11 +10,13 @@ #include <unistd.h> #include <filesystem> +#include <optional> #include <string> namespace waybar::modules::hyprland { std::filesystem::path IPC::socketFolder_; +std::optional<bool> IPC::s_luaProtocolDetected_; std::filesystem::path IPC::getSocketFolder(const char* instanceSig) { static std::mutex folderMutex; @@ -243,4 +245,69 @@ Json::Value IPC::getSocket1JsonReply(const std::string& rq) { return parser_.parse(reply); } +bool IPC::isLuaProtocol() { + if (s_luaProtocolDetected_.has_value()) { + 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; + + if (luaProto) { + spdlog::info("Hyprland IPC: detected Lua-based dispatch protocol (Hyprland >= 0.54)"); + } else { + spdlog::info("Hyprland IPC: detected legacy dispatch protocol"); + } + + s_luaProtocolDetected_ = luaProto; + return luaProto; +} + +std::string IPC::buildLuaDispatch(const std::string& dispatcher, const std::string& arg) { + // Map old-style dispatchers to the new Lua hl.dsp API. + // + // Old format: dispatch workspace 1 + // New format: /dispatch hl.dsp.focus({ workspace = "1" }) + // + // Old format: dispatch focusworkspaceoncurrentmonitor 2 + // New format: /dispatch hl.dsp.focus({ workspace = "2", monitor = "current" }) + // + // Old format: dispatch togglespecialworkspace name + // New format: /dispatch hl.dsp.workspace.toggle_special("name") + + if (dispatcher == "workspace") { + return "/dispatch hl.dsp.focus({ workspace = \"" + arg + "\" })"; + } + if (dispatcher == "focusworkspaceoncurrentmonitor") { + return "/dispatch hl.dsp.focus({ workspace = \"" + arg + "\", monitor = \"current\" })"; + } + if (dispatcher == "togglespecialworkspace") { + if (arg.empty()) { + return "/dispatch hl.dsp.workspace.toggle_special()"; + } + return "/dispatch hl.dsp.workspace.toggle_special(\"" + arg + "\")"; + } + + // Fallback for any other dispatcher: try the old format wrapped in dispatch(). + // This may not work for all dispatchers, but it's a reasonable default. + spdlog::warn("Hyprland IPC: unknown dispatcher '{}' in Lua mode, attempting generic format", + dispatcher); + return "/dispatch hl.dsp." + dispatcher + "(\"" + arg + "\")"; +} + +std::string IPC::dispatch(const std::string& dispatcher, const std::string& arg) { + if (isLuaProtocol()) { + return getSocket1Reply(buildLuaDispatch(dispatcher, arg)); + } + // Legacy format: "dispatch <dispatcher> <arg>" + std::string cmd = "dispatch " + dispatcher; + if (!arg.empty()) { + cmd += " " + arg; + } + return getSocket1Reply(cmd); +} + } // namespace waybar::modules::hyprland diff --git a/src/modules/hyprland/workspace.cpp b/src/modules/hyprland/workspace.cpp index 4cdd891..b8090bd 100644 --- a/src/modules/hyprland/workspace.cpp +++ b/src/modules/hyprland/workspace.cpp @@ -71,20 +71,20 @@ bool Workspace::handleClicked(GdkEventButton* bt) const { try { if (id() > 0) { // normal if (m_workspaceManager.moveToMonitor()) { - m_ipc.getSocket1Reply("dispatch focusworkspaceoncurrentmonitor " + std::to_string(id())); + IPC::dispatch("focusworkspaceoncurrentmonitor", std::to_string(id())); } else { - m_ipc.getSocket1Reply("dispatch workspace " + std::to_string(id())); + IPC::dispatch("workspace", std::to_string(id())); } } else if (!isSpecial()) { // named (this includes persistent) if (m_workspaceManager.moveToMonitor()) { - m_ipc.getSocket1Reply("dispatch focusworkspaceoncurrentmonitor name:" + name()); + IPC::dispatch("focusworkspaceoncurrentmonitor", "name:" + name()); } else { - m_ipc.getSocket1Reply("dispatch workspace name:" + name()); + IPC::dispatch("workspace", "name:" + name()); } } else if (id() != -99) { // named special - m_ipc.getSocket1Reply("dispatch togglespecialworkspace " + name()); + IPC::dispatch("togglespecialworkspace", name()); } else { // special - m_ipc.getSocket1Reply("dispatch togglespecialworkspace"); + IPC::dispatch("togglespecialworkspace", ""); } return true; } catch (const std::exception& e) {
signature.asc
Description: PGP signature

