VR keyboard: the keyboard popup lookup in the finder library

find.keyboardPopup() (finders.js VERSION 3) replaces the same
g_PopupManager lookup in the swipe, extra keys and touch typing patches
(VERSIONs 29, 24, 4). hub.js keeps its own: it gets no finder library.
This commit is contained in:
Pierre Kisters committed 2026-10-01 04:09:59 +02:00
1 parent 0908713667
commit c810df7f5a
5 files changed
+16 -16

No files matched your search

+2 -2
View File
@@ -125,8 +125,8 @@ Every signature must match exactly once, otherwise the patch changes nothing
and reports it: `resolvePatch` returns e.g. `signature not found, Steam left
unpatched: layouts.currentLayout (module 40222): ambiguous export,
candidates r_, xy` as the patch's result. Results are cached per page. The
library also has `ensureStyle(doc, id, css)` and `logger(buffer)` (a capped
debug log).
library also has `ensureStyle(doc, id, css)`, `logger(buffer)` (a capped
debug log) and `keyboardPopup()` (Steam's VR keyboard popup or `null`).
Signatures live in `modules/steam-ui-patches/lib/signatures.json`, shared
by patches and the offline checker. An entry can also list `expects` (strings the patch relies
+8 -3
View File
@@ -3,7 +3,8 @@
// ids or minified names (which change with every Steam update). Like Decky
// Loader's @decky/ui finders and Vencord's `find`.
//
// Also small helpers every patch needs (resolvePatch, ensureStyle, logger).
// Also small helpers every patch needs (resolvePatch, ensureStyle, logger,
// keyboardPopup).
//
// A single expression: installs window.__sfuiFind (unless an equal or newer
// VERSION is there) and evaluates to it; mkPatch passes it as `find`.
@@ -41,7 +42,7 @@
// Every lookup must match exactly once; otherwise a FinderError names the
// signature, the part that failed and the candidates.
(() => {
const VERSION = 2;
const VERSION = 3;
const G = globalThis;
const have = G.__sfuiFind;
if (have && have.version >= VERSION) return have;
@@ -280,6 +281,10 @@
if (s.textContent !== css) s.textContent = css;
return s;
}
// Steam's VR keyboard popup (the g_PopupManager popup with [data-key]
// elements), or null.
const keyboardPopup = () =>
[...(G.g_PopupManager?.GetPopups?.() || [])].find((p) => p.window?.document.querySelector('[data-key]')) ?? null;
// log(msg, data?) appending { t, msg, data } to buf, keeping the last max.
const logger = (buf, max = 200) => (msg, data) => {
buf.push({ t: new Date().toISOString().slice(11, 23), msg, ...(data !== undefined ? { data } : {}) });
@@ -290,7 +295,7 @@
version: VERSION, FinderError, fnSource, matchText, matchValue, kindOf,
getWebpackRequire, findAllModules, findModule, findAllExports, findExport, resolve, resolveAll,
fiberOf, propsOf, findFiberUp, findFiberDown, findInReactTree, cache, requires,
resolvePatch, ensureStyle, logger,
resolvePatch, ensureStyle, logger, keyboardPopup,
};
G.__sfuiFind = lib;
return lib;
+2 -3
View File
@@ -23,7 +23,7 @@
// mkPatch patch (see steam-ui-patches/lib/default.nix); no options. On a
// signature mismatch it returns an error and changes nothing. Idempotent.
((find, sigs) => {
const VERSION = 23;
const VERSION = 24;
const send = (msg) => window.__vrkbdKey && window.__vrkbdKey(msg);
const mods = find.resolvePatch('webpackChunksteamui', sigs);
if (typeof mods === 'string') return mods;
@@ -185,8 +185,7 @@
});
// ---- keyboard component -------------------------------------------------------
const kbPopup = [...(g_PopupManager.GetPopups?.() || [])]
.find((p) => p.window?.document.querySelector('[data-key]'));
const kbPopup = find.keyboardPopup();
if (!kbPopup) return 'no keyboard popup yet';
const doc = kbPopup.window.document;
// The keyboard component: nearest fiber above a key whose instance has TypeKeyInternal.
+2 -6
View File
@@ -17,7 +17,7 @@
// "cancel" (no pose), frames stopping for STALE_MS, the keyboard moving or
// closing end a touch without typing. Debugging: __sfuiTouchTypeLog.
((find, sigs, opts, hooks, TR, HUB) => {
const VERSION = 3;
const VERSION = 4;
const G = window;
const STALE_MS = 1000; // Steam's UI thread can stall frames for ~0.3 s
const SNAP = 3; // SteamVR overlay haptic effect (1 ButtonEnter, 3 Snap)
@@ -43,10 +43,6 @@
typeof f.stateNode?.HandleTouchEnd === 'function' && f.stateNode.m_mapTouched instanceof Set, 200)?.stateNode;
const touches = new Map(); // hand -> { t, inst, doc }
function keyboardWindow() {
const p = [...(G.g_PopupManager?.GetPopups?.() || [])].find((x) => x.window?.document.querySelector('[data-key]'));
return p?.window ?? null;
}
// Steam's handlers read target, changedTouches, touches (tracker.js
// touchEvent) and the touches' target / clientX / clientY.
const others = (t, inst) => [...touches.values()].filter((e) => e.inst === inst && e.t !== t).map((e) => e.t);
@@ -66,7 +62,7 @@
function down(hand, u, v) {
end(hand, { cancel: true });
const win = keyboardWindow();
const win = find.keyboardPopup()?.window;
if (!win) return;
const doc = win.document, x = u * win.innerWidth, y = v * win.innerWidth;
const el = doc.elementsFromPoint(x, y).find((e) => e.id !== 'MouseHoverBlockerHack');
+2 -2
View File
@@ -36,7 +36,7 @@
// Steam's events. Debugging: __sfuiSwipeLog, __sfuiSwipePaths
// (scripts/vr-keyboard-replay.mjs).
((find, sigs, opts, hooks, D, T, C, DICT, P, HUB, F) => {
const VERSION = 28;
const VERSION = 29;
const G = window;
const O = opts;
@@ -67,7 +67,7 @@
return `Steam internals changed, keyboard left stock: ${e.message}`;
}
const popup = [...(g_PopupManager.GetPopups?.() || [])].find((p) => p.window?.document.querySelector('[data-key]'));
const popup = find.keyboardPopup();
if (!popup) return 'no keyboard popup yet';
const doc = popup.window.document;
const stamp = `${VERSION}:${P.VERSION}:${HUB?.version} ${JSON.stringify(O)}`; // new code or options: re-attach