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:
+399
-198
@@ -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 "=============================================================="
|
||||
|
||||
Reference in New Issue
Block a user