summaryrefslogtreecommitdiff
path: root/platform/osx
diff options
context:
space:
mode:
Diffstat (limited to 'platform/osx')
-rw-r--r--platform/osx/detect.py57
-rw-r--r--platform/osx/display_server_osx.h2
-rw-r--r--platform/osx/display_server_osx.mm24
-rw-r--r--platform/osx/export/export_plugin.cpp120
-rw-r--r--platform/osx/godot_application.mm5
-rw-r--r--platform/osx/godot_application_delegate.h1
-rw-r--r--platform/osx/godot_application_delegate.mm65
-rw-r--r--platform/osx/godot_content_view.h1
-rw-r--r--platform/osx/godot_content_view.mm9
-rw-r--r--platform/osx/godot_main_osx.mm13
-rw-r--r--platform/osx/key_mapping_osx.mm29
-rw-r--r--platform/osx/os_osx.h6
-rw-r--r--platform/osx/os_osx.mm8
13 files changed, 249 insertions, 91 deletions
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 8d848d2094..47765cff71 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -24,7 +24,7 @@ def get_opts():
return [
("osxcross_sdk", "OSXCross SDK version", "darwin16"),
("MACOS_SDK_PATH", "Path to the macOS SDK", ""),
- ("VULKAN_SDK_PATH", "Path to the Vulkan SDK", ""),
+ ("vulkan_sdk_path", "Path to the Vulkan SDK", ""),
EnumVariable("macports_clang", "Build using Clang from MacPorts", "no", ("no", "5.0", "devel")),
BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True),
BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False),
@@ -36,7 +36,38 @@ def get_opts():
def get_flags():
- return []
+ return [
+ ("use_volk", False),
+ ]
+
+
+def get_mvk_sdk_path():
+ def int_or_zero(i):
+ try:
+ return int(i)
+ except:
+ return 0
+
+ def ver_parse(a):
+ return [int_or_zero(i) for i in a.split(".")]
+
+ dirname = os.path.expanduser("~/VulkanSDK")
+ files = os.listdir(dirname)
+
+ ver_file = "0.0.0.0"
+ ver_num = ver_parse(ver_file)
+
+ for file in files:
+ if os.path.isdir(os.path.join(dirname, file)):
+ ver_comp = ver_parse(file)
+ lib_name = os.path.join(
+ os.path.join(dirname, file), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/libMoltenVK.a"
+ )
+ if os.path.isfile(lib_name) and ver_comp > ver_num:
+ ver_num = ver_comp
+ ver_file = file
+
+ return os.path.join(os.path.join(dirname, ver_file), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/")
def configure(env):
@@ -79,10 +110,12 @@ def configure(env):
if env["arch"] == "arm64":
print("Building for macOS 11.0+, platform arm64.")
+ env.Append(ASFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=11.0"])
else:
print("Building for macOS 10.12+, platform x86_64.")
+ env.Append(ASFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
@@ -197,4 +230,22 @@ def configure(env):
env.Append(CPPDEFINES=["VULKAN_ENABLED"])
env.Append(LINKFLAGS=["-framework", "Metal", "-framework", "QuartzCore", "-framework", "IOSurface"])
if not env["use_volk"]:
- env.Append(LINKFLAGS=["-L$VULKAN_SDK_PATH/MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/", "-lMoltenVK"])
+ env.Append(LINKFLAGS=["-lMoltenVK"])
+ mvk_found = False
+ if env["vulkan_sdk_path"] != "":
+ mvk_path = os.path.join(
+ os.path.expanduser(env["vulkan_sdk_path"]), "MoltenVK/MoltenVK.xcframework/macos-arm64_x86_64/"
+ )
+ if os.path.isfile(os.path.join(mvk_path, "libMoltenVK.a")):
+ mvk_found = True
+ env.Append(LINKFLAGS=["-L" + mvk_path])
+ if not mvk_found:
+ mvk_path = get_mvk_sdk_path()
+ if os.path.isfile(os.path.join(mvk_path, "libMoltenVK.a")):
+ mvk_found = True
+ env.Append(LINKFLAGS=["-L" + mvk_path])
+ if not mvk_found:
+ print(
+ "MoltenVK SDK installation directory not found, use 'vulkan_sdk_path' SCons parameter to specify SDK path."
+ )
+ sys.exit(255)
diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h
index 52b4fab2ea..9575cb29a2 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -208,7 +208,7 @@ public:
void push_to_key_event_buffer(const KeyEvent &p_event);
void update_im_text(const Point2i &p_selection, const String &p_text);
void set_last_focused_window(WindowID p_window);
- void mouse_process_popups(bool p_close = false);
+ bool mouse_process_popups(bool p_close = false);
void popup_open(WindowID p_window);
void popup_close(WindowID p_window);
void set_is_resizing(bool p_is_resizing);
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 536751432b..11474dac46 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -569,9 +569,6 @@ DisplayServerOSX::WindowData &DisplayServerOSX::get_window(WindowID p_window) {
}
void DisplayServerOSX::send_event(NSEvent *p_event) {
- if ([p_event type] == NSEventTypeLeftMouseDown || [p_event type] == NSEventTypeRightMouseDown || [p_event type] == NSEventTypeOtherMouseDown) {
- mouse_process_popups();
- }
// Special case handling of command-period, which is traditionally a special
// shortcut in macOS and doesn't arrive at our regular keyDown handler.
if ([p_event type] == NSEventTypeKeyDown) {
@@ -1181,10 +1178,7 @@ Ref<Texture2D> DisplayServerOSX::global_menu_get_item_icon(const String &p_menu_
GodotMenuItem *obj = [menu_item representedObject];
if (obj) {
if (obj->img.is_valid()) {
- Ref<ImageTexture> txt;
- txt.instantiate();
- txt->create_from_image(obj->img);
- return txt;
+ return ImageTexture::create_from_image(obj->img);
}
}
}
@@ -2014,6 +2008,10 @@ void DisplayServerOSX::window_set_current_screen(int p_screen, WindowID p_window
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
+ if (window_get_current_screen(p_window) == p_screen) {
+ return;
+ }
+
bool was_fullscreen = false;
if (wd.fullscreen) {
// Temporary exit fullscreen mode to move window.
@@ -2923,7 +2921,9 @@ void DisplayServerOSX::make_rendering_thread() {
void DisplayServerOSX::swap_buffers() {
#if defined(GLES3_ENABLED)
- gl_manager->swap_buffers();
+ if (gl_manager) {
+ gl_manager->swap_buffers();
+ }
#endif
}
@@ -3085,15 +3085,17 @@ void DisplayServerOSX::popup_close(WindowID p_window) {
}
}
-void DisplayServerOSX::mouse_process_popups(bool p_close) {
+bool DisplayServerOSX::mouse_process_popups(bool p_close) {
_THREAD_SAFE_METHOD_
bool was_empty = popup_list.is_empty();
+ bool closed = false;
if (p_close) {
// Close all popups.
List<WindowID>::Element *E = popup_list.front();
if (E) {
send_window_event(windows[E->get()], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ closed = true;
}
if (!was_empty) {
// Inform OS that all popups are closed.
@@ -3102,7 +3104,7 @@ void DisplayServerOSX::mouse_process_popups(bool p_close) {
} else {
uint64_t delta = OS::get_singleton()->get_ticks_msec() - time_since_popup;
if (delta < 250) {
- return;
+ return false;
}
Point2i pos = mouse_get_position();
@@ -3125,12 +3127,14 @@ void DisplayServerOSX::mouse_process_popups(bool p_close) {
}
if (C) {
send_window_event(windows[C->get()], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
+ closed = true;
}
if (!was_empty && popup_list.is_empty()) {
// Inform OS that all popups are closed.
[[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"com.apple.HIToolbox.endMenuTrackingNotification" object:@"org.godotengine.godot.popup_window"];
}
}
+ return closed;
}
DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp
index 9309b9f89b..a22d7e5e3d 100644
--- a/platform/osx/export/export_plugin.cpp
+++ b/platform/osx/export/export_plugin.cpp
@@ -252,7 +252,7 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
if (icon_infos[i].is_png) {
// Encode PNG icon.
- it->create_from_image(copy);
+ it->set_image(copy);
String path = EditorPaths::get_singleton()->get_cache_dir().plus_file("icon.png");
ResourceSaver::save(path, it);
@@ -261,7 +261,8 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
if (f.is_null()) {
// Clean up generated file.
DirAccess::remove_file_or_error(path);
- ERR_FAIL();
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Icon Creation"), vformat(TTR("Could not open icon file \"%s\"."), path));
+ return;
}
int ofs = data.size();
@@ -441,18 +442,25 @@ Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset
String str;
Error err = OS::get_singleton()->execute("xcrun", args, &str, nullptr, true);
- ERR_FAIL_COND_V(err != OK, err);
+ if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Could not start xcrun executable."));
+ return err;
+ }
print_verbose("altool (" + p_path + "):\n" + str);
- if (str.find("RequestUUID") == -1) {
- EditorNode::add_io_error("altool: " + str);
+ int rq_offset = str.find("RequestUUID");
+ if (rq_offset == -1) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed."));
return FAILED;
} else {
- print_line(TTR("Note: The notarization process generally takes less than an hour. When the process is completed, you'll receive an email."));
- print_line(" " + TTR("You can check progress manually by opening a Terminal and running the following command:"));
- print_line(" \"xcrun altool --notarization-history 0 -u <your email> -p <app-specific pwd>\"");
- print_line(" " + TTR("Run the following command to staple the notarization ticket to the exported application (optional):"));
- print_line(" \"xcrun stapler staple <app path>\"");
+ int next_nl = str.find("\n", rq_offset);
+ String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14);
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour. When the process is completed, you'll receive an email."));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:"));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun altool --notarization-history 0 -u <your email> -p <app-specific pwd>\"");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("Run the following command to staple the notarization ticket to the exported application (optional):"));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun stapler staple <app path>\"");
}
#endif
@@ -470,21 +478,21 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
#ifdef OSX_ENABLED
if (p_preset->get("codesign/timestamp") && p_warn) {
- WARN_PRINT("Timestamping is not compatible with ad-hoc signature, and was disabled!");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Timestamping is not compatible with ad-hoc signature, and was disabled!"));
}
if (p_preset->get("codesign/hardened_runtime") && p_warn) {
- WARN_PRINT("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!"));
}
#endif
String error_msg;
Error err = CodeSign::codesign(false, p_preset->get("codesign/replace_existing_signature"), p_path, p_ent_path, error_msg);
if (err != OK) {
- EditorNode::add_io_error("Built-in CodeSign: " + error_msg);
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Built-in CodeSign failed with error \"%s\"."), error_msg));
return FAILED;
}
#else
- ERR_FAIL_V_MSG(FAILED, "Built-in CodeSign require regex module");
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Built-in CodeSign require regex module."));
#endif
return OK;
} else {
@@ -493,7 +501,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
if (p_preset->get("codesign/timestamp")) {
if (ad_hoc) {
if (p_warn) {
- WARN_PRINT("Timestamping is not compatible with ad-hoc signature, and was disabled!");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Timestamping is not compatible with ad-hoc signature, and was disabled!"));
}
} else {
args.push_back("--timestamp");
@@ -502,7 +510,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
if (p_preset->get("codesign/hardened_runtime")) {
if (ad_hoc) {
if (p_warn) {
- WARN_PRINT("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!"));
}
} else {
args.push_back("--options");
@@ -540,15 +548,18 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
String str;
Error err = OS::get_singleton()->execute("codesign", args, &str, nullptr, true);
- ERR_FAIL_COND_V(err != OK, err);
+ if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) {
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start codesign executable, make sure Xcode command line tools are installed."));
+ return err;
+ }
print_verbose("codesign (" + p_path + "):\n" + str);
if (str.find("no identity found") != -1) {
- EditorNode::add_io_error("CodeSign: " + TTR("No identity found."));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found."));
return FAILED;
}
if ((str.find("unrecognized blob type") != -1) || (str.find("cannot read entitlement data") != -1)) {
- EditorNode::add_io_error("CodeSign: " + TTR("Invalid entitlements file."));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Invalid entitlements file."));
return FAILED;
}
return OK;
@@ -593,7 +604,7 @@ Error EditorExportPlatformOSX::_code_sign_directory(const Ref<EditorExportPreset
return code_sign_error;
}
} else if (p_should_error_on_non_code) {
- ERR_PRINT(vformat("Cannot sign file %s.", current_file));
+ add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Cannot sign file %s."), current_file));
return Error::FAILED;
}
@@ -611,7 +622,7 @@ Error EditorExportPlatformOSX::_copy_and_sign_files(Ref<DirAccess> &dir_access,
Error err{ OK };
if (dir_access->dir_exists(p_src_path)) {
#ifndef UNIX_ENABLED
- WARN_PRINT("Relative symlinks are not supported, exported " + p_src_path.get_file() + " might be broken!");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Export"), vformat(TTR("Relative symlinks are not supported, exported \"%s\" might be broken!"), p_src_path.get_file()));
#endif
print_verbose("export framework: " + p_src_path + " -> " + p_in_app_path);
err = dir_access->make_dir_recursive(p_in_app_path);
@@ -668,14 +679,17 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin
String str;
Error err = OS::get_singleton()->execute("hdiutil", args, &str, nullptr, true);
- ERR_FAIL_COND_V(err != OK, err);
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("DMG Creation"), TTR("Could not start hdiutil executable."));
+ return err;
+ }
print_verbose("hdiutil returned: " + str);
if (str.find("create failed") != -1) {
if (str.find("File exists") != -1) {
- EditorNode::add_io_error("hdiutil: " + TTR("DMG creation failed, file already exists."));
+ add_message(EXPORT_MESSAGE_ERROR, TTR("DMG Creation"), TTR("`hdiutil create` failed - file exists."));
} else {
- EditorNode::add_io_error("hdiutil: " + TTR("DMG create failed."));
+ add_message(EXPORT_MESSAGE_ERROR, TTR("DMG Creation"), TTR("`hdiutil create` failed."));
}
return FAILED;
}
@@ -685,7 +699,10 @@ Error EditorExportPlatformOSX::_create_dmg(const String &p_dmg_path, const Strin
Error EditorExportPlatformOSX::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
- ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE);
+ if (f.is_null()) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Debug Script Export"), vformat(TTR("Could not open file \"%s\"."), p_path));
+ return ERR_CANT_CREATE;
+ }
f->store_line("#!/bin/sh");
f->store_line("echo -ne '\\033c\\033]0;" + p_app_name + "\\a'");
@@ -713,12 +730,13 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
String err;
src_pkg_name = find_export_template("osx.zip", &err);
if (src_pkg_name.is_empty()) {
- EditorNode::add_io_error(err);
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("Export template not found."));
return ERR_FILE_NOT_FOUND;
}
}
if (!DirAccess::exists(p_path.get_base_dir())) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), TTR("The given export path doesn't exist."));
return ERR_FILE_BAD_PATH;
}
@@ -731,7 +749,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
if (!src_pkg_zip) {
- EditorNode::add_io_error(TTR("Could not find template app to export:") + "\n" + src_pkg_name);
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Could not find template app to export: \"%s\"."), src_pkg_name));
return ERR_FILE_NOT_FOUND;
}
@@ -756,7 +774,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
} else if (p_path.ends_with("app")) {
export_format = "app";
} else {
- EditorNode::add_io_error("Invalid export format");
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Invalid export format."));
return ERR_CANT_CREATE;
}
@@ -781,13 +799,16 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
Ref<DirAccess> tmp_app_dir = DirAccess::create_for_path(tmp_base_path_name);
if (tmp_app_dir.is_null()) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create directory: \"%s\"."), tmp_base_path_name));
err = ERR_CANT_CREATE;
}
DirAccess::remove_file_or_error(scr_path);
if (DirAccess::exists(tmp_app_path_name)) {
+ String old_dir = tmp_app_dir->get_current_dir();
if (tmp_app_dir->change_dir(tmp_app_path_name) == OK) {
tmp_app_dir->erase_contents_recursive();
+ tmp_app_dir->change_dir(old_dir);
}
}
@@ -797,21 +818,33 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (err == OK) {
print_verbose("Creating " + tmp_app_path_name + "/Contents/MacOS");
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS");
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create directory \"%s\"."), tmp_app_path_name + "/Contents/MacOS"));
+ }
}
if (err == OK) {
print_verbose("Creating " + tmp_app_path_name + "/Contents/Frameworks");
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks");
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create directory \"%s\"."), tmp_app_path_name + "/Contents/Frameworks"));
+ }
}
if ((err == OK) && helpers.size() > 0) {
print_line("Creating " + tmp_app_path_name + "/Contents/Helpers");
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Helpers");
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create directory \"%s\"."), tmp_app_path_name + "/Contents/Helpers"));
+ }
}
if (err == OK) {
print_verbose("Creating " + tmp_app_path_name + "/Contents/Resources");
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create directory \"%s\"."), tmp_app_path_name + "/Contents/Resources"));
+ }
}
Dictionary appnames = ProjectSettings::get_singleton()->get("application/config/name_localized");
@@ -955,16 +988,22 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (((info.external_fa >> 16L) & 0120000) == 0120000) {
#ifndef UNIX_ENABLED
- WARN_PRINT(vformat("Relative symlinks are not supported on this OS, the exported project might be broken!"));
+ add_message(EXPORT_MESSAGE_INFO, TTR("Export"), TTR("Relative symlinks are not supported on this OS, the exported project might be broken!"));
#endif
// Handle symlinks in the archive.
file = tmp_app_path_name.plus_file(file);
if (err == OK) {
err = tmp_app_dir->make_dir_recursive(file.get_base_dir());
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create directory \"%s\"."), file.get_base_dir()));
+ }
}
if (err == OK) {
String lnk_data = String::utf8((const char *)data.ptr(), data.size());
err = tmp_app_dir->create_link(lnk_data, file);
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not created symlink \"%s\" -> \"%s\"."), lnk_data, file));
+ }
print_verbose(vformat("ADDING SYMLINK %s => %s\n", file, lnk_data));
}
@@ -1039,16 +1078,21 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
file = tmp_app_path_name.plus_file(file);
if (err == OK) {
err = tmp_app_dir->make_dir_recursive(file.get_base_dir());
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not create directory \"%s\"."), file.get_base_dir()));
+ }
}
if (err == OK) {
Ref<FileAccess> f = FileAccess::open(file, FileAccess::WRITE);
if (f.is_valid()) {
f->store_buffer(data.ptr(), data.size());
+ f.unref();
if (is_execute) {
// chmod with 0755 if the file is executable.
FileAccess::set_unix_permissions(file, 0755);
}
} else {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Could not open \"%s\"."), file));
err = ERR_CANT_CREATE;
}
}
@@ -1061,7 +1105,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
unzClose(src_pkg_zip);
if (!found_binary) {
- ERR_PRINT(vformat("Requested template binary '%s' not found. It might be missing from your template archive.", binary_to_use));
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), vformat(TTR("Requested template binary \"%s\" not found. It might be missing from your template archive."), binary_to_use));
err = ERR_FILE_NOT_FOUND;
}
@@ -1071,6 +1115,9 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if ((con_scr == 1 && p_debug) || (con_scr == 2)) {
err = _export_debug_script(p_preset, pkg_name, tmp_app_path_name.get_file() + "/Contents/MacOS/" + pkg_name, scr_path);
FileAccess::set_unix_permissions(scr_path, 0755);
+ if (err != OK) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Could not create console script."));
+ }
}
}
@@ -1214,6 +1261,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
ent_f->store_line("</dict>");
ent_f->store_line("</plist>");
} else {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Could not create entitlements file."));
err = ERR_CANT_CREATE;
}
@@ -1231,6 +1279,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
ent_f->store_line("</dict>");
ent_f->store_line("</plist>");
} else {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Could not create helper entitlements file."));
err = ERR_CANT_CREATE;
}
}
@@ -1258,7 +1307,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
ad_hoc = (sign_identity == "" || sign_identity == "-");
bool lib_validation = p_preset->get("codesign/entitlements/disable_library_validation");
if ((!dylibs_found.is_empty() || !shared_objects.is_empty()) && sign_enabled && ad_hoc && !lib_validation) {
- ERR_PRINT("Ad-hoc signed applications require the 'Disable Library Validation' entitlement to load dynamic libraries.");
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Ad-hoc signed applications require the 'Disable Library Validation' entitlement to load dynamic libraries."));
err = ERR_CANT_CREATE;
}
}
@@ -1342,7 +1391,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
bool noto_enabled = p_preset->get("notarization/enable");
if (err == OK && noto_enabled) {
if (export_format == "app") {
- WARN_PRINT("Notarization requires the app to be archived first, select the DMG or ZIP export format instead.");
+ add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("Notarization requires the app to be archived first, select the DMG or ZIP export format instead."));
} else {
if (ep.step(TTR("Sending archive for notarization"), 4)) {
return ERR_SKIP;
@@ -1467,7 +1516,8 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
Ref<FileAccess> fa = FileAccess::open(dir.plus_file(f), FileAccess::READ);
if (fa.is_null()) {
- ERR_FAIL_MSG(vformat("Can't open file to read from path \"%s\".", dir.plus_file(f)));
+ add_message(EXPORT_MESSAGE_ERROR, TTR("ZIP Creation"), vformat(TTR("Could not open file to read from path \"%s\"."), dir.plus_file(f)));
+ return;
}
const int bufsize = 16384;
uint8_t buf[bufsize];
@@ -1616,9 +1666,7 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset
}
EditorExportPlatformOSX::EditorExportPlatformOSX() {
- Ref<Image> img = memnew(Image(_osx_logo));
- logo.instantiate();
- logo->create_from_image(img);
+ logo = ImageTexture::create_from_image(memnew(Image(_osx_logo)));
}
EditorExportPlatformOSX::~EditorExportPlatformOSX() {
diff --git a/platform/osx/godot_application.mm b/platform/osx/godot_application.mm
index 00a58700e8..13313a025a 100644
--- a/platform/osx/godot_application.mm
+++ b/platform/osx/godot_application.mm
@@ -37,6 +37,11 @@
- (void)sendEvent:(NSEvent *)event {
DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
if (ds) {
+ if ([event type] == NSEventTypeLeftMouseDown || [event type] == NSEventTypeRightMouseDown || [event type] == NSEventTypeOtherMouseDown) {
+ if (ds->mouse_process_popups()) {
+ return;
+ }
+ }
ds->send_event(event);
}
diff --git a/platform/osx/godot_application_delegate.h b/platform/osx/godot_application_delegate.h
index 8eec762d8f..f5b67b580f 100644
--- a/platform/osx/godot_application_delegate.h
+++ b/platform/osx/godot_application_delegate.h
@@ -40,6 +40,7 @@
- (void)forceUnbundledWindowActivationHackStep1;
- (void)forceUnbundledWindowActivationHackStep2;
- (void)forceUnbundledWindowActivationHackStep3;
+- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
@end
#endif // GODOT_APPLICATION_DELEGATE_H
diff --git a/platform/osx/godot_application_delegate.mm b/platform/osx/godot_application_delegate.mm
index dc82075c44..4d3558b273 100644
--- a/platform/osx/godot_application_delegate.mm
+++ b/platform/osx/godot_application_delegate.mm
@@ -67,6 +67,52 @@
}
}
+- (id)init {
+ self = [super init];
+
+ NSAppleEventManager *aem = [NSAppleEventManager sharedAppleEventManager];
+ [aem setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
+ [aem setEventHandler:self andSelector:@selector(handleAppleEvent:withReplyEvent:) forEventClass:kCoreEventClass andEventID:kAEOpenDocuments];
+
+ return self;
+}
+
+- (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent {
+ OS_OSX *os = (OS_OSX *)OS::get_singleton();
+ if (!event || !os) {
+ return;
+ }
+
+ List<String> args;
+ if (([event eventClass] == kInternetEventClass) && ([event eventID] == kAEGetURL)) {
+ // Opening URL scheme.
+ NSString *url = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
+ args.push_back(vformat("--uri=\"%s\"", String::utf8([url UTF8String])));
+ }
+
+ if (([event eventClass] == kCoreEventClass) && ([event eventID] == kAEOpenDocuments)) {
+ // Opening file association.
+ NSAppleEventDescriptor *files = [event paramDescriptorForKeyword:keyDirectObject];
+ if (files) {
+ NSInteger count = [files numberOfItems];
+ for (NSInteger i = 1; i <= count; i++) {
+ NSURL *url = [NSURL URLWithString:[[files descriptorAtIndex:i] stringValue]];
+ args.push_back(String::utf8([url.path UTF8String]));
+ }
+ }
+ }
+
+ if (!args.is_empty()) {
+ if (os->get_main_loop()) {
+ // Application is already running, open a new instance with the URL/files as command line arguments.
+ os->create_instance(args);
+ } else {
+ // Application is just started, add to the list of command line arguments and continue.
+ os->set_cmdline_platform_args(args);
+ }
+ }
+}
+
- (void)applicationDidResignActive:(NSNotification *)notification {
DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
if (ds) {
@@ -99,25 +145,6 @@
}
}
-- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
- // Note: may be called called before main loop init!
- OS_OSX *os = (OS_OSX *)OS::get_singleton();
- if (os) {
- os->set_open_with_filename(String::utf8([filename UTF8String]));
- }
-
-#ifdef TOOLS_ENABLED
- // Open new instance.
- if (os && os->get_main_loop()) {
- List<String> args;
- args.push_back(os->get_open_with_filename());
- String exec = os->get_executable_path();
- os->create_process(exec, args);
- }
-#endif
- return YES;
-}
-
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
DisplayServerOSX *ds = (DisplayServerOSX *)DisplayServer::get_singleton();
if (ds) {
diff --git a/platform/osx/godot_content_view.h b/platform/osx/godot_content_view.h
index 7942d716dc..353305aec1 100644
--- a/platform/osx/godot_content_view.h
+++ b/platform/osx/godot_content_view.h
@@ -52,6 +52,7 @@
bool ime_input_event_in_progress;
bool mouse_down_control;
bool ignore_momentum_scroll;
+ bool last_pen_inverted;
}
- (void)processScrollEvent:(NSEvent *)event button:(MouseButton)button factor:(double)factor;
diff --git a/platform/osx/godot_content_view.mm b/platform/osx/godot_content_view.mm
index e96f0a8098..018b90e629 100644
--- a/platform/osx/godot_content_view.mm
+++ b/platform/osx/godot_content_view.mm
@@ -42,6 +42,7 @@
ime_input_event_in_progress = false;
mouse_down_control = false;
ignore_momentum_scroll = false;
+ last_pen_inverted = false;
[self updateTrackingAreas];
if (@available(macOS 10.13, *)) {
@@ -377,9 +378,15 @@
ds->update_mouse_pos(wd, mpos);
mm->set_position(wd.mouse_pos);
mm->set_pressure([event pressure]);
- if ([event subtype] == NSEventSubtypeTabletPoint) {
+ NSEventSubtype subtype = [event subtype];
+ if (subtype == NSEventSubtypeTabletPoint) {
const NSPoint p = [event tilt];
mm->set_tilt(Vector2(p.x, p.y));
+ mm->set_pen_inverted(last_pen_inverted);
+ } else if (subtype == NSEventSubtypeTabletProximity) {
+ // Check if using the eraser end of pen only on proximity event.
+ last_pen_inverted = [event pointingDeviceType] == NSPointingDeviceTypeEraser;
+ mm->set_pen_inverted(last_pen_inverted);
}
mm->set_global_position(wd.mouse_pos);
mm->set_velocity(Input::get_singleton()->get_last_mouse_velocity());
diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm
index 053a7f4a1d..722928ad60 100644
--- a/platform/osx/godot_main_osx.mm
+++ b/platform/osx/godot_main_osx.mm
@@ -74,16 +74,11 @@ int main(int argc, char **argv) {
// We must override main when testing is enabled.
TEST_MAIN_OVERRIDE
- if (os.get_open_with_filename() != "") {
- char *argv_c = (char *)malloc(os.get_open_with_filename().utf8().size());
- memcpy(argv_c, os.get_open_with_filename().utf8().get_data(), os.get_open_with_filename().utf8().size());
- err = Main::setup(argv[0], 1, &argv_c);
- free(argv_c);
- } else {
- err = Main::setup(argv[0], argc - first_arg, &argv[first_arg]);
- }
+ err = Main::setup(argv[0], argc - first_arg, &argv[first_arg]);
- if (err != OK) {
+ if (err == ERR_HELP) { // Returned by --help and --version, so success.
+ return 0;
+ } else if (err != OK) {
return 255;
}
diff --git a/platform/osx/key_mapping_osx.mm b/platform/osx/key_mapping_osx.mm
index bfec45de58..0bf6bc7d1c 100644
--- a/platform/osx/key_mapping_osx.mm
+++ b/platform/osx/key_mapping_osx.mm
@@ -130,7 +130,7 @@ static const Key _osx_to_godot_table[128] = {
/* 3d */ Key::ALT,
/* 3e */ Key::CTRL,
/* 3f */ Key::UNKNOWN, /* Function */
- /* 40 */ Key::UNKNOWN, /* F17 */
+ /* 40 */ Key::F17,
/* 41 */ Key::KP_PERIOD,
/* 42 */ Key::UNKNOWN,
/* 43 */ Key::KP_MULTIPLY,
@@ -145,8 +145,8 @@ static const Key _osx_to_godot_table[128] = {
/* 4c */ Key::KP_ENTER,
/* 4d */ Key::UNKNOWN,
/* 4e */ Key::KP_SUBTRACT,
- /* 4f */ Key::UNKNOWN, /* F18 */
- /* 50 */ Key::UNKNOWN, /* F19 */
+ /* 4f */ Key::F18,
+ /* 50 */ Key::F19,
/* 51 */ Key::EQUAL, /* KeypadEqual */
/* 52 */ Key::KP_0,
/* 53 */ Key::KP_1,
@@ -156,7 +156,7 @@ static const Key _osx_to_godot_table[128] = {
/* 57 */ Key::KP_5,
/* 58 */ Key::KP_6,
/* 59 */ Key::KP_7,
- /* 5a */ Key::UNKNOWN, /* F20 */
+ /* 5a */ Key::F20,
/* 5b */ Key::KP_8,
/* 5c */ Key::KP_9,
/* 5d */ Key::YEN, /* JIS Yen */
@@ -366,7 +366,26 @@ static const _KeyCodeText _native_keycodes[] = {
{Key::F13 ,NSF13FunctionKey},
{Key::F14 ,NSF14FunctionKey},
{Key::F15 ,NSF15FunctionKey},
- {Key::F16 ,NSF16FunctionKey}, //* ... NSF35FunctionKey */
+ {Key::F16 ,NSF16FunctionKey},
+ {Key::F17 ,NSF17FunctionKey},
+ {Key::F18 ,NSF18FunctionKey},
+ {Key::F19 ,NSF19FunctionKey},
+ {Key::F20 ,NSF20FunctionKey},
+ {Key::F21 ,NSF21FunctionKey},
+ {Key::F22 ,NSF22FunctionKey},
+ {Key::F23 ,NSF23FunctionKey},
+ {Key::F24 ,NSF24FunctionKey},
+ {Key::F25 ,NSF25FunctionKey},
+ {Key::F26 ,NSF26FunctionKey},
+ {Key::F27 ,NSF27FunctionKey},
+ {Key::F28 ,NSF28FunctionKey},
+ {Key::F29 ,NSF29FunctionKey},
+ {Key::F30 ,NSF30FunctionKey},
+ {Key::F31 ,NSF31FunctionKey},
+ {Key::F32 ,NSF32FunctionKey},
+ {Key::F33 ,NSF33FunctionKey},
+ {Key::F34 ,NSF34FunctionKey},
+ {Key::F35 ,NSF35FunctionKey},
{Key::MENU ,NSMenuFunctionKey},
{Key::HELP ,NSHelpFunctionKey},
{Key::STOP ,NSStopFunctionKey},
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index e4ec411c96..b105be4a06 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -57,7 +57,7 @@ class OS_OSX : public OS_Unix {
MainLoop *main_loop = nullptr;
- String open_with_filename;
+ List<String> launch_service_args;
static _FORCE_INLINE_ String get_framework_executable(const String &p_path);
static void pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context);
@@ -73,8 +73,8 @@ protected:
virtual void delete_main_loop() override;
public:
- String get_open_with_filename() const;
- void set_open_with_filename(const String &p_path);
+ virtual void set_cmdline_platform_args(const List<String> &p_args);
+ virtual List<String> get_cmdline_platform_args() const override;
virtual String get_name() const override;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index a8fa56e34b..5230ed4155 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -121,12 +121,12 @@ void OS_OSX::delete_main_loop() {
main_loop = nullptr;
}
-String OS_OSX::get_open_with_filename() const {
- return open_with_filename;
+void OS_OSX::set_cmdline_platform_args(const List<String> &p_args) {
+ launch_service_args = p_args;
}
-void OS_OSX::set_open_with_filename(const String &p_path) {
- open_with_filename = p_path;
+List<String> OS_OSX::get_cmdline_platform_args() const {
+ return launch_service_args;
}
String OS_OSX::get_name() const {