Skip to content

xdg: Apply the save dialog's selected filter to the file extension - #341

Open
itsF4LCON wants to merge 1 commit into
PolyMeilex:masterfrom
itsF4LCON:xdg-save-chosen-filter
Open

itsF4LCON wants to merge 1 commit into
PolyMeilex:masterfrom
itsF4LCON:xdg-save-chosen-filter

Conversation

@itsF4LCON

Copy link
Copy Markdown

Summary

With the XDG portal on GTK (xdg-desktop-portal-gtk), choosing a different filter in a save
dialog doesn't change the file name. The Response carries the selected filter in
current_filter, but rfd only read uris, so the app got the old extension back:

current_filter = ("PNG", [(0, "*.png")])
uris           = ["file:///home/me/Untitled-1.psd"]

An app that suggests Untitled-1.psd and offers PNG, JPEG, ... gets Untitled-1.psd when the
user picks PNG, and writes a PSD. The macOS save panel follows the selected format (#328), and
on Windows SetDefaultExtension makes the dialog swap the extension, so only Linux behaved this way.

This PR reads current_filter's label from the response, finds the filter rfd sent with that
label, and applies its first extension to the returned path when:

  • the name has no extension, or
  • it still has the extension of the name passed to set_file_name, and that extension isn't one
    of the selected filter's.

A typed extension is kept (Untitled-1.png typed with the PSD filter selected stays .png), as
is any extension that already matches the filter (psd/psb, any case). Filters whose first
extension is * or empty change nothing. If the renamed path already exists, the path the
portal returned is kept, since the portal only confirmed overwriting that one.

Only save_file uses the new field; Response::Selected gets a second element that the open
and folder paths ignore. The zenity fallback is unchanged.

Testing

  • Unit tests for the renaming rule (with_chosen_extension): suggested extension replaced,
    typed extension kept, matching extensions kept (case-insensitive), missing extension added,
    */empty filters ignored.
  • cargo test --no-default-features --features xdg-portal, cargo clippy --all-targets
    (default and xdg-portal), cargo fmt.
  • By hand on Hyprland with xdg-desktop-portal-gtk: a save dialog opened with
    Untitled-1.psd and PSD, PNG, ... filters.
    • PNG selected: before Untitled-1.psd, after Untitled-1.png.
    • PSD selected, Untitled-1.png typed: Untitled-1.png before and after.

Found through PhotoCraft (storytold/photocraft#4328), where Save As › PNG on Linux wrote a PSD.

zuujiscom added a commit to zuujiscom/photocraft that referenced this pull request Oct 15, 2026
…28, #4394)

The GTK file chooser behind the desktop portal keeps the typed name when
another file type is picked, and rfd 0.17.2 reads only the file name from
the portal's answer, so Untitled-1.psd with PNG picked was written as a
PSD. On Linux, Save As now asks the portal's FileChooser.SaveFile itself
(over the zbus already used for the portal), reads current_filter, and
gives the name that type's extension: an extension PhotoCraft saves is
replaced, none or another is appended. If that names an existing file, the
dialog opens again under the new name so the portal asks before replacing
it. rfd remains the fallback without a portal, and this can go once an rfd
release reads current_filter (PolyMeilex/rfd#341).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
zuujiscom added a commit to zuujiscom/photocraft that referenced this pull request Oct 15, 2026
… request handle

Review follow-ups, checked on real GNOME 46 and KDE Plasma 6.7.5 sessions
(Wayland and X11):

- An extension the user typed is kept, as in PolyMeilex/rfd#341: only a
  name with none, or still with the extension the dialog opened with, takes
  the picked type's. GTK reports the type even when it is untouched, so
  art.png with the PSD type left alone was saved as art.psd.
- The dialog opens on the stem (test), as on Windows (#4407): with
  test.psd in the name and PNG picked, GTK asked to replace test.psd,
  which the save leaves alone. A name that then exists is asked about
  again under that name; the rule compares against the suggested name, so
  a test.psd GTK completes back still becomes test.png.
- Response 2 (GNOME's dialog closed with Esc) is a cancel: it fell back to
  rfd, which opened a second Save As.
- The answer is awaited on the handle SaveFile returns, which a portal
  older than 0.9 picks itself (the Request documentation).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@PolyMeilex

Copy link
Copy Markdown
Owner

Sounds like a portal issue.

Lack of overwrite confirm dialog aside, a workaround in RFD would break for Flatpaks and Snaps which can't write to arbitrary paths.

skylartaylor added a commit to storytold/photocraft that referenced this pull request Oct 16, 2026
…, #4394) (#6151)

* Save As on Linux: the file type picked sets the extension (#6121, #4328, #4394)

The GTK file chooser behind the desktop portal keeps the typed name when
another file type is picked, and rfd 0.17.2 reads only the file name from
the portal's answer, so Untitled-1.psd with PNG picked was written as a
PSD. On Linux, Save As now asks the portal's FileChooser.SaveFile itself
(over the zbus already used for the portal), reads current_filter, and
gives the name that type's extension: an extension PhotoCraft saves is
replaced, none or another is appended. If that names an existing file, the
dialog opens again under the new name so the portal asks before replacing
it. rfd remains the fallback without a portal, and this can go once an rfd
release reads current_filter (PolyMeilex/rfd#341).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Save As on Linux: keep typed extensions, open on the stem, follow the request handle

Review follow-ups, checked on real GNOME 46 and KDE Plasma 6.7.5 sessions
(Wayland and X11):

- An extension the user typed is kept, as in PolyMeilex/rfd#341: only a
  name with none, or still with the extension the dialog opened with, takes
  the picked type's. GTK reports the type even when it is untouched, so
  art.png with the PSD type left alone was saved as art.psd.
- The dialog opens on the stem (test), as on Windows (#4407): with
  test.psd in the name and PNG picked, GTK asked to replace test.psd,
  which the save leaves alone. A name that then exists is asked about
  again under that name; the rule compares against the suggested name, so
  a test.psd GTK completes back still becomes test.png.
- Response 2 (GNOME's dialog closed with Esc) is a cancel: it fell back to
  rfd, which opened a second Save As.
- The answer is awaited on the handle SaveFile returns, which a portal
  older than 0.9 picks itself (the Request documentation).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* style(automation): format smart filter refresh closure

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: skylar taylor-barrick <hi@skylar.cc>
@itsF4LCON

Copy link
Copy Markdown
Author

Good point, I hadn't thought about the sandbox: a Flatpak or Snap only gets write access to the path the portal hands back, so renaming it in rfd would point at a file it can't write, and it would skip the portal's overwrite check too. I'll take it to xdg-desktop-portal-gtk instead. Happy to close this one.

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.

2 participants