mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 01:00:13 +02:00
VR keyboard controller bridge: no 11 ms timer while the keyboard is hidden
The TICK_MS loop ran (and returned at once) at ~90 Hz all the time; it now runs only while SteamVR shows the keyboard, started and stopped by the 250 ms poll. The pose query's 1 s timeout timer is cleared once the query settles. Frames are unchanged.
This commit is contained in:
1 parent
aa8ccc67c9
commit
605e42ffa1
1 file changed
+25
-27
@@ -19,15 +19,16 @@
|
||||
// Frames go out through the CDP binding __sfuiCtlOut(json) at TICK_MS while
|
||||
// a hand is relevant (tip within NEAR m of the keyboard or trigger pulled) or
|
||||
// Steam asked for it (S.demand(ms), hub.js demand: a laser press), else every
|
||||
// IDLE_MS; one { keyboard: null } frame when the keyboard goes.
|
||||
// Nothing at all while the keyboard is hidden (one DOM lookup per POLL_MS). Frame (hub.js adds page px):
|
||||
// IDLE_MS; one { keyboard: null } frame when the keyboard goes. While it is
|
||||
// hidden: no frames and no TICK_MS loop, one DOM lookup per POLL_MS.
|
||||
// Frame (hub.js adds page px):
|
||||
// { seq, t, moving, keyboard: { width } | null,
|
||||
// hands: { left, right: null | { tip: { u, v, d }, ray: { u, v, dist } | null,
|
||||
// trigger: 0..1 | null } } }
|
||||
// Never touches SteamVR's input or the lasers. Debugging: __sfuiCtl.log,
|
||||
// __sfuiCtl.last (the last frame).
|
||||
((find, sigs, opts, hooks, GEO) => {
|
||||
const VERSION = 4;
|
||||
const VERSION = 5;
|
||||
const G = window;
|
||||
const TICK_MS = 11, IDLE_MS = 1000, POLL_MS = 250, MOVE_QUIET_MS = 300, TIP_CACHE_MS = 5000;
|
||||
const NEAR = 0.1; // m
|
||||
@@ -94,10 +95,11 @@
|
||||
async function pollKeyboard() {
|
||||
pending = true;
|
||||
try {
|
||||
let timer;
|
||||
const xf = await Promise.race([
|
||||
G.SGQueryService.requestSGTransform(`${V.VROverlay.ThisOverlayKey()}::${PROBE}`),
|
||||
new Promise((_, rej) => setTimeout(() => rej(new Error('timeout')), 1000)),
|
||||
]);
|
||||
new Promise((_, rej) => { timer = setTimeout(() => rej(new Error('timeout')), 1000); }),
|
||||
]).finally(() => clearTimeout(timer));
|
||||
if (!probe) return;
|
||||
let ow = 1;
|
||||
try { ow = V.VROverlay.GetWidthInMeters(V.VROverlay.FindOverlay('valve.steam.gamepadui.keyboard')) || 1; } catch { /* 1 */ }
|
||||
@@ -140,23 +142,10 @@
|
||||
h.trigger >= 0.5);
|
||||
|
||||
// ---- loops ---------------------------------------------------------------------
|
||||
let active = false, fastUntil = -Infinity;
|
||||
let fast = null, fastUntil = -Infinity; // fast: the TICK_MS loop, only while the keyboard is shown
|
||||
S.demand = (ms) => { fastUntil = performance.now() + Math.max(0, Math.min(5000, +ms || 0)); };
|
||||
const slow = setInterval(() => {
|
||||
const parent = findScaled();
|
||||
if (!parent) {
|
||||
if (active) { send({ seq: ++seq, t: performance.now(), moving: false, keyboard: null, hands: { left: null, right: null } }); log('inactive'); }
|
||||
active = false; S.kb = null;
|
||||
removeProbe();
|
||||
return;
|
||||
}
|
||||
ensureProbe(parent);
|
||||
if (!active) log('active');
|
||||
active = true;
|
||||
if (!pending) pollKeyboard();
|
||||
}, POLL_MS);
|
||||
const fast = setInterval(() => {
|
||||
if (!active || !S.kb) return;
|
||||
function tick() {
|
||||
if (!S.kb) return;
|
||||
const now = performance.now(), hands = {};
|
||||
for (const h of HANDS) {
|
||||
try { hands[h] = handFrame(h, now); } catch (e) { hands[h] = null; log('pose', String(e)); }
|
||||
@@ -166,12 +155,21 @@
|
||||
send({ seq: ++seq, t: now, moving: now - movedAt < MOVE_QUIET_MS, keyboard: { width: S.kb.width }, hands });
|
||||
}
|
||||
wasRelevant = rel;
|
||||
}, TICK_MS);
|
||||
}
|
||||
function deactivate() {
|
||||
if (fast === null) return;
|
||||
clearInterval(fast); fast = null;
|
||||
send({ seq: ++seq, t: performance.now(), moving: false, keyboard: null, hands: { left: null, right: null } });
|
||||
log('inactive');
|
||||
}
|
||||
const slow = setInterval(() => {
|
||||
const parent = findScaled();
|
||||
if (!parent) { deactivate(); S.kb = null; removeProbe(); return; }
|
||||
ensureProbe(parent);
|
||||
if (fast === null) { fast = setInterval(tick, TICK_MS); log('active'); }
|
||||
if (!pending) pollKeyboard();
|
||||
}, POLL_MS);
|
||||
|
||||
S.dispose = () => {
|
||||
clearInterval(slow); clearInterval(fast);
|
||||
if (active) send({ seq: ++seq, t: performance.now(), moving: false, keyboard: null, hands: { left: null, right: null } });
|
||||
removeProbe();
|
||||
};
|
||||
S.dispose = () => { clearInterval(slow); deactivate(); removeProbe(); };
|
||||
return 'patched';
|
||||
})
|
||||
Reference in new issue
Block a user