From f7eadb9ac180881e78f2d87230bbf503becf3bc5 Mon Sep 17 00:00:00 2001 From: Pierre Kisters <1524059+lhns@users.noreply.github.com> Date: Sun, 27 Sep 2026 19:20:21 +0200 Subject: [PATCH] Keyboard patch: Enter types Return in app windows despite stale Steam search focus Steam's VirtualKeyboardManager keeps the props of the last focused Steam text field (m_ActiveElementProps) after leaving the dashboard. With a search box there, the VR keyboard for a gamescope window showed "Search" on Enter and its onEnterKeyPress returned "VKClose", hiding the keyboard instead of sending Return. While the keyboard serves something other than this Steam UI, ignore those props and the dismiss-on-Enter flag. --- README.md | 3 +++ modules/steam-keyboard-patch/patch.js | 33 ++++++++++++++++++++++++- modules/steam-keyboard-patch/unpatch.js | 3 +++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cfcebaf..5fedce2 100644 --- a/README.md +++ b/README.md @@ -261,6 +261,9 @@ stops (service stopped, or the option disabled, which stops it via held down (e.g. Ctrl+scroll to zoom). - Problem characters are typed with `xdotool type`; everything else still goes through Steam. +- Enter always types Return in app windows. Stock Steam keeps the last + focused Steam search box as the keyboard target, so Enter could be + labelled "Search" and close the keyboard instead of pressing Return. **Layouts:** the extra-character handling (which characters are routed to xdotool, and the keysym names used for umlauts in chords) targets the German diff --git a/modules/steam-keyboard-patch/patch.js b/modules/steam-keyboard-patch/patch.js index 59754a0..2a6ba5f 100644 --- a/modules/steam-keyboard-patch/patch.js +++ b/modules/steam-keyboard-patch/patch.js @@ -10,12 +10,14 @@ // - characters Steam's own key emulation (ControllerKeyboardSendText) turns // into "1" -- anything non-ASCII or needing AltGr / a dead key on the X // keymap -- are typed by the helper instead +// - Enter types Return for app windows, even if a Steam search box had focus +// before (Steam then labels it "Search" and closes the keyboard instead) // Everything goes through the CDP binding window.__vrkbdKey(":"), // executed by helper.mjs with xdotool on :0. Every replaced function keeps its // original as __vrkbdOrig (unpatch.js restores them). // Idempotent: safe to evaluate repeatedly. (() => { - const VERSION = 8; + const VERSION = 9; const send = (msg) => window.__vrkbdKey && window.__vrkbdKey(msg); const wr = window.__vrkbdWr || (webpackChunksteamui.push([[Symbol('vrkbd')], {}, (r) => { window.__vrkbdWr = r; }]), window.__vrkbdWr); @@ -90,6 +92,35 @@ if (run) return orig.call(this, run, ...rest); }); + // ---- Enter for app windows ------------------------------------------------------ + // The manager keeps the props of the last focused Steam text field + // (m_ActiveElementProps, set on DOM focus) until that field gets a gamepad + // blur, which doesn't happen when you leave the dashboard. Search boxes + // carry strEnterKeyLabel "#SearchEnterKeyLabel" ("Suchen") and an + // onEnterKeyPress returning "VKClose", so when the keyboard is then opened + // for an app window, Enter shows "Suchen", runs the Steam search and hides + // the keyboard instead of typing Return. While the keyboard serves + // something other than this Steam UI (Steam's own test, L() in module + // 5363), ignore those props and the dismiss-on-Enter flag. + const Manager = wr(5363).PE.prototype; + const forOther = (m) => { + const s = Status.VRKeyboardStatus, ui = m.m_Instance; + return !!s?.bIsOpen && !(s.sOverlayKey && s.sOverlayKey === ui?.GetVROverlayKey?.()) && + !(s.unAppID && s.unAppID === ui?.MainRunningAppID); + }; + wrap(Manager, 'GetEnterKeyLabel', (orig) => function (...a) { + return forOther(this) ? undefined : orig.apply(this, a); + }); + wrap(Manager, 'HandleVirtualKeyDown', (orig) => function (key, ...rest) { + if (key !== 'Enter' || !forOther(this)) return orig.call(this, key, ...rest); + const props = this.m_ActiveElementProps, dismiss = this.m_bDismissOnEnter; + this.m_ActiveElementProps = null; this.m_bDismissOnEnter = false; + try { return orig.call(this, key, ...rest); } finally { + if (this.m_ActiveElementProps === null) this.m_ActiveElementProps = props; + if (this.m_bDismissOnEnter === false) this.m_bDismissOnEnter = dismiss; + } + }); + // ---- keyboard component ------------------------------------------------------- const kbPopup = [...(g_PopupManager.GetPopups?.() || [])] .find((p) => p.window?.document.querySelector('[data-key]')); diff --git a/modules/steam-keyboard-patch/unpatch.js b/modules/steam-keyboard-patch/unpatch.js index 985425f..0430f56 100644 --- a/modules/steam-keyboard-patch/unpatch.js +++ b/modules/steam-keyboard-patch/unpatch.js @@ -10,6 +10,9 @@ for (const l of window.__vrkbdLayouts || []) unwrap(l, 'rgLayout'); unwrap(SteamClient.Input, 'ControllerKeyboardSendText'); unwrap(window.__vrkbdProto, 'TypeKeyInternal'); + const Manager = window.__vrkbdWr(5363).PE.prototype; + unwrap(Manager, 'GetEnterKeyLabel'); + unwrap(Manager, 'HandleVirtualKeyDown'); clearInterval(window.__vrkbdHoldTimer); const inst = window.__vrkbdInst;