Skip to content

Don't accept a trailing dot from native save dialogs - #122725

Open
AdrienUfferte wants to merge 1 commit into
godotengine:masterfrom
AdrienUfferte:fix-native-dialog-trailing-dot
Open

Don't accept a trailing dot from native save dialogs#122725
AdrienUfferte wants to merge 1 commit into
godotengine:masterfrom
AdrienUfferte:fix-native-dialog-trailing-dot

Conversation

@AdrienUfferte

Copy link
Copy Markdown
Contributor

Disclaimer: AI helped me find the root cause, check that Godot had no existing issue or PR for it, and write this description.

What problem(s) does this PR solve?

With the KDE portal, a native save dialog can return a name ending in a bare dot — new_asset_2.res.. Such a name has no extension, so ResourceSaver refuses to write it and the save silently fails behind a warning (hit on a mesh's save_to_file/path in Advanced Import Settings):

WARNING: Failed to save mesh <name> to 'res://models/new_asset_2.res.'.

The dot is KDE's, not Godot's: for application/octet-stream, KIO's KFileWidget auto-selected a single "." as the extension when the typed name carried no suffix it recognised — .res is not one, hence the dot after new_asset_2.res in the repro below. Present in KIO 6.12.0, removed in 6.13.0 (KDE bug 501085, commit a7be926869d8). Godot sends ;application/octet-stream for All Files (*.*) since #99350, so this affects Godot >= 4.4 on KIO < 6.13.

Godot then emits the name verbatim: All Files (*.*) is the last filter entry, so _native_dialog_cb_with_options takes its valid = true; // Match none. branch.

Same class as the macOS fixes #113757 and #114781, handled in platform/macos/* rather than left to the OS. Normalising a name Godot is handed also keeps this independent of the user's KIO version.

No issue opened, given the size of the fix.

Additional information

The 4 lines strip one trailing dot at the top of the FILE_MODE_SAVE_FILE branch and re-sync filename_edit, as the extension-append path just below already does. Doing it at the top also feeds that path a clean name: previously a returned foo. under a *.res filter became foo..res.

Nothing intentional is lost, because KIO treats a trailing dot the same way — appendExtension() strips it, so README. saves as README, and its comment tells you to type README.. if you really want the dot. The bug is that this check runs on the name as typed, so a dot KIO appends itself escapes it.

Glad to move the guard to platform/linuxbsd/freedesktop_portal_desktop.cpp (the placement matching the macOS fixes), or to stop sending application/octet-stream for the All Files (*.*) entry instead, if either is preferred.

Reproducer — needs a Plasma session on xdg-desktop-portal-kde with KIO < 6.13 and a target file that does not exist yet (appendExtension() early-returns when it does):

extends Node

func _ready() -> void:
	var fd := FileDialog.new()
	fd.use_native_dialog = true
	fd.access = FileDialog.ACCESS_FILESYSTEM
	fd.file_mode = FileDialog.FILE_MODE_SAVE_FILE
	fd.add_filter("*.res", "Resource")
	fd.file_selected.connect(func(p): print("[", p, "]"))
	add_child(fd)
	fd.popup_centered()

Select All Files (*.*), type new_asset_2.res, Save.
Before: [/.../new_asset_2.res.] — after: [/.../new_asset_2.res]

Here are the screenshots of how it happens:

1 (1) 2 (1) 3 (1) 4 (1)

KDE's "Automatically select filename extension" can append a bare "." to
the chosen file name when the selected filter carries no usable extension
(KDE bug 501085, fixed in KIO 6.13). FileDialog emitted that path as-is.

A file name ending in a bare dot has no extension, so ResourceSaver then
refuses to write it and the save silently fails behind a warning. This is
the same class of defect as the macOS extension handling fixed in godotengine#113757
and godotengine#114781, and is guarded the same way: in Godot, not in the OS.
@AdrienUfferte
AdrienUfferte requested a review from a team as a code owner August 22, 2026 19:17
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.

1 participant