Skip to content

fix(linux): register toggle hotkey via hyprctl eval on Hyprland Lua configs - #31

Open
jondkinney wants to merge 1 commit into
mainfrom
fix/hyprland-lua-config-toggle-bind
Open

fix(linux): register toggle hotkey via hyprctl eval on Hyprland Lua configs#31
jondkinney wants to merge 1 commit into
mainfrom
fix/hyprland-lua-config-toggle-bind

Conversation

@jondkinney

Copy link
Copy Markdown
Owner

Problem

On newer Hyprland (0.55+) with a Lua config manager (~/.config/hypr/hyprland.lua, as omarchy now ships), the toggle hotkey silently stops working. The daemon registers its runtime bind via hyprctl keyword "bind = …", which the non-legacy Lua parser rejects:

keyword can't work with non-legacy parsers. Use eval.

So no keybind is ever registered — hyprctl binds shows zero vernier entries and pressing the shortcut does nothing. Everything else stays healthy (daemon, IPC, vernier toggle from CLI/menu all work), which masks the failure and makes it look like a binding problem rather than a parser-compat one.

Fix

register_hyprland_toggle_for / unregister_hyprland_toggle try the legacy keyword path first and fall back to hyprctl eval + the hl.bind / hl.unbind Lua API when the config is Lua. Legacy hyprlang configs are unaffected.

  • New accel_to_hyprland_lua produces the MOD + MOD + KEY form Lua expects (e.g. SUPER + CTRL + ALT + SHIFT + F).
  • Small shared helpers: hyprctl_cmd, hyprctl_output_needs_lua_eval, lua_escape.

Subtle bug worth a look in review

hyprctl keyword "bind=…" exits 0 even when it prints the non-legacy rejection. So the "needs eval" branch is intentionally ordered before the status.success() arm — otherwise the success arm wins, the fallback never fires, and registration silently no-ops while logging success.

Verification

End-to-end on Hyprland 0.55.3 + a Lua config:

  • Daemon self-registers the bind via the eval path (hyprctl eval hl.bind: …).
  • Bind appears in hyprctl binds (modmask: 77, key: F, description: Vernier toggle).
  • Lua binds render as dispatcher __lua with no command text — grep hyprctl binds by description, not "vernier".

Note: this is orthogonal to a separate screencast-portal wedge that can stop measurement (capture) on long-running sessions; that one is a system/portal issue cleared by re-login, not a code change.

🤖 Generated with Claude Code

…onfigs

Newer Hyprland (0.55+) supports a Lua config manager (`~/.config/hypr/
hyprland.lua`, as omarchy now ships). Under that "non-legacy" parser
`hyprctl keyword "bind = ..."` is rejected with "keyword can't work with
non-legacy parsers. Use eval." — so the daemon's runtime toggle bind
never lands and the shortcut silently does nothing (the daemon, IPC, and
`vernier toggle` all stay healthy, which masks the failure).

`register_hyprland_toggle_for` / `unregister_hyprland_toggle` now try the
legacy `keyword` path first and fall back to `hyprctl eval` with the
`hl.bind` / `hl.unbind` Lua API when the config is Lua. Adds
`accel_to_hyprland_lua` (the `MOD + MOD + KEY` form) plus small
`hyprctl_cmd` / `hyprctl_output_needs_lua_eval` / `lua_escape` helpers.

Note: `hyprctl keyword` *exits 0* even when it prints the non-legacy
rejection, so the "needs eval" check is ordered before the
`status.success()` arm — otherwise the fallback never fires and
registration silently no-ops while logging success.

Legacy hyprlang configs are unaffected. Verified end-to-end on Hyprland
0.55.3 + a Lua config: the bind appears in `hyprctl binds` (modmask 77,
key F) and toggles measurement.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant