Fix clipboard watcher lifecycle

This commit is contained in:
David Heinemeier Hansson
2026-07-02 11:09:42 -07:00
parent 76e0b718b2
commit 738821c3ab
4 changed files with 216 additions and 9 deletions
+4 -3
View File
@@ -19,7 +19,8 @@ Item {
property string historyPath: Quickshell.env("HOME") + "/.local/state/omarchy/clipboard-history.json"
property string captureScript: root.omarchyPath + "/shell/plugins/clipboard/capture.sh"
property string watchCommand: "script=$1\ntrap 'kill $(jobs -p) 2>/dev/null' EXIT\nOMARCHY_CLIPBOARD_WATCH_MIME=text wl-paste --type text --watch \"$script\" 2>/dev/null &\nOMARCHY_CLIPBOARD_WATCH_MIME=image/png wl-paste --type image/png --watch \"$script\" 2>/dev/null &\nwait"
property string initScript: root.omarchyPath + "/shell/plugins/clipboard/init.sh"
property string watchScript: root.omarchyPath + "/shell/plugins/clipboard/watch.sh"
// Shares the [menu] surface tokens — themes that style the menu also
// style the clipboard. Selected-row colors composed in the
// singleton so consumers drop them straight into Rectangle bindings.
@@ -261,11 +262,11 @@ Item {
Process {
id: initProc
command: ["bash", "-c", "mkdir -p ~/.local/state/omarchy\nscript=$1\nfor pid in $(pgrep -x wl-paste || true); do\n cmdline=$(tr '\\0' ' ' <\"/proc/$pid/cmdline\" 2>/dev/null || true)\n if [[ $cmdline == *\"wl-paste --type text --watch $script \"* || $cmdline == *\"wl-paste --type \"*\" --watch $script \"* || $cmdline == *\"/shell/plugins/clipboard/capture.sh\"* ]]; then\n kill \"$pid\" 2>/dev/null || true\n fi\ndone", "clipboard-init", root.captureScript]
command: [root.initScript, root.captureScript]
onExited: {
currentProc.command = [root.captureScript]
currentProc.running = true
watchProc.command = ["bash", "-c", root.watchCommand, "clipboard-watch", root.captureScript]
watchProc.command = [root.watchScript, root.captureScript]
watchProc.running = true
}
}
+39
View File
@@ -0,0 +1,39 @@
#!/bin/bash
current_script=${1:-}
[[ -n $current_script ]] || exit 0
is_clipboard_capture() {
local path=$1
[[ $path == */shell/plugins/clipboard/capture.sh ]]
}
watched_script_for_pid() {
local pid=$1
local -a args=()
local i
[[ -r /proc/$pid/cmdline ]] || return 1
mapfile -d '' -t args <"/proc/$pid/cmdline" || return 1
((${#args[@]} > 0)) || return 1
for ((i = 0; i < ${#args[@]}; i++)); do
if [[ ${args[i]} == "--watch" ]]; then
printf '%s\n' "${args[i + 1]:-}"
return 0
fi
done
return 1
}
for pid in $(pgrep -x wl-paste 2>/dev/null || true); do
watched_script=$(watched_script_for_pid "$pid" || true)
[[ -n $watched_script ]] || continue
is_clipboard_capture "$watched_script" || continue
if [[ $watched_script == $current_script || ! -e $watched_script ]]; then
kill "$pid" 2>/dev/null || true
fi
done
+46
View File
@@ -0,0 +1,46 @@
#!/bin/bash
set -o pipefail
capture_script=${1:-}
[[ -n $capture_script && -x $capture_script ]] || exit 1
owner_pid=$PPID
watchdog_pid=""
cleanup() {
local pid
if [[ -n $watchdog_pid ]]; then
kill "$watchdog_pid" 2>/dev/null || true
fi
for pid in $(jobs -p); do
[[ $pid == $watchdog_pid ]] && continue
kill "$pid" 2>/dev/null || true
done
wait 2>/dev/null || true
}
stop() {
cleanup
exit 0
}
trap cleanup EXIT
trap stop HUP INT TERM
(
while kill -0 "$owner_pid" 2>/dev/null; do
sleep 1
done
kill -TERM "$$" 2>/dev/null || true
) &
watchdog_pid=$!
OMARCHY_CLIPBOARD_WATCH_MIME=text wl-paste --type text --watch "$capture_script" 2>/dev/null &
OMARCHY_CLIPBOARD_WATCH_MIME=image/png wl-paste --type image/png --watch "$capture_script" 2>/dev/null &
wait