Launchers: apps' own desktop entries, rewritten; keyring moves into them

steamFrame.launchers.<desktop ID> takes the app's own entry (a Flatpak's
export, a Nix package's or a host file) and rewrites only its command lines
(hostEnv, env, flatpakArgs, args, wrappers) and the keys asked for
(mimeTypes, defaultFor, settings), so name, icon, translations and actions
stay the app's and follow its updates.

- Package entries are rewritten at build time; Flatpak/host file entries at
  runtime by steam-frame-nix-launchers into
  <session.runtimeDir>/steam-frame-nix/applications (tmpfs), on switch, at
  login and when Flatpak installs/updates apps (path unit); the Home Manager
  links point there.
- keyring.{enable,electron} replaces steamFrame.keyring.{flatpaks,programs}
  (clean break: the old options fail with the new form).
- Firefox's launcher is the Flatpak's entry with the profile wrapper in
  front (no --profile for the profile manager); Jellyfin's hardware
  decoding sets flatpakArgs and env.
- cleanup --all removes the tmpfs entries.
- Check on copies of the real Element, KRDC, Firefox, gedit, Jellyfin and
  Claude entries, quoting and generator behaviour.
This commit is contained in:
Pierre Kisters committed 2026-09-29 02:05:06 +02:00
1 parent 5d15902ba1
commit 0d9a238e5a
37 files changed
+4140 -577

No files matched your search

