Improve native file dialog parent window selection.

This commit is contained in:
bruvzg 2024-09-30 12:19:48 +03:00 committed by Pāvels Nadtočajevs
parent 134da37497
commit 3e4e6e6c0c
18 changed files with 322 additions and 233 deletions

View File

@ -143,6 +143,7 @@
<param index="4" name="mode" type="int" enum="DisplayServer.FileDialogMode" /> <param index="4" name="mode" type="int" enum="DisplayServer.FileDialogMode" />
<param index="5" name="filters" type="PackedStringArray" /> <param index="5" name="filters" type="PackedStringArray" />
<param index="6" name="callback" type="Callable" /> <param index="6" name="callback" type="Callable" />
<param index="7" name="parent_window_id" type="int" default="0" />
<description> <description>
Displays OS native dialog for selecting files or directories in the file system. Displays OS native dialog for selecting files or directories in the file system.
Each filter string in the [param filters] array should be formatted like this: [code]*.png,*.jpg,*.jpeg;Image Files;image/png,image/jpeg[/code]. The description text of the filter is optional and can be omitted. It is recommended to set both file extension and MIME type. See also [member FileDialog.filters]. Each filter string in the [param filters] array should be formatted like this: [code]*.png,*.jpg,*.jpeg;Image Files;image/png,image/jpeg[/code]. The description text of the filter is optional and can be omitted. It is recommended to set both file extension and MIME type. See also [member FileDialog.filters].
@ -166,6 +167,7 @@
<param index="6" name="filters" type="PackedStringArray" /> <param index="6" name="filters" type="PackedStringArray" />
<param index="7" name="options" type="Dictionary[]" /> <param index="7" name="options" type="Dictionary[]" />
<param index="8" name="callback" type="Callable" /> <param index="8" name="callback" type="Callable" />
<param index="9" name="parent_window_id" type="int" default="0" />
<description> <description>
Displays OS native dialog for selecting files or directories in the file system with additional user selectable options. Displays OS native dialog for selecting files or directories in the file system with additional user selectable options.
Each filter string in the [param filters] array should be formatted like this: [code]*.png,*.jpg,*.jpeg;Image Files;image/png,image/jpeg[/code]. The description text of the filter is optional and can be omitted. It is recommended to set both file extension and MIME type. See also [member FileDialog.filters]. Each filter string in the [param filters] array should be formatted like this: [code]*.png,*.jpg,*.jpeg;Image Files;image/png,image/jpeg[/code]. The description text of the filter is optional and can be omitted. It is recommended to set both file extension and MIME type. See also [member FileDialog.filters].

View File

@ -65,7 +65,15 @@ void EditorFileDialog::_native_popup() {
} else if (access == ACCESS_USERDATA) { } else if (access == ACCESS_USERDATA) {
root = OS::get_singleton()->get_user_data_dir(); root = OS::get_singleton()->get_user_data_dir();
} }
DisplayServer::get_singleton()->file_dialog_with_options_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, _get_options(), callable_mp(this, &EditorFileDialog::_native_dialog_cb));
// 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;
DisplayServer::get_singleton()->file_dialog_with_options_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(dir->get_text()), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, _get_options(), callable_mp(this, &EditorFileDialog::_native_dialog_cb), wid);
} }
void EditorFileDialog::popup(const Rect2i &p_rect) { void EditorFileDialog::popup(const Rect2i &p_rect) {

View File

@ -7,3 +7,10 @@ should instead be used to justify these changes and describe how users should wo
Add new entries at the end of the file. Add new entries at the end of the file.
## Changes between 4.4-stable and 4.5-stable ## Changes between 4.4-stable and 4.5-stable
GH-98194
--------
Validate extension JSON: Error: Field 'classes/DisplayServer/methods/file_dialog_show/arguments': size changed value in new API, from 7 to 8.
Validate extension JSON: Error: Field 'classes/DisplayServer/methods/file_dialog_with_options_show/arguments': size changed value in new API, from 9 to 10.
Optional argument added. Compatibility methods registered.

View File

@ -204,7 +204,7 @@ void DisplayServerAndroid::emit_input_dialog_callback(String p_text) {
} }
} }
Error DisplayServerAndroid::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) { Error DisplayServerAndroid::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) {
GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
ERR_FAIL_NULL_V(godot_java, FAILED); ERR_FAIL_NULL_V(godot_java, FAILED);
file_picker_callback = p_callback; file_picker_callback = p_callback;

View File

@ -131,7 +131,7 @@ public:
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override; virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override;
void emit_input_dialog_callback(String p_text); void emit_input_dialog_callback(String p_text);
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, const FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override; virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, const FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) override;
void emit_file_picker_callback(bool p_ok, const Vector<String> &p_selected_paths); void emit_file_picker_callback(bool p_ok, const Vector<String> &p_selected_paths);
virtual Color get_accent_color() const override; virtual Color get_accent_color() const override;

