git.lucas.co / cce-remote
remote trackpad and keyboard server
git clone https://git.lucas.co/cce-remote.git

README.md (2.8K)

 1 # cce-remote
 2 
 3 Use a phone as a trackpad + keyboard for the cce desktop.
 4 
 5 A single small server: it serves an embedded web page (touch trackpad +
 6 keyboard UI) over HTTP on the LAN and bridges the page's WebSocket input
 7 events into the compositor's control socket — the same channel `ccectl`
 8 uses, so injection rides the real compositor input path.
 9 
10 ## Run
11 
12 ```sh
13 make install        # installs cce-remote to ~/.local/bin
14 cce-remote          # serves on 0.0.0.0:17017 (or: cce-remote <port>)
15 ```
16 
17 Open `http://<this-machine's-LAN-IP>:17017` on the phone. Add it to the
18 Home Screen for a fullscreen app feel.
19 
20 ## Controls
21 
22 - one-finger drag — move the pointer
23 - tap — left click; two-finger tap — right click
24 - two-finger drag — scroll (natural direction)
25 - press-and-hold, then drag — held drag (release on lift)
26 - `left` / `right` buttons — explicit clicks
27 - top bar — esc/tab/arrows; ctrl/alt/sup are sticky toggles (tap to hold,
28   tap again to release — chords work: ctrl on, tap `c`, ctrl off)
29 - ⌨ — summon the phone keyboard (typing goes through a US-layout
30   char→evdev map; iOS `beforeinput` is used, so autocorrect noise is
31   filtered)
32 - ☰ — window switcher: tap a window to focus it
33 - 🖥 — window view mode: a live stream of the focused window, delivered
34   ack-clocked over a WebSocket — at most one frame in flight, so a slow
35   link drops frame rate instead of falling behind — with resolution and
36   quality adapting to the measured link (up to 1400px edge when it's fast).
37   Frames come from the compositor's damage-driven window stream, falling
38   back to wlr-screencopy, then grim; `/stream` remains as a curl-friendly
39   MJPEG debug endpoint.
40   Input is identical to the trackpad — tap = click, two-finger tap = right
41   click, press-and-hold = held drag, one-finger drag = pointer motion (a
42   cyan ring marks the cursor — compositor frames carry none); taps never
43   warp the pointer. Two fingers pinch-zoom / pan the view itself. Toggle
44   again for the trackpad. Both `/stream` and the one-shot
45   `/shot` endpoint are PIN-gated; nothing accumulates on disk.
46 
47 ## Security
48 
49 Pairing PIN: a persistent 6-digit PIN is generated on first run (printed at
50 startup, stored 0600 in `~/.config/cce/cce-remote.pin`). The page asks for
51 it once per device and remembers it (localStorage); the server closes any
52 WebSocket whose first frame isn't `auth <pin>`, so no input can be injected
53 without pairing. Delete the PIN file to rotate it.
54 
55 Wrong PINs are rate-limited per source address — five in a row, then one more
56 every 30 seconds (HTTP replies `429 Too Many Requests`) — so the 6-digit space
57 can't be walked. Correct PINs cost nothing and a success clears the peer's
58 record, so a phone reconnecting its stream is never throttled.
59 
60 Traffic is plain HTTP on the LAN — for hostile networks, tunnel it.