Skip to content

Use the xdg-desktop-portal file chooser on Linux - #133

Merged
bjarneo merged 2 commits into
omacom:mainfrom
wienieclaurowy:portal-file-chooser
Oct 4, 2026
Merged

bjarneo merged 2 commits into
omacom:mainfrom
wienieclaurowy:portal-file-chooser

Conversation

@wienieclaurowy

Copy link
Copy Markdown
Contributor

Fixes #132.

Wails v2 draws GtkFileChooserDialog directly on Linux, so Aether's file and folder dialogs never reach xdg-desktop-portal and ignore the file picker the user has configured. This routes them through the portal's FileChooser and keeps the Wails dialog as a fallback.

What this changes

  • internal/platform/filechooser.go (new): PortalOpenFile calls org.freedesktop.portal.FileChooser.OpenFile over the session bus with godbus (already in the module graph through Wails; go.mod just marks it direct). It subscribes to the Request.Response signal before making the call so a fast reply can't be missed, and also handles the case where the portal returns a handle other than the one derived from handle_token. Wails-style ;-joined patterns are split into portal glob rules. Returned file:// URIs are decoded with url.Parse, so a + in a filename stays a +.
  • dialogs.go (new): unexported openFileDialog / openDirectoryDialog helpers on App. On Linux they try the portal first; if the call errors (no portal running, no FileChooser backend), they log it and show the Wails dialog as before. A cancelled pick returns "" just like the Wails dialog. On macOS and Windows nothing changes. The helpers are unexported, so no new frontend bindings are generated.
  • app.go: the five existing wailsrt.OpenFileDialog / wailsrt.OpenDirectoryDialog calls go through those helpers. Titles, filters and default directories are passed through unchanged.

No new dependencies.

Behaviour to be aware of

  • With Omarchy's default portal config (hyprland;gtk), users get the GTK portal's file chooser instead of the in-process GTK3 dialog. It looks very close, but it is a visible change.
  • The portal dialog is not attached to Aether's window as a transient parent, because Wails v2 does not expose the native window handle the portal expects.

Testing

  • Added internal/platform/filechooser_test.go: request path derivation, filter splitting, the a(sa(us)) D-Bus signature of the filters, response parsing (selected, cancelled, ended, no URIs, a path with spaces and +), and rejection of malformed bodies and non-file URIs.
  • go test ./internal/... ./cli/... passes.
  • go vet clean on the changed packages; gofmt -l clean on changed files.
  • npm run check: 0 errors. npm test: 116/116 pass (frontend untouched).
  • Manual, on Omarchy (Hyprland) with xdg-desktop-portal-termfilechooser as the FileChooser backend: built with make build, launched without GTK_USE_PORTAL / GDK_DEBUG, opened Select Wallpaper and Choose Wallpaper Folder. dbus-monitor showed the portal OpenFile calls answered through the configured backend, and no fallback was logged.

🤖 Generated with Claude Code

Wails v2 draws GtkFileChooserDialog directly, which bypasses
xdg-desktop-portal, so the file picker the user configured for their
desktop (KDE, GTK portal, a terminal file manager, ...) is never used.
Ask the portal's FileChooser over D-Bus for the five open-file and
open-directory dialogs, and fall back to the Wails dialog when no
portal answers.
Limit the OpenFile method call to 10 seconds, so a stuck portal no
longer blocks the dialog forever. Treat response 2 as an error, because
portal backends send it when they fail. Match Response signals only
from the portal bus name.
@bjarneo
bjarneo merged commit f96837c into omacom:main Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

File dialogs bypass xdg-desktop-portal on Linux (GTK3 dialog hardcoded by Wails v2)

2 participants