Add modules.desktop.portals, enabled by the desktop aggregator, pinning the XDG desktop portal routing explicitly: the three interfaces the Hyprland portal implements (screencast, screenshot, global shortcuts) go to Hyprland, and GTK is the default for file dialogs and appearance. The backend packages already arrive with the Hyprland compositor integration, so this module owns only the routing, which was previously empty and rode on the config file the Hyprland package happens to ship. Making it a first-class module so in-app screen sharing does not depend on that incidental default.
3.0 KiB
spec, blocked-by
| spec | blocked-by |
|---|---|
| hyprland-desktop | 0021-desktop-group-and-hyprland-session |
What to build
Screen sharing that works inside applications, so video calls and browser screen-share function.
Add a portals module to the desktop group, enabled through the aggregator, wiring the Hyprland desktop portal (screencast, screenshot, global shortcuts) plus the GTK portal (file dialogs and appearance). In-app screen sharing depends on these regardless of whether the recorder is present.
Acceptance criteria
- A portals module exists in the desktop group and is enabled by the aggregator.
- The Hyprland desktop portal (screencast, screenshot, global shortcuts) and the GTK portal (file dialogs, appearance) are both configured.
- In-app screen sharing is available independent of the screen recorder.
- neogaia builds green under
nix flake check.
Implementation Notes
-
The module owns routing, not the backend packages. The Hyprland compositor integration (
programs.hyprland) already forces both portal backends intoxdg.portal.extraPortals—xdg-desktop-portal-hyprlandthrough itsportalPackage, andxdg-desktop-portal-gtkthrough nixpkgs'wayland-session.nix(enableGtkPortaldefaults on) — and turnsxdg.portal.enableon. A portal backend only answers while its compositor runs, so those packages belong with the compositor and cannot be removed there; re-declaring them here would only duplicate them. The genuinely-missing, first-class piece was the routing:xdg.portal.configwas empty, and which backend answered each request rode on a config file the Hyprland package happens to ship (hyprland-portals.conf,default=hyprland;gtk). This module makes that routing explicit and declarative. -
Per-interface routing, not a preference list. Rather than
default = [ "hyprland" "gtk" ](which tries Hyprland first for every interface and falls through to GTK), the three interfaces the Hyprland portal actually implements —ScreenCast,Screenshot,GlobalShortcuts, confirmed from itshyprland.portalfile — are routed to Hyprland explicitly, and GTK is the default for everything else. This directly encodes the spec's split (Hyprland for the screen-facing requests, GTK for file dialogs and appearance) and keeps appearance on GTK even if a future Hyprland portal starts implementingorg.freedesktop.impl.portal.Settings. -
Already functional, now first-class. Because the compositor integration already supplied both backends and a working shipped route, in-app screen sharing was effectively working before this task as an implicit side-effect. The deliverable is the explicit, aggregator-enabled
modules.desktop.portalsmodule, so the desktop's checklist reads completely and screen sharing no longer depends on a package's incidental default. Verified: the built config emits/etc/xdg/xdg-desktop-portal/portals.confwithdefault=gtkplus the three Hyprland routes, and neogaia's toplevel builds green.