2026-08-09 01:22:23 -07:00
|
|
|
#!/bin/sh
|
|
|
|
|
# socktop-swipe installer.
|
|
|
|
|
#
|
2026-09-09 13:08:42 -07:00
|
|
|
# curl -fsSL https://gt.wittyoneoff.com/jason/socktop-swipe/raw/branch/main/install.sh | sh
|
2026-08-09 01:22:23 -07:00
|
|
|
#
|
2026-09-09 13:08:42 -07:00
|
|
|
# or, from a checkout:
|
|
|
|
|
#
|
|
|
|
|
# ./install.sh
|
|
|
|
|
#
|
|
|
|
|
# Everything is checked BEFORE anything is installed, and the full cost is
|
|
|
|
|
# printed once. Nothing touches the system before you answer the summary.
|
|
|
|
|
#
|
|
|
|
|
# --yes accept every default without asking
|
|
|
|
|
# --uninstall hand over to uninstall.sh
|
|
|
|
|
# --prefix DIR install to DIR/bin instead of /usr/local/bin
|
2026-08-09 01:22:23 -07:00
|
|
|
set -eu
|
|
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
REPO=https://gt.wittyoneoff.com/jason/socktop-swipe
|
|
|
|
|
PREFIX=/usr/local
|
|
|
|
|
ASSUME_YES=no
|
|
|
|
|
SRC=""
|
|
|
|
|
|
2026-08-09 01:22:23 -07:00
|
|
|
for a in "$@"; do
|
|
|
|
|
case "$a" in
|
2026-09-09 13:08:42 -07:00
|
|
|
--yes | -y) ASSUME_YES=yes ;;
|
|
|
|
|
--prefix=*) PREFIX=${a#--prefix=} ;;
|
|
|
|
|
--uninstall) exec sh -c "$(dirname "$0")/uninstall.sh" ;;
|
|
|
|
|
-h | --help) sed -n '2,16p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
|
2026-08-09 01:22:23 -07:00
|
|
|
*) echo "unknown option: $a" >&2; exit 2 ;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
BIN="$PREFIX/bin"
|
|
|
|
|
CONF_DIR="$HOME/.config/socktop-swipe"
|
|
|
|
|
CONF="$CONF_DIR/config.yaml"
|
|
|
|
|
UDEV=/etc/udev/rules.d/70-socktop-swipe.rules
|
|
|
|
|
XBLANK=/etc/X11/xorg.conf.d/10-no-blanking-socktop-swipe.conf
|
|
|
|
|
LIGHTDM=/etc/lightdm/lightdm.conf.d/50-autologin-socktop-swipe.conf
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Asking
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Piping into sh leaves stdin holding the SCRIPT, not a keyboard, so prompts
|
|
|
|
|
# must read the terminal directly. With no terminal at all we take defaults and
|
|
|
|
|
# say so rather than silently guessing.
|
|
|
|
|
if [ -r /dev/tty ] && [ -t 1 ]; then HAVE_TTY=yes; else HAVE_TTY=no; fi
|
|
|
|
|
|
|
|
|
|
say() { printf '%s\n' "$*"; }
|
|
|
|
|
step() { printf '\n==> %s\n' "$*"; }
|
|
|
|
|
warn() { printf ' !! %s\n' "$*" >&2; }
|
|
|
|
|
|
|
|
|
|
# ask "question" default(y|n) -> 0 for yes
|
|
|
|
|
ask() {
|
|
|
|
|
_q=$1
|
|
|
|
|
_d=$2
|
|
|
|
|
if [ "$ASSUME_YES" = yes ] || [ "$HAVE_TTY" = no ]; then
|
|
|
|
|
[ "$_d" = y ] && return 0 || return 1
|
2026-08-09 01:22:23 -07:00
|
|
|
fi
|
2026-09-09 13:08:42 -07:00
|
|
|
[ "$_d" = y ] && _hint="[Y/n]" || _hint="[y/N]"
|
|
|
|
|
while :; do
|
|
|
|
|
printf ' %s %s ' "$_q" "$_hint" >/dev/tty
|
|
|
|
|
read -r _a </dev/tty || _a=""
|
|
|
|
|
[ -z "$_a" ] && _a=$_d
|
|
|
|
|
case "$_a" in
|
|
|
|
|
[Yy] | [Yy][Ee][Ss]) return 0 ;;
|
|
|
|
|
[Nn] | [Nn][Oo]) return 1 ;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# askval "question" "default" -> echoes the answer
|
|
|
|
|
askval() {
|
|
|
|
|
if [ "$ASSUME_YES" = yes ] || [ "$HAVE_TTY" = no ]; then
|
|
|
|
|
printf '%s' "$2"
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
printf ' %s [%s] ' "$1" "$2" >/dev/tty
|
|
|
|
|
read -r _a </dev/tty || _a=""
|
|
|
|
|
[ -z "$_a" ] && _a=$2
|
|
|
|
|
printf '%s' "$_a"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
have() { command -v "$1" >/dev/null 2>&1; }
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Preflight
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
say "socktop-swipe installer"
|
|
|
|
|
say "======================="
|
|
|
|
|
|
|
|
|
|
OS_NAME=$(. /etc/os-release 2>/dev/null && printf '%s' "${PRETTY_NAME:-unknown}" || true)
|
|
|
|
|
[ -n "$OS_NAME" ] || OS_NAME=unknown
|
|
|
|
|
ARCH=$(uname -m)
|
|
|
|
|
|
|
|
|
|
PKG=""
|
|
|
|
|
PKG_INSTALL=""
|
|
|
|
|
for p in apt-get dnf pacman zypper apk; do
|
|
|
|
|
if have $p; then
|
|
|
|
|
PKG=$p
|
|
|
|
|
break
|
2026-08-09 01:22:23 -07:00
|
|
|
fi
|
2026-09-09 13:08:42 -07:00
|
|
|
done
|
|
|
|
|
case "$PKG" in
|
|
|
|
|
apt-get) PKG_INSTALL="sudo apt-get install -y" ;;
|
|
|
|
|
dnf) PKG_INSTALL="sudo dnf install -y" ;;
|
|
|
|
|
pacman) PKG_INSTALL="sudo pacman -S --needed --noconfirm" ;;
|
|
|
|
|
zypper) PKG_INSTALL="sudo zypper install -y" ;;
|
|
|
|
|
apk) PKG_INSTALL="sudo apk add" ;;
|
|
|
|
|
esac
|
|
|
|
|
|
|
|
|
|
# Display manager and window manager, for the autostart and autologin steps.
|
|
|
|
|
# NB: written as `if`, not `[ x ] && y`. Under `set -e` an AND-OR list that
|
|
|
|
|
# ends up false aborts the script, so a box with no lightdm would exit here.
|
|
|
|
|
DM=none
|
|
|
|
|
if [ -d /etc/lightdm ]; then DM=lightdm
|
|
|
|
|
elif [ -d /etc/gdm3 ] || [ -d /etc/gdm ]; then DM=gdm
|
|
|
|
|
elif [ -f /etc/sddm.conf ] || [ -d /etc/sddm.conf.d ]; then DM=sddm
|
2026-08-09 01:22:23 -07:00
|
|
|
fi
|
|
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
WM=none
|
|
|
|
|
if have i3; then WM=i3; fi
|
2026-08-09 01:22:23 -07:00
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
TERMINAL=""
|
|
|
|
|
for t in alacritty foot kitty xterm; do
|
|
|
|
|
if have $t; then
|
|
|
|
|
TERMINAL=$t
|
|
|
|
|
break
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
LOCKER=""
|
|
|
|
|
for l in xss-lock light-locker xscreensaver gnome-screensaver; do
|
|
|
|
|
if have $l; then
|
|
|
|
|
LOCKER="$LOCKER $l"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# Space for the toolchain and the build. Both land under $HOME unless
|
|
|
|
|
# CARGO_HOME says otherwise, which is exactly the 8GB-of-eMMC case.
|
|
|
|
|
avail_mb() { df -Pm "$1" 2>/dev/null | awk 'NR==2 {print $4}'; }
|
|
|
|
|
HOME_FREE=$(avail_mb "$HOME")
|
|
|
|
|
PREFIX_FREE=$(avail_mb "$(dirname "$PREFIX")")
|
|
|
|
|
|
|
|
|
|
step "Found"
|
|
|
|
|
say " system $OS_NAME ($ARCH)"
|
|
|
|
|
say " packages ${PKG:-none detected}"
|
|
|
|
|
say " display mgr $DM"
|
|
|
|
|
say " window mgr $WM"
|
|
|
|
|
say " terminal ${TERMINAL:-none found}"
|
|
|
|
|
say " tmux $(tmux -V 2>/dev/null || echo 'NOT INSTALLED')"
|
|
|
|
|
# Not `cargo --version | cut ... || echo`: the pipeline's status is cut's, and
|
|
|
|
|
# cut succeeds on empty input, so the fallback would never fire.
|
|
|
|
|
if have cargo; then
|
|
|
|
|
say " cargo $(cargo --version 2>/dev/null | cut -d' ' -f1-2)"
|
2026-08-09 01:22:23 -07:00
|
|
|
else
|
2026-09-09 13:08:42 -07:00
|
|
|
say " cargo NOT INSTALLED"
|
|
|
|
|
fi
|
|
|
|
|
say " git $(git --version 2>/dev/null || echo 'NOT INSTALLED')"
|
|
|
|
|
say " free space ${HOME_FREE:-?} MB in \$HOME, ${PREFIX_FREE:-?} MB on $PREFIX"
|
|
|
|
|
if [ -n "$LOCKER" ]; then say " screen locker $LOCKER"; fi
|
|
|
|
|
|
|
|
|
|
# What we are about to need.
|
|
|
|
|
NEED_PKGS=""
|
|
|
|
|
NEED_RUSTUP=no
|
|
|
|
|
COST_MB=10
|
|
|
|
|
|
|
|
|
|
if ! have tmux; then NEED_PKGS="$NEED_PKGS tmux"; fi
|
|
|
|
|
if ! have git; then NEED_PKGS="$NEED_PKGS git"; fi
|
|
|
|
|
if ! have cargo; then
|
|
|
|
|
NEED_RUSTUP=yes
|
|
|
|
|
COST_MB=$((COST_MB + 1200))
|
2026-08-09 01:22:23 -07:00
|
|
|
fi
|
2026-09-09 13:24:16 -07:00
|
|
|
# The build itself. Measured on an Atom x5-Z8350: a 103 MB target directory,
|
|
|
|
|
# 108 seconds, peaking at 1.1 GB of RAM. 250 leaves headroom.
|
|
|
|
|
COST_MB=$((COST_MB + 250))
|
2026-08-09 01:22:23 -07:00
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
if [ -z "$TERMINAL" ]; then
|
|
|
|
|
warn "no terminal emulator found. socktop-swipe can attach in an existing"
|
|
|
|
|
warn "terminal, but unattended autostart needs one. alacritty is the tested choice."
|
|
|
|
|
fi
|
|
|
|
|
if [ -z "$PKG" ]; then
|
|
|
|
|
warn "no supported package manager. Nothing will be installed for you;"
|
|
|
|
|
warn "make sure tmux, git and a Rust toolchain are present."
|
|
|
|
|
fi
|
|
|
|
|
if [ -n "$HOME_FREE" ] && [ "$HOME_FREE" -lt "$COST_MB" ]; then
|
|
|
|
|
warn "only ${HOME_FREE} MB free in \$HOME but about ${COST_MB} MB is needed."
|
|
|
|
|
warn "A source build will not fit. Free space first, or set CARGO_HOME and"
|
|
|
|
|
warn "CARGO_TARGET_DIR to somewhere with room."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
step "This will"
|
|
|
|
|
if [ -n "$NEED_PKGS" ]; then say " install packages:$NEED_PKGS"; fi
|
|
|
|
|
if [ "$NEED_RUSTUP" = yes ]; then say " install the Rust toolchain via rustup (~1.2 GB)"; fi
|
2026-09-09 13:24:16 -07:00
|
|
|
say " build socktop-swipe from source (~100 MB of build artifacts)"
|
2026-09-09 13:08:42 -07:00
|
|
|
say " install the binary to $BIN"
|
|
|
|
|
say " write a starter config to $CONF"
|
|
|
|
|
say " ...then ask about the touch device, autostart, autologin and blanking."
|
|
|
|
|
say ""
|
|
|
|
|
say " About ${COST_MB} MB of disk. Nothing has been changed yet."
|
|
|
|
|
say ""
|
|
|
|
|
|
|
|
|
|
if [ "$HAVE_TTY" = no ]; then
|
|
|
|
|
say "No terminal available, so every question takes its default."
|
|
|
|
|
say "Run the script directly for the interactive version:"
|
|
|
|
|
say " curl -fsSLO $REPO/raw/branch/main/install.sh && sh install.sh"
|
|
|
|
|
say ""
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
ask "Continue?" y || { say "Nothing done."; exit 0; }
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Dependencies
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
if [ -n "$NEED_PKGS" ]; then
|
|
|
|
|
step "Installing:$NEED_PKGS"
|
|
|
|
|
if [ -z "$PKG_INSTALL" ]; then
|
|
|
|
|
warn "no package manager -- install$NEED_PKGS yourself and re-run."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
if [ "$PKG" = apt-get ]; then sudo apt-get update; fi
|
|
|
|
|
# shellcheck disable=SC2086
|
|
|
|
|
$PKG_INSTALL $NEED_PKGS
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ "$NEED_RUSTUP" = yes ]; then
|
|
|
|
|
step "Installing the Rust toolchain"
|
|
|
|
|
if ask "Install rustup now?" y; then
|
|
|
|
|
curl -fsSL https://sh.rustup.rs | sh -s -- -y --profile minimal --no-modify-path
|
|
|
|
|
# shellcheck disable=SC1091
|
|
|
|
|
. "$HOME/.cargo/env"
|
|
|
|
|
else
|
|
|
|
|
say "Install Rust yourself, then re-run this script."
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
fi
|
|
|
|
|
if ! have cargo; then warn "cargo still not on PATH -- open a new shell and re-run."; exit 1; fi
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Source
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
here=$(CDPATH='' cd -- "$(dirname -- "$0")" 2>/dev/null && pwd || echo "")
|
|
|
|
|
if [ -n "$here" ] && [ -f "$here/Cargo.toml" ]; then
|
|
|
|
|
SRC=$here
|
|
|
|
|
step "Building from this checkout: $SRC"
|
2026-08-09 01:22:23 -07:00
|
|
|
else
|
2026-09-09 13:08:42 -07:00
|
|
|
SRC="$HOME/.local/src/socktop-swipe"
|
|
|
|
|
step "Fetching the source to $SRC"
|
|
|
|
|
mkdir -p "$(dirname "$SRC")"
|
|
|
|
|
if [ -d "$SRC/.git" ]; then
|
|
|
|
|
git -C "$SRC" pull --ff-only
|
|
|
|
|
else
|
|
|
|
|
git clone "$REPO" "$SRC"
|
|
|
|
|
fi
|
2026-08-09 01:22:23 -07:00
|
|
|
fi
|
|
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
step "Building (this is the slow part on a low-power box)"
|
|
|
|
|
( cd "$SRC" && cargo build --release )
|
|
|
|
|
sudo install -d "$BIN"
|
|
|
|
|
sudo install -m 755 "$SRC/target/release/socktop-swipe" "$BIN/socktop-swipe"
|
|
|
|
|
say " installed $BIN/socktop-swipe"
|
2026-08-10 00:47:36 -07:00
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Touch device
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
step "Touch panel"
|
|
|
|
|
DEVICE=""
|
|
|
|
|
# Prefer the by-id path: eventN numbers get reshuffled on reboot.
|
|
|
|
|
for d in /dev/input/by-id/*event*; do
|
|
|
|
|
[ -e "$d" ] || continue
|
|
|
|
|
if udevadm info --query=property --name="$d" 2>/dev/null | grep -q '^ID_INPUT_TOUCHSCREEN=1'; then
|
|
|
|
|
say " found touchscreen: $d"
|
|
|
|
|
if [ -z "$DEVICE" ]; then DEVICE=$d; fi
|
2026-08-10 00:47:36 -07:00
|
|
|
fi
|
2026-09-09 13:08:42 -07:00
|
|
|
done
|
|
|
|
|
if [ -z "$DEVICE" ]; then
|
|
|
|
|
warn "no touchscreen found under /dev/input/by-id/."
|
|
|
|
|
warn "If the panel is not plugged in yet, that is fine -- set touch.device"
|
|
|
|
|
warn "in the config later. 'socktop-swipe doctor --list' will show it."
|
|
|
|
|
DEVICE=/dev/input/by-id/CHANGE-ME
|
|
|
|
|
else
|
|
|
|
|
DEVICE=$(askval "Use which device?" "$DEVICE")
|
|
|
|
|
fi
|
2026-08-10 00:47:36 -07:00
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
step "Device access"
|
|
|
|
|
say " Reading touch events needs permission on the device."
|
|
|
|
|
say " A udev rule grants it for touchscreens only and takes effect at once."
|
|
|
|
|
say " The 'input' group grants access to every input device, keyboard included,"
|
|
|
|
|
say " and needs a full logout."
|
|
|
|
|
RELOGIN=no
|
|
|
|
|
if ask "Install the udev rule?" y; then
|
|
|
|
|
sudo install -m 644 "$SRC/packaging/70-socktop-swipe.rules" "$UDEV"
|
|
|
|
|
sudo udevadm control --reload
|
|
|
|
|
sudo udevadm trigger --subsystem-match=input
|
|
|
|
|
say " wrote $UDEV"
|
|
|
|
|
if ! id -nG | tr ' ' '\n' | grep -qx input; then
|
|
|
|
|
warn "the rule uses GROUP=input and you are not in it."
|
|
|
|
|
if ask "Add $(id -un) to the 'input' group as well?" y; then
|
|
|
|
|
sudo usermod -aG input "$(id -un)"
|
|
|
|
|
RELOGIN=yes
|
2026-08-10 00:47:36 -07:00
|
|
|
fi
|
|
|
|
|
fi
|
2026-09-09 13:08:42 -07:00
|
|
|
elif ask "Add $(id -un) to the 'input' group instead?" n; then
|
|
|
|
|
sudo usermod -aG input "$(id -un)"
|
|
|
|
|
RELOGIN=yes
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Config
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
step "Configuration"
|
|
|
|
|
mkdir -p "$CONF_DIR"
|
|
|
|
|
if [ -e "$CONF" ]; then
|
|
|
|
|
say " keeping the existing $CONF"
|
|
|
|
|
else
|
|
|
|
|
sed "s|^ device: .*| device: $DEVICE|" "$SRC/config.example.yaml" >"$CONF"
|
|
|
|
|
say " wrote $CONF"
|
|
|
|
|
say " EDIT IT: the example screens are the author's rack, not yours."
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Optional monitors
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
step "Monitor programs (all optional -- socktop-swipe runs whatever you configure)"
|
|
|
|
|
if ! have socktop && ask "Install socktop (the point of the project)?" y; then
|
|
|
|
|
cargo install socktop
|
|
|
|
|
fi
|
|
|
|
|
if ! have uptime-kuma-status && ask "Install uptime-kuma-status?" n; then
|
|
|
|
|
cargo install uptime-kuma-status
|
|
|
|
|
fi
|
|
|
|
|
if ! have unifly && ask "Build unifly (UniFi TUI) from source?" n; then
|
|
|
|
|
U="$HOME/.local/src/unifly"
|
|
|
|
|
mkdir -p "$(dirname "$U")"
|
|
|
|
|
if [ -d "$U/.git" ]; then git -C "$U" pull --ff-only; else
|
|
|
|
|
git clone https://github.com/jasonwitty/unifly "$U"
|
2026-08-28 09:53:39 -07:00
|
|
|
fi
|
2026-09-09 13:08:42 -07:00
|
|
|
( cd "$U" && cargo build --profile release-small -p unifly )
|
|
|
|
|
say " built $U/target/release-small/unifly"
|
|
|
|
|
say " put that path under 'binaries: unifly:' in $CONF"
|
2026-08-28 09:53:39 -07:00
|
|
|
fi
|
|
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
# Unattended operation
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
step "Wall-display behaviour"
|
|
|
|
|
|
|
|
|
|
if ask "Stop the screen blanking, sleeping and locking?" y; then
|
|
|
|
|
sudo mkdir -p /etc/X11/xorg.conf.d
|
|
|
|
|
sudo tee "$XBLANK" >/dev/null <<-'EOF'
|
|
|
|
|
# Installed by socktop-swipe. This is a wall display: it must never blank.
|
|
|
|
|
Section "ServerFlags"
|
|
|
|
|
Option "BlankTime" "0"
|
|
|
|
|
Option "StandbyTime" "0"
|
|
|
|
|
Option "SuspendTime" "0"
|
|
|
|
|
Option "OffTime" "0"
|
|
|
|
|
EndSection
|
|
|
|
|
EOF
|
|
|
|
|
say " wrote $XBLANK"
|
|
|
|
|
# The Xorg snippet covers every session including the greeter and survives
|
|
|
|
|
# reboots; xset covers a session that re-enables blanking after X starts.
|
|
|
|
|
# Both are needed, and xset MUST run as the session user -- under sudo it
|
|
|
|
|
# targets root's X connection and silently does nothing.
|
|
|
|
|
if [ -n "${DISPLAY:-}" ] && have xset; then
|
|
|
|
|
xset s off s noblank -dpms 2>/dev/null || true
|
|
|
|
|
say " applied to the running session"
|
2026-08-28 12:41:35 -07:00
|
|
|
fi
|
2026-09-09 13:08:42 -07:00
|
|
|
for l in $LOCKER; do
|
|
|
|
|
warn "$l is installed and may still lock the screen. Disable it in your"
|
|
|
|
|
warn "session's autostart."
|
|
|
|
|
done
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if [ "$WM" = i3 ] && [ -e "$HOME/.config/i3/config" ]; then
|
|
|
|
|
if ask "Add the i3 autostart lines?" y; then
|
|
|
|
|
i3conf="$HOME/.config/i3/config"
|
|
|
|
|
if grep -q socktop-swipe "$i3conf"; then
|
|
|
|
|
say " already present; leaving it alone"
|
2026-08-09 01:22:23 -07:00
|
|
|
else
|
2026-09-09 13:08:42 -07:00
|
|
|
bak="$i3conf.bak-$(date +%Y%m%d-%H%M%S)"
|
|
|
|
|
cp "$i3conf" "$bak"
|
|
|
|
|
{
|
|
|
|
|
printf '\n# --- socktop-swipe ---\n'
|
|
|
|
|
printf '# One process: builds the session, opens it in a terminal and reads the panel.\n'
|
|
|
|
|
printf 'exec --no-startup-id %s/socktop-swipe run\n' "$BIN"
|
|
|
|
|
printf '# Never blank (the Xorg snippet covers reboots; this covers this session).\n'
|
|
|
|
|
printf 'exec --no-startup-id xset s off s noblank -dpms\n'
|
|
|
|
|
if have unclutter; then
|
|
|
|
|
printf '# With the panel grabbed, nothing ever moves the pointer, so hide it.\n'
|
|
|
|
|
printf 'exec --no-startup-id unclutter --timeout 1 --ignore-scrolling\n'
|
|
|
|
|
fi
|
|
|
|
|
} >>"$i3conf"
|
|
|
|
|
if i3 -C -c "$i3conf" >/dev/null 2>&1; then
|
|
|
|
|
say " added the autostart (backup: $bak)"
|
|
|
|
|
else
|
|
|
|
|
cp "$bak" "$i3conf"
|
|
|
|
|
warn "i3 rejected the config; restored $bak"
|
|
|
|
|
fi
|
2026-08-09 01:22:23 -07:00
|
|
|
fi
|
|
|
|
|
fi
|
2026-09-09 13:08:42 -07:00
|
|
|
elif [ "$DM" != none ] || [ "$WM" != none ]; then
|
|
|
|
|
say " no i3 config found. For a systemd user session instead:"
|
|
|
|
|
say " cp $SRC/packaging/socktop-swipe.service ~/.config/systemd/user/"
|
|
|
|
|
say " systemctl --user enable --now socktop-swipe"
|
2026-08-09 01:22:23 -07:00
|
|
|
fi
|
|
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
if [ "$DM" = lightdm ]; then
|
|
|
|
|
say ""
|
|
|
|
|
say " Autologin makes the display come back by itself after a power cut."
|
|
|
|
|
say " ANYONE WITH PHYSICAL ACCESS TO THE PANEL GETS THIS USER'S SESSION."
|
|
|
|
|
say " Only do this where the account is nothing but the dashboard."
|
|
|
|
|
if ask "Log $(id -un) straight into $WM at boot?" n; then
|
|
|
|
|
sudo mkdir -p /etc/lightdm/lightdm.conf.d
|
|
|
|
|
sudo tee "$LIGHTDM" >/dev/null <<-EOF
|
|
|
|
|
# Installed by socktop-swipe. Delete this file to restore the login prompt.
|
|
|
|
|
[Seat:*]
|
|
|
|
|
autologin-user=$(id -un)
|
|
|
|
|
autologin-user-timeout=0
|
|
|
|
|
autologin-session=$WM
|
|
|
|
|
EOF
|
|
|
|
|
say " wrote $LIGHTDM (takes effect at next boot)"
|
|
|
|
|
fi
|
|
|
|
|
elif [ "$DM" != none ]; then
|
|
|
|
|
say " Autologin is only automated for lightdm; yours is $DM. Configure it there"
|
|
|
|
|
say " if the display must come back unattended after a power cut."
|
2026-08-10 00:47:36 -07:00
|
|
|
fi
|
2026-09-09 13:08:42 -07:00
|
|
|
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
say ""
|
|
|
|
|
say "=============================================================="
|
|
|
|
|
say "Installed."
|
|
|
|
|
if [ "$RELOGIN" = yes ]; then say "LOG OUT AND BACK IN before use (group membership changed)."; fi
|
2026-08-09 01:22:23 -07:00
|
|
|
cat <<EOF
|
|
|
|
|
|
2026-09-09 13:08:42 -07:00
|
|
|
Next:
|
|
|
|
|
1. Edit $CONF -- the screens are the author's, not yours.
|
|
|
|
|
2. socktop-swipe validate check it, and see the grid map
|
|
|
|
|
3. socktop-swipe doctor swipe, and see what the panel reports
|
|
|
|
|
4. socktop-swipe run build the session and start swiping
|
2026-08-09 01:22:23 -07:00
|
|
|
|
|
|
|
|
EOF
|
2026-09-09 13:08:42 -07:00
|
|
|
say "=============================================================="
|