1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
#!/bin/sh
# Bundled with UWSM, but is independent of it.
# https://github.com/Vladimir-csp/uwsm
# https://gitlab.freedesktop.org/Vladimir-csp/uwsm
# NOTE: this is a hack to locally prop up applications that do not properly
# wait for tray themselves, but should.
#
# Put it into `ExecStartPre=-` of the autostart unit or make it a part of a
# wrapper to delay application startup until tray is available or timeout is
# reached. Positional arguments: [TIMEOUT_SECONDS [DELAY_SECONDS]]
#
# This is not a part of any standard mechanism nor it should be, because there
# is no standard. Other custom mechanisms exist, i.e NixOS's `tray.target`, but
# nothing of sorts should be encouraged.
#
# If you find yourself in need of putting this script to use, consider filing a
# bug report for the culprit app.
set -e
wait_tray() {
# Run busctl monitor in background, save pid to $MON_PID.
# It will exit when any of tray dbus services' owner changes from
# nothing to something.
# wrap tray service names with dbus match args
set --
for arg in $TRAY_NAMES; do
# shellcheck disable=SC2089
set -- "$@" --match "type='signal',member='NameOwnerChanged',path='/org/freedesktop/DBus',arg0='${arg}',arg1=''"
done
# watch for message
busctl --user monitor \
--json=short \
--no-pager \
--no-legend \
"$@" \
--limit-messages 1 \
--timeout "${TIMEOUT}s" \
> /dev/null 2>&1 &
MON_PID=$!
}
check_tray() {
# return 0 if any of tray serivces is active
for service in $TRAY_NAMES; do
if busctl --user status "$service" --no-pager --no-legend > /dev/null 2>&1; then
return 0
fi
done
return 1
}
# shellcheck disable=SC2329
trapterm() {
# cancel trap to make it single-use
trap - INT TERM HUP EXIT
# suppress stderr, including "Terminated" message
exec 2> /dev/null
kill "$MON_PID" || true
wait "$MON_PID" || true
}
delay() {
if [ "$DELAY" -gt "0" ]; then
printf '%s\n' "Delaying for $DELAY seconds"
sleep "$DELAY"
fi
}
usage() {
printf '%s\n' "Usage: ${0##*/} [TIMEOUT_SECONDS [DELAY_SECONDS]]"
}
########
TRAY_NAMES="org.kde.StatusNotifierWatcher org.freedesktop.StatusNotifierWatcher"
TIMEOUT=${1:-30}
DELAY=${2:-0}
case " $* " in
*' -h '* | *' --help '*)
usage
exit 0
;;
esac
case "$TIMEOUT" in
*[!0-9]*)
{
printf '%s\n' "Expected number of seconds as timeout, got: $TIMEOUT"
usage
} >&2
exit 1
;;
esac
case "$DELAY" in
*[!0-9]*)
{
printf '%s\n' "Expected number of seconds as delay, got: $DELAY"
usage
} >&2
exit 1
;;
esac
## start busctl monitor in background
wait_tray
## set cleanup trap
trap trapterm INT TERM HUP EXIT
## check current state and exit on success
if check_tray; then
printf '%s\n' "Tray is active"
delay
exit 0
fi
printf '%s\n' "Waiting $TIMEOUT seconds for Tray to activate..."
wait "$MON_PID" || true
# recheck current status
if check_tray; then
printf '%s\n' "Tray is active"
delay
exit 0
else
RC=$?
printf '%s\n' "Tray failed to activate!" >&2
exit "$RC"
fi
|