View File

@ -306,7 +306,7 @@ void DisplayServerWayland::set_system_theme_change_callback(const Callable &p_ca
portal_desktop->set_system_theme_change_callback(p_callable); portal_desktop->set_system_theme_change_callback(p_callable);
} }
Error DisplayServerWayland::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) { Error DisplayServerWayland::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) {
WindowID window_id = MAIN_WINDOW_ID; WindowID window_id = MAIN_WINDOW_ID;
// TODO: Use window IDs for multiwindow support. // TODO: Use window IDs for multiwindow support.
@ -314,7 +314,7 @@ Error DisplayServerWayland::file_dialog_show(const String &p_title, const String
return portal_desktop->file_dialog_show(window_id, (ws ? ws->exported_handle : String()), p_title, p_current_directory, String(), p_filename, p_mode, p_filters, TypedArray<Dictionary>(), p_callback, false); return portal_desktop->file_dialog_show(window_id, (ws ? ws->exported_handle : String()), p_title, p_current_directory, String(), p_filename, p_mode, p_filters, TypedArray<Dictionary>(), p_callback, false);
} }
Error DisplayServerWayland::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) { Error DisplayServerWayland::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) {
WindowID window_id = MAIN_WINDOW_ID; WindowID window_id = MAIN_WINDOW_ID;
// TODO: Use window IDs for multiwindow support. // TODO: Use window IDs for multiwindow support.

View File

@ -187,8 +187,8 @@ public:
virtual bool is_dark_mode() const override; virtual bool is_dark_mode() const override;
virtual void set_system_theme_change_callback(const Callable &p_callable) override; virtual void set_system_theme_change_callback(const Callable &p_callable) override;
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override; virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) override;
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override; virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) override;
#endif #endif
virtual void beep() const override; virtual void beep() const override;

View File

@ -402,26 +402,26 @@ void DisplayServerX11::set_system_theme_change_callback(const Callable &p_callab
portal_desktop->set_system_theme_change_callback(p_callable); portal_desktop->set_system_theme_change_callback(p_callable);
} }
Error DisplayServerX11::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) { Error DisplayServerX11::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) {
WindowID window_id = last_focused_window; WindowID window_id = p_window_id;
if (!windows.has(window_id)) { if (!windows.has(window_id) && !windows[window_id].is_popup) {
window_id = MAIN_WINDOW_ID; window_id = MAIN_WINDOW_ID;
} }
String xid = vformat("x11:%x", (uint64_t)windows[window_id].x11_window); String xid = vformat("x11:%x", (uint64_t)windows[window_id].x11_window);
return portal_desktop->file_dialog_show(last_focused_window, xid, p_title, p_current_directory, String(), p_filename, p_mode, p_filters, TypedArray<Dictionary>(), p_callback, false); return portal_desktop->file_dialog_show(p_window_id, xid, p_title, p_current_directory, String(), p_filename, p_mode, p_filters, TypedArray<Dictionary>(), p_callback, false);
} }
Error DisplayServerX11::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) { Error DisplayServerX11::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) {
WindowID window_id = last_focused_window; WindowID window_id = p_window_id;
if (!windows.has(window_id)) { if (!windows.has(window_id) && !windows[window_id].is_popup) {
window_id = MAIN_WINDOW_ID; window_id = MAIN_WINDOW_ID;
} }
String xid = vformat("x11:%x", (uint64_t)windows[window_id].x11_window); String xid = vformat("x11:%x", (uint64_t)windows[window_id].x11_window);
return portal_desktop->file_dialog_show(last_focused_window, xid, p_title, p_current_directory, p_root, p_filename, p_mode, p_filters, p_options, p_callback, true); return portal_desktop->file_dialog_show(p_window_id, xid, p_title, p_current_directory, p_root, p_filename, p_mode, p_filters, p_options, p_callback, true);
} }
#endif #endif

