summaryrefslogtreecommitdiff
path: root/platform/osx
diff options
context:
space:
mode:
Diffstat (limited to 'platform/osx')
-rw-r--r--platform/osx/detect.py14
-rw-r--r--platform/osx/export/export.cpp182
-rw-r--r--platform/osx/os_osx.h11
-rw-r--r--platform/osx/os_osx.mm96
4 files changed, 239 insertions, 64 deletions
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 8a0883eca3..6eee8f204f 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -1,5 +1,6 @@
import os
import sys
+from methods import detect_darwin_sdk_path
def is_active():
@@ -23,6 +24,7 @@ def get_opts():
return [
('osxcross_sdk', 'OSXCross SDK version', 'darwin14'),
+ ('MACOS_SDK_PATH', 'Path to the macOS SDK', ''),
EnumVariable('debug_symbols', 'Add debugging symbols to release builds', 'yes', ('yes', 'no', 'full')),
BoolVariable('separate_debug_symbols', 'Create a separate file containing debugging symbols', False),
]
@@ -70,7 +72,11 @@ def configure(env):
## Compiler configuration
- if "OSXCROSS_ROOT" not in os.environ: # regular native build
+ # Save this in environment for use by other modules
+ if "OSXCROSS_ROOT" in os.environ:
+ env["osxcross"] = True
+
+ if not "osxcross" in env: # regular native build
env.Append(CCFLAGS=['-arch', 'x86_64'])
env.Append(LINKFLAGS=['-arch', 'x86_64'])
if (env["macports_clang"] != 'no'):
@@ -84,12 +90,16 @@ def configure(env):
env['AS'] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-as"
env.Append(CCFLAGS=['-D__MACPORTS__']) #hack to fix libvpx MM256_BROADCASTSI128_SI256 define
+ detect_darwin_sdk_path('osx', env)
+ env.Append(CPPFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
+ env.Append(LINKFLAGS=['-isysroot', '$MACOS_SDK_PATH'])
+
else: # osxcross build
root = os.environ.get("OSXCROSS_ROOT", 0)
basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
ccache_path = os.environ.get("CCACHE")
- if ccache_path == None:
+ if ccache_path is None:
env['CC'] = basecmd + "cc"
env['CXX'] = basecmd + "c++"
else:
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index 27b4fdc228..12a0193521 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -74,7 +74,14 @@ public:
virtual String get_os_name() const { return "OSX"; }
virtual Ref<Texture> get_logo() const { return logo; }
- virtual String get_binary_extension(const Ref<EditorExportPreset> &p_preset) const { return use_dmg() ? "dmg" : "zip"; }
+ virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const {
+ List<String> list;
+ if (use_dmg()) {
+ list.push_back("dmg");
+ }
+ list.push_back("zip");
+ return list;
+ }
virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0);
virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const;
@@ -132,10 +139,76 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc2"), false));
}
+void _rgba8_to_packbits_encode(int p_ch, int p_size, PoolVector<uint8_t> &p_source, Vector<uint8_t> &p_dest) {
+
+ int src_len = p_size * p_size;
+
+ Vector<uint8_t> result;
+ result.resize(src_len * 1.25); //temp vector for rle encoded data, make it 25% larger for worst case scenario
+ int res_size = 0;
+
+ uint8_t buf[128];
+ int buf_size = 0;
+
+ int i = 0;
+ while (i < src_len) {
+ uint8_t cur = p_source.read()[i * 4 + p_ch];
+
+ if (i < src_len - 2) {
+
+ if ((p_source.read()[(i + 1) * 4 + p_ch] == cur) && (p_source.read()[(i + 2) * 4 + p_ch] == cur)) {
+ if (buf_size > 0) {
+ result.write[res_size++] = (uint8_t)(buf_size - 1);
+ copymem(&result.write[res_size], &buf, buf_size);
+ res_size += buf_size;
+ buf_size = 0;
+ }
+
+ uint8_t lim = i + 130 >= src_len ? src_len - i - 1 : 130;
+ bool hit_lim = true;
+
+ for (int j = 3; j <= lim; j++) {
+ if (p_source.read()[(i + j) * 4 + p_ch] != cur) {
+ hit_lim = false;
+ i = i + j - 1;
+ result.write[res_size++] = (uint8_t)(j - 3 + 0x80);
+ result.write[res_size++] = cur;
+ break;
+ }
+ }
+ if (hit_lim) {
+ result.write[res_size++] = (uint8_t)(lim - 3 + 0x80);
+ result.write[res_size++] = cur;
+ i = i + lim;
+ }
+ } else {
+ buf[buf_size++] = cur;
+ if (buf_size == 128) {
+ result.write[res_size++] = (uint8_t)(buf_size - 1);
+ copymem(&result.write[res_size], &buf, buf_size);
+ res_size += buf_size;
+ buf_size = 0;
+ }
+ }
+ } else {
+ buf[buf_size++] = cur;
+ result.write[res_size++] = (uint8_t)(buf_size - 1);
+ copymem(&result.write[res_size], &buf, buf_size);
+ res_size += buf_size;
+ buf_size = 0;
+ }
+
+ i++;
+ }
+
+ int ofs = p_dest.size();
+ p_dest.resize(p_dest.size() + res_size);
+ copymem(&p_dest.write[ofs], result.ptr(), res_size);
+}
+
void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
Ref<ImageTexture> it = memnew(ImageTexture);
- int size = 512;
Vector<uint8_t> data;
@@ -145,32 +218,82 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
data.write[2] = 'n';
data.write[3] = 's';
- const char *name[] = { "ic09", "ic08", "ic07", "icp6", "icp5", "icp4" };
- int index = 0;
-
- while (size >= 16) {
-
+ struct MacOSIconInfo {
+ const char *name;
+ const char *mask_name;
+ bool is_png;
+ int size;
+ };
+
+ static const MacOSIconInfo icon_infos[] = {
+ { "ic10", "", true, 1024 }, //1024x1024 32-bit PNG and 512x512@2x 32-bit "retina" PNG
+ { "ic09", "", true, 512 }, //512×512 32-bit PNG
+ { "ic14", "", true, 512 }, //256x256@2x 32-bit "retina" PNG
+ { "ic08", "", true, 256 }, //256×256 32-bit PNG
+ { "ic13", "", true, 256 }, //128x128@2x 32-bit "retina" PNG
+ { "ic07", "", true, 128 }, //128x128 32-bit PNG
+ { "ic12", "", true, 64 }, //32x32@2x 32-bit "retina" PNG
+ { "ic11", "", true, 32 }, //16x16@2x 32-bit "retina" PNG
+ { "il32", "l8mk", false, 32 }, //32x32 24-bit RLE + 8-bit uncompressed mask
+ { "is32", "s8mk", false, 16 } //16x16 24-bit RLE + 8-bit uncompressed mask
+ };
+
+ for (unsigned int i = 0; i < (sizeof(icon_infos) / sizeof(icon_infos[0])); ++i) {
Ref<Image> copy = p_icon; // does this make sense? doesn't this just increase the reference count instead of making a copy? Do we even need a copy?
copy->convert(Image::FORMAT_RGBA8);
- copy->resize(size, size);
- it->create_from_image(copy);
- String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("icon.png");
- ResourceSaver::save(path, it);
-
- FileAccess *f = FileAccess::open(path, FileAccess::READ);
- ERR_FAIL_COND(!f);
-
- int ofs = data.size();
- uint32_t len = f->get_len();
- data.resize(data.size() + len + 8);
- f->get_buffer(&data.write[ofs + 8], len);
- memdelete(f);
- len += 8;
- len = BSWAP32(len);
- copymem(&data.write[ofs], name[index], 4);
- encode_uint32(len, &data.write[ofs + 4]);
- index++;
- size /= 2;
+ copy->resize(icon_infos[i].size, icon_infos[i].size);
+
+ if (icon_infos[i].is_png) {
+ //encode png icon
+ it->create_from_image(copy);
+ String path = EditorSettings::get_singleton()->get_cache_dir().plus_file("icon.png");
+ ResourceSaver::save(path, it);
+
+ FileAccess *f = FileAccess::open(path, FileAccess::READ);
+ ERR_FAIL_COND(!f);
+
+ int ofs = data.size();
+ uint32_t len = f->get_len();
+ data.resize(data.size() + len + 8);
+ f->get_buffer(&data.write[ofs + 8], len);
+ memdelete(f);
+ len += 8;
+ len = BSWAP32(len);
+ copymem(&data.write[ofs], icon_infos[i].name, 4);
+ encode_uint32(len, &data.write[ofs + 4]);
+ } else {
+ PoolVector<uint8_t> src_data = copy->get_data();
+
+ //encode 24bit RGB RLE icon
+ {
+ int ofs = data.size();
+ data.resize(data.size() + 8);
+
+ _rgba8_to_packbits_encode(0, icon_infos[i].size, src_data, data); // encode R
+ _rgba8_to_packbits_encode(1, icon_infos[i].size, src_data, data); // encode G
+ _rgba8_to_packbits_encode(2, icon_infos[i].size, src_data, data); // encode B
+
+ int len = data.size() - ofs;
+ len = BSWAP32(len);
+ copymem(&data.write[ofs], icon_infos[i].name, 4);
+ encode_uint32(len, &data.write[ofs + 4]);
+ }
+
+ //encode 8bit mask uncompressed icon
+ {
+ int ofs = data.size();
+ int len = copy->get_width() * copy->get_height();
+ data.resize(data.size() + len + 8);
+
+ for (int j = 0; j < len; j++) {
+ data.write[ofs + 8 + j] = src_data.read()[j * 4 + 3];
+ }
+ len += 8;
+ len = BSWAP32(len);
+ copymem(&data.write[ofs], icon_infos[i].mask_name, 4);
+ encode_uint32(len, &data.write[ofs + 4]);
+ }
+ }
}
uint32_t total_len = data.size();
@@ -334,7 +457,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
io2.opaque = &dst_f;
zipFile dst_pkg_zip = NULL;
- if (use_dmg()) {
+ String export_format = use_dmg() && p_path.ends_with("dmg") ? "dmg" : "zip";
+ if (export_format == "dmg") {
// We're on OSX so we can export to DMG, but first we create our application bundle
tmp_app_path_name = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".app");
print_line("Exporting to " + tmp_app_path_name);
@@ -429,7 +553,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
print_line("ADDING: " + file + " size: " + itos(data.size()));
total_size += data.size();
- if (use_dmg()) {
+ if (export_format == "dmg") {
// write it into our application bundle
file = tmp_app_path_name + "/" + file;
@@ -491,7 +615,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (err == OK) {
ep.step("Making PKG", 1);
- if (use_dmg()) {
+ if (export_format == "dmg") {
String pack_path = tmp_app_path_name + "/Contents/Resources/" + pkg_name + ".pck";
Vector<SharedObject> shared_objects;
err = save_pack(p_preset, pack_path, &shared_objects);
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index 6fd52f09d1..ae2eb6288c 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -74,8 +74,12 @@ public:
IP_Unix *ip_unix;
+#ifdef COREAUDIO_ENABLED
AudioDriverCoreAudio audio_driver;
+#endif
+#ifdef COREMIDI_ENABLED
MIDIDriverCoreMidi midi_driver;
+#endif
InputDefault *input;
JoypadOSX *joypad_osx;
@@ -120,8 +124,8 @@ public:
Point2 im_position;
bool im_active;
- ImeCallback im_callback;
- void *im_target;
+ String im_text;
+ Point2 im_selection;
power_osx *power_manager;
@@ -241,7 +245,8 @@ public:
virtual void set_ime_active(const bool p_active);
virtual void set_ime_position(const Point2 &p_pos);
- virtual void set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp);
+ virtual Point2 get_ime_selection() const;
+ virtual String get_ime_text() const;
virtual String get_unique_id() const;
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 70b49805d2..dd82e982ed 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -76,6 +76,13 @@
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
#endif
+#ifndef NSAppKitVersionNumber10_12
+#define NSAppKitVersionNumber10_12 1504
+#endif
+#ifndef NSAppKitVersionNumber10_14
+#define NSAppKitVersionNumber10_14 1671
+#endif
+
static void get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> state) {
state->set_shift((p_osx_state & NSEventModifierFlagShift));
@@ -326,15 +333,15 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto
- (void)windowDidBecomeKey:(NSNotification *)notification {
//_GodotInputWindowFocus(window, GL_TRUE);
//_GodotPlatformSetCursorMode(window, window->cursorMode);
- [OS_OSX::singleton->context update];
- get_mouse_pos(
- [OS_OSX::singleton->window_object mouseLocationOutsideOfEventStream],
- [OS_OSX::singleton->window_view backingScaleFactor]);
- OS_OSX::singleton->input->set_mouse_position(Point2(mouse_x, mouse_y));
+ if (OS_OSX::singleton->get_main_loop()) {
+ get_mouse_pos(
+ [OS_OSX::singleton->window_object mouseLocationOutsideOfEventStream],
+ [OS_OSX::singleton->window_view backingScaleFactor]);
+ OS_OSX::singleton->input->set_mouse_position(Point2(mouse_x, mouse_y));
- if (OS_OSX::singleton->get_main_loop())
OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN);
+ }
}
- (void)windowDidResignKey:(NSNotification *)notification {
@@ -364,6 +371,8 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto
bool imeMode;
}
- (void)cancelComposition;
+- (BOOL)wantsUpdateLayer;
+- (void)updateLayer;
@end
@implementation GodotContentView
@@ -374,6 +383,14 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto
}
}
+- (BOOL)wantsUpdateLayer {
+ return YES;
+}
+
+- (void)updateLayer {
+ [OS_OSX::singleton->context update];
+}
+
- (id)init {
self = [super init];
trackingArea = nil;
@@ -410,11 +427,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
} else {
[markedText initWithString:aString];
}
- if (OS_OSX::singleton->im_callback) {
+ if (OS_OSX::singleton->im_active) {
imeMode = true;
- String ret;
- ret.parse_utf8([[markedText mutableString] UTF8String]);
- OS_OSX::singleton->im_callback(OS_OSX::singleton->im_target, ret, Point2(selectedRange.location, selectedRange.length));
+ OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]);
+ OS_OSX::singleton->im_selection = Point2(selectedRange.location, selectedRange.length);
+
+ if (OS_OSX::singleton->get_main_loop())
+ OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE);
}
}
@@ -426,8 +445,13 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
- (void)unmarkText {
imeMode = false;
[[markedText mutableString] setString:@""];
- if (OS_OSX::singleton->im_callback)
- OS_OSX::singleton->im_callback(OS_OSX::singleton->im_target, "", Point2());
+ if (OS_OSX::singleton->im_active) {
+ OS_OSX::singleton->im_text = String();
+ OS_OSX::singleton->im_selection = Point2();
+
+ if (OS_OSX::singleton->get_main_loop())
+ OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE);
+ }
}
- (NSArray *)validAttributesForMarkedText {
@@ -933,7 +957,7 @@ static int remapKey(unsigned int key) {
CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
if (!layoutData)
- return 0;
+ return translateKey(key);
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
@@ -1051,6 +1075,8 @@ static int remapKey(unsigned int key) {
inline void sendScrollEvent(int button, double factor, int modifierFlags) {
+ unsigned int mask = 1 << (button - 1);
+
Ref<InputEventMouseButton> sc;
sc.instance();
@@ -1061,9 +1087,13 @@ inline void sendScrollEvent(int button, double factor, int modifierFlags) {
Vector2 mouse_pos = Vector2(mouse_x, mouse_y);
sc->set_position(mouse_pos);
sc->set_global_position(mouse_pos);
+ button_mask |= mask;
sc->set_button_mask(button_mask);
OS_OSX::singleton->push_input(sc);
+
sc->set_pressed(false);
+ button_mask &= ~mask;
+ sc->set_button_mask(button_mask);
OS_OSX::singleton->push_input(sc);
}
@@ -1119,12 +1149,14 @@ inline void sendPanEvent(double dx, double dy, int modifierFlags) {
@end
-void OS_OSX::set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp) {
- im_callback = p_callback;
- im_target = p_inp;
- if (!im_callback) {
- [window_view cancelComposition];
- }
+Point2 OS_OSX::get_ime_selection() const {
+
+ return im_selection;
+}
+
+String OS_OSX::get_ime_text() const {
+
+ return im_text;
}
String OS_OSX::get_unique_id() const {
@@ -1152,10 +1184,14 @@ String OS_OSX::get_unique_id() const {
}
void OS_OSX::set_ime_active(const bool p_active) {
+
im_active = p_active;
+ if (!im_active)
+ [window_view cancelComposition];
}
void OS_OSX::set_ime_position(const Point2 &p_pos) {
+
im_position = p_pos;
}
@@ -1227,6 +1263,9 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
ERR_FAIL_COND_V(window_object == nil, ERR_UNAVAILABLE);
window_view = [[GodotContentView alloc] init];
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_14) {
+ [window_view setWantsLayer:TRUE];
+ }
float displayScale = 1.0;
if (is_hidpi_allowed()) {
@@ -1384,7 +1423,6 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
visual_server = memnew(VisualServerRaster);
if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) {
-
visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD));
}
@@ -1408,7 +1446,9 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
void OS_OSX::finalize() {
+#ifdef COREMIDI_ENABLED
midi_driver.close();
+#endif
CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL);
CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL);
@@ -1458,7 +1498,7 @@ public:
switch (p_type) {
case ERR_WARNING:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_info(OS_LOG_DEFAULT,
"WARNING: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1468,7 +1508,7 @@ public:
logf_error("\E[0;33m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SCRIPT:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"SCRIPT ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1478,7 +1518,7 @@ public:
logf_error("\E[0;35m At: %s:%i.\E[0m\n", p_file, p_line);
break;
case ERR_SHADER:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"SHADER ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -1489,7 +1529,7 @@ public:
break;
case ERR_ERROR:
default:
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_12) {
+ if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
os_log_error(OS_LOG_DEFAULT,
"ERROR: %{public}s: %{public}s\nAt: %{public}s:%i.",
p_function, err_details, p_file, p_line);
@@ -2160,11 +2200,7 @@ void OS_OSX::set_window_size(const Size2 p_size) {
if (menuBarHeight != 0.f) {
size.y += menuBarHeight;
} else {
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200
if (floor(NSAppKitVersionNumber) < NSAppKitVersionNumber10_12) {
-#else
- {
-#endif
size.y += [[NSStatusBar systemStatusBar] thickness];
}
}
@@ -2620,8 +2656,6 @@ OS_OSX::OS_OSX() {
singleton = this;
im_active = false;
im_position = Point2();
- im_callback = NULL;
- im_target = NULL;
layered_window = false;
autoreleasePool = [[NSAutoreleasePool alloc] init];
@@ -2725,7 +2759,9 @@ OS_OSX::OS_OSX() {
[NSApp sendEvent:event];
}
+#ifdef COREAUDIO_ENABLED
AudioDriverManager::add_driver(&audio_driver);
+#endif
}
bool OS_OSX::_check_internal_feature_support(const String &p_feature) {