Applications menu for KDE apps in the Steam session

SteamOS only ships /etc/xdg/menus/plasma-applications.menu; the nested
desktop sets XDG_MENU_PREFIX=plasma-, the Steam session doesn't, so KDE
apps started there (Dolphin from the "+" menu) built an empty app
database: "no installed application can open" every file.

session.applicationsMenu (module applications-menu, on by default) links
~/.config/menus/applications.menu to Plasma's menu. Flake check: the link
is generated by default and absent when disabled.
This commit is contained in:
Pierre Kisters committed 2026-09-29 03:01:38 +02:00
1 parent 0d9a238e5a
commit 59513bcbb1
7 files changed
+103 -13

No files matched your search

+9 -7
View File
@@ -3,10 +3,10 @@
[Home Manager](https://github.com/nix-community/home-manager) modules for the
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).
(portal, KDE app menu, 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).
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
@@ -15,8 +15,8 @@ their lifetime and what removes them; `steam-frame-nix-cleanup` removes every
one of them (on each switch what the configuration no longer uses, `--all`
for everything).
All options live under `steamFrame.*`. The portal fix and clipboard sync are
on by default; everything else is opt-in.
All options live under `steamFrame.*`. The portal fix, the applications menu
and clipboard sync are on by default; everything else is opt-in.
## Features
@@ -27,6 +27,7 @@ configuration, limitations and how it works.
- [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.
- [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.
- [Clipboard sync](docs/session.md#clipboard-sync) (`clipboardSync`, on): one clipboard for the Steam session and the nested desktop.
@@ -214,7 +215,7 @@ home-manager switch --flake .#steamos # manual setup, from the flake's director
In your own flake, add the input as above and
`steam-frame-nix.homeManagerModules.default` to the modules. `default`
imports all modules; single ones:
`homeManagerModules.{session,portal,keyboard-layout,vr-keyboard-extra-keys,vr-keyboard,hidden-apps,steam-ui-patches,launcher-menu,steamvr-debugger,cleanup,dashboard-windows,steam-close-button,window-curvature,frame-controls,clipboard-sync,firefox,jellyfin,launchers,docker}`
`homeManagerModules.{session,portal,applications-menu,keyboard-layout,vr-keyboard-extra-keys,vr-keyboard,hidden-apps,steam-ui-patches,launcher-menu,steamvr-debugger,cleanup,dashboard-windows,steam-close-button,window-curvature,frame-controls,clipboard-sync,firefox,jellyfin,launchers,docker}`
(`steam-keyboard-patch` and `keyring` still work as the former names of
`vr-keyboard-extra-keys` and `launchers`). Every module imports `cleanup` (see
[Changes outside Nix](#changes-outside-nix-exceptions)); which file is
@@ -231,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.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.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.variant` | null or str | `null` | XKB variant for the Steam session, e.g. `"nodeadkeys"`; see [Keyboard layout](docs/session.md#keyboard-layout). |
| `steamFrame.keyboard.vr.extraKeys.enable` | bool | `false` | VR keyboard with Esc/Ctrl/Alt, arrows, real chords, AltGr/non-ASCII. |
+2
View File
@@ -50,6 +50,8 @@ modules/
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
portal.nix Steam session portal config (session.portalFix)
applications-menu.nix applications.menu link for KDE apps (session.applicationsMenu)
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)
clipboard-sync.nix app: KDE autostart of clipboard-sync (clipboardSync)
hidden-apps.nix Hidden=true desktop entries (launcherMenu.hiddenApps)
+28 -4
View File
@@ -1,9 +1,10 @@
# Session fixes
Four fixes for the Frame's [two graphical sessions](../README.md#two-sessions):
session settings and services, the portal, the keyboard layout and the
clipboard. Options: [README, Options](../README.md#options) (`session.*`,
`keyboard.layout`, `keyboard.variant`, `clipboardSync.*`).
Five fixes for the Frame's [two graphical sessions](../README.md#two-sessions):
session settings and services, the portal, the applications menu, the
keyboard layout and the clipboard. Options:
[README, Options](../README.md#options) (`session.*`, `keyboard.layout`,
`keyboard.variant`, `clipboardSync.*`).
## Session settings and services
@@ -55,6 +56,29 @@ desktop's portal is unaffected.
files plus a config (`default=holo;gamescope`), and a drop-in on
`xdg-desktop-portal.service`.
## Applications menu
`session.applicationsMenu.enable`, module `applications-menu`. On by default;
`false` turns it off.
**Problem:** KDE apps build their app database (ksycoca) from
`applications.menu`, but SteamOS only ships
`/etc/xdg/menus/plasma-applications.menu`. The nested desktop sets
`XDG_MENU_PREFIX=plasma-`, the Steam session doesn't: KDE apps started there
(e.g. Dolphin from the "+" menu) know no apps at all ("no installed
application can open …").
**What you get:** KDE apps in the Steam session see every installed app,
Flatpaks included, e.g. for "Open with". The nested desktop is unaffected (it
reads Plasma's menu through its prefix).
**Remove when** the Steam session sets `XDG_MENU_PREFIX` or SteamOS ships
`applications.menu`.
**How it works:** `~/.config/menus/applications.menu` is a Home Manager link
to `/etc/xdg/menus/plasma-applications.menu`. If SteamOS drops that file,
the link dangles, which is the same as no menu.
## Keyboard layout
`keyboard.layout`, `keyboard.variant`, module `keyboard-layout`.
+4 -1
View File
@@ -14,6 +14,7 @@
modules = {
session = ./modules/session.nix;
portal = ./modules/portal.nix;
applications-menu = ./modules/applications-menu.nix;
keyboard-layout = ./modules/keyboard-layout.nix;
vr-keyboard-extra-keys = ./modules/vr-keyboard-extra-keys.nix;
vr-keyboard = ./modules/vr-keyboard.nix;
@@ -65,8 +66,10 @@
# Tests of the VR keyboard (text model, corrector, swipe decoder on the
# default German + English dictionary), the Jellyfin mpv shim, the
# Firefox wrapper, the launchers and install.sh cleanup: nix flake check
# Firefox wrapper, the launchers, install.sh cleanup and the
# applications.menu link: nix flake check
checks = forSystems (pkgs: {
applications-menu = import ./modules/applications-menu/check.nix { inherit pkgs; };
cleanup = import ./modules/cleanup/check.nix { inherit pkgs; };
firefox = import ./modules/firefox/check.nix { inherit pkgs; };
jellyfin = import ./modules/jellyfin/check.nix { inherit pkgs; };
+27
View File
@@ -0,0 +1,27 @@
# Workaround (SteamOS 0.3.0, build 20260922): KDE apps build their app
# database (ksycoca) from "applications.menu", but SteamOS only ships
# /etc/xdg/menus/plasma-applications.menu. The nested desktop sets
# XDG_MENU_PREFIX=plasma-, the Steam session doesn't, so KDE apps started
# there (Dolphin from the "+" menu) know no apps. We link the user's
# applications.menu to Plasma's. A missing host file leaves a dangling link,
# which KDE treats like no file. Remove once the Steam session sets the prefix.
{ config, lib, ... }:
let
sys = "/etc/xdg/menus/plasma-applications.menu";
in {
imports = [ ./cleanup.nix ];
options.steamFrame.session.applicationsMenu.enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Link `~/.config/menus/applications.menu` to Plasma's menu, so KDE apps
in the Steam session find the installed apps.
'';
};
config = lib.mkIf config.steamFrame.session.applicationsMenu.enable {
xdg.configFile."menus/applications.menu".source =
config.lib.file.mkOutOfStoreSymlink sys;
};
}
+31
View File
@@ -0,0 +1,31 @@
# Evaluates the applications-menu module against a stub of Home Manager's
# options: on by default the link to Plasma's menu is generated, disabled it
# is absent.
{ pkgs }:
let
inherit (pkgs) lib;
eval = cfg: (lib.evalModules {
modules = [
../applications-menu.nix
{
options.xdg.configFile = 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.configFile;
on = eval { };
off = eval { steamFrame.session.applicationsMenu.enable = false; };
in
assert on."menus/applications.menu".source
== "out-of-store:/etc/xdg/menus/plasma-applications.menu";
assert !(off ? "menus/applications.menu");
pkgs.runCommand "applications-menu-check" { } "touch $out"
+2 -1
View File
@@ -13,7 +13,8 @@
# home.packages = with pkgs; [ htop ripgrep ];
# Steam Frame fixes, see https://github.com/lhns/steam-frame-nix
# (session.portalFix and clipboardSync are on by default).
# (session.portalFix, session.applicationsMenu and clipboardSync are on
# by default).
# steamFrame = {
# keyboard.layout = "de"; # XKB layout, Steam session
# keyboard.vr.extraKeys.enable = true; # Esc/Ctrl/Alt/arrows in VR