Open shell menus and panels through Hyprland global shortcuts (#13418)

Every binding that opened a menu or panel ran omarchy-menu or
omarchy-shell, which starts a qs client just to deliver one IPC call:
~60ms before the shell heard about the keypress.

The shell now registers a Hyprland global shortcut for each menu route
and panel in default/omarchy/shortcuts, and o.bind turns { menu = ... }
and { panel = ... } into hl.dsp.global for those, so a keypress spawns
nothing. A route or panel missing from the list binds through the
command as before. The default menu and panel bindings use the new form.

SUPER+SPACE opens the menu in ~31ms instead of ~94ms, measured from a
simulated keypress until the menu layer maps.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
David Heinemeier HanssonandClaude Opus 5.5 authored and GitHub committed 2026-09-27 18:02:01 +02:00
1 parent fd961e5300
commit 6762769bbf
9 files changed
+251 -22

No files matched your search

@@ -36,8 +36,12 @@ Edit `~/.config/hypr/bindings.lua`. Format:
```lua
o.bind("SUPER + SHIFT + R", "SSH", "alacritty -e ssh your-server")
o.bind("SUPER + B", "Browser", { launch = "chromium" }) -- launch wraps with uwsm-app
o.bind("SUPER + M", "Theme menu", { menu = "theme" }) -- toggle an Omarchy menu route
o.bind("SUPER + N", "Network", { panel = "omarchy.network" }) -- toggle a shell panel
```
Prefer `{ menu = ... }` and `{ panel = ... }` over running `omarchy-menu toggle ...` or `omarchy-shell shell toggle ...` as a command. Routes and panels listed in `$OMARCHY_PATH/default/omarchy/shortcuts` go straight to the running shell as Hyprland global shortcuts, with no process started on each press; any other route or panel still works, through the command.
View current bindings: `omarchy menu keybindings --print`
**IMPORTANT: When re-binding an existing key:**
+1 -1
View File
@@ -46,4 +46,4 @@ o.bind("SUPER + A", "Select all", send_shortcut_once("CTRL", "A"))
o.bind("SUPER + C", "Universal copy", universal_clipboard_shortcut("CTRL", "C", "CTRL SHIFT", "C"))
o.bind("SUPER + V", "Universal paste", universal_clipboard_shortcut("CTRL", "V", "CTRL SHIFT", "V"))
o.bind("SUPER + X", "Universal cut", send_shortcut_once("CTRL", "X"))
o.bind("SUPER + CTRL + V", "Clipboard manager", "omarchy-shell shell toggle omarchy.clipboard")
o.bind("SUPER + CTRL + V", "Clipboard manager", { panel = "omarchy.clipboard" })
+19 -19
View File
@@ -1,12 +1,12 @@
o.bind("SUPER + SPACE", "Omarchy menu", "omarchy-menu toggle")
o.bind("SUPER + ALT + SPACE", "Apps menu", "omarchy-menu toggle apps")
o.bind("SUPER + CTRL + E", "Emojis", "omarchy-shell shell toggle omarchy.emojis")
o.bind("SUPER + CTRL + C", "Capture menu", "omarchy-menu toggle capture")
o.bind("SUPER + CTRL + O", "Toggle menu", "omarchy-menu toggle toggle")
o.bind("SUPER + CTRL + H", "Hardware menu", "omarchy-menu toggle hardware")
o.bind("SUPER + SHIFT + code:201", "Omarchy menu", "omarchy-menu toggle root")
o.bind("SUPER + ESCAPE", "System menu", "omarchy-menu toggle system")
o.bind("XF86PowerOff", "Power menu", "omarchy-menu toggle system", { locked = true })
o.bind("SUPER + SPACE", "Omarchy menu", { menu = "root" })
o.bind("SUPER + ALT + SPACE", "Apps menu", { menu = "apps" })
o.bind("SUPER + CTRL + E", "Emojis", { panel = "omarchy.emojis" })
o.bind("SUPER + CTRL + C", "Capture menu", { menu = "capture" })
o.bind("SUPER + CTRL + O", "Toggle menu", { menu = "toggle" })
o.bind("SUPER + CTRL + H", "Hardware menu", { menu = "hardware" })
o.bind("SUPER + SHIFT + code:201", "Omarchy menu", { menu = "root" })
o.bind("SUPER + ESCAPE", "System menu", { menu = "system" })
o.bind("XF86PowerOff", "Power menu", { menu = "system" }, { locked = true })
o.bind("SUPER + K", "Keybindings", "omarchy-menu-keybindings")
o.bind("SUPER + ALT + K", "Tmux keybindings", "omarchy-menu-tmux-keybindings")
o.bind("SUPER + CTRL + K", "Herdr keybindings", "omarchy-menu-herdr-keybindings")
@@ -14,8 +14,8 @@ o.bind("SUPER + CTRL + Q", "Calculator", "omacalc")
o.bind("XF86Calculator", "Calculator", "omacalc")
o.bind_toggle("SUPER + SHIFT + SPACE", "Toggle top bar", "bar")
o.bind("SUPER + CTRL + SPACE", "Background switcher", "omarchy-menu toggle background")
o.bind("SUPER + SHIFT + CTRL + SPACE", "Theme menu", "omarchy-menu toggle theme")
o.bind("SUPER + CTRL + SPACE", "Background switcher", { menu = "background" })
o.bind("SUPER + SHIFT + CTRL + SPACE", "Theme menu", { menu = "theme" })
o.bind("SUPER + BACKSPACE", "Toggle window transparency", "omarchy-hyprland-window-transparency-toggle")
o.bind("SUPER + SHIFT + BACKSPACE", "Toggle window gaps", "omarchy-hyprland-window-gaps-toggle")
o.bind("SUPER + CTRL + BACKSPACE", "Toggle single-window square aspect", "omarchy-hyprland-window-single-square-aspect-toggle")
@@ -82,11 +82,11 @@ hl.on("layer.closed", function(layer)
end
end)
o.bind("SUPER + CTRL + S", "Share", "omarchy-menu toggle share")
o.bind("SUPER + CTRL + S", "Share", { menu = "share" })
o.bind("SUPER + CTRL + PERIOD", "Transcode", "omarchy-transcode")
o.bind("SUPER + CTRL + R", "Set reminder", "omarchy-menu toggle reminder-set")
o.bind("SUPER + CTRL + R", "Set reminder", { menu = "reminder-set" })
o.bind("SUPER + CTRL + ALT + R", "Show reminders", "omarchy-reminder show")
o.bind("SUPER + SHIFT + CTRL + R", "Clear reminders", "omarchy-reminder clear")
@@ -95,12 +95,12 @@ o.bind("SUPER + CTRL + ALT + B", "Show battery remaining", "omarchy-notification
o.bind("SUPER + CTRL + ALT + W", "Toggle weather", "omarchy-notification-weather")
o.bind("SUPER + SHIFT + CTRL + A", "Agent", "omarchy-agent --pick")
o.bind("SUPER + CTRL + A", "Audio", "omarchy-shell shell toggle omarchy.audio")
o.bind("SUPER + CTRL + B", "Bluetooth", "omarchy-shell shell toggle omarchy.bluetooth")
o.bind("SUPER + CTRL + D", "Display", "omarchy-shell shell toggle omarchy.monitor")
o.bind("SUPER + CTRL + ALT + D", "Calendar", "omarchy-shell shell toggle omarchy.clock")
o.bind("SUPER + CTRL + W", "Network", "omarchy-shell shell toggle omarchy.network")
o.bind("SUPER + CTRL + P", "Power", "omarchy-shell shell toggle omarchy.power")
o.bind("SUPER + CTRL + A", "Audio", { panel = "omarchy.audio" })
o.bind("SUPER + CTRL + B", "Bluetooth", { panel = "omarchy.bluetooth" })
o.bind("SUPER + CTRL + D", "Display", { panel = "omarchy.monitor" })
o.bind("SUPER + CTRL + ALT + D", "Calendar", { panel = "omarchy.clock" })
o.bind("SUPER + CTRL + W", "Network", { panel = "omarchy.network" })
o.bind("SUPER + CTRL + P", "Power", { panel = "omarchy.power" })
o.bind("SUPER + CTRL + T", "Activity", { tui = "btop" })
-- The letters above name a panel; the numbers count them. 1 is the leftmost
+38
View File
@@ -1,5 +1,7 @@
-- Shared helpers for Hyprland Lua configuration.
local paths = require("default.hypr.paths")
o = o or {}
local function shell_quote(value)
@@ -53,6 +55,38 @@ function o.cmd_missing(command)
return not o.cmd_present(command)
end
-- The global shortcuts the shell registers, read from the same list it reads.
local shell_shortcuts = nil
local function shell_shortcut_registered(name)
if not shell_shortcuts then
shell_shortcuts = {}
local file = io.open(paths.omarchy_path .. "/default/omarchy/shortcuts", "r")
if file then
for line in file:lines() do
local kind, target = line:match("^(%a+)%s+(%S+)%s*$")
if kind then
shell_shortcuts[kind .. "." .. target] = true
end
end
file:close()
end
end
return shell_shortcuts[name] == true
end
-- Reach the shell through its global shortcut when it registers one, so the
-- keypress spawns nothing. Anything else runs the command as before.
local function shell_dispatcher(kind, target, command)
local name = kind .. "." .. target
if shell_shortcut_registered(name) then
return hl.dsp.global("omarchy:" .. name)
end
return command
end
local function command_from(value, description)
if type(value) ~= "table" then
return value
@@ -60,6 +94,10 @@ local function command_from(value, description)
if value.omarchy then
return "omarchy-launch-" .. value.omarchy
elseif value.menu then
return shell_dispatcher("menu", value.menu, "omarchy-menu toggle " .. shell_quote(value.menu))
elseif value.panel then
return shell_dispatcher("panel", value.panel, "omarchy-shell shell toggle " .. shell_quote(value.panel))
elseif value.focus and value.launch then
return o.launch_sole(value.focus, value.launch)
elseif value.launch then
+24
View File
@@ -0,0 +1,24 @@
# Hyprland global shortcuts the Omarchy shell registers, one per line: a menu
# route to toggle, or a panel plugin to toggle. A binding written as
# o.bind(keys, description, { menu = "theme" }) or { panel = "omarchy.emojis" }
# dispatches the matching shortcut straight to the shell, with no IPC client to
# spawn per keypress. A route or panel missing here still binds, through the
# omarchy-menu or omarchy-shell command instead.
menu root
menu apps
menu capture
menu toggle
menu hardware
menu system
menu background
menu theme
menu share
menu reminder-set
panel omarchy.clipboard
panel omarchy.emojis
panel omarchy.audio
panel omarchy.bluetooth
panel omarchy.monitor
panel omarchy.clock
panel omarchy.network
panel omarchy.power