v2 release prep: installer, README, packaging, notes; retire the v1 scripts

Installer rewritten around a preflight: distro, package manager, display
manager, window manager, terminal, tmux, cargo, git, screen locker, touch
device, device permissions and free disk are all checked BEFORE anything is
installed, and the total cost is printed once for a single confirmation.
Prompts read /dev/tty so they still work when the script is piped from curl,
and fall back to defaults with a notice when there is no terminal at all.

Several "[ test ] && action" statements were set -e landmines: under set -e an
AND-OR list that ends up false aborts the script, so a box with no lightdm, no
i3 or nothing to install would have exited silently partway through detection
-- which is exactly the fresh-Debian case the installer exists for. Rewritten
as if-statements and verified against a stripped PATH with no tmux, cargo, git
or package manager present. Also fixed cargo detection reporting blank instead
of NOT INSTALLED: the status of `cargo --version | cut` is cut's, and cut
succeeds on empty input, so the fallback never fired.

Device access now defaults to a udev rule matching touchscreens only, rather
than the input group, which grants access to every input device including the
keyboard and needs a full logout.

README rewritten for someone who has not seen the project: what the photo
shows, the hardware, install, then a config built up step by step, each step
with the YAML and the resulting map. Every example is verified verbatim
against the binary, and every relative link resolves. The mechanism and the
reasoning move to notes/: DESIGN.md, HARDWARE-NOTES.md, V1-BASH.md, TODO.md.

cad/README.md was a verbatim copy of the one inside
geeekpi_rack_adapter_release_v1/, so every path in it -- including the
screenshot -- was broken from where it sits. Corrected to its own level, and
it now states once that the 9-inch screen, the 10-inch mini-rack mount and the
19-inch rack are three different measurements.

