Repository navigation
Conversation
…Amendment 6)
Presence answers "is the hardware there", not "is the user using it". A
camera hand-tracking provider that publishes simple_controller devices is
PRESENT whenever a camera exists, so under the presence-ranked walk it held
the controller roles permanently and the keyboard never got them back.
- xrt_input_plugin_iface: append the optional, struct_size-gated slot
int64_t (*get_engaged_ns)(struct xrt_input_plugin_instance *inst,
uint32_t hand) — os_monotonic_get_ns time of that hand's last deliberate
use, 0 = never. API major stays 1; XRT_INPUT_PLUGIN_IFACE_HAS_GET_ENGAGED_NS
announces it; ABI asserts pin the append order and the vtable size.
- Arbiter: per hand, the most recently engaged PRESENT controller candidate
wins; ties / never-engaged keep rank order; a provider without the slot is
engaged continuously while present (bit-identical to before); engagement
older than a candidate's return to PRESENT does not count. A pin, a session
request or a PreferredPlugin naming a controller provider turn it off for
that client. Engagement is read on the presence poll thread (never a client
thread), for every present slot provider, only while a client resolved
roles in the last second (providers may treat the calls as demand); a
change of leader bumps the state epoch.
- qwerty: qwerty_controller_last_input_ns() — the floor's engagement is the
last keyboard / mouse input aimed at an emulated controller.
- Policy ControllerSwitching = use (default) | presence: Windows
InputProviders\Policy\ControllerSwitching DWORD 1|0 (HKCU over HKLM, the
EmulatedControllers read), POSIX per-user controller_switching file. CLI
`input switching use|presence [--machine]`; `input list --json` carries
controller_switching {value, source}; live through the policy watch.
- sim-input: ENGAGE_MS setting, the in-tree reference for the slot.
- Tests: tests_input_arbiter_engagement; Windows N4 step checks the store,
the verb and input list --json.
- Docs: ADR-034 Amendment 6, input-provider-discovery §2/§3/§4,
input-modality-switching §3.D.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…is engaged First live run (camera hands filling get_engaged_ns): at generation 1 the arbiter gave both hand roles to the provider although nothing had engaged, because never-engaged ties fell back to rank — so the app started on controllers that report nothing (no hand in view) until the user touched the mouse. Rule (same intent, the role follows what you use): a provider that implements the slot and has not engaged that hand since its latest return to PRESENT does not hold it while any other eligible candidate exists — the qwerty floor (never touched = the default holder, not "never engaged") or an engaged / slot-less present provider holds instead. It holds by rank only when it is the only candidate (EmulatedControllers = 0). Among engaged candidates the most recent still wins; ControllerSwitching = presence is unchanged. Tests: nothing engaged -> qwerty holds from generation 1; first pinch -> provider (that hand only); no floor -> slot provider holds by rank; the pin case now starts the unpinned client on the keyboard. ADR-034 Amendment 6, the spec §4 item 2b, the slot doc and the roadmap updated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Presence answers "is the hardware there", not "is the user using it". A camera hand-tracking input provider that publishes left/right
khr/simple_controllerdevices (select = pinch, grip/aim = palm) reports PRESENT whenever a camera exists. Under the presence-ranked walk (Amendments 1/3) it therefore held the controller roles permanently, and keyboard/mouse never got them back. With this change the role follows what the user is actually using.What
ABI (append-only, API major stays 1):
xrt_input_plugin_ifacegainsIt returns the
os_monotonic_get_nstime (CLOCK_MONOTONIC on POSIX, QPC on Windows) of that hand's last deliberate use (0 = left, 1 = right), or 0 for never. Deliberate means a pinch or a button press, never mere visibility. The slot isstruct_size-gated throughXRT_INPUT_PLUGIN_IFACE_HASand announced byXRT_INPUT_PLUGIN_IFACE_HAS_GET_ENGAGED_NS. New ABI asserts pin the order of the appended slots and the size of the vtable.Arbiter (
target_input_arbiter.c), controller family only:EmulatedControllers= 0). Ties keep rank order. (Changed in 2d8c1ef after the first live run: apps started on silent camera controllers until the user touched the mouse.)PreferredPluginnaming a controller provider turns switching off for the clients it applies to.Policy\Lockacts through the precedence it already shapes.generation_idmoves.qwerty:
qwerty_controller_last_input_ns()returns the latest of the controller's button, stick and trackpad edges and the movement/look keys and mouse deltas aimed at that controller. The qwerty head's own WASD/mouse-look does not count. The qwerty builder installs it witht_input_arbiter_set_floor_engagement.Profile stability: the masquerade still applies. When the floor holds a hand by engagement while the provider is present, it reports the top provider's profile. The unit test asserts that
left_profilestays the same across camera → keyboard → camera.Policy
ControllerSwitching=use(default) |presence(exactly today's walk):InputProviders\Policy\ControllerSwitching, REG_DWORD 1 = use, 0 = presence. HKCU wins over HKLM, and HKCU is hidden underPolicy\Lock, the same read asEmulatedControllers.controller_switchingfile containinguseorpresence.displayxr-cli input switching use|presence [--machine].input list --jsonreportscontroller_switching: {value, source}.sim-input: a new
ENGAGE_MSsetting makes it the in-tree reference for the slot. Each active hand engages every n ms. The default is 0, which leaves the slot NULL and keeps today's behaviour.Docs: ADR-034 Amendment 6 (and its Status line), input-provider-discovery §2 / §3 / §4 (item 2b, and a policy table in item 3c), input-modality-switching §3.D.
Tests
tests_input_arbiter_engagement(7 cases):PreferredPluginmeans no switching.presencepolicy gives today's walk, and the slot is never called; a live flip back touseworks.aux_util,drv_qwerty,target_input_arbiter.c,target_input_plugin_loader.candcli_cmd_input.c.input switchingverb andinput list --json.Notes / deviations
Policy\Lockhas no direct switch of its own. It only hides per-user pins, requests and the user default (existing precedence), and switching is off whenever that precedence names a controller provider.🤖 Generated with Claude Code