wren-linux / lib / sway.sh
# shellcheck shell=bash
# lib/sway.sh: the sway config and the snippets parts add to it.
# Sourced by lib.sh.
SWAY_CONFIG="$HOME/.config/sway/config"
SWAY_SNIPPETS="$HOME/.config/sway/config.d"
SWAY_INCLUDE="include $SWAY_SNIPPETS/*.conf"
# The one definition of how Wren Linux locks the screen
# (the lock screen's color from the theme, bin/theme; black if it can't say)
# shellcheck disable=SC2016 # expanded where it runs; one word: a checked color
LOCK_CMD='swaylock -f -c $(~/.local/bin/theme get LOCK 2>/dev/null || echo 000000)'
# The launcher on Super+d (parts/wmenu.sh) is wmenu-run. wmenu has no height
# setting: its height follows its font. So the launcher gets a font a little
# larger than the bar's, to cover the bar completely instead of leaving a strip of
# it showing, and opaque colors in the bar's own black and white (the bar is
# see-through, so a see-through launcher would show it underneath). If a strip
# of the bar still shows, make the 12 bigger; if the launcher is too tall,
# smaller (the line is in ~/.config/sway/config, or here and run parts/wmenu.sh).
# shellcheck disable=SC2016 # $menu is sway's variable, not the shell's
LAUNCHER_STOCK='set $menu wmenu-run'
# shellcheck disable=SC2016
LAUNCHER_STYLED='set $menu wmenu-run -f '"'monospace 12'"' -N 000000 -n ffffff -M 000000 -m ffffff -S ffffff -s 000000'
# replace_line FILE OLD NEW: the line OLD in FILE becomes NEW; nothing else changes
replace_line() {
local tmp
tmp=$(mktemp)
awk -v old="$2" -v new="$3" '$0 == old { print new; next } { print }' "$1" >"$tmp"
cat "$tmp" >"$1"
rm -f "$tmp"
}
# style_launcher FILE: the stock launcher line becomes Wren Linux's. A line you
# changed yourself is left alone (the return status says whether it was ours).
style_launcher() {
if grep -qxF "$LAUNCHER_STYLED" "$1"; then return 0; fi
grep -qxF "$LAUNCHER_STOCK" "$1" || return 1
replace_line "$1" "$LAUNCHER_STOCK" "$LAUNCHER_STYLED"
}
# unstyle_launcher FILE: back to the stock line
unstyle_launcher() { replace_line "$1" "$LAUNCHER_STYLED" "$LAUNCHER_STOCK"; }
# Some apps only speak X11. sway runs them through XWayland, but only
# finds XWayland when sway starts, so a fresh install needs a re-login.
need_xwayland() {
local had=false
is_installed xwayland && had=true
# Always, even if it's there: this script's marker must hold it, or
# removing another app that uses XWayland would take it away
apt_install xwayland
$had || warn "Installed XWayland. Log out and back in once so sway can use it."
}
# The user's sway config is the stock /etc/sway/config plus one include
# line, so each parts/ script can add or remove its own snippet file.
ensure_sway_config() {
[ -f /etc/sway/config ] || die "sway isn't installed. Run install-base.sh first."
mkdir -p "$SWAY_SNIPPETS"
[ -f "$SWAY_CONFIG" ] || cp /etc/sway/config "$SWAY_CONFIG"
# The snippets rebind these keys; sway shows its "errors in your config
# file" bar for a key bound twice, so the stock bindings go
sed -i -E '/^[[:space:]]*bindsym( --locked)? (XF86(Audio(Mute|LowerVolume|RaiseVolume|MicMute)|MonBrightness(Down|Up))|Print) exec (pactl|brightnessctl|grim)/d' "$SWAY_CONFIG"
if ! grep -qxF "$SWAY_INCLUDE" "$SWAY_CONFIG"; then
printf '\n# Wren Linux feature snippets\n%s\n' "$SWAY_INCLUDE" >>"$SWAY_CONFIG"
fi
}
# What opens at login: one file of yours (bin/wren-autostart, parts/autostart.sh).
# autostart_ensure: the command, sway starting it, and the file if there is none
AUTOSTART_FILE=$HOME/.config/wren/autostart
autostart_ensure() {
install_bin wren-autostart
if [ ! -e "$AUTOSTART_FILE" ]; then
mkdir -p "${AUTOSTART_FILE%/*}"
install -m 0644 "$WREN_DIR/data/autostart" "$AUTOSTART_FILE"
fi
if [ ! -f "$SWAY_SNIPPETS/autostart.conf" ]; then
put_snippet autostart <<'EOF'
# What opens at login: ~/.config/wren/autostart (Wren Linux parts/autostart.sh)
exec ~/.local/bin/wren-autostart
EOF
fi
}
# sway -C exits 0 even on errors, so look for them in its output
check_sway_config() {
local out
# Headless backend: validating needs no seat, so this also works over ssh
out=$(WLR_BACKENDS=headless WLR_RENDERER=pixman WLR_LIBINPUT_NO_DEVICES=1 sway -C -c "$SWAY_CONFIG" 2>&1 || true)
if grep -q '\[ERROR\]' <<<"$out"; then
grep '\[ERROR\]' <<<"$out" >&2
return 1
fi
}
reload_sway() {
if [ -n "${SWAYSOCK:-}" ] && swaymsg reload >/dev/null 2>&1; then
note "Reloaded sway."
else
note "Takes effect the next time sway starts."
fi
}
# put_snippet NAME < content: writes config.d/NAME.conf and checks it. If
# sway rejects it, the snippet that was there before is put back.
put_snippet() {
local f="$SWAY_SNIPPETS/$1.conf" old=
ensure_sway_config
if [ -f "$f" ]; then
old=$(mktemp)
cp "$f" "$old"
fi
cat >"$f"
if ! check_sway_config; then
if [ -n "$old" ]; then
mv "$old" "$f"
die "sway rejected the new $f, so the old one was put back."
fi
rm -f "$f"
die "sway rejected $f, so it was removed."
fi
if [ -n "$old" ]; then rm -f "$old"; fi
note "Wrote $f"
reload_sway
}
remove_snippet() {
local f="$SWAY_SNIPPETS/$1.conf"
if [ -f "$f" ]; then
rm -f "$f"
note "Removed $f"
reload_sway
fi
}