godot icon indicating copy to clipboard operation
godot copied to clipboard

FileDialog appears when `use_native_dialog` is assigned `true`

Open sockeye-d opened this issue 2 weeks ago • 5 comments

Tested versions

  • Reproducible in master [dec5a373d9] on KDE Plasma

System information

Godot v4.6.dev (dec5a373d) - Arch Linux #1 SMP PREEMPT_DYNAMIC Mon, 24 Nov 2025 15:21:09 +0000 on Wayland - X11 display driver, Multi-window, 2 monitors - Vulkan (Forward+) - dedicated NVIDIA GeForce RTX 3080 (nvidia; 580.105.08) - 12th Gen Intel(R) Core(TM) i9-12900K (24 threads) - 46.80 GiB memory

Issue description

Whenever the use_native_dialog is assigned true the dialog is shown.

Steps to reproduce

Create a script:

extends Control


func _ready() -> void:
	var fd := FileDialog.new()
	fd.hide()
	add_child(fd)
	fd.use_native_dialog = true

It doesn't appear when the last line is commented out.

Minimal reproduction project (MRP)

N/A

sockeye-d avatar Dec 08 '25 11:12 sockeye-d

Regression from:

  • https://github.com/godotengine/godot/pull/111212

CC @KoBeWi

Doesn't seem to be any explanation in the PR for this change

AThousandShips avatar Dec 08 '25 11:12 AThousandShips

For some reason, the setter is

void FileDialog::set_use_native_dialog(bool p_native) {
	use_native_dialog = p_native;

#ifdef TOOLS_ENABLED
	if (is_part_of_edited_scene()) {
		return;
	}
#endif

	// Replace the built-in dialog with the native one if it's currently visible.
	if (is_inside_tree() && _should_use_native_popup()) {
		ConfirmationDialog::set_visible(false);
		_native_popup();
	}
}

which calls

void FileDialog::_native_popup() {
	// Show native dialog directly.
	String root;
	if (!root_prefix.is_empty()) {
		root = ProjectSettings::get_singleton()->globalize_path(root_prefix);
	} else if (access == ACCESS_RESOURCES) {
		root = ProjectSettings::get_singleton()->get_resource_path();
	} else if (access == ACCESS_USERDATA) {
		root = OS::get_singleton()->get_user_data_dir();
	}

	// Attach native file dialog to first persistent parent window.
	Window *w = (is_transient() || is_transient_to_focused()) ? get_parent_visible_window() : nullptr;
	while (w && w->get_flag(FLAG_POPUP) && w->get_parent_visible_window()) {
		w = w->get_parent_visible_window();
	}
	DisplayServer::WindowID wid = w ? w->get_window_id() : DisplayServer::INVALID_WINDOW_ID;

	if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE_EXTRA)) {
		DisplayServer::get_singleton()->file_dialog_with_options_show(get_displayed_title(), ProjectSettings::get_singleton()->globalize_path(full_dir), root, filename_edit->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, _get_options(), callable_mp(this, &FileDialog::_native_dialog_cb_with_options), wid);
	} else {
		DisplayServer::get_singleton()->file_dialog_show(get_displayed_title(), ProjectSettings::get_singleton()->globalize_path(full_dir), filename_edit->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, callable_mp(this, &FileDialog::_native_dialog_cb), wid);
	}
}

which call DisplayServer::file_dialog_show or DisplayServer::file_dialog_with_options_show, so it seems obvious that setting it to true would make the window appear.

sockeye-d avatar Dec 08 '25 11:12 sockeye-d

I'll add back in that check and make a PR, I guess

sockeye-d avatar Dec 08 '25 11:12 sockeye-d

This was changed and previously the method checked visibility, it even has a comment saying it shows if visible, but it doesnt

AThousandShips avatar Dec 08 '25 11:12 AThousandShips

I replaced the condition with a new method, but missed that it also checks is_visible().

KoBeWi avatar Dec 08 '25 11:12 KoBeWi