From 82ae514609e32507e7d59e653694dda6ae58d9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Toma=C5=A1evi=C4=87?= Date: Thu, 13 Aug 2026 20:28:43 +0200 Subject: [PATCH] Fix notification focus for agent terminals (#6801) * Fix notification focus for agent terminals * Restrict notification title fallback to agents * Simplify the focus fallback to a lazy two-tier query Co-Authored-By: Claude Fable 5 --------- Co-authored-by: David Heinemeier Hansson Co-authored-by: Claude Fable 5 --- bin/omarchy-hyprland-focus-app | 11 ++++++-- test/shell.d/hyprland-focus-app-test.sh | 35 ++++++++++++++++++++++--- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/bin/omarchy-hyprland-focus-app b/bin/omarchy-hyprland-focus-app index 08e1fa6a..ca7b9976 100755 --- a/bin/omarchy-hyprland-focus-app +++ b/bin/omarchy-hyprland-focus-app @@ -1,6 +1,6 @@ #!/bin/bash -# omarchy:summary=Focus a Hyprland window by application class +# omarchy:summary=Focus a Hyprland window by application identity # omarchy:args= # omarchy:examples=omarchy hyprland focus app Slack @@ -12,10 +12,17 @@ usage() { app=${1:-} [[ -n $app ]] || usage +# Agent terminals notify as kitty/foot/etc. while their shared window class is +# org.omarchy.agent, leaving the terminal name only in initialTitle. So match +# by class first, then fall back to the launch-time title of agent windows. address=$( hyprctl clients -j 2>/dev/null | jq -r --arg pattern "$app" \ - '[.[] | select((.class // "") | test($pattern; "i"))] | first.address // empty' + 'def matches($value): ($value // "") | test($pattern; "i"); + first( + (.[] | select(matches(.class))), + (.[] | select(.initialClass == "org.omarchy.agent" and matches(.initialTitle))) + ).address // empty' ) [[ -n $address ]] || exit 1 diff --git a/test/shell.d/hyprland-focus-app-test.sh b/test/shell.d/hyprland-focus-app-test.sh index 3b998ef6..e8422141 100644 --- a/test/shell.d/hyprland-focus-app-test.sh +++ b/test/shell.d/hyprland-focus-app-test.sh @@ -13,7 +13,7 @@ mkdir -p "$mock_bin" cat >"$mock_bin/hyprctl" <<'SH' #!/bin/bash if [[ $1 == "clients" ]]; then - printf '[{"address":"0xabc","class":"chromium"}]\n' + printf '%s\n' "$OMARCHY_TEST_CLIENTS_JSON" elif [[ $1 == "dispatch" ]]; then printf '%s\n' "$2" >"$OMARCHY_TEST_FOCUS_DISPATCH" fi @@ -21,10 +21,39 @@ SH chmod +x "$mock_bin/hyprctl" dispatch_log="$test_tmp/dispatch" -PATH="$mock_bin:$PATH" OMARCHY_TEST_FOCUS_DISPATCH="$dispatch_log" \ - bash "$ROOT/bin/omarchy-hyprland-focus-app" chromium +clients_json='[{"address":"0xabc","class":"chromium"}]' +PATH="$mock_bin:$PATH" OMARCHY_TEST_CLIENTS_JSON="$clients_json" \ + OMARCHY_TEST_FOCUS_DISPATCH="$dispatch_log" \ + bash "$ROOT/bin/omarchy-hyprland-focus-app" '^chromium$' grep -F 'hl.dsp.focus({ window = "address:0xabc" })' "$dispatch_log" >/dev/null || \ fail "app focus uses the workspace-aware Hyprland dispatcher" pass "app focus follows windows across workspaces" + +clients_json='[ + {"address":"0xviber","class":"com.viber.Viber","initialClass":"com.viber.Viber","initialTitle":"Viber"}, + {"address":"0xagent","class":"org.omarchy.agent","initialClass":"org.omarchy.agent","initialTitle":"kitty"} +]' +PATH="$mock_bin:$PATH" OMARCHY_TEST_CLIENTS_JSON="$clients_json" \ + OMARCHY_TEST_FOCUS_DISPATCH="$dispatch_log" \ + bash "$ROOT/bin/omarchy-hyprland-focus-app" kitty + +grep -F 'hl.dsp.focus({ window = "address:0xagent" })' "$dispatch_log" >/dev/null || \ + fail "app focus falls back to the initial window title" + +pass "app focus finds terminals launched under a shared agent class" + +clients_json='[ + {"address":"0xbrowser","class":"chromium","initialClass":"chromium","initialTitle":"Mail settings"} +]' +rm -f "$dispatch_log" +if PATH="$mock_bin:$PATH" OMARCHY_TEST_CLIENTS_JSON="$clients_json" \ + OMARCHY_TEST_FOCUS_DISPATCH="$dispatch_log" \ + bash "$ROOT/bin/omarchy-hyprland-focus-app" Mail; then + fail "app focus rejects title matches from non-agent windows" +fi + +[[ ! -e $dispatch_log ]] || fail "app focus leaves focus unchanged for unrelated title matches" + +pass "app focus restricts title matching to agent terminals"