Files
lhns--steam-frame-nix/modules/steam-keyboard-patch.nix
T
Pierre Kisters 6a8924f219 UI patches: find Steam internals by signature, offline checker
Runtime patches no longer use webpack module ids or minified export
names, which change with every Steam UI build:

- modules/lib/finders.js: finder library (getWebpackRequire,
  findModule/findExport by source text and shape, resolveAll with a
  per-page cache, findFiberUp/findFiberDown/findInReactTree), installed
  once per page as window.__sfuiFind.
- modules/lib/signatures.json: the signatures, per patch, shared by the
  patches and the checker. lib/default.nix mkPatch wraps a patch
  `(find, sigs, opts) => ...` with the library, its signatures and
  options; exposed as steamFrame.uiPatches.lib.
- Keyboard patch (VERSION 10): layouts module, current/enabled layout
  getters, arrow keys, VR keyboard status and VirtualKeyboardManager are
  found by signature; if one doesn't match it reports which and leaves
  Steam untouched. unpatch.js uses references the patch remembered.
  The helper logs inject results when they change.
- launcher-menu launch/pinned-desktop use the library's fiber helpers;
  launch no longer depends on the bar popup's window name.
- scripts/check-signatures.mjs (+ webpack-modules.mjs): extracts module
  factories from the installed bundles without a browser and checks
  every signature (found / ambiguous / missing, with module ids and
  export names). README: "Finders and signatures", "After a Steam update".
2026-09-27 20:04:15 +02:00

65 lines
3.0 KiB
Nix

# Runtime patch of Steam's on-screen (VR) keyboard. Steam's layouts are
# hardcoded in its UI, and in VR it can only send text (no Ctrl/Alt/Esc;
# SteamClient.Input.ControllerKeyboardSetKeyState throws "Unknown method").
# - patch.js is injected into Steam's running UI through its CEF DevTools port
# (127.0.0.1:8080; SteamOS starts Steam with -cef-enable-debugging); Steam's
# files are untouched. Bottom row: Esc Ctrl Alt [space] AltGr ← ↑ ↓ →, with
# AltGr + arrows = Pos1/PgUp/PgDn/End. Chords, Shift+arrows and characters
# Steam's key emulation turns into "1" (non-ASCII, AltGr/dead keys on the
# de keymap) are handed to the helper; Ctrl/Alt are held while toggled.
# - helper.mjs keeps the injection alive (Steam restarts, popup recreated),
# performs those requests with xdotool on :0 (X focus follows the window
# selected in VR) and reverts the patch when stopped (unpatch.js). Its
# allowlist can't type ASCII text or press Enter.
# Depends on Steam UI internals, found by signature (lib/finders.js, entry
# "steam-keyboard-patch" in lib/signatures.json) rather than webpack module
# ids; after a Steam update, scripts/check-signatures.mjs tells whether they
# still match. Tested with Steam client 1790377368 (UI build 11041156).
{ config, pkgs, lib, ... }:
let
patch = (import ./lib { inherit pkgs; }).mkPatch {
name = "steam-keyboard-patch";
src = ./steam-keyboard-patch/patch.js;
};
in {
imports = [ ./session.nix ];
options.steamFrame.steamKeyboardPatch.enable = lib.mkEnableOption ''
the runtime patch of Steam's on-screen (VR) keyboard: Esc/Ctrl/Alt and four
separate arrow keys, real Ctrl/Alt chords (held while toggled, e.g. for
Ctrl+scroll), and working AltGr/non-ASCII characters. Injected into Steam's
UI through its CEF DevTools port by an xdotool helper service; disabling
it reverts the patch on the next switch
'';
config = lib.mkMerge [
(lib.mkIf config.steamFrame.steamKeyboardPatch.enable {
systemd.user.services.steam-keyboard-patch = {
Unit.Description = "Modifier keys for Steam's VR keyboard (CEF patch + xdotool)";
Service = {
ExecStart = lib.escapeShellArgs [
"${pkgs.nodejs}/bin/node"
"${./steam-keyboard-patch/helper.mjs}"
"${patch}"
"${./steam-keyboard-patch/unpatch.js}"
"${pkgs.xdotool}/bin/xdotool"
];
Restart = "always";
RestartSec = 5;
TimeoutStopSec = 5; # the helper unpatches Steam's UI on SIGTERM
};
Install.WantedBy = [ "default.target" ];
};
# Restart on every switch so a changed patch is re-injected (it replaces
# the older version).
steamFrame.userServices.restart = [ "steam-keyboard-patch.service" ];
})
# Disabled: stop a still-running helper, which reverts the patch, so the
# stock keyboard is back right away (no Steam restart or reboot).
(lib.mkIf (!config.steamFrame.steamKeyboardPatch.enable) {
steamFrame.userServices.stop = [ "steam-keyboard-patch.service" ];
})
];
}