Skip to content

feat(flatpak): flatpak dynamic desktop entries, waypipe overhaul#1800

Merged
brianmcgillion merged 3 commits intotiiuae:mainfrom
kajusnau:flatpak-app-entries
Mar 6, 2026
Merged

feat(flatpak): flatpak dynamic desktop entries, waypipe overhaul#1800
brianmcgillion merged 3 commits intotiiuae:mainfrom
kajusnau:flatpak-app-entries

Conversation

@kajusnau
Copy link
Copy Markdown
Collaborator

@kajusnau kajusnau commented Mar 4, 2026

Description of Changes

TL;DR

  • Flatpak apps installed in the Flatpak VM now automatically appear in the GUI VM's app library and can be launched like any other app
  • Clicking a Flatpak app in the app library routes the launch through givc to the Flatpak VM, where the app is started via flatpak run
  • A single persistent Waypipe server replaces the previous per-app Waypipe instances, simplifying app VM configuration and fixing some display and environment config issues

1. Flatpak Desktop Entry Export

Flatpak app desktop entries installed in the Flatpak VM are automatically exported to the GUI VM, where they appear in the app library and can be launched like any other app.

How the export works:

  • Systemd service (flatpak-share-installer) watches for installed Flatpak apps and copies the flatpak exports/share dir (which includes the desktop entries and icons) to the Unsafe share (/home/appuser/Unsafe share/.flatpak-share)
    • Size impact - tested with 3 apps (Spotify, Discord, Solitaire), 216K of space is used.
      These are mostly icons (svg or png), .desktop entries, and some metainfo files.
  • The Unsafe share is configured as an XDG profile in the GUI VM via environment.profiles, making the entries visible to the DE
  • Each entry's Exec= field is rewritten to route the launch through givc's flatpak-run command, which (basically) triggers flatpak run <app-id> in the Flatpak VM
    • The flatpak-run givc app actually reads the real desktop entry for the given app-id and executes that in Flatpak VM.

Note

If a Flatpak app is installed that duplicates an app already provided by us (e.g. Element, which is also provided via comms-vm), both entries will appear in the app library.

The Flatpak entry will show its source as "unknown", while the system-provided entry will correctly show "Nix" as its source.

This is a known limitation of the (un)intelligent source-detection logic in the freedesktop-desktop-entry crate, which is used by cosmic-app-library.

Desktop Entries' Export Visualized

flowchart LR
    subgraph FLATPAK_VM["Flatpak VM"]
        INSTALLED["installed flatpak apps"]
        EXPORTER["flatpak-share-installer"]
        EDITED["desktop entries with rewritten Exec="]
        SHARE["Unsafe flatpak-vm share"]
        INSTALLED --> EXPORTER --> EDITED --> SHARE
    end

    subgraph GUI_VM["GUI VM"]
        PROFILES["environment.profiles adds share as XDG profile"]
        APPLIBRARY["app appears in app library"]
        SHARE --> PROFILES --> APPLIBRARY
    end
Loading

Flatpak App Launch Flowchart

flowchart LR
    USER["user clicks desktop entry"]
    EXEC["Exec= runs ghaf-open flatpak-run with http://app.id"]
    GIVC_GUI["givc in GUI VM"]
    GIVC_FLATPAK["givc in Flatpak VM"]
    RUN["run-flatpak-app"]
    APP["app starts in Flatpak VM"]

    USER --> EXEC
    EXEC --> GIVC_GUI
    GIVC_GUI -- "flatpak-run url=http://app.id" --> GIVC_FLATPAK
    GIVC_FLATPAK --> RUN --> APP
Loading

2. Persistent Waypipe Server

Previously, a new Waypipe server instance was spawned for every app launch, requiring run-waypipe to be explicitly prefixed to each givc app definition. This made launching apps across VMs unintuitive, as it was unclear which environment variables (WAYLAND_DISPLAY, DISPLAY, XDG_SESSION_TYPE, etc.) needed to be set for which app. Running multiple apps simultaneously also meant multiple Waypipe server instances running at the same time unnecessarily.

