Sync omarchy-air's handoff work: pointer patch, firewall, case fix
Everything from the air side of lan-mouse that was living only on that machine, plus corrections to what this repo already said. New: handoff/patch/ is a two-line source patch making the daemon forward the ACCELERATED pointer deltas. Upstream 0.11.0 forwards dx_unaccel and discards the accelerated pair in the same event, and the wlr receiver applies no curve either, so remote motion arrives with the sender's acceleration stripped and nothing replacing it -- and sensitivity / accel_profile are inert on both ends, so no config can fix it. The patch also adds LAN_MOUSE_POINTER_SCALE for the residual logical-ppi gap (0.7 for air's 140.1ppi against the LG's ~95.8). install.sh builds it per-machine; the unit now runs the result. This laptop is still unpatched, so its forwarded motion is still wrong until the handoff step runs here. New: install.sh --handoff opens 4242/udp for the peer in ufw. ufw is default-deny inbound and a dropped inbound packet presents IDENTICALLY to a bad certificate; this cost a day. Nothing in the repo covered it. Fixed: cmd_restart bypassed the systemd unit with pkill + uwsm-app, which races Restart=on-failure and can leave two daemons on 4242. It now prefers the unit, matching what cmd_log already assumed, and keeps the hand-start path only for when no unit exists. Documented, and this was the actual root cause of a day of dead crossings: fingerprints are CASE-SENSITIVE. lan-mouse generates them lowercase and compares with a plain map lookup, while openssl prints uppercase and cli authorize-key stores what it is handed. An uppercase digest is the right digest, valid TOML, non-empty, passes every guard, and never matches -- the handshake dies bad_certificate. Also documented: authorization is receiver-side only (connect.rs sets insecure_skip_verify), so each direction depends solely on the receiver's list and a sender cannot tell whether it is talking to the real peer. Corrected: README claimed the unknown-device* accel rule was needed because the receiver double-accelerates already-accelerated deltas. That is backwards and the rule is a measured no-op -- the device matches, but sensitivity and accel_profile are libinput settings and a wlr-virtual-pointer is not a libinput device. Measured on both machines: 398x198px travel at sensitivity 0 and identical at -0.9, exactly 1:1. Lines kept (harmless, and the naming note is worth having) with the real mechanism written down. ~/.config/lan-mouse/ stays out of the repo as before; handoff/config/ holds example configs carrying the backend, edge and lowercase rules instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LrgrMhPG8CTo9XZF326rjZ
This commit is contained in:
@@ -25,6 +25,7 @@ into the repo so this stays the source of truth.
|
||||
| `plugins.txt` | The 10 Omarchy shell plugins, each pinned to a commit. |
|
||||
| `plugin-patches/` | Local plugin work that exists on no remote (see below). |
|
||||
| `bin/` | `omarchy-handoff` and `fix-stuck-displays`. |
|
||||
| `handoff/` | The lan-mouse source patch that fixes pointer feel, plus example `config.toml`s. Not a `~/.config` mirror. |
|
||||
| `systemd/user/` | `lan-mouse.service`, `voxtype.service`. |
|
||||
| `system/` | `/etc` drop-ins: the ARP sysctl and `hid_apple` fnmode. |
|
||||
| `packages.txt` | Packages beyond the Omarchy baseline, each with a reason. |
|
||||
@@ -62,6 +63,33 @@ reversed form fails silently, and the log variable is `LAN_MOUSE_LOG_LEVEL`, not
|
||||
`o.launch_on_start` sends both streams to `/dev/null`, hiding every pairing
|
||||
failure.
|
||||
|
||||
Three further facts were only established after the above was first written, and
|
||||
they are what actually made it work:
|
||||
|
||||
- **Fingerprints are case-sensitive.** lan-mouse generates them lowercase and
|
||||
compares with a plain map lookup — no normalisation — while `openssl` prints
|
||||
uppercase and `cli authorize-key` stores whatever it is handed. An uppercase
|
||||
digest is the *correct* digest, valid TOML, non-empty, passes every guard, and
|
||||
never matches: the DTLS handshake dies `bad_certificate`, indistinguishable
|
||||
from a wrong key or a dropped packet. This was the root cause of a full day of
|
||||
dead crossings. `omarchy-handoff fixcase` repairs it; `doctor` now fails on it.
|
||||
- **Authorization is receiver-side only, not mutual.** `connect.rs` sets
|
||||
`insecure_skip_verify`, so the *connecting* side never checks the peer's
|
||||
certificate — only the listener consults `authorized_fingerprints`. Each
|
||||
direction therefore depends solely on the receiver's list, two-way control
|
||||
needs both lists, and a sender cannot tell whether it is talking to the real
|
||||
peer. Input goes to whatever answers on that IP:port.
|
||||
- **`ufw` is default-deny inbound**, and a dropped inbound 4242 presents
|
||||
*identically* to a bad certificate. `install.sh --handoff` opens it for the
|
||||
peer's addresses. Check it first: `journalctl -k -g 'UFW BLOCK'`.
|
||||
|
||||
`handoff/patch/` carries a two-line source patch so the daemon forwards the
|
||||
accelerated deltas, which is the only way to make the sender's `sensitivity` and
|
||||
`accel_profile` affect remote pointer feel at all; it also adds
|
||||
`LAN_MOUSE_POINTER_SCALE` for the residual difference in logical pixel density
|
||||
between the two screens. `install.sh` builds it per-machine — the two laptops are
|
||||
different architectures — and `systemd/user/lan-mouse.service` runs the result.
|
||||
|
||||
`system/sysctl.d/99-omarchy-handoff-arp.conf` goes with it: Wi-Fi and the dock's
|
||||
ethernet both sit on `192.168.1.0/24`, and with the default ARP settings the
|
||||
subnet's mapping collapses onto whichever NIC replied last.
|
||||
@@ -76,13 +104,23 @@ stock ChatGPT webapp to Claude, and adds four Herdr HUD bindings plus Handoff.
|
||||
|
||||
**Input** (`config/hypr/input.lua`) enables the three-finger horizontal
|
||||
workspace gesture that ships commented out, and flattens pointer acceleration for
|
||||
`unknown-device*`. That second rule belongs to Handoff: lan-mouse forwards
|
||||
relative deltas the *sending* compositor has already accelerated, and since
|
||||
Omarchy leaves `accel_profile` adaptive the receiver amplifies them a second time,
|
||||
so a forwarded pointer arrives hypersensitive while the local trackpad feels
|
||||
normal. `wlr-virtual-pointer` gives Hyprland no device name — virtual keyboards
|
||||
get named, pointers don't — hence matching on `unknown-device`; no real pointer on
|
||||
this machine uses that name, so the rule cannot touch the trackpad.
|
||||
`unknown-device*`.
|
||||
|
||||
That second rule is **a no-op, and the reasoning originally given for it was
|
||||
wrong.** It was added believing lan-mouse forwards deltas the sending compositor
|
||||
had already accelerated, which the receiver then amplified a second time. Upstream
|
||||
does the opposite: it forwards the *unaccelerated* deltas and discards the
|
||||
accelerated pair in the same event (`handoff/patch/REBUILD.md`). And the rule
|
||||
cannot act either way — `hl.device({name="unknown-device"})` does match the
|
||||
virtual pointer (provable by toggling `scroll_factor`), but `sensitivity` and
|
||||
`accel_profile` are libinput pointer-acceleration settings and a
|
||||
`wlr-virtual-pointer` is not a libinput device, so they have nothing to act on.
|
||||
Measured 2026-10-10 on both machines with `lan-mouse test-emulation` + `hyprctl
|
||||
cursorpos`: travel was 398x198px at `sensitivity = 0` and identical at `-0.9`,
|
||||
exactly 1:1 with the raw deltas. The lines are kept because they are harmless and
|
||||
the `unknown-device` naming note is worth preserving; the real fix is
|
||||
`handoff/patch/`. Do not add sensitivity or accel_profile rules here expecting
|
||||
them to change remote pointer feel.
|
||||
|
||||
**Terminals** are all dropped to a smaller font (9 -> 8) except ghostty, which
|
||||
went the other way to 12. `shell.toml` sets the bar font base size to 10.
|
||||
@@ -109,8 +147,13 @@ back into the repo.
|
||||
|
||||
- **Secrets.** `~/.config/lan-mouse/` holds a private key and per-machine
|
||||
fingerprints; `~/.config/novnc/auth.env`, SSH keys and the git credential
|
||||
helpers are likewise machine-local. Pair a new machine with
|
||||
`omarchy-handoff peer <host> <ip>` and `omarchy-handoff doctor`.
|
||||
helpers are likewise machine-local. Start from
|
||||
`handoff/config/config.toml.example-{air,laptop}` (which carry the
|
||||
`capture_backend`, edge and lowercase-fingerprint rules), then pair with
|
||||
`omarchy-handoff pair <peer> <lowercase-sha256>` and `omarchy-handoff doctor`.
|
||||
A fresh install regenerates the certificate, so this machine's fingerprint
|
||||
changes and the *peer* has to re-pair. Back up `lan-mouse.pem` beforehand if
|
||||
you would rather keep it stable — somewhere private, not here.
|
||||
- **Shell, git and dev tooling.** That is already its own repo, `dotfiles`
|
||||
(`git.nic-oconnor.com/public/dotfiles`), which handles zsh, mise, 1Password and
|
||||
the `~/.local/bin` tool shims. The only overlap avoided here is
|
||||
|
||||
Reference in New Issue
Block a user