+36 -30
View File
@@ -52,7 +52,7 @@ configuration, limitations and how it works.
- [Firefox](docs/firefox.md) (`firefox`): launcher for the Flatpak with a VR fullscreen fix, optional AV1 off, a separate desktop profile, optionally the default browser.
- [Jellyfin](docs/jellyfin.md) (`jellyfin.hardwareDecoding`): hardware video decoding in the Jellyfin Desktop Flatpak.
- [Keyring launchers](docs/keyring.md) (`keyring.flatpaks`, `keyring.programs`): apps (Flatpak or Nix, Electron too) keep their KDE wallet logins in both sessions.
- [Launchers](docs/launchers.md) (`launchers.<desktop ID>`): an app's own desktop entry (Flatpak, Nix package) with extra options, environment, wrappers and MIME defaults; `keyring` keeps its KDE wallet logins in both sessions (Electron too).
- [Docker](docs/docker.md) (`docker`): rootless Docker as a user service, CLI working in both sessions.
**Your own patches** of Steam's UI, and fixing patches after a Steam update: [UI patches](docs/ui-patches.md).
@@ -115,10 +115,10 @@ What this means for you:
([session settings](docs/session.md#session-settings-and-services)).
- **Wallet:** there should be one `kwalletd6`, on the outer bus; apps started
from the desktop would otherwise start a second one whose secrets VR can't
see. List such apps in [keyring](docs/keyring.md).
see. Give such apps a [launcher](docs/launchers.md) with `keyring.enable`.
- **Launchers:** the "+" menu only sees `~/.local/share/applications` (not
`~/.nix-profile/share`), so entries are written there, shadowing
Flatpak/package entries with the same ID.
`~/.nix-profile/share`), so [launchers](docs/launchers.md) are linked
there, replacing Flatpak/package entries with the same ID.
- **Keyboard layout, clipboard, Firefox:** each session has its own; see
[keyboard layout](docs/session.md#keyboard-layout),
[clipboard sync](docs/session.md#clipboard-sync),
@@ -195,10 +195,9 @@ these two files ([`template/`](template), with more comments):
firefox.disableAv1 = true;
firefox.defaultBrowser = true;
jellyfin.hardwareDecoding.enable = true; # install the Flatpak yourself
keyring.flatpaks."im.riot.Riot" = { # Element: logins in both sessions
name = "Element";
electron = true;
schemeHandlers = [ "element" "io.element.desktop" ];
launchers."im.riot.Riot" = { # Element: logins in both sessions
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
};
docker.enable = true; # rootless
};
@@ -215,9 +214,9 @@ 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,keyring,docker}`
(`steam-keyboard-patch` still works as the former name of
`vr-keyboard-extra-keys`). Every module imports `cleanup` (see
`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}`
(`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
which: [Repository layout](docs/development.md).
@@ -227,7 +226,7 @@ which: [Repository layout](docs/development.md).
|---|---|---|---|
| `steamFrame.session.runtimeDir` | str | `"/run/user/1000"` | `XDG_RUNTIME_DIR` of the outer (Steam/VR) session. |
| `steamFrame.session.bus` | str | `"unix:path=${runtimeDir}/bus"` | Outer session D-Bus (user manager, `kwalletd6`). |
| `steamFrame.session.busEnv` | str, read-only | `"env DBUS_SESSION_BUS_ADDRESS=${bus}"` | Prefix for launchers that must use the outer bus. |
| `steamFrame.session.busEnv` | str, read-only | `"env DBUS_SESSION_BUS_ADDRESS=${bus}"` | `Exec=` prefix for hand-written entries that must use the outer bus. |
| `steamFrame.session.services.start` | list of str | `[ ]` | User units started on switch if not running. |
| `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). |
@@ -306,22 +305,21 @@ which: [Repository layout](docs/development.md).
| `steamFrame.jellyfin.hardwareDecoding.enable` | bool | `false` | Hardware video decoding in the Jellyfin Desktop Flatpak, see [Jellyfin](docs/jellyfin.md). |
| `steamFrame.jellyfin.hardwareDecoding.hwdec` | str | `"v4l2m2m-copy,auto-copy"` | mpv `hwdec` used instead of Jellyfin's automatic one. |
| `steamFrame.jellyfin.hardwareDecoding.command` | str, read-only | | The `flatpak run …` command line of the desktop entry, for a terminal. |
| `steamFrame.keyring.flatpaks` | attrs of submodules | `{ }` | Flatpaks by app ID getting a wallet launcher (outer bus, wallet D-Bus names), see [Keyring launchers](docs/keyring.md). Fields below. |
| `steamFrame.keyring.programs` | attrs of submodules | `{ }` | Other programs by desktop ID (without `.desktop`) getting a wallet launcher (outer bus). Fields below. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.name` | str | required | `Name=`. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.genericName`, `.comment`, `.startupWMClass` | null or str | `null` | `GenericName=`, `Comment=`, `StartupWMClass=`. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.icon` | null or str | flatpaks: the app ID; programs: `null` | `Icon=`. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.categories` | list of str | `[ ]` | `Categories=`. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.schemeHandlers` | list of str | `[ ]` | URL schemes (e.g. login callbacks) the app handles and is made the default and recommended handler for. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.mimeTypes` | list of str | `[ ]` | Further `MimeType=` entries, not made default. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.electron` | bool | `false` | Pass `--password-store=kwallet6` (Electron apps). |
| `steamFrame.keyring.{flatpaks,programs}.<id>.args` | list of str | `[ ]` | Further app arguments (desktop entry syntax). |
| `steamFrame.keyring.{flatpaks,programs}.<id>.fieldCode` | `"%U"`, `"%u"`, `"%F"`, `"%f"`, `""` | `"%U"` | How the entry passes URLs/files. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.actions` | attrs of `{ name; args; }` | `{ }` | Desktop actions, each running the command with its args. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.settings` | attrs of str | `{ }` | Further `[Desktop Entry]` keys. |
| `steamFrame.keyring.{flatpaks,programs}.<id>.command` | str, read-only | | The command line without args, for a terminal. |
| `steamFrame.keyring.flatpaks.<id>.flatpakArgs` | list of str | `[ ]` | Further `flatpak run` options. |
| `steamFrame.keyring.programs.<id>.executable` | str | required | The program to run, e.g. `"${pkgs.claude-desktop}/bin/claude-desktop"`. |
| `steamFrame.launchers` | attrs of submodules | `{ }` | Launchers by desktop ID (without `.desktop`): the app's own entry, rewritten, see [Launchers](docs/launchers.md). Fields below. |
| `steamFrame.launchers.<id>.source.flatpak` | null or str | the desktop ID, if no other source | Flatpak app ID whose exported entry is rewritten (at runtime). |
| `steamFrame.launchers.<id>.source.package` | null or package | `null` | Package whose `share/applications/<id>.desktop` is rewritten (at build time; the build fails without it). |
| `steamFrame.launchers.<id>.source.file` | null or str | `null` | Desktop entry on the host, rewritten at runtime. |
| `steamFrame.launchers.<id>.keyring.enable` | bool | `false` | KDE wallet shared by both sessions: outer bus; Flatpaks may talk to `org.kde.kwalletd6`, `org.freedesktop.secrets`. |
| `steamFrame.launchers.<id>.keyring.electron` | bool | `false` | Pass `--password-store=kwallet6` (Electron apps; needs `keyring.enable`). |
| `steamFrame.launchers.<id>.defaultFor` | list of str | `[ ]` | MIME types / `x-scheme-handler/<scheme>` the app becomes the default and a recommended handler for (also in `MimeType=`); a type claimed twice fails. |
| `steamFrame.launchers.<id>.mimeTypes` | list of str | `[ ]` | Added to `MimeType=`, not made default. |
| `steamFrame.launchers.<id>.flatpakArgs` | list of str | `[ ]` | `flatpak run` options before the app ID (Flatpaks only). |
| `steamFrame.launchers.<id>.env` | attrs of str | `{ }` | App environment: `--env=K=V` for Flatpaks, like `hostEnv` otherwise. |
| `steamFrame.launchers.<id>.hostEnv` | attrs of str | `{ }` | Environment of the started process (`env K=V`; for Flatpaks the `flatpak` client). |
| `steamFrame.launchers.<id>.args` | list of str | `[ ]` | Arguments right after the app ID / program. |
| `steamFrame.launchers.<id>.wrappers` | list of str | `[ ]` | Commands the command line is passed to, outermost first. |
| `steamFrame.launchers.<id>.settings` | attrs of null or str | `{ }` | `[Desktop Entry]` keys to set (key-file syntax) or remove (`null`); drops their localized variants. |
| `steamFrame.launchers.<id>.command` | str, read-only | | About the command the entry runs, for a terminal. |
| `steamFrame.docker.enable` | bool | `false` | Rootless Docker as a user service, CLI for both sessions, see [Docker](docs/docker.md). |
| `steamFrame.docker.package` | package | `pkgs.docker` | Docker package (daemon and CLI). |
| `steamFrame.docker.host` | str, read-only | `"unix://${runtimeDir}/docker.sock"` | The daemon's `DOCKER_HOST` (the CLI's default). |
@@ -344,6 +342,12 @@ Renamed options still work under their old names, with a warning:
| `dashboard.windowCurvature.snapPixels`, `snapPoints` | `detentPixels`, `detentPoints` |
| `dashboard.windowCurvature.dragThreshold` | `dragThresholdPixels` |
Removed options fail with the new form:
| Old | New |
|---|---|
| `keyring.flatpaks.<id>`, `keyring.programs.<id>` | `launchers.<id>.keyring` (fields: [Launchers](docs/launchers.md#configuration)) |
## Changes outside Nix (exceptions)
Everything not listed here is a Home Manager link into the Nix store or
@@ -355,6 +359,8 @@ lives in memory (the UI patches). These are written at runtime:
| `~/.local/state/steam-frame-nix/steamvr-debugger.armed` | SteamVR debugger: the key's previous value | while SteamVR runs; after a power loss until the next SteamVR start or cleanup | SteamVR stopping; `steam-frame-nix-cleanup` |
| `/run/user/1000/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf`, `/run/user/1000/steam-frame-nix/steamvr-debugger-restore` | SteamVR debugger: puts the key back when SteamVR stops, without Nix | until reboot (tmpfs) | reboot; `steam-frame-nix-cleanup` while SteamVR is stopped and the debugger is off |
| `~/.local/state/steam-frame-nix/ui-patches/<name>.json` | Saved choices of dashboard patches ([persistent state](docs/ui-patches.md#persistent-state)): window control bar placements (`frame-controls`), "Steam hidden" (`steam-close-button`). SteamOS's `steamvr.service` deletes `~/.cache/SteamVR` (the dashboard's own browser storage) on every SteamVR start. | until removed: kept when a patch is disabled (the choices come back when you enable it again) | `steam-frame-nix-cleanup --all`, `install.sh uninstall` |
| `/run/user/1000/steam-frame-nix/applications/<id>.desktop` (with `.<id>.desktop.sum`, `.lock`) | [Launchers](docs/launchers.md) of Flatpaks and host files; `~/.local/share/applications/<id>.desktop` is a Home Manager link to it | until reboot (tmpfs), written again at login | reboot; the next switch or rewrite when the launcher or its app is gone; `steam-frame-nix-cleanup --all` |
| mtime of `~/.local/share/applications` | [Launchers](docs/launchers.md#how-it-works): a running Steam rescans the "+" menu | only the directory's timestamp | nothing to remove |
| mtime of `~/.local/share/icons/hicolor` | [icon fallbacks](docs/launcher-menu.md#icon-fallbacks): a running Steam rescans icons | only the directory's timestamp | nothing to remove |
**`steam-frame-nix-cleanup`** (`install.sh cleanup`,
@@ -379,8 +385,8 @@ versions left: [docs/cleanup.md](docs/cleanup.md).
- clipboard-sync runs from KDE autostart (a Home Manager link).
- Firefox: the desktop profile's `user.js` link exists only while its
Firefox runs (see [Firefox](docs/firefox.md#how-it-works)).
- Jellyfin, keyring launchers: the permissions are `flatpak run` options of
the desktop entries, not Flatpak overrides.
- Launchers (Jellyfin, wallet access): the permissions are `flatpak run`
options of the desktop entries, not Flatpak overrides.
- Docker: the daemon's socket in `/run/user/1000` (tmpfs) exists while
`docker.service` runs.
+1
View File
@@ -25,6 +25,7 @@ is reported as "left alone" and never touched:
| `firefox`: `user.js` in Firefox profiles | links to `/app/etc/firefox/steam-frame-nix-desktop-user.js` (left alone while the profile is in use), older links to `*-firefox-*user.js` and copies starting with the steam-frame-nix marker comment, and the values they left in `prefs.js` (only with Firefox closed) |
| `jellyfin` | the hwdec shim entries in the Jellyfin Flatpak's user override `~/.local/share/flatpak/overrides/org.jellyfin.JellyfinDesktop` (nix-flatpak), an empty override file, and the shim copy of earlier versions in `~/.var/app/org.jellyfin.JellyfinDesktop` (marker `~/.local/state/steam-frame-nix/jellyfin-hwdec-shim`) |
| `ui-state`: `~/.local/state/steam-frame-nix/ui-patches/<name>.json` | the dashboard patches' saved choices; `--all` only, never `--orphans`; stray `*.json.tmp` files |
| `launchers`: `/run/user/1000/steam-frame-nix/applications` | the entries of [launchers](launchers.md) (tmpfs); `--all` only (switches remove those of removed launchers themselves) |
| `dirs` | `~/.local/state/steam-frame-nix` and `/run/user/1000/steam-frame-nix` when empty |
### Left by older versions
+12 -5
View File
@@ -53,12 +53,18 @@ modules/
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)
keyring.nix app: launchers sharing the KDE wallet (keyring)
launchers.nix links, MIME defaults, units of the launchers (launchers.<id>)
launchers/
lib.nix the launcher option type, Exec quoting, package entries (build)
rewrite.awk build+service: rewrites a desktop entry's Exec lines and keys
generate.sh service steam-frame-nix-launchers (+ .path), switch: entries
of Flatpaks/host files in <runtimeDir>/steam-frame-nix/applications
check.nix, fixtures/ test: real entries rewritten (fixtures/expected), generator runs
docker.nix service: rootless dockerd (docker)
firefox.nix Flatpak prefs extension and launcher entry (firefox)
firefox/launcher.nix app: launcher script (desktop profile, fullscreen fix)
firefox/check.nix test: launcher against a fake flatpak
jellyfin.nix desktop entry with flatpak run options (jellyfin.hardwareDecoding)
firefox.nix Flatpak prefs extension and launcher (firefox)
firefox/wrapper.nix app: launcher wrapper (desktop profile, fullscreen fix)
firefox/check.nix test: wrapper against a fake flatpak
jellyfin.nix launcher with flatpak run options (jellyfin.hardwareDecoding)
jellyfin/mpv-hwdec-shim.c app: LD_PRELOAD shim, hwdec auto* -> v4l2m2m-copy
jellyfin/shim.nix build: the shim as lib/mpv-hwdec-shim.so
jellyfin/check.nix test: shim ELF and rewriting
@@ -116,6 +122,7 @@ they are kept even where a file name says more:
| `window-curvature` | `dashboard.windowCurvature` | `window-curvature` (SteamVR) | `steam-ui-patches` |
| `frame-controls` | `dashboard.frameControls` | `frame-controls` (SteamVR, state) | `steam-ui-patches` |
| `steamvr-debugger` | `steamvrDebugger` | | `steamvr-webhelper-debugger` |
| `launchers` | `launchers` | | `steam-frame-nix-launchers` (`.service`, `.path`) |
Log of all patches:
`journalctl --user -u steam-ui-patches -u steam-keyboard-patch -u vr-keyboard-relay`.
+12 -9
View File
@@ -14,9 +14,10 @@ browser the portal opens links with the first installed `https` handler
## What you get
A launcher for the Flathub Firefox Flatpak (`org.mozilla.firefox`, stable;
install it yourself). The launcher shadows the Flatpak's own entry (same
ID), so default-browser associations keep working.
A [launcher](launchers.md) for the Flathub Firefox Flatpak
(`org.mozilla.firefox`, stable; install it yourself): the Flatpak's own
entry with a wrapper in front, same ID, so default-browser associations
keep working.
- **`vrFullscreenFix`** (on): `full-screen-api.ignore-widgets` makes
fullscreen fill just the window. Not applied in the desktop profile.
@@ -26,11 +27,11 @@ ID), so default-browser associations keep working.
- **`prefs`:** further `about:config` values for every profile; they can
also override the fixes above.
- **`desktopProfile`** (`"desktop"`): in the nested desktop the launcher
uses this separate profile (a normal Firefox profile with its own browser
uses this separate profile (not for "Open Profile Manager") (a normal Firefox profile with its own browser
data, created on first use). `null`: the default profile in both sessions.
- **`defaultBrowser`** (off): the launcher becomes the default for `http`,
`https` and `text/html` (Home Manager's `xdg.mimeApps`, which then owns
`~/.config/mimeapps.list`).
`https` and `text/html` (the launcher's `defaultFor`: Home Manager's
`xdg.mimeApps`, which then owns `~/.config/mimeapps.list`).
`prefs` and the fixes are *default* values, not user values: `about:config`
can still change them per profile, and removing one leaves nothing behind.
@@ -71,9 +72,11 @@ to a store directory; Flatpak mounts it itself, so the sandbox doesn't get
### Desktop profile
The launcher (a desktop entry with the Flatpak's ID) picks `desktopProfile`
when started in the nested desktop. The desktop profile undoes the
fullscreen fix only while its Firefox runs: the launcher links the
The launcher's wrapper (`modules/firefox/wrapper.nix`) gets the entry's
`flatpak run …` command line and, in the nested desktop, adds `--profile
<desktopProfile>` (not to the profile manager action, `--ProfileManager`).
The desktop profile undoes the fullscreen fix only while its Firefox runs:
the wrapper links the
profile's `user.js` to `/app/etc/firefox/steam-frame-nix-desktop-user.js`
(a sandbox path) right before starting Firefox, waits for it, and once it
has exited and the profile is no longer in use removes the link and the
+12 -9
View File
@@ -19,8 +19,9 @@ which
## What you get
The Jellyfin desktop entry (same ID as the Flatpak's, so the KDE menu and
the "+" menu start it) runs the Flatpak with device access (`devices=all`)
A [launcher](launchers.md) (the Flatpak's own entry, rewritten under its
ID, so the KDE menu and the "+" menu start it) runs the Flatpak with device
access (`devices=all`)
and makes mpv use `hwdec` (default `v4l2m2m-copy,auto-copy`); explicit
values such as `no` stay. mpv tries the listed decoders in order and falls
back to software decoding per stream. With the default, 1080p H.264 plays
@@ -38,7 +39,7 @@ steamFrame.jellyfin.hardwareDecoding.enable = true;
```
From a terminal, start it with the command line of
`steamFrame.jellyfin.hardwareDecoding.command` (or `grep ^Exec=
`steamFrame.jellyfin.hardwareDecoding.command` (or the one of `grep ^Exec=
~/.local/share/applications/org.jellyfin.JellyfinDesktop.desktop`); its
output shows `mpv-hwdec-shim: hwdec "auto-copy" -> "v4l2m2m-copy,auto-copy"`,
then mpv's `Using hardware decoding (v4l2m2m-copy)`.
@@ -63,12 +64,13 @@ option). It is preloaded from the Nix store; only its store path is exposed
(read-only) to the sandbox. It would work for any libmpv app that sets
`hwdec=auto*`, but only Jellyfin Desktop is set up here.
### The desktop entry
### The launcher
Nothing is written to Flatpak's overrides: the entry
(`~/.local/share/applications/org.jellyfin.JellyfinDesktop.desktop`) passes
device access and the shim as `flatpak run` options, so they apply to
launches from that entry and are gone with it:
Nothing is written to Flatpak's overrides: the launcher
`steamFrame.launchers."org.jellyfin.JellyfinDesktop"` passes device access
and the shim as `flatpak run` options (`flatpakArgs`, `env`), so they apply
to launches from the entry and are gone with it. Its command lines (the
entry's and the four actions') become
```sh
flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop \
@@ -77,7 +79,8 @@ flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop \
--env=SFN_MPV_HWDEC=v4l2m2m-copy,auto-copy org.jellyfin.JellyfinDesktop
```
(`command` is this line with the store path.)
(`command` is about this line, with the store path and without the
entry's `--branch`/`--arch`/`--command`.)
Older versions used a Flatpak override (via nix-flatpak or a Home Manager
link) and a shim copy in `~/.var/app/org.jellyfin.JellyfinDesktop`;
+4 -126
View File
@@ -1,128 +1,6 @@
# Keyring launchers
`keyring.flatpaks.<app ID>`, `keyring.programs.<desktop ID>`, module
`keyring`. Options: [README, Options](../README.md#options).
## Problem
Apps that keep logins or passwords in the KDE wallet lose them between the
Frame's [two sessions](../README.md#two-sessions):
- **A second wallet:** the nested desktop has its own D-Bus. An app started
there starts a second `kwalletd6` on that bus; what it stores there is
invisible to the same app in the Steam session, which talks to the running
`kwalletd6` on the outer bus.
- **Electron in the Steam session:** Electron picks its keyring from
`XDG_CURRENT_DESKTOP`. In the Steam session that is `gamescope`, which it
doesn't know, so it falls back to `basic` (a local, unencrypted store) and
the login made in the desktop (stored in the wallet) is gone.
- **Flatpak permissions:** many Flatpaks may not talk to the wallet at all
(Element), or only to `org.kde.kwalletd6` while their KF6 wallet client
reads through the Secret Service `org.freedesktop.secrets` (KRDC: "Password
not found").
- **Login callbacks:** SSO logins come back through a URL scheme
(`io.element.desktop://`, `claude://`) opened by the portal. Unless the app
is the default and a recommended handler, the portal opens an app chooser,
which isn't shown in VR.
## What you get
For each listed app, a desktop entry in `~/.local/share/applications` with
the app's own desktop ID, so it replaces the Flatpak's or package's entry in
the KDE menu and the "+" menu. It starts the app
- on the outer bus (`session.busEnv`): one `kwalletd6` for both sessions;
- for Flatpaks, with `--talk-name=org.kde.kwalletd6` and
`--talk-name=org.freedesktop.secrets` as `flatpak run` options (not a
Flatpak override: they apply only to launches from this entry and are
gone with it);
- with `electron = true`, with `--password-store=kwallet6`;
- as the default and recommended handler of its `schemeHandlers`
(`xdg.mimeApps`).
Logins then survive switching between the desktop and VR windows. Changes
take effect at the next start of the app.
## Configuration
The Flatpak isn't in the Nix store, so its entry can't be read at build
time: give the fields you want in menus (`name` is required; `icon`
defaults to the app ID, as Flatpaks export it). A Flatpak (installing it is
up to you):
```nix
steamFrame.keyring.flatpaks = {
"im.riot.Riot" = {
name = "Element";
electron = true;
categories = [ "Network" "InstantMessaging" ];
schemeHandlers = [ "element" "io.element.desktop" ]; # SSO callback
};
"org.kde.krdc" = {
name = "KRDC";
fieldCode = "%u";
categories = [ "Qt" "KDE" "Network" "RemoteAccess" ];
mimeTypes = [ "x-scheme-handler/vnc" "x-scheme-handler/rdp" ]; # listed, not made default
};
};
```
A program from a Nix package: use the package's own desktop ID (without
`.desktop`), so the entry replaces the package's:
```nix
{ pkgs, ... }: {
home.packages = [ pkgs.claude-desktop ];
steamFrame.keyring.programs."com.anthropic.Claude" = {
name = "Claude";
executable = "${pkgs.claude-desktop}/bin/claude-desktop";
icon = "claude-desktop";
electron = true;
startupWMClass = "com.anthropic.Claude";
schemeHandlers = [ "claude" ]; # login callback
settings.StartupNotify = "true";
actions.NewChat = {
name = "New Chat";
args = [ ''"claude://claude.ai/new?surface=chat&source=desktop_action"'' ];
};
};
}
```
`args`, `actions.<name>.args` and `settings` are written into the entry as
given (desktop entry syntax: quote yourself). Each app's `command` (read
only) is its command line without arguments, to start it from a terminal
the same way. The fields each entry takes are in the
[options](../README.md#options).
## Caveats
- The wallet must be KDE's (`kwalletd6`, and `ksecretd` for the Secret
Service), as SteamOS ships it.
- Only launches from the entry get the fixes: a Flatpak started with plain
`flatpak run`, or a program from `~/.nix-profile/bin`, doesn't.
- `schemeHandlers` turns on Home Manager's `xdg.mimeApps`, which then owns
`~/.config/mimeapps.list`: set other defaults there too.
- A Flatpak's own entry may have fields not given here (translations,
`Keywords`, actions); add what you need through `settings` and `actions`.
## How it works
For `"im.riot.Riot" = { name = "Element"; electron = true; ... }` the entry's
command line is
```sh
env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
flatpak run --talk-name=org.kde.kwalletd6 --talk-name=org.freedesktop.secrets \
im.riot.Riot --password-store=kwallet6 %U
```
`flatpak run` connects the sandbox's D-Bus proxy to the bus in its own
environment, so the prefix (not `--env=`) moves the app to the outer bus.
`--talk-name` adds to the Flatpak's permissions for this launch only. The
entry also sets `X-Flatpak=<app ID>`. For `programs` the prefix runs
`executable` directly.
`schemeHandlers` go into `xdg.mimeApps.defaultApplications` and
`associations.added` (Added Associations, what the portal treats as
recommended), and into the entry's `MimeType=` with `mimeTypes`.
Moved: apps that keep their logins in the KDE wallet are now
[launchers](launchers.md) with `keyring.enable` (the former
`keyring.flatpaks` / `keyring.programs` options and how to convert them are
described there).
+204
View File
@@ -0,0 +1,204 @@
# Launchers
`launchers.<desktop ID>`, module `launchers`. Options:
[README, Options](../README.md#options).
## Problem
Starting an app the way the Frame needs often means changing its desktop
entry: extra `flatpak run` options, environment, a wrapper script, making it
a default handler. A hand-written entry with the same ID replaces the
original, but loses what the original has (translations, icon, actions,
MIME types) and goes stale when the app changes its entry in an update.
The most common case is the KDE wallet, where apps lose their logins between
the Frame's [two sessions](../README.md#two-sessions):
- **A second wallet:** the nested desktop has its own D-Bus. An app started
there starts a second `kwalletd6` on that bus; what it stores there is
invisible to the same app in the Steam session, which talks to the running
`kwalletd6` on the outer bus.
- **Electron in the Steam session:** Electron picks its keyring from
`XDG_CURRENT_DESKTOP`. In the Steam session that is `gamescope`, which it
doesn't know, so it falls back to `basic` (a local, unencrypted store) and
the login made in the desktop (stored in the wallet) is gone.
- **Flatpak permissions:** many Flatpaks may not talk to the wallet at all
(Element), or only to `org.kde.kwalletd6` while their KF6 wallet client
reads through the Secret Service `org.freedesktop.secrets` (KRDC: "Password
not found").
- **Login callbacks:** SSO logins come back through a URL scheme
(`io.element.desktop://`, `claude://`) opened by the portal. Unless the app
is the default and a recommended handler, the portal opens an app chooser,
which isn't shown in VR.
## What you get
For each `launchers.<desktop ID>`, the app's own desktop entry, rewritten,
under the same ID in `~/.local/share/applications`: it replaces the original
in the KDE menu and the "+" menu (which reads only that directory). Name,
icon, translations, categories, actions and MIME types stay the app's; only
the command lines (the entry's and every action's) and the keys you set
change. When a Flatpak update changes its entry, the launcher follows within
seconds.
- **`keyring.enable`:** the app runs on the outer bus (one `kwalletd6` for
both sessions); a Flatpak may also talk to the wallet
(`--talk-name=org.kde.kwalletd6 --talk-name=org.freedesktop.secrets`).
**`keyring.electron`** adds `--password-store=kwallet6`. Logins then
survive switching between the desktop and VR windows.
- **`defaultFor`:** the app becomes the default and a recommended handler of
these MIME types / URL schemes (login callbacks open without a chooser).
- **`flatpakArgs`, `env`, `hostEnv`, `args`, `wrappers`:** options,
environment and wrapper commands for the launch; Flatpak permissions this
way apply only to launches from the entry (no Flatpak override files).
- **`mimeTypes`, `settings`:** further `MimeType=` entries; set, override or
remove `[Desktop Entry]` keys.
Changes take effect at the next start of the app. [Firefox](firefox.md)
(`firefox.*`) and [Jellyfin](jellyfin.md) (`jellyfin.hardwareDecoding`) are
launchers too.
## Configuration
The desktop ID is the attribute name; the source is the Flatpak with that
app ID unless `source.package` or `source.file` is set. Installing the app
is up to you.
A Flatpak whose logins live in the wallet (Element, an Electron app), with
its SSO callback schemes:
```nix
steamFrame.launchers."im.riot.Riot" = {
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
};
steamFrame.launchers."org.kde.krdc".keyring.enable = true;
```
A program from a Nix package, from the package's own entry
(`share/applications/<desktop ID>.desktop`, rewritten at build time):
```nix
{ pkgs, ... }: {
home.packages = [ pkgs.claude-desktop ];
steamFrame.launchers."com.anthropic.Claude" = {
source.package = pkgs.claude-desktop;
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/claude" ]; # login callback
};
}
```
Flatpak permissions and environment for one app (what
[Jellyfin](jellyfin.md) sets):
```nix
steamFrame.launchers."org.jellyfin.JellyfinDesktop" = {
flatpakArgs = [ "--device=all" ];
env.SFN_MPV_HWDEC = "v4l2m2m-copy"; # --env= inside the sandbox
};
```
A wrapper, which gets the whole original command line as its arguments (how
[Firefox](firefox.md) picks its desktop profile), and keys of the entry:
```nix
{ pkgs, ... }: {
steamFrame.launchers."org.chromium.Chromium" = {
wrappers = [ "${pkgs.writeShellScript "no-gpu" ''exec "$@" --disable-gpu''}" ];
settings = { Name = "Chromium (no GPU)"; Keywords = null; }; # null: removed
};
}
```
`args`, `flatpakArgs`, `wrappers` and the environment values are plain
strings, quoted for the entry for you; `settings` values are written as
given (key-file syntax). Each launcher's `command` (read only) is roughly its
command line, to start it the same way from a terminal. A host file as
source: `source.file = "/usr/share/applications/<ID>.desktop"`.
**From `keyring.*` (until 2026-09):** `keyring.flatpaks.<ID>` and
`keyring.programs.<ID>` are gone; using them fails with the new form.
`electron = true` is `keyring = { enable = true; electron = true; }`,
`schemeHandlers = [ "x" ]` is `defaultFor = [ "x-scheme-handler/x" ]`,
`programs.<ID>.executable` becomes `source.package`; name, icon, categories,
actions and field codes come from the app's entry.
## Caveats
- Only launches from the entry get the changes: a Flatpak started with plain
`flatpak run`, or a program from `~/.nix-profile/bin`, doesn't.
- A Flatpak's or host file's launcher exists only while its source does: an
app not installed (or uninstalled) has none. The entry is written at
runtime into `/run/user/1000` (tmpfs); until then, e.g. right after boot
before the Steam session's user services started, the link in
`~/.local/share/applications` points nowhere, and menus show neither the
launcher nor the original entry.
- An entry whose command line isn't recognised (a Flatpak's without
`flatpak run ... <app ID>`, a program's starting with `env -…`) is used
unchanged, with a warning in the journal.
- Edits with KDE's "Edit Application" don't last: use `settings`. An
edited entry is overwritten at the next rewrite; a file that replaced the
link is reported, and Home Manager refuses the next switch until it is
removed. Warnings go to the journal
(`journalctl --user -u steam-frame-nix-launchers`).
- `defaultFor` turns on Home Manager's `xdg.mimeApps`, which then owns
`~/.config/mimeapps.list`: set other defaults there too. Two launchers
claiming the same type fail the build.
- The wallet must be KDE's (`kwalletd6`, and `ksecretd` for the Secret
Service), as SteamOS ships it.
## How it works
The Exec lines are rewritten, everything else is copied line by line
(comments, unknown and localized keys as they are):
| Source | Exec= becomes |
|---|---|
| Flatpak | `<hostEnv> <wrappers> <original up to the app ID> <flatpakArgs> <--env=…> <app ID> <args> <rest>` |
| package, file | `<hostEnv + env> <wrappers> <original up to the program> <args> <rest>` |
For a Flatpak the app ID is the first token equal to `X-Flatpak=` (or the
source ID) after `flatpak run`; for others the program is the first token
after an optional leading `env A=B …`. The rest (`--file-forwarding`,
`@@u %U @@`, `%c`, action arguments) stays. `DBusActivatable=true` becomes
`false` (otherwise the desktop would start the app over D-Bus, skipping
Exec), `defaultFor` and `mimeTypes` are added to `MimeType=`, and
`X-SteamFrameNix-Source=` names the source. Element's entry with
`keyring = { enable = true; electron = true; }`:
```sh
env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus \
/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=/app/bin/element \
--file-forwarding --talk-name=org.kde.kwalletd6 --talk-name=org.freedesktop.secrets \
im.riot.Riot --password-store=kwallet6 @@u %U @@
```
`flatpak run` connects the sandbox's D-Bus proxy (and portals) to the bus in
its own environment, so `hostEnv` (not `--env=`) moves the app to the outer
bus. `defaultFor` goes into `xdg.mimeApps.defaultApplications` and
`associations.added` (Added Associations, what the portal treats as
recommended).
**When it is written:** a package's entry at build time (a Home Manager link
into the store). Flatpak and host file entries can't be read at build time,
so `steam-frame-nix-launchers` (`modules/launchers/generate.sh`,
`rewrite.awk`) writes them to `/run/user/1000/steam-frame-nix/applications`
(tmpfs, `session.runtimeDir`), where the Home Manager links in
`~/.local/share/applications` point. It runs
- on every switch (Home Manager activation; skipped with a message when the
Steam session isn't running),
- at login (`steam-frame-nix-launchers.service` of the Steam session's user
manager),
- when Flatpak installs, updates or removes apps
(`steam-frame-nix-launchers.path` watches `.changed` of both Flatpak
installations and their exported `applications` directories).
Sources: `~/.local/share/flatpak/exports/share/applications/<ID>.desktop`,
then `/var/lib/flatpak/exports/share/applications/<ID>.desktop`. An entry is
replaced (temp file and rename) only when its content changes; entries of
launchers no longer configured or without a source are removed. If anything
changed, the mtime of `~/.local/share/applications` is updated, so a running
Steam rescans the "+" menu. A hash of the last written entry
(`.<ID>.desktop.sum`) shows edits by others.
+8 -9
View File
@@ -23,18 +23,17 @@ running") and skips `reloadSystemd`.
and applies `session.services.start` / `stop` / `restart`, which other
modules fill (you can add your own units).
**Configuration:** apps that keep secrets in the wallet get launchers from
[keyring](keyring.md). Another launcher that must reach the outer session
(its bus, services or wallet) uses the prefix:
**Configuration:** apps that keep secrets in the wallet get a
[launcher](launchers.md) with `keyring.enable`. Another app that must reach
the outer session (its bus, services or wallet) gets the bus through its
launcher's `hostEnv`; a hand-written entry uses the prefix `session.busEnv`:
```nix
{ config, ... }: {
xdg.dataFile."applications/org.example.App.desktop".text = ''
[Desktop Entry]
Type=Application
Name=Example
Exec=${config.steamFrame.session.busEnv} flatpak run org.example.App %U
'';
steamFrame.launchers."org.example.App".hostEnv.DBUS_SESSION_BUS_ADDRESS =
config.steamFrame.session.bus;
# or, in an entry of your own:
# Exec=${config.steamFrame.session.busEnv} flatpak run org.example.App %U
}
```
+4 -2
View File
@@ -34,13 +34,14 @@
};
firefox = ./modules/firefox.nix;
jellyfin = ./modules/jellyfin.nix;
keyring = ./modules/keyring.nix;
launchers = ./modules/launchers.nix;
docker = ./modules/docker.nix;
};
# Former attribute names, kept so existing imports keep working (not in
# `default`, which imports each module once under its current name).
aliases = {
steam-keyboard-patch = modules.vr-keyboard-extra-keys; # its name until 2026-09
keyring = modules.launchers; # until 2026-09 (its options now fail with the new form)
};
systems = [ "aarch64-linux" "x86_64-linux" ];
forSystems = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});
@@ -64,11 +65,12 @@
# Tests of the VR keyboard (text model, corrector, swipe decoder on the
# default German + English dictionary), the Jellyfin mpv shim, the
# Firefox launcher and install.sh cleanup: nix flake check
# Firefox wrapper, the launchers and install.sh cleanup: nix flake check
checks = forSystems (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; };
launchers = import ./modules/launchers/check.nix { inherit pkgs; };
vr-keyboard = import ./modules/vr-keyboard/check.nix { inherit pkgs; };
});
+17 -3
View File
@@ -397,7 +397,7 @@ EOF
# $SFN_STATE/icon-fallbacks).
# firefox user.js in Firefox profiles: links to
# /app/etc/firefox/steam-frame-nix-desktop-user.js (the
# launcher's, while the desktop profile runs; left alone while
# wrapper's, while the desktop profile runs; left alone while
# the profile is in use), older links to *-firefox-*user.js and
# copies starting with FF_MARKER, and the values they left in
# prefs.js (only with Firefox closed).
@@ -407,6 +407,9 @@ EOF
# ui-state the dashboard patches' saved choices
# ($SFN_STATE/ui-patches/<name>.json; --all only, never
# --orphans) and stray *.json.tmp files.
# launchers entries of steamFrame.launchers in
# $OUTER_RUNTIME_DIR/steam-frame-nix/applications (tmpfs; --all
# only: the switch's own run removes those of removed launchers).
# dirs $SFN_STATE and $OUTER_RUNTIME_DIR/steam-frame-nix when empty.
#
# --orphans keeps what the current configuration still uses (--keep ...);
@@ -720,7 +723,7 @@ clean_firefox() { # all
t="$(readlink "$u")"
case $t in
"$FF_DESKTOP_JS")
# The launcher's, while Firefox runs in the desktop profile.
# The wrapper's, while Firefox runs in the desktop profile.
if ff_in_use "$prof"; then
(( all )) && c_defer "$u: Firefox is using profile $name; close it and run this again"
continue
@@ -825,6 +828,17 @@ clean_jellyfin() {
return 0
}
# --- launcher entries (tmpfs) ---
clean_launchers() {
local d=$SFN_RUNTIME/applications f
[[ -d $d && ! -L $d ]] || return 0
while IFS= read -r -d '' f; do
c_rm "$f" "generated launcher entry"
done < <(find "$d" -mindepth 1 -maxdepth 1 -type f -print0)
c_rmdir "$d"
}
# --- dashboard patch state ---
clean_ui_state() { # all
@@ -877,7 +891,7 @@ cmd_cleanup() {
clean_jellyfin
clean_ui_state "$([[ $mode == all ]] && echo 1 || echo 0)"
c_rmdir "$SFN_STATE"
if [[ $mode == all ]]; then c_rmdir "$SFN_RUNTIME"; fi
if [[ $mode == all ]]; then clean_launchers; c_rmdir "$SFN_RUNTIME"; fi
(( CLEAN_ACTIONS || ${#CLEAN_DEFERRED[@]} || CLEAN_QUIET )) || info "nothing to clean up"
return 0
}
+5 -1
View File
@@ -53,6 +53,10 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } ''
touch $S/steamvr-debugger # marker of the first version
mkdir -p $root/run/steam-frame-nix $root/run/systemd/user/steamvr.service.d
echo old > $root/run/steam-frame-nix/steamvr-debugger-restore
mkdir -p $root/run/steam-frame-nix/applications # steamFrame.launchers
echo '[Desktop Entry]' > $root/run/steam-frame-nix/applications/im.riot.Riot.desktop
echo x > $root/run/steam-frame-nix/applications/.im.riot.Riot.desktop.sum
: > $root/run/steam-frame-nix/applications/.lock
echo old > $root/run/systemd/user/steamvr.service.d/50-steam-frame-nix-debugger.conf
echo keep > $root/run/systemd/user/steamvr.service.d/other.conf
ln -s /nix/store/00000000000000000000000000000000-breeze-icons-6.30.0/share/icons/breeze/apps/64/utilities-terminal.svg $I/utilities-terminal.svg
@@ -156,7 +160,7 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } ''
echo absent > $S/steamvr-debugger.armed
mkdir -p $F/desktop $F/x.default
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/desktop/user.js
touch $F/desktop/.parentlock; exec 8< $F/desktop/.parentlock # the launcher's, Firefox running
touch $F/desktop/.parentlock; exec 8< $F/desktop/.parentlock # the wrapper's, Firefox running
ln -s /app/etc/firefox/steam-frame-nix-desktop-user.js $F/x.default/user.js
printf '[Context]\ndevices=all;\nfilesystems=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro;\n\n[Environment]\nLD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so\nSFN_MPV_HWDEC=x\n' > $O/org.jellyfin.JellyfinDesktop
mkdir -p $HOME/.var/app/org.jellyfin.JellyfinDesktop
+17 -42
View File
@@ -11,10 +11,10 @@
# fullscreen inside the window.
# - 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, where fullscreen works: the launcher undoes
# the fix there while its Firefox runs (firefox/launcher.nix).
# The entry shadows the Flatpak's (same ID), keeping MIME associations, and is
# seen by the "+" menu (which reads only ~/.local/share/applications).
# desktop gets its own profile, where fullscreen works: the wrapper undoes
# the fix there while its Firefox runs (firefox/wrapper.nix).
# The launcher (launchers.nix) is the Flatpak's own entry with the wrapper in
# front, same ID, so MIME associations keep working and the "+" menu sees it.
# defaultBrowser: without a default the portal picks the first installed
# https handler (e.g. Chromium) in both sessions.
{ config, pkgs, lib, ... }:
@@ -41,13 +41,12 @@ let
(k: "user_pref(${builtins.toJSON k}, false);\n") desktopKeys)} $out/${desktopUserJsName}
'');
firefox = pkgs.callPackage ./firefox/launcher.nix {
profileDir = if cfg.desktopProfile == null then null else profileDir;
inherit desktopFix desktopKeys;
wrapper = pkgs.callPackage ./firefox/wrapper.nix {
inherit profileDir desktopFix desktopKeys;
desktopJs = "/app/etc/firefox/${desktopUserJsName}";
};
in {
imports = [ ./cleanup.nix ];
imports = [ ./launchers.nix ];
options.steamFrame.firefox = {
enable = lib.mkEnableOption ''
@@ -97,49 +96,25 @@ in {
type = lib.types.bool;
default = false;
description = ''
Make the launcher the default for http, https and text/html (in
Home Manager's ~/.config/mimeapps.list). Without a default the
portal opens links with the first installed https handler, in both
sessions.
Make the launcher the default for http, https and text/html (its
`defaultFor`, in Home Manager's ~/.config/mimeapps.list). Without a
default the portal opens links with the first installed https
handler, in both sessions.
'';
};
};
config = lib.mkIf cfg.enable {
xdg.mimeApps = lib.mkIf cfg.defaultBrowser {
enable = true;
defaultApplications = lib.genAttrs
[ "x-scheme-handler/http" "x-scheme-handler/https" "text/html" ]
(_: "org.mozilla.firefox.desktop");
steamFrame.launchers."org.mozilla.firefox" = {
wrappers = lib.optional (cfg.desktopProfile != null) "${wrapper}";
defaultFor = lib.optionals cfg.defaultBrowser
[ "x-scheme-handler/http" "x-scheme-handler/https" "text/html" ];
};
# stable: the branch the launcher runs (the extension point has no
# stable: the branch the Flatpak's entry runs (the extension point has no
# version, so it takes the app's branch).
xdg.dataFile = lib.optionalAttrs (defaultPrefs != { }) { # desktopFix implies a pref
xdg.dataFile = lib.mkIf (defaultPrefs != { }) { # desktopFix implies a pref
"flatpak/extension/org.mozilla.firefox.systemconfig/aarch64/stable".source = sysconfig;
} // {
"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 @@
'';
};
};
}
+14 -6
View File
@@ -1,8 +1,9 @@
# Checks of the Firefox launcher's desktop profile user.js (launcher.nix)
# Checks of the Firefox wrapper's desktop profile user.js (wrapper.nix)
# against a fake flatpak: the link exists only while Firefox runs, a second
# launch that hands over to the running Firefox doesn't remove it, the value
# Firefox stored from it leaves prefs.js once the profile is unlocked, and a
# user.js of the user's own is never touched.
# Firefox stored from it leaves prefs.js once the profile is unlocked, a
# user.js of the user's own is never touched, the profile manager action and
# the Steam session get no --profile.
{ pkgs }:
let
# Fake `flatpak run … org.mozilla.firefox --profile DIR …`: with the
@@ -22,11 +23,12 @@ let
while [ ! -e $FAKE/release ]; do sleep 0.1; done
exit 3
'';
launcher = pkgs.callPackage ./launcher.nix {
flatpakBin = fakeFlatpak;
wrapper = pkgs.callPackage ./wrapper.nix {
profileDir = "$HOME/ff/desktop";
desktopFix = true;
};
# What the launcher's Exec= runs: the wrapper, then the Flatpak's command.
launcher = "${wrapper} ${fakeFlatpak} run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox";
in
pkgs.runCommand "firefox-check" { nativeBuildInputs = [ pkgs.findutils pkgs.gnugrep ]; } ''
set -euo pipefail
@@ -36,7 +38,7 @@ pkgs.runCommand "firefox-check" { nativeBuildInputs = [ pkgs.findutils pkgs.gnug
p=$HOME/ff/desktop
# first launch: link made, Firefox runs
${launcher} https://example.org & first=$!
${launcher} @@u https://example.org @@ & first=$!
for i in $(seq 100); do grep -q started $FAKE/log && break; sleep 0.1; done
grep -qx 'started /app/etc/firefox/steam-frame-nix-desktop-user.js' $FAKE/log || fail "not linked at start"
echo 'user_pref("other", 1);' >> $p/prefs.js
@@ -59,6 +61,12 @@ pkgs.runCommand "firefox-check" { nativeBuildInputs = [ pkgs.findutils pkgs.gnug
grep -q ignore-widgets $p/prefs.js || fail "prefs.js changed with an own user.js"
rm $p/user.js
# profile manager action: no --profile, no link
: > $FAKE/log
${launcher} --ProfileManager || true
grep -qx 'default profile' $FAKE/log || fail "--profile with --ProfileManager"
[ ! -e $p/user.js ] || fail "linked for the profile manager"
# Steam session: default profile, no link
: > $FAKE/log
XDG_CURRENT_DESKTOP=gamescope ${launcher} || true
@@ -1,25 +1,24 @@
# The Firefox Flatpak launcher (firefox.nix). In the nested desktop (KDE) it
# uses the desktop profile; with the fullscreen fix it links that profile's
# user.js to the sandbox path desktopJs (undoing the fix there) right before
# Firefox starts, and once Firefox has exited and the profile is no longer in
# use (a second launch that only hands its URL to the running Firefox returns
# at once) removes the link and the value Firefox stored from it in
# prefs.js. A user.js of the user's own is never touched. After a crash the
# next launch or steam-frame-nix-cleanup finishes the removal.
# The Firefox Flatpak wrapper (firefox.nix, a steamFrame.launchers wrapper):
# gets the entry's full command line (`flatpak run … org.mozilla.firefox …`)
# as its arguments. Outside the nested desktop it just runs it. In the nested
# desktop (KDE) it adds `--profile <desktop profile>` (not to the profile
# manager action, --ProfileManager); with the fullscreen fix it links that
# profile's user.js to the sandbox path desktopJs (undoing the fix there)
# right before Firefox starts, and once Firefox has exited and the profile is
# no longer in use (a second launch that only hands its URL to the running
# Firefox returns at once) removes the link and the value Firefox stored from
# it in prefs.js. A user.js of the user's own is never touched. After a crash
# the next launch or steam-frame-nix-cleanup finishes the removal.
{ lib, writeShellScript, coreutils, findutils, gnugrep
, flatpakBin ? "/usr/bin/flatpak" # (not `flatpak`: callPackage would pass pkgs.flatpak)
, profileDir ? null # shell word, e.g. "$HOME/.var/app/…/desktop"; null: no desktop profile
, profileDir # shell word, e.g. "$HOME/.var/app/…/desktop"
, desktopFix ? false
, desktopJs ? "/app/etc/firefox/steam-frame-nix-desktop-user.js"
, desktopKeys ? [ "full-screen-api.ignore-widgets" ]
}:
writeShellScript "firefox-launcher" (''
writeShellScript "firefox-wrapper" (''
PATH=${lib.makeBinPath [ coreutils findutils gnugrep ]}:$PATH
run=(${flatpakBin} run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox)
'' + (if profileDir == null then ''
exec "''${run[@]}" "$@"
'' else ''
if [ "$XDG_CURRENT_DESKTOP" != KDE ]; then exec "''${run[@]}" "$@"; fi
if [ "$XDG_CURRENT_DESKTOP" != KDE ]; then exec "$@"; fi
for a; do [ "$a" = --ProfileManager ] && exec "$@"; done
prof="${profileDir}"
# Firefox exits (status 1) if the --profile dir doesn't exist yet.
mkdir -p "$prof"
@@ -45,10 +44,10 @@ writeShellScript "firefox-launcher" (''
else
ln -s "$js" "$u"
fi
"''${run[@]}" --profile "$prof" "$@"
"$@" --profile "$prof"
status=$?
sfn_unlink
exit $status
'' + lib.optionalString (!desktopFix) ''
exec "''${run[@]}" --profile "$prof" "$@"
''))
exec "$@" --profile "$prof"
'')
+26 -48
View File
@@ -7,11 +7,11 @@
# - an LD_PRELOAD shim (jellyfin/mpv-hwdec-shim.c) rewrites an "auto*" hwdec
# to $SFN_MPV_HWDEC. Preloaded from the store: only its store path is
# exposed (read-only) to the sandbox.
# - a desktop entry shadowing the Flatpak's (same ID, also seen by the "+"
# menu) starts it with those permissions as `flatpak run` options
# (--device=all, --filesystem, --env): nothing is written to Flatpak's
# override files, so they apply only to launches from this entry and
# disappear with it.
# - a launcher (launchers.nix: the Flatpak's own entry, same ID, also seen
# by the "+" menu) starts it with those permissions as `flatpak run`
# options (--device=all, --filesystem, --env): nothing is written to
# Flatpak's override files, so they apply only to launches from the entry
# and disappear with it.
# Earlier versions used an override file (nix-flatpak or Home Manager);
# steam-frame-nix-cleanup removes their entries.
{ config, lib, pkgs, ... }:
@@ -21,16 +21,16 @@ let
shim = pkgs.callPackage ./jellyfin/shim.nix { };
run = lib.concatStringsSep " " [
"flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop"
"--device=all"
"--filesystem=${shim}:ro"
"--env=LD_PRELOAD=${shim}/lib/mpv-hwdec-shim.so"
"--env=SFN_MPV_HWDEC=${cfg.hwdec}"
app
];
launcher = {
flatpakArgs = [ "--device=all" "--filesystem=${shim}:ro" ];
env = {
LD_PRELOAD = "${shim}/lib/mpv-hwdec-shim.so";
SFN_MPV_HWDEC = cfg.hwdec;
};
};
L = import ./launchers/lib.nix { inherit lib pkgs; };
in {
imports = [ ./cleanup.nix ];
imports = [ ./launchers.nix ];
options.steamFrame.jellyfin.hardwareDecoding = {
enable = lib.mkOption {
@@ -38,7 +38,7 @@ in {
default = false;
description = ''
Hardware video decoding (the Frame's V4L2 decoder) in the Jellyfin
Desktop Flatpak: a desktop entry (shadowing the Flatpak's) that
Desktop Flatpak: a launcher (the Flatpak's entry, rewritten) that
starts it with device access (devices=all) and an LD_PRELOAD shim
that makes mpv try hwdec's value below. Only launches from that
entry (menus, the "+" menu) get it; nothing is written to Flatpak's
@@ -58,43 +58,21 @@ in {
command = lib.mkOption {
type = lib.types.str;
readOnly = true;
default = run;
# Its launcher's, which exists only when enabled.
default = if cfg.enable then config.steamFrame.launchers.${app}.command
else L.command (launcher // {
id = app; source = { flatpak = null; package = null; file = null; };
hostEnv = { }; wrappers = [ ]; args = [ ];
});
defaultText = lib.literalMD "`flatpak run … org.jellyfin.JellyfinDesktop` with the options";
description = "The command line the desktop entry runs (for a terminal).";
description = ''
About the command line the launcher runs (for a terminal; the same
as `steamFrame.launchers."org.jellyfin.JellyfinDesktop".command`).
'';
};
};
# Fields as in the Flatpak's own entry (1.x), which has no MimeType.
config = lib.mkIf cfg.enable {
xdg.dataFile."applications/${app}.desktop".text = ''
[Desktop Entry]
Version=1.0
Name=Jellyfin
Comment=Desktop client for Jellyfin
Exec=${run}
Icon=${app}
Terminal=false
Type=Application
StartupWMClass=${app}
Categories=AudioVideo;Video;Player;TV;
Actions=DesktopF;DesktopW;TVF;TVW
X-Flatpak=${app}
[Desktop Action DesktopF]
Name=Desktop [Fullscreen]
Exec=${run} --fullscreen --desktop
[Desktop Action DesktopW]
Name=Desktop [Windowed]
Exec=${run} --windowed --desktop
[Desktop Action TVF]
Name=TV [Fullscreen]
Exec=${run} --fullscreen --tv
[Desktop Action TVW]
Name=TV [Windowed]
Exec=${run} --windowed --tv
'';
steamFrame.launchers.${app} = launcher;
};
}
-264
View File
@@ -1,264 +0,0 @@
# Launchers for apps that keep secrets in the KDE wallet, so both sessions
# share them.
# - One kwalletd6, on the outer bus: the nested desktop has its own D-Bus,
# where an app would start a second kwalletd6 whose secrets the Steam
# session never sees. The launchers run with session.busEnv.
# - Electron picks its keyring from XDG_CURRENT_DESKTOP; in the Steam session
# (gamescope) it falls back to "basic" (a local file) and the login made in
# the desktop is gone. `electron` passes --password-store=kwallet6.
# - Flatpaks: the wallet's D-Bus names (kwalletd6 and the Secret Service,
# served by ksecretd) as `flatpak run --talk-name` options, not Flatpak
# override files: they apply only to launches from the entry and are gone
# with it.
# - schemeHandlers: login callbacks (claude://, io.element.desktop://) go
# through the portal, which opens an app chooser (invisible in VR) unless
# the app is the default and a recommended handler (Added Associations).
# Each entry is written to ~/.local/share/applications with the app's own
# desktop ID: it shadows the Flatpak's/package's entry and is seen by the "+"
# menu (which reads only that directory).
{ config, lib, ... }:
let
cfg = config.steamFrame.keyring;
busEnv = config.steamFrame.session.busEnv;
walletNames = [ "org.kde.kwalletd6" "org.freedesktop.secrets" ];
actionModule = lib.types.submodule {
options = {
name = lib.mkOption {
type = lib.types.str;
description = "Name of the action (Name=).";
};
args = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ ''"claude://claude.ai/new"'' ];
description = ''
Arguments after the app's (in desktop entry Exec syntax: quote
yourself).
'';
};
};
};
# Shared by flatpaks and programs; `flatpak` switches the defaults and the
# command.
appModule = flatpak: { name, config, ... }: {
options = {
name = lib.mkOption {
type = lib.types.str;
example = "Element";
description = "Name shown in menus (Name=).";
};
genericName = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "GenericName=.";
};
comment = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "Comment=.";
};
icon = lib.mkOption ({
type = lib.types.nullOr lib.types.str;
default = if flatpak then name else null;
description = "Icon name (Icon=).";
} // lib.optionalAttrs flatpak { defaultText = lib.literalMD "the app ID"; });
categories = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "Network" "InstantMessaging" ];
description = "Categories=.";
};
startupWMClass = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "StartupWMClass=.";
};
mimeTypes = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "x-scheme-handler/rdp" ];
description = ''
Further MIME types listed in the entry (MimeType=), without making
the app their default.
'';
};
schemeHandlers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "element" "io.element.desktop" ];
description = ''
URL schemes (without `x-scheme-handler/`) the app handles and is
made the default and a recommended handler for, e.g. login
callbacks: otherwise the portal asks with an app chooser, which
isn't shown in VR. Listed in MimeType= too.
'';
};
electron = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Pass `--password-store=kwallet6`: Electron picks its keyring from
XDG_CURRENT_DESKTOP and in the Steam session (gamescope) would use
an unencrypted local store instead of the wallet.
'';
};
args = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Further arguments to the app (desktop entry Exec syntax), before
the field code.
'';
};
fieldCode = lib.mkOption {
type = lib.types.enum [ "%U" "%u" "%F" "%f" "" ];
default = "%U";
description = ''
How the entry passes URLs/files: `%U` several URLs, `%u` one,
`%F`/`%f` local files, `""` none.
'';
};
actions = lib.mkOption {
type = lib.types.attrsOf actionModule;
default = { };
example = lib.literalExpression
''{ NewChat = { name = "New Chat"; args = [ '''"claude://claude.ai/new"''' ]; }; }'';
description = ''
Desktop actions (right-click menu entries); each runs the command
with its args.
'';
};
settings = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
example = { StartupNotify = "true"; Keywords = "Matrix;chat;"; };
description = "Further keys of the [Desktop Entry] group.";
};
command = lib.mkOption {
type = lib.types.str;
readOnly = true;
description = ''
The command line the entry runs, without args and field code (for
a terminal).
'';
};
} // lib.optionalAttrs flatpak {
flatpakArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "--branch=stable" "--command=/app/bin/element" ];
description = "Further `flatpak run` options.";
};
} // lib.optionalAttrs (!flatpak) {
executable = lib.mkOption {
type = lib.types.str;
example = lib.literalExpression ''"''${pkgs.claude-desktop}/bin/claude-desktop"'';
description = "The program to run (a path, e.g. into a package).";
};
};
config.command = lib.concatStringsSep " " ([ busEnv ]
++ (if flatpak
then [ "flatpak run" ] ++ map (n: "--talk-name=${n}") walletNames
++ config.flatpakArgs ++ [ name ]
else [ config.executable ])
++ lib.optional config.electron "--password-store=kwallet6");
};
entry = id: app: let
exec = args: lib.concatStringsSep " " ([ app.command ] ++ args);
mime = map (s: "x-scheme-handler/${s}") app.schemeHandlers ++ app.mimeTypes;
list = xs: lib.concatMapStrings (x: "${x};") xs;
line = k: v: lib.optionalString (v != null && v != "") "${k}=${v}\n";
in ''
[Desktop Entry]
Type=Application
'' + line "Name" app.name
+ line "GenericName" app.genericName
+ line "Comment" app.comment
+ line "Icon" app.icon
+ line "Exec" (exec (app.args ++ lib.optional (app.fieldCode != "") app.fieldCode))
+ line "StartupWMClass" app.startupWMClass
+ line "Categories" (list app.categories)
+ line "MimeType" (list mime)
+ line "Actions" (list (lib.attrNames app.actions))
+ line "X-Flatpak" (if app ? flatpakArgs then id else null)
+ lib.concatStrings (lib.mapAttrsToList line app.settings)
+ lib.concatStrings (lib.mapAttrsToList (a: act: ''
[Desktop Action ${a}]
Name=${act.name}
Exec=${exec act.args}
'') app.actions);
apps = cfg.flatpaks // cfg.programs;
handlers = lib.concatLists (lib.mapAttrsToList (id: app:
map (s: lib.nameValuePair "x-scheme-handler/${s}" "${id}.desktop") app.schemeHandlers) apps);
in {
imports = [ ./cleanup.nix ];
options.steamFrame.keyring = {
flatpaks = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule (appModule true));
default = { };
example = lib.literalExpression ''
{
"im.riot.Riot" = {
name = "Element";
electron = true;
schemeHandlers = [ "element" "io.element.desktop" ];
};
"org.kde.krdc" = { name = "KRDC"; fieldCode = "%u"; };
}
'';
description = ''
Flatpaks (by app ID) that keep secrets in the KDE wallet: a desktop
entry shadowing the Flatpak's runs it on the outer bus, allowed to
talk to the wallet (`flatpak run --talk-name=...`).
'';
};
programs = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule (appModule false));
default = { };
example = lib.literalExpression ''
{
"com.anthropic.Claude" = {
name = "Claude";
executable = "''${pkgs.claude-desktop}/bin/claude-desktop";
icon = "claude-desktop";
electron = true;
schemeHandlers = [ "claude" ];
};
}
'';
description = ''
Other programs (e.g. from Nix packages), by desktop ID without
`.desktop` (use the package's own, so the entry replaces it): a
desktop entry that runs them on the outer bus.
'';
};
};
config = lib.mkIf (apps != { }) {
assertions = map (id: {
assertion = false;
message = "steamFrame.keyring: \"${id}\" is in both flatpaks and programs.";
}) (lib.intersectLists (lib.attrNames cfg.flatpaks) (lib.attrNames cfg.programs))
++ lib.mapAttrsToList (mime: ids: {
assertion = lib.length ids == 1;
message = "steamFrame.keyring: ${lib.removePrefix "x-scheme-handler/" mime} is in the schemeHandlers of ${lib.concatStringsSep " and " ids}.";
}) (lib.zipAttrs (map (h: { ${h.name} = lib.removeSuffix ".desktop" h.value; }) handlers));
xdg.dataFile = lib.mapAttrs' (id: app:
lib.nameValuePair "applications/${id}.desktop" { text = entry id app; }) apps;
xdg.mimeApps = lib.mkIf (handlers != [ ]) {
enable = true;
defaultApplications = lib.listToAttrs handlers;
associations.added = lib.listToAttrs handlers;
};
};
}
+167
View File
@@ -0,0 +1,167 @@
# Launchers: an app's own desktop entry (from its Flatpak, Nix package or a
# host file), rewritten with extra environment, options, wrappers, MIME
# defaults and wallet access, under the same desktop ID in
# ~/.local/share/applications, so it replaces the original in the KDE menu
# and the "+" menu (which reads only that directory).
# - Flatpak/host file entries only exist at runtime: steam-frame-nix-launchers
# (launchers/generate.sh + rewrite.awk) writes them to
# <session.runtimeDir>/steam-frame-nix/applications (tmpfs), on switch, at
# login and when Flatpak installs/updates apps (path unit); the Home
# Manager links point there.
# - Package entries are rewritten at build time.
# - keyring: one kwalletd6 for both sessions (the outer bus), the wallet's
# D-Bus names for Flatpaks, --password-store=kwallet6 for Electron.
# Replaces the keyring module (steamFrame.keyring.*), whose options fail with
# the new form.
{ config, lib, pkgs, ... }:
let
cfg = config.steamFrame.launchers;
session = config.steamFrame.session;
L = import ./launchers/lib.nix { inherit lib pkgs; };
all = lib.mapAttrs (id: l: l // { inherit id; }) cfg;
runtimeLaunchers = lib.filterAttrs (_: l: L.kindOf l != "package") all;
packageLaunchers = lib.filterAttrs (_: l: L.kindOf l == "package") all;
outDir = "${session.runtimeDir}/steam-frame-nix/applications";
exportDirs = [
"${config.xdg.dataHome}/flatpak/exports/share/applications"
"/var/lib/flatpak/exports/share/applications"
];
generator = L.generator {
launchers = runtimeLaunchers;
runtimeDir = session.runtimeDir;
applicationsDir = "${config.xdg.dataHome}/applications";
inherit exportDirs;
};
exe = lib.getExe generator;
defaults = lib.concatLists (lib.mapAttrsToList (id: l:
map (m: { inherit m id; }) (lib.unique l.defaultFor)) all);
byMime = lib.groupBy (d: d.m) defaults;
mimeAttrs = lib.mapAttrs (_: ds: "${(lib.head ds).id}.desktop") byMime;
removed = what: lib.mkRemovedOptionModule [ "steamFrame" "keyring" what ] ''
Keyring launchers are now steamFrame.launchers.<desktop ID>, made from the
app's own desktop entry (name, icon, actions come from it), e.g.
steamFrame.launchers."im.riot.Riot" = {
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
};
steamFrame.launchers."com.anthropic.Claude" = {
source.package = pkgs.claude-desktop;
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/claude" ];
};
(schemeHandlers = [ "x" ] -> defaultFor = [ "x-scheme-handler/x" ];
flatpakArgs, args, mimeTypes, settings keep their meaning; name, icon,
categories, actions, executable, fieldCode, ... are gone.)
See docs/launchers.md.'';
in {
imports = [ ./cleanup.nix (removed "flatpaks") (removed "programs") ];
options.steamFrame.launchers = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule (L.launcherModule { bus = session.bus; }));
default = { };
example = lib.literalExpression ''
{
"im.riot.Riot" = {
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
};
"org.kde.krdc".keyring.enable = true;
"com.anthropic.Claude" = {
source.package = pkgs.claude-desktop;
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/claude" ];
};
}
'';
description = ''
Desktop entries by desktop ID (without `.desktop`), made from the app's
own entry (a Flatpak by default) with extra environment, options,
wrappers and MIME defaults, replacing the original in the KDE menu and
the "+" menu. See docs/launchers.md.
'';
};
config = lib.mkMerge [ (lib.mkIf (cfg != { }) {
assertions = lib.concatLists (lib.mapAttrsToList (id: l: [
{
assertion = builtins.match "[A-Za-z0-9._-]+" id != null;
message = "steamFrame.launchers.\"${id}\": not a desktop ID (letters, digits, . _ -; without .desktop).";
}
{
assertion = lib.count (x: x != null) [ l.source.flatpak l.source.package l.source.file ] <= 1;
message = "steamFrame.launchers.\"${id}\": set only one of source.flatpak, source.package, source.file.";
}
{
assertion = L.kindOf l == "flatpak" || l.flatpakArgs == [ ];
message = "steamFrame.launchers.\"${id}\": flatpakArgs is only for Flatpaks (use args, env or wrappers).";
}
{
assertion = !l.keyring.electron || l.keyring.enable;
message = "steamFrame.launchers.\"${id}\": keyring.electron needs keyring.enable.";
}
{
assertion = lib.all (k: builtins.match "[A-Za-z0-9-]+" k != null) (lib.attrNames l.settings)
&& lib.all (v: v == null || !lib.hasInfix "\n" v) (lib.attrValues l.settings);
message = "steamFrame.launchers.\"${id}\".settings: keys are plain key names (no [locale]), values one line.";
}
]) all)
++ lib.mapAttrsToList (m: ds: {
assertion = lib.length ds == 1;
message = "steamFrame.launchers: ${m} is in defaultFor of ${lib.concatMapStringsSep " and " (d: "\"${d.id}\"") ds}.";
}) byMime;
xdg.dataFile = lib.mapAttrs' (id: _: lib.nameValuePair "applications/${id}.desktop" {
source = config.lib.file.mkOutOfStoreSymlink "${outDir}/${id}.desktop";
}) runtimeLaunchers // lib.mapAttrs' (id: l: lib.nameValuePair "applications/${id}.desktop" {
source = L.packageEntry l;
}) packageLaunchers;
xdg.mimeApps = lib.mkIf (defaults != [ ]) {
enable = true;
defaultApplications = mimeAttrs;
associations.added = mimeAttrs;
};
home.packages = lib.mkIf (runtimeLaunchers != { }) [ generator ];
systemd.user.services.steam-frame-nix-launchers = lib.mkIf (runtimeLaunchers != { }) {
Unit.Description = "steam-frame-nix: desktop entries of steamFrame.launchers";
Service = {
Type = "oneshot";
ExecStart = exe;
};
Install.WantedBy = [ "default.target" ];
};
# Flatpak touches .changed after installs, updates and removals.
systemd.user.paths.steam-frame-nix-launchers = lib.mkIf (runtimeLaunchers != { }) {
Unit.Description = "steam-frame-nix: rewrite launchers when their sources change";
Path = {
PathChanged = [
"${config.xdg.dataHome}/flatpak/.changed"
"/var/lib/flatpak/.changed"
] ++ exportDirs ++ lib.unique (lib.filter (f: f != null)
(lib.mapAttrsToList (_: l: l.source.file) runtimeLaunchers));
Unit = "steam-frame-nix-launchers.service";
};
Install.WantedBy = [ "default.target" ];
};
steamFrame.session.services.start =
lib.mkIf (runtimeLaunchers != { }) [ "steam-frame-nix-launchers.path" ];
}) {
# Also without launchers, to remove entries of ones no longer configured.
home.activation.steamFrameLaunchers = lib.hm.dag.entryAfter [ "linkGeneration" ] ''
if [[ ! -d ${lib.escapeShellArg session.runtimeDir} ]]; then
${lib.optionalString (runtimeLaunchers != { }) ''echo "steam-frame-nix: ${session.runtimeDir} doesn't exist (outer session not running?); launchers are written at its next login" >&2''}
:
elif [[ -v DRY_RUN ]]; then
echo "would run: STEAM_FRAME_NIX_RUNTIME_DIR=${session.runtimeDir} ${exe}"
else
STEAM_FRAME_NIX_RUNTIME_DIR=${lib.escapeShellArg session.runtimeDir} ${exe}
fi
'';
} ];
}
+191
View File
@@ -0,0 +1,191 @@
# Checks of steamFrame.launchers (lib.nix, rewrite.awk, generate.sh) on
# copies of real entries (fixtures/sources: Element, KRDC, Firefox, gedit
# (DBusActivatable) from /var/lib/flatpak, Jellyfin from the user
# installation, Claude from the claude-desktop package) and two made-up ones
# (quoting, an Exec without anchor):
# - the rewritten entries equal fixtures/expected (X-SteamFrameNix-Source
# compared separately) and pass desktop-file-validate;
# - the generator: unchanged sources change nothing (mtimes kept, no touch of
# the applications dir), a changed source is rewritten and touches it,
# entries of removed launchers and of missing sources are removed, an
# unknown Exec format gives the original entry with a warning, edits and
# replaced links are reported, no outer runtime dir is a no-op;
# - a package without the entry fails to build.
# The rewritten entries end up in $out/actual (to update fixtures/expected).
{ pkgs }:
let
inherit (pkgs) lib;
L = import ./lib.nix { inherit lib pkgs; };
src = ./fixtures/sources;
shim = "/nix/store/00000000000000000000000000000000-mpv-hwdec-shim";
fakeClaude = pkgs.runCommand "claude-desktop-fixture" { } ''
mkdir -p $out/share/applications
cp ${src}/com.anthropic.Claude.desktop $out/share/applications/
'';
noEntry = pkgs.runCommand "no-entry-fixture" { } "mkdir -p $out/share/applications";
launchers = (lib.evalModules {
modules = [ {
options.launchers = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule
(L.launcherModule { bus = "unix:path=/run/user/1000/bus"; }));
};
config.launchers = {
"im.riot.Riot" = {
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
};
"org.kde.krdc".keyring.enable = true;
"org.mozilla.firefox" = {
wrappers = [ "/nix/store/00000000000000000000000000000000-firefox-wrapper" ];
defaultFor = [ "x-scheme-handler/http" "x-scheme-handler/https" "text/html" ];
};
"org.jellyfin.JellyfinDesktop" = {
flatpakArgs = [ "--device=all" "--filesystem=${shim}:ro" ];
env = { LD_PRELOAD = "${shim}/lib/mpv-hwdec-shim.so"; SFN_MPV_HWDEC = "v4l2m2m-copy,auto-copy"; };
};
"org.gnome.gedit" = {
mimeTypes = [ "text/x-nix" "text/plain" ];
settings = { Name = "gedit (test)"; Keywords = null; StartupWMClass = "gedit"; };
};
"org.example.NoAnchor" = { };
"org.example.Quoting" = {
source.file = "${src}/org.example.Quoting.desktop";
wrappers = [ "/w/outer" "/w/in ner" ];
hostEnv.A = "x y";
env.B = "100%";
args = [ "a b" "50%" "q\"uote" "$HOME" "back\\slash" "back`tick" "" ];
settings.Keywords = "x;";
};
"com.anthropic.Claude" = {
source.package = fakeClaude;
keyring = { enable = true; electron = true; };
defaultFor = [ "x-scheme-handler/claude" ];
};
};
} ];
}).config.launchers;
all = lib.mapAttrs (id: l: l // { inherit id; }) launchers;
runtime = lib.filterAttrs (_: l: L.kindOf l != "package") all;
generator = L.generator {
launchers = runtime;
runtimeDir = "/nonexistent"; # overridden below
applicationsDir = "/nonexistent";
exportDirs = [ "/nonexistent" ];
};
empty = L.generator {
launchers = { };
runtimeDir = "/nonexistent";
applicationsDir = "/nonexistent";
exportDirs = [ "/nonexistent" ];
};
claude = L.packageEntry all."com.anthropic.Claude";
missing = pkgs.testers.testBuildFailure (L.packageEntry (all."com.anthropic.Claude" // {
source = all."com.anthropic.Claude".source // { package = noEntry; };
}));
in
pkgs.runCommand "launchers-check" {
nativeBuildInputs = [ generator pkgs.desktop-file-utils pkgs.diffutils ];
passthru = { inherit generator claude; };
} ''
set -euo pipefail
fail() { echo "FAIL: $*" >&2; exit 1; }
root=$PWD
export STEAM_FRAME_NIX_RUNTIME_DIR=$root/run
export STEAM_FRAME_NIX_APPLICATIONS_DIR=$root/apps
export STEAM_FRAME_NIX_FLATPAK_EXPORTS=$root/user:$root/system
out_dir=$root/run/steam-frame-nix/applications
mkdir -p $root/user $root/system $root/apps
for id in im.riot.Riot org.kde.krdc org.mozilla.firefox org.gnome.gedit org.example.NoAnchor; do
cp ${src}/$id.desktop $root/system/
done
cp ${src}/org.jellyfin.JellyfinDesktop.desktop $root/user/
# a user installation wins over the system one
cp ${src}/org.jellyfin.JellyfinDesktop.desktop $root/system/
chmod u+w $root/system/* $root/user/*
sed -i 's/^Name=Jellyfin$/Name=system copy/' $root/system/org.jellyfin.JellyfinDesktop.desktop
run() { steam-frame-nix-launchers 2> $root/log || fail "status $?: $(cat $root/log)"; cat $root/log >&2; }
logged() { grep -qF -- "$1" $root/log || fail "log lacks '$1': $(cat $root/log)"; }
mt() { stat -c %Y "$1"; }
old() { touch -d @1000000000 "$@"; }
# no outer runtime dir: nothing happens
run; logged "doesn't exist"; [ ! -e $root/run ] || fail "created the runtime dir"
mkdir -p $root/run
old $root/apps
run
[ "$(mt $root/apps)" != 1000000000 ] || fail "applications dir not touched"
logged "org.example.NoAnchor: unknown Exec format"
cmp -s ${src}/org.example.NoAnchor.desktop $out_dir/org.example.NoAnchor.desktop || fail "unknown Exec format: not the original"
mkdir -p $out/actual
for id in ${lib.concatStringsSep " " (lib.attrNames runtime)}; do
[ $id = org.example.NoAnchor ] && continue
cp $out_dir/$id.desktop $out/actual/
done
cp ${claude} $out/actual/com.anthropic.Claude.desktop
grep -qx "X-SteamFrameNix-Source=$root/user/org.jellyfin.JellyfinDesktop.desktop" $out/actual/org.jellyfin.JellyfinDesktop.desktop \
|| fail "Jellyfin not from the user installation"
grep -qx "X-SteamFrameNix-Source=$root/system/org.kde.krdc.desktop" $out/actual/org.kde.krdc.desktop || fail "KRDC source"
grep -qx "X-SteamFrameNix-Source=${src}/org.example.Quoting.desktop" $out/actual/org.example.Quoting.desktop || fail "file source"
grep -qx "X-SteamFrameNix-Source=${fakeClaude}/share/applications/com.anthropic.Claude.desktop" $out/actual/com.anthropic.Claude.desktop || fail "package source"
sed -i 's|^X-SteamFrameNix-Source=.*|X-SteamFrameNix-Source=@SOURCE@|' $out/actual/*.desktop
desktop-file-validate --no-hints $out/actual/*.desktop || fail "desktop-file-validate"
for f in ${./fixtures/expected}/*.desktop; do
diff -u $f $out/actual/''${f##*/} || fail "''${f##*/} differs from fixtures/expected"
done
[ "$(ls ${./fixtures/expected} | wc -l)" = "$(ls $out/actual | wc -l)" ] || fail "expected/actual count"
# unchanged: nothing written, applications dir untouched
old $root/apps $out_dir/*.desktop
run
[ "$(mt $root/apps)" = 1000000000 ] || fail "unchanged run touched the applications dir"
for f in $out_dir/*.desktop; do [ "$(mt $f)" = 1000000000 ] || fail "unchanged run rewrote $f"; done
# changed source: rewritten, dir touched
echo '# changed' >> $root/system/org.kde.krdc.desktop
run
logged "org.kde.krdc: entry written"
[ "$(mt $out_dir/org.kde.krdc.desktop)" != 1000000000 ] || fail "changed source not rewritten"
[ "$(mt $out_dir/im.riot.Riot.desktop)" = 1000000000 ] || fail "other entry rewritten"
[ "$(mt $root/apps)" != 1000000000 ] || fail "changed run didn't touch the applications dir"
grep -qx '# changed' $out_dir/org.kde.krdc.desktop || fail "comment not kept"
# launcher no longer configured, source gone: removed
echo stale > $out_dir/org.example.Old.desktop; echo x > $out_dir/.org.example.Old.desktop.sum
rm $root/system/org.gnome.gedit.desktop
old $root/apps
run
[ ! -e $out_dir/org.example.Old.desktop ] && [ ! -e $out_dir/.org.example.Old.desktop.sum ] || fail "stale entry kept"
[ ! -e $out_dir/org.gnome.gedit.desktop ] || fail "entry without source kept"
logged "org.gnome.gedit: entry removed (no source entry"
[ "$(mt $root/apps)" != 1000000000 ] || fail "removal didn't touch the applications dir"
# edited entry (e.g. KDE's editor writing through the link): overwritten
cp $out_dir/im.riot.Riot.desktop $root/riot
echo 'Name[de]=Edited' >> $out_dir/im.riot.Riot.desktop
run
logged "im.riot.Riot.desktop was edited"
cmp -s $root/riot $out_dir/im.riot.Riot.desktop || fail "edit not overwritten"
# replaced link: reported; our own link: not
ln -s $out_dir/im.riot.Riot.desktop $root/apps/im.riot.Riot.desktop
echo '[Desktop Entry]' > $root/apps/org.kde.krdc.desktop
run
logged "org.kde.krdc.desktop no longer leads to"
! grep -q "im.riot.Riot.desktop no longer" $root/log || fail "own link reported"
# no launchers left (the activation runs it anyway): all entries removed
old $root/apps
${lib.getExe empty} 2> $root/log || fail "empty: $(cat $root/log)"
[ -z "$(ls $out_dir)" ] || fail "entries left: $(ls $out_dir)"
[ "$(mt $root/apps)" != 1000000000 ] || fail "removal didn't touch the applications dir"
# a package without the entry: the build fails
[ -e ${missing}/testBuildFailure.log ] && grep -q "has no share/applications/com.anthropic.Claude.desktop" ${missing}/testBuildFailure.log \
|| fail "package without the entry built"
echo ok
''
@@ -0,0 +1,26 @@
[Desktop Entry]
Name=Claude
Comment=Desktop application for Claude.ai
GenericName=AI Assistant
Keywords=AI;Chat;Assistant;Claude;Code;LLM;
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop --password-store=kwallet6 %U
Icon=claude-desktop
Type=Application
StartupNotify=true
# Matches the Wayland app_id / X11 WM_CLASS Chromium derives from
# package.json desktopName, so docks group windows under this entry.
StartupWMClass=com.anthropic.Claude
# second-instance just focuses mainWindow; suppress GNOME's default "New Window" item
SingleMainWindow=true
Categories=Utility;Development;
MimeType=x-scheme-handler/claude;
Actions=NewChat;NewCode;
X-SteamFrameNix-Source=@SOURCE@
[Desktop Action NewChat]
Name=New Chat
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop --password-store=kwallet6 "claude://claude.ai/new?surface=chat&source=desktop_action"
[Desktop Action NewCode]
Name=New Claude Code Session
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop --password-store=kwallet6 "claude://code/new?source=desktop_action"
@@ -0,0 +1,12 @@
[Desktop Entry]
Type=Application
Name=Element
Comment=A Matrix-based instant messaging client
Icon=im.riot.Riot
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /usr/bin/flatpak run --branch=stable --arch=aarch64 --command=/app/bin/element --file-forwarding --talk-name=org.kde.kwalletd6 --talk-name=org.freedesktop.secrets im.riot.Riot --password-store=kwallet6 @@u %U @@
Categories=Network;InstantMessaging;Chat;VideoConference;
MimeType=x-scheme-handler/element;x-scheme-handler/io.element.desktop;
StartupWMClass=element
Keywords=Matrix;matrix.org;chat;irc;communications;talk;riot;vector;
X-Flatpak=im.riot.Riot
X-SteamFrameNix-Source=@SOURCE@
@@ -0,0 +1,18 @@
[Desktop Entry]
Type=Application
Name=Quoting test
Name[de]=Zitiertest
# a comment
Exec=env "A=x y" "B=100%%" /w/outer "/w/in ner" env FOO=1 "/opt/My App/bin/app" "a b" "50%%" "q\\"uote" "\\$HOME" "back\\\\slash" "back\\`tick" "" --flag "with \\"quote\\"" %F
Icon=app
Actions=second;
Keywords=x;
X-Unknown-Key=kept\sas is
X-SteamFrameNix-Source=@SOURCE@
[Desktop Action second]
Name=Second
Exec=env "A=x y" "B=100%%" /w/outer "/w/in ner" "/opt/My App/bin/app" "a b" "50%%" "q\\"uote" "\\$HOME" "back\\\\slash" "back\\`tick" "" --second
[X-Other Group]
Exec=untouched
@@ -0,0 +1,246 @@
[Desktop Entry]
Name=gedit (test)
Comment[af]=Redigeer tekslêers
Comment[am]=የጽሑፍ ፋይሎች ያስተካክሉ
Comment[an]=Edita fichers de texto
Comment[ar]=حرّر الملفات النصية
Comment[as]=লিখনি ফাইল সম্পাদনা
Comment[ast]=Editar ficheros de testu
Comment[az]=Mətn fayllarını redaktə edin
Comment[be]=Рэдагаванне тэкставых файлаў
Comment[be@latin]=Redahuj tekstavyja fajły
Comment[bg]=Редактиране на текстови файлове
Comment[bn]=টেক্সট ফাইল সম্পাদনা করুন
Comment[bn_IN]=টেক্সট ফাইল সম্পাদনা
Comment[br]=Embann restroù testenn
Comment[bs]=Izmijeni tekstualne datoteke
Comment[ca]=Editeu fitxers de text
Comment[ca@valencia]=Editeu fitxers de text
Comment[ckb]=دەق دەستکاریبکە
Comment[crh]=Metin dosyelerini tahrir et
Comment[cs]=Upravujte textové soubory
Comment[cy]=Golygu ffeiliau testun
Comment[da]=Redigér tekstfiler
Comment[de]=Textdateien bearbeiten
Comment[dz]=ཚིག་ཡིག་ཡིག་སྣོད་ཚུ་ ཞུན་དག་རྐྱབས་
Comment[el]=Επεξεργασία αρχείων κειμένου
Comment[en_CA]=Edit text files
Comment[en_GB]=Edit text files
Comment[en@shaw]=𐑧𐑛𐑦𐑑 𐑑𐑧𐑒𐑕𐑑 𐑓𐑲𐑤𐑟
Comment[eo]=Redakti tekstdosierojn
Comment[es]=Edite archivos de texto
Comment[et]=Tekstifailide redigeerimine
Comment[eu]=Editatu testu-fitxategiak
Comment[fa]=ویرایش پرونده‌های متنی
Comment[fi]=Muokkaa tekstitiedostoja
Comment[fr]=Éditer des fichiers texte
Comment[fur]=Modifiche file di test
Comment[ga]=Cuir comhaid téacs in eagar
Comment[gd]=Deasaich faidhlichean teacsa
Comment[gl]=Editar ficheiros de texto
Comment[gu]=લખાણ ફાઇલોમાં ફેરફાર કરો
Comment[he]=עריכת קובצי טקסט
Comment[hi]=पाठ फ़ाइलें संपादित करें
Comment[hr]=Uređivanje tekstovnih datoteka
Comment[hu]=Szövegfájlok szerkesztése
Comment[ia]=Rediger files de texto
Comment[id]=Menyunting berkas teks
Comment[ie]=Redacte files textual
Comment[is]=Sýsla með textaskrár
Comment[it]=Modifica file di testo
Comment[ja]=テキストファイルを編集します
Comment[ka]=ფაილების რედაქტირება
Comment[kab]=Ẓreg ifuyla n uḍris
Comment[kk]=Мәтіндік файлдарды түзету
Comment[km]=កែ​សម្រួល​ឯកសារ​អត្ថបទ
Comment[kn]=ಪಠ್ಯ ಕಡತಗಳನ್ನು ಸಂಪಾದಿಸು
Comment[ko]=텍스트 파일을 편집합니다
Comment[ku]=Pelên nivîsê sererast bike
Comment[ln]=Bɔngisa kásá ya nkomá
Comment[lt]=Redaguoti tekstinius failus
Comment[lv]=Rediģēt teksta datnes
Comment[mai]=पाठ फाइलकेँ संपादित करू
Comment[mg]=Hanova raki-dahabolana
Comment[mk]=Уредувај текстуални датотеки
Comment[ml]=പദാവലി ഫയലുകളില്‍ മാറ്റം വരുത്തുക
Comment[mn]=Текст файл боловсруулах
Comment[mr]=मजकूर फाइल्स् संपादीत करा
Comment[ms]=Sunting fail teks
Comment[my]=စာသားဖိုင်များပြင်ဆင်ရန်
Comment[nb]=Rediger tekstfiler
Comment[nds]=Textdateien bewarken
Comment[ne]=पाठ फाइल सम्पादन गर्नुहोस्
Comment[nl]=Bewerk tekstbestanden
Comment[nn]=Rediger tekstfiler
Comment[oc]=Editar de fichièrs tèxte
Comment[or]=ପାଠ୍ଯ ଫାଇଲଗୁଡ଼ିକୁ ସମ୍ପାଦନ କରନ୍ତୁ
Comment[pa]=ਲਿਖਤ ਫਾਇਲਾਂ ਸੋਧੋ
Comment[pl]=Edytor plików tekstowych
Comment[ps]=ليکن دوتنې سمول
Comment[pt]=Editar ficheiros de texto
Comment[pt_BR]=Edite arquivos de texto
Comment[ro]=Editare fișiere text
Comment[ru]=Редактор текстовых файлов
Comment[si]=පෙළ ගොනු සකසන්න
Comment[sk]=Úprava textových súborov
Comment[sl]=Enostavni urejevalnik besedilnih datotek
Comment[sq]=Ndrysho file teksti
Comment[sr]=Уређујте текстуалне документе
Comment[sr@latin]=Uređujte tekstualne dokumente
Comment[sv]=Redigera textfiler
Comment[ta]=உரை கோப்புகளை திருத்தவும்
Comment[te]=పాఠ్య ఫైళ్ళను సవరించు
Comment[th]=แก้ไขไฟล์ข้อความ
Comment[tk]=Metin faýllary editle
Comment[tr]=Metin dosyalarını düzenle
Comment[ug]=تېكىست ھۆججەتلىرىنى تەھرىرلەش
Comment[uk]=Редактор текстових файлів
Comment[vi]=Soạn thảo tập tin văn bản
Comment[wa]=Asspougnî des fitchîs tecses
Comment[xh]=Hlela iifayili zombhalo
Comment[zh_CN]=编辑文本文件
Comment[zh_HK]=編輯文字檔
Comment[zh_TW]=編輯文字檔
Comment=Edit text files
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=gedit --file-forwarding org.gnome.gedit @@u %U @@
Terminal=false
Type=Application
StartupNotify=true
MimeType=text/plain;application/x-zerosize;text/x-nix;
Icon=org.gnome.gedit
Categories=GNOME;GTK;Utility;TextEditor;
Actions=new-window;new-document;
DBusActivatable=false
X-Flatpak=org.gnome.gedit
StartupWMClass=gedit
X-SteamFrameNix-Source=@SOURCE@
[Desktop Action new-window]
Name[af]=Nuwe venster
Name[ar]=نافذة جديدة
Name[be]=Новае акно
Name[bg]=Нов прозорец
Name[bn_IN]=নতুন উইন্ডো
Name[ca]=Finestra nova
Name[ca@valencia]=_Finestra nova
Name[ckb]=پەنجەریەکی نوێ
Name[cs]=Nové okno
Name[da]=Nyt vindue
Name[de]=Neues Fenster
Name[el]=Νέο παράθυρο
Name[en_GB]=New Window
Name[eo]=Nova fenestro
Name[es]=Ventana nueva
Name[eu]=Leiho berria
Name[fa]=پنجره جدید
Name[fi]=Uusi ikkuna
Name[fr]=Nouvelle fenêtre
Name[fur]=Gnûf barcon
Name[gd]=Uinneag ùr
Name[gl]=_Xanela nova
Name[he]=חלון חדש
Name[hr]=Novi prozor
Name[hu]=Új ablak
Name[ia]=Nove fenestra
Name[id]=Jendela Baru
Name[ie]=Nov fenestre
Name[is]=Nýr gluggi
Name[it]=Nuova finestra
Name[ja]=新しいウィンドウ
Name[ka]=ახალი ფანჯარა
Name[kab]=Asfaylu amaynut
Name[kk]=Жаңа терезе
Name[ko]=새 창
Name[lt]=Naujas langas
Name[lv]=Jauns logs
Name[mjw]=Kimi Window
Name[ml]=പുതിയ ജാലകം
Name[ms]=Tetingkap Baharu
Name[nb]=Nytt vindu
Name[ne]=नयाँ सञ्झ्याल
Name[nl]=Nieuw venster
Name[oc]=Novèla fenèstra
Name[pa]=ਨਵੀਂ ਵਿੰਡੋ
Name[pl]=Nowe okno
Name[pt]=Nova janela
Name[pt_BR]=Nova janela
Name[ro]=Fereastră nouă
Name[ru]=Создать окно
Name[sk]=Nové okno
Name[sl]=Novo okno
Name[sr]=Нови прозор
Name[sr@latin]=Novi prozor
Name[sv]=Nytt fönster
Name[th]=หน้าต่างใหม่
Name[tr]=Yeni Pencere
Name[uk]=Створити вікно
Name[vi]=Cửa sổ mới
Name[zh_CN]=新建窗口
Name[zh_TW]=新增視窗
Name=New Window
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=gedit org.gnome.gedit --new-window
[Desktop Action new-document]
Name[af]=Nuwe dokument
Name[ar]=مستند جديد
Name[be]=Новы дакумент
Name[bg]=Нов документ
Name[bn_IN]=নতুন ডকুমেন্ট
Name[ca]=Crea un document nou
Name[ca@valencia]=Crea un document nou
Name[ckb]=بەڵگەنامەی نوێ
Name[cs]=Nový dokument
Name[da]=Nyt dokument
Name[de]=Neues Dokument
Name[el]=Νέο έγγραφο
Name[en_GB]=New Document
Name[eo]=Nova dokumento
Name[es]=Documento nuevo
Name[eu]=Dokumentu berria
Name[fa]=سند جدید
Name[fi]=Uusi asiakirja
Name[fr]=Nouveau document
Name[fur]=Gnûf document
Name[gd]=Sgrìobhainn ùr
Name[gl]=Novo documento
Name[he]=מסמך חדש
Name[hr]=Novi dokument
Name[hu]=Új dokumentum
Name[ia]=Nove documento
Name[id]=Dokumen Baru
Name[ie]=Nov document
Name[is]=Nýtt skjal
Name[it]=Nuovo documento
Name[ja]=新しいドキュメント
Name[ka]=ახალი დოკუმენტი
Name[kab]=Isemli amaynut
Name[kk]=Жаңа құжат
Name[ko]=새 문서
Name[lt]=Naujas dokumentas
Name[lv]=Jauns dokuments
Name[mjw]=Kimi Document
Name[ml]=പൂതിയ രേഖ
Name[ms]=Dokumen Baharu
Name[nb]=Nytt dokument
Name[ne]=नयाँ कागजात
Name[nl]=Nieuw document
Name[oc]=Novèl document
Name[pa]=ਨਵਾਂ ਡੌਕੂਮੈਂਟ
Name[pl]=Nowy dokument
Name[pt]=Novo documento
Name[pt_BR]=Novo documento
Name[ro]=Document nou
Name[ru]=Создать документ
Name[sk]=Nový dokument
Name[sl]=Nov dokument
Name[sr]=Нови документ
Name[sr@latin]=Novi dokument
Name[sv]=Nytt dokument
Name[th]=เอกสารใหม่
Name[tr]=Yeni Belge
Name[uk]=Створити документ
Name[vi]=Tài liệu mới
Name[zh_CN]=新建文档
Name[zh_TW]=新增文件
Name=New Document
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=gedit org.gnome.gedit --new-document
@@ -0,0 +1,29 @@
[Desktop Entry]
Version=1.0
Name=Jellyfin
Comment=Desktop client for Jellyfin
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop --device=all --filesystem=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro --env=LD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so --env=SFN_MPV_HWDEC=v4l2m2m-copy,auto-copy org.jellyfin.JellyfinDesktop
Icon=org.jellyfin.JellyfinDesktop
Terminal=false
Type=Application
StartupWMClass=org.jellyfin.JellyfinDesktop
Categories=AudioVideo;Video;Player;TV;
Actions=DesktopF;DesktopW;TVF;TVW
X-Flatpak=org.jellyfin.JellyfinDesktop
X-SteamFrameNix-Source=@SOURCE@
[Desktop Action DesktopF]
Name=Desktop [Fullscreen]
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop --device=all --filesystem=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro --env=LD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so --env=SFN_MPV_HWDEC=v4l2m2m-copy,auto-copy org.jellyfin.JellyfinDesktop --fullscreen --desktop
[Desktop Action DesktopW]
Name=Desktop [Windowed]
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop --device=all --filesystem=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro --env=LD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so --env=SFN_MPV_HWDEC=v4l2m2m-copy,auto-copy org.jellyfin.JellyfinDesktop --windowed --desktop
[Desktop Action TVF]
Name=TV [Fullscreen]
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop --device=all --filesystem=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro --env=LD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so --env=SFN_MPV_HWDEC=v4l2m2m-copy,auto-copy org.jellyfin.JellyfinDesktop --fullscreen --tv
[Desktop Action TVW]
Name=TV [Windowed]
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop --device=all --filesystem=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim:ro --env=LD_PRELOAD=/nix/store/00000000000000000000000000000000-mpv-hwdec-shim/lib/mpv-hwdec-shim.so --env=SFN_MPV_HWDEC=v4l2m2m-copy,auto-copy org.jellyfin.JellyfinDesktop --windowed --tv
@@ -0,0 +1,182 @@
[Desktop Entry]
Type=Application
Exec=env DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus /usr/bin/flatpak run --branch=stable --arch=aarch64 --command=/app/bin/krdc --file-forwarding --talk-name=org.kde.kwalletd6 --talk-name=org.freedesktop.secrets org.kde.krdc -qwindowtitle %c @@u %u @@
Icon=org.kde.krdc
Terminal=false
Name=KRDC
Name[ar]=كردس
Name[az]=KRDC
Name[bg]=KRDC
Name[bs]=KRDC
Name[ca]=KRDC
Name[ca@valencia]=KRDC
Name[cs]=KRDC
Name[da]=KRDC
Name[de]=KRDC
Name[el]=KRDC
Name[en_GB]=KRDC
Name[eo]=KRDC
Name[es]=KRDC
Name[et]=KRDC
Name[eu]=KRDC
Name[fi]=KRDC
Name[fr]=KRDC
Name[ga]=KRDC
Name[gl]=KRDC
Name[he]=KRDC
Name[hne]=केआरडीसी
Name[hr]=KRDC
Name[hu]=KRDC
Name[ia]=KRDC
Name[is]=KRDC
Name[it]=KRDC
Name[ja]=KRDC
Name[ka]=KRDC
Name[kk]=KRDC
Name[km]=KRDC
Name[ko]=KRDC
Name[lt]=KRDC
Name[lv]=KRDC
Name[ml]=കെആര്‍ഡിസി
Name[mr]=के-आर-डी-सी
Name[nb]=KRDC
Name[nds]=KRDC
Name[nl]=KRDC
Name[nn]=KRDC
Name[pa]=KRDC
Name[pl]=KRDC
Name[pt]=KRDC
Name[pt_BR]=KRDC
Name[ro]=KRDC
Name[ru]=KRDC
Name[sa]=केआरडीसी
Name[si]=KRDC
Name[sk]=KRDC
Name[sl]=KRDC
Name[sq]=KRDC
Name[sr]=КРДЦ
Name[sr@ijekavian]=КРДЦ
Name[sr@ijekavianlatin]=KRDC
Name[sr@latin]=KRDC
Name[sv]=KRDC
Name[tr]=KRDC
Name[ug]=KRDC
Name[uk]=KRDC
Name[wa]=KRDC
Name[zh_CN]=KRDC
Name[zh_TW]=遠端桌面_KRDC
GenericName=Remote Desktop Client
GenericName[ar]=عميل سطح المكتب البعيد
GenericName[az]=İş masasının uzaqdan idarə olunması
GenericName[bg]=Отдалечен работен плот
GenericName[bs]=Klijent udaljene radne površine
GenericName[ca]=Client d'escriptori remot
GenericName[ca@valencia]=Client d'escriptori remot
GenericName[cs]=Klient vzdálené pracovní plochy
GenericName[da]=Klient til fjernskrivebord
GenericName[de]=Verbindung zu entferntem Rechner
GenericName[el]=Πελάτης απομακρυσμένης επιφάνειας εργασίας
GenericName[en_GB]=Remote Desktop Client
GenericName[eo]=Kliento por fora labortablo
GenericName[es]=Cliente de escritorio remoto
GenericName[et]=Kaugtöölaua klient
GenericName[eu]=Urruneko mahaigainaren bezeroa
GenericName[fi]=Etätyöpöytäasiakas
GenericName[fr]=Connexion à un bureau distant
GenericName[ga]=Cliant Deisce Cianda
GenericName[gl]=Cliente de escritorio remoto
GenericName[he]=לקוח שולחן עבודה מרוחק
GenericName[hne]=रिमोट डेस्कटाप क्लाएंट
GenericName[hr]=Klijent za udaljeno povezivanje
GenericName[hu]=Távoli asztal kliens
GenericName[ia]=Cliente de scriptorio remote
GenericName[is]=Tengingar við fjarlæg skjáborð
GenericName[it]=Client per connessione a desktop remoto
GenericName[ja]=リモートデスクトップクライアント
GenericName[ka]=დისტანციური სამუშაო მაგიდის კლიენტი
GenericName[kk]=Қашықтан үстелге қосылу клиенті
GenericName[km]=កម្មវិធី​មើល​ផ្ទៃតុ​ពី​ចម្ងាយ
GenericName[ko]=원격 데스크톱 클라이언트
GenericName[lt]=Nuotolinio darbalaukio kliento programa
GenericName[lv]=Attālās darbvirsmas klients
GenericName[ml]=വിദൂര പണിയിട ക്ലയന്റ്
GenericName[mr]=दूरस्थ डेस्कटॉप ग्राहक
GenericName[nb]=Tilkobling til annet skrivebord
GenericName[nds]=Schriefdisch-Feernverbinnen
GenericName[nl]=Client voor verbinding met extern bureaublad
GenericName[nn]=Tilkopling til eksternt skrivebord
GenericName[pa]=ਰਿਮੋਟ ਡੈਸਕਟਾਪ ਕਲਾਈਟ
GenericName[pl]=Klient zdalnego dostępu do pulpitu
GenericName[pt]=Cliente de Ecrãs Remotos
GenericName[pt_BR]=Cliente de área de trabalho remota
GenericName[ro]=Client pentru birou la distanță
GenericName[ru]=Удалённый доступ к рабочему столу
GenericName[sa]=दूरस्थ डेस्कटॉप क्लायन्ट
GenericName[si]=දුරස්ථ වැඩතල යෙදුම
GenericName[sk]=Klient vzdialenej pracovnej plochy
GenericName[sl]=Odjemalec za oddaljena namizja
GenericName[sr]=Клијент удаљене површи
GenericName[sr@ijekavian]=Клијент удаљене површи
GenericName[sr@ijekavianlatin]=Klijent udaljene površi
GenericName[sr@latin]=Klijent udaljene površi
GenericName[sv]=Fjärranslutning till skrivbord
GenericName[th]=ไคลเอนต์เชื่อมต่อพื้นที่ทำงานทางไกล
GenericName[tr]=Uzak Masaüstü İstemcisi
GenericName[ug]=يىراقتىكى ئۈستەلئۈستى خېرىدارى
GenericName[uk]=Клієнт з'єднання з віддаленою стільницею
GenericName[zh_CN]=远程桌面客户端
GenericName[zh_TW]=遠端桌面用戶端
Comment=Connect with RDP or VNC to another computer
Comment[ar]=اتصل حاسوب آخر بواسطة RDP أو VNC
Comment[az]=RDP və ya VNC ilə başqa kompüterə qoşulun
Comment[bg]=Свързване чрез RDP or VNC с друг компютър
Comment[ca]=Connecta amb RDP o VNC a un altre ordinador
Comment[ca@valencia]=Connecta amb RDP o VNC a un altre ordinador
Comment[cs]=Připojte se k jinému počítači pomocí RDP nebo VNC
Comment[da]=Opret forbindelse til en anden computer med RDP eller VNC
Comment[de]=Verbindung mit RDP oder VNC zu einem anderen Rechner
Comment[el]=Σύνδεση με RDP ή VNC σε άλλον υπολογιστή
Comment[en_GB]=Connect with RDP or VNC to another computer
Comment[eo]=Konektiĝi per RDP aŭ VNC al alia komputilo
Comment[es]=Conectar con RDP o VNC a otro equipo
Comment[et]=Ühendumine RDP või VNC vahendusel teise arvutiga
Comment[eu]=Konektatu RDP edo VNC bidez beste ordenagailu batera
Comment[fi]=Yhdistä RDP:llä tai VNC:llä toiseen tietokoneeseen
Comment[fr]=Se connecter à un autre ordinateur avec RDP ou VNC
Comment[gl]=Conectarse por RDP ou VNC a outro computador.
Comment[he]=התחברות ל־RDP או ל־VNC במחשב אחר
Comment[hu]=Csatlakozás másik számítógéphez RDP-vel vagy VNC-vel
Comment[ia]=Connecte con RDP o VNC a un altere computator
Comment[is]=Tengstu með RDP eða VNC við aðrar tölvur
Comment[it]=Connessione via RDP o VNC ad un altro computer
Comment[ka]=მიუერთდით მოშორებულ კომპიუტერზე RDP ან VNC პროტოკოლით
Comment[ko]=다른 컴퓨터에 RDP나 VNC로 연결
Comment[lt]=Prisijungti prie kito kompiuterio naudojant RDP ar VNC
Comment[lv]=Izmantojiet RDP vai VNC, lai pievienotos citam datoram
Comment[nl]=Met RDP of VNC naar een andere computer verbinden
Comment[nn]=Kopla til ei anna datamaskin via RDP eller VNC
Comment[pl]=Połącz się przy użyciu RDP lub VNC do innego komputera
Comment[pt]=Ligar-se com RDP ou VNC a outro computador
Comment[pt_BR]=Conecte com RDP ou VNC em outro computador
Comment[ro]=Conectare la alt calculator prin RDP sau VNC
Comment[ru]=Подключение к другому компьютеру по RDP или VNC
Comment[sa]=RDP अथवा VNC इत्यनेन सह अन्यसङ्गणकेन सह सम्बद्धं कुर्वन्तु
Comment[sk]=Pripojiť pomocou RDP alebo VNC k inému počítaču
Comment[sl]=Povežite se preko RDP-ja ali VNC-ja z drugim računalnikom
Comment[sq]=Lidhu me një kompjuter tjetër përmes RDP ose VNC
Comment[sr]=Повежите се РДП‑ом или ВНЦ‑ом са другим рачунаром
Comment[sr@ijekavian]=Повежите се РДП‑ом или ВНЦ‑ом са другим рачунаром
Comment[sr@ijekavianlatin]=Povežite se RDP‑om ili VNC‑om sa drugim računarom
Comment[sr@latin]=Povežite se RDP‑om ili VNC‑om sa drugim računarom
Comment[sv]=Anslut till en annan dator med RDP eller VNC
Comment[tr]=Başka bir bilgisayara RDP veya VNC ile bağlan
Comment[uk]=З'єднання з іншим комп'ютером за допомогою RDP або VNC
Comment[zh_CN]=通过 RDP 或 VNC 连接到另一台计算机
Comment[zh_TW]=以 RDP 或 VNC 連線到其他電腦
X-DocPath=krdc/index.html
StartupWMClass=krdc
MimeType=x-scheme-handler/vnc;x-scheme-handler/rdp;application/x-krdc;
Categories=Qt;KDE;Network;RemoteAccess;
X-KDE-Wayland-Interfaces=org_kde_kwin_keystate
X-Flatpak=org.kde.krdc
X-SteamFrameNix-Source=@SOURCE@
@@ -0,0 +1,848 @@
[Desktop Entry]
Version=1.0
Type=Application
Exec=/nix/store/00000000000000000000000000000000-firefox-wrapper /usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox @@u %u @@
Terminal=false
X-MultipleArgs=false
Icon=org.mozilla.firefox
StartupWMClass=firefox
DBusActivatable=false
Categories=GNOME;GTK;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;
StartupNotify=true
Actions=new-window;new-private-window;open-profile-manager;
Name=Firefox
Name[ach]=Firefox
Name[af]=Firefox
Name[an]=Firefox
Name[ar]=Firefox
Name[ast]=Firefox
Name[az]=Firefox
Name[be]=Firefox
Name[bg]=Firefox
Name[bn]=Firefox
Name[br]=Firefox
Name[bs]=Firefox
Name[ca]=Firefox
Name[ca_valencia]=Firefox
Name[cak]=Firefox
Name[cs]=Firefox
Name[cy]=Firefox
Name[da]=Firefox
Name[de]=Firefox
Name[dsb]=Firefox
Name[el]=Firefox
Name[en_CA]=Firefox
Name[en_GB]=Firefox
Name[eo]=Firefox
Name[es_AR]=Firefox
Name[es_CL]=Firefox
Name[es_ES]=Firefox
Name[es_MX]=Firefox
Name[et]=Firefox
Name[eu]=Firefox
Name[fa]=Firefox
Name[ff]=Firefox
Name[fi]=Firefox
Name[fr]=Firefox
Name[fur]=Firefox
Name[fy_NL]=Firefox
Name[ga_IE]=Firefox
Name[gd]=Firefox
Name[gl]=Firefox
Name[gn]=Firefox
Name[gu_IN]=Firefox
Name[he]=Firefox
Name[hi_IN]=Firefox
Name[hr]=Firefox
Name[hsb]=Firefox
Name[hu]=Firefox
Name[hy_AM]=Firefox
Name[ia]=Firefox
Name[id]=Firefox
Name[is]=Firefox
Name[it]=Firefox
Name[ja]=Firefox
Name[ka]=Firefox
Name[kab]=Firefox
Name[kk]=Firefox
Name[km]=Firefox
Name[kn]=Firefox
Name[ko]=Firefox
Name[lij]=Firefox
Name[lt]=Firefox
Name[lv]=Firefox
Name[mk]=Firefox
Name[mr]=Firefox
Name[ms]=Firefox
Name[my]=Firefox
Name[nb_NO]=Firefox
Name[ne_NP]=Firefox
Name[nl]=Firefox
Name[nn_NO]=Firefox
Name[oc]=Firefox
Name[pa_IN]=Firefox
Name[pl]=Firefox
Name[pt_BR]=Firefox
Name[pt_PT]=Firefox
Name[rm]=Firefox
Name[ro]=Firefox
Name[ru]=Firefox
Name[sat]=Firefox
Name[sc]=Firefox
Name[sco]=Firefox
Name[si]=Firefox
Name[sk]=Firefox
Name[skr]=Firefox
Name[sl]=Firefox
Name[son]=Firefox
Name[sq]=Firefox
Name[sr]=Firefox
Name[sv_SE]=Firefox
Name[szl]=Firefox
Name[ta]=Firefox
Name[te]=Firefox
Name[tg]=Firefox
Name[th]=Firefox
Name[tl]=Firefox
Name[tr]=Firefox
Name[trs]=Firefox
Name[uk]=Firefox
Name[ur]=Firefox
Name[uz]=Firefox
Name[vi]=Firefox
Name[xh]=Firefox
Name[zh_CN]=Firefox
Name[zh_TW]=Firefox
Comment=Fast and private browser
Comment[ach]=Fast and private browser
Comment[af]=Fast and private browser
Comment[an]=Fast and private browser
Comment[ar]=متصفح سريع وخاص
Comment[ast]=Fast and private browser
Comment[az]=Fast and private browser
Comment[be]=Хуткі і прыватны браўзер
Comment[bg]=Fast and private browser
Comment[bn]=Fast and private browser
Comment[br]=Fast and private browser
Comment[bs]=Fast and private browser
Comment[ca]=Navegador ràpid i privat
Comment[ca_valencia]=Fast and private browser
Comment[cak]=Fast and private browser
Comment[cs]=Rychlý a soukromý prohlížeč
Comment[cy]=Porwr cyflym a phreifat
Comment[da]=Hurtig og privat browser
Comment[de]=Schneller und privater Browser
Comment[dsb]=Malsny a priwatny wobglědowak
Comment[el]=Γρήγορο και ιδιωτικό πρόγραμμα περιήγησης
Comment[en_CA]=Fast and private browser
Comment[en_GB]=Fast and private browser
Comment[eo]=Rapida kaj privata retumilo
Comment[es_AR]=Navegador rápido y privado
Comment[es_CL]=Navegador rápido y privado
Comment[es_ES]=Navegador rápido y privado
Comment[es_MX]=Navegación web rápida y privada
Comment[et]=Fast and private browser
Comment[eu]=Nabigatzaile bizkor eta pribatua
Comment[fa]=Fast and private browser
Comment[ff]=Fast and private browser
Comment[fi]=Nopea ja yksityinen selain
Comment[fr]=Navigateur rapide et privé
Comment[fur]=Navigadôr svelt e riservât
Comment[fy_NL]=Flugge en priveebrowser
Comment[ga_IE]=Fast and private browser
Comment[gd]=Fast and private browser
Comment[gl]=Fast and private browser
Comment[gn]=Kundahára ipya’e ha hekoñemíva
Comment[gu_IN]=Fast and private browser
Comment[he]=דפדפן מהיר ופרטי
Comment[hi_IN]=Fast and private browser
Comment[hr]=Brz i privatan preglednik
Comment[hsb]=Spěšny a priwatny wobhladowak
Comment[hu]=Gyors és privát böngésző
Comment[hy_AM]=Արագ և գաղտնի դիտարկիչ
Comment[ia]=Navigator veloce e private
Comment[id]=Fast and private browser
Comment[is]=Hraður og persónulegur vafri
Comment[it]=Browser veloce e riservato
Comment[ja]=高速プライベートブラウザー
Comment[ka]=სწრაფი და პირადი ბრაუზერი
Comment[kab]=Iminig arurad, uslig
Comment[kk]=Жылдам және жеке браузер
Comment[km]=Fast and private browser
Comment[kn]=Fast and private browser
Comment[ko]=빠르고 사생활을 보호하는 브라우저
Comment[lij]=Fast and private browser
Comment[lt]=Fast and private browser
Comment[lv]=Fast and private browser
Comment[mk]=Fast and private browser
Comment[mr]=Fast and private browser
Comment[ms]=Fast and private browser
Comment[my]=Fast and private browser
Comment[nb_NO]=Rask og privat nettleser
Comment[ne_NP]=Fast and private browser
Comment[nl]=Snelle en privébrowser
Comment[nn_NO]=Rask og privat nettlesar
Comment[oc]=Fast and private browser
Comment[pa_IN]=ਤੇਜ਼ ਅਤੇ ਪ੍ਰਾਈਵੇਟ ਬਰਾਊਜ਼ਰ
Comment[pl]=Szybka i prywatna przeglądarka
Comment[pt_BR]=Navegador rápido e privativo
Comment[pt_PT]=Navegador rápido e privado
Comment[rm]=Navigatur svelt e privat
Comment[ro]=Browser rapid și privat
Comment[ru]=Быстрый и приватный браузер
Comment[sat]=Fast and private browser
Comment[sc]=Navigadore lestru e privadu
Comment[sco]=Fast and private browser
Comment[si]=Fast and private browser
Comment[sk]=Rýchly a súkromný prehliadač
Comment[skr]=Fast and private browser
Comment[sl]=Hiter in zaseben brskalnik
Comment[son]=Fast and private browser
Comment[sq]=Shfletues i shpejtë dhe privat
Comment[sr]=Брз и приватан веб прегледач
Comment[sv_SE]=Snabb och privat webbläsare
Comment[szl]=Fast and private browser
Comment[ta]=Fast and private browser
Comment[te]=Fast and private browser
Comment[tg]=Браузери тезкор ва хусусӣ
Comment[th]=เบราว์เซอร์ที่รวดเร็วและเป็นส่วนตัว
Comment[tl]=Fast and private browser
Comment[tr]=Hızlı ve gizli tarayıcı
Comment[trs]=Fast and private browser
Comment[uk]=Швидкий і приватний браузер
Comment[ur]=Fast and private browser
Comment[uz]=Fast and private browser
Comment[vi]=Trình duyệt nhanh và riêng tư
Comment[xh]=Fast and private browser
Comment[zh_CN]=快速且私密的浏览器
Comment[zh_TW]=快速又有隱私的瀏覽器
GenericName=Web Browser
GenericName[ach]=Web Browser
GenericName[af]=Web Browser
GenericName[an]=Web Browser
GenericName[ar]=متصفح الوِب
GenericName[ast]=Web Browser
GenericName[az]=Web Browser
GenericName[be]=Вэб-браўзер
GenericName[bg]=Уеб браузър
GenericName[bn]=ওয়েব ব্রাউজার
GenericName[br]=Merdeer Web
GenericName[bs]=Web pretraživač
GenericName[ca]=Navegador web
GenericName[ca_valencia]=Web Browser
GenericName[cak]=Web Okik'amaya'l
GenericName[cs]=Webový prohlížeč
GenericName[cy]=Porwr Gwe
GenericName[da]=Webbrowser
GenericName[de]=Internet-Browser
GenericName[dsb]=Webwobglědowak
GenericName[el]=Πρόγραμμα περιήγησης
GenericName[en_CA]=Web Browser
GenericName[en_GB]=Web Browser
GenericName[eo]=Retumilo
GenericName[es_AR]=Navegador web
GenericName[es_CL]=Navegador Web
GenericName[es_ES]=Navegador web
GenericName[es_MX]=Navegador Web
GenericName[et]=Web Browser
GenericName[eu]=Web nabigatzailea
GenericName[fa]=مرورگر وب
GenericName[ff]=Web Browser
GenericName[fi]=Verkkoselain
GenericName[fr]=Navigateur web
GenericName[fur]=Navigadôr Web
GenericName[fy_NL]=Webbrowser
GenericName[ga_IE]=Web Browser
GenericName[gd]=Brabhsair-lìn
GenericName[gl]=Navegador web
GenericName[gn]=Ñanduti Kundahára
GenericName[gu_IN]=Web Browser
GenericName[he]=דפדפן אינטרנט
GenericName[hi_IN]=Web Browser
GenericName[hr]=Web preglednik
GenericName[hsb]=Webwobhladowak
GenericName[hu]=Webböngésző
GenericName[hy_AM]=Վեբ դիտարկիչ
GenericName[ia]=Navigator web
GenericName[id]=Peramban Web
GenericName[is]=Vafri
GenericName[it]=Browser web
GenericName[ja]=ウェブブラウザー
GenericName[ka]=ბრაუზერი
GenericName[kab]=Iminig web
GenericName[kk]=Веб-браузері
GenericName[km]=Web Browser
GenericName[kn]=Web Browser
GenericName[ko]=웹 브라우저
GenericName[lij]=Navegatô Web
GenericName[lt]=Web Browser
GenericName[lv]=Tīmekļa pārlūks
GenericName[mk]=Web Browser
GenericName[mr]=Web Browser
GenericName[ms]=Web Browser
GenericName[my]=Web Browser
GenericName[nb_NO]=Nettleser
GenericName[ne_NP]=वेब ब्राउजर
GenericName[nl]=Webbrowser
GenericName[nn_NO]=Nettlesar
GenericName[oc]=Navegador Web
GenericName[pa_IN]=ਵੈੱਬ ਬਰਾਊਜ਼ਰ
GenericName[pl]=Przeglądarka internetowa
GenericName[pt_BR]=Navegador web
GenericName[pt_PT]=Navegador Web
GenericName[rm]=Navigatur web
GenericName[ro]=Browser web
GenericName[ru]=Веб-браузер
GenericName[sat]=ᱣᱮᱵᱽ ᱵᱽᱨᱟᱣᱡᱚᱨ
GenericName[sc]=Navigadore web
GenericName[sco]=Web Browser
GenericName[si]=වියමන අතිරික්සුව
GenericName[sk]=Webový prehliadač
GenericName[skr]=ویب براؤزر
GenericName[sl]=Spletni brskalnik
GenericName[son]=Web Browser
GenericName[sq]=Shfletues
GenericName[sr]=Веб прегледач
GenericName[sv_SE]=Webbläsare
GenericName[szl]=Web Browser
GenericName[ta]=Web Browser
GenericName[te]=జాల విహారిణి
GenericName[tg]=Браузери веб
GenericName[th]=เว็บเบราว์เซอร์
GenericName[tl]=Web Browser
GenericName[tr]=Web Tarayıcısı
GenericName[trs]=Web riña gāchē nu’
GenericName[uk]=Браузер
GenericName[ur]=Web Browser
GenericName[uz]=Web Browser
GenericName[vi]=Trình duyệt web
GenericName[xh]=Web Browser
GenericName[zh_CN]=Web 浏览器
GenericName[zh_TW]=網頁瀏覽器
Keywords=Internet;WWW;Browser;Web;Explorer;
Keywords[ach]=Internet;WWW;Browser;Web;Explorer;
Keywords[af]=Internet;WWW;Browser;Web;Explorer;
Keywords[an]=Internet;WWW;Browser;Web;Explorer;
Keywords[ar]=إنترنت;WWW;متصفح;ويب;مستكشف;
Keywords[ast]=Internet;WWW;Browser;Web;Explorer;
Keywords[az]=Internet;WWW;Browser;Web;Explorer;
Keywords[be]=Internet;WWW;Browser;Web;Explorer;
Keywords[bg]=Internet;WWW;Browser;Web;Explorer;
Keywords[bn]=ইন্টারনেট;WWW;ব্রাউজার;ওয়েব;এক্সপ্লোরার;
Keywords[br]=Internet;WWW;Merdeer;Web;Ergerzhout;
Keywords[bs]=Internet;WWW;Pretraživač;Web;Istraživač;
Keywords[ca]=Internet;WWW;Browser;Web;Explorador;Navegador;
Keywords[ca_valencia]=Internet;WWW;Browser;Web;Explorer;
Keywords[cak]=K'amaya'l;WWW;Okik'amaya'l;Kanob'äl;
Keywords[cs]=internet;WWW;prohlížeč;web;
Keywords[cy]=Rhyngrwyd;WWW;Porwr;Gwe;Archwiliwr;
Keywords[da]=Internet;WWW;Browser;Nettet;Explorer;
Keywords[de]=Internet;WWW;Browser;Web;Explorer;
Keywords[dsb]=Internet;WWW;wobglědowak;Web;Explorer;
Keywords[el]=Internet;WWW;Browser;Web;Explorer;Διαδίκτυο;Ιστός;Ίντερνετ;
Keywords[en_CA]=Internet;WWW;Browser;Web;Explorer;
Keywords[en_GB]=Internet;WWW;Browser;Web;Explorer;
Keywords[eo]=Interreto;Retumilo;TTT;Teksaĵo;Reto;Internet;WWW;Browser;Web;Explorer;
Keywords[es_AR]=Internet;WWW;Navegador;Web;Explorador;
Keywords[es_CL]=Internet;WWW;Navegador;Web;Explorador;
Keywords[es_ES]=Internet;WWW;Navegador;Web;Explorador;
Keywords[es_MX]=Internet;WWW;Navegador;Web;Explorador;
Keywords[et]=Internet;WWW;Browser;Web;Explorer;
Keywords[eu]=Internet;WWW;Nabigatzailea;Web;Arakatzailea;
Keywords[fa]=Internet;WWW;Browser;Web;Explorer;
Keywords[ff]=Internet;WWW;Browser;Web;Explorer;
Keywords[fi]=Internet;WWW;Browser;Web;Explorer;netti;webbi;selain;
Keywords[fr]=Internet;WWW;Navigateur;Web;Explorer;
Keywords[fur]=Internet;WWW;Browser;Navigadôr;Web;Esploradôr;Explorer;
Keywords[fy_NL]=Ynternet;WWW;Browser;Web;Ferkenner;
Keywords[ga_IE]=Internet;WWW;Browser;Web;Explorer;
Keywords[gd]=Internet;WWW;Browser;Web;Explorer;eadar-lìon;brabhsair;brobhsair;lìon;taisgealaiche;
Keywords[gl]=Internet;WWW;Navegador;Web;Explorador;
Keywords[gn]=Internet;WWW;Browser;Web;Explorer;
Keywords[gu_IN]=Internet;WWW;Browser;Web;Explorer;
Keywords[he]=אינטרנט;WWW;דפדפן;רשת;סייר;מרשתת;
Keywords[hi_IN]=Internet;WWW;Browser;Web;Explorer;
Keywords[hr]=Internet;WWW;Preglednik;Web;Istraživač;
Keywords[hsb]=Internet;WWW;wobhladowak;Web;Explorer;
Keywords[hu]=Internet;WWW;Böngésző;Web;Világháló;
Keywords[hy_AM]=Համացանց,WWW,Զննիչ,Վեբ,Ցանցախույզ:
Keywords[ia]=Internet;WWW;Navigator;Web;Explorator;
Keywords[id]=Internet;WWW;Browser;Web;Explorer;
Keywords[is]=Internet;WWW; Vafri; Vefur; Explorer;
Keywords[it]=Internet;WWW;Browser;Web;Explorer;Navigatore;
Keywords[ja]=Internet;WWW;Browser;Web;Explorer;インターネット;ブラウザー;ウェブ;
Keywords[ka]=ინტერნეტი;WWW;ბრაუზერი;ქსელი;ქსელთან წვდომა;
Keywords[kab]=Internet;WWW;Browser;Web;Explorer;
Keywords[kk]=Internet;WWW;Browser;Web;Explorer;Интернет;Ғаламтор;Браузер;Желі;Шолғыш;
Keywords[km]=Internet;WWW;Browser;Web;Explorer;
Keywords[kn]=Internet;WWW;Browser;Web;Explorer;
Keywords[ko]=인터넷;브라우저;웹;탐색기;Internet;WWW;Browser;Web;Explorer;
Keywords[lij]=Internet;WWW;Browser;Web;Explorer;Navegatô;
Keywords[lt]=Internet;WWW;Browser;Web;Explorer;
Keywords[lv]=Internets;WWW;Pārlūkprogramma;Tīmeklis;
Keywords[mk]=Internet;WWW;Browser;Web;Explorer;
Keywords[mr]=Internet;WWW;Browser;Web;Explorer;
Keywords[ms]=Internet;WWW;Browser;Web;Explorer;
Keywords[my]=Internet;WWW;Browser;Web;Explorer;
Keywords[nb_NO]=Internett;WWW;Nettleser;Web;Utforsker;
Keywords[ne_NP]=Internet;WWW;Browser;Web;Explorer;
Keywords[nl]=Internet;WWW;Browser;Web;Verkenner;
Keywords[nn_NO]=Internett;WWW;Nettlesar;Web;Utforskar;
Keywords[oc]=Internet;WWW;Navegador;Navigador;Navegator;Navigator;Web;Explorer;
Keywords[pa_IN]=ਇੰਟਰਨੈੱਟ;WWW;ਬਰਾਊਜ਼ਰ;ਵੈੱਬ;ਐਕਸਪਲਰੋਰ;ਵੈਬ;ਇੰਟਰਨੈਟ;
Keywords[pl]=Internet;WWW;Przeglądarka;Browser;Wyszukiwarka;Web;Sieć;Explorer;Eksplorer;Strony;Witryny;internetowe;
Keywords[pt_BR]=Internet;WWW;Browser;Web;Explorer;Navegador;
Keywords[pt_PT]=Internet;WWW;Navegador;Web;Explorador;
Keywords[rm]=Internet;WWW;Browser;Web;Explorer;navigatur;
Keywords[ro]=Internet; WWW; Browser; Web; Explorer;
Keywords[ru]=Сеть;Интернет;Браузер;Доступ в Интернет;
Keywords[sat]=Internet;WWW;Browser;Web;Explorer;
Keywords[sc]=Internet;WWW;Navigadore;Web;Explorer;
Keywords[sco]=Internet;WWW;Browser;Web;Explorer;
Keywords[si]=අන්තර්ජාලය;අතිරික්සුව;පිරික්සන්න;ගවේශකය;Internet;WWW;Browser;Web;Explorer;
Keywords[sk]=Internet;WWW;Prehliadač;Web;Prieskumník;
Keywords[skr]=Internet;WWW;Browser;Web;Explorer;
Keywords[sl]=internet;www;brskalnik;splet;
Keywords[son]=Internet;WWW;Browser;Web;Explorer;
Keywords[sq]=Internet;WWW;Shfletues;Web;Eksplorues;
Keywords[sr]=Internet;WWW;Browser;Web;Explorer;интернет;њњњ;веб;мрежа;прегледач;експлорер;internet;pregledač;veb;mreža;pregledač;eksplorer;
Keywords[sv_SE]=Internet;WWW;Webbläsare;Webb;Utforskare;
Keywords[szl]=Internet;WWW;Browser;Web;Explorer;
Keywords[ta]=Internet;WWW;Browser;Web;Explorer;
Keywords[te]=Internet;WWW;Browser;Web;Explorer;
Keywords[tg]=Интернет;WWW;Браузер;Сомона;Ҷустуҷӯгар;
Keywords[th]=อินเทอร์เน็ต;เบราว์เซอร์;เว็บ;Internet;WWW;Browser;Web;Explorer;
Keywords[tl]=Internet;WWW;Browser;Web;Explorer;
Keywords[tr]=Internet;WWW;Browser;Web;Explorer;İnternet;Tarayıcı;
Keywords[trs]=Internet;WWW;Browser;Web;Explorer;
Keywords[uk]=Інтернет;WWW;Браузер;Веб;Переглядач;
Keywords[ur]=Internet;WWW;Browser;Web;Explorer;
Keywords[uz]=Internet;WWW;Browser;Web;Explorer;
Keywords[vi]=Internet;WWW;Trình duyệt;Web;Duyệt web;
Keywords[xh]=Internet;WWW;Browser;Web;Explorer;
Keywords[zh_CN]=Internet;WWW;Browser;Web;Explorer;
Keywords[zh_TW]=網際網路;網路;瀏覽器;網頁;上網;Internet;WWW;Browser;Web;Explorer;
X-GNOME-FullName=Mozilla Firefox
X-GNOME-FullName[ach]=Mozilla Firefox
X-GNOME-FullName[af]=Mozilla Firefox
X-GNOME-FullName[an]=Mozilla Firefox
X-GNOME-FullName[ar]=Mozilla Firefox
X-GNOME-FullName[ast]=Mozilla Firefox
X-GNOME-FullName[az]=Mozilla Firefox
X-GNOME-FullName[be]=Mozilla Firefox
X-GNOME-FullName[bg]=Mozilla Firefox
X-GNOME-FullName[bn]=Mozilla Firefox
X-GNOME-FullName[br]=Mozilla Firefox
X-GNOME-FullName[bs]=Mozilla Firefox
X-GNOME-FullName[ca]=Mozilla Firefox
X-GNOME-FullName[ca_valencia]=Mozilla Firefox
X-GNOME-FullName[cak]=Mozilla Firefox
X-GNOME-FullName[cs]=Mozilla Firefox
X-GNOME-FullName[cy]=Mozilla Firefox
X-GNOME-FullName[da]=Mozilla Firefox
X-GNOME-FullName[de]=Mozilla Firefox
X-GNOME-FullName[dsb]=Mozilla Firefox
X-GNOME-FullName[el]=Mozilla Firefox
X-GNOME-FullName[en_CA]=Mozilla Firefox
X-GNOME-FullName[en_GB]=Mozilla Firefox
X-GNOME-FullName[eo]=Mozilla Firefox
X-GNOME-FullName[es_AR]=Mozilla Firefox
X-GNOME-FullName[es_CL]=Mozilla Firefox
X-GNOME-FullName[es_ES]=Mozilla Firefox
X-GNOME-FullName[es_MX]=Mozilla Firefox
X-GNOME-FullName[et]=Mozilla Firefox
X-GNOME-FullName[eu]=Mozilla Firefox
X-GNOME-FullName[fa]=Mozilla Firefox
X-GNOME-FullName[ff]=Mozilla Firefox
X-GNOME-FullName[fi]=Mozilla Firefox
X-GNOME-FullName[fr]=Mozilla Firefox
X-GNOME-FullName[fur]=Mozilla Firefox
X-GNOME-FullName[fy_NL]=Mozilla Firefox
X-GNOME-FullName[ga_IE]=Mozilla Firefox
X-GNOME-FullName[gd]=Mozilla Firefox
X-GNOME-FullName[gl]=Mozilla Firefox
X-GNOME-FullName[gn]=Mozilla Firefox
X-GNOME-FullName[gu_IN]=Mozilla Firefox
X-GNOME-FullName[he]=Mozilla Firefox
X-GNOME-FullName[hi_IN]=Mozilla Firefox
X-GNOME-FullName[hr]=Mozilla Firefox
X-GNOME-FullName[hsb]=Mozilla Firefox
X-GNOME-FullName[hu]=Mozilla Firefox
X-GNOME-FullName[hy_AM]=Mozilla Firefox
X-GNOME-FullName[ia]=Mozilla Firefox
X-GNOME-FullName[id]=Mozilla Firefox
X-GNOME-FullName[is]=Mozilla Firefox
X-GNOME-FullName[it]=Mozilla Firefox
X-GNOME-FullName[ja]=Mozilla Firefox
X-GNOME-FullName[ka]=Mozilla Firefox
X-GNOME-FullName[kab]=Mozilla Firefox
X-GNOME-FullName[kk]=Mozilla Firefox
X-GNOME-FullName[km]=Mozilla Firefox
X-GNOME-FullName[kn]=Mozilla Firefox
X-GNOME-FullName[ko]=Mozilla Firefox
X-GNOME-FullName[lij]=Mozilla Firefox
X-GNOME-FullName[lt]=Mozilla Firefox
X-GNOME-FullName[lv]=Mozilla Firefox
X-GNOME-FullName[mk]=Mozilla Firefox
X-GNOME-FullName[mr]=Mozilla Firefox
X-GNOME-FullName[ms]=Mozilla Firefox
X-GNOME-FullName[my]=Mozilla Firefox
X-GNOME-FullName[nb_NO]=Mozilla Firefox
X-GNOME-FullName[ne_NP]=Mozilla Firefox
X-GNOME-FullName[nl]=Mozilla Firefox
X-GNOME-FullName[nn_NO]=Mozilla Firefox
X-GNOME-FullName[oc]=Mozilla Firefox
X-GNOME-FullName[pa_IN]=Mozilla Firefox
X-GNOME-FullName[pl]=Mozilla Firefox
X-GNOME-FullName[pt_BR]=Mozilla Firefox
X-GNOME-FullName[pt_PT]=Mozilla Firefox
X-GNOME-FullName[rm]=Mozilla Firefox
X-GNOME-FullName[ro]=Mozilla Firefox
X-GNOME-FullName[ru]=Mozilla Firefox
X-GNOME-FullName[sat]=Mozilla Firefox
X-GNOME-FullName[sc]=Mozilla Firefox
X-GNOME-FullName[sco]=Mozilla Firefox
X-GNOME-FullName[si]=Mozilla Firefox
X-GNOME-FullName[sk]=Mozilla Firefox
X-GNOME-FullName[skr]=Mozilla Firefox
X-GNOME-FullName[sl]=Mozilla Firefox
X-GNOME-FullName[son]=Mozilla Firefox
X-GNOME-FullName[sq]=Mozilla Firefox
X-GNOME-FullName[sr]=Mozilla Firefox
X-GNOME-FullName[sv_SE]=Mozilla Firefox
X-GNOME-FullName[szl]=Mozilla Firefox
X-GNOME-FullName[ta]=Mozilla Firefox
X-GNOME-FullName[te]=Mozilla Firefox
X-GNOME-FullName[tg]=Mozilla Firefox
X-GNOME-FullName[th]=Mozilla Firefox
X-GNOME-FullName[tl]=Mozilla Firefox
X-GNOME-FullName[tr]=Mozilla Firefox
X-GNOME-FullName[trs]=Mozilla Firefox
X-GNOME-FullName[uk]=Mozilla Firefox
X-GNOME-FullName[ur]=Mozilla Firefox
X-GNOME-FullName[uz]=Mozilla Firefox
X-GNOME-FullName[vi]=Mozilla Firefox
X-GNOME-FullName[xh]=Mozilla Firefox
X-GNOME-FullName[zh_CN]=Mozilla Firefox
X-GNOME-FullName[zh_TW]=Mozilla Firefox
X-Flatpak=org.mozilla.firefox
X-SteamFrameNix-Source=@SOURCE@
[Desktop Action new-window]
Exec=/nix/store/00000000000000000000000000000000-firefox-wrapper /usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox --new-window @@u %u @@
Name=New Window
Name[ach]=New Window
Name[af]=New Window
Name[an]=New Window
Name[ar]=نافذة جديدة
Name[ast]=New Window
Name[az]=New Window
Name[be]=Новае акно
Name[bg]=Нов прозорец
Name[bn]=নতুন উইন্ডো
Name[br]=Prenestr nevez
Name[bs]=Novi prozor
Name[ca]=Finestra nova
Name[ca_valencia]=New Window
Name[cak]=K'ak'a' Tzuwäch
Name[cs]=Nové okno
Name[cy]=Ffenestr Newydd
Name[da]=Nyt vindue
Name[de]=Neues Fenster
Name[dsb]=Nowe wokno
Name[el]=Νέο παράθυρο
Name[en_CA]=New Window
Name[en_GB]=New Window
Name[eo]=Nova fenestro
Name[es_AR]=Nueva ventana
Name[es_CL]=Nueva ventana
Name[es_ES]=Nueva ventana
Name[es_MX]=Nueva ventana
Name[et]=New Window
Name[eu]=Leiho berria
Name[fa]=پنجره جدید‌
Name[ff]=New Window
Name[fi]=Uusi ikkuna
Name[fr]=Nouvelle fenêtre
Name[fur]=Gnûf barcon
Name[fy_NL]=Nij finster
Name[ga_IE]=New Window
Name[gd]=Uinneag ùr
Name[gl]=Nova xanela
Name[gn]=Ovetã pyahu
Name[gu_IN]=New Window
Name[he]=חלון חדש
Name[hi_IN]=New Window
Name[hr]=Novi prozor
Name[hsb]=Nowe wokno
Name[hu]=Új ablak
Name[hy_AM]=Նոր պատուհան
Name[ia]=Nove fenestra
Name[id]=Jendela Baru
Name[is]=Nýr gluggi
Name[it]=Nuova finestra
Name[ja]=新しいウィンドウ
Name[ka]=ახალი ფანჯარა
Name[kab]=Asfaylu amaynut
Name[kk]=Жаңа терезе
Name[km]=បង្អួច​​​ថ្មី
Name[kn]=New Window
Name[ko]=새 창
Name[lij]=Neuvo Barcon
Name[lt]=New Window
Name[lv]=Jauns logs
Name[mk]=New Window
Name[mr]=New Window
Name[ms]=New Window
Name[my]=New Window
Name[nb_NO]=Nytt vindu
Name[ne_NP]=नयाँ सञ्झ्याल
Name[nl]=Nieuw venster
Name[nn_NO]=Nytt vindauge
Name[oc]=Fenèstra novèla
Name[pa_IN]=ਨਵੀਂ ਵਿੰਡੋ
Name[pl]=Nowe okno
Name[pt_BR]=Nova janela
Name[pt_PT]=Nova janela
Name[rm]=Nova fanestra
Name[ro]=Fereastră nouă
Name[ru]=Новое окно
Name[sat]=ᱱᱟᱶᱟ ᱣᱤᱱᱰᱳ
Name[sc]=Ventana noa
Name[sco]=New Window
Name[si]=නව කවුළුව
Name[sk]=Nové okno
Name[skr]=نویں ونڈو
Name[sl]=Novo okno
Name[son]=New Window
Name[sq]=Dritare e Re
Name[sr]=Нови прозор
Name[sv_SE]=Nytt fönster
Name[szl]=New Window
Name[ta]=New Window
Name[te]=కొత్త కిటికీ
Name[tg]=Равзанаи нав
Name[th]=หน้าต่างใหม่
Name[tl]=New Window
Name[tr]=Yeni pencere
Name[trs]=Bēntanâ nākàa
Name[uk]=Нове вікно
Name[ur]=New Window
Name[uz]=New Window
Name[vi]=Cửa sổ mới
Name[xh]=New Window
Name[zh_CN]=新建窗口
Name[zh_TW]=開新視窗
[Desktop Action new-private-window]
Exec=/nix/store/00000000000000000000000000000000-firefox-wrapper /usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox --private-window @@u %u @@
Name=New Private Window
Name[ach]=New Private Window
Name[af]=New Private Window
Name[an]=New Private Window
Name[ar]=نافذة خاصة جديدة
Name[ast]=New Private Window
Name[az]=New Private Window
Name[be]=Новае прыватнае акно
Name[bg]=Нов личен прозорец
Name[bn]=নতুন ব্যক্তিগত উইন্ডো
Name[br]=Prenestr prevez nevez
Name[bs]=Novi privatni prozor
Name[ca]=Finestra privada nova
Name[ca_valencia]=New Private Window
Name[cak]=K'ak'a' Ichinan Tzuwäch
Name[cs]=Nové anonymní okno
Name[cy]=Ffenestr Breifat Newydd
Name[da]=Nyt privat vindue
Name[de]=Neues privates Fenster
Name[dsb]=Nowe priwatne wokno
Name[el]=Νέο ιδιωτικό παράθυρο
Name[en_CA]=New Private Window
Name[en_GB]=New Private Window
Name[eo]=Nova privata fenestro
Name[es_AR]=Nueva ventana privada
Name[es_CL]=Nueva ventana privada
Name[es_ES]=Nueva ventana privada
Name[es_MX]=Nueva ventana privada
Name[et]=New Private Window
Name[eu]=Leiho pribatu berria
Name[fa]=پنجره ناشناس جدید
Name[ff]=New Private Window
Name[fi]=Uusi yksityinen ikkuna
Name[fr]=Nouvelle fenêtre privée
Name[fur]=Gnûf barcon privât
Name[fy_NL]=Nij priveefinster
Name[ga_IE]=New Private Window
Name[gd]=Uinneag phrìobhaideach ùr
Name[gl]=Nova xanela privada
Name[gn]=Ovetã ñemi pyahu
Name[gu_IN]=New Private Window
Name[he]=חלון פרטי חדש
Name[hi_IN]=New Private Window
Name[hr]=Novi privatni prozor
Name[hsb]=Nowe priwatne wokno
Name[hu]=Új privát ablak
Name[hy_AM]=Նոր գաղտնի պատուհան
Name[ia]=Nove fenestra private
Name[id]=Jendela Mode Pribadi Baru
Name[is]=Nýr huliðsgluggi
Name[it]=Nuova finestra anonima
Name[ja]=新しいプライベートウィンドウ
Name[ka]=ახალი პირადი ფანჯარა
Name[kab]=Asfaylu amaynut n tunigin tusligt
Name[kk]=Жаңа жекелік терезе
Name[km]=បង្អួច​ឯកជន​ថ្មី
Name[kn]=New Private Window
Name[ko]=새 사생활 보호 창
Name[lij]=Neuvo Barcon Privòu
Name[lt]=New Private Window
Name[lv]=Jauns privātais logs
Name[mk]=New Private Window
Name[mr]=New Private Window
Name[ms]=New Private Window
Name[my]=New Private Window
Name[nb_NO]=Nytt privat vindu
Name[ne_NP]=नयाँ निजी सञ्झ्याल
Name[nl]=Nieuw privévenster
Name[nn_NO]=Nytt privat vindauge
Name[oc]=Fenèstra privada novèla
Name[pa_IN]=ਨਵੀਂ ਪ੍ਰਾਈਵੇਟ ਵਿੰਡੋ
Name[pl]=Nowe okno prywatne
Name[pt_BR]=Nova janela privativa
Name[pt_PT]=Nova janela privada
Name[rm]=Nova fanestra privata
Name[ro]=Fereastră privată nouă
Name[ru]=Новое приватное окно
Name[sat]=ᱱᱟᱶᱟ ᱱᱤᱡᱮᱨᱟᱜ ᱣᱤᱱᱰᱳ
Name[sc]=Ventana privada noa
Name[sco]=New Private Window
Name[si]=නව පෞද්. කවුළුව
Name[sk]=Nové súkromné okno
Name[skr]=نویں نجی ونڈو
Name[sl]=Novo zasebno okno
Name[son]=New Private Window
Name[sq]=Dritare e Re Private
Name[sr]=Нови приватни прозор
Name[sv_SE]=Nytt privat fönster
Name[szl]=New Private Window
Name[ta]=New Private Window
Name[te]=కొత్త ఆంతరంగిక కిటికీ
Name[tg]=Равзанаи хусусии нав
Name[th]=หน้าต่างส่วนตัวใหม่
Name[tl]=New Private Window
Name[tr]=Yeni gizli pencere
Name[trs]=Bēntanâ huì nākàa
Name[uk]=Приватне вікно
Name[ur]=New Private Window
Name[uz]=New Private Window
Name[vi]=Cửa sổ riêng tư mới
Name[xh]=New Private Window
Name[zh_CN]=新建隐私窗口
Name[zh_TW]=開新隱私視窗
[Desktop Action open-profile-manager]
Exec=/nix/store/00000000000000000000000000000000-firefox-wrapper /usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox org.mozilla.firefox --ProfileManager
Name=Open Profile Manager
Name[ach]=Open Profile Manager
Name[af]=Open Profile Manager
Name[an]=Open Profile Manager
Name[ar]=افتح مدير الملف الشخصي
Name[ast]=Open Profile Manager
Name[az]=Open Profile Manager
Name[be]=Адкрыць менеджар профіляў
Name[bg]=Отваряне на мениджъра на профили
Name[bn]=Open Profile Manager
Name[br]=Digeriñ an ardoer aeladoù
Name[bs]=Otvori Menadžera profila
Name[ca]=Obre el gestor de perfils
Name[ca_valencia]=Open Profile Manager
Name[cak]=Open Profile Manager
Name[cs]=Otevřít Správce profilů
Name[cy]=Agorwch y Rheolwr Proffil
Name[da]=Åbn profilhåndtering
Name[de]=Profilverwaltung öffnen
Name[dsb]=Profilowy zastojnik wócyniś
Name[el]=Άνοιγμα Διαχείρισης προφίλ
Name[en_CA]=Open Profile Manager
Name[en_GB]=Open Profile Manager
Name[eo]=Malfermi administranton de profiloj
Name[es_AR]=Abrir administrador de perfiles
Name[es_CL]=Abrir administrador de perfiles
Name[es_ES]=Abrir administrador de perfiles
Name[es_MX]=Abrir administrador de perfiles
Name[et]=Open Profile Manager
Name[eu]=Ireki profilen kudeatzailea
Name[fa]=گشودن مدیر نمایه
Name[ff]=Open Profile Manager
Name[fi]=Avaa profiilien hallinta
Name[fr]=Ouvrir le gestionnaire de profils
Name[fur]=Vierç gjestôr profîi
Name[fy_NL]=Profylbehearder iepenje
Name[ga_IE]=Open Profile Manager
Name[gd]=Fosgail manaidsear nam pròifilean
Name[gl]=Abrir o xestor de perfís
Name[gn]=Embojuruja mba’ete ñangarekoha
Name[gu_IN]=Open Profile Manager
Name[he]=פתיחת מנהל הפרופילים
Name[hi_IN]=Open Profile Manager
Name[hr]=Otvori upravljač profila
Name[hsb]=Zrjadowak profilow wočinić
Name[hu]=Profilkezelő megnyitása
Name[hy_AM]=Բացեք պրոֆիլի կառավարիչը
Name[ia]=Aperir le gestor de profilo
Name[id]=Buka Pengelola Profil
Name[is]=Opna umsýslu notandasniða
Name[it]=Apri gestore profili
Name[ja]=プロファイルマネージャーを開く
Name[ka]=პროფილის მმართველის გახსნა
Name[kab]=Ldi amsefrak n umaɣnu
Name[kk]=Профильдер бақарушысын ашу
Name[km]=Open Profile Manager
Name[kn]=Open Profile Manager
Name[ko]=프로필 관리자 열기
Name[lij]=Open Profile Manager
Name[lt]=Open Profile Manager
Name[lv]=Atvērt profilu pārvaldnieku
Name[mk]=Open Profile Manager
Name[mr]=Open Profile Manager
Name[ms]=Open Profile Manager
Name[my]=Open Profile Manager
Name[nb_NO]=Åpne profilbehandler
Name[ne_NP]=Open Profile Manager
Name[nl]=Profielbeheerder openen
Name[nn_NO]=Opne profilhandsaming
Name[oc]=Dobrir lo gestionari de perfils
Name[pa_IN]=ਪਰੋਫ਼ਾਈਲ ਮੈਨੇਜਰ ਖੋਲ੍ਹੋ
Name[pl]=Menedżer profili
Name[pt_BR]=Abrir gerenciador de perfis
Name[pt_PT]=Abrir o Gestor de Perfis
Name[rm]=Avrir l'administraziun da profils
Name[ro]=Deschide managerul de profiluri
Name[ru]=Открыть менеджер профилей
Name[sat]=ᱢᱮᱫᱦᱟᱸ ᱢᱮᱱᱮᱡᱚᱨ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ
Name[sc]=Aberi su gestore de profilos
Name[sco]=Open Profile Manager
Name[si]=පැතිකඩ කළමනාකරු අරින්න
Name[sk]=Otvoriť Správcu profilov
Name[skr]=پروفائل منیجر کھولو
Name[sl]=Odpri upravitelja profilov
Name[son]=Open Profile Manager
Name[sq]=Hapni Përgjegjës Profilesh
Name[sr]=Отворите управљач профила
Name[sv_SE]=Öppna Profilhanteraren
Name[szl]=Open Profile Manager
Name[ta]=Open Profile Manager
Name[te]=Open Profile Manager
Name[tg]=Кушодани мудири профилҳо
Name[th]=เปิดตัวจัดการโปรไฟล์
Name[tl]=Open Profile Manager
Name[tr]=Profil yöneticisini aç
Name[trs]=Sa nīkāj ñu’ūnj nej perfî huā nì’nï̀nj ïn
Name[uk]=Відкрити менеджер профілів
Name[ur]=Open Profile Manager
Name[uz]=Open Profile Manager
Name[vi]=Mở trình quản lý hồ sơ
Name[xh]=Open Profile Manager
Name[zh_CN]=打开配置文件管理器
Name[zh_TW]=開啟設定檔管理員
@@ -0,0 +1,25 @@
[Desktop Entry]
Name=Claude
Comment=Desktop application for Claude.ai
GenericName=AI Assistant
Keywords=AI;Chat;Assistant;Claude;Code;LLM;
Exec=/nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop %U
Icon=claude-desktop
Type=Application
StartupNotify=true
# Matches the Wayland app_id / X11 WM_CLASS Chromium derives from
# package.json desktopName, so docks group windows under this entry.
StartupWMClass=com.anthropic.Claude
# second-instance just focuses mainWindow; suppress GNOME's default "New Window" item
SingleMainWindow=true
Categories=Utility;Development;
MimeType=x-scheme-handler/claude;
Actions=NewChat;NewCode;
[Desktop Action NewChat]
Name=New Chat
Exec=/nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop "claude://claude.ai/new?surface=chat&source=desktop_action"
[Desktop Action NewCode]
Name=New Claude Code Session
Exec=/nix/store/8cc1cplpbdlsqy4x0v1c9w66w3dq80w4-claude-desktop-2.7032.0/bin/claude-desktop "claude://code/new?source=desktop_action"
@@ -0,0 +1,11 @@
[Desktop Entry]
Type=Application
Name=Element
Comment=A Matrix-based instant messaging client
Icon=im.riot.Riot
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=/app/bin/element --file-forwarding im.riot.Riot @@u %U @@
Categories=Network;InstantMessaging;Chat;VideoConference;
MimeType=x-scheme-handler/element;x-scheme-handler/io.element.desktop;
StartupWMClass=element
Keywords=Matrix;matrix.org;chat;irc;communications;talk;riot;vector;
X-Flatpak=im.riot.Riot
@@ -0,0 +1,5 @@
[Desktop Entry]
Type=Application
Name=No anchor
Exec=/app/bin/noanchor %U
X-Flatpak=org.example.NoAnchor
@@ -0,0 +1,18 @@
[Desktop Entry]
Type=Application
Name=Quoting test
Name[de]=Zitiertest
# a comment
Exec=env FOO=1 "/opt/My App/bin/app" --flag "with \\"quote\\"" %F
Icon=app
Actions=second;
Keywords=a;b;
Keywords[de]=c;d;
X-Unknown-Key=kept\sas is
[Desktop Action second]
Name=Second
Exec="/opt/My App/bin/app" --second
[X-Other Group]
Exec=untouched
@@ -0,0 +1,373 @@
[Desktop Entry]
Name[af]=gedit
Name[am]=gedit
Name[an]=gedit
Name[as]=gedit
Name[ast]=gedit
Name[az]=gedit
Name[be]=gedit
Name[bg]=gedit
Name[bn_IN]=gedit
Name[br]=gedit
Name[bs]=gedit
Name[ca]=gedit
Name[ckb]=‫gedit
Name[crh]=gedit
Name[cs]=gedit
Name[da]=gedit
Name[de]=gedit
Name[el]=gedit
Name[en_CA]=gedit
Name[en_GB]=gedit
Name[eo]=gedit
Name[es]=gedit
Name[et]=gedit
Name[eu]=gedit
Name[fa]=جی‌ادیت
Name[fi]=gedit
Name[fr]=gedit
Name[fur]=gedit
Name[ga]=gedit
Name[gl]=gedit
Name[he]=gedit
Name[hr]=gedit
Name[hu]=gedit
Name[id]=gedit
Name[is]=gedit
Name[it]=gedit
Name[ja]=gedit
Name[ka]=gedit
Name[kab]=gedit
Name[kk]=gedit
Name[km]=gedit
Name[kn]=gedit
Name[ko]=지에디트
Name[lt]=gedit
Name[lv]=gedit
Name[mjw]=gedit
Name[mk]=gedit
Name[ms]=gedit
Name[my]=gedit
Name[nb]=gedit
Name[nds]=gedit
Name[ne]=जिइडिट
Name[nl]=gedit
Name[nn]=gedit
Name[oc]=gedit
Name[or]=gedit
Name[pa]=ਜੀ-ਸੰਪਾਦਕ
Name[pl]=gedit
Name[pt]=gedit
Name[pt_BR]=gedit
Name[ro]=gedit
Name[ru]=gedit
Name[sk]=gedit
Name[sl]=gedit
Name[sr]=Вилењакова бележница
Name[sv]=gedit
Name[ta]=gedit
Name[th]=gedit
Name[tk]=gedit
Name[tr]=gedit
Name[ug]=gedit
Name[uk]=gedit
Name[vi]=gedit
Name[wa]=gedit
Name[zh_CN]=gedit
Name[zh_HK]=gedit
Name[zh_TW]=gedit
Name=gedit
Comment[af]=Redigeer tekslêers
Comment[am]=የጽሑፍ ፋይሎች ያስተካክሉ
Comment[an]=Edita fichers de texto
Comment[ar]=حرّر الملفات النصية
Comment[as]=লিখনি ফাইল সম্পাদনা
Comment[ast]=Editar ficheros de testu
Comment[az]=Mətn fayllarını redaktə edin
Comment[be]=Рэдагаванне тэкставых файлаў
Comment[be@latin]=Redahuj tekstavyja fajły
Comment[bg]=Редактиране на текстови файлове
Comment[bn]=টেক্সট ফাইল সম্পাদনা করুন
Comment[bn_IN]=টেক্সট ফাইল সম্পাদনা
Comment[br]=Embann restroù testenn
Comment[bs]=Izmijeni tekstualne datoteke
Comment[ca]=Editeu fitxers de text
Comment[ca@valencia]=Editeu fitxers de text
Comment[ckb]=دەق دەستکاریبکە
Comment[crh]=Metin dosyelerini tahrir et
Comment[cs]=Upravujte textové soubory
Comment[cy]=Golygu ffeiliau testun
Comment[da]=Redigér tekstfiler
Comment[de]=Textdateien bearbeiten
Comment[dz]=ཚིག་ཡིག་ཡིག་སྣོད་ཚུ་ ཞུན་དག་རྐྱབས་
Comment[el]=Επεξεργασία αρχείων κειμένου
Comment[en_CA]=Edit text files
Comment[en_GB]=Edit text files
Comment[en@shaw]=𐑧𐑛𐑦𐑑 𐑑𐑧𐑒𐑕𐑑 𐑓𐑲𐑤𐑟
Comment[eo]=Redakti tekstdosierojn
Comment[es]=Edite archivos de texto
Comment[et]=Tekstifailide redigeerimine
Comment[eu]=Editatu testu-fitxategiak
Comment[fa]=ویرایش پرونده‌های متنی
Comment[fi]=Muokkaa tekstitiedostoja
Comment[fr]=Éditer des fichiers texte
Comment[fur]=Modifiche file di test
Comment[ga]=Cuir comhaid téacs in eagar
Comment[gd]=Deasaich faidhlichean teacsa
Comment[gl]=Editar ficheiros de texto
Comment[gu]=લખાણ ફાઇલોમાં ફેરફાર કરો
Comment[he]=עריכת קובצי טקסט
Comment[hi]=पाठ फ़ाइलें संपादित करें
Comment[hr]=Uređivanje tekstovnih datoteka
Comment[hu]=Szövegfájlok szerkesztése
Comment[ia]=Rediger files de texto
Comment[id]=Menyunting berkas teks
Comment[ie]=Redacte files textual
Comment[is]=Sýsla með textaskrár
Comment[it]=Modifica file di testo
Comment[ja]=テキストファイルを編集します
Comment[ka]=ფაილების რედაქტირება
Comment[kab]=Ẓreg ifuyla n uḍris
Comment[kk]=Мәтіндік файлдарды түзету
Comment[km]=កែ​សម្រួល​ឯកសារ​អត្ថបទ
Comment[kn]=ಪಠ್ಯ ಕಡತಗಳನ್ನು ಸಂಪಾದಿಸು
Comment[ko]=텍스트 파일을 편집합니다
Comment[ku]=Pelên nivîsê sererast bike
Comment[ln]=Bɔngisa kásá ya nkomá
Comment[lt]=Redaguoti tekstinius failus
Comment[lv]=Rediģēt teksta datnes
Comment[mai]=पाठ फाइलकेँ संपादित करू
Comment[mg]=Hanova raki-dahabolana
Comment[mk]=Уредувај текстуални датотеки
Comment[ml]=പദാവലി ഫയലുകളില്‍ മാറ്റം വരുത്തുക
Comment[mn]=Текст файл боловсруулах
Comment[mr]=मजकूर फाइल्स् संपादीत करा
Comment[ms]=Sunting fail teks
Comment[my]=စာသားဖိုင်များပြင်ဆင်ရန်
Comment[nb]=Rediger tekstfiler
Comment[nds]=Textdateien bewarken
Comment[ne]=पाठ फाइल सम्पादन गर्नुहोस्
Comment[nl]=Bewerk tekstbestanden
Comment[nn]=Rediger tekstfiler
Comment[oc]=Editar de fichièrs tèxte
Comment[or]=ପାଠ୍ଯ ଫାଇଲଗୁଡ଼ିକୁ ସମ୍ପାଦନ କରନ୍ତୁ
Comment[pa]=ਲਿਖਤ ਫਾਇਲਾਂ ਸੋਧੋ
Comment[pl]=Edytor plików tekstowych
Comment[ps]=ليکن دوتنې سمول
Comment[pt]=Editar ficheiros de texto
Comment[pt_BR]=Edite arquivos de texto
Comment[ro]=Editare fișiere text
Comment[ru]=Редактор текстовых файлов
Comment[si]=පෙළ ගොනු සකසන්න
Comment[sk]=Úprava textových súborov
Comment[sl]=Enostavni urejevalnik besedilnih datotek
Comment[sq]=Ndrysho file teksti
Comment[sr]=Уређујте текстуалне документе
Comment[sr@latin]=Uređujte tekstualne dokumente
Comment[sv]=Redigera textfiler
Comment[ta]=உரை கோப்புகளை திருத்தவும்
Comment[te]=పాఠ్య ఫైళ్ళను సవరించు
Comment[th]=แก้ไขไฟล์ข้อความ
Comment[tk]=Metin faýllary editle
Comment[tr]=Metin dosyalarını düzenle
Comment[ug]=تېكىست ھۆججەتلىرىنى تەھرىرلەش
Comment[uk]=Редактор текстових файлів
Comment[vi]=Soạn thảo tập tin văn bản
Comment[wa]=Asspougnî des fitchîs tecses
Comment[xh]=Hlela iifayili zombhalo
Comment[zh_CN]=编辑文本文件
Comment[zh_HK]=編輯文字檔
Comment[zh_TW]=編輯文字檔
Comment=Edit text files
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=gedit --file-forwarding org.gnome.gedit @@u %U @@
Terminal=false
Type=Application
StartupNotify=true
MimeType=text/plain;application/x-zerosize;
Icon=org.gnome.gedit
Categories=GNOME;GTK;Utility;TextEditor;
Actions=new-window;new-document;
Keywords[be]=Text;Editor;Plaintext;Write;gedit;;Тэкст;Рэдактар;Тэкставы;Запіс;
Keywords[bg]=текст;редактор;обикновен;текст;text;editor;plaintext;write;gedit;
Keywords[bn_IN]=পাঠ্য;সম্পাদক;প্লেটেক্সট;লিখুন;gedit;
Keywords[ca]=Text;Editor;text simple;escriure;gedit;
Keywords[cs]=text;editor;prostý text;psát;psaní;gedit;
Keywords[da]=Tekst;Editor;Redigering;Tekstredigering;Skrive;Skriv;gedit;
Keywords[de]=Text;Editor;Klartext;Schreiben;gedit;
Keywords[el]=Text;Editor;Plaintext;Write;gedit;κείμενο;επεξεργαστής;εγγραφή;γράψιμο;gedit;
Keywords[en_GB]=Text;Editor;Plaintext;Write;gedit;
Keywords[eo]=Teksto;Redaktilo;Plata teksto;Skribi;gedit;
Keywords[es]=texto;editor;plano;escribir;gedit;
Keywords[eu]=Testua;Editorea;Testu soila;Idatzi;gedit;
Keywords[fa]=Text;Editor;Plaintext;Write;gedit;ویرایشگر متن;متن;ویرایشگر;نوشتار;
Keywords[fi]=Text;Editor;Plaintext;Write;gedit;teksti;muokkain;editori;tekstieditori;tekstimuokkain;
Keywords[fr]=texte brut;éditeur;écrire;gedit;
Keywords[fur]=Text;Editor;Test sempliç;Scrivi;gedit;
Keywords[gl]=Texto;Editor;Texto plano;Escribir;gedit;
Keywords[he]=טקסט;עורך;עריכה;טקסט פשוט;כתיבה;gedit;
Keywords[hr]=Tekst;Uređivač;Izvoran tekst;Piši;gedit;
Keywords[hu]=Szöveg;Szerkesztő;Egyszerű szöveg;Írás;gedit;
Keywords[id]=Teks;Penyunting;Teks Polos;Tulis;gedit;
Keywords[is]=Texti;Ritill;Hreintexti;Skrifa;gedit;
Keywords[it]=Editor;Testo;Text;Scrivere;gedit;
Keywords[ja]=Text;Editor;Plaintext;Write;gedit;テキスト;エディター;プレーンテキスト;書く;
Keywords[ka]=Text;Editor;Plaintext;Write;gedit;
Keywords[kab]=Aḍris;Amaẓrag;Plaintext;Aru;gedit;
Keywords[kk]=Text;Editor;Plaintext;Write;gedit;Мәтін;Түзеткіш;Ашық мәтін;Жазу;
Keywords[ko]=Text;텍스트;Editor;편집기;Plaintext;일반텍스트;Write;글쓰기;작성;gedit;지에디트;
Keywords[lt]=Tekstas;Redaktorius;Grynasis tekstas;Rašymas;gedit;
Keywords[lv]=Teksts;Redaktors;Vienkāršs teksts;Rakstīt;gedit;
Keywords[mjw]=Text;Editor;Plaintext;Write;gedit;
Keywords[ms]=Teks;Penyunting;Plaintext;Menulis;gedit;
Keywords[nb]=Tekst;Redigering;Vanlig tekst;Skriv;gedit;
Keywords[ne]=पाठ;सम्पादक;सादापाठ;लेखाई;जिइडिट;
Keywords[nl]=Text;tekst;Editor;teksteditor;tekstverwerker;Plaintext;platte tekst;Write;schrijven;gedit;
Keywords[pa]=ਸ਼ਬਦ;ਟੈਕਸਟ;ਸੰਪਾਦਕ;ਐਡੀਟਰ;ਪਲੇਨਟੈਕਸਟ;ਜੀਸੰਪਾਦਕ;
Keywords[pl]=Tekst;Text;Edytor;Zwykły tekst;Pisanie;Pisz;Napisz;Write;gedit;
Keywords[pt]=Texto;Editor;Texto simples;Escrever;gedit;
Keywords[pt_BR]=Texto;Editor;Texto simples;Plaintext;Escrever;Write;gedit;
Keywords[ro]=Text;Editor;Plaintext;Write;Text simplu;Scrie;gedit;
Keywords[ru]=Text;Editor;Plaintext;Write;gedit;Текст;Редактор;Запись;Текстовый;
Keywords[sk]=Text;Editor;Čistý text;Písať;Napísať;Písanie;gedit;
Keywords[sl]=Besedilo;Urejevalnik;tekst;Write;gedit;Pisanje;
Keywords[sr]=Text;Editor;Plaintext;Write;текст;уређивач;обичан текст;писање;гедит;tekst;uređivač;običan tekst;pisanje;gedit;
Keywords[sv]=Text;Redigerare;Vanlig text;Skriv;gedit;
Keywords[th]=ข้อความ;เครื่องมือแก้ไข;ข้อความเปล่า;เขียน;gedit;
Keywords[tr]=Metin;Düzenleyici;Düzyazı;Yaz;gedit;
Keywords[uk]=Текст;Редактор;Запис;Написання;ґедіт;Text;Editor;Plaintext;Write;gedit;
Keywords[vi]=Text;văn;bản;van;ban;Editor;sửa;sua;soạn;thảo;soan;thao;chữ;chu;Plaintext;Chữ thường;Chu thuong;Write;Ghi;Lưu;Luu;gedit;
Keywords[zh_CN]=Text;Editor;Plaintext;Write;gedit;文本;文字;编辑器;纯文本;编写;
Keywords[zh_TW]=Text;Editor;Plaintext;Write;gedit;文字;編輯器;純文字;撰寫;編寫;
Keywords=Text;Editor;Plaintext;Write;gedit;
DBusActivatable=true
X-Flatpak=org.gnome.gedit
[Desktop Action new-window]
Name[af]=Nuwe venster
Name[ar]=نافذة جديدة
Name[be]=Новае акно
Name[bg]=Нов прозорец
Name[bn_IN]=নতুন উইন্ডো
Name[ca]=Finestra nova
Name[ca@valencia]=_Finestra nova
Name[ckb]=پەنجەریەکی نوێ
Name[cs]=Nové okno
Name[da]=Nyt vindue
Name[de]=Neues Fenster
Name[el]=Νέο παράθυρο
Name[en_GB]=New Window
Name[eo]=Nova fenestro
Name[es]=Ventana nueva
Name[eu]=Leiho berria
Name[fa]=پنجره جدید
Name[fi]=Uusi ikkuna
Name[fr]=Nouvelle fenêtre
Name[fur]=Gnûf barcon
Name[gd]=Uinneag ùr
Name[gl]=_Xanela nova
Name[he]=חלון חדש
Name[hr]=Novi prozor
Name[hu]=Új ablak
Name[ia]=Nove fenestra
Name[id]=Jendela Baru
Name[ie]=Nov fenestre
Name[is]=Nýr gluggi
Name[it]=Nuova finestra
Name[ja]=新しいウィンドウ
Name[ka]=ახალი ფანჯარა
Name[kab]=Asfaylu amaynut
Name[kk]=Жаңа терезе
Name[ko]=새 창
Name[lt]=Naujas langas
Name[lv]=Jauns logs
Name[mjw]=Kimi Window
Name[ml]=പുതിയ ജാലകം
Name[ms]=Tetingkap Baharu
Name[nb]=Nytt vindu
Name[ne]=नयाँ सञ्झ्याल
Name[nl]=Nieuw venster
Name[oc]=Novèla fenèstra
Name[pa]=ਨਵੀਂ ਵਿੰਡੋ
Name[pl]=Nowe okno
Name[pt]=Nova janela
Name[pt_BR]=Nova janela
Name[ro]=Fereastră nouă
Name[ru]=Создать окно
Name[sk]=Nové okno
Name[sl]=Novo okno
Name[sr]=Нови прозор
Name[sr@latin]=Novi prozor
Name[sv]=Nytt fönster
Name[th]=หน้าต่างใหม่
Name[tr]=Yeni Pencere
Name[uk]=Створити вікно
Name[vi]=Cửa sổ mới
Name[zh_CN]=新建窗口
Name[zh_TW]=新增視窗
Name=New Window
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=gedit org.gnome.gedit --new-window
[Desktop Action new-document]
Name[af]=Nuwe dokument
Name[ar]=مستند جديد
Name[be]=Новы дакумент
Name[bg]=Нов документ
Name[bn_IN]=নতুন ডকুমেন্ট
Name[ca]=Crea un document nou
Name[ca@valencia]=Crea un document nou
Name[ckb]=بەڵگەنامەی نوێ
Name[cs]=Nový dokument
Name[da]=Nyt dokument
Name[de]=Neues Dokument
Name[el]=Νέο έγγραφο
Name[en_GB]=New Document
Name[eo]=Nova dokumento
Name[es]=Documento nuevo
Name[eu]=Dokumentu berria
Name[fa]=سند جدید
Name[fi]=Uusi asiakirja
Name[fr]=Nouveau document
Name[fur]=Gnûf document
Name[gd]=Sgrìobhainn ùr
Name[gl]=Novo documento
Name[he]=מסמך חדש
Name[hr]=Novi dokument
Name[hu]=Új dokumentum
Name[ia]=Nove documento
Name[id]=Dokumen Baru
Name[ie]=Nov document
Name[is]=Nýtt skjal
Name[it]=Nuovo documento
Name[ja]=新しいドキュメント
Name[ka]=ახალი დოკუმენტი
Name[kab]=Isemli amaynut
Name[kk]=Жаңа құжат
Name[ko]=새 문서
Name[lt]=Naujas dokumentas
Name[lv]=Jauns dokuments
Name[mjw]=Kimi Document
Name[ml]=പൂതിയ രേഖ
Name[ms]=Dokumen Baharu
Name[nb]=Nytt dokument
Name[ne]=नयाँ कागजात
Name[nl]=Nieuw document
Name[oc]=Novèl document
Name[pa]=ਨਵਾਂ ਡੌਕੂਮੈਂਟ
Name[pl]=Nowy dokument
Name[pt]=Novo documento
Name[pt_BR]=Novo documento
Name[ro]=Document nou
Name[ru]=Создать документ
Name[sk]=Nový dokument
Name[sl]=Nov dokument
Name[sr]=Нови документ
Name[sr@latin]=Novi dokument
Name[sv]=Nytt dokument
Name[th]=เอกสารใหม่
Name[tr]=Yeni Belge
Name[uk]=Створити документ
Name[vi]=Tài liệu mới
Name[zh_CN]=新建文档
Name[zh_TW]=新增文件
Name=New Document
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=gedit org.gnome.gedit --new-document
@@ -0,0 +1,28 @@
[Desktop Entry]
Version=1.0
Name=Jellyfin
Comment=Desktop client for Jellyfin
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop org.jellyfin.JellyfinDesktop
Icon=org.jellyfin.JellyfinDesktop
Terminal=false
Type=Application
StartupWMClass=org.jellyfin.JellyfinDesktop
Categories=AudioVideo;Video;Player;TV;
Actions=DesktopF;DesktopW;TVF;TVW
X-Flatpak=org.jellyfin.JellyfinDesktop
[Desktop Action DesktopF]
Name=Desktop [Fullscreen]
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop org.jellyfin.JellyfinDesktop --fullscreen --desktop
[Desktop Action DesktopW]
Name=Desktop [Windowed]
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop org.jellyfin.JellyfinDesktop --windowed --desktop
[Desktop Action TVF]
Name=TV [Fullscreen]
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop org.jellyfin.JellyfinDesktop --fullscreen --tv
[Desktop Action TVW]
Name=TV [Windowed]
Exec=flatpak run --branch=stable --arch=aarch64 --command=jellyfin-desktop org.jellyfin.JellyfinDesktop --windowed --tv
@@ -0,0 +1,181 @@
[Desktop Entry]
Type=Application
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=/app/bin/krdc --file-forwarding org.kde.krdc -qwindowtitle %c @@u %u @@
Icon=org.kde.krdc
Terminal=false
Name=KRDC
Name[ar]=كردس
Name[az]=KRDC
Name[bg]=KRDC
Name[bs]=KRDC
Name[ca]=KRDC
Name[ca@valencia]=KRDC
Name[cs]=KRDC
Name[da]=KRDC
Name[de]=KRDC
Name[el]=KRDC
Name[en_GB]=KRDC
Name[eo]=KRDC
Name[es]=KRDC
Name[et]=KRDC
Name[eu]=KRDC
Name[fi]=KRDC
Name[fr]=KRDC
Name[ga]=KRDC
Name[gl]=KRDC
Name[he]=KRDC
Name[hne]=केआरडीसी
Name[hr]=KRDC
Name[hu]=KRDC
Name[ia]=KRDC
Name[is]=KRDC
Name[it]=KRDC
Name[ja]=KRDC
Name[ka]=KRDC
Name[kk]=KRDC
Name[km]=KRDC
Name[ko]=KRDC
Name[lt]=KRDC
Name[lv]=KRDC
Name[ml]=കെആര്‍ഡിസി
Name[mr]=के-आर-डी-सी
Name[nb]=KRDC
Name[nds]=KRDC
Name[nl]=KRDC
Name[nn]=KRDC
Name[pa]=KRDC
Name[pl]=KRDC
Name[pt]=KRDC
Name[pt_BR]=KRDC
Name[ro]=KRDC
Name[ru]=KRDC
Name[sa]=केआरडीसी
Name[si]=KRDC
Name[sk]=KRDC
Name[sl]=KRDC
Name[sq]=KRDC
Name[sr]=КРДЦ
Name[sr@ijekavian]=КРДЦ
Name[sr@ijekavianlatin]=KRDC
Name[sr@latin]=KRDC
Name[sv]=KRDC
Name[tr]=KRDC
Name[ug]=KRDC
Name[uk]=KRDC
Name[wa]=KRDC
Name[zh_CN]=KRDC
Name[zh_TW]=遠端桌面_KRDC
GenericName=Remote Desktop Client
GenericName[ar]=عميل سطح المكتب البعيد
GenericName[az]=İş masasının uzaqdan idarə olunması
GenericName[bg]=Отдалечен работен плот
GenericName[bs]=Klijent udaljene radne površine
GenericName[ca]=Client d'escriptori remot
GenericName[ca@valencia]=Client d'escriptori remot
GenericName[cs]=Klient vzdálené pracovní plochy
GenericName[da]=Klient til fjernskrivebord
GenericName[de]=Verbindung zu entferntem Rechner
GenericName[el]=Πελάτης απομακρυσμένης επιφάνειας εργασίας
GenericName[en_GB]=Remote Desktop Client
GenericName[eo]=Kliento por fora labortablo
GenericName[es]=Cliente de escritorio remoto
GenericName[et]=Kaugtöölaua klient
GenericName[eu]=Urruneko mahaigainaren bezeroa
GenericName[fi]=Etätyöpöytäasiakas
GenericName[fr]=Connexion à un bureau distant
GenericName[ga]=Cliant Deisce Cianda
GenericName[gl]=Cliente de escritorio remoto
GenericName[he]=לקוח שולחן עבודה מרוחק
GenericName[hne]=रिमोट डेस्कटाप क्लाएंट
GenericName[hr]=Klijent za udaljeno povezivanje
GenericName[hu]=Távoli asztal kliens
GenericName[ia]=Cliente de scriptorio remote
GenericName[is]=Tengingar við fjarlæg skjáborð
GenericName[it]=Client per connessione a desktop remoto
GenericName[ja]=リモートデスクトップクライアント
GenericName[ka]=დისტანციური სამუშაო მაგიდის კლიენტი
GenericName[kk]=Қашықтан үстелге қосылу клиенті
GenericName[km]=កម្មវិធី​មើល​ផ្ទៃតុ​ពី​ចម្ងាយ
GenericName[ko]=원격 데스크톱 클라이언트
GenericName[lt]=Nuotolinio darbalaukio kliento programa
GenericName[lv]=Attālās darbvirsmas klients
GenericName[ml]=വിദൂര പണിയിട ക്ലയന്റ്
GenericName[mr]=दूरस्थ डेस्कटॉप ग्राहक
GenericName[nb]=Tilkobling til annet skrivebord
GenericName[nds]=Schriefdisch-Feernverbinnen
GenericName[nl]=Client voor verbinding met extern bureaublad
GenericName[nn]=Tilkopling til eksternt skrivebord
GenericName[pa]=ਰਿਮੋਟ ਡੈਸਕਟਾਪ ਕਲਾਈਟ
GenericName[pl]=Klient zdalnego dostępu do pulpitu
GenericName[pt]=Cliente de Ecrãs Remotos
GenericName[pt_BR]=Cliente de área de trabalho remota
GenericName[ro]=Client pentru birou la distanță
GenericName[ru]=Удалённый доступ к рабочему столу
GenericName[sa]=दूरस्थ डेस्कटॉप क्लायन्ट
GenericName[si]=දුරස්ථ වැඩතල යෙදුම
GenericName[sk]=Klient vzdialenej pracovnej plochy
GenericName[sl]=Odjemalec za oddaljena namizja
GenericName[sr]=Клијент удаљене површи
GenericName[sr@ijekavian]=Клијент удаљене површи
GenericName[sr@ijekavianlatin]=Klijent udaljene površi
GenericName[sr@latin]=Klijent udaljene površi
GenericName[sv]=Fjärranslutning till skrivbord
GenericName[th]=ไคลเอนต์เชื่อมต่อพื้นที่ทำงานทางไกล
GenericName[tr]=Uzak Masaüstü İstemcisi
GenericName[ug]=يىراقتىكى ئۈستەلئۈستى خېرىدارى
GenericName[uk]=Клієнт з'єднання з віддаленою стільницею
GenericName[zh_CN]=远程桌面客户端
GenericName[zh_TW]=遠端桌面用戶端
Comment=Connect with RDP or VNC to another computer
Comment[ar]=اتصل حاسوب آخر بواسطة RDP أو VNC
Comment[az]=RDP və ya VNC ilə başqa kompüterə qoşulun
Comment[bg]=Свързване чрез RDP or VNC с друг компютър
Comment[ca]=Connecta amb RDP o VNC a un altre ordinador
Comment[ca@valencia]=Connecta amb RDP o VNC a un altre ordinador
Comment[cs]=Připojte se k jinému počítači pomocí RDP nebo VNC
Comment[da]=Opret forbindelse til en anden computer med RDP eller VNC
Comment[de]=Verbindung mit RDP oder VNC zu einem anderen Rechner
Comment[el]=Σύνδεση με RDP ή VNC σε άλλον υπολογιστή
Comment[en_GB]=Connect with RDP or VNC to another computer
Comment[eo]=Konektiĝi per RDP aŭ VNC al alia komputilo
Comment[es]=Conectar con RDP o VNC a otro equipo
Comment[et]=Ühendumine RDP või VNC vahendusel teise arvutiga
Comment[eu]=Konektatu RDP edo VNC bidez beste ordenagailu batera
Comment[fi]=Yhdistä RDP:llä tai VNC:llä toiseen tietokoneeseen
Comment[fr]=Se connecter à un autre ordinateur avec RDP ou VNC
Comment[gl]=Conectarse por RDP ou VNC a outro computador.
Comment[he]=התחברות ל־RDP או ל־VNC במחשב אחר
Comment[hu]=Csatlakozás másik számítógéphez RDP-vel vagy VNC-vel
Comment[ia]=Connecte con RDP o VNC a un altere computator
Comment[is]=Tengstu með RDP eða VNC við aðrar tölvur
Comment[it]=Connessione via RDP o VNC ad un altro computer
Comment[ka]=მიუერთდით მოშორებულ კომპიუტერზე RDP ან VNC პროტოკოლით
Comment[ko]=다른 컴퓨터에 RDP나 VNC로 연결
Comment[lt]=Prisijungti prie kito kompiuterio naudojant RDP ar VNC
Comment[lv]=Izmantojiet RDP vai VNC, lai pievienotos citam datoram
Comment[nl]=Met RDP of VNC naar een andere computer verbinden
Comment[nn]=Kopla til ei anna datamaskin via RDP eller VNC
Comment[pl]=Połącz się przy użyciu RDP lub VNC do innego komputera
Comment[pt]=Ligar-se com RDP ou VNC a outro computador
Comment[pt_BR]=Conecte com RDP ou VNC em outro computador
Comment[ro]=Conectare la alt calculator prin RDP sau VNC
Comment[ru]=Подключение к другому компьютеру по RDP или VNC
Comment[sa]=RDP अथवा VNC इत्यनेन सह अन्यसङ्गणकेन सह सम्बद्धं कुर्वन्तु
Comment[sk]=Pripojiť pomocou RDP alebo VNC k inému počítaču
Comment[sl]=Povežite se preko RDP-ja ali VNC-ja z drugim računalnikom
Comment[sq]=Lidhu me një kompjuter tjetër përmes RDP ose VNC
Comment[sr]=Повежите се РДП‑ом или ВНЦ‑ом са другим рачунаром
Comment[sr@ijekavian]=Повежите се РДП‑ом или ВНЦ‑ом са другим рачунаром
Comment[sr@ijekavianlatin]=Povežite se RDP‑om ili VNC‑om sa drugim računarom
Comment[sr@latin]=Povežite se RDP‑om ili VNC‑om sa drugim računarom
Comment[sv]=Anslut till en annan dator med RDP eller VNC
Comment[tr]=Başka bir bilgisayara RDP veya VNC ile bağlan
Comment[uk]=З'єднання з іншим комп'ютером за допомогою RDP або VNC
Comment[zh_CN]=通过 RDP 或 VNC 连接到另一台计算机
Comment[zh_TW]=以 RDP 或 VNC 連線到其他電腦
X-DocPath=krdc/index.html
StartupWMClass=krdc
MimeType=x-scheme-handler/vnc;x-scheme-handler/rdp;application/x-krdc;
Categories=Qt;KDE;Network;RemoteAccess;
X-KDE-Wayland-Interfaces=org_kde_kwin_keystate
X-Flatpak=org.kde.krdc
@@ -0,0 +1,847 @@
[Desktop Entry]
Version=1.0
Type=Application
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox @@u %u @@
Terminal=false
X-MultipleArgs=false
Icon=org.mozilla.firefox
StartupWMClass=firefox
DBusActivatable=false
Categories=GNOME;GTK;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;
StartupNotify=true
Actions=new-window;new-private-window;open-profile-manager;
Name=Firefox
Name[ach]=Firefox
Name[af]=Firefox
Name[an]=Firefox
Name[ar]=Firefox
Name[ast]=Firefox
Name[az]=Firefox
Name[be]=Firefox
Name[bg]=Firefox
Name[bn]=Firefox
Name[br]=Firefox
Name[bs]=Firefox
Name[ca]=Firefox
Name[ca_valencia]=Firefox
Name[cak]=Firefox
Name[cs]=Firefox
Name[cy]=Firefox
Name[da]=Firefox
Name[de]=Firefox
Name[dsb]=Firefox
Name[el]=Firefox
Name[en_CA]=Firefox
Name[en_GB]=Firefox
Name[eo]=Firefox
Name[es_AR]=Firefox
Name[es_CL]=Firefox
Name[es_ES]=Firefox
Name[es_MX]=Firefox
Name[et]=Firefox
Name[eu]=Firefox
Name[fa]=Firefox
Name[ff]=Firefox
Name[fi]=Firefox
Name[fr]=Firefox
Name[fur]=Firefox
Name[fy_NL]=Firefox
Name[ga_IE]=Firefox
Name[gd]=Firefox
Name[gl]=Firefox
Name[gn]=Firefox
Name[gu_IN]=Firefox
Name[he]=Firefox
Name[hi_IN]=Firefox
Name[hr]=Firefox
Name[hsb]=Firefox
Name[hu]=Firefox
Name[hy_AM]=Firefox
Name[ia]=Firefox
Name[id]=Firefox
Name[is]=Firefox
Name[it]=Firefox
Name[ja]=Firefox
Name[ka]=Firefox
Name[kab]=Firefox
Name[kk]=Firefox
Name[km]=Firefox
Name[kn]=Firefox
Name[ko]=Firefox
Name[lij]=Firefox
Name[lt]=Firefox
Name[lv]=Firefox
Name[mk]=Firefox
Name[mr]=Firefox
Name[ms]=Firefox
Name[my]=Firefox
Name[nb_NO]=Firefox
Name[ne_NP]=Firefox
Name[nl]=Firefox
Name[nn_NO]=Firefox
Name[oc]=Firefox
Name[pa_IN]=Firefox
Name[pl]=Firefox
Name[pt_BR]=Firefox
Name[pt_PT]=Firefox
Name[rm]=Firefox
Name[ro]=Firefox
Name[ru]=Firefox
Name[sat]=Firefox
Name[sc]=Firefox
Name[sco]=Firefox
Name[si]=Firefox
Name[sk]=Firefox
Name[skr]=Firefox
Name[sl]=Firefox
Name[son]=Firefox
Name[sq]=Firefox
Name[sr]=Firefox
Name[sv_SE]=Firefox
Name[szl]=Firefox
Name[ta]=Firefox
Name[te]=Firefox
Name[tg]=Firefox
Name[th]=Firefox
Name[tl]=Firefox
Name[tr]=Firefox
Name[trs]=Firefox
Name[uk]=Firefox
Name[ur]=Firefox
Name[uz]=Firefox
Name[vi]=Firefox
Name[xh]=Firefox
Name[zh_CN]=Firefox
Name[zh_TW]=Firefox
Comment=Fast and private browser
Comment[ach]=Fast and private browser
Comment[af]=Fast and private browser
Comment[an]=Fast and private browser
Comment[ar]=متصفح سريع وخاص
Comment[ast]=Fast and private browser
Comment[az]=Fast and private browser
Comment[be]=Хуткі і прыватны браўзер
Comment[bg]=Fast and private browser
Comment[bn]=Fast and private browser
Comment[br]=Fast and private browser
Comment[bs]=Fast and private browser
Comment[ca]=Navegador ràpid i privat
Comment[ca_valencia]=Fast and private browser
Comment[cak]=Fast and private browser
Comment[cs]=Rychlý a soukromý prohlížeč
Comment[cy]=Porwr cyflym a phreifat
Comment[da]=Hurtig og privat browser
Comment[de]=Schneller und privater Browser
Comment[dsb]=Malsny a priwatny wobglědowak
Comment[el]=Γρήγορο και ιδιωτικό πρόγραμμα περιήγησης
Comment[en_CA]=Fast and private browser
Comment[en_GB]=Fast and private browser
Comment[eo]=Rapida kaj privata retumilo
Comment[es_AR]=Navegador rápido y privado
Comment[es_CL]=Navegador rápido y privado
Comment[es_ES]=Navegador rápido y privado
Comment[es_MX]=Navegación web rápida y privada
Comment[et]=Fast and private browser
Comment[eu]=Nabigatzaile bizkor eta pribatua
Comment[fa]=Fast and private browser
Comment[ff]=Fast and private browser
Comment[fi]=Nopea ja yksityinen selain
Comment[fr]=Navigateur rapide et privé
Comment[fur]=Navigadôr svelt e riservât
Comment[fy_NL]=Flugge en priveebrowser
Comment[ga_IE]=Fast and private browser
Comment[gd]=Fast and private browser
Comment[gl]=Fast and private browser
Comment[gn]=Kundahára ipya’e ha hekoñemíva
Comment[gu_IN]=Fast and private browser
Comment[he]=דפדפן מהיר ופרטי
Comment[hi_IN]=Fast and private browser
Comment[hr]=Brz i privatan preglednik
Comment[hsb]=Spěšny a priwatny wobhladowak
Comment[hu]=Gyors és privát böngésző
Comment[hy_AM]=Արագ և գաղտնի դիտարկիչ
Comment[ia]=Navigator veloce e private
Comment[id]=Fast and private browser
Comment[is]=Hraður og persónulegur vafri
Comment[it]=Browser veloce e riservato
Comment[ja]=高速プライベートブラウザー
Comment[ka]=სწრაფი და პირადი ბრაუზერი
Comment[kab]=Iminig arurad, uslig
Comment[kk]=Жылдам және жеке браузер
Comment[km]=Fast and private browser
Comment[kn]=Fast and private browser
Comment[ko]=빠르고 사생활을 보호하는 브라우저
Comment[lij]=Fast and private browser
Comment[lt]=Fast and private browser
Comment[lv]=Fast and private browser
Comment[mk]=Fast and private browser
Comment[mr]=Fast and private browser
Comment[ms]=Fast and private browser
Comment[my]=Fast and private browser
Comment[nb_NO]=Rask og privat nettleser
Comment[ne_NP]=Fast and private browser
Comment[nl]=Snelle en privébrowser
Comment[nn_NO]=Rask og privat nettlesar
Comment[oc]=Fast and private browser
Comment[pa_IN]=ਤੇਜ਼ ਅਤੇ ਪ੍ਰਾਈਵੇਟ ਬਰਾਊਜ਼ਰ
Comment[pl]=Szybka i prywatna przeglądarka
Comment[pt_BR]=Navegador rápido e privativo
Comment[pt_PT]=Navegador rápido e privado
Comment[rm]=Navigatur svelt e privat
Comment[ro]=Browser rapid și privat
Comment[ru]=Быстрый и приватный браузер
Comment[sat]=Fast and private browser
Comment[sc]=Navigadore lestru e privadu
Comment[sco]=Fast and private browser
Comment[si]=Fast and private browser
Comment[sk]=Rýchly a súkromný prehliadač
Comment[skr]=Fast and private browser
Comment[sl]=Hiter in zaseben brskalnik
Comment[son]=Fast and private browser
Comment[sq]=Shfletues i shpejtë dhe privat
Comment[sr]=Брз и приватан веб прегледач
Comment[sv_SE]=Snabb och privat webbläsare
Comment[szl]=Fast and private browser
Comment[ta]=Fast and private browser
Comment[te]=Fast and private browser
Comment[tg]=Браузери тезкор ва хусусӣ
Comment[th]=เบราว์เซอร์ที่รวดเร็วและเป็นส่วนตัว
Comment[tl]=Fast and private browser
Comment[tr]=Hızlı ve gizli tarayıcı
Comment[trs]=Fast and private browser
Comment[uk]=Швидкий і приватний браузер
Comment[ur]=Fast and private browser
Comment[uz]=Fast and private browser
Comment[vi]=Trình duyệt nhanh và riêng tư
Comment[xh]=Fast and private browser
Comment[zh_CN]=快速且私密的浏览器
Comment[zh_TW]=快速又有隱私的瀏覽器
GenericName=Web Browser
GenericName[ach]=Web Browser
GenericName[af]=Web Browser
GenericName[an]=Web Browser
GenericName[ar]=متصفح الوِب
GenericName[ast]=Web Browser
GenericName[az]=Web Browser
GenericName[be]=Вэб-браўзер
GenericName[bg]=Уеб браузър
GenericName[bn]=ওয়েব ব্রাউজার
GenericName[br]=Merdeer Web
GenericName[bs]=Web pretraživač
GenericName[ca]=Navegador web
GenericName[ca_valencia]=Web Browser
GenericName[cak]=Web Okik'amaya'l
GenericName[cs]=Webový prohlížeč
GenericName[cy]=Porwr Gwe
GenericName[da]=Webbrowser
GenericName[de]=Internet-Browser
GenericName[dsb]=Webwobglědowak
GenericName[el]=Πρόγραμμα περιήγησης
GenericName[en_CA]=Web Browser
GenericName[en_GB]=Web Browser
GenericName[eo]=Retumilo
GenericName[es_AR]=Navegador web
GenericName[es_CL]=Navegador Web
GenericName[es_ES]=Navegador web
GenericName[es_MX]=Navegador Web
GenericName[et]=Web Browser
GenericName[eu]=Web nabigatzailea
GenericName[fa]=مرورگر وب
GenericName[ff]=Web Browser
GenericName[fi]=Verkkoselain
GenericName[fr]=Navigateur web
GenericName[fur]=Navigadôr Web
GenericName[fy_NL]=Webbrowser
GenericName[ga_IE]=Web Browser
GenericName[gd]=Brabhsair-lìn
GenericName[gl]=Navegador web
GenericName[gn]=Ñanduti Kundahára
GenericName[gu_IN]=Web Browser
GenericName[he]=דפדפן אינטרנט
GenericName[hi_IN]=Web Browser
GenericName[hr]=Web preglednik
GenericName[hsb]=Webwobhladowak
GenericName[hu]=Webböngésző
GenericName[hy_AM]=Վեբ դիտարկիչ
GenericName[ia]=Navigator web
GenericName[id]=Peramban Web
GenericName[is]=Vafri
GenericName[it]=Browser web
GenericName[ja]=ウェブブラウザー
GenericName[ka]=ბრაუზერი
GenericName[kab]=Iminig web
GenericName[kk]=Веб-браузері
GenericName[km]=Web Browser
GenericName[kn]=Web Browser
GenericName[ko]=웹 브라우저
GenericName[lij]=Navegatô Web
GenericName[lt]=Web Browser
GenericName[lv]=Tīmekļa pārlūks
GenericName[mk]=Web Browser
GenericName[mr]=Web Browser
GenericName[ms]=Web Browser
GenericName[my]=Web Browser
GenericName[nb_NO]=Nettleser
GenericName[ne_NP]=वेब ब्राउजर
GenericName[nl]=Webbrowser
GenericName[nn_NO]=Nettlesar
GenericName[oc]=Navegador Web
GenericName[pa_IN]=ਵੈੱਬ ਬਰਾਊਜ਼ਰ
GenericName[pl]=Przeglądarka internetowa
GenericName[pt_BR]=Navegador web
GenericName[pt_PT]=Navegador Web
GenericName[rm]=Navigatur web
GenericName[ro]=Browser web
GenericName[ru]=Веб-браузер
GenericName[sat]=ᱣᱮᱵᱽ ᱵᱽᱨᱟᱣᱡᱚᱨ
GenericName[sc]=Navigadore web
GenericName[sco]=Web Browser
GenericName[si]=වියමන අතිරික්සුව
GenericName[sk]=Webový prehliadač
GenericName[skr]=ویب براؤزر
GenericName[sl]=Spletni brskalnik
GenericName[son]=Web Browser
GenericName[sq]=Shfletues
GenericName[sr]=Веб прегледач
GenericName[sv_SE]=Webbläsare
GenericName[szl]=Web Browser
GenericName[ta]=Web Browser
GenericName[te]=జాల విహారిణి
GenericName[tg]=Браузери веб
GenericName[th]=เว็บเบราว์เซอร์
GenericName[tl]=Web Browser
GenericName[tr]=Web Tarayıcısı
GenericName[trs]=Web riña gāchē nu’
GenericName[uk]=Браузер
GenericName[ur]=Web Browser
GenericName[uz]=Web Browser
GenericName[vi]=Trình duyệt web
GenericName[xh]=Web Browser
GenericName[zh_CN]=Web 浏览器
GenericName[zh_TW]=網頁瀏覽器
Keywords=Internet;WWW;Browser;Web;Explorer;
Keywords[ach]=Internet;WWW;Browser;Web;Explorer;
Keywords[af]=Internet;WWW;Browser;Web;Explorer;
Keywords[an]=Internet;WWW;Browser;Web;Explorer;
Keywords[ar]=إنترنت;WWW;متصفح;ويب;مستكشف;
Keywords[ast]=Internet;WWW;Browser;Web;Explorer;
Keywords[az]=Internet;WWW;Browser;Web;Explorer;
Keywords[be]=Internet;WWW;Browser;Web;Explorer;
Keywords[bg]=Internet;WWW;Browser;Web;Explorer;
Keywords[bn]=ইন্টারনেট;WWW;ব্রাউজার;ওয়েব;এক্সপ্লোরার;
Keywords[br]=Internet;WWW;Merdeer;Web;Ergerzhout;
Keywords[bs]=Internet;WWW;Pretraživač;Web;Istraživač;
Keywords[ca]=Internet;WWW;Browser;Web;Explorador;Navegador;
Keywords[ca_valencia]=Internet;WWW;Browser;Web;Explorer;
Keywords[cak]=K'amaya'l;WWW;Okik'amaya'l;Kanob'äl;
Keywords[cs]=internet;WWW;prohlížeč;web;
Keywords[cy]=Rhyngrwyd;WWW;Porwr;Gwe;Archwiliwr;
Keywords[da]=Internet;WWW;Browser;Nettet;Explorer;
Keywords[de]=Internet;WWW;Browser;Web;Explorer;
Keywords[dsb]=Internet;WWW;wobglědowak;Web;Explorer;
Keywords[el]=Internet;WWW;Browser;Web;Explorer;Διαδίκτυο;Ιστός;Ίντερνετ;
Keywords[en_CA]=Internet;WWW;Browser;Web;Explorer;
Keywords[en_GB]=Internet;WWW;Browser;Web;Explorer;
Keywords[eo]=Interreto;Retumilo;TTT;Teksaĵo;Reto;Internet;WWW;Browser;Web;Explorer;
Keywords[es_AR]=Internet;WWW;Navegador;Web;Explorador;
Keywords[es_CL]=Internet;WWW;Navegador;Web;Explorador;
Keywords[es_ES]=Internet;WWW;Navegador;Web;Explorador;
Keywords[es_MX]=Internet;WWW;Navegador;Web;Explorador;
Keywords[et]=Internet;WWW;Browser;Web;Explorer;
Keywords[eu]=Internet;WWW;Nabigatzailea;Web;Arakatzailea;
Keywords[fa]=Internet;WWW;Browser;Web;Explorer;
Keywords[ff]=Internet;WWW;Browser;Web;Explorer;
Keywords[fi]=Internet;WWW;Browser;Web;Explorer;netti;webbi;selain;
Keywords[fr]=Internet;WWW;Navigateur;Web;Explorer;
Keywords[fur]=Internet;WWW;Browser;Navigadôr;Web;Esploradôr;Explorer;
Keywords[fy_NL]=Ynternet;WWW;Browser;Web;Ferkenner;
Keywords[ga_IE]=Internet;WWW;Browser;Web;Explorer;
Keywords[gd]=Internet;WWW;Browser;Web;Explorer;eadar-lìon;brabhsair;brobhsair;lìon;taisgealaiche;
Keywords[gl]=Internet;WWW;Navegador;Web;Explorador;
Keywords[gn]=Internet;WWW;Browser;Web;Explorer;
Keywords[gu_IN]=Internet;WWW;Browser;Web;Explorer;
Keywords[he]=אינטרנט;WWW;דפדפן;רשת;סייר;מרשתת;
Keywords[hi_IN]=Internet;WWW;Browser;Web;Explorer;
Keywords[hr]=Internet;WWW;Preglednik;Web;Istraživač;
Keywords[hsb]=Internet;WWW;wobhladowak;Web;Explorer;
Keywords[hu]=Internet;WWW;Böngésző;Web;Világháló;
Keywords[hy_AM]=Համացանց,WWW,Զննիչ,Վեբ,Ցանցախույզ:
Keywords[ia]=Internet;WWW;Navigator;Web;Explorator;
Keywords[id]=Internet;WWW;Browser;Web;Explorer;
Keywords[is]=Internet;WWW; Vafri; Vefur; Explorer;
Keywords[it]=Internet;WWW;Browser;Web;Explorer;Navigatore;
Keywords[ja]=Internet;WWW;Browser;Web;Explorer;インターネット;ブラウザー;ウェブ;
Keywords[ka]=ინტერნეტი;WWW;ბრაუზერი;ქსელი;ქსელთან წვდომა;
Keywords[kab]=Internet;WWW;Browser;Web;Explorer;
Keywords[kk]=Internet;WWW;Browser;Web;Explorer;Интернет;Ғаламтор;Браузер;Желі;Шолғыш;
Keywords[km]=Internet;WWW;Browser;Web;Explorer;
Keywords[kn]=Internet;WWW;Browser;Web;Explorer;
Keywords[ko]=인터넷;브라우저;웹;탐색기;Internet;WWW;Browser;Web;Explorer;
Keywords[lij]=Internet;WWW;Browser;Web;Explorer;Navegatô;
Keywords[lt]=Internet;WWW;Browser;Web;Explorer;
Keywords[lv]=Internets;WWW;Pārlūkprogramma;Tīmeklis;
Keywords[mk]=Internet;WWW;Browser;Web;Explorer;
Keywords[mr]=Internet;WWW;Browser;Web;Explorer;
Keywords[ms]=Internet;WWW;Browser;Web;Explorer;
Keywords[my]=Internet;WWW;Browser;Web;Explorer;
Keywords[nb_NO]=Internett;WWW;Nettleser;Web;Utforsker;
Keywords[ne_NP]=Internet;WWW;Browser;Web;Explorer;
Keywords[nl]=Internet;WWW;Browser;Web;Verkenner;
Keywords[nn_NO]=Internett;WWW;Nettlesar;Web;Utforskar;
Keywords[oc]=Internet;WWW;Navegador;Navigador;Navegator;Navigator;Web;Explorer;
Keywords[pa_IN]=ਇੰਟਰਨੈੱਟ;WWW;ਬਰਾਊਜ਼ਰ;ਵੈੱਬ;ਐਕਸਪਲਰੋਰ;ਵੈਬ;ਇੰਟਰਨੈਟ;
Keywords[pl]=Internet;WWW;Przeglądarka;Browser;Wyszukiwarka;Web;Sieć;Explorer;Eksplorer;Strony;Witryny;internetowe;
Keywords[pt_BR]=Internet;WWW;Browser;Web;Explorer;Navegador;
Keywords[pt_PT]=Internet;WWW;Navegador;Web;Explorador;
Keywords[rm]=Internet;WWW;Browser;Web;Explorer;navigatur;
Keywords[ro]=Internet; WWW; Browser; Web; Explorer;
Keywords[ru]=Сеть;Интернет;Браузер;Доступ в Интернет;
Keywords[sat]=Internet;WWW;Browser;Web;Explorer;
Keywords[sc]=Internet;WWW;Navigadore;Web;Explorer;
Keywords[sco]=Internet;WWW;Browser;Web;Explorer;
Keywords[si]=අන්තර්ජාලය;අතිරික්සුව;පිරික්සන්න;ගවේශකය;Internet;WWW;Browser;Web;Explorer;
Keywords[sk]=Internet;WWW;Prehliadač;Web;Prieskumník;
Keywords[skr]=Internet;WWW;Browser;Web;Explorer;
Keywords[sl]=internet;www;brskalnik;splet;
Keywords[son]=Internet;WWW;Browser;Web;Explorer;
Keywords[sq]=Internet;WWW;Shfletues;Web;Eksplorues;
Keywords[sr]=Internet;WWW;Browser;Web;Explorer;интернет;њњњ;веб;мрежа;прегледач;експлорер;internet;pregledač;veb;mreža;pregledač;eksplorer;
Keywords[sv_SE]=Internet;WWW;Webbläsare;Webb;Utforskare;
Keywords[szl]=Internet;WWW;Browser;Web;Explorer;
Keywords[ta]=Internet;WWW;Browser;Web;Explorer;
Keywords[te]=Internet;WWW;Browser;Web;Explorer;
Keywords[tg]=Интернет;WWW;Браузер;Сомона;Ҷустуҷӯгар;
Keywords[th]=อินเทอร์เน็ต;เบราว์เซอร์;เว็บ;Internet;WWW;Browser;Web;Explorer;
Keywords[tl]=Internet;WWW;Browser;Web;Explorer;
Keywords[tr]=Internet;WWW;Browser;Web;Explorer;İnternet;Tarayıcı;
Keywords[trs]=Internet;WWW;Browser;Web;Explorer;
Keywords[uk]=Інтернет;WWW;Браузер;Веб;Переглядач;
Keywords[ur]=Internet;WWW;Browser;Web;Explorer;
Keywords[uz]=Internet;WWW;Browser;Web;Explorer;
Keywords[vi]=Internet;WWW;Trình duyệt;Web;Duyệt web;
Keywords[xh]=Internet;WWW;Browser;Web;Explorer;
Keywords[zh_CN]=Internet;WWW;Browser;Web;Explorer;
Keywords[zh_TW]=網際網路;網路;瀏覽器;網頁;上網;Internet;WWW;Browser;Web;Explorer;
X-GNOME-FullName=Mozilla Firefox
X-GNOME-FullName[ach]=Mozilla Firefox
X-GNOME-FullName[af]=Mozilla Firefox
X-GNOME-FullName[an]=Mozilla Firefox
X-GNOME-FullName[ar]=Mozilla Firefox
X-GNOME-FullName[ast]=Mozilla Firefox
X-GNOME-FullName[az]=Mozilla Firefox
X-GNOME-FullName[be]=Mozilla Firefox
X-GNOME-FullName[bg]=Mozilla Firefox
X-GNOME-FullName[bn]=Mozilla Firefox
X-GNOME-FullName[br]=Mozilla Firefox
X-GNOME-FullName[bs]=Mozilla Firefox
X-GNOME-FullName[ca]=Mozilla Firefox
X-GNOME-FullName[ca_valencia]=Mozilla Firefox
X-GNOME-FullName[cak]=Mozilla Firefox
X-GNOME-FullName[cs]=Mozilla Firefox
X-GNOME-FullName[cy]=Mozilla Firefox
X-GNOME-FullName[da]=Mozilla Firefox
X-GNOME-FullName[de]=Mozilla Firefox
X-GNOME-FullName[dsb]=Mozilla Firefox
X-GNOME-FullName[el]=Mozilla Firefox
X-GNOME-FullName[en_CA]=Mozilla Firefox
X-GNOME-FullName[en_GB]=Mozilla Firefox
X-GNOME-FullName[eo]=Mozilla Firefox
X-GNOME-FullName[es_AR]=Mozilla Firefox
X-GNOME-FullName[es_CL]=Mozilla Firefox
X-GNOME-FullName[es_ES]=Mozilla Firefox
X-GNOME-FullName[es_MX]=Mozilla Firefox
X-GNOME-FullName[et]=Mozilla Firefox
X-GNOME-FullName[eu]=Mozilla Firefox
X-GNOME-FullName[fa]=Mozilla Firefox
X-GNOME-FullName[ff]=Mozilla Firefox
X-GNOME-FullName[fi]=Mozilla Firefox
X-GNOME-FullName[fr]=Mozilla Firefox
X-GNOME-FullName[fur]=Mozilla Firefox
X-GNOME-FullName[fy_NL]=Mozilla Firefox
X-GNOME-FullName[ga_IE]=Mozilla Firefox
X-GNOME-FullName[gd]=Mozilla Firefox
X-GNOME-FullName[gl]=Mozilla Firefox
X-GNOME-FullName[gn]=Mozilla Firefox
X-GNOME-FullName[gu_IN]=Mozilla Firefox
X-GNOME-FullName[he]=Mozilla Firefox
X-GNOME-FullName[hi_IN]=Mozilla Firefox
X-GNOME-FullName[hr]=Mozilla Firefox
X-GNOME-FullName[hsb]=Mozilla Firefox
X-GNOME-FullName[hu]=Mozilla Firefox
X-GNOME-FullName[hy_AM]=Mozilla Firefox
X-GNOME-FullName[ia]=Mozilla Firefox
X-GNOME-FullName[id]=Mozilla Firefox
X-GNOME-FullName[is]=Mozilla Firefox
X-GNOME-FullName[it]=Mozilla Firefox
X-GNOME-FullName[ja]=Mozilla Firefox
X-GNOME-FullName[ka]=Mozilla Firefox
X-GNOME-FullName[kab]=Mozilla Firefox
X-GNOME-FullName[kk]=Mozilla Firefox
X-GNOME-FullName[km]=Mozilla Firefox
X-GNOME-FullName[kn]=Mozilla Firefox
X-GNOME-FullName[ko]=Mozilla Firefox
X-GNOME-FullName[lij]=Mozilla Firefox
X-GNOME-FullName[lt]=Mozilla Firefox
X-GNOME-FullName[lv]=Mozilla Firefox
X-GNOME-FullName[mk]=Mozilla Firefox
X-GNOME-FullName[mr]=Mozilla Firefox
X-GNOME-FullName[ms]=Mozilla Firefox
X-GNOME-FullName[my]=Mozilla Firefox
X-GNOME-FullName[nb_NO]=Mozilla Firefox
X-GNOME-FullName[ne_NP]=Mozilla Firefox
X-GNOME-FullName[nl]=Mozilla Firefox
X-GNOME-FullName[nn_NO]=Mozilla Firefox
X-GNOME-FullName[oc]=Mozilla Firefox
X-GNOME-FullName[pa_IN]=Mozilla Firefox
X-GNOME-FullName[pl]=Mozilla Firefox
X-GNOME-FullName[pt_BR]=Mozilla Firefox
X-GNOME-FullName[pt_PT]=Mozilla Firefox
X-GNOME-FullName[rm]=Mozilla Firefox
X-GNOME-FullName[ro]=Mozilla Firefox
X-GNOME-FullName[ru]=Mozilla Firefox
X-GNOME-FullName[sat]=Mozilla Firefox
X-GNOME-FullName[sc]=Mozilla Firefox
X-GNOME-FullName[sco]=Mozilla Firefox
X-GNOME-FullName[si]=Mozilla Firefox
X-GNOME-FullName[sk]=Mozilla Firefox
X-GNOME-FullName[skr]=Mozilla Firefox
X-GNOME-FullName[sl]=Mozilla Firefox
X-GNOME-FullName[son]=Mozilla Firefox
X-GNOME-FullName[sq]=Mozilla Firefox
X-GNOME-FullName[sr]=Mozilla Firefox
X-GNOME-FullName[sv_SE]=Mozilla Firefox
X-GNOME-FullName[szl]=Mozilla Firefox
X-GNOME-FullName[ta]=Mozilla Firefox
X-GNOME-FullName[te]=Mozilla Firefox
X-GNOME-FullName[tg]=Mozilla Firefox
X-GNOME-FullName[th]=Mozilla Firefox
X-GNOME-FullName[tl]=Mozilla Firefox
X-GNOME-FullName[tr]=Mozilla Firefox
X-GNOME-FullName[trs]=Mozilla Firefox
X-GNOME-FullName[uk]=Mozilla Firefox
X-GNOME-FullName[ur]=Mozilla Firefox
X-GNOME-FullName[uz]=Mozilla Firefox
X-GNOME-FullName[vi]=Mozilla Firefox
X-GNOME-FullName[xh]=Mozilla Firefox
X-GNOME-FullName[zh_CN]=Mozilla Firefox
X-GNOME-FullName[zh_TW]=Mozilla Firefox
X-Flatpak=org.mozilla.firefox
[Desktop Action new-window]
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox --new-window @@u %u @@
Name=New Window
Name[ach]=New Window
Name[af]=New Window
Name[an]=New Window
Name[ar]=نافذة جديدة
Name[ast]=New Window
Name[az]=New Window
Name[be]=Новае акно
Name[bg]=Нов прозорец
Name[bn]=নতুন উইন্ডো
Name[br]=Prenestr nevez
Name[bs]=Novi prozor
Name[ca]=Finestra nova
Name[ca_valencia]=New Window
Name[cak]=K'ak'a' Tzuwäch
Name[cs]=Nové okno
Name[cy]=Ffenestr Newydd
Name[da]=Nyt vindue
Name[de]=Neues Fenster
Name[dsb]=Nowe wokno
Name[el]=Νέο παράθυρο
Name[en_CA]=New Window
Name[en_GB]=New Window
Name[eo]=Nova fenestro
Name[es_AR]=Nueva ventana
Name[es_CL]=Nueva ventana
Name[es_ES]=Nueva ventana
Name[es_MX]=Nueva ventana
Name[et]=New Window
Name[eu]=Leiho berria
Name[fa]=پنجره جدید‌
Name[ff]=New Window
Name[fi]=Uusi ikkuna
Name[fr]=Nouvelle fenêtre
Name[fur]=Gnûf barcon
Name[fy_NL]=Nij finster
Name[ga_IE]=New Window
Name[gd]=Uinneag ùr
Name[gl]=Nova xanela
Name[gn]=Ovetã pyahu
Name[gu_IN]=New Window
Name[he]=חלון חדש
Name[hi_IN]=New Window
Name[hr]=Novi prozor
Name[hsb]=Nowe wokno
Name[hu]=Új ablak
Name[hy_AM]=Նոր պատուհան
Name[ia]=Nove fenestra
Name[id]=Jendela Baru
Name[is]=Nýr gluggi
Name[it]=Nuova finestra
Name[ja]=新しいウィンドウ
Name[ka]=ახალი ფანჯარა
Name[kab]=Asfaylu amaynut
Name[kk]=Жаңа терезе
Name[km]=បង្អួច​​​ថ្មី
Name[kn]=New Window
Name[ko]=새 창
Name[lij]=Neuvo Barcon
Name[lt]=New Window
Name[lv]=Jauns logs
Name[mk]=New Window
Name[mr]=New Window
Name[ms]=New Window
Name[my]=New Window
Name[nb_NO]=Nytt vindu
Name[ne_NP]=नयाँ सञ्झ्याल
Name[nl]=Nieuw venster
Name[nn_NO]=Nytt vindauge
Name[oc]=Fenèstra novèla
Name[pa_IN]=ਨਵੀਂ ਵਿੰਡੋ
Name[pl]=Nowe okno
Name[pt_BR]=Nova janela
Name[pt_PT]=Nova janela
Name[rm]=Nova fanestra
Name[ro]=Fereastră nouă
Name[ru]=Новое окно
Name[sat]=ᱱᱟᱶᱟ ᱣᱤᱱᱰᱳ
Name[sc]=Ventana noa
Name[sco]=New Window
Name[si]=නව කවුළුව
Name[sk]=Nové okno
Name[skr]=نویں ونڈو
Name[sl]=Novo okno
Name[son]=New Window
Name[sq]=Dritare e Re
Name[sr]=Нови прозор
Name[sv_SE]=Nytt fönster
Name[szl]=New Window
Name[ta]=New Window
Name[te]=కొత్త కిటికీ
Name[tg]=Равзанаи нав
Name[th]=หน้าต่างใหม่
Name[tl]=New Window
Name[tr]=Yeni pencere
Name[trs]=Bēntanâ nākàa
Name[uk]=Нове вікно
Name[ur]=New Window
Name[uz]=New Window
Name[vi]=Cửa sổ mới
Name[xh]=New Window
Name[zh_CN]=新建窗口
Name[zh_TW]=開新視窗
[Desktop Action new-private-window]
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox --file-forwarding org.mozilla.firefox --private-window @@u %u @@
Name=New Private Window
Name[ach]=New Private Window
Name[af]=New Private Window
Name[an]=New Private Window
Name[ar]=نافذة خاصة جديدة
Name[ast]=New Private Window
Name[az]=New Private Window
Name[be]=Новае прыватнае акно
Name[bg]=Нов личен прозорец
Name[bn]=নতুন ব্যক্তিগত উইন্ডো
Name[br]=Prenestr prevez nevez
Name[bs]=Novi privatni prozor
Name[ca]=Finestra privada nova
Name[ca_valencia]=New Private Window
Name[cak]=K'ak'a' Ichinan Tzuwäch
Name[cs]=Nové anonymní okno
Name[cy]=Ffenestr Breifat Newydd
Name[da]=Nyt privat vindue
Name[de]=Neues privates Fenster
Name[dsb]=Nowe priwatne wokno
Name[el]=Νέο ιδιωτικό παράθυρο
Name[en_CA]=New Private Window
Name[en_GB]=New Private Window
Name[eo]=Nova privata fenestro
Name[es_AR]=Nueva ventana privada
Name[es_CL]=Nueva ventana privada
Name[es_ES]=Nueva ventana privada
Name[es_MX]=Nueva ventana privada
Name[et]=New Private Window
Name[eu]=Leiho pribatu berria
Name[fa]=پنجره ناشناس جدید
Name[ff]=New Private Window
Name[fi]=Uusi yksityinen ikkuna
Name[fr]=Nouvelle fenêtre privée
Name[fur]=Gnûf barcon privât
Name[fy_NL]=Nij priveefinster
Name[ga_IE]=New Private Window
Name[gd]=Uinneag phrìobhaideach ùr
Name[gl]=Nova xanela privada
Name[gn]=Ovetã ñemi pyahu
Name[gu_IN]=New Private Window
Name[he]=חלון פרטי חדש
Name[hi_IN]=New Private Window
Name[hr]=Novi privatni prozor
Name[hsb]=Nowe priwatne wokno
Name[hu]=Új privát ablak
Name[hy_AM]=Նոր գաղտնի պատուհան
Name[ia]=Nove fenestra private
Name[id]=Jendela Mode Pribadi Baru
Name[is]=Nýr huliðsgluggi
Name[it]=Nuova finestra anonima
Name[ja]=新しいプライベートウィンドウ
Name[ka]=ახალი პირადი ფანჯარა
Name[kab]=Asfaylu amaynut n tunigin tusligt
Name[kk]=Жаңа жекелік терезе
Name[km]=បង្អួច​ឯកជន​ថ្មី
Name[kn]=New Private Window
Name[ko]=새 사생활 보호 창
Name[lij]=Neuvo Barcon Privòu
Name[lt]=New Private Window
Name[lv]=Jauns privātais logs
Name[mk]=New Private Window
Name[mr]=New Private Window
Name[ms]=New Private Window
Name[my]=New Private Window
Name[nb_NO]=Nytt privat vindu
Name[ne_NP]=नयाँ निजी सञ्झ्याल
Name[nl]=Nieuw privévenster
Name[nn_NO]=Nytt privat vindauge
Name[oc]=Fenèstra privada novèla
Name[pa_IN]=ਨਵੀਂ ਪ੍ਰਾਈਵੇਟ ਵਿੰਡੋ
Name[pl]=Nowe okno prywatne
Name[pt_BR]=Nova janela privativa
Name[pt_PT]=Nova janela privada
Name[rm]=Nova fanestra privata
Name[ro]=Fereastră privată nouă
Name[ru]=Новое приватное окно
Name[sat]=ᱱᱟᱶᱟ ᱱᱤᱡᱮᱨᱟᱜ ᱣᱤᱱᱰᱳ
Name[sc]=Ventana privada noa
Name[sco]=New Private Window
Name[si]=නව පෞද්. කවුළුව
Name[sk]=Nové súkromné okno
Name[skr]=نویں نجی ونڈو
Name[sl]=Novo zasebno okno
Name[son]=New Private Window
Name[sq]=Dritare e Re Private
Name[sr]=Нови приватни прозор
Name[sv_SE]=Nytt privat fönster
Name[szl]=New Private Window
Name[ta]=New Private Window
Name[te]=కొత్త ఆంతరంగిక కిటికీ
Name[tg]=Равзанаи хусусии нав
Name[th]=หน้าต่างส่วนตัวใหม่
Name[tl]=New Private Window
Name[tr]=Yeni gizli pencere
Name[trs]=Bēntanâ huì nākàa
Name[uk]=Приватне вікно
Name[ur]=New Private Window
Name[uz]=New Private Window
Name[vi]=Cửa sổ riêng tư mới
Name[xh]=New Private Window
Name[zh_CN]=新建隐私窗口
Name[zh_TW]=開新隱私視窗
[Desktop Action open-profile-manager]
Exec=/usr/bin/flatpak run --branch=stable --arch=aarch64 --command=firefox org.mozilla.firefox --ProfileManager
Name=Open Profile Manager
Name[ach]=Open Profile Manager
Name[af]=Open Profile Manager
Name[an]=Open Profile Manager
Name[ar]=افتح مدير الملف الشخصي
Name[ast]=Open Profile Manager
Name[az]=Open Profile Manager
Name[be]=Адкрыць менеджар профіляў
Name[bg]=Отваряне на мениджъра на профили
Name[bn]=Open Profile Manager
Name[br]=Digeriñ an ardoer aeladoù
Name[bs]=Otvori Menadžera profila
Name[ca]=Obre el gestor de perfils
Name[ca_valencia]=Open Profile Manager
Name[cak]=Open Profile Manager
Name[cs]=Otevřít Správce profilů
Name[cy]=Agorwch y Rheolwr Proffil
Name[da]=Åbn profilhåndtering
Name[de]=Profilverwaltung öffnen
Name[dsb]=Profilowy zastojnik wócyniś
Name[el]=Άνοιγμα Διαχείρισης προφίλ
Name[en_CA]=Open Profile Manager
Name[en_GB]=Open Profile Manager
Name[eo]=Malfermi administranton de profiloj
Name[es_AR]=Abrir administrador de perfiles
Name[es_CL]=Abrir administrador de perfiles
Name[es_ES]=Abrir administrador de perfiles
Name[es_MX]=Abrir administrador de perfiles
Name[et]=Open Profile Manager
Name[eu]=Ireki profilen kudeatzailea
Name[fa]=گشودن مدیر نمایه
Name[ff]=Open Profile Manager
Name[fi]=Avaa profiilien hallinta
Name[fr]=Ouvrir le gestionnaire de profils
Name[fur]=Vierç gjestôr profîi
Name[fy_NL]=Profylbehearder iepenje
Name[ga_IE]=Open Profile Manager
Name[gd]=Fosgail manaidsear nam pròifilean
Name[gl]=Abrir o xestor de perfís
Name[gn]=Embojuruja mba’ete ñangarekoha
Name[gu_IN]=Open Profile Manager
Name[he]=פתיחת מנהל הפרופילים
Name[hi_IN]=Open Profile Manager
Name[hr]=Otvori upravljač profila
Name[hsb]=Zrjadowak profilow wočinić
Name[hu]=Profilkezelő megnyitása
Name[hy_AM]=Բացեք պրոֆիլի կառավարիչը
Name[ia]=Aperir le gestor de profilo
Name[id]=Buka Pengelola Profil
Name[is]=Opna umsýslu notandasniða
Name[it]=Apri gestore profili
Name[ja]=プロファイルマネージャーを開く
Name[ka]=პროფილის მმართველის გახსნა
Name[kab]=Ldi amsefrak n umaɣnu
Name[kk]=Профильдер бақарушысын ашу
Name[km]=Open Profile Manager
Name[kn]=Open Profile Manager
Name[ko]=프로필 관리자 열기
Name[lij]=Open Profile Manager
Name[lt]=Open Profile Manager
Name[lv]=Atvērt profilu pārvaldnieku
Name[mk]=Open Profile Manager
Name[mr]=Open Profile Manager
Name[ms]=Open Profile Manager
Name[my]=Open Profile Manager
Name[nb_NO]=Åpne profilbehandler
Name[ne_NP]=Open Profile Manager
Name[nl]=Profielbeheerder openen
Name[nn_NO]=Opne profilhandsaming
Name[oc]=Dobrir lo gestionari de perfils
Name[pa_IN]=ਪਰੋਫ਼ਾਈਲ ਮੈਨੇਜਰ ਖੋਲ੍ਹੋ
Name[pl]=Menedżer profili
Name[pt_BR]=Abrir gerenciador de perfis
Name[pt_PT]=Abrir o Gestor de Perfis
Name[rm]=Avrir l'administraziun da profils
Name[ro]=Deschide managerul de profiluri
Name[ru]=Открыть менеджер профилей
Name[sat]=ᱢᱮᱫᱦᱟᱸ ᱢᱮᱱᱮᱡᱚᱨ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ
Name[sc]=Aberi su gestore de profilos
Name[sco]=Open Profile Manager
Name[si]=පැතිකඩ කළමනාකරු අරින්න
Name[sk]=Otvoriť Správcu profilov
Name[skr]=پروفائل منیجر کھولو
Name[sl]=Odpri upravitelja profilov
Name[son]=Open Profile Manager
Name[sq]=Hapni Përgjegjës Profilesh
Name[sr]=Отворите управљач профила
Name[sv_SE]=Öppna Profilhanteraren
Name[szl]=Open Profile Manager
Name[ta]=Open Profile Manager
Name[te]=Open Profile Manager
Name[tg]=Кушодани мудири профилҳо
Name[th]=เปิดตัวจัดการโปรไฟล์
Name[tl]=Open Profile Manager
Name[tr]=Profil yöneticisini aç
Name[trs]=Sa nīkāj ñu’ūnj nej perfî huā nì’nï̀nj ïn
Name[uk]=Відкрити менеджер профілів
Name[ur]=Open Profile Manager
Name[uz]=Open Profile Manager
Name[vi]=Mở trình quản lý hồ sơ
Name[xh]=Open Profile Manager
Name[zh_CN]=打开配置文件管理器
Name[zh_TW]=開啟設定檔管理員
+106
View File
@@ -0,0 +1,106 @@
# steam-frame-nix-launchers (lib.nix prepends spec, awk_script, runtime,
# apps, exports): writes the Flatpak/file launchers of steamFrame.launchers
# to <runtime>/steam-frame-nix/applications (tmpfs), where the links in
# ~/.local/share/applications point.
# - one spec file per launcher (desktop ID = file name): rewrite.awk's
# environment, SFN_FILE for a host file;
# - an entry is replaced (temp file + rename) only when its content changed;
# entries without a source (app not installed) or of launchers no longer
# configured are removed; with an unknown Exec format the launcher is
# skipped: the entry is a copy of the original (a missing file behind the
# link would hide the original from the menus);
# - .<id>.desktop.sum holds the hash of what was written last: a mismatch
# means someone edited the entry (KDE's "Edit Application"), which is
# overwritten with a warning;
# - if anything changed, the mtime of ~/.local/share/applications is updated
# (a running Steam rescans the "+" menu).
out=$runtime/steam-frame-nix/applications
log() { echo "steam-frame-nix-launchers: $*" >&2; }
if [[ ! -d $runtime ]]; then
log "$runtime doesn't exist (outer session not running?); skipped"
exit 0
fi
ids=()
for f in "$spec"/*; do [[ -e $f ]] && ids+=("${f##*/}"); done
if (( ${#ids[@]} == 0 )) && [[ ! -d $out ]]; then exit 0; fi
mkdir -p "$out"
exec 9>"$out/.lock"
flock 9
rm -f "$out"/.*.tmp.*
IFS=: read -ra export_dirs <<< "$exports"
changed=0
remove() { # id why
if [[ -e $out/$1.desktop ]]; then
rm -f "$out/$1.desktop"
changed=1
log "$1: entry removed ($2)"
fi
rm -f "$out/.$1.desktop.sum"
}
# The link in ~/.local/share/applications is ours unless something replaced it.
check_link() { # id
local l=$apps/$1.desktop
if [[ -e $l || -L $l ]] && [[ $(readlink -m "$l") != "$(readlink -m "$out/$1.desktop")" ]]; then
log "warning: $l no longer leads to $out/$1.desktop (edited, e.g. with KDE's \"Edit Application\"?); set steamFrame.launchers.\"$1\".settings instead and remove it"
fi
}
generate() { # id
local id=$1 dst=$out/$1.desktop sum=$out/.$1.desktop.sum src='' d tmp rc
unset "${!SFN_@}"
# shellcheck source=/dev/null
source "$spec/$id"
if [[ -n $SFN_FILE ]]; then
[[ -f $SFN_FILE ]] && src=$SFN_FILE
else
for d in "${export_dirs[@]}"; do
if [[ -f $d/$SFN_FLATPAK_ID.desktop ]]; then src=$d/$SFN_FLATPAK_ID.desktop; break; fi
done
fi
if [[ -z $src ]]; then
remove "$id" "no source entry: ${SFN_FILE:-Flatpak $SFN_FLATPAK_ID not installed}"
return 0
fi
export "${!SFN_@}"
export SFN_SOURCE=$src
tmp=$(mktemp "$out/.$id.desktop.tmp.XXXXXX")
rc=0
LC_ALL=C gawk -f "$awk_script" "$src" "$src" > "$tmp" 2> "$tmp.err" || rc=$?
if (( rc == 3 )); then
log "warning: $id: $(tr -s "\n" " " < "$tmp.err"); launcher not applied, the original entry is used"
cat "$src" > "$tmp"
elif (( rc != 0 )); then
log "error: $id: rewriting $src failed (status $rc): $(tr -s "\n" " " < "$tmp.err")"
rm -f "$tmp" "$tmp.err"
return 0
fi
rm -f "$tmp.err"
if [[ -f $dst && -f $sum ]] && [[ $(sha256sum < "$dst") != "$(cat "$sum")" ]]; then
log "warning: $dst was edited (e.g. with KDE's \"Edit Application\"); overwritten, set steamFrame.launchers.\"$id\".settings instead"
fi
if [[ -f $dst ]] && cmp -s "$tmp" "$dst"; then
rm -f "$tmp"
else
chmod 644 "$tmp"
mv -f "$tmp" "$dst"
changed=1
log "$id: entry written from $src"
fi
sha256sum < "$dst" > "$sum.tmp.$$"
mv -f "$sum.tmp.$$" "$sum"
check_link "$id"
}
for id in "${ids[@]}"; do generate "$id"; done
# Launchers no longer configured.
for f in "$out"/*.desktop "$out"/.*.desktop.sum; do
[[ -e $f ]] || continue
id=${f##*/}; id=${id#.}; id=${id%.sum}; id=${id%.desktop}
[[ -e $spec/$id ]] || remove "$id" "launcher no longer configured"
done
if (( changed )) && [[ -d $apps ]]; then touch -c "$apps"; fi
+241
View File
@@ -0,0 +1,241 @@
# Pieces of steamFrame.launchers (launchers.nix) that the check
# (check.nix) uses too: the per-launcher option type, Exec quoting, the
# rewrite environment, the build-time entry of a package and the runtime
# generator.
{ lib, pkgs }:
let
walletNames = [ "org.kde.kwalletd6" "org.freedesktop.secrets" ];
# One argument in desktop entry Exec syntax (key-file escaping of the whole
# value is rewrite.awk's): quoted when it has characters outside a safe
# set, with " ` $ \ escaped; % doubled (field codes).
quoteExec = s:
let
q = if builtins.match "[A-Za-z0-9_/.:,=+@-]+" s != null then s
else "\"" + lib.replaceStrings [ "\\" "\"" "`" "$" ] [ "\\\\" "\\\"" "\\`" "\\$" ] s + "\"";
in lib.replaceStrings [ "%" ] [ "%%" ] q;
execLine = args: lib.concatMapStringsSep " " quoteExec args;
envArgs = env: lib.mapAttrsToList (k: v: "${k}=${v}") env;
envPrefix = env: lib.optionals (env != { }) ([ "env" ] ++ envArgs env);
# "flatpak" | "package" | "file"
kindOf = l: if l.source.package != null then "package"
else if l.source.file != null then "file" else "flatpak";
in rec {
inherit quoteExec execLine walletNames kindOf;
# The option type of one launcher; `bus` is session.bus.
launcherModule = { bus }: { name, config, ... }: let
flatpak = kindOf config == "flatpak";
in {
options = {
source = {
flatpak = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
defaultText = lib.literalMD "the desktop ID, when neither `package` nor `file` is set";
example = "org.mozilla.firefox";
description = ''
Flatpak app ID whose exported entry
(`~/.local/share/flatpak/exports/share/applications/<ID>.desktop`,
then `/var/lib/flatpak/...`) is rewritten at runtime.
'';
};
package = lib.mkOption {
type = lib.types.nullOr lib.types.package;
default = null;
example = lib.literalExpression "pkgs.claude-desktop";
description = ''
Nix package whose `share/applications/<desktop ID>.desktop` is
rewritten at build time (the build fails if it has none).
'';
};
file = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/usr/share/applications/org.kde.konsole.desktop";
description = "Desktop entry on the host, rewritten at runtime.";
};
};
hostEnv = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
example = { DBUS_SESSION_BUS_ADDRESS = "unix:path=/run/user/1000/bus"; };
description = ''
Environment of the process the entry starts (`env K=V` before the
command): for a Flatpak, of the `flatpak` client, so e.g. its
sandbox's D-Bus proxy and portals use that bus.
'';
};
env = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
example = { MOZ_ENABLE_WAYLAND = "0"; };
description = ''
Environment of the app: `flatpak run --env=K=V` for a Flatpak, like
`hostEnv` otherwise.
'';
};
flatpakArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "--device=all" ];
description = "Further `flatpak run` options, before the app ID (Flatpaks only).";
};
args = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "--ozone-platform=x11" ];
description = ''
Arguments right after the app ID / program, before the entry's own
(plain strings, quoted for you).
'';
};
wrappers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = lib.literalExpression ''[ "''${pkgs.writeShellScript "wrap" "exec \"$@\""}" ]'';
description = ''
Commands the entry's command line is passed to, outermost first:
`Exec=<wrappers> <original command>` (each gets the full command
line as its arguments).
'';
};
mimeTypes = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "x-scheme-handler/rdp" ];
description = "Added to the entry's `MimeType=`, without making the app their default.";
};
defaultFor = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
description = ''
MIME types / `x-scheme-handler/<scheme>` the app becomes the default
and a recommended handler for (`xdg.mimeApps`, Added Associations:
the portal then opens them without an app chooser, which VR doesn't
show); added to `MimeType=` too.
'';
};
settings = lib.mkOption {
type = lib.types.attrsOf (lib.types.nullOr lib.types.str);
default = { };
example = { Name = "Element (wallet)"; Keywords = null; };
description = ''
`[Desktop Entry]` keys to set or override (value in key-file syntax,
as given); `null` removes a key. Either way the key's localized
variants (`Name[de]=`) are dropped.
'';
};
keyring = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Keep the app's secrets in the one KDE wallet of both sessions: run
it on the outer bus (`hostEnv.DBUS_SESSION_BUS_ADDRESS`); a
Flatpak also gets `--talk-name=org.kde.kwalletd6
--talk-name=org.freedesktop.secrets`.
'';
};
electron = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Pass `--password-store=kwallet6` (Electron apps: in the Steam
session they'd use an unencrypted local store). Needs
`keyring.enable`.
'';
};
};
command = lib.mkOption {
type = lib.types.str;
readOnly = true;
description = ''
Approximately the command the entry runs, for a terminal (without
the entry's own options such as `--branch` or `--command`).
'';
};
};
config = {
hostEnv = lib.mkIf config.keyring.enable { DBUS_SESSION_BUS_ADDRESS = bus; };
flatpakArgs = lib.mkIf (config.keyring.enable && flatpak)
(lib.mkBefore (map (n: "--talk-name=${n}") walletNames));
args = lib.mkIf config.keyring.electron (lib.mkBefore [ "--password-store=kwallet6" ]);
command = command (config // { id = name; });
};
};
flatpakIdOf = l: if l.source.flatpak != null then l.source.flatpak else l.id;
# Approximate shell command of a launcher (attrs as the option, plus `id`).
command = l: let
kind = kindOf l;
pkg = l.source.package;
in lib.escapeShellArgs (
envPrefix (l.hostEnv // lib.optionalAttrs (kind != "flatpak") l.env)
++ l.wrappers
++ (if kind == "flatpak" then
[ "flatpak" "run" ] ++ l.flatpakArgs ++ map (e: "--env=${e}") (envArgs l.env) ++ [ (flatpakIdOf l) ]
else if kind == "package" then
[ "${pkg}/bin/${pkg.meta.mainProgram or (lib.getName pkg)}" ]
else [ "<program of ${l.source.file}>" ])
++ l.args);
# The environment of rewrite.awk for a launcher (without SFN_SOURCE).
rewriteEnv = l: let flatpak = kindOf l == "flatpak"; in {
SFN_MODE = if flatpak then "flatpak" else "program";
SFN_FLATPAK_ID = if flatpak then flatpakIdOf l else "";
SFN_PREFIX = execLine (envPrefix (l.hostEnv // lib.optionalAttrs (!flatpak) l.env) ++ l.wrappers);
SFN_FLATPAK_ARGS = lib.optionalString flatpak
(execLine (l.flatpakArgs ++ map (e: "--env=${e}") (envArgs l.env)));
SFN_ARGS = execLine l.args;
SFN_MIME = lib.concatMapStrings (m: "${m};") (lib.unique (l.mimeTypes ++ l.defaultFor));
SFN_SETTINGS = lib.concatStrings (lib.mapAttrsToList
(k: v: if v == null then "${k}\n" else "${k}=${v}\n") l.settings);
};
# Build time: the package's entry, rewritten.
packageEntry = l: let
src = "${l.source.package}/share/applications/${l.id}.desktop";
in pkgs.runCommand "${l.id}.desktop" ({
nativeBuildInputs = [ pkgs.gawk ];
preferLocalBuild = true;
allowSubstitutes = false;
SFN_SOURCE = src;
} // rewriteEnv l) ''
if [ ! -f ${lib.escapeShellArg src} ]; then
echo "steamFrame.launchers.\"${l.id}\": ${l.source.package} has no share/applications/${l.id}.desktop" >&2
exit 1
fi
LC_ALL=C gawk -f ${./rewrite.awk} "$SFN_SOURCE" "$SFN_SOURCE" > $out || {
echo "steamFrame.launchers.\"${l.id}\": can't rewrite $SFN_SOURCE" >&2
exit 1
}
'';
# Runtime: the steam-frame-nix-launchers command for the Flatpak/file
# `launchers` (attrs of launchers with `id`); the dirs can be overridden
# with STEAM_FRAME_NIX_{RUNTIME_DIR,APPLICATIONS_DIR,FLATPAK_EXPORTS}.
generator = { launchers, runtimeDir, exportDirs, applicationsDir }: let
spec = pkgs.linkFarm "steam-frame-nix-launchers-spec" (lib.mapAttrsToList (id: l: {
name = id;
path = pkgs.writeText "steam-frame-nix-launcher-${id}" (lib.toShellVars (rewriteEnv l // {
SFN_FILE = if kindOf l == "file" then l.source.file else "";
}));
}) launchers);
in pkgs.writeShellApplication {
name = "steam-frame-nix-launchers";
runtimeInputs = [ pkgs.coreutils pkgs.gawk pkgs.util-linux ];
text = ''
spec=${spec}
awk_script=${./rewrite.awk}
runtime=''${STEAM_FRAME_NIX_RUNTIME_DIR:-${lib.escapeShellArg runtimeDir}}
apps=''${STEAM_FRAME_NIX_APPLICATIONS_DIR:-${lib.escapeShellArg applicationsDir}}
exports=''${STEAM_FRAME_NIX_FLATPAK_EXPORTS:-${lib.escapeShellArg (lib.concatStringsSep ":" exportDirs)}}
'' + builtins.readFile ./generate.sh;
};
}
+192
View File
@@ -0,0 +1,192 @@
# Rewrites a desktop entry for steamFrame.launchers (launchers.nix): run as
# LC_ALL=C gawk -f rewrite.awk FILE FILE (two passes over the same file)
# with the launcher in the environment (ENVIRON, never -v: no escape
# processing):
# SFN_MODE flatpak | program
# SFN_FLATPAK_ID app ID, the anchor when the entry has no X-Flatpak=
# SFN_PREFIX Exec text before the command (env K=V..., wrappers)
# SFN_FLATPAK_ARGS Exec text before the app ID (flatpak)
# SFN_ARGS Exec text after the app ID / program
# SFN_MIME MIME types to add to MimeType= ("a;b;")
# SFN_SETTINGS lines "Key=value" (set) or "Key" (remove)
# SFN_SOURCE path written as X-SteamFrameNix-Source=
# The SFN_*ARGS/PREFIX values are in Exec syntax (quoted, % doubled); the
# key-file escaping of the whole Exec value is done here.
#
# Line based: comments, unknown and localized keys stay as they are. Exec= of
# [Desktop Entry] and every [Desktop Action *] is rewritten:
# flatpak: <prefix> <original up to the app ID> <flatpak args> <ID> <args> <rest>
# (the first token equal to the ID after `run`, whose preceding
# token's basename is `flatpak`)
# program: <prefix> <original up to the program> <args> <rest>
# (the first token after an optional leading `env A=B ...`)
# An Exec= without that anchor: nothing is printed, exit 3. No [Desktop
# Entry]: exit 4.
function trim(s) { sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s); return s }
# Key of a "Key=value" line ("" for other lines), localized keys included.
function keyof(line, k) {
if (line ~ /^[ \t]*#/ || line !~ /=/) return ""
k = line; sub(/=.*/, "", k); return trim(k)
}
function valueof(line, v) { v = line; sub(/^[^=]*=[ \t]*/, "", v); return v }
function base(k) { sub(/\[.*/, "", k); return k }
# Key-file string escapes (GLib): \s \n \t \r \\.
function kf_unescape(s, out, i, c, n) {
out = ""
for (i = 1; i <= length(s); i++) {
c = substr(s, i, 1)
if (c == "\\" && i < length(s)) {
n = substr(s, ++i, 1)
if (n == "s") c = " "; else if (n == "n") c = "\n"; else if (n == "t") c = "\t"
else if (n == "r") c = "\r"; else if (n == "\\") c = "\\"; else c = "\\" n
}
out = out c
}
return out
}
function kf_escape(s) {
gsub(/\\/, "\\\\", s); gsub(/\n/, "\\n", s); gsub(/\t/, "\\t", s); gsub(/\r/, "\\r", s)
return s
}
# Splits an Exec value (Exec syntax) into tokens: TS/TE start/end offsets in
# s, TV the unquoted value. Returns the count, -1 on an unclosed quote.
function tokenize(s, n, i, c, q, v, len) {
delete TS; delete TE; delete TV
n = 0; i = 1; len = length(s)
while (i <= len) {
c = substr(s, i, 1)
if (c == " " || c == "\t") { i++; continue }
TS[++n] = i; v = ""; q = 0
while (i <= len) {
c = substr(s, i, 1)
if (!q && (c == " " || c == "\t")) break
if (c == "\"") { q = !q; i++; continue }
if (q && c == "\\" && i < len) { v = v substr(s, i + 1, 1); i += 2; continue }
v = v c; i++
}
if (q) return -1
TE[n] = i; TV[n] = v
}
return n
}
function join3(a, b, c, r) {
r = a
if (b != "") r = (r == "" ? b : r " " b)
if (c != "") r = (r == "" ? c : r " " c)
return r
}
# The rewritten Exec value (raw key-file text), or "\001" without anchor.
function rewrite_exec(raw, s, n, k, j, b, head, tail, pre, v) {
s = kf_unescape(raw)
n = tokenize(s)
if (n <= 0) return "\001"
k = 0
if (ENVIRON["SFN_MODE"] == "flatpak") {
for (j = 2; j < n && !k; j++) {
b = TV[j - 1]; sub(/.*\//, "", b)
if (b == "flatpak" && TV[j] == "run")
for (v = j + 1; v <= n; v++) if (TV[v] == ANCHOR) { k = v; break }
}
if (!k) return "\001"
head = trim(substr(s, 1, TS[k] - 1))
pre = join3(ENVIRON["SFN_PREFIX"], head, ENVIRON["SFN_FLATPAK_ARGS"])
pre = join3(pre, substr(s, TS[k], TE[k] - TS[k]), "")
} else {
k = 1
if (TV[1] == "env") {
for (k = 2; k <= n && TV[k] ~ /^[A-Za-z_][A-Za-z0-9_]*=/; k++) ;
if (k > n || TV[k] ~ /^-/) return "\001"
}
pre = join3(ENVIRON["SFN_PREFIX"], trim(substr(s, 1, TE[k] - 1)), "")
}
tail = substr(s, TE[k])
return kf_escape(join3(pre, ENVIRON["SFN_ARGS"], "") tail)
}
function in_entry() { return GROUP == "[Desktop Entry]" }
# Pass 1: the X-Flatpak= of [Desktop Entry].
FNR == NR {
if ($0 ~ /^\[/) GROUP = trim($0)
else if (in_entry() && keyof($0) == "X-Flatpak" && XFLATPAK == "") XFLATPAK = trim(valueof($0))
next
}
FNR == 1 {
ANCHOR = XFLATPAK != "" ? XFLATPAK : ENVIRON["SFN_FLATPAK_ID"]
GROUP = ""; N = 0; ENTRY_END = 0; FAIL = ""
# settings: SET[key] = value, DEL[key]
ns = split(ENVIRON["SFN_SETTINGS"], sl, "\n")
for (i = 1; i <= ns; i++) {
if (sl[i] == "") continue
if (index(sl[i], "=")) { k = substr(sl[i], 1, index(sl[i], "=") - 1); SET[k] = substr(sl[i], index(sl[i], "=") + 1); ORDER[++NSET] = k }
else DEL[sl[i]] = 1
}
nm = split(ENVIRON["SFN_MIME"], ml, ";")
}
{
line = $0
if (line ~ /^\[/) {
GROUP = trim(line); L[++N] = line
if (in_entry()) { SEEN_ENTRY = 1; ENTRY_END = N }
next
}
key = keyof(line)
if (key != "" && (in_entry() || GROUP ~ /^\[Desktop Action /)) {
if (key == "Exec" && !(in_entry() && (key in SET || key in DEL))) {
v = rewrite_exec(valueof(line))
if (v == "\001") { FAIL = FAIL "\n " GROUP " Exec=" valueof(line); next }
line = "Exec=" v
}
}
if (key != "" && in_entry()) {
b = base(key)
if (b in SET || b in DEL) {
if (key != b || b in DEL || b in DONE) next # localized variant, removed, or duplicate
line = b "=" SET[b]; DONE[b] = 1
} else if (key == "DBusActivatable" && tolower(trim(valueof(line))) == "true") {
line = "DBusActivatable=false"
} else if (key == "X-SteamFrameNix-Source") {
next
} else if (key == "MimeType" && !MIMEDONE) {
line = "MimeType=" merge_mime(valueof(line)); MIMEDONE = 1
}
}
L[++N] = line
if (in_entry() && trim(line) != "") ENTRY_END = N
}
function merge_mime(v, have, cur, i, out) {
out = v
if (out != "" && out !~ /;$/) out = out ";"
split(v, cur, ";")
for (i in cur) if (cur[i] != "") have[trim(cur[i])] = 1
for (i = 1; i <= nm; i++) if (ml[i] != "" && !(ml[i] in have)) { out = out ml[i] ";"; have[ml[i]] = 1 }
return out
}
END {
if (FAIL != "") {
print "unknown Exec format (no " (ENVIRON["SFN_MODE"] == "flatpak" ? "`flatpak run ... " ANCHOR "`" : "program") "):" FAIL > "/dev/stderr"
exit 3
}
if (!SEEN_ENTRY) { print "no [Desktop Entry] group" > "/dev/stderr"; exit 4 }
for (i = 1; i <= N; i++) {
print L[i]
if (i == ENTRY_END) {
for (j = 1; j <= NSET; j++) if (!(ORDER[j] in DONE)) print ORDER[j] "=" SET[ORDER[j]]
if (!MIMEDONE && !("MimeType" in SET) && !("MimeType" in DEL) && nm > 0) {
m = merge_mime("")
if (m != "") print "MimeType=" m
}
print "X-SteamFrameNix-Source=" ENVIRON["SFN_SOURCE"]
}
}
}
+4 -4
View File
@@ -62,10 +62,10 @@
# jellyfin.hardwareDecoding.enable = true;
# # Apps that keep logins in the KDE wallet: one wallet for both
# # sessions (Element: install im.riot.Riot yourself):
# keyring.flatpaks."im.riot.Riot" = {
# name = "Element";
# electron = true;
# schemeHandlers = [ "element" "io.element.desktop" ]; # SSO callback
# launchers."im.riot.Riot" = {
# keyring = { enable = true; electron = true; };
# # SSO callback:
# defaultFor = [ "x-scheme-handler/element" "x-scheme-handler/io.element.desktop" ];
# };
# docker.enable = true; # rootless Docker, user service
# };