View File

@ -422,8 +422,8 @@ public:
virtual bool is_dark_mode() const override; virtual bool is_dark_mode() const override;
virtual void set_system_theme_change_callback(const Callable &p_callable) override; virtual void set_system_theme_change_callback(const Callable &p_callable) override;
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override; virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) override;
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override; virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) override;
#endif #endif
virtual void beep() const override; virtual void beep() const override;

View File

@ -236,7 +236,7 @@ private:
static NSCursor *_cursor_from_selector(SEL p_selector, SEL p_fallback = nil); static NSCursor *_cursor_from_selector(SEL p_selector, SEL p_fallback = nil);
Error _file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb); Error _file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb, WindowID p_window_id);
public: public:
void menu_callback(id p_sender); void menu_callback(id p_sender);
@ -303,8 +303,8 @@ public:
virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override; virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override;
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override; virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override;
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override; virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) override;
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override; virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) override;
virtual void beep() const override; virtual void beep() const override;

View File

@ -979,21 +979,25 @@ Error DisplayServerMacOS::dialog_show(String p_title, String p_description, Vect
return OK; return OK;
} }
Error DisplayServerMacOS::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) { Error DisplayServerMacOS::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) {
return _file_dialog_with_options_show(p_title, p_current_directory, String(), p_filename, p_show_hidden, p_mode, p_filters, TypedArray<Dictionary>(), p_callback, false); return _file_dialog_with_options_show(p_title, p_current_directory, String(), p_filename, p_show_hidden, p_mode, p_filters, TypedArray<Dictionary>(), p_callback, false, p_window_id);
} }
Error DisplayServerMacOS::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) { Error DisplayServerMacOS::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) {
return _file_dialog_with_options_show(p_title, p_current_directory, p_root, p_filename, p_show_hidden, p_mode, p_filters, p_options, p_callback, true); return _file_dialog_with_options_show(p_title, p_current_directory, p_root, p_filename, p_show_hidden, p_mode, p_filters, p_options, p_callback, true, p_window_id);
} }
Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb) { Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb, WindowID p_window_id) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
ERR_FAIL_INDEX_V(int(p_mode), FILE_DIALOG_MODE_SAVE_MAX, FAILED); ERR_FAIL_INDEX_V(int(p_mode), FILE_DIALOG_MODE_SAVE_MAX, FAILED);
NSString *url = [NSString stringWithUTF8String:p_current_directory.utf8().get_data()]; NSString *url = [NSString stringWithUTF8String:p_current_directory.utf8().get_data()];
WindowID prev_focus = last_focused_window;
NSWindow *nswindow = nullptr;
if (windows.has(p_window_id) && !windows[p_window_id].is_popup) {
nswindow = windows[p_window_id].window_object;
}
GodotOpenSaveDelegate *panel_delegate = [[GodotOpenSaveDelegate alloc] init]; GodotOpenSaveDelegate *panel_delegate = [[GodotOpenSaveDelegate alloc] init];
if (p_root.length() > 0) { if (p_root.length() > 0) {
@ -1015,8 +1019,7 @@ Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title,
[panel setNameFieldStringValue:fileurl]; [panel setNameFieldStringValue:fileurl];
} }
[panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] void (^completion_handler)(NSInteger ret) = ^(NSInteger ret) {
completionHandler:^(NSInteger ret) {
if (ret == NSModalResponseOK) { if (ret == NSModalResponseOK) {
// Save bookmark for folder. // Save bookmark for folder.
if (OS::get_singleton()->is_sandboxed()) { if (OS::get_singleton()->is_sandboxed()) {
@ -1103,10 +1106,15 @@ Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title,
} }
} }
} }
if (prev_focus != INVALID_WINDOW_ID) { if (p_window_id != INVALID_WINDOW_ID) {
callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(prev_focus); callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(p_window_id);
}
};
if (nswindow) {
[panel beginSheetModalForWindow:nswindow completionHandler:completion_handler];
} else {
[panel beginWithCompletionHandler:completion_handler];
} }
}];
} else { } else {
NSOpenPanel *panel = [NSOpenPanel openPanel]; NSOpenPanel *panel = [NSOpenPanel openPanel];
@ -1125,8 +1133,7 @@ Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title,
} }
[panel setAllowsMultipleSelection:(p_mode == FILE_DIALOG_MODE_OPEN_FILES)]; [panel setAllowsMultipleSelection:(p_mode == FILE_DIALOG_MODE_OPEN_FILES)];
[panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] void (^completion_handler)(NSInteger ret) = ^(NSInteger ret) {
completionHandler:^(NSInteger ret) {
if (ret == NSModalResponseOK) { if (ret == NSModalResponseOK) {
// Save bookmark for folder. // Save bookmark for folder.
NSArray *urls = [(NSOpenPanel *)panel URLs]; NSArray *urls = [(NSOpenPanel *)panel URLs];
@ -1219,10 +1226,15 @@ Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title,
} }
} }
} }
if (prev_focus != INVALID_WINDOW_ID) { if (p_window_id != INVALID_WINDOW_ID) {
callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(prev_focus); callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(p_window_id);
}
};
if (nswindow) {
[panel beginSheetModalForWindow:nswindow completionHandler:completion_handler];
} else {
[panel beginWithCompletionHandler:completion_handler];
} }
}];
} }
return OK; return OK;

