18ddd39184
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>
194 lines
7.4 KiB
Markdown
194 lines
7.4 KiB
Markdown
# 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.
|