diff options
Diffstat (limited to '')
-rw-r--r-- | dot_local/lib/sway/executable_session.sh | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/dot_local/lib/sway/executable_session.sh b/dot_local/lib/sway/executable_session.sh new file mode 100644 index 0000000..43c4d35 --- /dev/null +++ b/dot_local/lib/sway/executable_session.sh @@ -0,0 +1,137 @@ +#!/bin/sh +# +# Address several issues with DBus activation and systemd user sessions +# +# 1. DBus-activated and systemd services do not share the environment with user +# login session. In order to make the applications that have GUI or interact +# with the compositor work as a systemd user service, certain variables must +# be propagated to the systemd and dbus. +# Possible (but not exhaustive) list of variables: +# - DISPLAY - for X11 applications that are started as user session services +# - WAYLAND_DISPLAY - similarly, this is needed for wayland-native services +# - I3SOCK/SWAYSOCK - allow services to talk with sway using i3 IPC protocol +# +# 2. `xdg-desktop-portal` requires XDG_CURRENT_DESKTOP to be set in order to +# select the right implementation for screenshot and screencast portals. +# With all the numerous ways to start sway, it's not possible to rely on the +# right value of the XDG_CURRENT_DESKTOP variable within the login session, +# therefore the script will ensure that it is always set to `sway`. +# +# 3. GUI applications started as a systemd service (or via xdg-autostart-generator) +# may rely on the XDG_SESSION_TYPE variable to select the backend. +# Ensure that it is always set to `wayland`. +# +# 4. The common way to autostart a systemd service along with the desktop +# environment is to add it to a `graphical-session.target`. However, systemd +# forbids starting the graphical session target directly and encourages use +# of an environment-specific target units. Therefore, the integration +# package here provides and uses `sway-session.target` which would bind to +# the `graphical-session.target`. +# +# 5. Stop the target and unset the variables when the compositor exits. +# +# References: +# - https://github.com/swaywm/sway/wiki#gtk-applications-take-20-seconds-to-start +# - https://github.com/emersion/xdg-desktop-portal-wlr/wiki/systemd-user-services,-pam,-and-environment-variables +# - https://www.freedesktop.org/software/systemd/man/systemd.special.html#graphical-session.target +# - https://systemd.io/DESKTOP_ENVIRONMENTS/ +# +export XDG_CURRENT_DESKTOP=sway +export XDG_SESSION_DESKTOP="${XDG_SESSION_DESKTOP:-sway}" +export XDG_SESSION_TYPE=wayland +VARIABLES="DESKTOP_SESSION XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_TYPE" +VARIABLES="${VARIABLES} DISPLAY I3SOCK SWAYSOCK WAYLAND_DISPLAY" +VARIABLES="${VARIABLES} XCURSOR_THEME XCURSOR_SIZE" +SESSION_TARGET="sway-session.target" +SESSION_SHUTDOWN_TARGET="sway-session-shutdown.target" +WITH_CLEANUP=1 + +print_usage() { + cat <<EOH +Usage: + --help Show this help message and exit. + --add-env NAME, -E NAME + Add a variable name to the subset of environment passed + to the user session. Can be specified multiple times. + --no-cleanup Skip cleanup code at compositor exit. +EOH +} + +while [ $# -gt 0 ]; do + case "$1" in + --help) + print_usage + exit 0 ;; + # The following flag is intentionally not exposed in the usage info: + # - I don't believe that's the right or safe thing to do; + # - systemd upstream is of the same opinion and has already deprecated + # the ability to import the full environment (systemd/systemd#18137) + --all-environment) + VARIABLES="" ;; + --add-env=?*) + VARIABLES="${VARIABLES} ${1#*=}" ;; + --add-env | -E) + shift + VARIABLES="${VARIABLES} ${1}" ;; + --with-cleanup) + ;; # ignore (enabled by default) + --no-cleanup) + unset WITH_CLEANUP ;; + -*) + echo "Unexpected option: $1" 1>&2 + print_usage + exit 1 ;; + *) + break ;; + esac + shift +done + +# Check if another Sway session is already active. +# +# Ignores all other kinds of parallel or nested sessions +# (Sway on Gnome/KDE/X11/etc.), as the only way to detect these is to check +# for (WAYLAND_)?DISPLAY and that is know to be broken on Arch. +if systemctl --user -q is-active "$SESSION_TARGET"; then + echo "Another session found; refusing to overwrite the variables" + exit 1 +fi + +# DBus activation environment is independent from systemd. While most of +# dbus-activated services are already using `SystemdService` directive, some +# still don't and thus we should set the dbus environment with a separate +# command. +if hash dbus-update-activation-environment 2>/dev/null; then + # shellcheck disable=SC2086 + dbus-update-activation-environment --systemd ${VARIABLES:- --all} +fi + +# reset failed state of all user units +systemctl --user reset-failed + +# shellcheck disable=SC2086 +systemctl --user import-environment $VARIABLES +systemctl --user start "$SESSION_TARGET" + +# Optionally, wait until the compositor exits and cleanup variables and services. +if [ -z "$WITH_CLEANUP" ] || + [ -z "$SWAYSOCK" ] || + ! hash swaymsg 2>/dev/null +then + exit 0; +fi + +# declare cleanup handler and run it on script termination via kill or Ctrl-C +session_cleanup () { + # stop the session target and unset the variables + systemctl --user start --job-mode=replace-irreversibly "$SESSION_SHUTDOWN_TARGET" + if [ -n "$VARIABLES" ]; then + # shellcheck disable=SC2086 + systemctl --user unset-environment $VARIABLES + fi +} +trap session_cleanup INT TERM +# wait until the compositor exits +swaymsg -t subscribe '["shutdown"]' +# run cleanup handler on normal exit +session_cleanup |