Initial commit: swipe-to-zoom touchscreen navigation for socktop

Tiled socktop dashboard where a right-to-left swipe zooms into each host
full-screen and left-to-right walks back out.

The carousel is tmux pane zoom rather than separate socktop instances, so
there is one process per host: half the processes, no reconnect delay when
swiping back, and constant polling load on the monitored hosts.

Gestures come from lisgd because libinput emits gesture events only for
touchpads, never touchscreens, which rules out libinput-gestures entirely.

Documents the four gotchas found while building this: panels reporting 2-3
contacts for a one-finger swipe, X needing to ignore the panel so the
terminal and socktop stop competing for the same touches, tmux mouse mode
being incompatible with swipes, and lisgd not grabbing the device
exclusively so two instances double-fire.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
jasonwitty
2026-08-09 01:22:23 -07:00
commit 18ddd39184
11 changed files with 735 additions and 0 deletions
+193
View File
@@ -0,0 +1,193 @@
# socktop-swipe
Swipe-to-zoom touchscreen navigation for a wall-mounted
[socktop](https://crates.io/crates/socktop) dashboard.
One tmux window shows every monitored host tiled together. Swiping right-to-left
on the panel zooms into each host full-screen, one at a time; swiping
left-to-right walks back out to the overview.
```
overview -> host 1 -> host 2 -> host 3 -> host 4
(tiled) zoomed zoomed zoomed zoomed
<-------------- swipe left-to-right --------------
```
Built for a 10" touch panel on a server rack driving four Raspberry Pis, on a
low-power x86 box running i3 on X11.
## How it works, and why
**The carousel is tmux pane zoom, not extra socktop instances.** There is exactly
one socktop process per host. Zooming calls `tmux resize-pane -Z`, which makes one
pane fill the window and sends `SIGWINCH` so socktop repaints at the new size.
That matters for three reasons:
- **Half the processes.** Separate full-screen instances would mean N extra
socktop processes and double the polling load on the monitored hosts. On a
1.9 GB display host, that is the difference between comfortable and not.
- **No reconnect delay.** Hidden panes keep running and stay connected, so
swiping back to a host shows current data, not a stale snapshot.
- **Constant load.** The monitored hosts see the same connections regardless of
what is on screen.
**Gestures come from lisgd, below the terminal.** No Linux terminal maps
horizontal swipes to commands, so this cannot be done in terminal config.
Critically, **libinput deliberately emits gesture events only for touchpads,
never for touchscreens** — so `libinput-gestures` and similar tools cannot work
here at all. [lisgd](https://git.sr.ht/~mil/lisgd) reads raw touch events and
synthesises the swipes itself, reading `/dev/input` directly and bypassing X.
## Requirements
- `tmux`, `socktop`, and a working `~/.config/socktop/profiles.json`
- `lisgd` (the installer builds it)
- A C toolchain plus `libinput` and `libX11` headers, to build lisgd
- Membership of the `input` group (the installer adds you; needs a relogin)
## Install
```sh
git clone https://gt.wittyoneoff.com/jason/socktop-swipe
cd socktop-swipe
./install.sh --xignore --i3
```
Then **log out and back in** — the `input` group and the X rule both need a
fresh session.
| Flag | Effect |
| --- | --- |
| *(none)* | Build/install lisgd, install the three scripts and the default config |
| `--xignore` | Also tell X to ignore the touch panel (see below — usually wanted) |
| `--i3` | Also add i3 autostart lines, with a backup and `i3 -C` validation |
Re-running is safe: an existing config file is never overwritten, and the i3
edit is skipped if already present.
### Verify
```sh
tools/find-device.sh # confirm TOUCH_DEV is right
tools/diag.sh # stage 1: device live? stage 2: what does lisgd see?
tools/test-foreground.sh # run the real daemon, watch the display, swipe
```
## Configuration
Everything lives in **`/usr/local/etc/socktop-swipe.env`**. Edit it there, not in
the repo copy. After changing it, restart the daemon and rebuild the session:
```sh
pkill -x lisgd && socktop-gestures &
socktop-rack
```
| Option | Default | What it does |
| --- | --- | --- |
| `SOCKTOP_HOSTS` | four Pi profiles | socktop profile names, **in swipe order**. Any count works; layout and carousel adapt. |
| `SOCKTOP_SESSION` | `socktop4` | tmux session name |
| `SOCKTOP_BIN` | `$HOME/.cargo/bin/socktop` | Full path — i3 does not have `~/.cargo/bin` on `PATH` |
| `TOUCH_DEV` | ILITEK by-id path | Touch device. **Always use a `/dev/input/by-id/` path**; `eventN` numbers change on reboot. |
| `SCREEN_W` / `SCREEN_H` | `1024` / `600` | The **panel's** resolution, not the X screen. See gotcha 2. |
| `SWIPE_THRESHOLD` | `80` | Pixels of travel before a drag counts as a swipe |
| `SWIPE_LENIENCY` | `30` | Degrees off-axis tolerated (max 45) |
| `FINGER_COUNTS` | `1 2 3` | Contact counts accepted. **The setting most likely to need changing** — see gotcha 1. |
| `GESTURE_IN` / `GESTURE_OUT` | `RL` / `LR` | Swap these to reverse swipe direction |
### Adding or removing hosts
Edit `SOCKTOP_HOSTS` and run `socktop-rack`. Nothing else needs touching — the
carousel derives its length from the pane count at runtime.
## Autostart
`./install.sh --i3` appends to `~/.config/i3/config`. For systemd user sessions
instead:
```sh
cp socktop-swipe.service ~/.config/systemd/user/
systemctl --user enable --now socktop-swipe
```
Either way, **run exactly one gesture daemon**. lisgd does not grab the input
device exclusively, so two instances make every swipe fire twice.
## Uninstall
```sh
./uninstall.sh # scripts, config, X rule
./uninstall.sh --keep-config # keep your settings
```
lisgd, the `input` group and your socktop profiles are deliberately left alone;
the script prints how to remove each.
## Troubleshooting
Four gotchas account for nearly every failure. All were found the hard way.
### 1. Gestures are recognised but never fire
Run `tools/diag.sh` and read stage 2:
```
[swipe]: Cfg(f=1/s=3/e=0/d=0) <=> Evt(f=2/s=3/e=1/d=2)
^ configured ^ what happened
```
Matching `s=` with differing `f=` means **your panel reports more contacts than
you configured**. Many multipoint panels report 2 or even 3 contacts for a
physically one-finger swipe. Add them to `FINGER_COUNTS`.
Direction enum: `0=DU`, `1=UD`, `2=LR`, `3=RL`.
### 2. Swipes register, but erratically — resizing panes, zooming text
X is also delivering touch to whatever is on screen, so a single swipe hits
several consumers at once: tmux mouse mode drags pane borders, the terminal
reads 2-contact swipes as pinch-zoom, and socktop enables its own all-motion
mouse reporting (`?1003h`). Meanwhile lisgd fires too.
Fix with `./install.sh --xignore` and relog. lisgd is unaffected because it
reads the device directly. Trade-off: no tap or pinch-zoom on that panel —
terminal keyboard zoom (`Ctrl +` / `Ctrl -`) still works.
Also ensure tmux mouse mode is **off**; `socktop-rack` sets this.
### 3. Every swipe jumps two panes
Two lisgd instances are running. `pgrep -x lisgd` should show exactly one.
### 4. Swipes do nothing at all
In order: is the session running (`tmux ls`)? Is the daemon running
(`pgrep -x lisgd`)? Does `tools/diag.sh` stage 1 read bytes? Are you in the
`input` group (`id -nG | grep input`, needs a relogin)?
Note lisgd's verbose flag is **`-v`**, not `-D`.
### Multi-monitor note
If the display host has a second monitor, X reports the **combined** root window
(e.g. 2304x720). lisgd would scale its maths to that, so `SCREEN_W`/`SCREEN_H`
must describe the touch panel alone. `socktop-gestures` always passes them
explicitly.
## Known limitations
- **~300 ms repaint on zoom-in.** Between tmux making the pane full-screen and
socktop repainting, you briefly see the old small rendering anchored top-left.
This is socktop's redraw latency, not the gesture path; nothing outside
socktop can fix it. Zooming out has no visible artifact, since panes return to
sizes they were already drawn at.
- Deliberately **no wrap-around** at the ends of the carousel — on a wall display
wrapping makes it impossible to tell where you are.
- X11 only. The lisgd build disables its Wayland backend (`WITHOUT_WAYLAND=1`).
## Tested on
LattePanda (Atom x5-Z8350, 1.9 GB RAM, Cherry Trail graphics), 1024x600 ILITEK
DSI touch panel, Debian 11, i3 on X11, Alacritty 0.16.1, lisgd from git,
monitoring four Raspberry Pis.
+66
View File
@@ -0,0 +1,66 @@
# socktop-swipe configuration.
#
# Installed to /usr/local/etc/socktop-swipe.env. Every script reads that file if
# it exists, so edit it there on the display host -- not this copy in the repo.
# After editing, restart the gesture daemon and rebuild the session (see README).
#
# Values use ${VAR:-default} so an environment variable of the same name always
# wins over this file. That keeps the file editable in the obvious way while
# still allowing one-off overrides, e.g. SOCKTOP_SESSION=test socktop-rack
# ---------------------------------------------------------------------------
# What to monitor
# ---------------------------------------------------------------------------
# socktop profile names (from ~/.config/socktop/profiles.json), in swipe order.
# The first is what you land on after one right-to-left swipe from the overview.
# Any count works; the tiled layout and the carousel adapt automatically.
SOCKTOP_HOSTS="${SOCKTOP_HOSTS:-rpi-master rpi-worker-1 rpi-worker-2 rpi-worker-3}"
# tmux session name. Change only if it collides with something else.
SOCKTOP_SESSION="${SOCKTOP_SESSION:-socktop4}"
# Absolute path to the socktop binary. i3 and non-login shells do not have
# ~/.cargo/bin on PATH, so a full path is safer than relying on lookup.
SOCKTOP_BIN="${SOCKTOP_BIN:-$HOME/.cargo/bin/socktop}"
# ---------------------------------------------------------------------------
# Touch panel
# ---------------------------------------------------------------------------
# The touchscreen event device. ALWAYS prefer a /dev/input/by-id/ symlink --
# /dev/input/eventN numbers get reshuffled on reboot or USB re-enumeration.
# Find yours with: tools/find-device.sh
TOUCH_DEV="${TOUCH_DEV:-/dev/input/by-id/usb-ILITEK_ILITEK-TOUCH-event-if00}"
# The touch panel's own resolution -- NOT the X screen size. lisgd otherwise
# asks X, which reports the full root window across all monitors (e.g. 2304x720
# with a second display attached) and skews its edge and distance maths.
SCREEN_W="${SCREEN_W:-1024}"
SCREEN_H="${SCREEN_H:-600}"
# ---------------------------------------------------------------------------
# Gesture tuning
# ---------------------------------------------------------------------------
# Pixels of travel before a drag counts as a swipe. Too low and stray contact
# triggers it; too high and normal swipes are ignored. Measured on the ILITEK
# panel: real swipes land at 150-260px, accidental ones under 70px.
SWIPE_THRESHOLD="${SWIPE_THRESHOLD:-80}"
# Degrees of leniency off the axis, max 45. Real finger swipes came in 1-25
# degrees off true horizontal, so 30 leaves comfortable margin.
SWIPE_LENIENCY="${SWIPE_LENIENCY:-30}"
# Contact counts to accept for one logical swipe.
#
# THIS IS THE SETTING THAT MOST OFTEN NEEDS CHANGING ON NEW HARDWARE. Many
# multipoint panels report 2 or even 3 contacts for what is physically a
# one-finger swipe (palm, or ghost contacts). If gestures are recognised but
# never fire, run tools/diag.sh and compare Cfg(f=N) against Evt(f=N).
FINGER_COUNTS="${FINGER_COUNTS:-1 2 3}"
# Swipe directions. RL = right-to-left = zoom in; LR = left-to-right = zoom out.
# Swap these two values to reverse the direction of travel.
GESTURE_IN="${GESTURE_IN:-RL}"
GESTURE_OUT="${GESTURE_OUT:-LR}"
Executable
+146
View File
@@ -0,0 +1,146 @@
#!/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 --xignore --i3 full display-host setup
#
# Safe to re-run: an existing config file is never overwritten, and the i3 edit
# is skipped if already present.
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
SRC="$HOME/src/lisgd"
here=$(cd "$(dirname "$0")" && pwd)
do_xignore=no
do_i3=no
for a in "$@"; do
case "$a" in
--xignore) do_xignore=yes ;;
--i3) do_i3=yes ;;
*) 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."
fi
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"
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/"
if [ -e "$CONF" ]; then
echo "==> keeping existing $CONF (not overwritten)"
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."
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)"
sudo usermod -aG input "$(id -un)"
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
fi
# --- optional: i3 autostart -------------------------------------------------
if [ "$do_i3" = yes ]; then
i3conf="$HOME/.config/i3/config"
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
exec --no-startup-id \$TERMINAL -e $BIN/socktop-rack
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."
[ "$relogin" = yes ] && echo "LOG OUT and back in before use (group and/or X changes)."
cat <<EOF
Start it by hand with:
$BIN/socktop-gestures & # exactly one instance
$BIN/socktop-rack # builds and attaches the session
Configuration: $CONF
Diagnostics: tools/diag.sh
EOF
echo "=============================================================="
+51
View File
@@ -0,0 +1,51 @@
#!/bin/sh
# Touch gesture daemon for the socktop display. Pass -v to log each detection.
#
# Single source of truth for the lisgd arguments -- referenced by the i3 autostart,
# the systemd unit and tools/test-foreground.sh, so they cannot drift apart.
#
# IMPORTANT: run exactly ONE instance. lisgd does not grab the input device
# exclusively, so two running copies make every swipe fire twice.
set -eu
for c in /usr/local/etc/socktop-swipe.env "$(dirname "$0")/config.env"; do
[ -r "$c" ] && . "$c" && break
done
: "${TOUCH_DEV:?no TOUCH_DEV -- is the config installed?}"
: "${SCREEN_W:=1024}"
: "${SCREEN_H:=600}"
: "${SWIPE_THRESHOLD:=80}"
: "${SWIPE_LENIENCY:=30}"
: "${FINGER_COUNTS:=1 2 3}"
: "${GESTURE_IN:=RL}"
: "${GESTURE_OUT:=LR}"
SWIPE_CMD=${SWIPE_CMD:-$(dirname "$0")/socktop-swipe}
[ -x /usr/local/bin/socktop-swipe ] && SWIPE_CMD=/usr/local/bin/socktop-swipe
verbose=
[ "${1:-}" = "-v" ] && verbose=-v
if [ ! -e "$TOUCH_DEV" ]; then
echo "socktop-gestures: $TOUCH_DEV not present" >&2
exit 1
fi
if [ ! -r "$TOUCH_DEV" ]; then
echo "socktop-gestures: cannot read $TOUCH_DEV -- are you in the 'input' group?" >&2
echo " sudo usermod -aG input $(id -un) then log out and back in" >&2
exit 1
fi
# Bind every configured contact count to the same action; see config.env for why.
set --
for f in $FINGER_COUNTS; do
set -- "$@" -g "$f,$GESTURE_IN,*,*,R,$SWIPE_CMD next"
set -- "$@" -g "$f,$GESTURE_OUT,*,*,R,$SWIPE_CMD prev"
done
exec lisgd $verbose \
-d "$TOUCH_DEV" \
-w "$SCREEN_W" -h "$SCREEN_H" \
-t "$SWIPE_THRESHOLD" -r "$SWIPE_LENIENCY" \
"$@"
Executable
+47
View File
@@ -0,0 +1,47 @@
#!/bin/sh
# Build the socktop display session: one window, N tiled panes, one per host.
# Pane index order is the swipe order.
set -eu
# shellcheck source=config.env
for c in /usr/local/etc/socktop-swipe.env "$(dirname "$0")/config.env"; do
[ -r "$c" ] && . "$c" && break
done
: "${SOCKTOP_HOSTS:?no SOCKTOP_HOSTS -- is the config installed?}"
: "${SOCKTOP_SESSION:=socktop4}"
: "${SOCKTOP_BIN:=socktop}"
WIN="$SOCKTOP_SESSION:rack"
tmux kill-session -t "$SOCKTOP_SESSION" 2>/dev/null || true
first=1
for h in $SOCKTOP_HOSTS; do
if [ "$first" = 1 ]; then
tmux new-session -d -s "$SOCKTOP_SESSION" -n rack "$SOCKTOP_BIN -P $h"
first=0
else
# Split the most recently created pane so creation order == index order.
tmux split-window -t "$WIN" "$SOCKTOP_BIN -P $h"
fi
# Label the pane with the host it is showing.
tmux select-pane -t "$WIN.$(tmux display-message -t "$WIN" -p '#{pane_index}')" -T "$h"
done
tmux select-layout -t "$WIN" tiled
tmux select-pane -t "$WIN.0"
tmux set-option -t "$SOCKTOP_SESSION" pane-border-status top
tmux set-option -t "$SOCKTOP_SESSION" pane-border-format ' #{pane_title} '
tmux set-option -t "$SOCKTOP_SESSION" status off
# Keep dead panes so pane indices stay stable if a socktop exits.
tmux set-option -t "$SOCKTOP_SESSION" remain-on-exit on
# Mouse mode MUST stay off. With it on, every touch swipe is ALSO delivered to
# tmux as a click-drag: dragging across a pane border resizes it and taps
# reselect panes, which fights the gesture daemon. See README, "Why no tapping".
tmux set-option -t "$SOCKTOP_SESSION" mouse off
exec tmux attach -t "$SOCKTOP_SESSION"
Executable
+59
View File
@@ -0,0 +1,59 @@
#!/bin/sh
# socktop-swipe next|prev
#
# Walks a linear "zoom carousel" over the tiled socktop window:
#
# overview <-> pane 0 <-> pane 1 <-> ... <-> pane N-1
# (all hosts) host 1 host 2 last host
#
# "next" moves right along that line and stops at the last pane.
# "prev" moves back and stops at the overview. Deliberately no wrap-around:
# on a wall display, wrapping makes it impossible to tell where you are.
#
# This is tmux pane zoom, NOT extra socktop instances. All panes keep running
# and stay connected while hidden, so swiping back shows current data with no
# reconnect, and the polling load on the monitored hosts is constant.
set -eu
for c in /usr/local/etc/socktop-swipe.env "$(dirname "$0")/config.env"; do
[ -r "$c" ] && . "$c" && break
done
: "${SOCKTOP_SESSION:=socktop4}"
dir=${1:?usage: socktop-swipe next|prev}
# Resolve the session's active window to its window id (@N) rather than assuming
# a window name, so this works against any socktop session however it was built.
WIN=$(tmux display-message -t "$SOCKTOP_SESSION" -p '#{window_id}' 2>/dev/null) || exit 0
[ -n "$WIN" ] || exit 0
state=$(tmux display-message -t "$WIN" -p '#{window_zoomed_flag} #{pane_index} #{window_panes}') || exit 0
zoomed=${state%% *}
rest=${state#* }
idx=${rest%% *}
count=${rest##* }
last=$((count - 1))
zoom_to() {
# Selecting a different pane auto-unzooms, so zoom explicitly afterwards.
tmux select-pane -t "$WIN.$1"
tmux resize-pane -Z -t "$WIN.$1"
}
if [ "$zoomed" = 0 ]; then
case "$dir" in
next) zoom_to 0 ;;
prev) : ;; # already at the overview; nothing further out
esac
else
case "$dir" in
next) [ "$idx" -lt "$last" ] && zoom_to $((idx + 1)) || : ;;
prev)
if [ "$idx" -gt 0 ]; then
zoom_to $((idx - 1))
else
tmux resize-pane -Z -t "$WIN.$idx" # unzoom -> overview
fi
;;
esac
fi
+17
View File
@@ -0,0 +1,17 @@
[Unit]
Description=socktop-swipe touchscreen gesture daemon
Documentation=https://gt.wittyoneoff.com/jason/socktop-swipe
After=graphical-session.target
PartOf=graphical-session.target
[Service]
Type=simple
# lisgd queries X for screen geometry unless -w/-h are given (socktop-gestures
# always passes them), but keep DISPLAY set so it starts cleanly either way.
Environment=DISPLAY=:0
ExecStart=/usr/local/bin/socktop-gestures
Restart=always
RestartSec=2
[Install]
WantedBy=graphical-session.target
Executable
+56
View File
@@ -0,0 +1,56 @@
#!/bin/sh
# Gesture diagnostic. Two stages, each answering exactly one question.
#
# Stage 1: is the panel delivering events to us at all?
# Stage 2: which direction and how many contacts does lisgd see?
#
# Stage 2 is the important one. Each line reads:
# [swipe]: Cfg(f=1/s=3/e=0/d=0) <=> Evt(f=2/s=3/e=1/d=2)
# ^ what you configured ^ what actually happened
# f=fingers, s=direction, e=edge, d=distance. Direction enum:
# 0=DU (down-to-up) 1=UD 2=LR (left-to-right) 3=RL (right-to-left)
#
# If Cfg and Evt agree on s= but differ on f=, your panel reports more contacts
# than you configured -- add them to FINGER_COUNTS in the config.
set -eu
for c in /usr/local/etc/socktop-swipe.env "$(dirname "$0")/../config.env"; do
[ -r "$c" ] && . "$c" && break
done
: "${TOUCH_DEV:?no TOUCH_DEV configured}"
: "${SCREEN_W:=1024}"
: "${SCREEN_H:=600}"
: "${SWIPE_THRESHOLD:=80}"
: "${SWIPE_LENIENCY:=30}"
echo "=============================================================="
echo "STAGE 1 -- is the panel delivering events at all?"
echo "Touch and drag on the TOUCHSCREEN for the next 6 seconds..."
echo "=============================================================="
bytes=$(timeout 6 cat "$TOUCH_DEV" 2>/dev/null | wc -c)
echo
echo " read $bytes bytes from $TOUCH_DEV"
if [ "$bytes" -eq 0 ]; then
cat <<-EOF
-> NOTHING. Stage 2 cannot work. Check, in order:
* are you in the 'input' group? (id -nG | grep input; needs a relogin)
* is TOUCH_DEV the right device? (tools/find-device.sh)
EOF
exit 1
fi
echo " -> device is live."
echo
echo "=============================================================="
echo "STAGE 2 -- what does lisgd actually see?"
echo "All four directions are bound, for 1, 2 and 3 contacts."
echo "Swipe LEFT, RIGHT, UP, DOWN. Ctrl-C when done."
echo "=============================================================="
set --
for f in 1 2 3; do
for g in RL LR DU UD; do
set -- "$@" -g "$f,$g,*,*,R,echo \" >>> FIRED: ${f}-contact $g\""
done
done
exec lisgd -v -d "$TOUCH_DEV" -w "$SCREEN_W" -h "$SCREEN_H" \
-t "$SWIPE_THRESHOLD" -r "$SWIPE_LENIENCY" "$@"
+36
View File
@@ -0,0 +1,36 @@
#!/bin/sh
# Identify the touchscreen and print the stable by-id path for config.env.
set -eu
echo "=== input devices reporting a touch-ish name ==="
found=
for ev in /dev/input/event*; do
name=$(cat "/sys/class/input/$(basename "$ev")/device/name" 2>/dev/null || true)
case "$name" in
*[Tt]ouch* | *TOUCH*)
found=yes
echo
echo " device: $ev"
echo " name: $name"
for l in /dev/input/by-id/* /dev/input/by-path/*; do
[ -e "$l" ] || continue
if [ "$(readlink -f "$l")" = "$(readlink -f "$ev")" ]; then
echo " stable: $l"
fi
done
;;
esac
done
if [ -z "$found" ]; then
echo " (none matched by name)"
echo
echo "Fall back to listing everything:"
for ev in /dev/input/event*; do
printf ' %-22s %s\n' "$ev" "$(cat "/sys/class/input/$(basename "$ev")/device/name" 2>/dev/null)"
done
fi
echo
echo "Put the 'stable:' path (prefer /dev/input/by-id/) into TOUCH_DEV."
echo "Event numbers change across reboots; by-id symlinks do not."
+20
View File
@@ -0,0 +1,20 @@
#!/bin/sh
# Run the real gesture daemon in the foreground, with logging, so you can watch
# the display while you swipe. Ctrl-C to stop.
#
# Expect: swipe right-to-left -> zooms in one host at a time
# swipe left-to-right -> walks back out to the overview
# "Execute ..." in the output means a gesture matched and fired.
#
# Make sure no other instance is running first -- two copies fire every swipe
# twice, which looks like the carousel skipping.
set -eu
if pgrep -x lisgd >/dev/null 2>&1; then
echo "!! lisgd is already running (pid: $(pgrep -x lisgd | tr '\n' ' '))." >&2
echo "!! Two instances make every swipe fire twice. Stop it first:" >&2
echo " pkill -x lisgd" >&2
exit 1
fi
exec "$(dirname "$0")/../socktop-gestures" -v
Executable
+44
View File
@@ -0,0 +1,44 @@
#!/bin/sh
# Remove socktop-swipe. Leaves lisgd, the 'input' group membership and your
# socktop profiles alone -- those are useful independently and removing them
# could break other things.
#
# ./uninstall.sh remove scripts, config and the X ignore rule
# ./uninstall.sh --keep-config leave the config file in place
set -eu
PREFIX=${PREFIX:-/usr/local}
BIN="$PREFIX/bin"
CONF="$PREFIX/etc/socktop-swipe.env"
XCONF=/etc/X11/xorg.conf.d/99-ignore-touch-socktop-swipe.conf
keep_config=no
[ "${1:-}" = "--keep-config" ] && keep_config=yes
# Stop anything running. -x matches the exact process name; -f would also match
# this script's own command line and kill the shell running it.
pkill -x lisgd 2>/dev/null || true
for f in socktop-rack socktop-swipe socktop-gestures; do
if [ -e "$BIN/$f" ]; then
sudo rm -f "$BIN/$f"
echo "removed $BIN/$f"
fi
done
if [ "$keep_config" = no ] && [ -e "$CONF" ]; then
sudo rm -f "$CONF"
echo "removed $CONF"
fi
if [ -e "$XCONF" ]; then
sudo rm -f "$XCONF"
echo "removed $XCONF (touch returns to X after the next X restart)"
fi
echo
echo "Left in place on purpose:"
echo " * lisgd -- remove with: sudo make -C ~/src/lisgd uninstall"
echo " * 'input' group -- remove with: sudo gpasswd -d $(id -un) input"
echo " * i3 autostart -- delete the 'socktop-swipe' block in ~/.config/i3/config"
echo " * socktop profiles -- ~/.config/socktop/profiles.json"