You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-19 14:31:59 +00:00
[macOS] Implement optional native file selection dialog support for sandboxed apps.
This commit is contained in:
@@ -442,6 +442,10 @@ bool OS::has_feature(const String &p_feature) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OS::is_sandboxed() const {
|
||||||
|
return ::OS::get_singleton()->is_sandboxed();
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t OS::get_static_memory_usage() const {
|
uint64_t OS::get_static_memory_usage() const {
|
||||||
return ::OS::get_singleton()->get_static_memory_usage();
|
return ::OS::get_singleton()->get_static_memory_usage();
|
||||||
}
|
}
|
||||||
@@ -545,6 +549,10 @@ Vector<String> OS::get_granted_permissions() const {
|
|||||||
return ::OS::get_singleton()->get_granted_permissions();
|
return ::OS::get_singleton()->get_granted_permissions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS::revoke_granted_permissions() {
|
||||||
|
::OS::get_singleton()->revoke_granted_permissions();
|
||||||
|
}
|
||||||
|
|
||||||
String OS::get_unique_id() const {
|
String OS::get_unique_id() const {
|
||||||
return ::OS::get_singleton()->get_unique_id();
|
return ::OS::get_singleton()->get_unique_id();
|
||||||
}
|
}
|
||||||
@@ -636,10 +644,12 @@ void OS::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("get_main_thread_id"), &OS::get_main_thread_id);
|
ClassDB::bind_method(D_METHOD("get_main_thread_id"), &OS::get_main_thread_id);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &OS::has_feature);
|
ClassDB::bind_method(D_METHOD("has_feature", "tag_name"), &OS::has_feature);
|
||||||
|
ClassDB::bind_method(D_METHOD("is_sandboxed"), &OS::is_sandboxed);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("request_permission", "name"), &OS::request_permission);
|
ClassDB::bind_method(D_METHOD("request_permission", "name"), &OS::request_permission);
|
||||||
ClassDB::bind_method(D_METHOD("request_permissions"), &OS::request_permissions);
|
ClassDB::bind_method(D_METHOD("request_permissions"), &OS::request_permissions);
|
||||||
ClassDB::bind_method(D_METHOD("get_granted_permissions"), &OS::get_granted_permissions);
|
ClassDB::bind_method(D_METHOD("get_granted_permissions"), &OS::get_granted_permissions);
|
||||||
|
ClassDB::bind_method(D_METHOD("revoke_granted_permissions"), &OS::revoke_granted_permissions);
|
||||||
|
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "low_processor_usage_mode"), "set_low_processor_usage_mode", "is_in_low_processor_usage_mode");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec");
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "low_processor_usage_mode_sleep_usec"), "set_low_processor_usage_mode_sleep_usec", "get_low_processor_usage_mode_sleep_usec");
|
||||||
|
|||||||
@@ -234,10 +234,12 @@ public:
|
|||||||
Thread::ID get_main_thread_id() const;
|
Thread::ID get_main_thread_id() const;
|
||||||
|
|
||||||
bool has_feature(const String &p_feature) const;
|
bool has_feature(const String &p_feature) const;
|
||||||
|
bool is_sandboxed() const;
|
||||||
|
|
||||||
bool request_permission(const String &p_name);
|
bool request_permission(const String &p_name);
|
||||||
bool request_permissions();
|
bool request_permissions();
|
||||||
Vector<String> get_granted_permissions() const;
|
Vector<String> get_granted_permissions() const;
|
||||||
|
void revoke_granted_permissions();
|
||||||
|
|
||||||
static OS *get_singleton() { return singleton; }
|
static OS *get_singleton() { return singleton; }
|
||||||
|
|
||||||
|
|||||||
@@ -505,6 +505,10 @@ bool OS::has_feature(const String &p_feature) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OS::is_sandboxed() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void OS::set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments) {
|
void OS::set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments) {
|
||||||
restart_on_exit = p_restart;
|
restart_on_exit = p_restart;
|
||||||
restart_commandline = p_restart_arguments;
|
restart_commandline = p_restart_arguments;
|
||||||
|
|||||||
@@ -295,6 +295,8 @@ public:
|
|||||||
|
|
||||||
bool has_feature(const String &p_feature);
|
bool has_feature(const String &p_feature);
|
||||||
|
|
||||||
|
virtual bool is_sandboxed() const;
|
||||||
|
|
||||||
void set_has_server_feature_callback(HasServerFeatureCallback p_callback);
|
void set_has_server_feature_callback(HasServerFeatureCallback p_callback);
|
||||||
|
|
||||||
void set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments);
|
void set_restart_on_exit(bool p_restart, const List<String> &p_restart_arguments);
|
||||||
@@ -304,6 +306,7 @@ public:
|
|||||||
virtual bool request_permission(const String &p_name) { return true; }
|
virtual bool request_permission(const String &p_name) { return true; }
|
||||||
virtual bool request_permissions() { return true; }
|
virtual bool request_permissions() { return true; }
|
||||||
virtual Vector<String> get_granted_permissions() const { return Vector<String>(); }
|
virtual Vector<String> get_granted_permissions() const { return Vector<String>(); }
|
||||||
|
virtual void revoke_granted_permissions() {}
|
||||||
|
|
||||||
// For recording / measuring benchmark data. Only enabled with tools
|
// For recording / measuring benchmark data. Only enabled with tools
|
||||||
void set_use_benchmark(bool p_use_benchmark);
|
void set_use_benchmark(bool p_use_benchmark);
|
||||||
|
|||||||
@@ -96,6 +96,24 @@
|
|||||||
[b]Note:[/b] This method is implemented only on Windows.
|
[b]Note:[/b] This method is implemented only on Windows.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="file_dialog_show">
|
||||||
|
<return type="int" enum="Error" />
|
||||||
|
<param index="0" name="title" type="String" />
|
||||||
|
<param index="1" name="current_directory" type="String" />
|
||||||
|
<param index="2" name="filename" type="String" />
|
||||||
|
<param index="3" name="show_hidden" type="bool" />
|
||||||
|
<param index="4" name="mode" type="int" enum="DisplayServer.FileDialogMode" />
|
||||||
|
<param index="5" name="filters" type="PackedStringArray" />
|
||||||
|
<param index="6" name="callback" type="Callable" />
|
||||||
|
<description>
|
||||||
|
Displays OS native dialog for selecting files or directories in the file system.
|
||||||
|
Callbacks have the following arguments: [code]bool status, PackedStringArray selected_paths[/code].
|
||||||
|
[b]Note:[/b] This method is implemented if the display server has the [code]FEATURE_NATIVE_DIALOG[/code] feature.
|
||||||
|
[b]Note:[/b] This method is implemented on macOS.
|
||||||
|
[b]Note:[/b] On macOS, native file dialogs have no title.
|
||||||
|
[b]Note:[/b] On macOS, sandboxed apps will save security-scoped bookmarks to retain access to the opened folders across multiple sessions. Use [method OS.get_granted_permissions] to get a list of saved bookmarks.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="force_process_and_drop_events">
|
<method name="force_process_and_drop_events">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<description>
|
<description>
|
||||||
@@ -1729,6 +1747,21 @@
|
|||||||
<constant name="CURSOR_MAX" value="17" enum="CursorShape">
|
<constant name="CURSOR_MAX" value="17" enum="CursorShape">
|
||||||
Represents the size of the [enum CursorShape] enum.
|
Represents the size of the [enum CursorShape] enum.
|
||||||
</constant>
|
</constant>
|
||||||
|
<constant name="FILE_DIALOG_MODE_OPEN_FILE" value="0" enum="FileDialogMode">
|
||||||
|
The native file dialog allows selecting one, and only one file.
|
||||||
|
</constant>
|
||||||
|
<constant name="FILE_DIALOG_MODE_OPEN_FILES" value="1" enum="FileDialogMode">
|
||||||
|
The native file dialog allows selecting multiple files.
|
||||||
|
</constant>
|
||||||
|
<constant name="FILE_DIALOG_MODE_OPEN_DIR" value="2" enum="FileDialogMode">
|
||||||
|
The native file dialog only allows selecting a directory, disallowing the selection of any file.
|
||||||
|
</constant>
|
||||||
|
<constant name="FILE_DIALOG_MODE_OPEN_ANY" value="3" enum="FileDialogMode">
|
||||||
|
The native file dialog allows selecting one file or directory.
|
||||||
|
</constant>
|
||||||
|
<constant name="FILE_DIALOG_MODE_SAVE_FILE" value="4" enum="FileDialogMode">
|
||||||
|
The native file dialog will warn when a file exists.
|
||||||
|
</constant>
|
||||||
<constant name="WINDOW_MODE_WINDOWED" value="0" enum="WindowMode">
|
<constant name="WINDOW_MODE_WINDOWED" value="0" enum="WindowMode">
|
||||||
Windowed mode, i.e. [Window] doesn't occupy the whole screen (unless set to the size of the screen).
|
Windowed mode, i.e. [Window] doesn't occupy the whole screen (unless set to the size of the screen).
|
||||||
</constant>
|
</constant>
|
||||||
|
|||||||
@@ -83,6 +83,10 @@
|
|||||||
If [code]true[/code], the dialog will show hidden files.
|
If [code]true[/code], the dialog will show hidden files.
|
||||||
</member>
|
</member>
|
||||||
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default=""Save a File"" />
|
<member name="title" type="String" setter="set_title" getter="get_title" overrides="Window" default=""Save a File"" />
|
||||||
|
<member name="use_native_dialog" type="bool" setter="set_use_native_dialog" getter="get_use_native_dialog" default="false">
|
||||||
|
If [code]true[/code], [member access] is set to [constant ACCESS_FILESYSTEM], and it is supported by the current [DisplayServer], OS native dialog will be used instead of custom one.
|
||||||
|
[b]Note:[/b] On macOS, sandboxed apps always use native dialogs to access host filesystem.
|
||||||
|
</member>
|
||||||
</members>
|
</members>
|
||||||
<signals>
|
<signals>
|
||||||
<signal name="dir_selected">
|
<signal name="dir_selected">
|
||||||
|
|||||||
@@ -240,8 +240,8 @@
|
|||||||
<method name="get_granted_permissions" qualifiers="const">
|
<method name="get_granted_permissions" qualifiers="const">
|
||||||
<return type="PackedStringArray" />
|
<return type="PackedStringArray" />
|
||||||
<description>
|
<description>
|
||||||
With this function, you can get the list of dangerous permissions that have been granted to the Android application.
|
On Android devices: With this function, you can get the list of dangerous permissions that have been granted.
|
||||||
[b]Note:[/b] This method is implemented only on Android.
|
On macOS (sandboxed applications only): This function returns the list of user selected folders accessible to the application. Use native file dialog to request folder access permission.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_keycode_string" qualifiers="const">
|
<method name="get_keycode_string" qualifiers="const">
|
||||||
@@ -534,6 +534,13 @@
|
|||||||
Returns [code]true[/code] if the project will automatically restart when it exits for any reason, [code]false[/code] otherwise. See also [method set_restart_on_exit] and [method get_restart_on_exit_arguments].
|
Returns [code]true[/code] if the project will automatically restart when it exits for any reason, [code]false[/code] otherwise. See also [method set_restart_on_exit] and [method get_restart_on_exit_arguments].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="is_sandboxed" qualifiers="const">
|
||||||
|
<return type="bool" />
|
||||||
|
<description>
|
||||||
|
Returns [code]true[/code] if application is running in the sandbox.
|
||||||
|
[b]Note:[/b] This method is implemented on macOS.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="is_stdout_verbose" qualifiers="const">
|
<method name="is_stdout_verbose" qualifiers="const">
|
||||||
<return type="bool" />
|
<return type="bool" />
|
||||||
<description>
|
<description>
|
||||||
@@ -602,6 +609,12 @@
|
|||||||
[b]Note:[/b] This method is implemented only on Android.
|
[b]Note:[/b] This method is implemented only on Android.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="revoke_granted_permissions">
|
||||||
|
<return type="void" />
|
||||||
|
<description>
|
||||||
|
On macOS (sandboxed applications only), this function clears list of user selected folders accessible to the application.
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="set_environment" qualifiers="const">
|
<method name="set_environment" qualifiers="const">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<param index="0" name="variable" type="String" />
|
<param index="0" name="variable" type="String" />
|
||||||
|
|||||||
@@ -315,6 +315,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 void mouse_set_mode(MouseMode p_mode) override;
|
virtual void mouse_set_mode(MouseMode p_mode) override;
|
||||||
virtual MouseMode mouse_get_mode() const override;
|
virtual MouseMode mouse_get_mode() const override;
|
||||||
|
|
||||||
|
|||||||
@@ -1847,6 +1847,176 @@ 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) {
|
||||||
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
|
NSString *url = [NSString stringWithUTF8String:p_current_directory.utf8().get_data()];
|
||||||
|
NSMutableArray *allowed_types = [[NSMutableArray alloc] init];
|
||||||
|
bool allow_other = false;
|
||||||
|
for (int i = 0; i < p_filters.size(); i++) {
|
||||||
|
Vector<String> tokens = p_filters[i].split(";");
|
||||||
|
if (tokens.size() > 0) {
|
||||||
|
if (tokens[0].strip_edges() == "*.*") {
|
||||||
|
allow_other = true;
|
||||||
|
} else {
|
||||||
|
[allowed_types addObject:[NSString stringWithUTF8String:tokens[0].replace("*.", "").strip_edges().utf8().get_data()]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Callable callback = p_callback; // Make a copy for async completion handler.
|
||||||
|
switch (p_mode) {
|
||||||
|
case FILE_DIALOG_MODE_SAVE_FILE: {
|
||||||
|
NSSavePanel *panel = [NSSavePanel savePanel];
|
||||||
|
|
||||||
|
[panel setDirectoryURL:[NSURL fileURLWithPath:url]];
|
||||||
|
if ([allowed_types count]) {
|
||||||
|
[panel setAllowedFileTypes:allowed_types];
|
||||||
|
}
|
||||||
|
[panel setAllowsOtherFileTypes:allow_other];
|
||||||
|
[panel setExtensionHidden:YES];
|
||||||
|
[panel setCanSelectHiddenExtension:YES];
|
||||||
|
[panel setCanCreateDirectories:YES];
|
||||||
|
[panel setShowsHiddenFiles:p_show_hidden];
|
||||||
|
if (p_filename != "") {
|
||||||
|
NSString *fileurl = [NSString stringWithUTF8String:p_filename.utf8().get_data()];
|
||||||
|
[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<String> files;
|
||||||
|
String url;
|
||||||
|
url.parse_utf8([[[panel URL] path] UTF8String]);
|
||||||
|
files.push_back(url);
|
||||||
|
if (!callback.is_null()) {
|
||||||
|
Variant v_status = true;
|
||||||
|
Variant v_files = files;
|
||||||
|
Variant *v_args[2] = { &v_status, &v_files };
|
||||||
|
Variant ret;
|
||||||
|
Callable::CallError ce;
|
||||||
|
callback.callp((const Variant **)&v_args, 2, ret, ce);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!callback.is_null()) {
|
||||||
|
Variant v_status = false;
|
||||||
|
Variant v_files = Vector<String>();
|
||||||
|
Variant *v_args[2] = { &v_status, &v_files };
|
||||||
|
Variant ret;
|
||||||
|
Callable::CallError ce;
|
||||||
|
callback.callp((const Variant **)&v_args, 2, ret, ce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
} break;
|
||||||
|
case FILE_DIALOG_MODE_OPEN_ANY:
|
||||||
|
case FILE_DIALOG_MODE_OPEN_FILE:
|
||||||
|
case FILE_DIALOG_MODE_OPEN_FILES:
|
||||||
|
case FILE_DIALOG_MODE_OPEN_DIR: {
|
||||||
|
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||||
|
|
||||||
|
[panel setDirectoryURL:[NSURL fileURLWithPath:url]];
|
||||||
|
if ([allowed_types count]) {
|
||||||
|
[panel setAllowedFileTypes:allowed_types];
|
||||||
|
}
|
||||||
|
[panel setAllowsOtherFileTypes:allow_other];
|
||||||
|
[panel setExtensionHidden:YES];
|
||||||
|
[panel setCanSelectHiddenExtension:YES];
|
||||||
|
[panel setCanCreateDirectories:YES];
|
||||||
|
[panel setCanChooseFiles:(p_mode != FILE_DIALOG_MODE_OPEN_DIR)];
|
||||||
|
[panel setCanChooseDirectories:(p_mode == FILE_DIALOG_MODE_OPEN_DIR || p_mode == FILE_DIALOG_MODE_OPEN_ANY)];
|
||||||
|
[panel setShowsHiddenFiles:p_show_hidden];
|
||||||
|
if (p_filename != "") {
|
||||||
|
NSString *fileurl = [NSString stringWithUTF8String:p_filename.utf8().get_data()];
|
||||||
|
[panel setNameFieldStringValue:fileurl];
|
||||||
|
}
|
||||||
|
[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<String> 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_null()) {
|
||||||
|
Variant v_status = true;
|
||||||
|
Variant v_files = files;
|
||||||
|
Variant *v_args[2] = { &v_status, &v_files };
|
||||||
|
Variant ret;
|
||||||
|
Callable::CallError ce;
|
||||||
|
callback.callp((const Variant **)&v_args, 2, ret, ce);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!callback.is_null()) {
|
||||||
|
Variant v_status = false;
|
||||||
|
Variant v_files = Vector<String>();
|
||||||
|
Variant *v_args[2] = { &v_status, &v_files };
|
||||||
|
Variant ret;
|
||||||
|
Callable::CallError ce;
|
||||||
|
callback.callp((const Variant **)&v_args, 2, ret, ce);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
Error DisplayServerMacOS::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {
|
Error DisplayServerMacOS::dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) {
|
||||||
_THREAD_SAFE_METHOD_
|
_THREAD_SAFE_METHOD_
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,9 @@
|
|||||||
<member name="codesign/entitlements/app_sandbox/files_pictures" type="int" setter="" getter="">
|
<member name="codesign/entitlements/app_sandbox/files_pictures" type="int" setter="" getter="">
|
||||||
Allows read or write access to the user's "Pictures" folder. See [url=https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_assets_pictures_read-write]com.apple.security.files.pictures.read-write[/url].
|
Allows read or write access to the user's "Pictures" folder. See [url=https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_assets_pictures_read-write]com.apple.security.files.pictures.read-write[/url].
|
||||||
</member>
|
</member>
|
||||||
|
<member name="codesign/entitlements/app_sandbox/files_user_selected" type="int" setter="" getter="">
|
||||||
|
Allows read or write access to the locations the user has selected using a native file dialog. See [url=https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_files_user-selected_read-write]com.apple.security.files.user-selected.read-write[/url].
|
||||||
|
</member>
|
||||||
<member name="codesign/entitlements/app_sandbox/helper_executables" type="Array" setter="" getter="">
|
<member name="codesign/entitlements/app_sandbox/helper_executables" type="Array" setter="" getter="">
|
||||||
List of helper executables to embedded to the app bundle. Sandboxed app are limited to execute only these executable. See [url=https://developer.apple.com/documentation/xcode/embedding-a-helper-tool-in-a-sandboxed-app]Embedding a command-line tool in a sandboxed app[/url].
|
List of helper executables to embedded to the app bundle. Sandboxed app are limited to execute only these executable. See [url=https://developer.apple.com/documentation/xcode/embedding-a-helper-tool-in-a-sandboxed-app]Embedding a command-line tool in a sandboxed app[/url].
|
||||||
</member>
|
</member>
|
||||||
|
|||||||
@@ -425,6 +425,7 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options
|
|||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_pictures", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_pictures", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_music", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_music", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
||||||
|
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_user_selected", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::ARRAY, "codesign/entitlements/app_sandbox/helper_executables", PROPERTY_HINT_ARRAY_TYPE, itos(Variant::STRING) + "/" + itos(PROPERTY_HINT_GLOBAL_FILE) + ":"), Array()));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::ARRAY, "codesign/entitlements/app_sandbox/helper_executables", PROPERTY_HINT_ARRAY_TYPE, itos(Variant::STRING) + "/" + itos(PROPERTY_HINT_GLOBAL_FILE) + ":"), Array()));
|
||||||
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
|
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
|
||||||
|
|
||||||
@@ -1922,6 +1923,14 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p
|
|||||||
ent_f->store_line("<key>com.apple.security.files.movies.read-write</key>");
|
ent_f->store_line("<key>com.apple.security.files.movies.read-write</key>");
|
||||||
ent_f->store_line("<true/>");
|
ent_f->store_line("<true/>");
|
||||||
}
|
}
|
||||||
|
if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_user_selected") == 1) {
|
||||||
|
ent_f->store_line("<key>com.apple.security.files.user-selected.read-only</key>");
|
||||||
|
ent_f->store_line("<true/>");
|
||||||
|
}
|
||||||
|
if ((int)p_preset->get("codesign/entitlements/app_sandbox/files_user_selected") == 2) {
|
||||||
|
ent_f->store_line("<key>com.apple.security.files.user-selected.read-write</key>");
|
||||||
|
ent_f->store_line("<true/>");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ent_f->store_line("</dict>");
|
ent_f->store_line("</dict>");
|
||||||
|
|||||||
@@ -113,6 +113,10 @@ public:
|
|||||||
virtual String get_unique_id() const override;
|
virtual String get_unique_id() const override;
|
||||||
virtual String get_processor_name() const override;
|
virtual String get_processor_name() const override;
|
||||||
|
|
||||||
|
virtual bool is_sandboxed() const override;
|
||||||
|
virtual Vector<String> get_granted_permissions() const override;
|
||||||
|
virtual void revoke_granted_permissions() override;
|
||||||
|
|
||||||
virtual bool _check_internal_feature_support(const String &p_feature) override;
|
virtual bool _check_internal_feature_support(const String &p_feature) override;
|
||||||
|
|
||||||
virtual void disable_crash_handler() override;
|
virtual void disable_crash_handler() override;
|
||||||
|
|||||||
@@ -76,6 +76,36 @@ String OS_MacOS::get_processor_name() const {
|
|||||||
ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string."));
|
ERR_FAIL_V_MSG("", String("Couldn't get the CPU model name. Returning an empty string."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OS_MacOS::is_sandboxed() const {
|
||||||
|
return has_environment("APP_SANDBOX_CONTAINER_ID");
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<String> OS_MacOS::get_granted_permissions() const {
|
||||||
|
Vector<String> ret;
|
||||||
|
|
||||||
|
if (is_sandboxed()) {
|
||||||
|
NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"];
|
||||||
|
for (id bookmark in bookmarks) {
|
||||||
|
NSError *error = nil;
|
||||||
|
BOOL isStale = NO;
|
||||||
|
NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error];
|
||||||
|
if (!error && !isStale) {
|
||||||
|
String url_string;
|
||||||
|
url_string.parse_utf8([[url path] UTF8String]);
|
||||||
|
ret.push_back(url_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OS_MacOS::revoke_granted_permissions() {
|
||||||
|
if (is_sandboxed()) {
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"sec_bookmarks"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OS_MacOS::initialize_core() {
|
void OS_MacOS::initialize_core() {
|
||||||
OS_Unix::initialize_core();
|
OS_Unix::initialize_core();
|
||||||
|
|
||||||
@@ -85,6 +115,18 @@ void OS_MacOS::initialize_core() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OS_MacOS::finalize() {
|
void OS_MacOS::finalize() {
|
||||||
|
if (is_sandboxed()) {
|
||||||
|
NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"];
|
||||||
|
for (id bookmark in bookmarks) {
|
||||||
|
NSError *error = nil;
|
||||||
|
BOOL isStale = NO;
|
||||||
|
NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error];
|
||||||
|
if (!error && !isStale) {
|
||||||
|
[url stopAccessingSecurityScopedResource];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef COREMIDI_ENABLED
|
#ifdef COREMIDI_ENABLED
|
||||||
midi_driver.close();
|
midi_driver.close();
|
||||||
#endif
|
#endif
|
||||||
@@ -733,6 +775,23 @@ void OS_MacOS::run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OS_MacOS::OS_MacOS() {
|
OS_MacOS::OS_MacOS() {
|
||||||
|
if (is_sandboxed()) {
|
||||||
|
// Load security-scoped bookmarks, request access, remove stale or invalid bookmarks.
|
||||||
|
NSArray *bookmarks = [[NSUserDefaults standardUserDefaults] arrayForKey:@"sec_bookmarks"];
|
||||||
|
NSMutableArray *new_bookmarks = [[NSMutableArray alloc] init];
|
||||||
|
for (id bookmark in bookmarks) {
|
||||||
|
NSError *error = nil;
|
||||||
|
BOOL isStale = NO;
|
||||||
|
NSURL *url = [NSURL URLByResolvingBookmarkData:bookmark options:NSURLBookmarkResolutionWithSecurityScope relativeToURL:nil bookmarkDataIsStale:&isStale error:&error];
|
||||||
|
if (!error && !isStale) {
|
||||||
|
if ([url startAccessingSecurityScopedResource]) {
|
||||||
|
[new_bookmarks addObject:bookmark];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:new_bookmarks forKey:@"sec_bookmarks"];
|
||||||
|
}
|
||||||
|
|
||||||
main_loop = nullptr;
|
main_loop = nullptr;
|
||||||
|
|
||||||
Vector<Logger *> loggers;
|
Vector<Logger *> loggers;
|
||||||
|
|||||||
@@ -54,6 +54,38 @@ void FileDialog::_focus_file_text() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileDialog::popup(const Rect2i &p_rect) {
|
||||||
|
if (access == ACCESS_FILESYSTEM && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_NATIVE_DIALOG) && (use_native_dialog || OS::get_singleton()->is_sandboxed())) {
|
||||||
|
DisplayServer::get_singleton()->file_dialog_show(get_title(), dir->get_text(), file->get_text().get_file(), show_hidden_files, DisplayServer::FileDialogMode(mode), filters, callable_mp(this, &FileDialog::_native_dialog_cb));
|
||||||
|
} else {
|
||||||
|
ConfirmationDialog::popup(p_rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileDialog::_native_dialog_cb(bool p_ok, const Vector<String> &p_files) {
|
||||||
|
if (p_ok) {
|
||||||
|
if (p_files.size() > 0) {
|
||||||
|
String f = p_files[0];
|
||||||
|
if (mode == FILE_MODE_OPEN_FILES) {
|
||||||
|
emit_signal("files_selected", p_files);
|
||||||
|
} else {
|
||||||
|
if (mode == FILE_MODE_SAVE_FILE) {
|
||||||
|
emit_signal("file_selected", f);
|
||||||
|
} else if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
|
||||||
|
emit_signal("file_selected", f);
|
||||||
|
} else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) {
|
||||||
|
emit_signal("dir_selected", f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file->set_text(f);
|
||||||
|
dir->set_text(f.get_base_dir());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
file->set_text("");
|
||||||
|
emit_signal("cancelled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VBoxContainer *FileDialog::get_vbox() {
|
VBoxContainer *FileDialog::get_vbox() {
|
||||||
return vbox;
|
return vbox;
|
||||||
}
|
}
|
||||||
@@ -980,6 +1012,8 @@ void FileDialog::_bind_methods() {
|
|||||||
ClassDB::bind_method(D_METHOD("get_root_subfolder"), &FileDialog::get_root_subfolder);
|
ClassDB::bind_method(D_METHOD("get_root_subfolder"), &FileDialog::get_root_subfolder);
|
||||||
ClassDB::bind_method(D_METHOD("set_show_hidden_files", "show"), &FileDialog::set_show_hidden_files);
|
ClassDB::bind_method(D_METHOD("set_show_hidden_files", "show"), &FileDialog::set_show_hidden_files);
|
||||||
ClassDB::bind_method(D_METHOD("is_showing_hidden_files"), &FileDialog::is_showing_hidden_files);
|
ClassDB::bind_method(D_METHOD("is_showing_hidden_files"), &FileDialog::is_showing_hidden_files);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_use_native_dialog", "native"), &FileDialog::set_use_native_dialog);
|
||||||
|
ClassDB::bind_method(D_METHOD("get_use_native_dialog"), &FileDialog::get_use_native_dialog);
|
||||||
ClassDB::bind_method(D_METHOD("deselect_all"), &FileDialog::deselect_all);
|
ClassDB::bind_method(D_METHOD("deselect_all"), &FileDialog::deselect_all);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate);
|
ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate);
|
||||||
@@ -990,6 +1024,7 @@ void FileDialog::_bind_methods() {
|
|||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "root_subfolder"), "set_root_subfolder", "get_root_subfolder");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "root_subfolder"), "set_root_subfolder", "get_root_subfolder");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters");
|
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_native_dialog"), "set_use_native_dialog", "get_use_native_dialog");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*", PROPERTY_USAGE_NONE), "set_current_file", "get_current_file");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE, "*", PROPERTY_USAGE_NONE), "set_current_file", "get_current_file");
|
||||||
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_path", "get_current_path");
|
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_path", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_current_path", "get_current_path");
|
||||||
@@ -1025,6 +1060,14 @@ void FileDialog::set_default_show_hidden_files(bool p_show) {
|
|||||||
default_show_hidden_files = p_show;
|
default_show_hidden_files = p_show;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileDialog::set_use_native_dialog(bool p_native) {
|
||||||
|
use_native_dialog = p_native;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileDialog::get_use_native_dialog() const {
|
||||||
|
return use_native_dialog;
|
||||||
|
}
|
||||||
|
|
||||||
FileDialog::FileDialog() {
|
FileDialog::FileDialog() {
|
||||||
show_hidden_files = default_show_hidden_files;
|
show_hidden_files = default_show_hidden_files;
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ private:
|
|||||||
|
|
||||||
static bool default_show_hidden_files;
|
static bool default_show_hidden_files;
|
||||||
bool show_hidden_files = false;
|
bool show_hidden_files = false;
|
||||||
|
bool use_native_dialog = false;
|
||||||
|
|
||||||
bool is_invalidating = false;
|
bool is_invalidating = false;
|
||||||
|
|
||||||
@@ -158,6 +159,8 @@ private:
|
|||||||
|
|
||||||
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
|
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
|
||||||
|
|
||||||
|
void _native_dialog_cb(bool p_ok, const Vector<String> &p_files);
|
||||||
|
|
||||||
bool _is_open_should_be_disabled();
|
bool _is_open_should_be_disabled();
|
||||||
|
|
||||||
virtual void _post_popup() override;
|
virtual void _post_popup() override;
|
||||||
@@ -169,6 +172,8 @@ protected:
|
|||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
//bind helpers
|
//bind helpers
|
||||||
public:
|
public:
|
||||||
|
virtual void popup(const Rect2i &p_rect = Rect2i()) override;
|
||||||
|
|
||||||
void popup_file_dialog();
|
void popup_file_dialog();
|
||||||
void clear_filters();
|
void clear_filters();
|
||||||
void add_filter(const String &p_filter, const String &p_description = "");
|
void add_filter(const String &p_filter, const String &p_description = "");
|
||||||
@@ -191,6 +196,9 @@ public:
|
|||||||
void set_mode_overrides_title(bool p_override);
|
void set_mode_overrides_title(bool p_override);
|
||||||
bool is_mode_overriding_title() const;
|
bool is_mode_overriding_title() const;
|
||||||
|
|
||||||
|
void set_use_native_dialog(bool p_native);
|
||||||
|
bool get_use_native_dialog() const;
|
||||||
|
|
||||||
void set_file_mode(FileMode p_mode);
|
void set_file_mode(FileMode p_mode);
|
||||||
FileMode get_file_mode() const;
|
FileMode get_file_mode() const;
|
||||||
|
|
||||||
|
|||||||
@@ -2308,7 +2308,7 @@ void PopupMenu::_bind_methods() {
|
|||||||
ADD_SIGNAL(MethodInfo("menu_changed"));
|
ADD_SIGNAL(MethodInfo("menu_changed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupMenu::popup(const Rect2 &p_bounds) {
|
void PopupMenu::popup(const Rect2i &p_bounds) {
|
||||||
moved = Vector2();
|
moved = Vector2();
|
||||||
popup_time_msec = OS::get_singleton()->get_ticks_msec();
|
popup_time_msec = OS::get_singleton()->get_ticks_msec();
|
||||||
Popup::popup(p_bounds);
|
Popup::popup(p_bounds);
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ public:
|
|||||||
void set_allow_search(bool p_allow);
|
void set_allow_search(bool p_allow);
|
||||||
bool get_allow_search() const;
|
bool get_allow_search() const;
|
||||||
|
|
||||||
virtual void popup(const Rect2 &p_bounds = Rect2());
|
virtual void popup(const Rect2i &p_bounds = Rect2i()) override;
|
||||||
|
|
||||||
void take_mouse_focus();
|
void take_mouse_focus();
|
||||||
|
|
||||||
|
|||||||
@@ -315,7 +315,7 @@ public:
|
|||||||
Window *get_parent_visible_window() const;
|
Window *get_parent_visible_window() const;
|
||||||
Viewport *get_parent_viewport() const;
|
Viewport *get_parent_viewport() const;
|
||||||
|
|
||||||
void popup(const Rect2i &p_screen_rect = Rect2i());
|
virtual void popup(const Rect2i &p_screen_rect = Rect2i());
|
||||||
void popup_on_parent(const Rect2i &p_parent_rect);
|
void popup_on_parent(const Rect2i &p_parent_rect);
|
||||||
void popup_centered(const Size2i &p_minsize = Size2i());
|
void popup_centered(const Size2i &p_minsize = Size2i());
|
||||||
void popup_centered_ratio(float p_ratio = 0.8);
|
void popup_centered_ratio(float p_ratio = 0.8);
|
||||||
|
|||||||
@@ -497,6 +497,11 @@ Error DisplayServer::dialog_input_text(String p_title, String p_description, Str
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
WARN_PRINT("Native dialogs not supported by this display server.");
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
int DisplayServer::keyboard_get_layout_count() const {
|
int DisplayServer::keyboard_get_layout_count() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -755,6 +760,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("keyboard_get_layout_count"), &DisplayServer::keyboard_get_layout_count);
|
ClassDB::bind_method(D_METHOD("keyboard_get_layout_count"), &DisplayServer::keyboard_get_layout_count);
|
||||||
ClassDB::bind_method(D_METHOD("keyboard_get_current_layout"), &DisplayServer::keyboard_get_current_layout);
|
ClassDB::bind_method(D_METHOD("keyboard_get_current_layout"), &DisplayServer::keyboard_get_current_layout);
|
||||||
ClassDB::bind_method(D_METHOD("keyboard_set_current_layout", "index"), &DisplayServer::keyboard_set_current_layout);
|
ClassDB::bind_method(D_METHOD("keyboard_set_current_layout", "index"), &DisplayServer::keyboard_set_current_layout);
|
||||||
@@ -846,6 +853,12 @@ void DisplayServer::_bind_methods() {
|
|||||||
BIND_ENUM_CONSTANT(CURSOR_HELP);
|
BIND_ENUM_CONSTANT(CURSOR_HELP);
|
||||||
BIND_ENUM_CONSTANT(CURSOR_MAX);
|
BIND_ENUM_CONSTANT(CURSOR_MAX);
|
||||||
|
|
||||||
|
BIND_ENUM_CONSTANT(FILE_DIALOG_MODE_OPEN_FILE);
|
||||||
|
BIND_ENUM_CONSTANT(FILE_DIALOG_MODE_OPEN_FILES);
|
||||||
|
BIND_ENUM_CONSTANT(FILE_DIALOG_MODE_OPEN_DIR);
|
||||||
|
BIND_ENUM_CONSTANT(FILE_DIALOG_MODE_OPEN_ANY);
|
||||||
|
BIND_ENUM_CONSTANT(FILE_DIALOG_MODE_SAVE_FILE);
|
||||||
|
|
||||||
BIND_ENUM_CONSTANT(WINDOW_MODE_WINDOWED);
|
BIND_ENUM_CONSTANT(WINDOW_MODE_WINDOWED);
|
||||||
BIND_ENUM_CONSTANT(WINDOW_MODE_MINIMIZED);
|
BIND_ENUM_CONSTANT(WINDOW_MODE_MINIMIZED);
|
||||||
BIND_ENUM_CONSTANT(WINDOW_MODE_MAXIMIZED);
|
BIND_ENUM_CONSTANT(WINDOW_MODE_MAXIMIZED);
|
||||||
|
|||||||
@@ -493,6 +493,15 @@ public:
|
|||||||
virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback);
|
virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback);
|
||||||
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback);
|
virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback);
|
||||||
|
|
||||||
|
enum FileDialogMode {
|
||||||
|
FILE_DIALOG_MODE_OPEN_FILE,
|
||||||
|
FILE_DIALOG_MODE_OPEN_FILES,
|
||||||
|
FILE_DIALOG_MODE_OPEN_DIR,
|
||||||
|
FILE_DIALOG_MODE_OPEN_ANY,
|
||||||
|
FILE_DIALOG_MODE_SAVE_FILE
|
||||||
|
};
|
||||||
|
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 int keyboard_get_layout_count() const;
|
virtual int keyboard_get_layout_count() const;
|
||||||
virtual int keyboard_get_current_layout() const;
|
virtual int keyboard_get_current_layout() const;
|
||||||
virtual void keyboard_set_current_layout(int p_index);
|
virtual void keyboard_set_current_layout(int p_index);
|
||||||
@@ -546,5 +555,6 @@ VARIANT_ENUM_CAST(DisplayServer::VirtualKeyboardType);
|
|||||||
VARIANT_ENUM_CAST(DisplayServer::CursorShape)
|
VARIANT_ENUM_CAST(DisplayServer::CursorShape)
|
||||||
VARIANT_ENUM_CAST(DisplayServer::VSyncMode)
|
VARIANT_ENUM_CAST(DisplayServer::VSyncMode)
|
||||||
VARIANT_ENUM_CAST(DisplayServer::TTSUtteranceEvent)
|
VARIANT_ENUM_CAST(DisplayServer::TTSUtteranceEvent)
|
||||||
|
VARIANT_ENUM_CAST(DisplayServer::FileDialogMode)
|
||||||
|
|
||||||
#endif // DISPLAY_SERVER_H
|
#endif // DISPLAY_SERVER_H
|
||||||
|
|||||||
Reference in New Issue
Block a user