View File

@ -269,12 +269,12 @@ void DisplayServerWindows::tts_stop() {
tts->stop(); tts->stop();
} }
Error DisplayServerWindows::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) { Error DisplayServerWindows::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) {
return _file_dialog_with_options_show(p_title, p_current_directory, String(), p_filename, p_show_hidden, p_mode, p_filters, TypedArray<Dictionary>(), p_callback, false); return _file_dialog_with_options_show(p_title, p_current_directory, String(), p_filename, p_show_hidden, p_mode, p_filters, TypedArray<Dictionary>(), p_callback, false, p_window_id);
} }
Error DisplayServerWindows::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) { Error DisplayServerWindows::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) {
return _file_dialog_with_options_show(p_title, p_current_directory, p_root, p_filename, p_show_hidden, p_mode, p_filters, p_options, p_callback, true); return _file_dialog_with_options_show(p_title, p_current_directory, p_root, p_filename, p_show_hidden, p_mode, p_filters, p_options, p_callback, true, p_window_id);
} }
// Silence warning due to a COM API weirdness. // Silence warning due to a COM API weirdness.
@ -700,15 +700,11 @@ void DisplayServerWindows::_thread_fd_monitor(void *p_ud) {
} }
} }
Error DisplayServerWindows::_file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb) { Error DisplayServerWindows::_file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb, WindowID p_window_id) {
_THREAD_SAFE_METHOD_ _THREAD_SAFE_METHOD_
ERR_FAIL_INDEX_V(int(p_mode), FILE_DIALOG_MODE_SAVE_MAX, FAILED); ERR_FAIL_INDEX_V(int(p_mode), FILE_DIALOG_MODE_SAVE_MAX, FAILED);
WindowID window_id = _get_focused_window_or_popup();
if (!windows.has(window_id)) {
window_id = MAIN_WINDOW_ID;
}
String appname; String appname;
if (Engine::get_singleton()->is_editor_hint()) { if (Engine::get_singleton()->is_editor_hint()) {
appname = "Godot.GodotEditor." + String(VERSION_BRANCH); appname = "Godot.GodotEditor." + String(VERSION_BRANCH);
@ -729,8 +725,8 @@ Error DisplayServerWindows::_file_dialog_with_options_show(const String &p_title
} }
FileDialogData *fd = memnew(FileDialogData); FileDialogData *fd = memnew(FileDialogData);
if (window_id != INVALID_WINDOW_ID) { if (windows.has(p_window_id) && !windows[p_window_id].is_popup) {
fd->hwnd_owner = windows[window_id].hWnd; fd->hwnd_owner = windows[p_window_id].hWnd;
RECT crect; RECT crect;
GetWindowRect(fd->hwnd_owner, &crect); GetWindowRect(fd->hwnd_owner, &crect);
fd->wrect = Rect2i(crect.left, crect.top, crect.right - crect.left, crect.bottom - crect.top); fd->wrect = Rect2i(crect.left, crect.top, crect.right - crect.left, crect.bottom - crect.top);
@ -745,7 +741,7 @@ Error DisplayServerWindows::_file_dialog_with_options_show(const String &p_title
fd->filename = p_filename; fd->filename = p_filename;
fd->show_hidden = p_show_hidden; fd->show_hidden = p_show_hidden;
fd->mode = p_mode; fd->mode = p_mode;
fd->window_id = window_id; fd->window_id = p_window_id;
fd->filters = p_filters; fd->filters = p_filters;
fd->options = p_options; fd->options = p_options;
fd->callback = p_callback; fd->callback = p_callback;

View File

@ -673,7 +673,7 @@ class DisplayServerWindows : public DisplayServer {
}; };
BitField<WinKeyModifierMask> _get_mods() const; BitField<WinKeyModifierMask> _get_mods() const;
Error _file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb); Error _file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, bool p_options_in_cb, WindowID p_window_id);
String _get_keyboard_layout_display_name(const String &p_klid) const; String _get_keyboard_layout_display_name(const String &p_klid) const;
String _get_klid(HKL p_hkl) const; String _get_klid(HKL p_hkl) const;
@ -713,8 +713,8 @@ public:
virtual Color get_base_color() const override; virtual Color get_base_color() const override;
virtual void set_system_theme_change_callback(const Callable &p_callable) override; virtual void set_system_theme_change_callback(const Callable &p_callable) override;
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override; virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) override;
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override; virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) override;
virtual void beep() const override; virtual void beep() const override;

