The documented restart was `pkill -x lisgd && socktop-gestures &`. pkill exits non-zero when it matches nothing, so `&&` short-circuits and the daemon silently does not start when none was running -- you swipe, get nothing, and reasonably blame the config change you just made. socktop-gestures exec'd lisgd with no guard, so nothing downstream caught it. Rather than only fixing the one-liner, move the invariant into the tool: it now exits non-zero if a daemon is already running, and --replace stops the old one first (waiting for it to actually exit). This is the failure the README itself flags as gotcha 3, so a false success there is expensive. Verified against a live daemon: refusal, --help, bad-option exit codes, and a clean pid handover under --replace with the carousel still working. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8.0 KiB
socktop-swipe
Swipe-to-zoom touchscreen navigation for a wall-mounted 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 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.jsonlisgd(the installer builds it)- A C toolchain plus
libinputandlibX11headers, to build lisgd - Membership of the
inputgroup (the installer adds you; needs a relogin)
Install
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
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:
socktop-gestures --replace & # restarts the daemon, running or not
socktop-rack
Use --replace rather than pkill -x lisgd && socktop-gestures: pkill exits
non-zero when it matches nothing, so that one-liner silently starts nothing
if no daemon was running — you would swipe, get no response, and reasonably
blame the config change.
| 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:
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.
socktop-gestures enforces this: it exits non-zero if one is already running,
unless given --replace.
Uninstall
./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.
socktop-gestures refuses to start if a daemon is already running, so this
should not happen via the normal path; --replace restarts cleanly. It can
still occur if lisgd was launched by hand.
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.