diff --git a/bin/omarchy-menu b/bin/omarchy-menu index e947995e..59e4af8e 100755 --- a/bin/omarchy-menu +++ b/bin/omarchy-menu @@ -4,19 +4,30 @@ # omarchy:args=[toggle|summon|close|refresh|ping] [route] # omarchy:examples=omarchy menu | omarchy menu toggle system | omarchy menu summon style.theme | omarchy menu refresh -# Thin wrapper around `omarchy-shell menu`. Keybinds and the bar icon -# call omarchy-shell directly to skip the omarchy-CLI dispatch hop; -# this exists so humans get `omarchy menu toggle X` etc. +# Thin wrapper around the standard plugin IPC surface. The menu is the +# first-party `omarchy.menu` plugin; routes are passed as JSON payload. + +set -euo pipefail verb="${1-toggle}" route="${2-root}" +menu_payload() { + perl -MEncode=decode -MJSON::PP=encode_json -e 'print encode_json({ menu => decode("UTF-8", $ARGV[0]) })' "$1" +} + case "$verb" in - toggle | summon) - exec omarchy-shell menu "$verb" "$route" + toggle) + exec omarchy-shell shell toggle omarchy.menu "$(menu_payload "$route")" ;; - close | refresh | ping) - exec omarchy-shell menu "$verb" + summon) + exec omarchy-shell shell summon omarchy.menu "$(menu_payload "$route")" + ;; + close) + exec omarchy-shell shell hide omarchy.menu + ;; + refresh | ping) + exec omarchy-shell shell call omarchy.menu "$verb" "{}" ;; -h | --help | help) cat < [args...] -# omarchy:examples=omarchy shell shell ping | omarchy-shell menu toggle root +# omarchy:examples=omarchy shell shell ping | omarchy-shell shell toggle omarchy.menu '{"menu":"root"}' QUIET=0 if [[ ${1:-} == "-q" ]]; then @@ -26,7 +26,7 @@ Examples: omarchy-shell shell summon omarchy.settings "{}" omarchy-shell -q Indicators refresh omarchy-shell shell listPlugins - omarchy-shell menu toggle root + omarchy-shell shell toggle omarchy.menu '{"menu":"root"}' USAGE exit 0 fi diff --git a/config/omarchy/extensions/omarchy-menu.jsonc b/config/omarchy/extensions/omarchy-menu.jsonc index d989e1f3..ca9e95f6 100644 --- a/config/omarchy/extensions/omarchy-menu.jsonc +++ b/config/omarchy/extensions/omarchy-menu.jsonc @@ -11,7 +11,7 @@ // action Shell command to run. If omitted, the row is a submenu. // target Existing submenu id to open. Use for links/aliases. // provider Runtime provider function/command returning JSON rows. - // aliases alternate `omarchy-shell menu summon ` routes; also searchable. + // aliases alternate `omarchy menu summon ` routes; also searchable. // keywords Extra search terms beyond id/label/aliases. // description Optional subtitle and extra search text. // when Shell condition; hide row when it fails. diff --git a/default/hypr/bindings/utilities.lua b/default/hypr/bindings/utilities.lua index 0926a6cd..00720bf7 100644 --- a/default/hypr/bindings/utilities.lua +++ b/default/hypr/bindings/utilities.lua @@ -1,12 +1,12 @@ o.bind("SUPER + SPACE", "Launch apps", "omarchy-shell shell toggle omarchy.launcher \"{}\"") o.bind("SUPER + CTRL + E", "Emojis", "omarchy-shell shell toggle omarchy.emojis") -o.bind("SUPER + CTRL + C", "Capture menu", "omarchy-shell menu toggle capture") -o.bind("SUPER + CTRL + O", "Toggle menu", "omarchy-shell menu toggle toggle") -o.bind("SUPER + CTRL + H", "Hardware menu", "omarchy-shell menu toggle hardware") -o.bind("SUPER + ALT + SPACE", "Omarchy menu", "omarchy-shell menu toggle root") -o.bind("SUPER + SHIFT + code:201", "Omarchy menu", "omarchy-shell menu toggle root") -o.bind("SUPER + ESCAPE", "System menu", "omarchy-shell menu toggle system") -o.bind("XF86PowerOff", "Power menu", "omarchy-shell menu toggle system", { locked = true }) +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 + ALT + SPACE", "Omarchy menu", "omarchy-menu toggle root") +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 + K", "Show key bindings", "omarchy-menu-keybindings") o.bind("SUPER + ALT + K", "Show Tmux key bindings", "omarchy-menu-tmux-keybindings") o.bind("XF86Calculator", "Calculator", "gnome-calculator") @@ -16,8 +16,8 @@ o.bind("SUPER + SHIFT + CTRL + UP", "Move bar to top", "omarchy-style-bar-positi o.bind("SUPER + SHIFT + CTRL + DOWN", "Move bar to bottom", "omarchy-style-bar-position bottom") o.bind("SUPER + SHIFT + CTRL + LEFT", "Move bar to left", "omarchy-style-bar-position left") o.bind("SUPER + SHIFT + CTRL + RIGHT", "Move bar to right", "omarchy-style-bar-position right") -o.bind("SUPER + CTRL + SPACE", "Background switcher", "omarchy-shell menu toggle background") -o.bind("SUPER + SHIFT + CTRL + SPACE", "Theme menu", "omarchy-shell menu toggle theme") +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 + 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") @@ -37,15 +37,15 @@ o.bind("switch:on:Lid Switch", nil, "omarchy-hw-external-monitors && omarchy-hyp o.bind("switch:off:Lid Switch", nil, "omarchy-hyprland-monitor-internal on", { locked = true }) o.bind("PRINT", "Screenshot", "omarchy-capture-screenshot") -o.bind("ALT + PRINT", "Screenrecording", "omarchy-capture-screenrecording --stop-recording || omarchy-shell menu toggle trigger.capture.screenrecord") +o.bind("ALT + PRINT", "Screenrecording", "omarchy-capture-screenrecording --stop-recording || omarchy-menu toggle trigger.capture.screenrecord") o.bind("SUPER + PRINT", "Color picker", "pkill hyprpicker || hyprpicker -a") o.bind("SUPER + CTRL + PRINT", "Extract text (OCR) from screenshot", "omarchy-capture-text-extraction") -o.bind("SUPER + CTRL + S", "Share", "omarchy-shell menu toggle share") +o.bind("SUPER + CTRL + S", "Share", "omarchy-menu toggle share") o.bind("SUPER + CTRL + PERIOD", "Transcode", "omarchy-transcode") -o.bind("SUPER + CTRL + R", "Set reminder", "omarchy-shell menu toggle reminder-set") +o.bind("SUPER + CTRL + R", "Set reminder", "omarchy-menu toggle reminder-set") o.bind("SUPER + CTRL + ALT + R", "Show reminders", "omarchy-reminder show") o.bind("SUPER + SHIFT + CTRL + R", "Clear reminders", "omarchy-reminder clear") @@ -53,11 +53,11 @@ o.bind("SUPER + CTRL + ALT + T", "Show time", "omarchy-notification-time") o.bind("SUPER + CTRL + ALT + B", "Show battery remaining", "omarchy-notification-battery") o.bind("SUPER + CTRL + ALT + W", "Toggle weather", "omarchy-notification-weather") -o.bind("SUPER + CTRL + A", "Audio panel", "omarchy-shell panels.audio toggle") -o.bind("SUPER + CTRL + B", "Bluetooth panel", "omarchy-shell panels.bluetooth toggle") -o.bind("SUPER + CTRL + D", "Display panel", "omarchy-shell panels.monitor toggle") -o.bind("SUPER + CTRL + W", "Network panel", "omarchy-shell panels.network toggle") -o.bind("SUPER + CTRL + P", "Power panel", "omarchy-shell panels.power toggle") +o.bind("SUPER + CTRL + A", "Audio", "omarchy-shell omarchy.audio toggle") +o.bind("SUPER + CTRL + B", "Bluetooth", "omarchy-shell omarchy.bluetooth toggle") +o.bind("SUPER + CTRL + D", "Display", "omarchy-shell omarchy.monitor toggle") +o.bind("SUPER + CTRL + W", "Network", "omarchy-shell omarchy.network toggle") +o.bind("SUPER + CTRL + P", "Power", "omarchy-shell omarchy.power toggle") o.bind("SUPER + CTRL + T", "Activity", { tui = "btop" }) o.bind("SUPER + CTRL + Z", "Zoom in", function() diff --git a/default/omarchy/omarchy-menu.jsonc b/default/omarchy/omarchy-menu.jsonc index 960f9c3e..2145a428 100644 --- a/default/omarchy/omarchy-menu.jsonc +++ b/default/omarchy/omarchy-menu.jsonc @@ -7,7 +7,7 @@ // Dotted IDs define the tree. Use provider:"name" only when the submenu // calls provider_name() or a command named "name" to return JSON rows. // Optional fields: - // aliases alternate `omarchy-shell menu summon ` routes; also searchable + // aliases alternate `omarchy menu summon ` routes; also searchable // keywords extra search terms beyond id/label/aliases // when shell condition; hide row when it fails // checked shell condition; append ✓ when it succeeds diff --git a/install/config/hardware/bluetooth.sh b/install/config/hardware/bluetooth.sh index 1e5d0c30..c93379e3 100644 --- a/install/config/hardware/bluetooth.sh +++ b/install/config/hardware/bluetooth.sh @@ -7,7 +7,7 @@ sudo sed -i 's/^#\?AutoEnable=.*/AutoEnable=false/' /etc/bluetooth/main.conf mkdir -p ~/.config/wireplumber/wireplumber.conf.d/ cp "$OMARCHY_PATH/default/wireplumber/wireplumber.conf.d/bluetooth-a2dp-autoconnect.conf" ~/.config/wireplumber/wireplumber.conf.d/ -# Quickshell.Bluetooth has no Agent API, so the omarchy-shell panels.bluetooth +# Quickshell.Bluetooth has no Agent API, so the omarchy.bluetooth plugin # can't answer the auth prompts bluez issues during pair(). bt-agent registers # a NoInputNoOutput agent on the system bus so pair() actually completes. mkdir -p ~/.config/systemd/user/ diff --git a/install/first-run/wifi.sh b/install/first-run/wifi.sh index f184eba5..d03e7ad7 100644 --- a/install/first-run/wifi.sh +++ b/install/first-run/wifi.sh @@ -8,7 +8,7 @@ notify_update() { notify_wifi() { ( action=$(notify-send -a omarchy-action -u critical --hint=string:omarchy-glyph:󰖩 "Click to Setup Wi-Fi" -A "default=Setup") - [[ $action == "default" ]] && omarchy-shell panels.network toggle + [[ $action == "default" ]] && omarchy-shell omarchy.network toggle ) >/dev/null 2>&1 & } diff --git a/shell/plugins/menu/Menu.qml b/shell/plugins/menu/Menu.qml index 4918b04c..669c6288 100644 --- a/shell/plugins/menu/Menu.qml +++ b/shell/plugins/menu/Menu.qml @@ -23,8 +23,7 @@ Item { if (payload.mode === "select" || payload.mode === "input") { root.openDmenu(payload) } else { - root.pendingInitialMenu = payload.initialMenu || payload.menu || "root" - root.openExistingMenu(root.pendingInitialMenu) + root.openRoute(payload.initialMenu || payload.menu || "root") } } @@ -32,6 +31,14 @@ Item { root.cancel() } + function refresh() { + defaultMenuFile.reload() + userMenuFile.reload() + return "ok" + } + + function ping() { return "ok" } + property string fontFamily: Style.font.menuFamily // JSONC menu definitions. The shell parses both at startup and merges // the user file on top of the defaults, so the keybind → IPC → visible @@ -761,17 +768,13 @@ Item { } ListModel { id: displayModel } - // ----------------------------------------------------------- IPC surface + // ----------------------------------------------------------- route surface // - // `omarchy-shell menu summon ` is the keybind hot path — the - // Hyprland bindings call straight into here, no bash hops. `refresh` is - // a manual nudge for when watchChanges isn't enough (e.g. someone wired - // a CI step that re-emits the JSONC). - - // Mirrors `route_target` in the old bash bin: caller may pass a real id - // (`system`, `setup.power`) or an alias declared in JSONC (`power`, - // `reminder-set`). Unknown strings fall through to the id-as-route - // behavior so misspellings still attempt to open the literal id. + // The menu is opened through the standard plugin lifecycle: + // `omarchy-shell shell summon omarchy.menu '{"menu":"system"}'`. + // Callers may pass a real id (`system`, `setup.power`) or an alias declared + // in JSONC (`power`, `reminder-set`). Unknown strings fall through to the + // id-as-route behavior so misspellings still attempt to open the literal id. function resolveRoute(input) { var raw = String(input || "").toLowerCase().replace(/_/g, "-") if (!raw || raw === "go" || raw === "menu") return "root" @@ -786,49 +789,22 @@ Item { return raw } - IpcHandler { - target: "menu" - - function summon(initialMenu: string): string { - var id = root.resolveRoute(initialMenu) - var entry = root.items[id] - // If the resolved id is an action (i.e. the user invoked an alias for - // a leaf, e.g. `omarchy-shell menu summon screenrecord-stop`), - // run it directly instead of opening an action with no children. - if (entry && entry.kind === "action" && entry.action) { - Quickshell.execDetached(["bash", "-lc", entry.action]) - return "ok" - } - // If it's a link (a redirect to another menu), follow the link. - if (entry && entry.kind === "link" && entry.target) id = entry.target - var payload = JSON.stringify({ menu: id }) - root.open(payload) - return "ok" - } - - // Hitting the same menu keybind while the menu is already visible should - // close it — even if the requested target differs from the active one. - // Matches the old bash bin's `close_visible_quickshell_menu` short-circuit. - function toggle(initialMenu: string): string { - if (root.opened) { - root.cancel() - return "closed" - } - return summon(initialMenu) - } - - function refresh(): string { - defaultMenuFile.reload() - userMenuFile.reload() - return "ok" - } - - function close(): string { + function openRoute(initialMenu) { + var id = root.resolveRoute(initialMenu) + var entry = root.items[id] + // If the resolved id is an action (i.e. the user invoked an alias for + // a leaf, e.g. `omarchy menu summon screenrecord-stop`), run it directly + // instead of opening an action with no children. + if (entry && entry.kind === "action" && entry.action) { root.cancel() + Quickshell.execDetached(["bash", "-lc", entry.action]) return "ok" } - - function ping(): string { return "ok" } + // If it's a link (a redirect to another menu), follow the link. + if (entry && entry.kind === "link" && entry.target) id = entry.target + root.pendingInitialMenu = id + root.openExistingMenu(id) + return "ok" } Process { diff --git a/shell/plugins/notifications/Service.qml b/shell/plugins/notifications/Service.qml index 025773a3..ebca0b32 100644 --- a/shell/plugins/notifications/Service.qml +++ b/shell/plugins/notifications/Service.qml @@ -28,7 +28,7 @@ Item { // ~/.cache where regeneratable artifacts belong. readonly property string cacheDir: home + "/.cache/omarchy/" readonly property string imageCacheDir: cacheDir + "notification-images/" - // Corner radius is shared with omarchy-shell menu and bar settings panel. + // Corner radius is shared with the menu and bar settings panel. // It mirrors Hyprland's current decoration:rounding value. readonly property int cornerRadius: Style.cornerRadius // Surfaces anchor relative to the omarchy bar so popups and history land