Bound IPC transport deadlines while preserving portal leases, supervise desktop helper and agent recovery, and reserve final floating window geometry during placement. Stabilize CLI output and isolated tests, expand workspace CI, resolve formatting and lint failures, and bundle the MIT license with installer compatibility.
110 lines
4.2 KiB
Bash
Executable File
110 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
session_target_started=0
|
|
shell_pid=
|
|
agent_pid=
|
|
autostart_pid=
|
|
manage_session=0
|
|
if [[ ${FERESE_SESSION_MODE:-desktop} == desktop && ${FERESE_SESSION_IMPORT_ENV:-0} == 1 ]]; then
|
|
manage_session=1
|
|
fi
|
|
cleanup() {
|
|
trap - EXIT INT TERM
|
|
if [[ -n $autostart_pid ]]; then
|
|
kill "$autostart_pid" 2>/dev/null || true
|
|
wait "$autostart_pid" 2>/dev/null || true
|
|
fi
|
|
if [[ -n $shell_pid ]]; then kill "$shell_pid" 2>/dev/null || true; fi
|
|
if [[ -n $agent_pid ]]; then
|
|
kill "$agent_pid" 2>/dev/null || true
|
|
wait "$agent_pid" 2>/dev/null || true
|
|
fi
|
|
if ((session_target_started)); then
|
|
systemctl --user stop ferese-session.target || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
trap 'exit 130' INT
|
|
trap 'exit 143' TERM
|
|
|
|
# The compositor supplies its new Wayland socket before this helper starts.
|
|
# Nested previews must never replace the host session's activation environment.
|
|
if ((manage_session)); then
|
|
# Shell control uses a private socket FD. Activation must use the public
|
|
# socket so portal and other desktop services connect as ordinary clients.
|
|
public_display=${FERESE_PUBLIC_WAYLAND_DISPLAY:-${WAYLAND_DISPLAY:-}}
|
|
# Empty assignments replace stale values; D-Bus cannot remove activation variables.
|
|
activation_vars=(
|
|
"WAYLAND_DISPLAY=$public_display"
|
|
"DISPLAY=${DISPLAY:-}"
|
|
"XAUTHORITY=${XAUTHORITY:-}"
|
|
"FERESE_SOCKET=${FERESE_SOCKET:-}"
|
|
XDG_CURRENT_DESKTOP
|
|
XDG_SESSION_DESKTOP
|
|
XDG_SESSION_TYPE
|
|
)
|
|
if command -v dbus-update-activation-environment >/dev/null; then
|
|
if ! env WAYLAND_DISPLAY="$public_display" \
|
|
dbus-update-activation-environment --systemd "${activation_vars[@]}"; then
|
|
env WAYLAND_DISPLAY="$public_display" \
|
|
dbus-update-activation-environment "${activation_vars[@]}" || true
|
|
fi
|
|
fi
|
|
# User buses can outlive logout and may predate a newly installed service directory.
|
|
if command -v dbus-send >/dev/null; then
|
|
dbus-send --session --type=method_call --print-reply \
|
|
--dest=org.freedesktop.DBus /org/freedesktop/DBus \
|
|
org.freedesktop.DBus.ReloadConfig >/dev/null || true
|
|
fi
|
|
if command -v systemctl >/dev/null; then
|
|
systemctl --user daemon-reload || true
|
|
if systemctl --user start ferese-session.target; then
|
|
session_target_started=1
|
|
# A user manager can retain the target across session transitions.
|
|
# Refresh an already-running portal after importing this session's
|
|
# environment so it uses the installed release and current display.
|
|
systemctl --user try-restart xdg-desktop-portal-ferese.service || true
|
|
else
|
|
echo 'Ferese: graphical session target could not start; portal activation may be unavailable.' >&2
|
|
fi
|
|
fi
|
|
fi
|
|
release_dir=$(dirname -- "$(readlink -f -- "$0")")
|
|
# Agent failures must not take down a healthy shell. The compositor supervises
|
|
# this helper (and creates fresh private connections) when the shell itself exits.
|
|
supervise_agent() {
|
|
local child= delay=1 started
|
|
trap 'trap - TERM INT; if [[ -n $child ]]; then kill "$child" 2>/dev/null || true; wait "$child" 2>/dev/null || true; fi; exit 0' TERM INT
|
|
while true; do
|
|
started=$SECONDS
|
|
env -u WAYLAND_SOCKET -u FERESE_SHELL_CONTROL_SOCKET \
|
|
WAYLAND_DISPLAY="${FERESE_PUBLIC_WAYLAND_DISPLAY:-${WAYLAND_DISPLAY:-}}" \
|
|
"$release_dir/ferese-polkit-agent" &
|
|
child=$!
|
|
wait "$child" || true
|
|
child=
|
|
if ((SECONDS - started >= 60)); then delay=1; fi
|
|
sleep "$delay" &
|
|
child=$!
|
|
wait "$child" || true
|
|
child=
|
|
if ((delay < 30)); then delay=$((delay * 2)); fi
|
|
if ((delay > 30)); then delay=30; fi
|
|
done
|
|
}
|
|
supervise_agent &
|
|
agent_pid=$!
|
|
"$release_dir/ferese-shell" &
|
|
shell_pid=$!
|
|
if ((manage_session)) && [[ ${FERESE_CLIENT_RESTART:-0} != 1 && -x $release_dir/feresectl ]]; then
|
|
env WAYLAND_DISPLAY="${FERESE_PUBLIC_WAYLAND_DISPLAY:-${WAYLAND_DISPLAY:-}}" \
|
|
"$release_dir/feresectl" autostart &
|
|
autostart_pid=$!
|
|
fi
|
|
if wait "$shell_pid"; then
|
|
status=0
|
|
else
|
|
status=$?
|
|
fi
|
|
exit "$status"
|