From e5b585d6b3de0c4701d4050606451f3bf4eeab0e Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 21 May 2026 11:44:11 +0200 Subject: [PATCH] Extract notification window focus helper --- bin/omarchy-hyprland-focus-app | 23 +++++++++++++++++++++++ shell/plugins/notifications/Service.qml | 16 ++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) create mode 100755 bin/omarchy-hyprland-focus-app diff --git a/bin/omarchy-hyprland-focus-app b/bin/omarchy-hyprland-focus-app new file mode 100755 index 00000000..d22d360c --- /dev/null +++ b/bin/omarchy-hyprland-focus-app @@ -0,0 +1,23 @@ +#!/bin/bash + +# omarchy:summary=Focus a Hyprland window by application class +# omarchy:args= +# omarchy:examples=omarchy hyprland focus app Slack + +usage() { + echo "Usage: omarchy-hyprland-focus-app " >&2 + exit 1 +} + +app=${1:-} +[[ -n $app ]] || usage + +address=$( + hyprctl clients -j 2>/dev/null | + jq -r --arg name "${app,,}" \ + '[.[] | select((.class // "") | ascii_downcase | startswith($name))] | first.address // empty' +) + +[[ -n $address ]] || exit 1 + +hyprctl dispatch focuswindow "address:$address" >/dev/null diff --git a/shell/plugins/notifications/Service.qml b/shell/plugins/notifications/Service.qml index e7c22687..025773a3 100644 --- a/shell/plugins/notifications/Service.qml +++ b/shell/plugins/notifications/Service.qml @@ -16,6 +16,7 @@ Item { // Injected by omarchy-shell (the first-party service loader). property var shell: null + property string omarchyPath: Quickshell.env("OMARCHY_PATH") readonly property string home: Quickshell.env("HOME") // History + DND live under XDG_STATE_HOME: they're persistent user state // (history of received notifications, last-set DND preference), not @@ -361,18 +362,13 @@ Item { } // Try to focus an existing Hyprland window matching the notification's - // sender. We shell out to a small bash one-liner because Hyprland's class - // matcher is regex-based but its case-sensitivity is implementation- - // defined (std::regex doesn't reliably honor `(?i)`). Easier to query the - // client list ourselves and pick the first match. + // sender. The helper handles case-insensitive class matching. function focusApp(entry) { if (!entry || !entry.app) return - var lower = String(entry.app).toLowerCase() - focusAppProc.command = ["bash", "-lc", - "hyprctl clients -j 2>/dev/null | " + - "jq -r --arg name " + Util.shellQuote(lower) + " " + - "'[.[] | select((.class // \"\") | ascii_downcase | startswith($name))] | first.address // empty' | " + - "xargs -r -I{} hyprctl dispatch focuswindow address:{}"] + focusAppProc.command = [ + service.omarchyPath + "/bin/omarchy-hyprland-focus-app", + String(entry.app) + ] focusAppProc.running = true }