mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 04:04:16 +02:00
Portal: KDE file dialog for Flatpak apps in the Steam session
Neither Valve backend (gamescope, holo) implements FileChooser, so sandboxed apps fell back to an in-sandbox dialog without the home dir (e.g. Element's Attachments). session.portalFix.fileChooser (on) links kde.portal into the Steam session's portal dir and selects kde for FileChooser; xdg-desktop-portal-kde is D-Bus activated with DISPLAY=:0. Flake check for the portal config.
This commit is contained in:
1 parent
356dcb9012
commit
50e5991c59
6 files changed
+92
-17
No files matched your search
@@ -26,7 +26,7 @@ configuration, limitations and how it works.
|
|||||||
**Session** ([docs/session.md](docs/session.md)):
|
**Session** ([docs/session.md](docs/session.md)):
|
||||||
|
|
||||||
- [Session settings](docs/session.md#session-settings-and-services) (`session.*`): outer bus and user services, for launchers and the other modules.
|
- [Session settings](docs/session.md#session-settings-and-services) (`session.*`): outer bus and user services, for launchers and the other modules.
|
||||||
- [Portal fix](docs/session.md#portal-fix) (`session.portalFix`, on): apps in the Steam session can open links.
|
- [Portal fix](docs/session.md#portal-fix) (`session.portalFix`, on): apps in the Steam session can open links, and Flatpak apps get KDE's file dialog.
|
||||||
- [Applications menu](docs/session.md#applications-menu) (`session.applicationsMenu`, on): KDE apps in the Steam session (Dolphin from the "+" menu) know the installed apps.
|
- [Applications menu](docs/session.md#applications-menu) (`session.applicationsMenu`, on): KDE apps in the Steam session (Dolphin from the "+" menu) know the installed apps.
|
||||||
- [Keyboard layout](docs/session.md#keyboard-layout) (`keyboard.layout`, `keyboard.variant`): XKB layout for the Steam session.
|
- [Keyboard layout](docs/session.md#keyboard-layout) (`keyboard.layout`, `keyboard.variant`): XKB layout for the Steam session.
|
||||||
- [Clipboard sync](docs/session.md#clipboard-sync) (`clipboardSync`, on): one clipboard for the Steam session and the nested desktop.
|
- [Clipboard sync](docs/session.md#clipboard-sync) (`clipboardSync`, on): one clipboard for the Steam session and the nested desktop.
|
||||||
@@ -232,6 +232,7 @@ which: [Repository layout](docs/development.md).
|
|||||||
| `steamFrame.session.services.restart` | list of str | `[ ]` | User units restarted on every switch. |
|
| `steamFrame.session.services.restart` | list of str | `[ ]` | User units restarted on every switch. |
|
||||||
| `steamFrame.session.services.stop` | list of str | `[ ]` | User units stopped on switch if running (e.g. of a disabled feature). |
|
| `steamFrame.session.services.stop` | list of str | `[ ]` | User units stopped on switch if running (e.g. of a disabled feature). |
|
||||||
| `steamFrame.session.portalFix.enable` | bool | `true` | Working portal config (OpenURI) for the Steam session. |
|
| `steamFrame.session.portalFix.enable` | bool | `true` | Working portal config (OpenURI) for the Steam session. |
|
||||||
|
| `steamFrame.session.portalFix.fileChooser` | bool | `true` | KDE's file dialog as the Steam session's FileChooser portal (Flatpak apps can open and save files outside their sandbox). Needs `portalFix.enable`. |
|
||||||
| `steamFrame.session.applicationsMenu.enable` | bool | `true` | `~/.config/menus/applications.menu` linked to Plasma's, for KDE apps in the Steam session. |
|
| `steamFrame.session.applicationsMenu.enable` | bool | `true` | `~/.config/menus/applications.menu` linked to Plasma's, for KDE apps in the Steam session. |
|
||||||
| `steamFrame.keyboard.layout` | null or str | `null` | XKB layout for the Steam session, e.g. `"de"`; `null`: US. |
|
| `steamFrame.keyboard.layout` | null or str | `null` | XKB layout for the Steam session, e.g. `"de"`; `null`: US. |
|
||||||
| `steamFrame.keyboard.variant` | null or str | `null` | XKB variant for the Steam session, e.g. `"nodeadkeys"`; see [Keyboard layout](docs/session.md#keyboard-layout). |
|
| `steamFrame.keyboard.variant` | null or str | `null` | XKB variant for the Steam session, e.g. `"nodeadkeys"`; see [Keyboard layout](docs/session.md#keyboard-layout). |
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ modules/
|
|||||||
cleanup/package.nix build: install.sh as a command (cleanup, steamvr-debugger-arm)
|
cleanup/package.nix build: install.sh as a command (cleanup, steamvr-debugger-arm)
|
||||||
cleanup/check.nix test: install.sh cleanup on fake home/runtime dirs
|
cleanup/check.nix test: install.sh cleanup on fake home/runtime dirs
|
||||||
portal.nix Steam session portal config (session.portalFix)
|
portal.nix Steam session portal config (session.portalFix)
|
||||||
|
portal/check.nix test: KDE FileChooser on by default, absent when disabled
|
||||||
applications-menu.nix applications.menu link for KDE apps (session.applicationsMenu)
|
applications-menu.nix applications.menu link for KDE apps (session.applicationsMenu)
|
||||||
applications-menu/check.nix test: the link on by default, absent when disabled
|
applications-menu/check.nix test: the link on by default, absent when disabled
|
||||||
keyboard-layout.nix gamescope-session drop-in with XKB_DEFAULT_* (keyboard.layout)
|
keyboard-layout.nix gamescope-session drop-in with XKB_DEFAULT_* (keyboard.layout)
|
||||||
|
|||||||
+22
-6
@@ -40,21 +40,37 @@ launcher's `hostEnv`; a hand-written entry uses the prefix `session.busEnv`:
|
|||||||
|
|
||||||
## Portal fix
|
## Portal fix
|
||||||
|
|
||||||
`session.portalFix.enable`, module `portal`. On by default.
|
`session.portalFix.enable` and `session.portalFix.fileChooser`, module
|
||||||
|
`portal`. Both on by default.
|
||||||
|
|
||||||
**Problem:** the Frame image (SteamOS 0.3.0, build 20260922) points the Steam
|
**Problem:** the Frame image (SteamOS 0.3.0, build 20260922) points the Steam
|
||||||
session's `xdg-desktop-portal` at `/usr/share/xdg-desktop-portal/gamescope-portals`,
|
session's `xdg-desktop-portal` at `/usr/share/xdg-desktop-portal/gamescope-portals`,
|
||||||
which lacks `gamescope-portals.conf`: no backend, no OpenURI, so no app in
|
which lacks `gamescope-portals.conf`: no backend, no OpenURI, so no app in
|
||||||
the Steam session can open links.
|
the Steam session can open links. Its two backends (gamescope, holo) also
|
||||||
|
have no FileChooser, so Flatpak apps fall back to a dialog inside their
|
||||||
|
sandbox: e.g. Element's Attachments shows an empty file selector without
|
||||||
|
your home dir.
|
||||||
|
|
||||||
**What you get:** a working OpenURI portal in the Steam session; the
|
**What you get:** a working OpenURI portal in the Steam session and, with
|
||||||
desktop's portal is unaffected.
|
`fileChooser`, KDE's file dialog there (a normal window in VR) with access
|
||||||
|
to all your files; the app gets only the files you pick. The desktop's
|
||||||
|
portal is unaffected.
|
||||||
|
|
||||||
**Remove when** SteamOS ships `gamescope-portals.conf`.
|
**Configuration:** takes effect when the portal restarts (next Steam session
|
||||||
|
start, or `systemctl --user restart xdg-desktop-portal`) and the app
|
||||||
|
restarts (Electron apps check for the portal at startup). To keep the old
|
||||||
|
dialog: `steamFrame.session.portalFix.fileChooser = false;`.
|
||||||
|
|
||||||
|
**Remove when** SteamOS ships `gamescope-portals.conf` (and a FileChooser
|
||||||
|
backend, for `fileChooser`).
|
||||||
|
|
||||||
**How it works:** a portal dir in `~/.local/share` linking Valve's `.portal`
|
**How it works:** a portal dir in `~/.local/share` linking Valve's `.portal`
|
||||||
files plus a config (`default=holo;gamescope`), and a drop-in on
|
files plus a config (`default=holo;gamescope`), and a drop-in on
|
||||||
`xdg-desktop-portal.service`.
|
`xdg-desktop-portal.service`. `fileChooser` adds a link to
|
||||||
|
`/usr/share/xdg-desktop-portal/portals/kde.portal` and
|
||||||
|
`org.freedesktop.impl.portal.FileChooser=kde`; the preinstalled
|
||||||
|
`xdg-desktop-portal-kde` starts on demand (D-Bus activation) with the Steam
|
||||||
|
session's `DISPLAY=:0`.
|
||||||
|
|
||||||
## Applications menu
|
## Applications menu
|
||||||
|
|
||||||
|
|||||||
@@ -66,14 +66,15 @@
|
|||||||
|
|
||||||
# Tests of the VR keyboard (text model, corrector, swipe decoder on the
|
# Tests of the VR keyboard (text model, corrector, swipe decoder on the
|
||||||
# default German + English dictionary), the Jellyfin mpv shim, the
|
# default German + English dictionary), the Jellyfin mpv shim, the
|
||||||
# Firefox wrapper, the launchers, install.sh cleanup and the
|
# Firefox wrapper, the launchers, install.sh cleanup, the
|
||||||
# applications.menu link: nix flake check
|
# applications.menu link and the portal config: nix flake check
|
||||||
checks = forSystems (pkgs: {
|
checks = forSystems (pkgs: {
|
||||||
applications-menu = import ./modules/applications-menu/check.nix { inherit pkgs; };
|
applications-menu = import ./modules/applications-menu/check.nix { inherit pkgs; };
|
||||||
cleanup = import ./modules/cleanup/check.nix { inherit pkgs; };
|
cleanup = import ./modules/cleanup/check.nix { inherit pkgs; };
|
||||||
firefox = import ./modules/firefox/check.nix { inherit pkgs; };
|
firefox = import ./modules/firefox/check.nix { inherit pkgs; };
|
||||||
jellyfin = import ./modules/jellyfin/check.nix { inherit pkgs; };
|
jellyfin = import ./modules/jellyfin/check.nix { inherit pkgs; };
|
||||||
launchers = import ./modules/launchers/check.nix { inherit pkgs; };
|
launchers = import ./modules/launchers/check.nix { inherit pkgs; };
|
||||||
|
portal = import ./modules/portal/check.nix { inherit pkgs; };
|
||||||
vr-keyboard = import ./modules/vr-keyboard/check.nix { inherit pkgs; };
|
vr-keyboard = import ./modules/vr-keyboard/check.nix { inherit pkgs; };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+28
-8
@@ -3,8 +3,11 @@
|
|||||||
# gamescope-portals.conf, so no backend is selected and there is no OpenURI
|
# 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
|
# (links don't open). We point it at our own dir: Valve's .portal files + a
|
||||||
# config. Remove once SteamOS ships the .conf.
|
# config. Remove once SteamOS ships the .conf.
|
||||||
|
# Neither Valve backend has a FileChooser, so sandboxed apps fall back to an
|
||||||
|
# in-sandbox dialog that can't see home; fileChooser adds KDE's for it.
|
||||||
{ config, lib, ... }:
|
{ config, lib, ... }:
|
||||||
let
|
let
|
||||||
|
cfg = config.steamFrame.session.portalFix;
|
||||||
sys = "/usr/share/xdg-desktop-portal/gamescope-portals";
|
sys = "/usr/share/xdg-desktop-portal/gamescope-portals";
|
||||||
dir = "xdg-desktop-portal/gamescope-portals";
|
dir = "xdg-desktop-portal/gamescope-portals";
|
||||||
in {
|
in {
|
||||||
@@ -15,23 +18,40 @@ in {
|
|||||||
[ "steamFrame" "session" "portalFix" "enable" ])
|
[ "steamFrame" "session" "portalFix" "enable" ])
|
||||||
];
|
];
|
||||||
|
|
||||||
options.steamFrame.session.portalFix.enable = lib.mkOption {
|
options.steamFrame.session.portalFix = {
|
||||||
type = lib.types.bool;
|
enable = lib.mkOption {
|
||||||
default = true;
|
type = lib.types.bool;
|
||||||
description = ''
|
default = true;
|
||||||
Give the Steam session's xdg-desktop-portal a config so apps there can
|
description = ''
|
||||||
open links (OpenURI).
|
Give the Steam session's xdg-desktop-portal a config so apps there can
|
||||||
'';
|
open links (OpenURI).
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
fileChooser = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = ''
|
||||||
|
Use KDE's file dialog (xdg-desktop-portal-kde) as the Steam session's
|
||||||
|
FileChooser portal, so sandboxed apps (Flatpak) can open and save
|
||||||
|
files outside their sandbox. Needs `enable`.
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf config.steamFrame.session.portalFix.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
xdg.dataFile."${dir}/holo.portal".source =
|
xdg.dataFile."${dir}/holo.portal".source =
|
||||||
config.lib.file.mkOutOfStoreSymlink "${sys}/holo.portal";
|
config.lib.file.mkOutOfStoreSymlink "${sys}/holo.portal";
|
||||||
xdg.dataFile."${dir}/gamescope.portal".source =
|
xdg.dataFile."${dir}/gamescope.portal".source =
|
||||||
config.lib.file.mkOutOfStoreSymlink "${sys}/gamescope.portal";
|
config.lib.file.mkOutOfStoreSymlink "${sys}/gamescope.portal";
|
||||||
|
xdg.dataFile."${dir}/kde.portal" = lib.mkIf cfg.fileChooser {
|
||||||
|
source = config.lib.file.mkOutOfStoreSymlink
|
||||||
|
"/usr/share/xdg-desktop-portal/portals/kde.portal";
|
||||||
|
};
|
||||||
xdg.dataFile."${dir}/gamescope-portals.conf".text = ''
|
xdg.dataFile."${dir}/gamescope-portals.conf".text = ''
|
||||||
[preferred]
|
[preferred]
|
||||||
default=holo;gamescope
|
default=holo;gamescope
|
||||||
|
'' + lib.optionalString cfg.fileChooser ''
|
||||||
|
org.freedesktop.impl.portal.FileChooser=kde
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Outer (systemd) portal only; the nested desktop's keeps kde-portals.conf.
|
# Outer (systemd) portal only; the nested desktop's keeps kde-portals.conf.
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# Evaluates the portal module against a stub of Home Manager's options: on by
|
||||||
|
# default the Steam session's portal config picks KDE's FileChooser, with
|
||||||
|
# `fileChooser = false` it has neither the kde.portal link nor that line.
|
||||||
|
{ pkgs }:
|
||||||
|
let
|
||||||
|
inherit (pkgs) lib;
|
||||||
|
dir = "xdg-desktop-portal/gamescope-portals";
|
||||||
|
eval = cfg: (lib.evalModules {
|
||||||
|
modules = [
|
||||||
|
../portal.nix
|
||||||
|
{
|
||||||
|
options.xdg.dataFile = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.attrsOf lib.types.anything);
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
options.lib = lib.mkOption { type = lib.types.attrsOf lib.types.anything; };
|
||||||
|
config = {
|
||||||
|
_module.check = false; # Home Manager options the stub doesn't declare
|
||||||
|
_module.args.pkgs = pkgs;
|
||||||
|
lib.file.mkOutOfStoreSymlink = p: "out-of-store:${p}";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
cfg
|
||||||
|
];
|
||||||
|
}).config.xdg.dataFile;
|
||||||
|
on = eval { };
|
||||||
|
off = eval { steamFrame.session.portalFix.fileChooser = false; };
|
||||||
|
kde = "org.freedesktop.impl.portal.FileChooser=kde";
|
||||||
|
in
|
||||||
|
assert on."${dir}/kde.portal".source
|
||||||
|
== "out-of-store:/usr/share/xdg-desktop-portal/portals/kde.portal";
|
||||||
|
assert lib.hasInfix kde on."${dir}/gamescope-portals.conf".text;
|
||||||
|
assert !(off ? "${dir}/kde.portal");
|
||||||
|
assert !(lib.hasInfix kde off."${dir}/gamescope-portals.conf".text);
|
||||||
|
assert off ? "${dir}/holo.portal";
|
||||||
|
pkgs.runCommand "portal-check" { } "touch $out"
|
||||||
Reference in new issue
Block a user