The v1 shell implementation is removed; it stays recoverable at tag v1.2 and
notes/V1-BASH.md carries the setting-by-setting migration table.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
jasonwitty
2026-09-09 13:08:42 -07:00
parent 9f082b52b7
commit ce6acec299
29 changed files with 1388 additions and 1089 deletions
+399 -198
View File
@@ -1,238 +1,439 @@
#!/bin/sh
# socktop-swipe installer.
#
# ./install.sh scripts + config + lisgd (build if missing)
# ./install.sh --xignore ...and tell X to ignore the touch panel
# ./install.sh --i3 ...and add i3 autostart lines
# ./install.sh --noblank ...and stop the screen blanking
# ./install.sh --autologin ...and make lightdm log this user straight into i3
# ./install.sh --xignore --i3 --noblank --autologin full wall-display setup
# curl -fsSL https://gt.wittyoneoff.com/jason/socktop-swipe/raw/branch/main/install.sh | sh
#
# Safe to re-run: an existing config file is never overwritten, and the i3 edit
# is skipped if already present.
# 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
set -eu
PREFIX=${PREFIX:-/usr/local}
BIN="$PREFIX/bin"
ETC="$PREFIX/etc"
CONF="$ETC/socktop-swipe.env"
XCONF=/etc/X11/xorg.conf.d/99-ignore-touch-socktop-swipe.conf
BCONF=/etc/X11/xorg.conf.d/10-no-blanking-socktop-swipe.conf
LCONF=/etc/lightdm/lightdm.conf.d/50-autologin-socktop-swipe.conf
SRC="$HOME/src/lisgd"
REPO=https://gt.wittyoneoff.com/jason/socktop-swipe
PREFIX=/usr/local
ASSUME_YES=no
SRC=""
here=$(cd "$(dirname "$0")" && pwd)
do_xignore=no
do_i3=no
do_noblank=no
do_autologin=no
for a in "$@"; do
case "$a" in
--xignore) do_xignore=yes ;;
--i3) do_i3=yes ;;
--noblank) do_noblank=yes ;;
--autologin) do_autologin=yes ;;
--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 ;;
*) echo "unknown option: $a" >&2; exit 2 ;;
esac
done
# --- lisgd ------------------------------------------------------------------
# libinput deliberately emits gesture events only for touchpads, never for
# touchscreens, so libinput-gestures and friends cannot work here. lisgd reads
# raw touch events and synthesises the swipes itself.
if command -v lisgd >/dev/null 2>&1; then
echo "==> lisgd already installed: $(command -v lisgd)"
else
echo "==> building lisgd"
if command -v apt-get >/dev/null 2>&1; then
sudo apt-get update
sudo apt-get install -y build-essential pkg-config git libinput-dev libx11-dev
else
echo "!! Non-Debian system: ensure a C toolchain, libinput and libX11 headers"
echo "!! are present, then re-run."
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
fi
[ "$_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
fi
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
fi
WM=none
if have i3; then WM=i3; fi
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)"
else
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))
fi
# The build itself: a debug-free release build of this crate and its deps.
COST_MB=$((COST_MB + 600))
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
say " build socktop-swipe from source (~600 MB of build artifacts)"
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"
else
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 https://git.sr.ht/~mil/lisgd "$SRC"
if [ -d "$SRC/.git" ]; then
git -C "$SRC" pull --ff-only
else
git clone "$REPO" "$SRC"
fi
# WITHOUT_WAYLAND: lisgd builds both backends by default and would otherwise
# need libwayland-dev for code that never runs on an X11-only host.
make -C "$SRC" WITHOUT_WAYLAND=1
sudo make -C "$SRC" install WITHOUT_WAYLAND=1 PREFIX="$PREFIX"
fi
# --- scripts and config -----------------------------------------------------
echo "==> installing scripts to $BIN"
sudo install -d "$BIN" "$ETC"
sudo install -m 755 "$here/socktop-rack" "$here/socktop-swipe" "$here/socktop-gestures" "$BIN/"
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"
if [ -e "$CONF" ]; then
echo "==> keeping existing $CONF (not overwritten)"
# --------------------------------------------------------------------------
# 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
fi
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
sudo install -m 644 "$here/config.env" "$CONF"
echo "==> installed default config to $CONF"
echo " EDIT IT before first run if your hardware differs."
DEVICE=$(askval "Use which device?" "$DEVICE")
fi
# --- input group ------------------------------------------------------------
if id -nG | tr ' ' '\n' | grep -qx input; then
echo "==> already in the 'input' group"
relogin=no
else
echo "==> adding $(id -un) to the 'input' group (lisgd reads /dev/input directly)"
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
fi
fi
elif ask "Add $(id -un) to the 'input' group instead?" n; then
sudo usermod -aG input "$(id -un)"
relogin=yes
RELOGIN=yes
fi
# --- optional: make X ignore the panel --------------------------------------
if [ "$do_xignore" = yes ]; then
# shellcheck disable=SC1090
. "$CONF"
product=${XIGNORE_MATCH:-ILITEK}
echo "==> telling X to ignore touch devices matching '$product'"
sudo mkdir -p /etc/X11/xorg.conf.d
sudo tee "$XCONF" >/dev/null <<EOF
# Installed by socktop-swipe.
# The panel is driven by lisgd via /dev/input, NOT through X. Letting X also
# deliver touch makes the terminal, tmux and socktop react to the same swipes
# the gesture daemon is interpreting. MatchProduct is narrow on purpose so it
# cannot match keyboards or other HID devices.
Section "InputClass"
Identifier "ignore touchscreen (socktop-swipe)"
MatchProduct "$product"
MatchIsTouchscreen "on"
Option "Ignore" "on"
EndSection
EOF
echo " wrote $XCONF (takes effect after X restarts)"
relogin=yes
# --------------------------------------------------------------------------
# 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: stop the screen blanking -------------------------------------
if [ "$do_noblank" = yes ]; then
echo "==> disabling screen blanking and DPMS"
# Two layers on purpose:
# 1. An Xorg ServerFlags snippet, so it applies to every X session including
# the display manager greeter, and survives reboots.
# 2. An xset call at i3 startup, because a session or DM can re-enable the
# screensaver after X starts.
# Note `xset` alone is NOT enough, and must run as the session user -- running
# it under sudo targets root's X connection and silently does nothing.
sudo mkdir -p /etc/X11/xorg.conf.d
sudo tee "$BCONF" >/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
echo " wrote $BCONF"
# --------------------------------------------------------------------------
# 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"
fi
( 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"
fi
# Apply immediately too, if a session is available.
if [ -n "${DISPLAY:-}" ]; then
# --------------------------------------------------------------------------
# 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
echo " applied to the running session"
say " applied to the running session"
fi
i3conf="$HOME/.config/i3/config"
if [ -e "$i3conf" ] && ! grep -q "xset s off" "$i3conf"; then
bak="$i3conf.bak-$(date +%Y%m%d-%H%M%S)"
cp "$i3conf" "$bak"
printf '\n# Wall display: never blank (socktop-swipe --noblank)\nexec --no-startup-id xset s off s noblank -dpms\n' >>"$i3conf"
if i3 -C -c "$i3conf" >/dev/null 2>&1; then
echo " added xset to i3 autostart (backup: $bak)"
else
cp "$bak" "$i3conf"
echo "!! i3 rejected the config; restored $bak" >&2
fi
fi
relogin=yes
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
# --- optional: lightdm autologin --------------------------------------------
if [ "$do_autologin" = yes ]; then
# A wall display must come back by itself after a power cut. Without this a
# reboot leaves the panel at the greeter with nothing autostarted.
# SECURITY: anyone with physical access to the screen gets this user's
# session. Only use it on a display whose user account is nothing but the
# dashboard. Debian's lightdm-autologin PAM stack needs no extra group.
if [ ! -d /etc/lightdm ]; then
echo "!! /etc/lightdm not found; skipping autologin (not lightdm?)" >&2
else
session=i3
[ -e /usr/share/xsessions/$session.desktop ] ||
echo "!! /usr/share/xsessions/$session.desktop missing; check autologin-session in $LCONF" >&2
echo "==> enabling lightdm autologin for $(id -un) into '$session'"
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"
else
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
fi
fi
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"
fi
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 "$LCONF" >/dev/null <<EOF
# Installed by socktop-swipe (--autologin). Wall display: come back unattended
# after a reboot. Remove this file to restore the login prompt.
[Seat:*]
autologin-user=$(id -un)
autologin-user-timeout=0
autologin-session=$session
EOF
echo " wrote $LCONF (takes effect at next boot)"
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."
fi
# --- optional: i3 autostart -------------------------------------------------
if [ "$do_i3" = yes ]; then
i3conf="$HOME/.config/i3/config"
if ! command -v unclutter >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1; then
echo "==> installing unclutter-xfixes (hides the idle pointer on the wall display)"
sudo apt-get install -y unclutter-xfixes || echo "!! unclutter-xfixes not installed; the pointer will stay visible" >&2
fi
if [ ! -e "$i3conf" ]; then
echo "!! $i3conf not found; skipping i3 autostart" >&2
elif grep -q "socktop-gestures" "$i3conf"; then
echo "==> i3 autostart already present; leaving it alone"
else
bak="$i3conf.bak-$(date +%Y%m%d-%H%M%S)"
cp "$i3conf" "$bak"
cat >>"$i3conf" <<EOF
# --- socktop-swipe --------------------------------------------------------
# Exactly ONE gesture daemon: lisgd does not grab the device exclusively, so a
# second instance makes every swipe fire twice.
exec --no-startup-id $BIN/socktop-gestures
# Start the dashboard on the primary output and fullscreen (which also hides
# the i3 bar), so no keyboard is needed after a reboot and a second monitor
# cannot capture it. --class gives the window a distinct instance name for the
# rule; alacritty syntax -- adapt for other terminals.
for_window [instance="^socktop-rack\$"] move window to output primary, fullscreen enable
exec --no-startup-id \$TERMINAL --class socktop-rack -e $BIN/socktop-rack
# Hide the idle pointer: with X ignoring the touch panel nothing ever moves it,
# so it would sit at screen centre forever. (apt install unclutter-xfixes)
exec --no-startup-id unclutter --timeout 1 --ignore-scrolling
EOF
if i3 -C -c "$i3conf" >/dev/null 2>&1; then
echo "==> added i3 autostart (backup: $bak)"
echo " NOTE: set \$TERMINAL in your i3 config, or edit those lines"
echo " to your terminal's full path."
else
cp "$bak" "$i3conf"
echo "!! i3 rejected the config; restored $bak" >&2
i3 -C -c "$i3conf" || true
fi
fi
fi
echo
echo "=============================================================="
echo "Installed."
if [ "$relogin" = yes ]; then
echo "LOG OUT and back in before use (group and/or X changes)."
fi
# --------------------------------------------------------------------------
say ""
say "=============================================================="
say "Installed."
if [ "$RELOGIN" = yes ]; then say "LOG OUT AND BACK IN before use (group membership changed)."; fi
cat <<EOF
Start it by hand with:
$BIN/socktop-gestures & # exactly one instance
$BIN/socktop-rack # builds and attaches the session
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
Configuration: $CONF
Diagnostics: tools/diag.sh
EOF
echo "=============================================================="
say "=============================================================="