mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 01:00:13 +02:00
Trim: firefox launcher, debugger-arm migration, comments and docs
- firefox: the prefs.js patterns built once; the extension link condition without the redundant desktopFix (it implies a pref). - install.sh steamvr-debugger-arm: no second copy of the old-marker migration (cleanup, run on every switch before the arm unit exists, already does it). - steam-ui-patches: shorter state option description; lib's description mentions extraArgs. - README: uiPatches.patches fields in the options table (moved from docs/ui-patches.md); docs/ui-patches.md: the finder helpers; docs/steamvr-debugger.md: repeated sentences removed.
This commit is contained in:
1 parent
a5ecbad76d
commit
b3d93e8526
8 files changed
+43
-69
No files matched your search
@@ -4,9 +4,9 @@
|
||||
Valve Steam Frame (SteamOS, `aarch64-linux`, standalone home-manager). They
|
||||
work around quirks of the Frame's [two graphical sessions](#two-sessions)
|
||||
(portal, keyboard layout, clipboard, KDE wallet, Firefox), enable hardware
|
||||
video decoding in Jellyfin, run rootless Docker, and extend Steam's and SteamVR's UIs at runtime (VR keyboard,
|
||||
"+" menu, dashboard windows, Steam close button, window curvature, window
|
||||
controls).
|
||||
video decoding in Jellyfin, run rootless Docker, and extend Steam's and
|
||||
SteamVR's UIs at runtime (VR keyboard, "+" menu, dashboard windows, Steam
|
||||
close button, window curvature, window controls).
|
||||
|
||||
Everything is declarative: files are links into the Nix store, UI patches
|
||||
live in memory. The few things that have to be written elsewhere at runtime
|
||||
@@ -253,7 +253,13 @@ Every module imports `cleanup` (see
|
||||
| `steamFrame.keyboard.vr.backspaceDrag.wordDetentPixels` | int | `90` | Extra travel across a word border (`0`: none). |
|
||||
| `steamFrame.keyboard.vr.haptics` | bool | `true` | Haptic ticks for drag steps, word detents and picks. |
|
||||
| `steamFrame.keyboard.vr.checks` | package, read-only | | The tests, built with the configured dictionary. |
|
||||
| `steamFrame.uiPatches.patches` | list of submodules | `[ ]` | Runtime patches of Steam's web UIs, see [UI patches](docs/ui-patches.md). |
|
||||
| `steamFrame.uiPatches.patches` | list of submodules | `[ ]` | Runtime patches of Steam's web UIs, see [UI patches](docs/ui-patches.md#defining-a-patch). Fields below. |
|
||||
| `steamFrame.uiPatches.patches.*.name` | str | required | Unique name (log). |
|
||||
| `steamFrame.uiPatches.patches.*.endpoint` | str | `"http://127.0.0.1:8080"` | DevTools base URL, `/json/list` polled every 5 s: Steam 8080, SteamVR 8087. |
|
||||
| `steamFrame.uiPatches.patches.*.target.{title,titleRegex,urlRegex}` | null or str | `null` | Pages to patch: exact title, JS regexes; all given ones must match. |
|
||||
| `steamFrame.uiPatches.patches.*.patch` | path | required | JS evaluated (awaited) in every matching page. |
|
||||
| `steamFrame.uiPatches.patches.*.unpatch` | null or path | `null` | JS evaluated when the service stops. |
|
||||
| `steamFrame.uiPatches.patches.*.state` | bool | `false` | One [persistent JSON value](docs/ui-patches.md#persistent-state) for the patch. |
|
||||
| `steamFrame.uiPatches.lib` | attrs, read-only | | Patch helpers (`mkPatch`), see [Finders and signatures](docs/ui-patches.md#mkpatch). |
|
||||
| `steamFrame.launcherMenu.sort` | bool | `false` | Sort the "+" menu alphabetically. |
|
||||
| `steamFrame.launcherMenu.pinDesktop` | null or `"top"` / `"bottom"` | `null` | Pin "Desktop" above/below the "+" menu's list; `null`: normal entry. |
|
||||
|
||||
@@ -44,12 +44,6 @@ Port: `VRWebHelper/DebuggerPort`, default 8087.
|
||||
- when SteamVR stops, the key goes back to its previous value (removed if
|
||||
it wasn't there) and `.armed` is removed.
|
||||
|
||||
The runtime files don't need Nix, which is why rollback and uninstall are
|
||||
covered; they are gone at reboot, and `.armed` (the only trace after a
|
||||
power loss) is resolved by the next SteamVR start or
|
||||
`steam-frame-nix-cleanup`. Disabled, there is no unit; the switch (cleanup)
|
||||
restores the key if SteamVR is stopped, otherwise the runtime drop-in does
|
||||
when it stops.
|
||||
|
||||
Until SteamVR has been restarted once with the drop-in, the port is closed
|
||||
and `steam-ui-patches` keeps polling it.
|
||||
The runtime files need no Nix (rollback, uninstall) and are gone at reboot;
|
||||
`.armed`, the only trace after a power loss, is resolved by the next
|
||||
SteamVR start or `steam-frame-nix-cleanup`.
|
||||
+10
-17
@@ -65,16 +65,8 @@ it runs. What they have in common:
|
||||
|
||||
## Defining a patch
|
||||
|
||||
`steamFrame.uiPatches.patches` entries:
|
||||
|
||||
| Attribute | Default | Description |
|
||||
|---|---|---|
|
||||
| `name` | | Unique name (log). |
|
||||
| `endpoint` | `"http://127.0.0.1:8080"` | DevTools base URL; `/json/list` is polled every 5 s. |
|
||||
| `target.title` / `target.titleRegex` / `target.urlRegex` | `null` | Pages to patch; all given criteria must match (JS regexes). |
|
||||
| `patch` | | JS file evaluated in every matching page (awaited). |
|
||||
| `unpatch` | `null` | JS file evaluated when the service stops. |
|
||||
| `state` | `false` | Give the patch one [persistent JSON value](#persistent-state). |
|
||||
A `steamFrame.uiPatches.patches` entry (fields:
|
||||
[README, Options](../README.md#options)):
|
||||
|
||||
```nix
|
||||
steamFrame.uiPatches.patches = [ {
|
||||
@@ -128,9 +120,11 @@ patches never use them. `modules/lib/finders.js` (like Decky Loader's
|
||||
`findInReactTree`).
|
||||
|
||||
Every signature must match exactly once, otherwise the patch changes nothing
|
||||
and reports it (e.g. `signature not found, Steam left unpatched:
|
||||
layouts.currentLayout (module 40222): ambiguous export, candidates r_, xy`).
|
||||
Results are cached per page.
|
||||
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).
|
||||
|
||||
Signatures live in `modules/lib/signatures.json`, shared by patches and the
|
||||
offline checker. An entry can also list `expects` (strings the patch relies
|
||||
@@ -164,10 +158,9 @@ steamFrame.uiPatches.patches = [ {
|
||||
|
||||
```js
|
||||
((find, sigs, opts, hooks) => {
|
||||
let mods;
|
||||
try { mods = find.resolveAll(find.getWebpackRequire('webpackChunksteamui'), sigs); }
|
||||
catch (e) { return `not patched: ${e.message}`; }
|
||||
const Thing = mods.thing.exports.Thing; // SteamVR dashboard: 'webpackChunkvrwebui'
|
||||
const mods = find.resolvePatch('webpackChunksteamui', sigs); // SteamVR dashboard: 'webpackChunkvrwebui'
|
||||
if (typeof mods === 'string') return mods; // signature not found
|
||||
const Thing = mods.thing.exports.Thing;
|
||||
…
|
||||
})
|
||||
```
|
||||
|
||||
@@ -591,12 +591,6 @@ cmd_debugger_arm() {
|
||||
local cur tmp
|
||||
need_not_root
|
||||
command -v jq >/dev/null 2>&1 || die "jq not found"
|
||||
if [[ -f $DEBUGGER_MARKER_V1 ]]; then # marker of older versions: key was absent
|
||||
mkdir -p "$SFN_STATE"
|
||||
[[ -f $DEBUGGER_ARMED ]] || printf 'absent\n' >"$DEBUGGER_ARMED"
|
||||
rm -f -- "$DEBUGGER_MARKER_V1"
|
||||
info "migrated $DEBUGGER_MARKER_V1 to $DEBUGGER_ARMED"
|
||||
fi
|
||||
if [[ ! -f $DEBUGGER_ARMED ]]; then
|
||||
if [[ -f $VRSETTINGS ]]; then
|
||||
cur="$(jq -r 'if (.VRWebHelper | type) == "object" and (.VRWebHelper | has("DebuggerEnabled"))
|
||||
|
||||
@@ -203,11 +203,9 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } ''
|
||||
arm() { bash ${../../install.sh} steamvr-debugger-arm; }
|
||||
fresh e
|
||||
printf '{\n "steamvr" : {}\n}\n' > $V
|
||||
touch $S/steamvr-debugger # old marker: migrated
|
||||
echo activating > $STUB/state
|
||||
res=$(arm); echo "$res"
|
||||
[ "$(cat $S/steamvr-debugger.armed)" = absent ] || fail "armed"
|
||||
gone $S/steamvr-debugger
|
||||
[ "$(jq -c .VRWebHelper $V)" = '{"DebuggerEnabled":true}' ] || fail "arm: $(cat $V)"
|
||||
there $root/run/steam-frame-nix/steamvr-debugger-restore
|
||||
[ "$(grep -c daemon-reload $STUB/log)" = 1 ] || fail "arm reload"
|
||||
|
||||
+10
-17
@@ -1,25 +1,18 @@
|
||||
# Firefox Flatpak (org.mozilla.firefox) launcher.
|
||||
# - prefs and vrFullscreenFix are default prefs (pref(), the default branch:
|
||||
# never written to prefs.js, so removing one leaves nothing behind). Firefox
|
||||
# reads defaults/pref/*.js from its system config dir, /app/etc/firefox in
|
||||
# the Flatpak, the mount point of the org.mozilla.firefox.systemconfig
|
||||
# extension. The user installation's "unmaintained extension" dir
|
||||
# ($XDG_DATA_HOME/flatpak/extension/<id>/<arch>/<branch>) provides it: a
|
||||
# home-manager link to a store dir, which Flatpak mounts itself (the
|
||||
# sandbox needn't see /nix).
|
||||
# - prefs and vrFullscreenFix are default prefs (pref(): never written to
|
||||
# prefs.js, so removing one leaves nothing behind) in defaults/pref/ of the
|
||||
# org.mozilla.firefox.systemconfig extension (/app/etc/firefox), provided
|
||||
# as the user installation's "unmaintained extension"
|
||||
# ($XDG_DATA_HOME/flatpak/extension/<id>/<arch>/<branch>): a Home Manager
|
||||
# link to a store dir, which Flatpak mounts itself (the sandbox needn't see
|
||||
# /nix).
|
||||
# - vrFullscreenFix: in the Steam session gamescope focuses a fullscreen X11
|
||||
# window but never shows it (Firefox looks frozen). ignore-widgets keeps
|
||||
# fullscreen inside the window.
|
||||
# - desktopProfile: the sessions have separate buses/displays, so a second
|
||||
# Firefox can't reach the running one and hits the profile lock; the nested
|
||||
# desktop gets its own profile (a normal Firefox profile: browser data).
|
||||
# Fullscreen works there, so the launcher undoes the fix in that profile
|
||||
# only while its Firefox runs: a user.js link to the extension's
|
||||
# steam-frame-nix-desktop-user.js (a sandbox path; dangling on the host),
|
||||
# made right before Firefox starts and removed, with the value Firefox
|
||||
# stored from it in prefs.js, once it has exited (firefox/launcher.nix).
|
||||
# Leftovers (a crash) and what older versions wrote into profiles (user.js
|
||||
# copies and links) are removed by steam-frame-nix-cleanup (on switch).
|
||||
# desktop gets its own profile, where fullscreen works: the launcher undoes
|
||||
# the fix there while its Firefox runs (firefox/launcher.nix).
|
||||
# The entry shadows the Flatpak's (same ID), keeping MIME associations, and is
|
||||
# seen by the "+" menu (which reads only ~/.local/share/applications).
|
||||
# defaultBrowser: without a default the portal picks the first installed
|
||||
@@ -122,7 +115,7 @@ in {
|
||||
|
||||
# stable: the branch the launcher runs (the extension point has no
|
||||
# version, so it takes the app's branch).
|
||||
xdg.dataFile = lib.optionalAttrs (defaultPrefs != { } || desktopFix) {
|
||||
xdg.dataFile = lib.optionalAttrs (defaultPrefs != { }) { # desktopFix implies a pref
|
||||
"flatpak/extension/org.mozilla.firefox.systemconfig/aarch64/stable".source = sysconfig;
|
||||
} // {
|
||||
"applications/org.mozilla.firefox.desktop".text = ''
|
||||
|
||||
@@ -26,14 +26,15 @@ writeShellScript "firefox-launcher" (''
|
||||
'' + lib.optionalString desktopFix ''
|
||||
js=${lib.escapeShellArg desktopJs}
|
||||
u=$prof/user.js
|
||||
pats=${lib.escapeShellArg (lib.concatMapStringsSep "\n" (k: "user_pref(${builtins.toJSON k},") desktopKeys)}
|
||||
# Firefox holds .parentlock open while it uses a profile (the sandbox sees
|
||||
# the profile at the same path).
|
||||
inUse() { find /proc/[0-9]*/fd -lname "$prof/.parentlock" -print -quit 2>/dev/null | grep -q .; }
|
||||
ours() { [ -L "$u" ] && [ "$(readlink "$u")" = "$js" ]; }
|
||||
sfn_unlink() {
|
||||
ours && ! inUse || return 0
|
||||
if [ -f "$prof/prefs.js" ] && grep -qF -f <(printf '%s\n' ${lib.escapeShellArgs (map (k: "user_pref(${builtins.toJSON k},") desktopKeys)}) "$prof/prefs.js"; then
|
||||
grep -vF -f <(printf '%s\n' ${lib.escapeShellArgs (map (k: "user_pref(${builtins.toJSON k},") desktopKeys)}) "$prof/prefs.js" > "$prof/prefs.js.sfn" || true
|
||||
if [ -f "$prof/prefs.js" ] && grep -qF "$pats" "$prof/prefs.js"; then
|
||||
grep -vF "$pats" "$prof/prefs.js" > "$prof/prefs.js.sfn" || true
|
||||
cat "$prof/prefs.js.sfn" > "$prof/prefs.js"
|
||||
rm -f "$prof/prefs.js.sfn"
|
||||
fi
|
||||
|
||||
@@ -70,15 +70,10 @@ let
|
||||
default = false;
|
||||
description = ''
|
||||
Give the patch one persistent JSON value (e.g. choices made in its
|
||||
UI), kept by the service in
|
||||
$XDG_STATE_HOME/steam-frame-nix/ui-patches/<name>.json across
|
||||
SteamVR restarts and reboots: the page reads it with
|
||||
`window.__sfuiStore.get(name)` and writes it with
|
||||
`window.__sfuiStore.set(name, value)` (see injector.mjs). The file
|
||||
is kept when the patch is disabled or removed (the choices come
|
||||
back when it is enabled again) and removed by
|
||||
`steam-frame-nix-cleanup --all` (also run by `install.sh
|
||||
uninstall`).
|
||||
UI): `window.__sfuiStore.get(name)` / `.set(name, value)` in the
|
||||
page, kept in $XDG_STATE_HOME/steam-frame-nix/ui-patches/<name>.json
|
||||
across SteamVR restarts, reboots and disabling the patch; removed
|
||||
by `steam-frame-nix-cleanup --all`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -106,9 +101,9 @@ in {
|
||||
defaultText = lib.literalMD "the helpers of `modules/lib`";
|
||||
description = ''
|
||||
Patch helpers from modules/lib/default.nix: `mkPatch { name, src,
|
||||
signatures ? …, opts ? { } }` (calls `src` as
|
||||
`(find, sigs, opts, hooks) => …`; see there), plus `finders`, `hooks`
|
||||
(paths) and `signatures` (parsed signatures.json).
|
||||
signatures ? …, opts ? { }, extraArgs ? [ ] }` (calls `src` as
|
||||
`(find, sigs, opts, hooks, ...extraArgs) => …`; see there), plus
|
||||
`finders`, `hooks` (paths) and `signatures` (parsed signatures.json).
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user