The controller bridge reads the poses with setTimeout instead of a fixed
11 ms interval: the next read after (distance - 10 cm) / 2.5 m/s, 11-250 ms,
the distance being the nearest tip's to the keyboard's rect plus a margin,
so a hand up to 2.5 m/s is read within 10 cm before it reaches the surface
(the tracker's crossing and 8 cm jump guard see 11 ms steps as before).
Full rate during a demand or with a pulled trigger. Without touch typing
(controllers.continuous, set by vr-keyboard-touch) no reads while the
keyboard is shown until a swipe demands them; a demand starting reads at
once. Bridge VERSION 6. Tests with a fake clock: bridge.test.mjs.
keyboard.vr.touchTyping (off by default): a key is pressed when a
controller's tip, where SteamVR's laser starts (/pose/tip: the device pose
times the render model's "tip" component), passes through it from the
front; released when pulled back 1 cm, re-armed 5 mm in front. Both hands,
also at once. Keys go through the keyboard's own HandleTouchStart /
HandleTouchEnd, like a laser press (Backspace repeats while held). Options
depth (cm) and haptics.
The geometry lives in a reusable controller bridge (vr-keyboard-controllers,
internal option): a systemui patch reads the keyboard's pose with SteamVR's
SGQueryService (an empty transform of ours in the keyboard's mount) and both
controllers' poses, and streams per hand the tip, the laser's hit on the
keyboard and the trigger (~90 Hz while relevant) through the
vr-keyboard-controllers-relay service to __sfuiControllers in Steam's
SharedJSContext. Tests: flake checks vr-keyboard-controllers and
vr-keyboard-touch.