What changed:

  • A single persistent Waypipe server now runs as a systemd user service in the App VM, listening for Wayland connections at $XDG_RUNTIME_DIR/wayland-ghaf
  • Apps are launched directly via their binaries with no Waypipe arguments or wrapper scripts. They automatically attach to the persistent server via WAYLAND_DISPLAY=wayland-ghaf
  • All required environment variables are set once at the session level, so any app launched in the VM gets the correct display configuration automatically
  • Optionally, an XWayland Satellite instance is also managed as a user service through the same Waypipe server, enabling X11 apps to run in the App VM via DISPLAY=:99

The following environment variables are set in the AppUser session:

WAYLAND_DISPLAY=wayland-ghaf
DISPLAY=:99
XDG_SESSION_TYPE=wayland
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus

Side-by-side Comparison

Aspect Old approach New approach
Waypipe instances One per app launch Single persistent server
App definitions Each givc app must be prefixed with run-waypipe No Waypipe arguments needed in app definitions, apps can be launched directly
Display and env. configuration Must be manually set per app, easy to misconfigure Set once at session level, inherited by all apps
X11 support Separate service required per app VM, manual starting/restarting for each app Optional XWayland Satellite managed by same server, X11 apps 'just work'
Performance Each app launch incurs Waypipe startup overhead No per-launch overhead, server is always ready. Potentially less memory overhead, faster startup
Failure impact Only affects the single app whose server crashed All running apps lose display if server crashes
Restart behavior New server spawned on next launch automatically Requires Restart=on-failure to recover

Old Approach Flowchart

flowchart TB
    subgraph BEFORE["BEFORE"]
        direction TB
        subgraph GUIVM_OLD["GUI VM"]
            CLIENT_OLD["waypipe client <- compositor"]
        end
        subgraph APPVM_OLD["App VM (flatpak)"]
            SP["Spotify"]
            DI["Discord (X11)"]
            WP1["waypipe server #1"]
            WP2["waypipe server #2"]
            VSOCK["vsock"]
            SP --> WP1 --> VSOCK
            DI --> WP2 --> VSOCK
        end
        VSOCK --> CLIENT_OLD
    end
Loading

New Approach Flowchart

flowchart TB
    subgraph AFTER["AFTER"]
        direction TB
        subgraph GUIVM_NEW["GUI VM"]
            CLIENT_NEW["waypipe client <- compositor"]
        end
        subgraph APPVM_NEW["App VM (flatpak)"]
            SERVER["waypipe server (systemd) (+ optional xwayland-satellite)"]
            VSOCK["vsock"]
            SP["Spotify"]
            DI["Discord (X11)"]
            SP -- "WAYLAND_DISPLAY=wayland-ghaf" --> SERVER
            DI -- "DISPLAY=:99" --> SERVER
        end
        SERVER --> VSOCK --> CLIENT_NEW
    end
Loading

Note

Flatpak VM is used heavily as an example here, but note that the waypipe overhaul applies to ALL App VMs

Type of Change

  • New Feature
  • Bug Fix
  • Improvement / Refactor

Related Issues / Tickets

Checklist

  • Clear summary in PR description
  • Detailed and meaningful commit message(s)
  • Commits are logically organized and squashed if appropriate
  • Contribution guidelines followed
  • Ghaf documentation updated with the commit - https://tiiuae.github.io/ghaf/
  • Author has run make-checks and it passes
  • All automatic GitHub Action checks pass - see actions
  • Author has added reviewers and removed PR draft status

Testing Instructions

Applicable Targets

  • Orin AGX aarch64
  • Orin NX aarch64
  • Lenovo X1 x86_64
  • Dell Latitude x86_64
  • System 76 x86_64

Installation Method

  • Requires full re-installation
  • Can be updated with nixos-rebuild ... switch
  • Other:

Test Steps To Verify:

Flatpak app desktop entries:

  1. Boot into Ghaf
  2. Launch the App Store and install some apps (good options include - Spotify (picky), Discord (X11), GNOME Weather (known to cause issues previously)
  3. After installation, verify apps appear in the app library (Note: some apps are automatically sorted/categorized, so they may appear in specific app library pages)

Flatpak app launching:

  1. Try launching any Flatpak app via their desktop entry from the app library, verify the app opens
  2. Try launching any flatpak app through the App Store, verify the app opens
  3. (Optional) verify flatpak file browser dialogs open as before, if this was present and tested before

Regression:

  1. Test crucial (or all) virtual apps - they should launch properly, have their appropriate border colors, names, icons.

Add a persistent Waypipe server as a systemd user service, replacing
the previous approach of spawning a new Waypipe instance per app launch
Apps now attach to the server automatically via WAYLAND_DISPLAY=wayland-ghaf.
XWayland Satellite is optionally started as a systemd service for X11 support.

Changes apply to all App VMs

Signed-off-by: Kajus Naujokaitis <kajus.naujokaitis@unikie.com>
@kajusnau kajusnau force-pushed the flatpak-app-entries branch from aa626c1 to 9eb1402 Compare March 5, 2026 12:15
@kajusnau kajusnau marked this pull request as ready for review March 5, 2026 12:16
@kajusnau kajusnau changed the title Flatpak dynamic desktop entries, waypipe overhaul feat(flatpak): flatpak dynamic desktop entries, waypipe overhaul Mar 5, 2026
@kajusnau
Copy link
Copy Markdown
Collaborator Author

kajusnau commented Mar 5, 2026

Waiting for reviews before asking for testing 🫡

@vunnyso
Copy link
Copy Markdown
Collaborator

vunnyso commented Mar 5, 2026

Nice feature to integrate. 🙂

Just did a quick test on fresh install on Lenovo Gen12.

  1. Open App store and installed Spotify
  2. Observed below message in journal of flatpak-vm
Mar 05 14:43:27 flatpak-vm flatpak-system-helper[1185]: system: Pulled app/com.spotify.Client/x86_64/stable from /var/lib/flatpak/repo/tmp/flatpak-cache-UPSIL3/repo-yLQaDI
Mar 05 14:43:27 flatpak-vm systemd[1]: Flatpak Share Installer was skipped because of an unmet condition check (ConditionDirectoryNotEmpty=/var/lib/flatpak/exports/share).
  1. Didn't see any desktop entry created for Spotify

Add flatpak-apps-forwarder service to copy installed Flatpak app desktop
entries to the Unsafe share, which is imported as an XDG profile in the
gui-vm
Exec fields are rewritten to route app launches through givc's
flatpak-run 'app' which runs 'flatpak run <app-id>' in flatpak-vm

Signed-off-by: Kajus Naujokaitis <kajus.naujokaitis@unikie.com>
@kajusnau
Copy link
Copy Markdown
Collaborator Author

kajusnau commented Mar 6, 2026

Just did a quick test on fresh install on Lenovo Gen12.

  1. Open App store and installed Spotify
  2. Observed below message in journal of flatpak-vm
    ...
  3. Didn't see any desktop entry created for Spotify

Thanks for testing!
The Path unit was too eager on fresh installs and the directory condition is not necessary, adjusted accordingly. Should be good now 👍

Add "Force Quit" and "Uninstall" desktop entry actions
to all installed flatpak apps. Allows the user to kill,
or uninstall the given application easily via GUI

Signed-off-by: Kajus Naujokaitis <kajus.naujokaitis@unikie.com>
@kajusnau
Copy link
Copy Markdown
Collaborator Author

kajusnau commented Mar 6, 2026

New feature:
"Force Quit" and "Uninstall" actions for each flatpak app desktop entry.
These work similar to the flatpak-run givc command used before, but instead making use of flatpak kill and flatpak uninstall respectively.
In GUI, these will show up as buttons in COSMIC App Library when right-clicking the app, or in the Dock when the app is already open and right-clicked.

Also did some minor refactoring as a consequence of this

Note: It seems that at the moment these actions don't appear to function in the COSMIC App Library, but work fine if the app is already open and right-clicked in the Dock. Seems like a COSMIC bug at first glance.

@brianmcgillion
Copy link
Copy Markdown
Collaborator

Waypipe instances One per app launch Single persistent server - I think that this goes against the wayland approach to keeping apps separate to ensure they do not interfer with each other. this is the X11 way :)

@brianmcgillion brianmcgillion merged commit 9afdb9c into tiiuae:main Mar 6, 2026
32 checks passed
@kajusnau kajusnau deleted the flatpak-app-entries branch March 9, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants