mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 02:00:13 +02:00
The Flatpak sandbox doesn't see /nix, so the linked user.js dangled and Firefox never read it (vrFullscreenFix had no effect). The copy starts with a marker line, so the module still recognises its own file.
121 lines
5.4 KiB
Nix
121 lines
5.4 KiB
Nix
# 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 written into each profile on switch
|
|
# (a copy: /nix isn't visible in the Flatpak sandbox, a store link dangles).
|
|
# - 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 fullscreen fix: fullscreen works there).
|
|
# - prefs: about:config values for every profile, desktop one included.
|
|
# 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;
|
|
marker = "// Managed by steam-frame-nix (steamFrame.firefox); rewritten on switch.";
|
|
toUserJs = name: prefs: pkgs.writeText name (marker + "\n" + lib.concatStrings (lib.mapAttrsToList
|
|
(k: v: "user_pref(${builtins.toJSON k}, ${builtins.toJSON v});\n") prefs));
|
|
vrPrefs = cfg.prefs // lib.optionalAttrs cfg.vrFullscreenFix { "full-screen-api.ignore-widgets" = true; };
|
|
userJs = toUserJs "firefox-user.js" vrPrefs;
|
|
desktopUserJs = toUserJs "firefox-desktop-user.js" cfg.prefs;
|
|
ffDir = "$HOME/.var/app/org.mozilla.firefox/config/mozilla/firefox";
|
|
profileDir = "${ffDir}/${cfg.desktopProfile}";
|
|
# user.js for a profile dir ($prof): desktop profile -> prefs only.
|
|
pickUserJs = if cfg.desktopProfile == null then "js=${userJs}" else ''
|
|
js=${userJs}
|
|
[ "$(basename "$prof")" = ${lib.escapeShellArg cfg.desktopProfile} ] && js=${desktopUserJs}
|
|
'';
|
|
|
|
firefox = pkgs.writeShellScript "firefox-launcher" (''
|
|
profile=()
|
|
'' + lib.optionalString (cfg.desktopProfile != null) ''
|
|
if [ "$XDG_CURRENT_DESKTOP" = KDE ]; then
|
|
# Firefox exits (status 1) if the --profile dir doesn't exist yet.
|
|
mkdir -p "${profileDir}"
|
|
profile=(--profile "${profileDir}")
|
|
fi
|
|
'' + ''
|
|
exec /usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox \
|
|
--file-forwarding org.mozilla.firefox "''${profile[@]}" "$@"
|
|
'');
|
|
in {
|
|
options.steamFrame.firefox = {
|
|
enable = lib.mkEnableOption ''
|
|
the Firefox Flatpak (org.mozilla.firefox) launcher with Steam Frame
|
|
fixes'';
|
|
vrFullscreenFix = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = ''
|
|
Set full-screen-api.ignore-widgets in every profile except the
|
|
desktop one, so fullscreen fills the window instead of freezing in the
|
|
Steam session.
|
|
'';
|
|
};
|
|
prefs = lib.mkOption {
|
|
type = with lib.types; attrsOf (oneOf [ bool int str ]);
|
|
default = { };
|
|
example = { "media.av1.enabled" = false; };
|
|
description = ''
|
|
about:config preferences for every profile (desktop one included),
|
|
set through a linked user.js on each switch. E.g. media.av1.enabled =
|
|
false: the Frame's decoder has no AV1, so sites like YouTube fall back
|
|
to VP9/H.264, which it decodes in hardware.
|
|
'';
|
|
};
|
|
desktopProfile = lib.mkOption {
|
|
type = lib.types.nullOr lib.types.str;
|
|
default = "desktop";
|
|
description = ''
|
|
Profile used in the nested desktop, so both sessions can run Firefox at
|
|
once; null = default profile in both.
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
# Written into every existing profile (profile names are random); a
|
|
# user.js with no prefs is harmless and keeps turning prefs off revertible.
|
|
# Ours: a symlink (older versions) or a file starting with the marker.
|
|
home.activation.firefoxUserJs =
|
|
(lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
|
for prof in "${ffDir}"/*/; do
|
|
[ -f "$prof/prefs.js" ] || continue # only real profiles
|
|
${pickUserJs}
|
|
target="$prof/user.js"
|
|
if [ -e "$target" ] && [ ! -L "$target" ] && [ "$(head -n1 "$target")" != ${lib.escapeShellArg marker} ]; then
|
|
echo "firefox: skipping $target (not managed by us, move it away to adopt)"
|
|
continue
|
|
fi
|
|
cmp -s "$js" "$target" && [ ! -L "$target" ] && continue
|
|
run rm -f "$target"
|
|
run install -m644 "$js" "$target"
|
|
done
|
|
'');
|
|
|
|
xdg.dataFile."applications/org.mozilla.firefox.desktop".text = ''
|
|
[Desktop Entry]
|
|
Type=Application
|
|
Name=Firefox
|
|
GenericName=Web Browser
|
|
Icon=org.mozilla.firefox
|
|
Exec=${firefox} @@u %u @@
|
|
StartupWMClass=firefox
|
|
StartupNotify=true
|
|
Terminal=false
|
|
Categories=Network;WebBrowser;
|
|
MimeType=application/json;application/pdf;application/rdf+xml;application/rss+xml;application/x-xpinstall;application/xhtml+xml;application/xml;audio/flac;audio/ogg;audio/webm;image/avif;image/gif;image/jpeg;image/png;image/svg+xml;image/webp;text/html;text/xml;video/ogg;video/webm;x-scheme-handler/chrome;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/mailto;
|
|
Actions=new-window;new-private-window;
|
|
|
|
[Desktop Action new-window]
|
|
Name=New Window
|
|
Exec=${firefox} --new-window @@u %u @@
|
|
|
|
[Desktop Action new-private-window]
|
|
Name=New Private Window
|
|
Exec=${firefox} --private-window @@u %u @@
|
|
'';
|
|
};
|
|
}
|