mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 01:00:13 +02:00
Nix option docs and module comments: concise
Descriptions say what, default and notable caveats; the mkPatch calling convention is referenced from lib/default.nix instead of repeated.
This commit is contained in:
1 parent
4c843c3ce4
commit
65f5ccde9b
15 files changed
+210
-401
No files matched your search
@@ -24,9 +24,7 @@
|
||||
steam-close-button = ./modules/steam-close-button.nix;
|
||||
window-curvature = ./modules/window-curvature.nix;
|
||||
frame-controls = ./modules/frame-controls.nix;
|
||||
# Built with the consumer's pkgs; only the source comes from our input.
|
||||
# The key lets the module system deduplicate it when it is imported both
|
||||
# directly and through `default`.
|
||||
# Built with the consumer's pkgs; `key` dedups direct + `default` imports.
|
||||
clipboard-sync = {
|
||||
key = "steam-frame-nix/clipboard-sync";
|
||||
_file = ./modules/clipboard-sync.nix;
|
||||
|
||||
+10
-16
@@ -1,10 +1,7 @@
|
||||
# clipboard-sync: bridges the clipboards of the Steam session's X displays and
|
||||
# the nested Plasma desktop (own Wayland + Xwayland :2).
|
||||
# Started via KDE autostart, not systemd: the nested desktop has no access to
|
||||
# the user systemd instance, and clipboard-sync must start after :2 exists.
|
||||
#
|
||||
# Built from source with the consumer's pkgs (the upstream flake outputs are
|
||||
# x86-only); flake.nix passes the source in through this closure.
|
||||
# clipboard-sync between the Steam session's X displays and the nested desktop
|
||||
# (Xwayland :2). KDE autostart, not systemd: the nested desktop can't reach the
|
||||
# user manager, and :2 must exist first. Built from source (upstream flake is
|
||||
# x86-only); flake.nix passes the source in.
|
||||
{ clipboard-sync-src }:
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
@@ -15,8 +12,8 @@ in {
|
||||
type = lib.types.bool;
|
||||
default = true; # without it the nested desktop's clipboard is isolated
|
||||
description = ''
|
||||
Whether to run clipboard-sync between the Steam session and the nested
|
||||
desktop (KDE autostart; on switch, stale builds and duplicates are stopped).
|
||||
Run clipboard-sync between the Steam session and the nested desktop
|
||||
(KDE autostart; switch stops stale builds and duplicates).
|
||||
'';
|
||||
};
|
||||
package = lib.mkOption {
|
||||
@@ -46,13 +43,10 @@ in {
|
||||
NoDisplay=true
|
||||
'';
|
||||
|
||||
# Keep exactly one instance of the current build, preferably one started in
|
||||
# the nested desktop (XDG_CURRENT_DESKTOP=KDE): it inherits the process
|
||||
# environment, so a copy started from a Steam-session terminal runs with
|
||||
# the wrong session's env. Stale builds and duplicate instances are
|
||||
# stopped (workers of an instance are left alone). A new
|
||||
# instance is only started when switching from the nested desktop;
|
||||
# otherwise the autostart entry starts it with the desktop.
|
||||
# Keep one instance of the current build, preferably one started in the
|
||||
# nested desktop (it inherits the environment; one from a Steam-session
|
||||
# terminal has the wrong one). Kill stale builds and duplicates; start a new
|
||||
# one only when switching from the nested desktop (else autostart does).
|
||||
home.activation.startClipboardSync = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
want="${cfg.package}/bin/clipboard-sync"
|
||||
desktop=() other=()
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
# Resize and grab-distance limits of SteamVR dashboard windows (Steam, app
|
||||
# windows, overlays, the theater screen, the dashboard itself), through a
|
||||
# runtime patch of SteamVR's dashboard page (vrwebhelper "systemui", DevTools
|
||||
# 127.0.0.1:8087; see dashboard-windows/patch.js for how it works). It is
|
||||
# registered with steam-ui-patches.nix only when an option is set, and turns
|
||||
# on the SteamVR web helper debugger (steamvr-debugger.nix), which needs one
|
||||
# SteamVR restart the first time. Changes apply immediately (the dashboard
|
||||
# resends its scene graph); unsetting all options reverts to stock.
|
||||
# Depends on SteamVR UI internals, found by signature (lib/signatures.json,
|
||||
# "dashboard-windows"; scripts/check-signatures.mjs checks them offline).
|
||||
# Resize and grab-distance limits of SteamVR dashboard windows. Dashboard patch
|
||||
# (dashboard-windows/patch.js; "systemui" on 127.0.0.1:8087), registered only
|
||||
# when an option is set; enables steamvr-debugger.nix (one SteamVR restart the
|
||||
# first time). Unsetting all options reverts to stock.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.steamFrame.dashboard;
|
||||
@@ -26,8 +20,8 @@ let
|
||||
type = types.nullOr types.number;
|
||||
default = null;
|
||||
description = ''
|
||||
Closest distance in meters ${what} can be pulled in to while grabbed.
|
||||
null = stock (${toString stockDistance.${kind}.min} m).
|
||||
Closest distance (m) ${what} can be pulled in to while grabbed; null =
|
||||
stock (${toString stockDistance.${kind}.min} m).
|
||||
'';
|
||||
};
|
||||
max = mkOption {
|
||||
@@ -35,8 +29,8 @@ let
|
||||
default = null;
|
||||
example = stockDistance.${kind}.max * 2;
|
||||
description = ''
|
||||
Farthest distance in meters ${what} can be pushed back to while
|
||||
grabbed. null = stock (${toString stockDistance.${kind}.max} m).
|
||||
Farthest distance (m) ${what} can be pushed back to while grabbed;
|
||||
null = stock (${toString stockDistance.${kind}.max} m).
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -57,12 +51,9 @@ in {
|
||||
default = null;
|
||||
example = 4.0;
|
||||
description = ''
|
||||
Largest size, relative to their default size, that SteamVR dashboard
|
||||
windows (Steam, app windows, overlays, the theater screen) can be
|
||||
enlarged to with the resize handle. null = stock (2; the smallest is
|
||||
0.25). The theater screen's default size is 2.8x that of a normal
|
||||
window, so its limit is 2.8x this value. Runtime patch of the SteamVR
|
||||
dashboard (steamFrame.uiPatches), applied immediately.
|
||||
Largest resize factor of SteamVR dashboard windows, relative to their
|
||||
default size; null = stock (2). The theater screen starts 2.8x larger,
|
||||
so its limit is 2.8x this. Dashboard patch, applied immediately.
|
||||
'';
|
||||
};
|
||||
windowDistance = {
|
||||
|
||||
+15
-25
@@ -1,22 +1,13 @@
|
||||
# Firefox (Flathub Flatpak org.mozilla.firefox) on the Frame.
|
||||
#
|
||||
# vrFullscreenFix: real fullscreen is broken in the Steam session: gamescope
|
||||
# gives the fullscreen X11 window input focus but never shows it, so Firefox
|
||||
# looks frozen. With ignore-widgets, fullscreen (e.g. YouTube) only fills the
|
||||
# Firefox window itself, which in VR can be made as large as you like.
|
||||
# Profile names are random, and flakes can't read $HOME at eval time, so the
|
||||
# user.js is linked into every existing profile on each switch.
|
||||
#
|
||||
# desktopProfile: the Steam session and the nested desktop have separate D-Bus
|
||||
# buses and displays, so a second Firefox can't find the running one and
|
||||
# stops at the locked profile. In the nested desktop (XDG_CURRENT_DESKTOP=KDE)
|
||||
# the launcher uses its own profile instead (the launcher creates the dir,
|
||||
# Firefox fills it). It gets no user.js: real fullscreen works there.
|
||||
#
|
||||
# The launcher's desktop entry shadows the Flatpak's own entry (same ID), so
|
||||
# MIME/default-browser associations for org.mozilla.firefox.desktop still
|
||||
# apply, and the Steam "+" menu (which only reads ~/.local/share/applications)
|
||||
# sees it.
|
||||
# Firefox Flatpak (org.mozilla.firefox) launcher.
|
||||
# - 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. Profile names are random and $HOME isn't
|
||||
# readable at eval time, so user.js is linked into each profile on switch.
|
||||
# - 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 (no user.js: fullscreen works there).
|
||||
# The entry shadows the Flatpak's (same ID), keeping MIME associations, and is
|
||||
# seen by the "+" menu (which reads only ~/.local/share/applications).
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
cfg = config.steamFrame.firefox;
|
||||
@@ -48,18 +39,17 @@ in {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Link a user.js setting full-screen-api.ignore-widgets into every
|
||||
existing Firefox profile (except the desktop profile), so fullscreen
|
||||
fills only the Firefox window instead of freezing in the Steam session.
|
||||
Link a user.js (full-screen-api.ignore-widgets) into every existing
|
||||
profile except the desktop one, so fullscreen fills the window instead
|
||||
of freezing in the Steam session.
|
||||
'';
|
||||
};
|
||||
desktopProfile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = "desktop";
|
||||
description = ''
|
||||
Name of the separate profile the launcher uses in the nested desktop
|
||||
(XDG_CURRENT_DESKTOP=KDE), so both sessions can run Firefox at once.
|
||||
null uses the default profile in both sessions.
|
||||
Profile used in the nested desktop, so both sessions can run Firefox at
|
||||
once; null = default profile in both.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
+16
-31
@@ -1,16 +1,7 @@
|
||||
# Window control bar (steamFrame.dashboard.frameControls): move the control
|
||||
# icons under SteamVR dashboard windows between the bottom bar and the More
|
||||
# Options (three-dot) menu with a long press on the icon or menu row (a popup
|
||||
# with "Show in bar"). Placement is per control type, for all windows, kept
|
||||
# across SteamVR restarts; inBar / inMenu set defaults. Optionally gives
|
||||
# theater windows the "Float" control back. Runtime patch of SteamVR's
|
||||
# dashboard page (vrwebhelper "systemui", DevTools 127.0.0.1:8087; see
|
||||
# frame-controls/patch.js for how it works), registered with
|
||||
# steam-ui-patches.nix only when enabled; it turns on the SteamVR web helper
|
||||
# debugger (steamvr-debugger.nix), which needs one SteamVR restart the first
|
||||
# time. Depends on SteamVR UI internals, found by signature
|
||||
# (lib/signatures.json, "frame-controls"; scripts/check-signatures.mjs checks
|
||||
# them offline).
|
||||
# Move window controls between a dashboard window's bottom bar and its
|
||||
# three-dot menu (long press). Dashboard patch (frame-controls/patch.js;
|
||||
# "systemui" on 127.0.0.1:8087), registered only when enabled; enables
|
||||
# steamvr-debugger.nix (one SteamVR restart the first time).
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.steamFrame.dashboard.frameControls;
|
||||
@@ -31,28 +22,23 @@ in {
|
||||
|
||||
options.steamFrame.dashboard.frameControls = {
|
||||
enable = lib.mkEnableOption ''
|
||||
moving 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 opens a popup with "Show in bar"; the choice
|
||||
applies to that control in all windows and is kept across SteamVR
|
||||
restarts. Short presses work as usual. Runtime patch of the SteamVR
|
||||
dashboard (steamFrame.uiPatches), applied immediately; turning it off
|
||||
restores the stock controls (next switch)'';
|
||||
moving SteamVR dashboard window controls between the bottom bar and the
|
||||
three-dot menu: long press an icon or menu row for a "Show in bar"
|
||||
popup. Applies to that control in all windows, kept across SteamVR
|
||||
restarts. Dashboard patch; off restores stock (next switch)'';
|
||||
longPressMs = mkOption {
|
||||
type = types.ints.between 300 10000;
|
||||
default = 1500;
|
||||
description = ''
|
||||
Hold time (ms) of the long press that opens the popup. A ring around
|
||||
the icon shows the progress from half the time (at most after 1 s),
|
||||
so ordinary clicks show nothing.
|
||||
Long-press time (ms) to open the popup. A progress ring appears after
|
||||
half of it (at most 1 s), so ordinary clicks show nothing.
|
||||
'';
|
||||
};
|
||||
inBar = controlList ''
|
||||
Controls that start in the bar (by default: SteamVR's placement).
|
||||
Names: ${lib.concatStringsSep ", " names}, or "icon:<n>" (the action's
|
||||
icon number, see window.__sfuiFrameControls.dump() in the dashboard's
|
||||
DevTools). A choice made in the popup wins until the control's entry
|
||||
here changes.
|
||||
Controls that start in the bar (default: SteamVR's placement):
|
||||
${lib.concatStringsSep ", " names}, or "icon:<n>" (see
|
||||
window.__sfuiFrameControls.dump() in the dashboard's DevTools). A popup
|
||||
choice wins until the control's entry here changes.
|
||||
'';
|
||||
inMenu = controlList ''
|
||||
Controls that start in the three-dot menu (same names as inBar).
|
||||
@@ -61,9 +47,8 @@ in {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Give windows in the theater the "Float" control (SteamVR only shows it
|
||||
for windows docked in the dashboard): floats the window in the world,
|
||||
like the stock button. Follows Float's placement.
|
||||
Give theater windows the "Float" control too (stock: dashboard-docked
|
||||
windows only). Follows Float's placement.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
# Hide system apps from menus, including the Steam session's "+" menu (with
|
||||
# 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.
|
||||
# Hide desktop entries from the "+" menu and the KDE menu: a user entry with
|
||||
# Hidden=true masks the system one.
|
||||
{ config, lib, ... }: {
|
||||
options.steamFrame.hiddenApps = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
# Keyboard layout for the Steam session. gamescope (and its Xwayland displays
|
||||
# :0/:1) uses xkbcommon defaults, i.e. US, unless XKB_DEFAULT_* is set. KDE's
|
||||
# layout setting only applies to the nested desktop. systemd --user on the
|
||||
# Frame does not pick up ~/.config/environment.d, so set it directly on the
|
||||
# unit that launches gamescope. Takes effect the next time the Steam session
|
||||
# starts.
|
||||
# Keyboard layout for the Steam session: gamescope uses xkbcommon defaults (US)
|
||||
# unless XKB_DEFAULT_* is set; KDE's setting only covers the nested desktop.
|
||||
# environment.d isn't read on the Frame, so it goes on gamescope-session.service
|
||||
# (next session start).
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.steamFrame;
|
||||
@@ -14,8 +12,7 @@ in {
|
||||
default = null;
|
||||
example = "de";
|
||||
description = ''
|
||||
XKB layout for the Steam session (XKB_DEFAULT_LAYOUT). null leaves
|
||||
gamescope's default (US) and writes no drop-in.
|
||||
XKB layout for the Steam session (XKB_DEFAULT_LAYOUT); null = US.
|
||||
'';
|
||||
};
|
||||
keyboardVariant = lib.mkOption {
|
||||
|
||||
+48
-85
@@ -1,37 +1,19 @@
|
||||
# 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. 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;
|
||||
# - 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);
|
||||
# - grid/: restyles the programs section as a grid of tiles (icon, name
|
||||
# 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.
|
||||
# The VR dashboard's "+" menu (non-Steam programs). Steam lists them in GLib
|
||||
# hash-table order (random-looking). Runtime patches in SharedJSContext, each
|
||||
# registered only when its option is set, reverted when unset (next switch):
|
||||
# - order/: sorts ScanForInstalledNonSteamApps() by name;
|
||||
# - pinned-desktop/: hides Desktop in the list, pins a proxy above/below it;
|
||||
# - launch/: wraps LaunchNonSteamApp (menu-only) to close the menu and/or
|
||||
# debounce repeated launches;
|
||||
# - grid/: programs as a grid of tiles, optionally maxRows visible;
|
||||
# - show-all/: empties the list Steam hides without Developer Mode.
|
||||
# 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),
|
||||
# so programs whose icon exists only in the desktop's Breeze theme (SteamOS'
|
||||
# Konsole and KDE System Settings) have no icon in the menu. On every switch,
|
||||
# launcher-menu/icon-fallbacks.sh looks through the desktop entries Steam
|
||||
# sees and links the missing icons that nixpkgs' Breeze has into
|
||||
# ~/.local/share/icons/hicolor (see the script). Until 2026-09 iconFallbacks
|
||||
# was a list of names; setting a list now fails with a message pointing to
|
||||
# enable/extra.
|
||||
# iconFallbacks (not a patch): Steam resolves Icon= names only in hicolor (and
|
||||
# pixmaps), so Breeze-only icons (Konsole, KDE System Settings) are missing;
|
||||
# icon-fallbacks.sh links them from nixpkgs' Breeze into
|
||||
# ~/.local/share/icons/hicolor on switch. It was a list of names until 2026-09;
|
||||
# a list now fails with a pointer to enable/extra.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.steamFrame.launcherMenu;
|
||||
@@ -51,9 +33,7 @@ in {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Sort the VR dashboard's "+" menu (non-Steam programs) alphabetically
|
||||
instead of Steam's random-looking order. Runtime patch of Steam's UI
|
||||
(steamFrame.uiPatches).
|
||||
Sort the "+" menu (non-Steam programs) by name. Runtime patch.
|
||||
'';
|
||||
};
|
||||
pinDesktop = lib.mkOption {
|
||||
@@ -61,23 +41,17 @@ in {
|
||||
default = null;
|
||||
example = "bottom";
|
||||
description = ''
|
||||
Pin "Desktop" (the nested Plasma session) above ("top", below the
|
||||
menu heading) or below ("bottom") the scrolling program list of the
|
||||
"+" menu, separated by a thin line, so it is always visible; it is
|
||||
hidden in the list itself. null leaves it a normal list entry. Runtime
|
||||
patch of Steam's UI (steamFrame.uiPatches).
|
||||
Pin "Desktop" (the nested Plasma session) above ("top") or below
|
||||
("bottom") the "+" menu's scrolling list, so it is always visible;
|
||||
null = normal list entry. Runtime patch.
|
||||
'';
|
||||
};
|
||||
closeOnLaunch = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Close the "+" menu as soon as a program in it is activated (pointer,
|
||||
controller or the pinned Desktop entry). Stock, it stays open until the
|
||||
program's window appears, so it looks as if the click did nothing and
|
||||
programs get launched twice. Runtime patch of Steam's UI
|
||||
(steamFrame.uiPatches); off by default like the other launcherMenu
|
||||
options, so nothing is injected unless asked for.
|
||||
Close the "+" menu as soon as a program is launched (stock: it stays
|
||||
open until the window appears, inviting double launches). Runtime patch.
|
||||
'';
|
||||
};
|
||||
launchDebounce = lib.mkOption {
|
||||
@@ -85,22 +59,21 @@ in {
|
||||
default = 0;
|
||||
example = 10;
|
||||
description = ''
|
||||
Seconds during which another launch of the same program (same command
|
||||
line) from the "+" menu is ignored, counted from the last launch that
|
||||
went through; ignored launches are logged (steam-ui-patches journal).
|
||||
0 disables it. Runtime patch of Steam's UI (steamFrame.uiPatches).
|
||||
Ignore another "+" menu launch of the same command line within this
|
||||
many seconds of the last one that went through (logged); 0 = off.
|
||||
Runtime patch.
|
||||
'';
|
||||
};
|
||||
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)'';
|
||||
the "+" menu's programs as a grid of tiles (icon, name below) instead
|
||||
of a list. Runtime patch'';
|
||||
columns = lib.mkOption {
|
||||
type = lib.types.ints.between 1 8;
|
||||
default = 4;
|
||||
description = ''
|
||||
Tiles per row. The menu popup is a fixed 300 px wide: 3 columns give
|
||||
tiles of about 92 px, 4 about 68 px, 5 about 53 px.
|
||||
Tiles per row (the menu is 300 px wide: 3 → ~92 px tiles, 4 → ~68,
|
||||
5 → ~53).
|
||||
'';
|
||||
};
|
||||
maxRows = lib.mkOption {
|
||||
@@ -108,9 +81,8 @@ in {
|
||||
default = null;
|
||||
example = 4;
|
||||
description = ''
|
||||
Rows of tiles visible at once: the menu shrinks to that many rows and
|
||||
the rest scrolls. null: the grid fills up to the menu's stock maximum
|
||||
height (600 px).
|
||||
Rows visible at once (the rest scrolls); null = up to the menu's
|
||||
stock max height (600 px).
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -118,24 +90,20 @@ in {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
List all programs in the "+" menu without Steam's Developer Mode.
|
||||
Without it, Steam hides a fixed list (konsole, systemsettings,
|
||||
dolphin, plasma-discover, vlc, firewall-config, cmake-gui, qrenderdoc,
|
||||
lxterminal, sh). Only that list is emptied; the Developer Mode setting
|
||||
itself (used by other settings pages) is untouched. Hide individual
|
||||
programs with steamFrame.hiddenApps. Runtime patch of Steam's UI
|
||||
(steamFrame.uiPatches).
|
||||
List all programs in the "+" menu without Developer Mode (Steam
|
||||
otherwise hides konsole, systemsettings, dolphin, plasma-discover, vlc,
|
||||
firewall-config, cmake-gui, qrenderdoc, lxterminal, sh). Developer Mode
|
||||
itself is untouched; hide single programs with steamFrame.hiddenApps.
|
||||
Runtime patch.
|
||||
'';
|
||||
};
|
||||
iconFallbacks = lib.mkOption {
|
||||
default = { };
|
||||
description = ''
|
||||
Hicolor fallbacks for program icons only the desktop's Breeze theme
|
||||
has, so the "+" menu shows them: Steam resolves program icons only in
|
||||
the hicolor theme.
|
||||
Hicolor links for program icons only Breeze has, so the "+" menu shows
|
||||
them (Steam looks only in hicolor).
|
||||
'';
|
||||
# The option used to be a list of icon names: keep a list from being
|
||||
# silently misread and fail with a message instead (see the assertion).
|
||||
# Formerly a list of names: fail with a message instead (see assertion).
|
||||
type = lib.types.coercedTo (lib.types.listOf lib.types.str)
|
||||
(names: { legacyList = names; })
|
||||
(lib.types.submodule {
|
||||
@@ -144,16 +112,12 @@ in {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
On every switch, look through the desktop entries Steam sees
|
||||
(XDG data dirs, shadowed and Hidden/NoDisplay entries skipped)
|
||||
and, for each Icon= name no hicolor theme dir (or pixmaps)
|
||||
has but nixpkgs' Breeze app icons do (SteamOS: Konsole's
|
||||
utilities-terminal, KDE System Settings' preferences-system),
|
||||
link the Breeze SVG as
|
||||
~/.local/share/icons/hicolor/scalable/apps/<name>.svg. Links
|
||||
no longer needed are removed; only links made by this option
|
||||
(listed in ~/.local/state/steam-frame-nix/icon-fallbacks) are
|
||||
ever touched. false removes them all.
|
||||
On switch, for each Icon= of the desktop entries Steam sees
|
||||
that hicolor lacks but nixpkgs' Breeze has (SteamOS:
|
||||
utilities-terminal, preferences-system), link the Breeze SVG
|
||||
into ~/.local/share/icons/hicolor/scalable/apps. Only its own
|
||||
links (listed in ~/.local/state/steam-frame-nix/icon-fallbacks)
|
||||
are touched; stale ones are removed; false removes all.
|
||||
'';
|
||||
};
|
||||
extra = lib.mkOption {
|
||||
@@ -161,9 +125,8 @@ in {
|
||||
default = [ ];
|
||||
example = [ "system-file-manager" ];
|
||||
description = ''
|
||||
Icon names to provide even if no desktop entry the scan sees
|
||||
uses them (still only if hicolor lacks them). A name Breeze
|
||||
has no app icon for is reported on switch and skipped.
|
||||
Extra icon names to provide (if hicolor lacks them); names
|
||||
Breeze doesn't have are reported and skipped.
|
||||
'';
|
||||
};
|
||||
legacyList = lib.mkOption {
|
||||
@@ -188,8 +151,8 @@ in {
|
||||
'';
|
||||
} ];
|
||||
|
||||
# After installPackages, so the new profile's desktop entries and icons count.
|
||||
# Disabled, the script removes its links (no BREEZE_APPS).
|
||||
# After installPackages so the new profile counts; without BREEZE_APPS the
|
||||
# script removes its links.
|
||||
config.home.activation.steamFrameIconFallbacks =
|
||||
lib.hm.dag.entryAfter [ "writeBoundary" "installPackages" ] (
|
||||
if cfg.iconFallbacks.enable then ''
|
||||
|
||||
+8
-12
@@ -1,11 +1,8 @@
|
||||
# Workaround for the Steam Frame image (SteamOS 0.3.0, build 20260922):
|
||||
# the Steam session's xdg-desktop-portal gets XDG_DESKTOP_PORTAL_DIR pointing at
|
||||
# /usr/share/xdg-desktop-portal/gamescope-portals, which contains the holo and
|
||||
# gamescope backends but no gamescope-portals.conf (and no UseIn=). With that
|
||||
# variable set, the portal only reads config from that dir, so it selects no
|
||||
# backend and offers no OpenURI: no app in the Steam session can open links.
|
||||
# Fix: our own portal dir = links to Valve's .portal files + a config.
|
||||
# Remove once SteamOS ships a gamescope-portals.conf.
|
||||
# Workaround (SteamOS 0.3.0, build 20260922): the Steam session's portal dir
|
||||
# /usr/share/xdg-desktop-portal/gamescope-portals has backends but no
|
||||
# gamescope-portals.conf, so no backend is selected and there is no OpenURI
|
||||
# (links don't open). We point it at our own dir: Valve's .portal files + a
|
||||
# config. Remove once SteamOS ships the .conf.
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
sys = "/usr/share/xdg-desktop-portal/gamescope-portals";
|
||||
@@ -15,8 +12,8 @@ in {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Give the Steam session's xdg-desktop-portal a working config
|
||||
(gamescope-portals.conf) so apps there can open links (OpenURI).
|
||||
Give the Steam session's xdg-desktop-portal a config so apps there can
|
||||
open links (OpenURI).
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -30,8 +27,7 @@ in {
|
||||
default=holo;gamescope
|
||||
'';
|
||||
|
||||
# Only affects the systemd-managed (outer) portal; the nested desktop's
|
||||
# portal is D-Bus-activated on its own bus and keeps using kde-portals.conf.
|
||||
# Outer (systemd) portal only; the nested desktop's keeps kde-portals.conf.
|
||||
xdg.configFile."systemd/user/xdg-desktop-portal.service.d/gamescope-portals.conf".text = ''
|
||||
[Service]
|
||||
Environment=XDG_DESKTOP_PORTAL_DIR=%h/.local/share/${dir}
|
||||
|
||||
+12
-24
@@ -1,19 +1,11 @@
|
||||
# Shared settings for the two sessions on the Steam Frame, and the
|
||||
# user-services mechanism.
|
||||
# Settings shared by both sessions, and user-service handling on switch.
|
||||
#
|
||||
# The Frame runs the Steam/VR session (gamescope, systemd user manager, outer
|
||||
# D-Bus at <runtimeDir>/bus) and a nested Plasma desktop with its own
|
||||
# XDG_RUNTIME_DIR and private D-Bus. Modules that talk to the outer session use
|
||||
# `runtimeDir` / `userBus` explicitly.
|
||||
#
|
||||
# User services: `home-manager switch` usually runs from the nested desktop,
|
||||
# whose XDG_RUNTIME_DIR and D-Bus can't reach the user manager, so
|
||||
# home-manager's own reloadSystemd step is skipped ("User systemd daemon not
|
||||
# running"). The `steamFrameUserServices` activation entry does it instead,
|
||||
# pointed at the outer session: it always runs `systemctl --user
|
||||
# daemon-reload` (so changed unit files are picked up even when both lists are
|
||||
# empty), then starts the units in `userServices.start`, stops those in
|
||||
# `userServices.stop` and restarts those in `userServices.restart`.
|
||||
# The Steam/VR session owns the systemd user manager and the outer D-Bus
|
||||
# (<runtimeDir>/bus); the nested Plasma desktop has its own XDG_RUNTIME_DIR
|
||||
# and private bus. `switch` usually runs from the nested desktop, where
|
||||
# home-manager's reloadSystemd is skipped ("User systemd daemon not running"),
|
||||
# so `steamFrameUserServices` does it against the outer session: always
|
||||
# daemon-reload, then start/stop/restart the units in `userServices`.
|
||||
{ config, lib, ... }:
|
||||
let
|
||||
cfg = config.steamFrame;
|
||||
@@ -30,8 +22,8 @@ in {
|
||||
default = "unix:path=${cfg.runtimeDir}/bus";
|
||||
defaultText = lib.literalExpression ''"unix:path=''${config.steamFrame.runtimeDir}/bus"'';
|
||||
description = ''
|
||||
Address of the outer session D-Bus. The user systemd manager and the
|
||||
single running kwalletd6 are only reachable over this bus.
|
||||
Outer session D-Bus address; the only bus that reaches the user
|
||||
systemd manager and the running kwalletd6.
|
||||
'';
|
||||
};
|
||||
outerBusEnv = lib.mkOption {
|
||||
@@ -40,9 +32,8 @@ in {
|
||||
default = "env DBUS_SESSION_BUS_ADDRESS=${cfg.userBus}";
|
||||
defaultText = lib.literalExpression ''"env DBUS_SESSION_BUS_ADDRESS=''${config.steamFrame.userBus}"'';
|
||||
description = ''
|
||||
Command prefix for launchers (desktop entry Exec= lines) that must use
|
||||
the outer bus, e.g. so apps started from the nested desktop use the
|
||||
one kwalletd6 instead of starting a second wallet on the private bus.
|
||||
Exec= prefix for launchers that must use the outer bus, e.g. so apps
|
||||
in the nested desktop use the running kwalletd6 instead of a second one.
|
||||
'';
|
||||
};
|
||||
userServices = {
|
||||
@@ -61,10 +52,7 @@ in {
|
||||
stop = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ ];
|
||||
description = ''
|
||||
User units stopped on switch if still running, e.g. the service of a
|
||||
feature that was just disabled (its unit file is already gone).
|
||||
'';
|
||||
description = "User units stopped on switch if running (e.g. of a just-disabled feature).";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
# Close (X) button on the SteamVR dashboard's main Steam window
|
||||
# (steamFrame.dashboard.steamCloseButton.enable): it switches to the
|
||||
# previously active dashboard window, or leaves just the dashboard bar when
|
||||
# Steam was the last one. Runtime patch of SteamVR's dashboard page
|
||||
# (vrwebhelper "systemui", DevTools 127.0.0.1:8087; see
|
||||
# steam-close-button/patch.js for how it works), registered with
|
||||
# steam-ui-patches.nix only when enabled; it turns on the SteamVR web helper
|
||||
# debugger (steamvr-debugger.nix), which needs one SteamVR restart the first
|
||||
# time. Depends on SteamVR UI internals, found by signature
|
||||
# (lib/signatures.json, "steam-close-button"; scripts/check-signatures.mjs
|
||||
# checks them offline).
|
||||
# Close (X) button on the dashboard's Steam window. Dashboard patch
|
||||
# (steam-close-button/patch.js; "systemui" on 127.0.0.1:8087), registered only
|
||||
# when enabled; enables steamvr-debugger.nix (one SteamVR restart the first time).
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.steamFrame.dashboard.steamCloseButton;
|
||||
@@ -17,14 +9,10 @@ in {
|
||||
imports = [ ./steam-ui-patches.nix ./steamvr-debugger.nix ];
|
||||
|
||||
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)'';
|
||||
a Close (X) button on the dashboard's Steam window: docks it back if it
|
||||
was in the world, then switches to the last active other window, or
|
||||
leaves only the dashboard bar (until a window is activated, e.g. via the
|
||||
Steam tab). Dashboard patch; off removes it (next switch)'';
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
steamFrame.uiPatches.patches = [ {
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
# 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).
|
||||
# Steam's VR keyboard can only send text (ControllerKeyboardSetKeyState throws
|
||||
# "Unknown method" in VR), and its layouts are hardcoded.
|
||||
# - patch.js (injected over CEF DevTools, 127.0.0.1:8080) adds a bottom row
|
||||
# Esc Ctrl Alt [space] AltGr ← ↑ ↓ → (AltGr+arrows = Pos1/PgUp/PgDn/End) and
|
||||
# hands chords, Shift+arrows and characters Steam would turn into "1"
|
||||
# (non-ASCII, AltGr/dead keys) to the helper.
|
||||
# - helper.mjs keeps it injected, sends those keys with xdotool on :0 (an
|
||||
# allowlist: no ASCII text, no Enter) and unpatches on stop.
|
||||
# Tested with Steam client 1790377368 (UI build 11041156).
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
patch = (import ./lib { inherit pkgs; }).mkPatch {
|
||||
@@ -25,11 +17,9 @@ 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'';
|
||||
Esc/Ctrl/Alt, arrow keys, Ctrl/Alt chords (held while toggled) and
|
||||
AltGr/non-ASCII characters on Steam's VR keyboard (runtime patch plus an
|
||||
xdotool helper service); off reverts it on the next switch'';
|
||||
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf config.steamFrame.steamKeyboardPatch.enable {
|
||||
@@ -50,12 +40,10 @@ in {
|
||||
Install.WantedBy = [ "default.target" ];
|
||||
};
|
||||
|
||||
# Restart on every switch so a changed patch is re-injected (it replaces
|
||||
# the older version).
|
||||
# Restart on switch to re-inject a changed patch.
|
||||
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).
|
||||
# Disabled: stopping the helper reverts the patch right away.
|
||||
(lib.mkIf (!config.steamFrame.steamKeyboardPatch.enable) {
|
||||
steamFrame.userServices.stop = [ "steam-keyboard-patch.service" ];
|
||||
})
|
||||
|
||||
@@ -1,24 +1,11 @@
|
||||
# Runtime patches of Steam's (and SteamVR's) web UIs through their local CEF
|
||||
# DevTools ports: Steam's client UI on 127.0.0.1:8080 (SteamOS starts Steam
|
||||
# with -cef-enable-debugging), SteamVR's vrwebhelper on 127.0.0.1:8087 when
|
||||
# its debugger is enabled. Steam's files are untouched: the
|
||||
# `steam-ui-patches` service (injector.mjs, Node) evaluates each registered
|
||||
# patch in its target pages, re-injects it when a page is reloaded or
|
||||
# recreated (and every 15 s), and evaluates its unpatch expression when the
|
||||
# service stops, so the UI is back to stock without a Steam restart.
|
||||
#
|
||||
# Other modules (and your own config) register patches in
|
||||
# `steamFrame.uiPatches.patches`; the service exists only while that list is
|
||||
# non-empty. It is restarted on every switch (changed patches are re-injected,
|
||||
# removed ones reverted by the old instance) and stopped once the list is
|
||||
# empty. The keyboard patch (steam-keyboard-patch.nix) has its own helper.
|
||||
#
|
||||
# Patches that need Steam's webpack modules should find them by signature
|
||||
# rather than by module id or minified export name, which change with Steam
|
||||
# updates: `steamFrame.uiPatches.lib.mkPatch` wraps a patch written as
|
||||
# `(find, sigs, opts, hooks) => …` with the finder library (lib/finders.js),
|
||||
# its signatures and the shared method hooks (lib/hooks.js);
|
||||
# scripts/check-signatures.mjs checks signatures offline.
|
||||
# Runtime patches of Steam's and SteamVR's web UIs over local CEF DevTools
|
||||
# (Steam 127.0.0.1:8080; SteamVR's vrwebhelper 127.0.0.1:8087, see
|
||||
# steamvr-debugger.nix). The steam-ui-patches service (injector.mjs) injects
|
||||
# each registered patch into its target pages, re-injects on reload and every
|
||||
# 15 s, and runs the unpatches on stop; Steam's files are untouched.
|
||||
# It exists while `patches` is non-empty, restarts on every switch (the old
|
||||
# instance reverts removed patches) and is stopped once the list is empty.
|
||||
# Patch calling convention (mkPatch): lib/default.nix.
|
||||
{ config, pkgs, lib, ... }:
|
||||
let
|
||||
cfg = config.steamFrame.uiPatches;
|
||||
@@ -36,8 +23,7 @@ let
|
||||
default = "http://127.0.0.1:8080";
|
||||
example = "http://127.0.0.1:8087";
|
||||
description = ''
|
||||
DevTools base URL of the CEF instance (its /json/list is polled).
|
||||
Steam's client UI is on port 8080, SteamVR's vrwebhelper on 8087.
|
||||
DevTools base URL (its /json/list is polled): Steam 8080, SteamVR 8087.
|
||||
'';
|
||||
};
|
||||
target = {
|
||||
@@ -61,21 +47,18 @@ let
|
||||
patch = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
JavaScript file evaluated in every matching page (DevTools
|
||||
Runtime.evaluate, awaited). Must be idempotent: it is re-evaluated
|
||||
after page reloads and every 15 s. Its result value is logged when it
|
||||
changes; return e.g. "patched", and "unchanged" (never logged) when
|
||||
already applied. To use the finder library, build it with
|
||||
`config.steamFrame.uiPatches.lib.mkPatch`.
|
||||
JavaScript evaluated (awaited) in every matching page after reloads
|
||||
and every 15 s, so it must be idempotent. Its result is logged when
|
||||
it changes ("unchanged" never is). Build with `lib.mkPatch` to get
|
||||
the finder library.
|
||||
'';
|
||||
};
|
||||
unpatch = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
JavaScript file evaluated in every patched page when the service
|
||||
stops (switch, list emptied, logout), reverting the patch. Must be
|
||||
safe when the page isn't patched.
|
||||
JavaScript that reverts the patch when the service stops; must be
|
||||
safe on an unpatched page.
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -102,16 +85,10 @@ in {
|
||||
default = import ./lib { inherit pkgs; };
|
||||
defaultText = lib.literalMD "the helpers of `modules/lib`";
|
||||
description = ''
|
||||
Helpers for writing patches (see modules/lib/default.nix):
|
||||
`mkPatch { name, src, signatures ? …, opts ? { } }` returns a patch
|
||||
file that calls `src`, a JavaScript function expression
|
||||
`(find, sigs, opts, hooks) => …`, with the finder library `find`
|
||||
(modules/lib/finders.js: getWebpackRequire, resolveAll, findModule,
|
||||
findExport, findFiberUp, findInReactTree, …), the module signatures
|
||||
`sigs` (format: modules/lib/signatures.json; default: its entry
|
||||
`name`, if any), `opts` and the shared method hooks `hooks`
|
||||
(modules/lib/hooks.js: before, remove, has). `finders` and `hooks`
|
||||
are the libraries' paths, `signatures` the parsed signatures.json.
|
||||
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).
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -128,9 +105,8 @@ in {
|
||||
'';
|
||||
description = ''
|
||||
Runtime patches of Steam's web UIs, kept injected by the
|
||||
`steam-ui-patches` user service over the local CEF DevTools ports and
|
||||
reverted when it stops. Every target (page) of the endpoint matching all
|
||||
given target criteria is patched.
|
||||
steam-ui-patches service and reverted when it stops. Every page
|
||||
matching all given target criteria is patched.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -156,13 +132,11 @@ in {
|
||||
Install.WantedBy = [ "default.target" ];
|
||||
};
|
||||
|
||||
# Restart on every switch so changed patches are re-injected (each
|
||||
# replaces its older version) and removed ones are reverted by the old
|
||||
# instance.
|
||||
# Restart on switch: re-inject changed patches; the old instance reverts
|
||||
# removed ones.
|
||||
steamFrame.userServices.restart = [ "steam-ui-patches.service" ];
|
||||
})
|
||||
# No patches: stop a still-running injector, which reverts its patches, so
|
||||
# Steam's UI is stock right away.
|
||||
# No patches: stopping the injector reverts them right away.
|
||||
(lib.mkIf (cfg.patches == [ ]) {
|
||||
steamFrame.userServices.stop = [ "steam-ui-patches.service" ];
|
||||
})
|
||||
|
||||
@@ -1,29 +1,16 @@
|
||||
# Enables the SteamVR web helper debugger: Chromium DevTools of vrwebhelper,
|
||||
# which renders the SteamVR dashboard, on 127.0.0.1:8087, so steam-ui-patches
|
||||
# can patch the dashboard the way it patches Steam's UI on 127.0.0.1:8080.
|
||||
# Turned on automatically (mkDefault) when a UI patch targets port 8087.
|
||||
# SteamVR web helper debugger: DevTools of the dashboard (vrwebhelper) on
|
||||
# 127.0.0.1:8087, for dashboard patches. On automatically (mkDefault) when a
|
||||
# patch targets port 8087.
|
||||
#
|
||||
# SteamVR only opens the port when /settings/VRWebHelper/DebuggerEnabled is
|
||||
# true (settingsschema.vrsettings: requires_restart; port from
|
||||
# VRWebHelper/DebuggerPort, default 8087). User settings live in
|
||||
# ~/.config/openvr/config/steamvr.vrsettings, which SteamVR rewrites at
|
||||
# runtime and on exit (from memory), so it can't be a read-only store link,
|
||||
# and editing it while SteamVR runs would be overwritten.
|
||||
# steamvr-webhelper-debugger.service merges just that key with jq (atomic
|
||||
# write, other keys untouched, file created if missing), before every start
|
||||
# of steamvr.service (SteamVR's systemd user unit): a drop-in makes it
|
||||
# Want + start After the oneshot. (Its own ExecStartPre= chain already starts
|
||||
# vrserver, so an added ExecStartPre= would run too late.) Hence the setting
|
||||
# takes effect with the next SteamVR start, once.
|
||||
#
|
||||
# The service is installed even when disabled: if this module set the key
|
||||
# before (marker in $XDG_STATE_HOME/steam-frame-nix), it sets it back to
|
||||
# false at the next SteamVR start and removes the marker; otherwise it
|
||||
# leaves the file alone (a setting made by hand is kept).
|
||||
#
|
||||
# Security: the port listens on 127.0.0.1 only; Steam's Developer Mode makes
|
||||
# SteamOS forward it to 0.0.0.0:8088 (README, "DevTools on the LAN"), so keep
|
||||
# Developer Mode off. Our patches only use 127.0.0.1.
|
||||
# The port opens only with VRWebHelper/DebuggerEnabled (requires a SteamVR
|
||||
# restart). steamvr.vrsettings is rewritten by SteamVR from memory, so it
|
||||
# can't be a store link or be edited while SteamVR runs: a oneshot merges just
|
||||
# that key with jq before each steamvr.service start (drop-in Wants/After;
|
||||
# ExecStartPre= would be too late, vrserver starts in the unit's own chain).
|
||||
# Disabled, it resets the key only if it set it (marker in
|
||||
# $XDG_STATE_HOME/steam-frame-nix); a manual setting is kept.
|
||||
# Developer Mode forwards the port to 0.0.0.0:8088 (README, "DevTools on the
|
||||
# LAN"); our patches use 127.0.0.1 only.
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.steamFrame.steamvrDebugger;
|
||||
@@ -73,15 +60,11 @@ in {
|
||||
default = false;
|
||||
defaultText = lib.literalMD "on automatically when a dashboard patch (a `steamFrame.uiPatches.patches` entry on port 8087) is enabled";
|
||||
description = ''
|
||||
Enable SteamVR's web helper debugger (DevTools of the SteamVR dashboard
|
||||
on 127.0.0.1:8087, setting VRWebHelper/DebuggerEnabled in
|
||||
~/.config/openvr/config/steamvr.vrsettings), needed by patches of the
|
||||
SteamVR dashboard. Set before each SteamVR start, so it takes effect
|
||||
after SteamVR is restarted once. Turning it off sets the key back to
|
||||
false at the next SteamVR start. Normally there is no need to set it:
|
||||
it is turned on automatically when a dashboard patch is enabled. The
|
||||
port listens on 127.0.0.1; keep Steam's Developer Mode off, which would
|
||||
also forward it to the LAN (0.0.0.0:8088).
|
||||
SteamVR's web helper debugger (dashboard DevTools on 127.0.0.1:8087,
|
||||
VRWebHelper/DebuggerEnabled in steamvr.vrsettings), needed by dashboard
|
||||
patches, which turn it on automatically. Takes effect after one SteamVR
|
||||
restart; off resets the key at the next start. Developer Mode also
|
||||
forwards the port to the LAN (0.0.0.0:8088).
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -100,8 +83,7 @@ in {
|
||||
};
|
||||
};
|
||||
|
||||
# Wants= (not Requires=): if the merge fails (e.g. broken JSON), SteamVR
|
||||
# still starts, just without the debugger.
|
||||
# Wants=, not Requires=: SteamVR still starts if the merge fails.
|
||||
xdg.configFile."systemd/user/steamvr.service.d/webhelper-debugger.conf".text = ''
|
||||
[Unit]
|
||||
Wants=steamvr-webhelper-debugger.service
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
# Adjustable curvature per SteamVR dashboard window
|
||||
# (steamFrame.dashboard.windowCurvature): the "Toggle Curvature" control of a
|
||||
# window (row of its More Options menu, or its bottom-bar button when moved
|
||||
# there) becomes a wheel (click: toggle, drag up/down: curvature, with
|
||||
# controller haptics). Runtime patch of SteamVR's dashboard page (vrwebhelper
|
||||
# "systemui", DevTools 127.0.0.1:8087; see window-curvature/patch.js for how
|
||||
# it works), registered with steam-ui-patches.nix only when enabled; it turns
|
||||
# on the SteamVR web helper debugger (steamvr-debugger.nix), which needs one
|
||||
# SteamVR restart the first time. Depends on SteamVR UI internals, found by
|
||||
# signature (lib/signatures.json, "window-curvature";
|
||||
# scripts/check-signatures.mjs checks them offline).
|
||||
# Adjustable curvature per dashboard window. Dashboard patch
|
||||
# (window-curvature/patch.js; "systemui" on 127.0.0.1:8087), registered only
|
||||
# when enabled; enables steamvr-debugger.nix (one SteamVR restart the first time).
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.steamFrame.dashboard.windowCurvature;
|
||||
@@ -24,29 +16,20 @@ in {
|
||||
|
||||
options.steamFrame.dashboard.windowCurvature = {
|
||||
enable = lib.mkEnableOption ''
|
||||
adjustable curvature per SteamVR dashboard window: the "Toggle
|
||||
Curvature" row of a window's More Options (three-dot) menu shows the
|
||||
window's curvature and becomes a control, and so does its button in
|
||||
the window's bottom bar when it sits there (no value shown; steps and
|
||||
snap points are felt as haptics). Click: curved → flat, flat → stock
|
||||
curve. Press and drag up/down with the laser: set the curvature
|
||||
live. Values are relative to SteamVR's stock curve (1 = stock, 2 = twice
|
||||
as curved, i.e. half the radius, 0 = flat) and kept per window until
|
||||
SteamVR restarts. Runtime patch of the SteamVR dashboard
|
||||
(steamFrame.uiPatches), applied immediately; turning it off restores the
|
||||
stock menu and radius (next switch)'';
|
||||
adjustable curvature per SteamVR dashboard window via its "Toggle
|
||||
Curvature" menu row (shows the value) or bar button: click toggles
|
||||
curved/flat, drag up/down sets it live. Values are relative to the stock
|
||||
curve (1 = stock, 2 = half the radius, 0 = flat), kept per window until
|
||||
SteamVR restarts. Dashboard patch; off restores stock (next switch)'';
|
||||
default = value 1.0 ''
|
||||
Curvature of windows placed in the world or on a hand that have no value
|
||||
of their own yet, once curved (stock SteamVR shows them flat; the
|
||||
toggle turns them on). Windows docked in the dashboard or in the theater
|
||||
start at 1 (stock), so the docked Steam window stays concentric with the
|
||||
dashboard bar.
|
||||
Curvature a world/hand window (stock: flat) gets when first curved.
|
||||
Dashboard and theater windows start at 1, keeping the docked Steam
|
||||
window concentric with the bar.
|
||||
'';
|
||||
max = value 3.0 "Largest curvature the control goes to (relative to the stock curve).";
|
||||
step = value 0.05 "Step the value is rounded to while dragging.";
|
||||
snap = value 0.15 ''
|
||||
While dragging, values within ± this distance of a snap point snap to
|
||||
it exactly; dragging on moves past. 0 = no snapping.
|
||||
Snap distance around snap points while dragging; 0 = no snapping.
|
||||
'';
|
||||
snapPoints = mkOption {
|
||||
type = types.listOf types.number;
|
||||
@@ -57,34 +40,29 @@ in {
|
||||
type = types.ints.unsigned;
|
||||
default = 8;
|
||||
description = ''
|
||||
Vertical laser travel (menu pixels) before a press on the row becomes
|
||||
a drag instead of a click.
|
||||
Vertical laser travel (menu px) that turns a press into a drag.
|
||||
'';
|
||||
};
|
||||
dragPixelsPerUnit = value 60 ''
|
||||
Drag distance (menu pixels) per 1.0 of curvature. The laser's position
|
||||
stops at the menu's edge (about 190 px above the row), so 0 to `max`
|
||||
should fit into that.
|
||||
Menu pixels per 1.0 of curvature. The laser stops at the menu's edge
|
||||
(~190 px above the row), so 0 to `max` should fit.
|
||||
'';
|
||||
barDragPixelsPerUnit = value 30 ''
|
||||
Drag distance (bar pixels) per 1.0 of curvature on the bottom-bar
|
||||
button (when the control sits in the bar).
|
||||
Bar pixels per 1.0 of curvature on the bottom-bar button.
|
||||
'';
|
||||
barDragRoom = mkOption {
|
||||
type = types.ints.unsigned;
|
||||
default = 160;
|
||||
description = ''
|
||||
Transparent room (pixels) added above and below a window's bottom bar
|
||||
while its curvature button is dragged, so the laser stays on the bar
|
||||
panel (its position stops at the pressed panel's edge). 0 = none.
|
||||
Transparent room (px) added above and below the bar while its button
|
||||
is dragged, so the laser stays on the panel; 0 = none.
|
||||
'';
|
||||
};
|
||||
haptics = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
Controller haptics while dragging: a snap at snap points, a stronger
|
||||
edge at 0 and `max`, a light tick for other steps.
|
||||
Controller haptics while dragging (snap points, 0/`max` edges, steps).
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user