Gaze first: plan, and tools for the headset tests

docs/gaze-first.md is the plan agreed on 2026-09-30: with gaze on and no
game, the gaze drives the 3D pointer everywhere, either trigger clicks
where you look (tap, precision by hand movement, hold to drag), and the
controllers keep everything but their lasers.

For its four tests:
- The driver takes "role treadmill", and its compositor bindings repeat
  the right hand's under /user/treadmill. They're additive, so nothing
  changes while the device is a hand. POINTER_ROLE accepts treadmill.
- pointer/probe/lasertest follows who has the dashboard laser and the
  controllers' roles, and with --snapback takes the laser back.
- input/vrws.py reads vrserver's web socket with the standard library
  (the host's Python has no websockets module) and prints component
  changes and update rates. Checked: it connects, and lists the
  controllers' bumper, thumbstick axes, and Steam button, and the
  headset's /proximity, which flickers off for 0.3-0.5 s while worn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
DeeJanuzandClaude Opus 5.5 committed 2026-09-30 17:00:09 -06:00
1 parent d5c2ec65d7
commit bd06207db9
7 files changed
+575 -10

No files matched your search

+9 -6
View File
@@ -17,11 +17,12 @@
// btn <name> <0|1> name: trigger, b, x, system, joystick, a (a = claim the laser, no click)
// scroll <x> <y> joystick deflection -1..1
// show | hide connect (take the hand role) or disconnect (give it back)
// role right|left|stylus which role to hint while connected, from now on (the helper
// sends POINTER_ROLE). A Frame controller in your hand takes
// its hand's role back (it counts as used while held), so a
// role right|left|stylus|treadmill which role to hint while connected, from now on (the
// helper sends POINTER_ROLE). A Frame controller in your hand
// takes its hand's role back (it counts as used while held), so a
// controller used beside the pointer needs the pointer on the
// other hand, or on no hand at all
// other hand, or on no hand at all. Treadmill is no hand: its
// bindings are under /user/treadmill (docs/gaze-first.md, test 1)
//
// The device starts disconnected, so it never holds a hand role at boot (holding
// the right hand while SteamVR started left the Steam UI stuck loading). It
@@ -30,7 +31,8 @@
// SteamVR keeps a hand role reserved for a disconnected device that still hints
// that hand, so the real controller would never get it back otherwise.
//
// Settings (steamvr.vrsettings section "driver_ft_pointer"): role (int, 2 = right hand, 5 = stylus).
// Settings (steamvr.vrsettings section "driver_ft_pointer"): role (int, 2 = right hand, 4 = treadmill,
// 5 = stylus).
#include <openvr_driver.h>
#include <atomic>
@@ -343,7 +345,8 @@ private:
state_.role = !std::strcmp(name, "left") ? TrackedControllerRole_LeftHand
: !std::strcmp(name, "right") ? TrackedControllerRole_RightHand
: !std::strcmp(name, "stylus") ? TrackedControllerRole_Stylus
: state_.role;
: !std::strcmp(name, "treadmill") ? TrackedControllerRole_Treadmill
: state_.role;
} else if (std::sscanf(cmd, "btn %31s %d", name, &v) == 2) {
for (int i = 0; i < kButtons; ++i)
if (std::strcmp(name, kButtonNames[i]) == 0) state_.buttons[i] = v != 0;