diff --git a/modules/firefox.nix b/modules/firefox.nix index 77bb480..d615a0a 100644 --- a/modules/firefox.nix +++ b/modules/firefox.nix @@ -43,8 +43,7 @@ let in { options.steamFrame.firefox = { enable = lib.mkEnableOption '' - the Firefox Flatpak (org.mozilla.firefox) launcher with Steam Frame fixes - ''; + the Firefox Flatpak (org.mozilla.firefox) launcher with Steam Frame fixes''; vrFullscreenFix = lib.mkOption { type = lib.types.bool; default = true; diff --git a/modules/frame-controls/patch.js b/modules/frame-controls/patch.js index 85a9ba5..0c43df5 100644 --- a/modules/frame-controls/patch.js +++ b/modules/frame-controls/patch.js @@ -1,8 +1,8 @@ // frame-controls: move the control icons under SteamVR dashboard windows // between the window's bottom bar and its More Options (three-dot) menu. // A long press on a bar icon or a menu row (opts.longPressMs; a ring around -// the icon fills up once half a second .. a second has passed) opens a small -// popup with a "Show in bar" checkbox; toggling it moves that control for all +// the icon shows the progress from half that time, at most after 1 s) opens a +// small popup with a "Show in bar" checkbox; toggling it moves that control for all // windows. Short presses stay stock. The three-dot button itself can't be // moved (stock shows it while its menu has entries). opts.floatInTheater // gives theater windows the "Float" control back. @@ -46,7 +46,7 @@ // dashboard (no right-click; the thumbstick click arrives as nothing), so a // long press is the trigger. Nothing is stopped or restyled while holding; // the timer keeps running when the laser moves or leaves the control and is -// cancelled only by an early release. When it completes, the popup opens and +// cancelled by an early release (or a curvature drag, below). When it completes, the popup opens and // the one click that follows the release on that control is swallowed, so // its stock action doesn't run. // window-curvature (its controls own press-and-drag) contract: its elements diff --git a/modules/hidden-apps.nix b/modules/hidden-apps.nix index 00696b9..ede25af 100644 --- a/modules/hidden-apps.nix +++ b/modules/hidden-apps.nix @@ -1,5 +1,6 @@ # Hide system apps from menus, including the Steam session's "+" menu (with -# Developer Mode on it lists every desktop entry GLib would show). A user +# Developer Mode on, or launcherMenu.showAllApps, it lists every desktop entry +# GLib would show). A user # entry with Hidden=true in ~/.local/share/applications masks the one in # /usr/share/applications. Also hides them from the nested desktop's KDE menu. { config, lib, ... }: { diff --git a/modules/launcher-menu.nix b/modules/launcher-menu.nix index cf916b8..d2916ea 100644 --- a/modules/launcher-menu.nix +++ b/modules/launcher-menu.nix @@ -1,24 +1,27 @@ # The VR dashboard's "+" menu (non-Steam programs, #VRDashboard_LaunchNonSteamApp) # lists programs in the order SteamClient.Apps.ScanForInstalledNonSteamApps() # returns them: GLib hash-table order, effectively random, with "Desktop" (the -# nested Plasma session) somewhere in a scrolling list. Two runtime patches of -# Steam's UI (steam-ui-patches.nix, evaluated in SharedJSContext) fix that: +# nested Plasma session) somewhere in a scrolling list. Runtime patches of +# Steam's UI (steam-ui-patches.nix, evaluated in SharedJSContext), each +# registered only when its option is set: # - order/: wraps ScanForInstalledNonSteamApps to sort the list by name; # - pinned-desktop/: hides Desktop in the scrolling list and pins a copy above # or below it, with a separator; clicking the copy clicks the hidden -# original. The position is passed by calling the patch's function. +# original; # - launch/: wraps SteamClient.Apps.LaunchNonSteamApp (only called by this # menu) to close the menu right after a program is started, and/or to # ignore repeated launches of the same program within a few seconds (stock, # the menu stays open until the program's window appears, inviting double -# launches). Options are passed by calling the patch's function. +# launches); # - grid/: restyles the programs section as a grid of tiles (icon, name -# below), optionally limited to maxRows visible rows. -# All are reverted when turned off (next switch). -# Depends on Steam UI internals (React props, popup names, the scroll fade's -# classes and CSS), not on webpack module ids; scripts/check-signatures.mjs -# checks them after a Steam update (lib/signatures.json). Tested with Steam -# client 1790377368. +# below), optionally limited to maxRows visible rows; +# - show-all/: empties the list of programs Steam hides without Developer +# Mode (the webpack module holding it is found by signature). +# Options reach the patches through mkPatch's `opts`. All are reverted when +# turned off (next switch). Besides that one module, they depend on Steam UI +# internals such as React props, popup names and the scroll fade's classes +# and CSS; scripts/check-signatures.mjs checks all of them after a Steam +# update (lib/signatures.json). Tested with Steam client 1790377368. # # iconFallbacks is not a patch: Steam's scan of host programs resolves a # desktop entry's Icon= name only in the hicolor icon theme (and pixmaps), @@ -91,8 +94,7 @@ in { grid = { enable = lib.mkEnableOption '' the "+" menu's programs as a grid of tiles (large icon, name below) - instead of a list. Runtime patch of Steam's UI (steamFrame.uiPatches) - ''; + instead of a list. Runtime patch of Steam's UI (steamFrame.uiPatches)''; columns = lib.mkOption { type = lib.types.ints.between 1 8; default = 4; diff --git a/modules/launcher-menu/pinned-desktop/patch.js b/modules/launcher-menu/pinned-desktop/patch.js index 70cced3..f1a4220 100644 --- a/modules/launcher-menu/pinned-desktop/patch.js +++ b/modules/launcher-menu/pinned-desktop/patch.js @@ -27,7 +27,8 @@ // unpatch.js (or a new VERSION/position) calls __sfuiPinnedDesktop.stop(), // which removes the pinned blocks, CSS, markers, observers and the timer. ((find, sigs, opts) => { - const VERSION = 2; + const NAME = 'launcher-menu-pinned-desktop'; + const VERSION = 3; const POS = opts.position === 'top' ? 'top' : 'bottom'; const KEY = 'steamos-nested-desktop'; const HIDDEN = 'data-sfui-desktop-hidden'; @@ -42,10 +43,10 @@ const prev = window.__sfuiPinnedDesktop; if (prev?.version === VERSION && prev.position === POS) { prev.scan(); return 'unchanged'; } prev?.stop?.(); - window.__sfuiDesktopFooter?.stop?.(); // predecessor of this patch if (!window.g_PopupManager) return 'g_PopupManager missing'; const docs = new Map(); // popup document -> MutationObserver + const guard = (f) => (...a) => { try { f(...a); } catch (e) { console.error(`sfui ${NAME}:`, e); } }; // The stock Desktop item: role=button element whose fiber ancestors include // the list entry keyed by the program's exe path. const isDesktop = (el) => { @@ -128,7 +129,7 @@ s.id = STYLE_ID; s.textContent = CSS; (d.head ?? d.documentElement).appendChild(s); } - const obs = new MutationObserver(() => { try { update(d); } catch (e) { console.error('sfui pinned-desktop:', e); } }); + const obs = new MutationObserver(guard(() => update(d))); obs.observe(d.body, { childList: true, subtree: true, characterData: true }); docs.set(d, obs); update(d); @@ -136,10 +137,8 @@ const scan = () => { for (const [d, obs] of docs) if (!d.defaultView || d.defaultView.closed) { obs.disconnect(); docs.delete(d); } - for (const p of g_PopupManager.GetPopups()) { - if (!/barpopup/.test(p.m_strName ?? '')) continue; - try { attach(p.window?.document); } catch (e) { console.error('sfui pinned-desktop:', e); } - } + for (const p of g_PopupManager.GetPopups()) + if (/barpopup/.test(p.m_strName ?? '')) guard(() => attach(p.window?.document))(); }; const timer = setInterval(scan, 1000); diff --git a/modules/steam-close-button.nix b/modules/steam-close-button.nix index 95f9875..30d47dd 100644 --- a/modules/steam-close-button.nix +++ b/modules/steam-close-button.nix @@ -16,20 +16,15 @@ let in { imports = [ ./steam-ui-patches.nix ./steamvr-debugger.nix ]; - options.steamFrame.dashboard.steamCloseButton.enable = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - Close (X) button on the SteamVR dashboard's main Steam window. It - docks the window back into the dashboard if it was placed in the world, - then switches to the most recently active other dashboard window, or, - with none, leaves the dashboard open with just its bar ("bar only"; - kept when the dashboard is closed and reopened, until a window is - activated, e.g. with the Steam tab). Runtime patch of the SteamVR - dashboard (steamFrame.uiPatches), applied immediately; turning it off - removes the button (next switch). - ''; - }; + options.steamFrame.dashboard.steamCloseButton.enable = lib.mkEnableOption '' + a Close (X) button on the SteamVR dashboard's main Steam window. It + docks the window back into the dashboard if it was placed in the world, + then switches to the most recently active other dashboard window, or, + with none, leaves the dashboard open with just its bar ("bar only"; + kept when the dashboard is closed and reopened, until a window is + activated, e.g. with the Steam tab). Runtime patch of the SteamVR + dashboard (steamFrame.uiPatches), applied immediately; turning it off + removes the button (next switch)''; config = lib.mkIf cfg.enable { steamFrame.uiPatches.patches = [ { diff --git a/modules/steam-close-button/patch.js b/modules/steam-close-button/patch.js index 4af7787..32cdb7c 100644 --- a/modules/steam-close-button/patch.js +++ b/modules/steam-close-button/patch.js @@ -46,8 +46,7 @@ // // State that must outlive this instance (bar-only flag, last open time, // pending Steam request, frame history, suppression log) is kept in -// window.__sfuiSteamCloseState (schema 1, shared with the earlier personal -// version 4 of this patch, whose instance is handed over seamlessly). +// window.__sfuiSteamCloseState (schema 1), which upgrades take over. // Teardown (unpatch.js, a newer VERSION) only removes overrides, reactions // and markers: it never switches frames and leaves the state, so a // re-injection (service restart, switch) continues bar-only. It is in-page diff --git a/modules/steam-keyboard-patch.nix b/modules/steam-keyboard-patch.nix index 32b30fb..ec77a6e 100644 --- a/modules/steam-keyboard-patch.nix +++ b/modules/steam-keyboard-patch.nix @@ -29,8 +29,7 @@ in { 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 - ''; + it reverts the patch on the next switch''; config = lib.mkMerge [ (lib.mkIf config.steamFrame.steamKeyboardPatch.enable { diff --git a/modules/window-curvature/patch.js b/modules/window-curvature/patch.js index 08926fe..7fb08e0 100644 --- a/modules/window-curvature/patch.js +++ b/modules/window-curvature/patch.js @@ -2,7 +2,7 @@ // stock "Toggle Curvature" control becomes a wheel wherever it is shown: the // row of a window's More Options (three-dot) menu (with the value on the // right of the row) and, when the control sits in the window's bottom bar -// (e.g. moved there by another patch), that bar button (no value shown: +// (e.g. moved there by frame-controls), that bar button (no value shown: // the steps and snap points are felt as controller haptics). Click toggles // (curved -> flat, flat -> stock curve), dragging up/down with the laser sets // the curvature live.