View File

@ -68,10 +68,18 @@ void FileDialog::_native_popup() {
} else if (access == ACCESS_USERDATA) { } else if (access == ACCESS_USERDATA) {
root = OS::get_singleton()->get_user_data_dir(); 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)) { if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG_FILE_EXTRA)) {
DisplayServer::get_singleton()->file_dialog_with_options_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(full_dir), root, file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, _get_options(), callable_mp(this, &FileDialog::_native_dialog_cb_with_options)); DisplayServer::get_singleton()->file_dialog_with_options_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(full_dir), root, file->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 { } else {
DisplayServer::get_singleton()->file_dialog_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(full_dir), file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, callable_mp(this, &FileDialog::_native_dialog_cb)); DisplayServer::get_singleton()->file_dialog_show(get_translated_title(), ProjectSettings::get_singleton()->globalize_path(full_dir), file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), processed_filters, callable_mp(this, &FileDialog::_native_dialog_cb), wid);
} }
} }

View File

@ -0,0 +1,46 @@
/**************************************************************************/
/* display_server.compat.inc */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef DISABLE_DEPRECATED
Error DisplayServer::_file_dialog_show_bind_compat_98194(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) {
return file_dialog_show(p_title, p_current_directory, p_filename, p_show_hidden, p_mode, p_filters, p_callback, MAIN_WINDOW_ID);
}
Error DisplayServer::_file_dialog_with_options_show_bind_compat_98194(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) {
return file_dialog_with_options_show(p_title, p_current_directory, p_root, p_filename, p_show_hidden, p_mode, p_filters, p_options, p_callback, MAIN_WINDOW_ID);
}
void DisplayServer::_bind_compatibility_methods() {
ClassDB::bind_compatibility_method(D_METHOD("file_dialog_show", "title", "current_directory", "filename", "show_hidden", "mode", "filters", "callback"), &DisplayServer::_file_dialog_show_bind_compat_98194);
ClassDB::bind_compatibility_method(D_METHOD("file_dialog_with_options_show", "title", "current_directory", "root", "filename", "show_hidden", "mode", "filters", "options", "callback"), &DisplayServer::_file_dialog_with_options_show_bind_compat_98194);
}
#endif

View File

