From 3e4e6e6c0ce57ddecfa6c2653d940dd9f7f9aa5a Mon Sep 17 00:00:00 2001 From: bruvzg <7645683+bruvzg@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:19:48 +0300 Subject: [PATCH] Improve native file dialog parent window selection. --- doc/classes/DisplayServer.xml | 2 + editor/gui/editor_file_dialog.cpp | 10 +- .../4.4-stable.expected | 7 + platform/android/display_server_android.cpp | 2 +- platform/android/display_server_android.h | 2 +- .../wayland/display_server_wayland.cpp | 4 +- .../linuxbsd/wayland/display_server_wayland.h | 4 +- platform/linuxbsd/x11/display_server_x11.cpp | 16 +- platform/linuxbsd/x11/display_server_x11.h | 4 +- platform/macos/display_server_macos.h | 6 +- platform/macos/display_server_macos.mm | 388 +++++++++--------- platform/windows/display_server_windows.cpp | 20 +- platform/windows/display_server_windows.h | 6 +- scene/gui/file_dialog.cpp | 12 +- servers/display_server.compat.inc | 46 +++ servers/display_server.cpp | 9 +- servers/display_server.h | 13 +- servers/display_server_headless.h | 4 +- 18 files changed, 322 insertions(+), 233 deletions(-) create mode 100644 servers/display_server.compat.inc diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 6089f85bc77..635488a2223 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -143,6 +143,7 @@ + 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]. @@ -166,6 +167,7 @@ + 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]. diff --git a/editor/gui/editor_file_dialog.cpp b/editor/gui/editor_file_dialog.cpp index 03fe1f7f988..4ad3101b9c3 100644 --- a/editor/gui/editor_file_dialog.cpp +++ b/editor/gui/editor_file_dialog.cpp @@ -65,7 +65,15 @@ void EditorFileDialog::_native_popup() { } else if (access == ACCESS_USERDATA) { 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) { diff --git a/misc/extension_api_validation/4.4-stable.expected b/misc/extension_api_validation/4.4-stable.expected index a3ea3f2ed10..51a16f6512e 100644 --- a/misc/extension_api_validation/4.4-stable.expected +++ b/misc/extension_api_validation/4.4-stable.expected @@ -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. ## 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. diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index f8d960f2b70..5db5d85aa6b 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -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 &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 &p_filters, const Callable &p_callback, WindowID p_window_id) { GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java(); ERR_FAIL_NULL_V(godot_java, FAILED); file_picker_callback = p_callback; diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 587d8731a10..8162371f522 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -131,7 +131,7 @@ public: 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); - 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 &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 &p_filters, const Callable &p_callback, WindowID p_window_id) override; void emit_file_picker_callback(bool p_ok, const Vector &p_selected_paths); virtual Color get_accent_color() const override; diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 5334446b224..4fed8e8096a 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -306,7 +306,7 @@ void DisplayServerWayland::set_system_theme_change_callback(const Callable &p_ca 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 &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 &p_filters, const Callable &p_callback, WindowID p_window_id) { WindowID window_id = MAIN_WINDOW_ID; // 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(), 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 &p_filters, const TypedArray &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, WindowID p_window_id) { WindowID window_id = MAIN_WINDOW_ID; // TODO: Use window IDs for multiwindow support. diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h index 4e21aea6a55..632c4f56b91 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.h +++ b/platform/linuxbsd/wayland/display_server_wayland.h @@ -187,8 +187,8 @@ public: virtual bool is_dark_mode() const 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 &p_filters, 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 &p_filters, const TypedArray &p_options, 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 &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, WindowID p_window_id) override; #endif virtual void beep() const override; diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index 56277d85c96..72f2e88ecf4 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -402,26 +402,26 @@ void DisplayServerX11::set_system_theme_change_callback(const Callable &p_callab 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 &p_filters, const Callable &p_callback) { - WindowID window_id = last_focused_window; +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 &p_filters, const Callable &p_callback, WindowID p_window_id) { + 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; } 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(), 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(), 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 &p_filters, const TypedArray &p_options, const Callable &p_callback) { - WindowID window_id = last_focused_window; +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 &p_filters, const TypedArray &p_options, const Callable &p_callback, WindowID p_window_id) { + 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; } 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 diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index b21d9024627..80db727b978 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -422,8 +422,8 @@ public: virtual bool is_dark_mode() const 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 &p_filters, 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 &p_filters, const TypedArray &p_options, 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 &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, WindowID p_window_id) override; #endif virtual void beep() const override; diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index eb536f9894c..3a044c72346 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -236,7 +236,7 @@ private: 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 &p_filters, const TypedArray &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, bool p_options_in_cb, WindowID p_window_id); public: void menu_callback(id p_sender); @@ -303,8 +303,8 @@ public: virtual Error dialog_show(String p_title, String p_description, Vector 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 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 &p_filters, 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 &p_filters, const TypedArray &p_options, 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 &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, WindowID p_window_id) override; virtual void beep() const override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 556c4c966ef..57e1fdef8c5 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -979,21 +979,25 @@ Error DisplayServerMacOS::dialog_show(String p_title, String p_description, Vect 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 &p_filters, const Callable &p_callback) { - return _file_dialog_with_options_show(p_title, p_current_directory, String(), p_filename, p_show_hidden, p_mode, p_filters, TypedArray(), p_callback, false); +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 &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(), 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 &p_filters, const TypedArray &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, true); +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 &p_filters, const TypedArray &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, 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 &p_filters, const TypedArray &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, bool p_options_in_cb, WindowID p_window_id) { _THREAD_SAFE_METHOD_ ERR_FAIL_INDEX_V(int(p_mode), FILE_DIALOG_MODE_SAVE_MAX, FAILED); 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]; if (p_root.length() > 0) { @@ -1015,98 +1019,102 @@ Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title, [panel setNameFieldStringValue:fileurl]; } - [panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] - completionHandler:^(NSInteger ret) { - if (ret == NSModalResponseOK) { - // Save bookmark for folder. - if (OS::get_singleton()->is_sandboxed()) { - NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"]; - bool skip = false; - for (id bookmark in bookmarks) { - NSError *error = nil; - BOOL isStale = NO; - NSURL *exurl = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error]; - if (!error && !isStale && ([[exurl path] compare:[[panel directoryURL] path]] == NSOrderedSame)) { - skip = true; - break; - } - } - if (!skip) { - NSError *error = nil; - NSData *bookmark = [[panel directoryURL] bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&error]; - if (!error) { - NSArray *new_bookmarks = [bookmarks arrayByAddingObject:bookmark]; - [[NSUserDefaults standardUserDefaults] setObject:new_bookmarks forKey:@"sec_bookmarks"]; - } - } - } - // Callback. - Vector files; - String url; - url.parse_utf8([[[panel URL] path] UTF8String]); - files.push_back(url); - if (callback.is_valid()) { - if (p_options_in_cb) { - Variant v_result = true; - Variant v_files = files; - Variant v_index = [panel_delegate getIndex]; - Variant v_opt = [panel_delegate getSelection]; - Variant ret; - Callable::CallError ce; - const Variant *args[4] = { &v_result, &v_files, &v_index, &v_opt }; + void (^completion_handler)(NSInteger ret) = ^(NSInteger ret) { + if (ret == NSModalResponseOK) { + // Save bookmark for folder. + if (OS::get_singleton()->is_sandboxed()) { + NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"]; + bool skip = false; + for (id bookmark in bookmarks) { + NSError *error = nil; + BOOL isStale = NO; + NSURL *exurl = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error]; + if (!error && !isStale && ([[exurl path] compare:[[panel directoryURL] path]] == NSOrderedSame)) { + skip = true; + break; + } + } + if (!skip) { + NSError *error = nil; + NSData *bookmark = [[panel directoryURL] bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&error]; + if (!error) { + NSArray *new_bookmarks = [bookmarks arrayByAddingObject:bookmark]; + [[NSUserDefaults standardUserDefaults] setObject:new_bookmarks forKey:@"sec_bookmarks"]; + } + } + } + // Callback. + Vector files; + String url; + url.parse_utf8([[[panel URL] path] UTF8String]); + files.push_back(url); + if (callback.is_valid()) { + if (p_options_in_cb) { + Variant v_result = true; + Variant v_files = files; + Variant v_index = [panel_delegate getIndex]; + Variant v_opt = [panel_delegate getSelection]; + Variant ret; + Callable::CallError ce; + const Variant *args[4] = { &v_result, &v_files, &v_index, &v_opt }; - callback.callp(args, 4, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 4, ce))); - } - } else { - Variant v_result = true; - Variant v_files = files; - Variant v_index = [panel_delegate getIndex]; - Variant ret; - Callable::CallError ce; - const Variant *args[3] = { &v_result, &v_files, &v_index }; + callback.callp(args, 4, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 4, ce))); + } + } else { + Variant v_result = true; + Variant v_files = files; + Variant v_index = [panel_delegate getIndex]; + Variant ret; + Callable::CallError ce; + const Variant *args[3] = { &v_result, &v_files, &v_index }; - callback.callp(args, 3, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 3, ce))); - } - } - } - } else { - if (callback.is_valid()) { - if (p_options_in_cb) { - Variant v_result = false; - Variant v_files = Vector(); - Variant v_index = [panel_delegate getIndex]; - Variant v_opt = [panel_delegate getSelection]; - Variant ret; - Callable::CallError ce; - const Variant *args[4] = { &v_result, &v_files, &v_index, &v_opt }; + callback.callp(args, 3, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 3, ce))); + } + } + } + } else { + if (callback.is_valid()) { + if (p_options_in_cb) { + Variant v_result = false; + Variant v_files = Vector(); + Variant v_index = [panel_delegate getIndex]; + Variant v_opt = [panel_delegate getSelection]; + Variant ret; + Callable::CallError ce; + const Variant *args[4] = { &v_result, &v_files, &v_index, &v_opt }; - callback.callp(args, 4, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 4, ce))); - } - } else { - Variant v_result = false; - Variant v_files = Vector(); - Variant v_index = [panel_delegate getIndex]; - Variant ret; - Callable::CallError ce; - const Variant *args[3] = { &v_result, &v_files, &v_index }; + callback.callp(args, 4, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 4, ce))); + } + } else { + Variant v_result = false; + Variant v_files = Vector(); + Variant v_index = [panel_delegate getIndex]; + Variant ret; + Callable::CallError ce; + const Variant *args[3] = { &v_result, &v_files, &v_index }; - callback.callp(args, 3, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 3, ce))); - } - } - } - } - if (prev_focus != INVALID_WINDOW_ID) { - callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(prev_focus); - } - }]; + callback.callp(args, 3, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 3, ce))); + } + } + } + } + if (p_window_id != INVALID_WINDOW_ID) { + 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 { NSOpenPanel *panel = [NSOpenPanel openPanel]; @@ -1125,104 +1133,108 @@ Error DisplayServerMacOS::_file_dialog_with_options_show(const String &p_title, } [panel setAllowsMultipleSelection:(p_mode == FILE_DIALOG_MODE_OPEN_FILES)]; - [panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] - completionHandler:^(NSInteger ret) { - if (ret == NSModalResponseOK) { - // Save bookmark for folder. - NSArray *urls = [(NSOpenPanel *)panel URLs]; - if (OS::get_singleton()->is_sandboxed()) { - NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"]; - NSMutableArray *new_bookmarks = [bookmarks mutableCopy]; - for (NSUInteger i = 0; i != [urls count]; ++i) { - bool skip = false; - for (id bookmark in bookmarks) { - NSError *error = nil; - BOOL isStale = NO; - NSURL *exurl = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error]; - if (!error && !isStale && ([[exurl path] compare:[[urls objectAtIndex:i] path]] == NSOrderedSame)) { - skip = true; - break; - } - } - if (!skip) { - NSError *error = nil; - NSData *bookmark = [[urls objectAtIndex:i] bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&error]; - if (!error) { - [new_bookmarks addObject:bookmark]; - } - } - } - [[NSUserDefaults standardUserDefaults] setObject:new_bookmarks forKey:@"sec_bookmarks"]; - } - // Callback. - Vector files; - for (NSUInteger i = 0; i != [urls count]; ++i) { - String url; - url.parse_utf8([[[urls objectAtIndex:i] path] UTF8String]); - files.push_back(url); - } - if (callback.is_valid()) { - if (p_options_in_cb) { - Variant v_result = true; - Variant v_files = files; - Variant v_index = [panel_delegate getIndex]; - Variant v_opt = [panel_delegate getSelection]; - Variant ret; - Callable::CallError ce; - const Variant *args[4] = { &v_result, &v_files, &v_index, &v_opt }; + void (^completion_handler)(NSInteger ret) = ^(NSInteger ret) { + if (ret == NSModalResponseOK) { + // Save bookmark for folder. + NSArray *urls = [(NSOpenPanel *)panel URLs]; + if (OS::get_singleton()->is_sandboxed()) { + NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"]; + NSMutableArray *new_bookmarks = [bookmarks mutableCopy]; + for (NSUInteger i = 0; i != [urls count]; ++i) { + bool skip = false; + for (id bookmark in bookmarks) { + NSError *error = nil; + BOOL isStale = NO; + NSURL *exurl = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error]; + if (!error && !isStale && ([[exurl path] compare:[[urls objectAtIndex:i] path]] == NSOrderedSame)) { + skip = true; + break; + } + } + if (!skip) { + NSError *error = nil; + NSData *bookmark = [[urls objectAtIndex:i] bookmarkDataWithOptions:NSURLBookmarkCreationWithSecurityScope includingResourceValuesForKeys:nil relativeToURL:nil error:&error]; + if (!error) { + [new_bookmarks addObject:bookmark]; + } + } + } + [[NSUserDefaults standardUserDefaults] setObject:new_bookmarks forKey:@"sec_bookmarks"]; + } + // Callback. + Vector files; + for (NSUInteger i = 0; i != [urls count]; ++i) { + String url; + url.parse_utf8([[[urls objectAtIndex:i] path] UTF8String]); + files.push_back(url); + } + if (callback.is_valid()) { + if (p_options_in_cb) { + Variant v_result = true; + Variant v_files = files; + Variant v_index = [panel_delegate getIndex]; + Variant v_opt = [panel_delegate getSelection]; + Variant ret; + Callable::CallError ce; + const Variant *args[4] = { &v_result, &v_files, &v_index, &v_opt }; - callback.callp(args, 4, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 4, ce))); - } - } else { - Variant v_result = true; - Variant v_files = files; - Variant v_index = [panel_delegate getIndex]; - Variant ret; - Callable::CallError ce; - const Variant *args[3] = { &v_result, &v_files, &v_index }; + callback.callp(args, 4, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 4, ce))); + } + } else { + Variant v_result = true; + Variant v_files = files; + Variant v_index = [panel_delegate getIndex]; + Variant ret; + Callable::CallError ce; + const Variant *args[3] = { &v_result, &v_files, &v_index }; - callback.callp(args, 3, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 3, ce))); - } - } - } - } else { - if (callback.is_valid()) { - if (p_options_in_cb) { - Variant v_result = false; - Variant v_files = Vector(); - Variant v_index = [panel_delegate getIndex]; - Variant v_opt = [panel_delegate getSelection]; - Variant ret; - Callable::CallError ce; - const Variant *args[4] = { &v_result, &v_files, &v_index, &v_opt }; + callback.callp(args, 3, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 3, ce))); + } + } + } + } else { + if (callback.is_valid()) { + if (p_options_in_cb) { + Variant v_result = false; + Variant v_files = Vector(); + Variant v_index = [panel_delegate getIndex]; + Variant v_opt = [panel_delegate getSelection]; + Variant ret; + Callable::CallError ce; + const Variant *args[4] = { &v_result, &v_files, &v_index, &v_opt }; - callback.callp(args, 4, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 4, ce))); - } - } else { - Variant v_result = false; - Variant v_files = Vector(); - Variant v_index = [panel_delegate getIndex]; - Variant ret; - Callable::CallError ce; - const Variant *args[3] = { &v_result, &v_files, &v_index }; + callback.callp(args, 4, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 4, ce))); + } + } else { + Variant v_result = false; + Variant v_files = Vector(); + Variant v_index = [panel_delegate getIndex]; + Variant ret; + Callable::CallError ce; + const Variant *args[3] = { &v_result, &v_files, &v_index }; - callback.callp(args, 3, ret, ce); - if (ce.error != Callable::CallError::CALL_OK) { - ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 3, ce))); - } - } - } - } - if (prev_focus != INVALID_WINDOW_ID) { - callable_mp(DisplayServer::get_singleton(), &DisplayServer::window_move_to_foreground).call_deferred(prev_focus); - } - }]; + callback.callp(args, 3, ret, ce); + if (ce.error != Callable::CallError::CALL_OK) { + ERR_PRINT(vformat("Failed to execute file dialog callback: %s.", Variant::get_callable_error_text(callback, args, 3, ce))); + } + } + } + } + if (p_window_id != INVALID_WINDOW_ID) { + 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; diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 20b9236e462..383a402f84c 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -269,12 +269,12 @@ void DisplayServerWindows::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 &p_filters, const Callable &p_callback) { - return _file_dialog_with_options_show(p_title, p_current_directory, String(), p_filename, p_show_hidden, p_mode, p_filters, TypedArray(), p_callback, false); +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 &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(), 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 &p_filters, const TypedArray &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, true); +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 &p_filters, const TypedArray &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, p_window_id); } // 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 &p_filters, const TypedArray &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, bool p_options_in_cb, WindowID p_window_id) { _THREAD_SAFE_METHOD_ 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; if (Engine::get_singleton()->is_editor_hint()) { 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); - if (window_id != INVALID_WINDOW_ID) { - fd->hwnd_owner = windows[window_id].hWnd; + if (windows.has(p_window_id) && !windows[p_window_id].is_popup) { + fd->hwnd_owner = windows[p_window_id].hWnd; RECT crect; GetWindowRect(fd->hwnd_owner, &crect); 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->show_hidden = p_show_hidden; fd->mode = p_mode; - fd->window_id = window_id; + fd->window_id = p_window_id; fd->filters = p_filters; fd->options = p_options; fd->callback = p_callback; diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 4a6b51b5923..92a6fd69bf6 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -673,7 +673,7 @@ class DisplayServerWindows : public DisplayServer { }; BitField _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 &p_filters, const TypedArray &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 &p_filters, const TypedArray &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_klid(HKL p_hkl) const; @@ -713,8 +713,8 @@ public: virtual Color get_base_color() const 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 &p_filters, 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 &p_filters, const TypedArray &p_options, 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 &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, WindowID p_window_id) override; virtual void beep() const override; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index bd89fb19c01..90a221b71b3 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -68,10 +68,18 @@ void FileDialog::_native_popup() { } 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_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 { - 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); } } diff --git a/servers/display_server.compat.inc b/servers/display_server.compat.inc new file mode 100644 index 00000000000..165dad94c14 --- /dev/null +++ b/servers/display_server.compat.inc @@ -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 &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 &p_filters, const TypedArray &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 diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 87300bd8b6a..0bb7b8b7879 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "display_server.h" +#include "display_server.compat.inc" #include "core/input/input.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; } -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 &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 &p_filters, const Callable &p_callback, WindowID p_window_id) { WARN_PRINT("Native dialogs not supported by this display server."); 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 &p_filters, const TypedArray &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, WindowID p_window_id) { WARN_PRINT("Native dialogs not supported by this display server."); 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_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_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_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", "parent_window_id"), &DisplayServer::file_dialog_with_options_show, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("beep"), &DisplayServer::beep); diff --git a/servers/display_server.h b/servers/display_server.h index 80bba6897ff..d833574aba4 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -109,6 +109,10 @@ private: protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + static void _bind_compatibility_methods(); +#endif + static Ref _get_cursor_image_from_resource(const Ref &p_cursor, const Vector2 &p_hotspot); enum { @@ -592,8 +596,13 @@ public: FILE_DIALOG_MODE_SAVE_FILE, 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 &p_filters, 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 &p_filters, const TypedArray &p_options, 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 &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 &p_filters, const TypedArray &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 &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 &p_filters, const TypedArray &p_options, const Callable &p_callback); +#endif virtual void beep() const; diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index 7bd8cbf0752..c1d5b0907e0 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -184,8 +184,8 @@ public: Error dialog_show(String p_title, String p_description, Vector 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 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 &p_filters, 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 &p_filters, const TypedArray &p_options, 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 &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 &p_filters, const TypedArray &p_options, const Callable &p_callback, WindowID p_window_id) override { return ERR_UNAVAILABLE; } void release_rendering_thread() override {} void swap_buffers() override {}