godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
87.2k stars 19.6k forks source link

FileSelected Signal Never Emitted on Windows Native File Dialog #94154

Open caleb-mostyn opened 2 weeks ago

caleb-mostyn commented 2 weeks ago

Tested versions

Reproducible in 4.2.2 Stable Mono (.NET)

System information

Windows 11 - Godot v4.2.2.stable.mono - Vulkan (Forward+) - AMD Ryzen 7 7840HS w/ Radeon 780M Graphics (16 Threads)

Issue description

When creating a FileDialog object in C# set to use native dialogs, the FileSelected signal is emitted correctly on Linux but not on Windows.

On Linux, regardless of at what point the signal is connected to, it is properly emitted and connected to. When running the same code on Windows, it appears that either the signal is not properly emitted or is not being connected to. This issue did not occur if the FileDialog was a native Godot file dialog.

Some more investigating showed that the signal worked properly if connected to before calling Show() on the FileDialog object, but not after.

Steps to reproduce

  1. Create a new FileDialog object
  2. Set FileDialog.Access to FileDialog.AccessEnum.FileSystem and FileDialog.UseNativeDialog to true so that the native OS file dialog is used
  3. Call Show() on the FileDialog object
  4. Connect to the FileSelected signal in whichever manner appropriate (+= the signal, Connect())
  5. Open the FileDialog and attempt to select a file

My MRP does these steps, both in that order as well as swapping step 3 and 4. To see it work correctly and print the path selected, run it in the editor then press the left arrow key, and to see it fail to work and not print anything, press the right arrow key.

(If necessary, the InputMap can be changed, the two inputs are simply titled "working" and "not_working")

Minimal reproduction project (MRP)

file-dialog-mrp.zip

bruvzg commented 2 weeks ago

Call Show() on the FileDialog object Connect to the FileSelected signal in whichever manner appropriate (+= the signal, Connect())

It should be connected before calling show (the same is true for any other file dialog property).

Due to the nature of native file dialogs, Godot do not have any control over it after it is shown. In many cases, the native dialog is executed in the context of a separate process and is fully isolated for security reasons (the primary purpose of native dialogs is accessing files outside the base application sandbox).

lostminds commented 2 weeks ago

It should be connected before calling show (the same is true for any other file dialog property).

I understand this regarding the other dialogue properties, as they need to be set before the native dialogue panel is shown. But for the signal for a file having been selected, shouldn't that call be made from the native dialogue back into the godot FileDialog object when the file is selected? And at that point if the signal has been connected, shouldn't it be emitted? Even if the signal was connected while the native panel UI was showing?

caleb-mostyn commented 2 weeks ago

Due to the nature of native file dialogs, Godot do not have any control over it after it is shown.

I get that, but what caused me to notice this in the first place was that the problem did not occur on Linux but did on Windows, for no immediately obvious reason. If there's not really a way to control it, I'd say it would be ideal to prevent connecting to signals or any other behavior that may be incorrect after show() is called, or at the very least add it to the documentation that show() may cause OS specific issues.

bruvzg commented 2 weeks ago

But for the signal for a file having been selected, shouldn't that call be made from the native dialogue back into the godot FileDialog object when the file is selected? And at that point if the signal has been connected, shouldn't it be emitted?

Native dialog is calling the built-in callback in the FileDialog class, which is calling user callback, so it's actually strange that it is not working. I guess show call on Windows is blocking, and it is never connected until dialog is closed. I will check it a bit later.

bruvzg commented 2 weeks ago

I guess show call on Windows is blocking, and it is never connected until dialog is closed. I will check it a bit later.

It is blocking, and seems like it can't be called from a thread, so probably nothing can be done.

lostminds commented 2 weeks ago

It is blocking, and seems like it can't be called from a thread, so probably nothing can be done.

Perhaps a warning could be issued to highlight this limitation then? As it's likely the fileSelected signal will always be intended to be used with FileDialogs, perhaps a check can be performed on show for native FileDialogs to check if the signal has anything connected, and if not warn that it needs to be connected before show is called as it's blocking on some platforms?

A slightly hacky way to get around this could be to defer the actual native dialog show call until the next frame when show is called. This would as I understand it mean that at least the order of the signal connection line and show line or any other configuration in the same script function won't matter. It might also have the benefit of not blocking at that show call on some platforms so the script execution will continue the same on all platforms.