@ -29,6 +29,7 @@
/**************************************************************************/ /**************************************************************************/
#include "display_server.h" #include "display_server.h"
#include "display_server.compat.inc"
#include "core/input/input.h" #include "core/input/input.h"
#include "scene/resources/texture.h" #include "scene/resources/texture.h"
@ -704,12 +705,12 @@ Error DisplayServer::dialog_input_text(String p_title, String p_description, Str
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
} }
Error DisplayServer::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) { Error DisplayServer::file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) {
WARN_PRINT("Native dialogs not supported by this display server."); WARN_PRINT("Native dialogs not supported by this display server.");
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
} }
Error DisplayServer::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) { Error DisplayServer::file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) {
WARN_PRINT("Native dialogs not supported by this display server."); WARN_PRINT("Native dialogs not supported by this display server.");
return ERR_UNAVAILABLE; return ERR_UNAVAILABLE;
} }
@ -1040,8 +1041,8 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("dialog_show", "title", "description", "buttons", "callback"), &DisplayServer::dialog_show); ClassDB::bind_method(D_METHOD("dialog_show", "title", "description", "buttons", "callback"), &DisplayServer::dialog_show);
ClassDB::bind_method(D_METHOD("dialog_input_text", "title", "description", "existing_text", "callback"), &DisplayServer::dialog_input_text); ClassDB::bind_method(D_METHOD("dialog_input_text", "title", "description", "existing_text", "callback"), &DisplayServer::dialog_input_text);
ClassDB::bind_method(D_METHOD("file_dialog_show", "title", "current_directory", "filename", "show_hidden", "mode", "filters", "callback"), &DisplayServer::file_dialog_show); ClassDB::bind_method(D_METHOD("file_dialog_show", "title", "current_directory", "filename", "show_hidden", "mode", "filters", "callback", "parent_window_id"), &DisplayServer::file_dialog_show, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("file_dialog_with_options_show", "title", "current_directory", "root", "filename", "show_hidden", "mode", "filters", "options", "callback"), &DisplayServer::file_dialog_with_options_show); ClassDB::bind_method(D_METHOD("file_dialog_with_options_show", "title", "current_directory", "root", "filename", "show_hidden", "mode", "filters", "options", "callback", "parent_window_id"), &DisplayServer::file_dialog_with_options_show, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("beep"), &DisplayServer::beep); ClassDB::bind_method(D_METHOD("beep"), &DisplayServer::beep);

View File

@ -109,6 +109,10 @@ private:
protected: protected:
static void _bind_methods(); static void _bind_methods();
#ifndef DISABLE_DEPRECATED
static void _bind_compatibility_methods();
#endif
static Ref<Image> _get_cursor_image_from_resource(const Ref<Resource> &p_cursor, const Vector2 &p_hotspot); static Ref<Image> _get_cursor_image_from_resource(const Ref<Resource> &p_cursor, const Vector2 &p_hotspot);
enum { enum {
@ -592,8 +596,13 @@ public:
FILE_DIALOG_MODE_SAVE_FILE, FILE_DIALOG_MODE_SAVE_FILE,
FILE_DIALOG_MODE_SAVE_MAX FILE_DIALOG_MODE_SAVE_MAX
}; };
virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback); virtual Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id = MAIN_WINDOW_ID);
virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback); virtual Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id = MAIN_WINDOW_ID);
#ifndef DISABLE_DEPRECATED
Error _file_dialog_show_bind_compat_98194(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback);
Error _file_dialog_with_options_show_bind_compat_98194(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback);
#endif
virtual void beep() const; virtual void beep() const;

View File

@ -184,8 +184,8 @@ public:
Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override { return ERR_UNAVAILABLE; } Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override { return ERR_UNAVAILABLE; } Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override { return ERR_UNAVAILABLE; }
Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback) override { return ERR_UNAVAILABLE; } Error file_dialog_show(const String &p_title, const String &p_current_directory, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const Callable &p_callback, WindowID p_window_id) override { return ERR_UNAVAILABLE; }
Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback) override { return ERR_UNAVAILABLE; } Error file_dialog_with_options_show(const String &p_title, const String &p_current_directory, const String &p_root, const String &p_filename, bool p_show_hidden, FileDialogMode p_mode, const Vector<String> &p_filters, const TypedArray<Dictionary> &p_options, const Callable &p_callback, WindowID p_window_id) override { return ERR_UNAVAILABLE; }
void release_rendering_thread() override {} void release_rendering_thread() override {}
void swap_buffers() override {} void swap_buffers() override {}